哪种算法对于计算3D向量之间的角度更准确?

问题描述 投票:0回答:1

多年来,我遇到了一些计算两个 3D 矢量之间角度的算法。如图所示,我已经放弃了 acos 和 asin 的极端情况问题。

我现在只剩下两个了。

  • 版本 A) atan(sub/add) 使用输入向量归一化版本的加法和减法。
  • 版本 B)atan2(crossnorm, dot) 使用输入向量的叉积和点积的长度。

我在不同的地方读过有关它们的内容,但在这个问题中,这个答案指出atan方法在较小的角度上更好。我尝试了一下,但没有注意到较小角度的任何问题。我想更深入地了解为什么一个人比另一个人更好。或者也许了解我应该如何测试它们或者我应该将它们的输出与哪个参考进行比较。

我实际上偏向atan2解决方案,版本B,因为:

  • 我在此过程中免费获得标准化旋转轴,带有 cross/crosslen。
  • 我只使用一次幂/平方根来获得十字的长度。
  • 我没有除以 0,因为当 b == -a 时,版本 A 中的 add 变量变为 0。

也就是说,如果确实版本 A 确实更准确,我会考虑将其用于我正在执行的操作,而不是 B,但我想更好地理解其原因,也许我也可以将其可视化,并且这样就更有信心采用版本 A,而不是版本 B。

以下是所有版本的实时代码版本:repl.it

谢谢

python vector trigonometry angle
1个回答
0
投票

如果您想根据经验比较方法,您需要一个基本事实来与实际的准确值进行比较。您需要使用任意精度的数学来计算它,尽管您可以使用现有的算法之一来完成它。这是一个例子:

import mpmath

mpmath.mp.dps = 50

def angle_atan_true(x, y):
    xnorm = mpmath.sqrt(mpmath.fdot(x, x))
    ynorm = mpmath.sqrt(mpmath.fdot(y, y))
    xprod = [mpmath.fmul(n, ynorm) for n in x]
    yprod = [mpmath.fmul(n, xnorm) for n in y]
    plus = [mpmath.fadd(*n) for n in zip(xprod, yprod)]
    minus = [mpmath.fsub(*n) for n in zip(xprod, yprod)]
    norm1 = mpmath.sqrt(mpmath.fdot(plus, plus))
    norm2 = mpmath.sqrt(mpmath.fdot(minus, minus))
    return mpmath.fmul(2, mpmath.atan2(norm2, norm1))

a = [1, 0, 0]
b = [1, 0, 1e-8]

print("a", a, ", b", b)
print("atan_true:", angle_atan_true(a, b))
a [1, 0, 0] , b [1, 0, 1e-08]
atan_true: 0.0000000099999999999999998758922749679513924973721774310726

(这也不是准确的值,但它应该精确到至少 40 位,足以验证机器精度版本。)

您还需要查看各种输入,而不仅仅是少数。循环遍历批次并绘制错误可能会有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.