Go Down

Topic: loss of precission (Read 1 time)previous topic - next topic

Oct 17, 2012, 12:41 am
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: [Select]

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;
}

johnwasser

#1
Oct 17, 2012, 01:03 am
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.
Send Bitcoin tips to: 1G2qoGwMRXx8az71DVP1E81jShxtbSh5Hp

MarkT

#2
Oct 17, 2012, 01:08 am
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
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

PeterH

#3
Oct 17, 2012, 01:13 am

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.

MarkT

#4
Oct 17, 2012, 01:17 am
It always helps to read the specification carefully - look for 'optional second parameter': http://www.arduino.cc/en/Serial/Print
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

#5
Oct 17, 2012, 09:22 pm
Code: [Select]

#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 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;
}
{
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())
{
inputString += inChar;

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

stringComplete = true;

}

}
}

#6
Oct 17, 2012, 09:31 pm
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

KeithRB

#7
Oct 17, 2012, 09:35 pm
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.

#8
Oct 17, 2012, 09:37 pm
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)

MichaelMeissner

#9
Oct 17, 2012, 09:45 pm
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.

KeithRB

#10
Oct 17, 2012, 09:50 pm
Note that the dlon calculation already does what I suggested. 8^)

KeithRB

#11
Oct 17, 2012, 09:58 pm
A chip like this might be helpful:

It will even parse the NMEA strings.

PeterH

#12
Oct 17, 2012, 10:17 pm

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?

MarkT

#13
Oct 18, 2012, 01:20 am

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.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Loudhvx

#14
Oct 18, 2012, 06:23 am
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.

Go Up