Pages: [1]   Go Down
 Author Topic: loss of precission  (Read 576 times) 0 Members and 1 Guest are viewing this topic.
Offline
Newbie
Karma: 0
Posts: 4
 « on: October 16, 2012, 05:41:28 pm » Bigger Smaller Reset

When i am trying to convert the coordinates, there is a big loss of precission... please tell me what to do...
coordinates in ddmm.mmmm : 2240.2027, 7552.6356
expected coordinates in dd.dddddd : 22.670045, 75.877246
what i am getting : 22.67, 75.88

Code:
String lat = "2240.2027";
float floatLat=0;
String lng = "7552.6356";
float floatLng=0;
String test ="";

convert()
{
test=lat;
int ddlat=0;
int mmlat=0;
int mmmmlat=0;
test=test.substring(0,2);
ddlat=test.toInt();
test=lat;
test=test.substring(2,4);
mmlat=test.toInt();
test=lat;
test=test.substring(5,9);
mmmmlat=test.toInt();
floatLat=(mmlat+(mmmmlat*0.0001));
floatLat=floatLat/60;
floatLat=floatLat+ddlat;

test=lng;
test=test.substring(0,2);
ddlat=test.toInt();
test=lng;
test=test.substring(2,4);
mmlat=test.toInt();
test=lng;
test=test.substring(5,9);
mmmmlat=test.toInt();
floatLng=(mmlat+(mmmmlat*0.0001));
floatLng=floatLng/60;
floatLng=floatLng+ddlat;
}
 Logged

Massachusetts, USA
Offline
Tesla Member
Karma: 169
Posts: 7898
 « Reply #1 on: October 16, 2012, 06:03:41 pm » Bigger Smaller Reset

From what I have read the Arduino floating-point math is only good for 6 or 7 digits.

Using an 'unsigned long' type (32 bits) you can get about 9.5 digits of range.  That should let you calculate in millionths of a degree.
 Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

0
Offline
Tesla Member
Karma: 145
Posts: 9947
Arduino rocks
 « Reply #2 on: October 16, 2012, 06:08:55 pm » Bigger Smaller Reset

Please post the whole code - or at least something that compiles without error:
Quote
sketch_oct17a:6: error: ISO C++ forbids declaration of ‘convert’ with no type
 Logged

