GPS坐标的多点定位
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GPS坐标的多点定位相关的知识,希望对你有一定的参考价值。
我有N
GPS坐标与N
距离给我一个未知的位置,我想确定。
我的第一种方法是使用三点和三边测量,正如here所描述的那样。这种方法已经非常准确(最佳误差~5km),但我想改进这一点并增加鲁棒性。因为给定距离开始时不是很准确,所以我考虑使用多个测量和多点定位。然而,事实证明这种方法准确性不太准确(最佳误差~100km)虽然我提供超过3点/距离(最多6次测试),现在我问,如果有人知道我可以拥有什么做错了。
简而言之,我的多点定位方法如下:
- 将所有坐标转换为ECEF
- 如qqxswpoi中的等式7所述构建矩阵
- 使用SVD查找最小化器
- 由于解决方案仅达到规模,我使用根寻找方法来确定归一化,以便转换回LLA的坐标导致高度为0(我的初始假设是所有坐标都在零高度)
- 转换回LLA
LLA / ECEF转换经过双重检查并且正确无误。第2步和第3步我用欧氏坐标(和精确距离)检查并显示正确。我自己想出了第4步,我不知道这是否是一个很好的方法,所以欢迎提出建议。
+++ UPDATE
我已经在python中汇总了示例代码,以说明一些基本事实的问题。三角测量接近400米,而多重定位在这里10-130公里。因为长度,我把它放在wikipedia
最终,我自己弄清楚了 - 或者至少显着提高了准确性。
维基百科(方程式7)中描述的方法显然不太适合这个应用程序,但在这种情况下它已经容易多了。
考虑方程式来自维基百科的6,我们可以简化它:ideone可以猜测为地球半径,因为ECEF坐标的原点位于地球的中心。因此,没有必要移动所有东西使一个点成为原点,我们可以使用所有R_0
方程。
在python中,N
是一个ECEF坐标数组,P
指向这些点的距离,这一切都归结为
dists
通过这种方法,我不再需要我所描述的步骤4。事实上,它甚至使解决方案变得更糟。
现在,精度范围在2km到275m之间 - 在大多数情况下比“最佳”三边测量更好,误差为464m。
一些评论:
1)您已经针对确切的答案检查了一些步骤。我建议您创建玩具问题,并在观察中添加已知量的随机噪声。由于您在这种情况下知道正确答案,因此您可以看到错误传播会发生什么。如果你的方法在这里工作得很好但对真实数据很糟糕,你可能想要考虑现实生活中的可怕行为,例如一个或几个距离严重错误。
2)我不知道为什么你的解决方案只是达到规模,因为底层数据被正确缩放 - 如果我去那里用绳索切割长度并将它们绑定到固定点,就没有歧义。当您使用SVD求解方程式(7)时,您是否正在执行类似www.cse.unr.edu/~bebis/MathMethods/SVD/lecture.pdf的操作以获得最小二乘解?这应该给你x,y和z没有歧义。
3)我完全不确定观察错误是如何起作用的(7)。一方面,我不喜欢所有的分歧。对于未知位置给定x,y,z的测量距离和计算距离之间的差异的平方和,可能值得写下等式,然后将其最小化为x,y,z。维基百科的文章由于其成本而放弃了这种方法,但它可能会给你一个更准确的答案,即使你不能在实践中使用这种方法,计算和比较这个答案也可能会告诉你一些事情。
我按照上面显示的@ zerm代码进行了相当好的工作(黄色是从3个塔点计算出来的)。结果显示在Folium片段中。 R = 6378137 # Earth radius in meters
A = []
for m in range(0,len(P)):
x = P[m][0]
y = P[m][1]
z = P[m][2]
Am = -2*x
Bm = -2*y
Cm = -2*z
Dm = R*R + (pow(x,2)+pow(y,2)+pow(z,2)) - pow(dists[m],2)
A += [[Am,Bm,Cm,Dm]]
# Solve using SVD
A = numpy.array(A)
(_,_,v) = numpy.linalg.svd(A)
# Get the minimizer
w = v[3,:]
w /= w[3] # Resulting position in ECEF
但是,当我使用@mcdowella建议(#2)使用MxN系统解决方案的最小二乘法进行相同的算法时,结果要好得多。 Multilateration using linalg.SVD
这是修改后的代码:
Multilateration using Least Squares MxN
我还在探索其他多点定位方法,但这篇文章真的让我理解了N点MLAT的基础知识。谢谢!
为了改善A = []
b = []
for m in range(0,len(P)):
x = P[m][0]
y = P[m][1]
z = P[m][2]
Am = 2*x
Bm = 2*y
Cm = 2*z
Dm = R*R + (pow(x,2)+pow(y,2)+pow(z,2)) - pow(dists[m],2)
A += [[Am,Bm,Cm]]
b += [[Dm]]
# Solve using Least Squares of an MxN System
# A*x = b --> x = (ATA)_inv.AT.b = A+.b
A = np.array(A)
b = np.array(b)
AT = A.T
ATA = np.matmul(AT,A)
ATA_inv = np.linalg.inv(ATA)
Aplus = np.matmul(ATA_inv,AT)
x = np.matmul(Aplus,b)
# convert back to lat/long from ECEF
# convert to degrees
lat = math.degrees(math.asin(x[2] / R))
lon = math.degrees(math.atan2(x[1],x[0]))
,改善SVD解决方案的一种方法是根据纬度考虑地球半径的变化;这特别影响海拔估计,但它对纬度和经度也有一些连锁反应。 “简单”的解决方案是使用the accepted answer的平均值,根据维基百科,它是6371008.8米而不是6378137米。
更准确的估计是调整纬度的R
:
R
然后根据其中一个初始点的纬度设置def EarthRadiusAtLatitude(lat):
rlat = np.deg2rad(lat)
a = np.float64(6378137.0)
b = np.float64(6356752.3)
rad = np.sqrt(((a*a*np.cos(rlat))**2 + (b*b*np.sin(rlat))**2) /
((a*np.cos(rlat))**2 + (b*np.sin(rlat))**2))
return rad
。或者,如果您的纬度变化很大,您可以根据R
的估计值计算SVD,并使用初步解决方案的纬度来使用更接近的R
估算来求解。
在进行此调整之后,在我使用构建的示例和基于LTE eNodeB时序提前值的“真实世界”数据的实验中,SVD解决方案通常在纬度和经度的一秒内,除了在一些退化情况下,这与a相当基于迭代优化的解决方案(即最小化距离残差)。
以上是关于GPS坐标的多点定位的主要内容,如果未能解决你的问题,请参考以下文章