how to use direction angle and speed to calculate next time's latitude and longitude

前端 未结 5 1551
自闭症患者
自闭症患者 2021-02-04 07:42

I have know my current position({lat:x,lon:y}) and I know my speed and direction angle; How to predict next position at next time?

相关标签:
5条回答
  • 2021-02-04 07:55

    This code works for me :
    1. We have to count the distance ( speed * time ).
    2. The code converts the distance to KM because earthradius is used in KM too.

                const double radiusEarthKilometres = 6371.01f;
    
                kmDistance = kmSpeed * (timer1.Interval / 1000f) / 3600f;
    
                var distRatio = kmDistance / radiusEarthKilometres;
                var distRatioSine = Math.Sin(distRatio);
                var distRatioCosine = Math.Cos(distRatio);
    
                var startLatRad = deg2rad(lat0);
                var startLonRad = deg2rad(lon0);
    
                var startLatCos = Math.Cos(startLatRad);
                var startLatSin = Math.Sin(startLatRad);
    
                var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(angleRadHeading)));
    
                var endLonRads = startLonRad
                    + Math.Atan2(Math.Sin(angleRadHeading) * distRatioSine * startLatCos,
                        distRatioCosine - startLatSin * Math.Sin(endLatRads));
    
                newLat = rad2deg(endLatRads);
                newLong = rad2deg(endLonRads);
    
    0 讨论(0)
  • 2021-02-04 07:58

    Here in JS for calculating lat and lng given bearing and distance:

    //lat, lng in degrees. Bearing in degrees. Distance in Km
    calculateNewPostionFromBearingDistance = function(lat, lng, bearing, distance) {
      var R = 6371; // Earth Radius in Km
    
      var lat2 = Math.asin(Math.sin(Math.PI / 180 * lat) * Math.cos(distance / R) + Math.cos(Math.PI / 180 * lat) * Math.sin(distance / R) * Math.cos(Math.PI / 180 * bearing));
      var lon2 = Math.PI / 180 * lng + Math.atan2(Math.sin( Math.PI / 180 * bearing) * Math.sin(distance / R) * Math.cos( Math.PI / 180 * lat ), Math.cos(distance / R) - Math.sin( Math.PI / 180 * lat) * Math.sin(lat2));
    
      return [180 / Math.PI * lat2 , 180 / Math.PI * lon2];
    };
    
    calculateNewPostionFromBearingDistance(60,25,30,1)
    [60.007788047871614, 25.008995333937197]
    
    0 讨论(0)
  • 2021-02-04 08:06

    Based on the answer of @clody96 and @mike, here is an implementation in R using a data.frame with velocity and timesteps instead of distance:

    points = data.frame(
      lon = seq(11, 30, 1),
      lat = seq(50, 59.5, 0.5),
      bea = rep(270, 20),
      time = rep(60,20),
      vel = runif(20,1000, 3000)
    )
    
    ## lat, lng in degrees. Bearing in degrees. Distance in m
    calcPosBear = function(df) {
      earthR = 6371000; 
    
      ## Units meter, seconds and meter/seconds
      df$dist = df$time * df$vel
    
      lat2 = asin(sin(
         pi / 180 * df$lat) * 
          cos(df$dist / earthR) + 
          cos(pi / 180 * df$lat) * 
          sin(df$dist / earthR) * 
          cos(pi / 180 * df$bea));
    
      lon2 = pi / 180 * df$lon + 
        atan2(sin( pi / 180 * df$bea) * 
                     sin(df$dist / earthR) * 
                     cos( pi / 180 * df$lat ), 
                   cos(df$dist / earthR) - 
                     sin( pi / 180 * df$lat) * 
                     sin(lat2));
    
      df$latR = (180 * lat2) / pi
      df$lonR = (180 * lon2) / pi
    
      return(df);
    };
    
    df = calcPosBear(points)
    plot(df$lon, df$lat)
    points(df$lonR, df$latR, col="red")
    

    Which brings the same result as for @clody96:

    points = data.frame(
      lon = 25,
      lat = 60,
      bea = 30,
      time = 1000,
      vel = 1
    )
    df = calcPosBear(points)
    df
    
      lon lat bea time vel dist        latR        lonR
    1  25  60  30 1000   1 1000 60.00778805 25.00899533
    
    0 讨论(0)
  • 2021-02-04 08:18

    Same code in Java:

        final double r = 6371 * 1000; // Earth Radius in m
    
        double lat2 = Math.asin(Math.sin(Math.toRadians(lat)) * Math.cos(distance / r)
                + Math.cos(Math.toRadians(lat)) * Math.sin(distance / r) * Math.cos(Math.toRadians(bearing)));
        double lon2 = Math.toRadians(lon)
                + Math.atan2(Math.sin(Math.toRadians(bearing)) * Math.sin(distance / r) * Math.cos(Math.toRadians(lat)), Math.cos(distance / r)
                - Math.sin(Math.toRadians(lat)) * Math.sin(lat2));
        lat2 = Math.toDegrees( lat2);
        lon2 = Math.toDegrees(lon2);
    
    0 讨论(0)
  • 2021-02-04 08:19

    First, calculate the distance you will travel based on your current speed and your known time interval ("next time"):

    distance = speed * time
    

    Then you can use this formula to calculate your new position (lat2/lon2):

    lat2 =asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
    dlon=atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat2))
    lon2=mod( lon1-dlon +pi,2*pi )-pi
    

    For an implementation in Javascript, see the function LatLon.prototype.destinationPoint on this page

    Update for those wishing a more fleshed-out implementation of the above, here it is in Javascript:

      /**
      * Returns the destination point from a given point, having travelled the given distance
      * on the given initial bearing.
      *
      * @param   {number} lat - initial latitude in decimal degrees (eg. 50.123)
      * @param   {number} lon - initial longitude in decimal degrees (e.g. -4.321)
      * @param   {number} distance - Distance travelled (metres).
      * @param   {number} bearing - Initial bearing (in degrees from north).
      * @returns {array} destination point as [latitude,longitude] (e.g. [50.123, -4.321])
      *
      * @example
      *     var p = destinationPoint(51.4778, -0.0015, 7794, 300.7); // 51.5135°N, 000.0983°W
      */
      function destinationPoint(lat, lon, distance, bearing) {
         var radius = 6371e3; // (Mean) radius of earth
    
         var toRadians = function(v) { return v * Math.PI / 180; };
         var toDegrees = function(v) { return v * 180 / Math.PI; };
    
         // sinφ2 = sinφ1·cosδ + cosφ1·sinδ·cosθ
         // tanΔλ = sinθ·sinδ·cosφ1 / cosδ−sinφ1·sinφ2
         // see mathforum.org/library/drmath/view/52049.html for derivation
    
         var δ = Number(distance) / radius; // angular distance in radians
         var θ = toRadians(Number(bearing));
    
         var φ1 = toRadians(Number(lat));
         var λ1 = toRadians(Number(lon));
    
         var sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1);
         var sinδ = Math.sin(δ), cosδ = Math.cos(δ);
         var sinθ = Math.sin(θ), cosθ = Math.cos(θ);
    
         var sinφ2 = sinφ1*cosδ + cosφ1*sinδ*cosθ;
         var φ2 = Math.asin(sinφ2);
         var y = sinθ * sinδ * cosφ1;
         var x = cosδ - sinφ1 * sinφ2;
         var λ2 = λ1 + Math.atan2(y, x);
    
         return [toDegrees(φ2), (toDegrees(λ2)+540)%360-180]; // normalise to −180..+180°
      }
    
    0 讨论(0)
提交回复
热议问题