Pages: [1]   Go Down
Author Topic: loss of precission  (Read 628 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Tesla Member
***
Karma: 180
Posts: 8096
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Shannon Member
****
Karma: 162
Posts: 10456
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Shannon Member
****
Karma: 184
Posts: 11195
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Shannon Member
****
Karma: 162
Posts: 10456
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Edison Member
*
Karma: 18
Posts: 1171
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Edison Member
*
Karma: 50
Posts: 1767
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Edison Member
*
Karma: 18
Posts: 1171
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Edison Member
*
Karma: 18
Posts: 1171
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Shannon Member
****
Karma: 184
Posts: 11195
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Shannon Member
****
Karma: 162
Posts: 10456
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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 Offline
Jr. Member
**
Karma: 0
Posts: 85
View Profile
 Bigger Bigger  Smaller Smaller  Reset 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: