基于给定距离和与trans的方位移动xy坐标

2024-04-28 22:32:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一条船沿着样带移动,寻找动物。有人站在船的顶部,面向前方,当看到一只动物时,他正在记录离船的距离和船前部的方位。我有这方面的信息,以及看到动物时船的xy坐标。我需要根据这些信息获取动物自身的xy坐标。

我没有船原来的指南针方位,这使得这件事很棘手;但我有船的下一个GPS(xy)坐标,从中我可以计算出一个起始角度。由此,可以加上或减去观察动物的方位角,给出一个标准化的角度,该角度可用于通过三角法找到动物的xy坐标。不幸的是,我的数学能力还不能胜任这项工作。

我有几百个点,所以我需要把它放到一个Python脚本中来完成所有的点。

总之,数据集具有:

原始X,原始Y,结束(下一个)X,结束(下一个)Y,方向角,距离

编辑:对不起,我太急了,没有很好的解释。

我认为这个问题有三个阶段。

  1. 寻找样带的原始方位
  2. 确定点相对于横断面的方位
  3. 基于此标准化角度和在起点xy处与船的距离,找到点的新坐标

我最初使用的Python代码如下,尽管它没有太多用处-给出的数字是示例。

    distFromBoat = 100
    bearing = 45


    lengthOpposite = origX-nextX
    lengthAdjacent = origY - nextY
    virtX = origX #virtual X
    virtY = origY-lengthOpposite #virtual Y
    angle = math.degrees(math.asin(math.radians((lengthOpposite/transectLen))))
    newangle = angle + bearing
    newLenAdj = math.cos(newangle)*distFromBoat
    newLenOpp = math.sqrt(math.pow(distFromBoat,2) + math.pow(newLenAdj,2) - 2*(distFromBoat*newLenAdj)*(math.cos(newangle)))
    newX = virtX-newLenOpp
    newY = origY-newLenAdj
    print str(newX) +"---"+str(newY)

提前感谢您的帮助!


Tags: 信息距离math角度动物xy方位newangle
3条回答

据我所知,这是你的问题:

  • 你有两个点,startnext你走在
  • 你想找到第三个点的坐标,New,它应该是从startnext的距离和方位,因为你已经面对从startnext

我的解决方案是:

  • 创建从startnext的规范化向量
  • 按给定方向旋转规范化向量
  • 将标准化的旋转矢量乘以距离,然后将其添加到start
  • start当作向量,加法的结果就是新的点

因为逆时针旋转(“左”从当前点)被认为是正的,所以需要反转bearing,使端口与负相关联,右舷与正相关联。

代码

import math
origX = 95485
origY = 729380

nextX = 95241
nextY = 729215

distance = 2000.0
bearing = 45

origVec = origX, origY
nextVec = nextX, nextY


#Euclidean distance between vectors (L2 norm)
dist = math.sqrt((nextVec[0] - origVec[0])**2 + (nextVec[1] - origVec[1])**2)

#Get a normalized difference vector
diffVec = (nextVec[0] - origVec[0])/dist, (nextVec[1] - origVec[1])/dist


#rotate our vector by bearing to get a vector from orig towards new point
#also, multiply by distance to get new value
#invert bearing, because +45 in math is counter-clockwise (left), not starboard
angle = math.radians(-bearing)

newVec = origVec[0]+(diffVec[0]*math.cos(angle) - diffVec[1]*math.sin(angle))*distance, \
         origVec[1]+(diffVec[0]*math.sin(angle) + diffVec[1]*math.cos(angle))*distance

print newVec

输出:

(93521.29597031244, 729759.2973553676)

马特的函数有一点问题,所以我用atan2来得到船的角度。

编辑:这比我想象的要复杂。最后,你需要减去90,取反方向,从地理参考角度到三角角度。

(还有一个angles库(可能还有其他地理库)内置了这个功能。

现在取origXorigY,找到三角角并将其转换为heading,将方向角添加到为横断面确定的角度。然后它在距离上触发,但使用转换回触发度的角度-(X-90)。这是一种扭曲,因为我们习惯于把0度看作北/上,但在trig中它是“向右”,trig逆时针与顺时针进行导航。

import math

origX = 0.0
origY = 0.0

nextX = 0.0
nextY = -1.0

distance = 100.0
bearing = 45


def angle(origX,origY,nextX,nextY):
    opp = float(nextY - origY)
    adj = float(nextX - origX)
    return(math.degrees(math.atan2(adj,opp)))
# atan2 seems to even work correctly (return zero) when origin equals next

transectAngle = angle(origX,origY,nextX,nextY) # assuming the function has been defined
print "bearing plus trans", transectAngle + bearing
trigAngle = -(transectAngle + bearing -90)
print "trig equiv angle", trigAngle
newX = origX + distance * math.cos(math.radians(trigAngle))
newY = origY + distance * math.sin(math.radians(trigAngle))

print "position",newX,newY

输出:

-70.7106781187 -70.7106781187

这里有一个函数可以打印出一堆测试用例(使用全局变量,因此应该折叠到上面的代码中)

def testcase():
    bearinglist = [-45,45,135,-135]
    dist = 10
    for bearing in bearinglist:
        print "----transect assuming relative bearing of {}------".format(bearing)
        print "{:>6}  {:>6}  {:>6}  {:>6}  {:>6}  {:>6}  {:>6}  {:>6}".format("x","y","tran","head","trigT","trigH","newX","newY")  
        for x in [0,.5,-.5]:
            for y in [0,.5,1,-.5]:
                # print "A:", x,y,angle(origX,origY,x,y)
                tA = newangle(origX,origY,x,y)
                trigA = -(tA-90)
                heading = tA + bearing
                trigHead = -(heading-90)
                Xnew = distance * math.cos(math.radians(trigHead))
                Ynew = distance * math.sin(math.radians(trigHead))
                print "{:>6.1f}  {:>6.1f}  {:>6.1f}  {:>6.1f}  {:>6.1f}  {:>6.1f}  {:>6.1f}  {:>6.1f}".format(x,y,tA,heading,trigA,trigHead,Xnew,Ynew)

enter image description hereadding paths

可能有比这更优雅的解决方案…假设我正确理解了你的问题。但是,这会给你从原来位置的方位:

(以硬编码输入为例)

import math

origX = 0.0
origY = 0.0

nextX = 1.0
nextY = 0.0

Dist = ((nextX - origX)**2 + (nextY - origY)**2)**0.5

if origX == nextX and origY == nextY:
    angle = 0

if origX == nextX and nextY < origY:
    angle = 180

if nextY < origY and origX > nextX:
    angle = math.degrees(math.asin((nextX -origX)/Dist)) - 90

if nextX > origX and nextY < origY:
    angle = math.degrees(math.asin((nextX -origX)/Dist)) + 90

else:
    angle = math.degrees(math.asin((nextX -origX)/Dist))

print angle

相关问题 更多 >