Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Distance between two coordinates


  • Please log in to reply
8 replies to this topic

#1 Patrick

Patrick

    Advanced Member

  • Members
  • PipPipPip
  • 54 posts
  • LocationTampa

Posted 31 August 2010 - 08:44 PM

I've used the Haversine formula many times when calculating distances between two points on this big blue marble but it's normally over long distances. Well, I was playing with my Netduino and wired a simple homing beacon style GPS application that blinks the LED faster as you approach a target lat/lon.

private double calculateDistance(double lat1, double lon1, double lat2, double lon2)
{
double R = 20902230.97112861; //feet
double dLat = (lat2-lat1) * (exMath.PI / 180.0);
double dLon = (lon2-lon1) * (exMath.PI / 180.0); 
double a = exMath.Sin(dLat/2.0) * exMath.Sin(dLat/2.0) +
        exMath.Cos(lat1 * (exMath.PI / 180.0)) * exMath.Cos(lat2 * (exMath.PI / 180.0)) * 
        exMath.Sin(dLon/2) * exMath.Sin(dLon/2); 
double  c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a)); 
double d = R * c;

return d;
}

The problem arises when, *I think*, the distance gets small between the two points (say 1000 feet or so), the

exMath.Cos(lat1 * (exMath.PI / 180.0)) * exMath.Cos(lat2 * (exMath.PI / 180.0))

part goes to zero instead of being a really small number and then I get an incorrect result. Like the double in the .Net micro has less precision than it's desktop counterpart...

Any insight here would be greatly appreciated!

Ps.. I'm using this library for the math operations.

#2 Chris Seto

Chris Seto

    Advanced Member

  • Members
  • PipPipPip
  • 405 posts

Posted 31 August 2010 - 10:31 PM

Are you sure your GPS is giving you correct data? Garbage in, garbage out.

#3 Patrick

Patrick

    Advanced Member

  • Members
  • PipPipPip
  • 54 posts
  • LocationTampa

Posted 31 August 2010 - 10:33 PM

Thanks Chris, but I'm positive. I tested with hard coded values that I verified against an online calculator.

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 31 August 2010 - 11:09 PM

Can you give us sample data (along with the set of math conversions) for the desktop version and the .NET MF library you're using--and then we can take a look to see what we can do to help? Chris

#5 Patrick

Patrick

    Advanced Member

  • Members
  • PipPipPip
  • 54 posts
  • LocationTampa

Posted 31 August 2010 - 11:49 PM

Thanks for the reply Chris...

This code on the desktop .Net Framework returns 45.016489891829075 Notice the hardcoded values... Accurate. Perfect!

static double calculateDistance(double lat1, double lon1, double lat2, double lon2)
        {
            double dist = 0.0;

            lat1 = 41.9243;
            lon1 = -88.1007;

            lat2 = 41.924399;
            lon2 = -88.100799;
            
            double rLat1 = lat1 * 0.017453293;
            double rLon1 = lon1 * 0.017453293;
            double rLat2 = lat2 * 0.017453293;
            double rLon2 = lon2 * 0.017453293;

            double R = 20902230.97112861;

            //Haversine
            double dLat = (rLat2 - rLat1);
            double dLon = (rLon2 - rLon1);

            double a = Math.Sin(dLat / 2.0) * Math.Sin(dLat / 2.0) +
                       Math.Cos(rLat1) * Math.Cos(rLat2) *
                       Math.Sin(dLon / 2.0) * Math.Sin(dLon / 2.0);

            double c = 2.0 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1.0 - a));

            dist = R * c;

            return dist;
        }

This code on the .Net MF returns 4082.6324955905925. Note that the exMath.Atan2 arguments needed to be flip flopped.

static double calculateDistance(double lat1, double lon1, double lat2, double lon2)
        {
            double dist = 0.0;

            lat1 = 41.9243;
            lon1 = -88.1007;

            lat2 = 41.924399;
            lon2 = -88.100799;

            double rLat1 = lat1 * 0.017453293;
            double rLon1 = lon1 * 0.017453293;
            double rLat2 = lat2 * 0.017453293;
            double rLon2 = lon2 * 0.017453293;

            double R = 20902230.97112861;

            //Haversine
            double dLat = (rLat2 - rLat1);
            double dLon = (rLon2 - rLon1);

            double a = exMath.Sin(dLat / 2.0) * exMath.Sin(dLat / 2.0) +
                       exMath.Cos(rLat1) * exMath.Cos(rLat2) *
                       exMath.Sin(dLon / 2.0) * exMath.Sin(dLon / 2.0);

            double c = 2.0 * exMath.Atan2(exMath.Sqrt(1.0 - a), exMath.Sqrt(a));

            dist = R * c;

            return dist;
        }


#6 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 01 September 2010 - 12:38 AM

Just to confirm...so you're getting ~45 on the desktop and ~4082 using the exMath library? I'll also put in an internal bug report and see if there's something we can do to boost the accuracy... Chris

#7 Patrick

Patrick

    Advanced Member

  • Members
  • PipPipPip
  • 54 posts
  • LocationTampa

Posted 01 September 2010 - 01:16 AM

Just to confirm...so you're getting ~45 on the desktop and ~4082 using the exMath library?

That's correct.

#8 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 01 September 2010 - 01:59 AM

Great, thanks! We didn't write the 3rd-party exMath library but we'll take a look and see what we can do...

#9 Patrick

Patrick

    Advanced Member

  • Members
  • PipPipPip
  • 54 posts
  • LocationTampa

Posted 01 September 2010 - 02:32 AM

Chris,

I tracked it down to an error in the exMath.Pow function when executing:

exMath.Sqrt(a)

I would get a much larger value on the .Net MF. I can't say where in that function it goes wrong however or why. However, I get around it by using the following code:

static double calculateDistance(double lat1, double lon1, double lat2, double lon2)
        {
            double dist = 0.0;

            lat1 = 41.9243;
            lon1 = -88.1007;

            lat2 = 41.924399;
            lon2 = -88.100799;

            double rLat1 = lat1 * 0.017453293;
            double rLon1 = lon1 * 0.017453293;
            double rLat2 = lat2 * 0.017453293;
            double rLon2 = lon2 * 0.017453293;

            double R = 20902230.97112861;

            //Haversine
            double dLat = (rLat2 - rLat1);
            double dLon = (rLon2 - rLon1);

            double a = exMath.Sin(dLat / 2.0) * exMath.Sin(dLat / 2.0) +
                       exMath.Cos(rLat1) * exMath.Cos(rLat2) *
                       exMath.Sin(dLon / 2.0) * exMath.Sin(dLon / 2.0);

            //using Math.Pow(a, 0.5) instead of exMath.Sqrt(a)
            double c = 2.0 * exMath.Atan2(System.Math.Pow((1.0 - a), 0.5), System.Math.Pow(a, 0.5));
  
            dist = R * c;

            return dist;
        }





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.