欧拉角和旋转矩阵的求解方法:由两个三维点求得

4

我正在尝试找到欧拉角,以使点A在三维空间中转换到点B

考虑归一化向量A=[1,0,0]B=[0.32 0.88 -0.34]

我理解通过计算A×B即可获得旋转轴。AB之间的角度tan⁻¹(||cross||,A·B)给出,其中A·BAB点积

这给我提供了旋转向量rotvec=[0 0.36 0.93 1.24359531111],其中rotvec=[A × B; angle](叉积已归一化)。

现在我的问题是:我该如何从这里开始获得与从AB变换对应的欧拉角

在MATLAB中,函数vrrotvec2mat接收旋转向量作为输入并输出旋转矩阵。然后函数rotm2eul应返回相应的欧拉角。根据XYZ约定,我得到以下结果(以弧度为单位):[0.2456 0.3490 1.2216]。然而,这不是预期的结果。

正确答案是[0 0.3490 1.2216],对应于YZ上的20°70°旋转。

当我使用eul2rot([0 0.3490 1.2216])(使用此处eul2rot)验证结果的旋转矩阵时,它与使用vrrotvec2mat(rotvec)获得的旋转矩阵不同。

我还有一个Python片段,产生与上述完全相同的结果。

--- Python(2.7)使用transform3d ---

import numpy as np
import transforms3d

cross = np.cross(A, B)
dot = np.dot(A, B.transpose())
angle = math.atan2(np.linalg.norm(cross), dot)
rotation_axes = sklearn.preprocessing.normalize(cross)
rotation_m = transforms3d.axangles.axangle2mat(rotation_axes[0], angle, True)
rotation_angles = transforms3d.euler.mat2euler(rotation_m, 'sxyz')

我在这里缺少什么?我应该做些什么呢?
谢谢。

1
欧拉角在两点之间并不唯一。这就是四元数存在的原因。 - Ander Biguri
1
@AnderBiguri 我不太明白四元数与问题有什么关系。或者你是在暗示这是一个 XY 问题 吗? - jodag
如果我使用四元数,是否可以得到唯一的解决方案?最终我仍然需要将其转换为欧拉角。 - jcampos
3
不。单位四元数是三维旋转的一种替代表示方法。与旋转矩阵相比,它更加紧凑、数值稳定并且在计算中应用更快,但其表示能力并不更强。它比欧拉角更不紧凑但不会遭受“万向锁”问题的困扰。事实上,存在多个旋转满足您的问题,因此您需要想出一种方法来强制施加进一步的约束以获得所需的解决方案。 - jodag
2个回答

4
旋转矩阵有三个自由度,但是您的问题只限制了其中两个自由度。当我们考虑一个旋转矩阵R,它将A旋转到B。如果我们构造另一个绕向量B旋转的旋转矩阵RB,则将其应用于RA不会产生任何影响,即B = RA = RBR*A。但是,它将产生不同的旋转矩阵RB * R,具有不同的欧拉角。以下是MATLAB中的示例:
A = [1; 0; 0];
B = [0.32; 0.88; -0.34];

A = A / norm(A);
B = B / norm(B);

ax = cross(A, B);
ang = atan2(norm(ax), dot(A, B)); % ang = acos(dot(A, B)) works too
R = axang2rotm([ax; ang].');

ang_arbitrary = rand()*2*pi;
RB = axang2rotm([B; ang_arbitrary].');

R*A - B
RB*R*A - B

rotm2eul(R)
rotm2eul(RB*R)

结果

ans =
   1.0e-15 *

   -0.0555
    0.1110
         0

ans =
   1.0e-15 *

    0.2220
    0.7772
   -0.2776

ans =    
    1.2220    0.3483    0.2452

ans =    
    1.2220    0.3483    0.7549

非常感谢您的回复。 我明白在这个例子中,一个向量围绕自身旋转并不成问题,但如果我有一系列相互连接的向量,它们的变换取决于前一个向量,那么就会出现您上面所示的问题。忽略X轴的旋转是正确的吗?因为叉积告诉我X轴和其他变量之间没有相互作用? - jcampos
我不确定我理解你所说的“它们的转换取决于前一个”的意思。你发布的示例是一个特殊情况,事实上,如果你将A更改为[0; 1; 0],你会发现旋转轴在Y分量中有一个零,但是RRB*R之间的所有3个欧拉角都将不同。在你的示例中我们观察到只有X轴发生变化是因为欧拉角的约定(在你的情况下是XYZ)。 - jodag
如果答案还不够清晰,那么你得到的欧拉角可以起到旋转点A到点B的作用。它们只是与你期望的不同,因为有多组欧拉角可以实现这个效果。 - jodag

1

我将基于欧拉旋转定理为您提供解决方案。

这个解决方案仅给出了一个角度,但其他角度可以推导出来。

import numpy as np


a_vec = np.array([1, 0, 0])/np.linalg.norm(np.array([1, 0, 0]))
b_vec = np.array([0.32, 0.88, -0.34])/np.linalg.norm(np.array([0.32, 0.88, -0.34]))

cross = np.cross(a_vec, b_vec)
ab_angle = np.arccos(np.dot(a_vec,b_vec))


vx = np.array([[0,-cross[2],cross[1]],[cross[2],0,-cross[0]],[-cross[1],cross[0],0]])
R = np.identity(3)*np.cos(ab_angle) + (1-np.cos(ab_angle))*np.outer(cross,cross) + np.sin(ab_angle)*vx


validation=np.matmul(R,a_vec)

在这种情况下,使用旋转轴(特征向量)作为叉乘。

矩阵R是旋转矩阵

这是一种通用且非常简单的方法。


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