-
Notifications
You must be signed in to change notification settings - Fork 287
Lost of precision due to the use of float as type for degrees #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
… to type double.
Conversion from latitude and longitude to meters:
- delta_latitude_in_meters = delta_latitude_in_degrees * 40008000 / 360
- delta_longitude_in_meters = delta_longitude_in_degrees * 40075160 * cos(latitude_in_degrees) / 360
- The below examples are centered in the conversions of longitude to meters in its worst case (latitude 0º).
The use of the type minmea_float for storing the positions seems to be convenient:
- Mapping of digits in 32 bit integer range:
2**31 21474 83648
Latitude XDDMM.MMMMM
Longitude DDDMM.MMMMM
- It allows to store 5 decimals, so we will obtain an error of 0.00001 / 60 * 40075160 * cos(0) / 360 = 0.01855 m.
- In the readme it is specified an error of 2 cm. It matches with the above value.
Use of float for storing the positions is not convenient:
- The precision of float is between 6 and 7 digits.
- The precission of double is between 15 and 16 digits.
- The worst case is with a latitude 0.0 º (equator) and a longitude with 3 digits used by the degrees part.
- If we use the type float, 4 digits are available for the decimal part of the longitude, so we will obtain an error of 0.0001 * 40075160 * cos(0) / 360 = 11.13 m.
- If we use the type double, 13 digits are available for the decimal part of the longitude, so we will obtain an error of 0.0000000000001 * 40075160 * cos(0) / 360 = 0.00000001113 m.
- We need at least 7 digits for the decimal part of the longitude to obtain an error of 0.0000001 * 40075160 * cos(0) / 360 = 0.01113 m.
References:
- https://blog.demofox.org/2017/11/21/floating-point-precision/.
- https://stackoverflow.com/questions/3024404/transform-longitude-latitude-into-meters
|
I also would like this modification. |
|
+1, looks like a simple change. If there are MCUs out there that really can't or shouldn't be using doubles, then maybe provide a |
|
I also would like this modification. there is experience of experiencing problems with float-type GPS coordinate errors. |
|
The tests are not building. You should change the use of |
|
I went one step further with #83, because GPS RTK can provide higher precision than 2 cm and according modules sent eight decimal digits. My PR includes this PR's change, including adjusted tests. |
|
Probably stating the obvious here, but it would be a pity to leave non-double users as second class citizens. Even the few MCU's that do have an FPU that supports doubles, all do so with complex compromises on what are fundamentally 32-bit systems. I've attempted a short survey of microcontrollers (excluding "microprocessors") on their hardware support for doubles. There's definitely mistakes here - improvements welcome! STM32
Texas Instruments
Renesas
So I guess the point is that only the highest-power, highest cost MCU's have hardware-emabled support for doubles, which is probably not where most people are targeting if they're running MCUs. And even then there are various caveats when it comes to loading and unloading 64-bit workloads on a 32-bit architecture. On reflection, perhaps this is a sensible proposal:
|
Today there are more and more highest cost MCU. For example new rpi pico is a M33 with fpu (previous was M0+). Why not introduce another API : minmea_tocoord -> float User can chose if they want the result as float or double. |
|
You all have clearly more experience with pitfalls on microcontrollers. I'm happy to make adjustments to my PR, my main goal is to make this library work with GPS RTK modules on an STM32H723 (which according to the list above is suitable for this, so I didn't run into problems). For my better understanding: Is the pure existence of functions a problem? Because I don't see any |
It's a good question, and I posted before I reviewed your work in that light. I went back and took a closer look, because the mere existence of a double is not a problem. It only matters for executing code. As a random example, the standard c lib expects doubles for the So it needn't be an |
|
Is there a need to introduce int_least64_t ? What is the precision provided in nmea stream ? In my application nmea is is [d]ddmm.mmmm : 9 or 8 digits that will fit in a minmea_float with int_least32_t. But the conversion need to be done with double instead of float to not loose precision. |
|
RTK modules - at least the one I have - adds 4 decimal digits, so it would be |
|
Ok, so we have 2 problems here :
|
|
Oh yes, for my part I overlooked the original issue sorry. I think the original calculations might be wrong [1], but the conclusion is the same: floats could reduce resolution to some 1.7m. Being an accessor (rather than a critical periodic function), I think an alternative Parsing higher precision sentences produced by RTK modules does indeed sound like a somewhat separate problem. I'm not sure a build time option is necessary, since the user calls the
|
Well... this affects only latitude and longitude in RMC, GGA and GLL messages. The way the library is used in the examples, you'd declare a local struct variable before calling If you're not using RTK, then that's 16 stack bytes of overhead that could be avoided - but are you really working in such a constrainted environment that you would notice this? I imagine that software which interacts with a GPS module is probably more advanced and probably has other complex interfaces, so chances are good that it's not the most low-end microcontroller. Build-time options on the other hand add a lot of complexity for tests as you need to compile for each combination and run separate tests. So that another kind of overhead to consider. |
|
@jmfermun any interest in picking this up, or anyone else here? How clean is @matthieu-c-tagheuer approach? This only works if these functions are the direct user callable api and we aren't storing floats internally and losing precision. |
Function minmea_tocoord now converts positions from type minmea_float to type double.
Conversion from latitude and longitude to meters:
The use of the type minmea_float for storing the positions seems to be convenient:
2**31 21474 83648
Latitude XDDMM.MMMMM
Longitude DDDMM.MMMMM
Use of float for storing the positions is not convenient:
References: