我有N
GPS坐标,N
距离给我想要确定的未知位置。
我的第一种方法是仅使用三点和三边测量,完全如描述here。这种方法已经非常准确(最佳误差~5km),但我想改进这一点并增加鲁棒性。 因为给定距离开始时不是很准确,所以我考虑使用多个测量和多点定位。 然而,事实证明这种方法准确性不太准确(最佳误差~100km)虽然我提供超过3点/距离(最多6次测试),现在我问,如果有人知道我可以拥有什么做错了。
简而言之,我的多角化方法如下:
答案 0 :(得分:6)
最终,我自己弄清楚了 - 或者至少显着提高了准确性。
维基百科(Eq.7)中描述的方法显然不太适合这个应用程序,但在这种情况下它已经容易得多了。
考虑方程式6来自维基百科,我们可以简化它:R_0
可以猜测为地球半径,因为ECEF坐标的原点位于地球的中心。因此,没有必要转移所有内容以使一个Point成为原点,我们可以使用所有N
方程式。
在python中,P
是一个ECEF坐标数组,dists
到这些点的距离,一切都归结为
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
使用这种方法,我不再需要我所描述的 Step 4 。事实上,它甚至会使解决方案变得更糟。
现在,准确度范围在2km到275m之间 - 在大多数情况下比“最佳”三边测量更好,误差为464m。
答案 1 :(得分:2)
一些意见:
1)您已经针对确切答案检查了一些步骤。我建议您创建玩具问题,并在观察中添加已知量的随机噪声。由于您在这种情况下知道正确答案,因此您可以看到错误传播会发生什么。如果你的方法在这里工作得很好但对真实数据很糟糕,你可能想要考虑现实生活中的可怕行为,例如一个或几个距离严重错误。
2)我不知道为什么你的解决方案只是按比例扩展,因为基础数据被正确缩放 - 如果我去那里用绳索剪切长度并将它们绑定到固定点,那么就没有歧义。当您使用SVD求解方程式(7)时,您是否正在执行类似www.cse.unr.edu/~bebis/MathMethods/SVD/lecture.pdf的操作以获得最小二乘解?这应该给你x,y和z没有歧义。
3)我完全不确定观察错误是如何起作用的(7)。一方面,我不喜欢所有的分歧。对于未知位置给定x,y,z的测量距离和计算距离之间的差异的平方和,可能值得写下方程式,然后将其最小化为x,y,z。维基百科的文章由于其成本而放弃了这种方法,但它可能会给你一个更准确的答案,即使你不能在实践中使用这种方法,计算和比较这个答案也可能会告诉你一些事情。
答案 2 :(得分:0)
我按照上面显示的@ zerm代码运行得相当好(黄色是从3个塔点计算的)。结果显示在Folium片段中。 Multilateration using linalg.SVD
然而,当我使用@mcdowella建议(#2)使用MxN系统解决方案的最小二乘法进行的相同算法时,结果要好得多。 Multilateration using Least Squares MxN
以下是修订后的代码:
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]))
我还在探索其他多重定位方法,但是这篇文章真的让我理解了N点MLAT的基础知识。谢谢!
答案 3 :(得分:0)
为了改善the accepted answer,改善SVD解决方案的一种方法是根据纬度考虑地球半径的变化;这特别影响海拔估计,但它对纬度和经度也有一些连锁反应。 “简单”的解决方案是使用R
的平均值,根据维基百科的平均值为6371008.8米,而不是6378137米。
更准确的估算是调整纬度的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
。或者,如果您的纬度变化很大,您可以根据估算值R
来计算SVD,并使用初步解决方案的纬度来使用更近的R
估算来解决。
在进行此调整之后,在我使用构建的示例和基于LTE eNodeB时序提前值的“真实世界”数据的实验中,SVD解决方案通常在纬度和经度的一秒之内,除了在一些退化情况下,这是相当的与基于迭代优化的解决方案相当(即最小化距离残差)。