[ I won't respond to messages, use the forum please ]

UK
Offline
Shannon Member
Karma: 160
Posts: 10280
-
 « Reply #3 on: October 16, 2012, 06:13:12 pm » Bigger Smaller Reset

When i am trying to convert the coordinates, there is a big loss of precission... please tell me what to do...
coordinates in ddmm.mmmm : 2240.2027, 7552.6356
expected coordinates in dd.dddddd : 22.670045, 75.877246
what i am getting : 22.67, 75.88

You haven't posted the whole code, so I can't tell what your sketch does. What evidence do you have that the result has poor precision? If you're formatting it via the Serial object, I think you'll find that automatically rounds float values to two decimal places and does not print the exact number given to it.
 Logged

I only provide help via the forum - please do not contact me for private consultancy.

0
Offline
Tesla Member
Karma: 145
Posts: 9947
Arduino rocks
 « Reply #4 on: October 16, 2012, 06:17:49 pm » Bigger Smaller Reset

It always helps to read the specification carefully - look for 'optional second parameter': http://www.arduino.cc/en/Serial/Print
 Logged

[ I won't respond to messages, use the forum please ]

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #5 on: October 17, 2012, 02:22:14 pm » Bigger Smaller Reset

Code:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String inputString = "";         // a string to hold incoming data
String test = "";
String ggaString = "";
String vtgString = "";
boolean stringComplete = false;  // whether the string is complete
boolean gotGgaData = false;
boolean gotVtgData = false;
String utcTime = "";
float floatUtcTime=0;
String lat = "";
float floatLat=0;
String lng = "";
float floatLng=0;

void setup() {

Serial.begin(9600);
lcd.begin(16, 2);
inputString.reserve(200);
}

void loop() {

if (stringComplete) {

inputString = "";
stringComplete = false;
}
if(gotGgaData==true)
{
gotGgaData=false;
utcTime=ggaString.substring(7,16);
lcd.print("Time : ");
lcd.print(utcTime);
delay(1000);
lcd.clear();
lat=ggaString.substring(18,27);
lcd.print("Lat  : ");
lcd.print(lat);
delay(1000);
lcd.clear();
lng=ggaString.substring(31,40);
lcd.print("Lng  : ");
lcd.print(lng);
delay(1000);
lcd.clear();
convert();

}

}

void convert()
{
test=lat;
int ddlat=0;
int mmlat=0;
int mmmmlat=0;
test=test.substring(0,2);
ddlat=test.toInt();
test=lat;
test=test.substring(2,4);
mmlat=test.toInt();
test=lat;
test=test.substring(5,9);
mmmmlat=test.toInt();
floatLat=(mmlat+(mmmmlat*0.0001));
floatLat=floatLat/60;
floatLat=floatLat+ddlat;

test=lng;
test=test.substring(0,2);
ddlat=test.toInt();
test=lng;
test=test.substring(2,4);
mmlat=test.toInt();
test=lng;
test=test.substring(5,9);
mmmmlat=test.toInt();
floatLng=(mmlat+(mmmmlat*0.0001));
floatLng=floatLng/60;
floatLng=floatLng+ddlat;
}

void serialEvent()

{
while (Serial.available())
{
char inChar = (char)Serial.read();
inputString += inChar;

if (inChar == '\n')
{
test=inputString.substring(0,6);
if(test=="\$GPVTG")
{ vtgString=inputString; gotVtgData= true;}
else if(test=="\$GPGGA")
{ ggaString=inputString; gotGgaData= true;}

stringComplete = true;

}

}
}
 Logged

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #6 on: October 17, 2012, 02:31:46 pm » Bigger Smaller Reset

i want to design an odometer using GPS... the data coming from GPS modules is in form of strings...the format of coordinates is ddmm.mmmm
In order to calculate the distance b/w 2 coordinates, we use haversine fomula... this formula requires coordinates in form dd.dddddddd so i first need to convert string into float then convert it into dd.ddddddd form.... the above code gives me coordinates as dd.dd i need more precision in my project
 Logged

Offline
Edison Member
Karma: 17
Posts: 1045
 « Reply #7 on: October 17, 2012, 02:35:01 pm » Bigger Smaller Reset

Maybe you could just drop the first 4 digits (DD.dd), after all for an odometer they will be the same anyway. (i.e., instead of using 83.4212121212, always use 1.2121212e-4.
 Logged

Offline
Newbie
Karma: 0
Posts: 4
 « Reply #8 on: October 17, 2012, 02:37:35 pm » Bigger Smaller Reset

but in haversine formula we need to put complete coordinates...

it is calculated as  :

dlon = lon2 - lon1
dlat = lat2 - lat1
a = (sin(dlat/2))^2 + cos(lat1) * cos(lat2) * (sin(dlon/2))^2
c = 2 * atan2( sqrt(a), sqrt(1-a) )
d = R * c (where R is the radius of the Earth)
 Logged

Ayer, Massachusetts, USA
Offline
Edison Member
Karma: 49
Posts: 1728
 « Reply #9 on: October 17, 2012, 02:45:58 pm » Bigger Smaller Reset

Note, double and long double are treated the same as float in the AVR/arduino environment.  This means you only have 6 digits or so of precision.

Also note, if you are making very heavy use of floating point, that you might want to consider using another machine that has floating point in hardware.  On arduino systems, floating point is all done by emulation routines.
 Logged

Offline
Edison Member
Karma: 17
Posts: 1045
 « Reply #10 on: October 17, 2012, 02:50:11 pm » Bigger Smaller Reset

Note that the dlon calculation already does what I suggested. 8^)
 Logged

Offline
Edison Member
Karma: 17
Posts: 1045
 « Reply #11 on: October 17, 2012, 02:58:05 pm » Bigger Smaller Reset

A chip like this might be helpful:
http://www.micromegacorp.com/downloads/documentation/uMFPU-V3_1%20Datasheet.pdf

It will even parse the NMEA strings.
 Logged

UK
Offline
Shannon Member
Karma: 160
Posts: 10280
-
 « Reply #12 on: October 17, 2012, 03:17:15 pm » Bigger Smaller Reset

the above code gives me coordinates as dd.dd

In what way does it give you dd.dd? Where is this value output? Which part of your code actually formats the value output there?
 Logged

I only provide help via the forum - please do not contact me for private consultancy.

0
Offline
Tesla Member
Karma: 145
Posts: 9947
Arduino rocks
 « Reply #13 on: October 17, 2012, 06:20:17 pm » Bigger Smaller Reset

d = R * c (where R is the radius of the Earth)

Slight issue here, the earth is not a sphere.  However the error in radius from the mean is at most 0.25% which is fit for most purposes.
 Logged

[ I won't respond to messages, use the forum please ]

Offline
Jr. Member
Karma: 0
Posts: 84
 « Reply #14 on: October 17, 2012, 11:23:42 pm » Bigger Smaller Reset

Also, beware that in floating-point math, another phenomenon often shows up known as "Loss of significance". Wikipedia has a page describing it.  I can't tell with a quick look if your formula will suffere from it, but you may want to look into it.

Basically, it's a problem that arises when you subtract a number from another number of similar magnitude, then multiply it, or square it etc.  All of the significant digits get lost in the subtraction, then you multiply the remaining insignificant digits by some meaningful value. The result is just amplified noise, and can be completely meaningless.

I usually perform a check anytime I perform a subtraction (if the result is to be used for other operations). If the difference is less than some percentage of either (or both) of the first two values, then you have to force it to zero. (And do a check for a divide-by-zero if your next step divides.)

There are probably other ways to avoid this problem for specific purposes as well.
 Logged

 Pages: [1]   Go Up
Jump to: