【问题标题】:how to use direction angle and speed to calculate next time's latitude and longitude如何使用方向角和速度计算下一次的经纬度
【发布时间】:2013-10-21 14:05:05
【问题描述】:

我知道我现在的位置({lat:x,lon:y}) 我知道我的速度和方向角; 下一次如何预测下一个位置?

【问题讨论】:

    标签: geolocation gps latitude-longitude


    【解决方案1】:

    首先,根据您当前的速度和已知的时间间隔(“下一次”)计算您将行驶的距离:

    distance = speed * time
    

    然后你可以使用这个公式来计算你的新位置(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
    

    有关 Javascript 的实现,请参阅 this page 上的函数 LatLon.prototype.destinationPoint

    更新对于那些希望更充实地实现上述内容的人,这里是 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°
      }
    

    【讨论】:

    • 这里tc的值是多少,
    • tc 是径向轴承,即tc = brngInDegrees.toRadians(); - 参见destinationPoint() here where θ == tc
    • 公认的答案是最糟糕的。没有任何定义,也没有任何单位。 lat1 必须是弧度,必须说明,d 是什么?
    【解决方案2】:

    在 JS 中计算 lat 和 lng 给定方位和距离:

    //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]
    

    【讨论】:

      【解决方案3】:

      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);
      

      【讨论】:

        【解决方案4】:

        根据@clody96 和@mike 的回答,这是 R 中的一个实现,它使用具有 velocitytimesteps 的 data.frame而不是距离:

        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")
        

        这带来了与@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
        

        【讨论】:

          【解决方案5】:

          此代码适用于我:
          1. 我们要计算距离(速度*时间)。
          2. 因为在KM中也使用了earthradius,所以代码将距离转换为KM。

                      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);
          

          【讨论】:

          • 不错的代码,但我不理解“lat0”和“lon0”。你的字面意思是北极吗?还是这些是开始的纬度和经度?谢谢。
          • 是经纬度的开始
          • 太棒了。谢谢!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-19
          • 2010-09-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多