Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/rest/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 用加权多边形法寻找未知点_Python_Math_Numpy_Geolocation_Scipy - Fatal编程技术网

Python 用加权多边形法寻找未知点

Python 用加权多边形法寻找未知点,python,math,numpy,geolocation,scipy,Python,Math,Numpy,Geolocation,Scipy,我在地球上有一系列的点(纬度/经度坐标),以及从每个点到未知位置的一系列距离估计。我想用它来估计这个未知位置的位置。从一个简单的示例开始,想象4个点以及到未知位置的未知点的相关距离估计: 纬度、经度、距离估计值3元组如下: p1 = (31.2297, 121.4734, 3335.65) p2 = (34.539, 69.171, 2477.17) p3 = (47.907, 106.91

我在地球上有一系列的点(纬度/经度坐标),以及从每个点到未知位置的一系列距离估计。我想用它来估计这个未知位置的位置。从一个简单的示例开始,想象4个点以及到未知位置的未知点的相关距离估计:

纬度、经度、距离估计值3元组如下:

p1 = (31.2297, 121.4734, 3335.65)                           
p2 = (34.539, 69.171, 2477.17)                          
p3 = (47.907, 106.91, 1719.65)                      
p4 = (50.43, 80.25, 1242.27) 
已经解释了如何找到未知点,并给出了三边测量示例。使用上述示例,未知位置位于纬度/经度坐标:36.989,91.464

我的问题是独特的,因为我正在寻找一种方法来执行多重加权。每个距离估计值只是一个估计值;测量不精确,但距离越小,测量越精确。我想使用多向性,但我想在确定最终答案时,给与较小距离估计相关的点更多的“权重”,因为这些较短的估计更准确。我该怎么做?我正在寻找Python的解决方案

回到上一个示例,但引入了错误,我想再次找到点的未知位置:

p1 = (31.2297, 121.4734, 4699.15)           
p2 = (34.539, 69.171, 2211.97)        
p3 = (47.907, 106.91, 1439.75)                              
p4 = (50.43, 80.25, 1222.07)    

虽然这可能不是您想要的,但您可以将其作为起点:

import numpy as np
import scipy.optimize as opt

#Returns the distance from a point to the list of spheres
def calc_distance(point):
    return np.power(np.sum(np.power(centers-point,2),axis=1),.5)-rad

#Latitude/longitude to carteisan
def geo2cart(lat,lon):
    lat=np.deg2rad(lat)
    lon=np.deg2rad(lon)
    points=np.vstack((earth_radius*np.cos(lat)*np.cos(lon),
           earth_radius*np.cos(lat)*np.sin(lon),
           earth_radius*np.sin(lat))).T
    return points

#Cartesian to lat/lon
def cart2geo(xyz):
    if xyz.ndim==1: xyz=xyz[None,:]
    lat=np.arcsin(xyz[:,2]/earth_radius)
    lon=np.arctan2(xyz[:,1],xyz[:,0])
    return np.rad2deg(lat),np.rad2deg(lon)

#Minimization function. 
def minimize(point):
    dist= calc_distance(point)
    #Here you can change the minimization parameter, here the distances
    #from a sphere to a point is divided by its radius for linear weighting.
    err=np.linalg.norm(dist/rad)
    return err

earth_radius = 6378
p1 = (31.2297, 121.4734, 3335.65)
p2 = (34.539, 69.171, 2477.17)
p3 = (47.907, 106.91, 1719.65)
p4 = (50.43, 80.25, 1242.27)

points = np.vstack((p1,p2,p3,p4))
lat    = points[:,0]
lon    = points[:,1]
rad    = points[:,2]

centers = geo2cart(lat,lon)

out=[]
for x in range(30):
    latrand=np.average(lat/rad)*np.random.rand(1)*np.sum(rad)
    lonrand=np.average(lon/rad)*np.random.rand(1)*np.sum(rad)
    start=geo2cart(latrand,lonrand)
    end_pos=opt.fmin_powell(minimize,start)
    out.append([cart2geo(end_pos),np.linalg.norm(end_pos-geo2cart(36.989,91464))])


out = sorted(out, key=lambda x: x[1])
print 'Latitude:',out[0][0][0],'Longitude:',out[0][0][1],'Distance:',out[0][1]
我们获得:

First set of points:  lat 40.1105092 lon 88.07068701
Second set of points: lat 40.36636421 lon 88.84527729
我相信有更好的方法,但至少你可以通过权值和误差函数来看看会发生什么。当然有几个严重的问题,一个是你可能陷入局部极小值。也许有一种最小二乘法可以做到这一点——我只是目前看不到

只需再次检查这是否有效:

p0=np.random.rand(2)*90+20
p1=np.random.rand(2)*-10+20+p0
p2=np.random.rand(2)*-10+20+p0
p3=np.random.rand(2)*-10+20+p0
p4=np.random.rand(2)*-10+20+p0

target=geo2cart(p0[0],p0[1])
points=np.vstack((p1,p2,p3,p4))
lat    = points[:,0]
lon    = points[:,1]

centers=geo2cart(lat,lon)
#You can change the random at the end to tune the amount of noise
rad =  np.power(np.sum(np.power(centers-target,2),axis=1),.5)#+np.random.rand(4)*10    

print '------------'
start=geo2cart(np.average(lat),np.average(lon))
end_pos=opt.fmin_powell(minimize,start)
print 'Exact',p0
print 'Start guess',cart2geo(start)
print 'Found',cart2geo(end_pos)
print 'Distance',np.linalg.norm(end_pos-target)

Exact [  45.21292244  101.85151772]
Start guess (array([ 60.63554123]), array([ 115.08426225]))
Found (array([ 45.21292244]), array([ 101.85151772]))
Distance 5.30420680512e-11

你能描述一下你对每项测量的误差估计是如何随着距离的变化而变化的吗?它是线性增加的吗?二次?这是个好问题。为了简单起见,让我们假设它是线性的。感谢这项伟大的工作。有一件事我不明白,你从哪里得到第一组和第二组点的答案。例如,对于第一组点,您得到的解为
40.1105092,88.07068701
,距离实际位置很远(~500km)。另外,当我运行您的脚本时,
cart2geo()
给出了预测的lat,lon,位于
54.85960821,89.49203514
,而不是
40.1105092,88.07068701
。我理解正确吗?你能详细解释一下吗?我在玩起点游戏——正如前面提到的,你很容易陷入局部极小值。原始数据中存在什么样的噪声?噪音的微小变化可以在很大程度上改变答案。另外,SVD下的第二组点给出了完全不同的结果。