使用位置信息查找移动旋转角度

3
我需要找到以度数表示的车辆转向角度。位置点等间隔更新(1秒)。因此,在转弯过程中,设备会生成大约4-5个点。我在图片上用示意图显示了这一点。
能否使用位置信息计算转向角度?如果可以,如何计算?
我的尝试:
1. 从点3、4和点1、2创建两个几何向量,然后找到这些向量之间的角度。 我计算向量的坐标为Vector1(lat2-lat1; lon2-lon2)。 不确定这种方法是否适用于位置坐标。 2. 使用location1.bearingTo(location2)。 但是,这并没有给出预期的结果。似乎它提供了“指南针”结果。也许我可以用它来做些什么,但我不确定。 3. 还尝试了一些三角公式,例如这里这里这里。 它们都没有给出预期的角度。
编辑:解决方案 接受的答案非常好。 但是为了完成答案,我必须展示angleDifference方法。 这个对我有用:
public int getAngleDifference(int currentAngle){
    int r = 0;
    angleList.add(currentAngle);
    if (angleList.size() == 4) {
        int d = Math.abs(angleList.get(0) - angleList.get(3)) % 360;
        r = d > 180 ? 360 - d : d;

        angleList.clear();
    }
    return r;
}

我将在列表中添加点,直到有四个点,并计算第一个点和第四个点之间的角度差以获得更好的结果。
希望这对某个人有所帮助!
2个回答

2
vect1 = LatLon2 - LatLon1; // vector subtraction

vect2 = LatLon4 - LatLon3;

根据点积的定义,其具有以下属性:

vect1.vect2 = ||vect1||*||vect2||*Cos(theta)

以下是符号说明

vect1.vect2 表示向量 vect1vect2 的点积。

点积的一般形式可以按照分量进行拆解,假设 v1=<x1,y1>v2=<x2,y2> 是两个任意向量,则它们的点积为:

v1.v2 = x1*x2 + y1*y2 

任意向量v的大小为:

||v|| = sqrt(v.v); which is a scalar.

上述内容等同于具有x和y分量的欧几里得距离公式:
||v|| = sqrt(x^2 + y^2)

获取角度

给定两个向量vect1vect2,找到theta的值:

theta = Math.ArcCos(vect1.vect2/(||vect1||*||vect2||))

ArcCos在小角度下数值上是病态的,这种情况会在连续的GPS修复中发生。(这就是为什么存在Haversine公式,它避免了ArcCos())你是否曾经实现过这个任务的工作解决方案? - AlexWien
@AlexWien 小角度是一个 U 形转弯吗?点积给出了他所寻找的角度,是的,任何坐标几何课程都会让你实现这个功能。唯一不足的是,它不能确定人的行进方向,是向右还是向左。它总是给出两个向量之间的最小角度。 - Felix Castor
谁在谈论掉头?这只是一个转弯。你的公式结果范围是多少:[0-90)还是[0-180)?它是否会返回179.99用于掉头?当直行没有转弯时,它是否会返回0? - AlexWien
OP并没有要求那个。他画了一张图片,指出了他所寻找的角度。请参见点积……阅读几何定义部分。我假设坐标可以近似为欧几里得距离,因为球体比转弯距离大得多,所以不需要使用haversine函数。 - Felix Castor
抱歉如果我之前没有提到,但是我也对U型转弯感兴趣。当我直行时,角度应该为0。角度越精确,解决方案就越好。 - AnZ
@FelixCastor,我也想尝试你的方法。请问vector.vectorsqrt(vect.vect)中代表什么?据我所知,它应该是一个点积值。但是,vect1.vect2vector.vector有什么区别呢?可能是我太蠢了。 - AnZ

1
方法一并不像您所描述的那样起作用:纬度和经度不是笛卡尔坐标(一度经度在米中表示不是一度纬度,这只在赤道上有效)。您首先需要转换为(本地)笛卡尔系统。
绘图中有一个错误:标记为“?”的角度放错了。您很可能想要的角度是:180-? 在您的示例中,汽车转弯的角度小于90度,尽管您的角度显示大于90度。 为了更好地理解,请再画一个图,汽车向左转10度。在您的图中,这将是170°,这是错误的。
方法二)效果更好,但您需要总结角度差异。 您必须自己编写一个方法。
double angleDifference(double angle1, double angle2);

这看起来比实际要容易些,尽管代码只有几行。 确保你有一些测试用例来测试穿越360度限制时的行为。 例如(从方位角10转到方位角350),应该给出20或-20,具体取决于您希望该方法给出绝对值还是相对角度。

我已经实施了这种方法。即使我没有移动,角度也会每次改变。这可能是由于位置坐标的散布(其精度约为10米)引起的。无论如何,我会测试一下并告诉你结果。 - AnZ
bearingTo表现很好,指向正确方向,尽管我不是很了解如何将那些(-180; 180)度转换为汽车转向角度。您可以给出更多说明或angleDifference()方法的示例(最好是示例)吗? - AnZ
1
你需要过滤站立时的那些动作。至于角度差别,可以在网上搜索并编写一些单元测试案例。如果将角度差相加,就能得到旋转角度。 - AlexWien

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接