# GPS very short distance calculation

I'm currently working on a project involving making a "parent-child distance warning system" with my Flora board + Ultimate GPS Module (https://www.adafruit.com/product/1059). I'm on the preliminary phase and just trying to retrieve the current GPS module position, comparing it with a pre-fixed position (expressed in GPS decimal coordinates, e.g. 40.779006, -74.289395), calculate the distance between these two points and, if the distance is more than a certain value, say 20 meters, print on serial monitor a warning message. I was able to correctly retrieve the GPS module position (expressed in decimal coordinates, as above), but when I try to calculate the distance I'm not able to achieve a few-meter accurancy.

So, my questions are:

1. Is there a specific/best formula to calculate short distances (max 100 meters) on the earth surface with an accurancy of 2-3 meters? I tried with Haversine formula with not so bad results, but because of the scarce Double precision (in ATMega processors is the same of the Float one, i.e. 32 bits), I'm able to obtain a precision of only 6-7 digits in total (as stated in https://www.arduino.cc/en/Reference/Float). These approximations lead to large errors in the final distance value.
2. How can I obtain a fast and precise position update during my path? If I walk along a direction I'm no able to retrieve a fast enough position update in terms of lat/lon coordinates.

Hope to be as much clear as possible and to have explained my problem, thanks in advance to anyone will give me any feedback or any information and please be patience for my bad english.

Filippo

[UPDATE]

@EdgarBonet that's exactly what I was looking for!!! Huge thanks!

Does the simple GPS library you linked is good to me also if my Flora board mounts an AtMega32u4 processor instead of the ATtiny85 you mentioned?

Last question: do you know how faster can I retrieve a GPS fix? I mean, if I am in a certain position (say X) and I am able to correctly obtain my GPS coordinates, then I move 5 meters ahead (say X+5), when I arrive at X+5 position can I retrieve within few seconds the X+5 GPS coordinates?

Thank you so much again @EdgarBonet!!

I'm currently working on a project involving making a "parent-child distance warning system" with my Flora board + Ultimate GPS Module (https://www.adafruit.com/product/1059). I'm on the preliminary phase and just trying to retrieve the current GPS module position, comparing it with a pre-fixed position (expressed in GPS decimal coordinates, e.g. 40.779006, -74.289395), calculate the distance between these two points and, if the distance is more than a certain value, say 20 meters, print on serial monitor a warning message. I was able to correctly retrieve the GPS module position (expressed in decimal coordinates, as above), but when I try to calculate the distance I'm not able to achieve a few-meter accurancy.

So, my questions are:

1. Is there a specific/best formula to calculate short distances (max 100 meters) on the earth surface with an accurancy of 2-3 meters? I tried with Haversine formula with not so bad results, but because of the scarce Double precision (in ATMega processors is the same of the Float one, i.e. 32 bits), I'm able to obtain a precision of only 6-7 digits in total (as stated in https://www.arduino.cc/en/Reference/Float). These approximations lead to large errors in the final distance value.
2. How can I obtain a fast and precise position update during my path? If I walk along a direction I'm no able to retrieve a fast enough position update in terms of lat/lon coordinates.

Hope to be as much clear as possible and to have explained my problem, thanks in advance to anyone will give me any feedback or any information and please be patience for my bad english.

Filippo

[UPDATE]

@EdgarBonet that's exactly what I was looking for!!! Huge thanks!

Does the simple GPS library you linked is good to me also if my Flora board mounts an AtMega32u4 processor instead of the ATtiny85 you mentioned?

Last question: do you know how faster can I retrieve a GPS fix? I mean, if I am in a certain position (say X) and I am able to correctly obtain my GPS coordinates, then I move 5 meters ahead (say X+5), when I arrive at X+5 position can I retrieve within few seconds the X+5 GPS coordinates?

Thank you so much again @EdgarBonet!!

[UPDATE 2]

The `DistanceBetween` method recommended to me by @EdgarBonet returns to me always 0, even if I move my self a couple of tens of meters.

But, maybe I am wrong in passing the parameters. Do I have to pass the lat/lon parameters as decimal coordinates (e.g: 45.892829, 12.082583)? If I am wrong, in which format do I have to pass the lat/lon parameters to the `DistanceBetween` method?

• It may be that you cannot get this kind of accuracy with the position fix outputs of everyday GPS units, but rather that you need DGPS (or yet fancier schemes) capable units that can exchange their raw data readings to factor out the part of the inherent system error that is essentially the same in the local region, leaving only the position difference. This is really a differential GPS question, not an Arduino question - or at least, don't try to do it on an Arduino until you've verified elsewhere that computations on real sample data yield a useful result. May 30, 2017 at 22:54
• Why not use a short range radio signal, i.e. Bluetooth. Pair the parent and child and then pulse a signal between them. As soon as a number of pulses are missed raise the alarm at the parent end. Its a bit more clumsy if you have 5 children, but... May 31, 2017 at 7:14
• @Filippo not related to athe question itself, but.. Please avoid using multiple accounts (partcularly to add information about the question, like you did in the pending edit).. May 31, 2017 at 10:37
• @CodeGorilla That tells you they have wandered off but it doesn't tell you which direction they went. It will also be very environment specific, lots of people around will absorb the signals and so shorten the range. Not necessarily a bad thing for this application but it wouldn't be a controllable effect. May 31, 2017 at 11:49
• Do you have two user accounts? You appear to be suggesting edits from an account that differs from the account that you originally posted your question from. If you contact the moderators, then they can merge the two accounts for you. May 31, 2017 at 16:18

