9

Looking for resources or algorithm to calculate the following in a navigation app:

If my current GPS position is (0,0) and I'm heading 32 degrees at 15 miles per hour, how can I calculate what my position will be in 10 seconds?

i.e.: GPSCoordinate predictedCoord = GPSCoordinate.FromLatLong(0, 0).AddByMovement(32, 15, TimeSpan.FromSeconds(10));

Edit: Current code based on answer below:

public GPSCoordinate AddMovementMilesPerHour(double heading, double speedMph, TimeSpan duration)
{
    double x = speedMph * System.Math.Sin(heading * pi / 180) * duration.TotalSeconds / 3600;
    double y = speedMph * System.Math.Cos(heading * pi / 180) * duration.TotalSeconds / 3600;

    double newLat = this.Latitude + 180 / pi * y / earthRadius;
    double newLong = this.Longitude + 180 / pi / System.Math.Sin(this.Latitude * pi / 180) * x / earthRadius;

    return GPSCoordinate.FromLatLong(newLat, newLong);
}
Brandon
  • 13,956
  • 16
  • 72
  • 114
  • If the car is moving on a street you might want to follow the street instead of extrapolating linearly. – CodesInChaos Feb 05 '11 at 20:36
  • @CodeInChaos in this case, I do want linear; this does not take ground paths into account (maybe later!) – Brandon Feb 05 '11 at 21:23
  • The code in first answer on http://stackoverflow.com/questions/3225803/calculate-endpoint-given-distance-bearing-starting-point
    will explain you everything
    – Faruk Dec 17 '13 at 03:45

2 Answers2

10

Here is the complete parametric answer :

variables :

  • heading : heading (i.e. backwards angle from azimuth 0°, in degrees)
  • speed : velocity (i.e. norm of the speed vector, in miles/hour)
  • lat0, lon0 : initial coordinates in degrees
  • dtime : time interval from the start position, in seconds
  • lat, lon : predicted coordinates in degrees
  • pi : the pi constant (3.14159...)
  • Rt : Earth radius in miles (6378137.0 meters which makes 3964.037911746 miles)

In an (East, North) local frame, the position after the time interval is :

x = speed * sin(heading*pi/180) * dtime / 3600;
y = speed * cos(heading*pi/180) * dtime / 3600;

(with coordinates in miles)

From there you can compute the new position in the WGS84 frame (i.e. latitude and longitude) :

lat = lat0 + 180 / pi * y / Rt;
lon = lon0 + 180 / pi / sin(lat0*pi/180) * x / Rt;

Edit : corrected the last line : *sin(phi) to /sin(phi)

Stéphane
  • 6,920
  • 2
  • 43
  • 53
  • 1
    Don't try this on a polar expedition :P The code breaks down in close proximity (a few meters I guess) to a pole – CodesInChaos Feb 05 '11 at 21:32
  • Yeah maybe I should have mentioned it... But it is a good approximation as long as you don't get too close to the poles and the order of magnitudes for the distances stay around or below 10km. Thanks! – Stéphane Feb 05 '11 at 21:37
  • 1
    Great answer, thank you. If I am ever on a polar expedition, my code would not only be broken, but my idea of a good time would be as well... – Brandon Feb 05 '11 at 21:40
  • Interesting, from point (0, 1) to (0, 2) this yields ~111 kilometers / ~69 miles, but from point (35, 1) to (35, 2) yields ~3081 km / ~1914 miles. Any idea why? – Brandon Feb 06 '11 at 04:03
  • Oops eror in the last line... COrrected, thanks! This is because the ratio longitude/distance depends on the latitude (this is the sin(lat0) factor in the last code line). To understand it, imagine you have to walk around the Earth while staying at a given latitude : the higher the latitude (i.e. the closer to the poles), the shorter it gets! – Stéphane Feb 06 '11 at 08:06
  • Isn't WGS84 an ellipsoid? This looks like a spherical approximation. – Peter Taylor Feb 06 '11 at 14:21
  • @Peter - Yes, and yes. As I wrote above, this simple approximation is precise enough as long as distances stay small (roughly below 100km). – Stéphane Feb 06 '11 at 18:38
0

Here are the formulas that you need.

http://www.movable-type.co.uk/scripts/latlong.html

Hope that helps.

Bob

[update] Here are the formulas in JavaScript (copied from source)

var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +                       Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) ); var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),                              Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));

d=distance traveled=velocity x time R=radius of the earth

rcravens
  • 8,320
  • 2
  • 33
  • 26