From 2bbfb9c3057a92f25ebf67c5af4baa4d2b53d788 Mon Sep 17 00:00:00 2001 From: jmfermun Date: Sun, 29 Jan 2023 19:49:38 +0100 Subject: [PATCH] Function minmea_tocoord now converts positions from type minmea_float to type double. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- minmea.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/minmea.h b/minmea.h index 494b218..5a1128f 100644 --- a/minmea.h +++ b/minmea.h @@ -262,10 +262,10 @@ static inline float minmea_tofloat(const struct minmea_float *f) } /** - * Convert a raw coordinate to a floating point DD.DDD... value. + * Convert a raw coordinate to a double floating point DD.DDD... value. * Returns NaN for "unknown" values. */ -static inline float minmea_tocoord(const struct minmea_float *f) +static inline double minmea_tocoord(const struct minmea_float *f) { if (f->scale == 0) return NAN; @@ -275,7 +275,7 @@ static inline float minmea_tocoord(const struct minmea_float *f) return NAN; int_least32_t degrees = f->value / (f->scale * 100); int_least32_t minutes = f->value % (f->scale * 100); - return (float) degrees + (float) minutes / (60 * f->scale); + return (double) degrees + (double) minutes / (60 * f->scale); } /**