From: Jon Keller <jon@65...>  20070513 04:17:58

I've asked this same question around some of the avr lists but am having troubles getting an answer so I thought I may as well try this list as well, sorry if its a little off topic. I'm trying to calculate the distance between two gps coordinates on the robostix and am running into some weird issues. I'm using the code below for the calc. When I run this same code within perl and C on my standard workstation I get the correct values, which for the coordinates below are "NMiles: 2.5005995199488 SMiles: 2.87763854023694 SKm: 4.63111031889908" However when running the same code over the robostix I get the following results. "NMiles: 2.9072017670 SMiles: 3.3455481529 SKm: 5.3841376305" Obviously theres quite a big difference in the results, could anyone shed some light on why? Another very strange problem I've noticed is that if I make the two coords closer together, the results on the robostix stop decreasing when they hit a certain value, for instances the nautical miles result stops at 1.678 no matter how close the coords get to each other. Any help is greatly appreciated, Cheers. Jon double lon1 = 174.681821; double lon2 = 174.629821; double lat2 = deg2rad(36.728889); double lat1 = deg2rad(36.728889); double dlon = lon2  lon1; if (dlon > 180) { dlon = 360; } if (dlon < 180) { dlon += 360; } double rdlon = deg2rad(dlon); double cosdist = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(rdlon); double rdist = acos(cosdist); double nautical_miles = rad2deg(rdist) * 60; double statue_miles = fabs((rad2deg(rdist) * 60.) * 1.15077945); double statue_km = fabs((rad2deg(rdist) * 60.) * 1.8520000031807997); print_double("Distance  NMiles: %.2lf SMiles: %.2lf SKm: %.2lf\n", nautical_miles, statue_miles, statue_km); 
From: Garth Webb <garth.webb@gm...>  20070513 17:00:36
Attachments:
Message as HTML

You are running into precision limits. The numbers you are dealing with are very small and your doing a lot of multiplications and trig calculations to create intermediate results. Each intermediate result has to be rounded to fit into the 8 byte double. The fact that the robotstix doesn't give you results below 1.6 nautical miles shows that you're hitting these limits and your intermediate results are being rounded. Additionally, while the Amtel double is 8 bytes, its only an 8bit microcontroller vs. the 32/64bit desktop you have. If you're pushing precision limits this is probably what gives the difference between the robostix and your desktop. As for the differences between your final results, (2.9 NM vs 2.5 NM) the differences are only big because the units are nautical miles. Considering how small your numbers are before the final calculation its not surprising that they could differ by a few tenths from machine to machine. To get around this there are a few things you can do. The first it to try to rearrange the math to either cancel out operations that aren't necessary or to avoid creating results that can't be represented. For example, I could do this: a = 1 / 3; b = 21 * a; however the calculation in 'a' will be 0.3333..., an number which simply cannot be represented on any computer. However, if I combined those steps to divide by 3 directly and avoid storing an intermediate value: b = 21 / 3; there is a defined, finite result that can be easily stored with no loss of precision. Another thing you can do is work in the smallest units possible. For example, if I wanted to write a program that calculated the position of a spacecraft, I might choose AU (1 astronomical unit == distance between the earth and the sun) as my unit of measure. This gives me good results when calculating my distance to nearby planets, (e.g. Mars is 1.29 AU away) however if I'm trying to dock with a satelite this unit way to large, (e.g. "we are 0.000000000006684 AU and closing"). In your case if you care about tenths of miles, then you probably want to work in a smaller unit like feet or inches. I don't know how this changes your calculations but working with a smaller unit can help you avoid amplifying the 'noise' of precision loss. Finally, what you're doing has probably already been done many times before. Try to find a real code example (nontextbook) of this calculation someplace where somebody has already considered the limitations of computer math. On 5/12/07, Jon Keller <jon@...> wrote: > > I've asked this same question around some of the avr lists but am having > troubles getting an answer so I thought I may as well try this list as > well, sorry if its a little off topic. > > I'm trying to calculate the distance between two gps coordinates on the > robostix and am running into some weird issues. I'm using the code below > for the calc. When I run this same code within perl and C on my standard > workstation I get the correct values, which for the coordinates below are > > "NMiles: 2.5005995199488 SMiles: 2.87763854023694 SKm: 4.63111031889908" > > However when running the same code over the robostix I get the following > results. > > "NMiles: 2.9072017670 SMiles: 3.3455481529 SKm: 5.3841376305" > > Obviously theres quite a big difference in the results, could anyone > shed some light on why? Another very strange problem I've noticed is > that if I make the two coords closer together, the results on the > robostix stop decreasing when they hit a certain value, for instances > the nautical miles result stops at 1.678 no matter how close the coords > get to each other. Any help is greatly appreciated, Cheers. > > Jon > > > double lon1 = 174.681821; > double lon2 = 174.629821; > double lat2 = deg2rad(36.728889); > double lat1 = deg2rad(36.728889); > > double dlon = lon2  lon1; > if (dlon > 180) { > dlon = 360; > } > if (dlon < 180) { > dlon += 360; > } > > double rdlon = deg2rad(dlon); > double cosdist = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * > cos(rdlon); > double rdist = acos(cosdist); > > double nautical_miles = rad2deg(rdist) * 60; > double statue_miles = fabs((rad2deg(rdist) * 60.) * 1.15077945); > double statue_km = fabs((rad2deg(rdist) * 60.) * > 1.8520000031807997); > > print_double("Distance  NMiles: %.2lf SMiles: %.2lf SKm: > %.2lf\n", nautical_miles, statue_miles, statue_km); > > > >  > This SF.net email is sponsored by DB2 Express > Download DB2 Express C  the FREE version of DB2 express and take > control of your XML. No limits. Just data. Click to get it now. > http://sourceforge.net/powerbar/db2/ > _______________________________________________ > gumstixusers mailing list > gumstixusers@... > https://lists.sourceforge.net/lists/listinfo/gumstixusers > 
From: Dave Hylands <dhylands@gm...>  20070529 18:09:06

Hi Jon, > I'm trying to calculate the distance between two gps coordinates on the > robostix and am running into some weird issues. I'm using the code below > for the calc. When I run this same code within perl and C on my standard > workstation I get the correct values, which for the coordinates below are > > "NMiles: 2.5005995199488 SMiles: 2.87763854023694 SKm: 4.63111031889908" > > However when running the same code over the robostix I get the following > results. > > "NMiles: 2.9072017670 SMiles: 3.3455481529 SKm: 5.3841376305" Extending Garth's reply about precision, the avr only uses 32bit floats (for both the float and double types). >From the avrlibc FAQ: <http://www.nongnu.org/avrlibc/usermanual/FAQ.html#faq_reg_usage>;  Dave Hylands Vancouver, BC, Canada http://www.DaveHylands.com/ 