我知道我当前的位置({lat:x,lon:y}) 我知道我的速度和方向角度; 如何在下次预测下一个位置?
答案 0 :(得分:10)
首先,根据您当前的速度和您已知的时间间隔(“下一次”)计算您的行程距离:
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°
}
答案 1 :(得分:7)
这里用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]
答案 2 :(得分:2)
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);
答案 3 :(得分:1)
此代码适用于我:
1.我们必须计算距离(速度*时间)。
2.代码将距离转换为KM,因为地球半径也用于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);
答案 4 :(得分:1)
根据@ clody96和@mike的答案,这是 R 中使用带有速度和时间步长的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