分解旋转矩阵 (x,y',z'') - 笛卡尔角

Decomposing rotation matrix (x,y',z'') - Cartesian angles

分解旋转矩阵 (x,y',z'') - 笛卡尔角

我目前正在使用 旋转矩阵,我遇到了以下问题: 给定三个重合的坐标系 (O0,x0,y0,z0; O1,x1,y1,z1; O2,x2,y2,z2)。我们首先相对于帧 #0 旋转帧 #1,然后相对于帧 #1 旋转帧 #2。

旋转的顺序:R = Rx_alpha * Ry_beta * Rz_gamma,所以先是x,然后是y',然后是z'',也称为笛卡尔角。 如果 R1 代表第 1 次旋转,R2 代表第 2 次旋转,我们将在两次旋转后寻找第 2 帧相对于初始帧 (#0) 的角度。这可以通过 分解旋转矩阵 R (其中:R = R1*R2 )来完成。有很多可用的文献,如何通过欧拉角和 RPY 角来完成,但我没有找到,如何在笛卡尔角的情况下解决这个问题。

我有一个 matlab 函数,它只能通过简单的旋转来工作。如果所有角度的值都不是 0(下例),那么结果会变得非常不稳定。

第 1 帧相对于第 0 帧的方向:

    alpha1 = 30*pi/180;
    beta1 = 10*pi/180;
    gamma1 = 0*pi/180;

第 2 帧相对于第 1 帧的方向

    alpha2 = 10*pi/180;
    beta2 = 10*pi/180;
    gamma2 = 0*pi/180;

我用来解题的matlab函数:

function [q] = cartesian_angles(R)

beta = asin(R(1,3));

*% Catching the numerical singularty*
if abs(abs(beta)-pi/2) > eps;
    *% singulartiy of acos*
    gamma1 = acos(R(1,1) / cos(beta));
    gamma2 = asin(-R(1,2) / cos(beta));
    if gamma2<0
        gamma=2*pi-gamma1;
    else
        gamma=gamma1;
    end
    alpha1 = acos(R(3,3) / cos(beta));
    alpha2 = asin(-R(2,3) / cos(beta));
    if alpha2<0
        alpha = 2*pi-alpha1;
    else
        alpha = alpha1;
    end
else
    fprintf('beta=pi/2 \n')
    gamma = 0;
    alpha = 0;
    beta  = 0;
end;

alpha = alpha*180/pi;
beta = beta*180/pi;
gamma = gamma*180/pi;

q = [alpha; beta; gamma];

感谢您的帮助!如果您有任何问题,请随时提问!

马尔西

首先,我假设您要将条件良好的右手旋转矩阵传递给您的函数。我将使用与上面列出的相同的旋转顺序,X Y' Z''

如果您知道要从中提取角度的旋转矩阵的符号构造,那么数学就很简单了。下面是一个matlab代码示例,用于确定X-Y'-Z''阶旋转矩阵的构造

a = sym('a');%x
b = sym('b');%y
g = sym('g');%z

Rx = [1 0 0;0 cos(a) -sin(a);0 sin(a) cos(a)];
Ry = [cos(b) 0 sin(b);0 1 0;-sin(b) 0 cos(b)];
Rz = [cos(g) -sin(g) 0;sin(g) cos(g) 0;0 0 1];

R = Rz*Ry*Rx

输出如下所示:

R =

[ cos(b)*cos(g), cos(g)*sin(a)*sin(b) - cos(a)*sin(g), sin(a)*sin(g) + cos(a)*cos(g)*sin(b)]
[ cos(b)*sin(g), cos(a)*cos(g) + sin(a)*sin(b)*sin(g), cos(a)*sin(b)*sin(g) - cos(g)*sin(a)]
[       -sin(b),                        cos(b)*sin(a),                        cos(a)*cos(b)]

这是相同的结果,格式更漂亮:

现在让我们复习一下从该矩阵中提取角度的数学运算。现在是熟悉 atan2() 函数的好时机。

先求出β角(顺便说一下,alpha是绕X轴的旋转,beta是绕Y'轴的旋转,gamma是绕Z''轴的角度):

beta = atan2(-1*R(3,1),sqrt(R(1,1)^2+R(2,1)^2))

写的比较正式,

现在我们已经求解了 beta 角,我们可以更简单地求解其他两个角:

alpha = atan2(R(3,2)/cos(beta),R(3,3)/cos(beta))
gamma = atan2(R(2,1)/cos(beta),R(1,1)/cos(beta))

简化且格式更好,

上述方法是从旋转矩阵中获取欧拉角的一种非常可靠的方法。 atan2 函数确实让它变得简单多了。

最后我会回答如何求解一系列旋转后的旋转角度。首先考虑以下符号。矢量或旋转矩阵将以下列方式表示:

这里"U"表示通用坐标系,即全局坐标系。 "Fn"表示第n个不同于U的局部坐标系。R表示旋转矩阵(这种表示法也可以用于齐次变换)。左侧上标始终表示旋转矩阵或向量的父参照系。左侧下标表示子参照系。例如,如果我在 F1 中有一个向量,并且我想知道它在通用参考系中等效于什么,我将执行以下操作:

为了在通用坐标系中解析向量,我简单地将它乘以将事物从 F1 转换为 U 的旋转矩阵。请注意下标是如何 "cancelled" 由下一项的上标输出的方程。这是一个聪明的符号,可以帮助人们避免混淆。如果你还记得,条件良好的旋转矩阵的一个特殊属性是逆矩阵是矩阵的转置,也将是这样的逆变换:

既然符号细节已经解决了,我们可以开始考虑解决复杂的旋转系列。可以说我有 "n" 个坐标系(另一种说法 "n" 不同的旋转)。要找出通用框架中 "nth" 框架中的向量,我将执行以下操作:

要确定 "n" 旋转产生的 Cardan/Euler 角度,您已经知道如何分解矩阵以获得正确的角度(在某些领域也称为逆运动学),您只需需要正确的矩阵。在这个例子中,我对旋转矩阵感兴趣,它在 "nth" 坐标系中获取事物并将它们解析为通用坐标系 U:

就是这样,我只需按正确的顺序相乘即可将所有旋转组合成感兴趣的旋转。这个例子很简单。当有人想找到一个刚体的参考系在另一个刚体的参考系中解析时,会出现更复杂的情况,而这两个刚体唯一的共同点是它们在通用参考系中的测量。

我还想指出,这种表示法和方法也可以用于齐次变换,但有一些关键区别。旋转矩阵的逆是它的转置,对于齐次变换不是这样。

谢谢willpower2727的回答,你的回答很有帮助!

但我想提一下,您显示的代码对于分解按以下方式构建的旋转矩阵很有用:

R = Rz*Ry*Rx

我在找什么:

R = Rx*Ry*Rz

这导致以下旋转矩阵:

但是,这不是问题,因为按照计算角度 alpha、beta 和 gamma 的方法,修改代码很容易,所以它分解了上面显示的矩阵。

角度:

beta = atan2(  R(1,3), sqrt(R(1,1)^2+(-R(1,2))^2) )
alpha = atan2( -(R(2,3)/cos(beta)),R(3,3)/cos(beta) )
gamma = atan2( -(R(1,2)/cos(beta)),R(1,1)/cos(beta) )

有一件事还不清楚。该方法非常有用,仅当我计算旋转一圈后的角度时才会出现。由于彼此之间有更多的旋转 linked,结果是错误的。然而,我想它仍然是可以解决的,考虑以下方式:假设,我们有两个旋转 linked 彼此相继(R1 和 R2)。 q1表示R1、q2与R2的夹角。分解单个矩阵后。矩阵的总旋转角度R=R1*R2可以很容易地通过将之前的范围相加得到:q=q1+q2

有没有办法,如何计算总旋转的角度,不是求和部分角度,而是分解矩阵R=R1*R2

更新:

考虑以下基本示例。轮换 link 轮换:

a1 = 10*pi/180
b1 = 20*pi/180
g1 = 40*pi/180
R1 = Rx_a1*Ry_b1_Rz_g1

a2 = 20*pi/180
b2 = 30*pi/180
g2 = 30*pi/180
R2 = Rx_a2*Ry_b2*Rz_g2

分解单个矩阵 R1 和 R2 得到直角。问题发生了,当我 link 旋转后,我试图确定惯性框架中最后一帧的角度。从理论上讲,这可以通过分解变换链的所有旋转矩阵的乘积来完成。

R = R1*R2

分解此矩阵会得到以下以度数表示的错误结果:

a = 0.5645
b = 54.8024
g = 61.4240

马尔西