The Haversine formula is way overkill for your needs. At the scale you are concerned about, the Earth is essentially flat, so the distance between two points is given by the standard Cartesian formula:

d = √(Δx2 + Δy2)

where Δx and Δy are the distances along the west–east and south–north axes respectively. These can be computed from the differences in latitude and longitude as

Δx = R Δλ cos(φ)
Δy = R Δφ

where φ is the latitude, λ is the longitude (both in radians), and R is the Earth radius. The term cos(φ) accounts for the fact that, far from the equator, consecutive meridians are closer together than consecutive parallels. When computing this cosine, it does not matter whether you use the latitude of either point.

I suggest you take a look at this simple GPS library. It was designed for doing exactly this kind of simple calculations on a small AVR processor like the ATtiny85. It should work great on your Flora. The function you want is `DistanceBetween()`. It uses the “locally flat Earth” approximation above, which is only good for distances up to a few hundred kilometers.

• the library trades accuracy for efficiency: everything is fixed-point and it uses low-order polynomial approximations for cos(x) and √(x2 + y2)
• angles are given in units of 10−4 arc minutes, as this is what you usually get from an NMEA sentence
• `DistanceBetween()` reports the distance as an integer number of meters, but you can easily modify it to give it in units of half-meters, quarter-meters, etc.: just replace the value 512 in the last line (`return ... / 512;`) by a smaller power of two.
• Personally I wouldn't trust the "locally flat earth" model for distances much over the 10-20 km region, certainly not hundreds of km. But it does depend a lot on what you consider to be good enough accuracy. But certainly good enough for the distances in this question. May 31, 2017 at 10:29
• But... Are you really sure that Earth is not flat? May 31, 2017 at 10:46
• @Andrew: The library is intended for low-accuracy applications. For example, it uses the approximation cos(π/2 ⋅ x) ≈ 0.962(1 – x²), which has a maximum error of about 0.038. It this accuracy level the “locally flat Earth” approximation is valid for quite large distances at mid-latitudes. May 31, 2017 at 10:55
• @EdgarBonet I'm probably just too used to working in an environment where an error of 1 cm is unacceptable high ;-) May 31, 2017 at 11:47

I have successfully used an Arduino + hobby GPS to get an accuracy within a few meters with an update every second using normal floating point on Arduino. This should be possible.

A 32-bit float has 24 bits of precision, and one 2^24th of half the Earth's circumference is about 1.2 meters, so the theoretical cap is roughly that.

If I recall correctly, you would get better accuracy for short distances on a 32-bit float using normal 2D trig than haversine, but both should work.

Check to make sure you are reading your GPS correctly and go over the equations again. Is everything converted to radians correctly for the trig? Make sure your version of PI has enough digits. Are you correctly parsing the GPS output value as degrees+decimal minutes? It is not a simple decimal degree number (like Google Maps coordinates would be) if it came from an NMEA message. Are there any configuration startup commands you need to send your GPS unit?

I think the fastest updates you can expect is a new coordinate every second, but I haven't used your specific GPS.

• Uhm.. in fact you do not have to take into account the radius of Earth, but the emi-circumference. This means that the maximum resolution for a float is about 1.2 meters... May 31, 2017 at 10:40
• @frarugi87 wow, yeah, thats a dumb mistake. Thanks. May 31, 2017 at 15:28

The position difference calculation part of the question has been handled by Edgar. Which leaves the heading to the child part.

To work out which direction the parent is walking in don't use change in position. Use the heading and velocity outputs from the GPS. These will be far more accurate than calculating the velocity based on the change in position.

As for rate of update it depends a lot on the GPS being used, the one you linked to indicates that it supports 10 Hz updates so you should be able to get a position and heading update 10 times per second. The default will be 1 Hz so you'll need to send the correct configuration command. This will however significantly increase battery usage.

Those low end GPS systems typically have a fair amount of latency but the values you get in the serial stream shouldn't be more than 100 ms old, easily good enough for something as slow as a person walking.

You may be interested in my NeoGPS library. It is smaller, faster, more reliable and more accurate than all other libraries. It preserves the full accuracy of the GPS locations (10 significant digits), even during distance and bearing calculations. NeoGPS uses the equirectangular simplification suggested by Edgar at small distances, and switches to Haversine at large distances. As you have discovered, naive floating-point calculations (like those in all other libraries) lose that accuracy at small distances.

If you want to try it, NeoGPS is available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.

• `It is smaller, faster, more reliable and more accurate than all other libraries` Not true. I have a library where the position is always 0,0. It's not very accurate but it's a lot smaller and far faster. May 31, 2017 at 13:28
• The library I linked to in my answer sits somewhere between @Andrew's library and NeoGPS, both in terms of speed and accuracy. May 31, 2017 at 16:13
• @Andrew, like the watch that is exactly correct once per day, your library would be optimal at exactly one place on Earth. ;) May 31, 2017 at 23:39
• @EdgarBonet, I enjoyed reading about that project. The parser is basically a custom `scanf`... cute! I was curious how NeoGPS version would compare. It would still fit in an ATtiny85, using about half the RAM of TinyNav (67 bytes vs. 119) but almost twice the program space (7746 bytes vs. 4084). The NeoGPS Distance & Bearing routines require the floating-point library. Jun 1, 2017 at 1:04