Changing floats to doubles in NeoGps

For awhile now I have been using the NeoGps library with an Arduino Uno to control an autonomous RC car. Recently I upgraded the project to an Arduino Due. My question is, would changing the floats to doubles in the library increase the libraries accuracy?

32 bit floats use the same memory as 32 bit doubles.

CrossRoads:
32 bit floats use the same memory as 32 bit doubles.

On the Due, doubles are 64 bits.

Well, GPS only returns values like
42.356915, -71.524225
or perhaps
4235.6915, -7152.4225
or
42 35.6915, -71 52.4225

How many bits do you need for that?

would changing the floats to doubles increase the library's accuracy?

Good question!

The simple answer is no, because NeoGPS does not use float for parsing any GPS data. None. This means that the fix data structure contains values that are as accurate as the GPS device is sending.

However, there are two places where NeoGPS uses float:

  1. When calculating distance, bearing or offset; and

  2. To return a floating-point value of some fix members.

For the first case, switching to double does not give you any meaningful improvement in accuracy. The NeoGPS routines are very careful to preserve accuracy in these calculations, unlike all other GPS libraries. In fact, mostly integer math is used until a trig function is finally needed.

For short distances (10's of km), NeoGPS calculates the distance between two points within a fraction of a millimeter. You have to be careful about that claim, because the GPS device provides two locations that could be off by meters. The distance, while it is calculated very accurately, actually suffers from the much larger inaccuracy of the GPS device.

For longer distances, the calculations are still very accurate, but you have to add in the inaccuracies of the Haversine forumla. It pretends the Earth is a mathematically perfect ellipsoid, so the distance along this approximated surface starts to deviate from the actual surface. The errors in the GPS device (meters) plus the errors in the approximation are much larger than the errors introduced by NeoGPS.

For the second case, using double could help a little for the lat/lon, but I'm not sure it's meaningful. Internally, NeoGPS stores lat/lon values that are within 11mm of the value sent by the GPS device. This is much more accurate than the device is reporting. If you call the float lat/lon functions, their values are accurate to about 1m, also much better than most GPS devices ever provide. The point is that the float values are already much more accurate than the GPS device provides: switching to double doesn't make the GPS device more accurate. :frowning:

If you do have an accurate GPS device, returning a double from fix.latitude() would preserve the GPS device's sub-meter accuracy. This kind of accuracy requires special (expensive) GPS devices and/or base stations for differential adjustments.

So the complicated answer is that switching to double doesn't really help, unless you have an expensive, unusually accurate GPS setup.

On the other hand, it would be fairly innocuous to modify NeoGPS to use double instead of float. I'll take a look.

Cheers,
/dev

Thanks /dev for the informative response. I am looking into the more high end GPS systems, and want to push the accuracy level as far as I can. I’ve incorporated the Kalman filter into my software to improve the accuracy of my compass and GPS. With this implementation, I have seen tremendous accuracy results. Please let me know about your results from the doubles.

/dev I was going through the library and noticed the int32's being used for location. Would changing these to int64's increase the accuracy? Would this allow for more than 10 significant digits?

What do you mean by "high end" GPS? You can spend several thousand US, with a subscription service, to get better than 1-2 meters accuracy, but then you get a complete system with about 1 cm accuracy.

There is nothing you can do on the Arduino to improve on the accuracy of consumer grade GPS modules, over and above the approach taken by NeoGPS.

/dev I was going through the library and noticed the int32's being used for location. Would changing these to int64's increase the accuracy? Would this allow for more than 10 significant digits?

Take a look at the source of the data that NeoGPS and other GPS libraries use. The data that NeoGPS produces can be no more accurate than the input it gets.

The data that NeoGPS produces can be no more accurate than the input it gets.

This.

Are you really getting GPS locations to an accuracy better than 11mm? How would you know?

Sigh. If you really want to try doubles, convert the internal int32_t lat/lon directly into doubles:

 double lat = fix.location.lat();  // 10 sigfig, but scaled
  lat /= NeoGPS::Location_t::LOC_SCALE;
  double lon = fix.location.lon();
  lon /= NeoGPS::Location_t::LOC_SCALE;

Since you haven't tried this, I have to assume you haven't really analyzed your calculations to determine how the accuracy of the computed locations are propagated through to the answers. You may be introducing more errors in that pipeline.

And yes, long long (aka int64_t) would allow 20 significant digits (21?), but NeoGPS does not parse more than 6 decimals of the lat/lon minutes. I'm pretty sure your device does not send that. If you are reducing errors after NeoGPS gives you the values, there's no reason to modify NeoGPS. This all takes place in your code, so use whatever types you want.