【问题标题】:Decomposing rotation matrix (x,y',z'') - Cartesian angles分解旋转矩阵 (x,y',z'') - 笛卡尔角
【发布时间】:2016-12-31 21:36:52
【问题描述】:

分解旋转矩阵 (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 角来完成,但我没有找到任何关于在笛卡尔角的情况下如何解决这个问题的文献。

我有一个 ma​​tlab 函数,它只能通过简单的旋转来工作。如果所有角度的值都不是 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];

感谢您的帮助!如果您有任何问题,请不要犹豫!

马西

【问题讨论】:

  • 首先,Matlab 有一个名为 atan2() 的函数,它可以为您节省一些麻烦。其次,我认为欧拉角与您在这里尝试使用的相同。我错了吗?
  • 我知道 atan2 功能,但老实说,我对使用它还没有信心,我不知道如何将它包含到上面的代码中。通过欧拉角,第一次和最后一次旋转的轴总是相同的(例如:Z,X',Z'')。通过万向角,我们围绕每个轴旋转一次(例如:X、Y'、Z''),但是,旋转的顺序可能会有所不同(根据此链接:kwon3d.com/theory/euler/euler_angles.html)。在我的理解中,这意味着 Roll-Pitch-Yaw 角 (Z,Y',X'') 只是一种特殊的万向角。我在找什么:X,Y',Z''

标签: matlab rotational-matrices cartesian decomposition


【解决方案1】:

感谢您对 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) )

但仍有一点不清楚。该方法非常有用,仅当我在旋转一圈后计算角度时才有效。由于有更多的旋转相互连接,结果是错误的。但是,我想它仍然可以解决,考虑以下方式:假设我们有两个相互连接的旋转(R1 和 R2)。 q1 表示 R1 和 R2 的 q2 的角度。在分解单个矩阵之后。矩阵R=R1*R2的总旋转角度可以通过前面的范围相加很容易计算出来:q=q1+q2

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

更新:

考虑以下基本示例。它们是相互连接的旋转:

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 得到直角。当我将旋转彼此链接并尝试确定惯性框架中最后一帧的角度时,就会出现问题。理论上,这可以通过分解变换链的所有旋转矩阵的乘积来完成。

R = R1*R2

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

a = 0.5645
b = 54.8024
g = 61.4240

马西

【讨论】:

  • 是的,有一种正确的方法来计算最终或总旋转集。我将编辑我的答案以包含此信息
  • 将来,当您在 SO 上拥有超过 20 个代表点时,您可以使用聊天服务而不是回复另一个答案。仅供参考
  • 还要注意乘以旋转矩阵的顺序,RxRyRz 与 RzRyRx 不同,正确的顺序取决于您的应用程序
  • 根据我读过的文献,RzRyRx 旋转比较常见,但是,在这种情况下我必须使用 RxRyRz 旋转。
【解决方案2】:

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

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

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() 函数的好时机。

首先求解 beta 角(顺便说一下,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”表示不同于 U 的第 n 个局部坐标系。R 表示旋转矩阵(该符号也可用于齐次变换)。左侧上标将始终表示旋转矩阵或向量的父参考系。左侧下标表示子参考系。例如,如果我在 F1 中有一个向量,并且我想知道它在通用参考系中的等价物是什么,我将执行以下操作:

为了在通用框架中解析向量,我只需将其乘以将事物从 F1 转换为 U 的旋转矩阵。注意下标是如何被等式中下一项的上标“取消”的。这是一个巧妙的符号,可以帮助某人避免混淆。如果您还记得,条件良好的旋转矩阵的一个特殊属性是逆矩阵是矩阵的转置,也将是这样的逆变换:

现在符号细节已经不碍事了,我们可以开始考虑求解复杂的旋转序列了。假设我有“n”个坐标系(另一种说法是“n”个不同的旋转)。要找出通用框架中“第 n 个”框架中的向量,我会执行以下操作:

要确定由“n”个旋转产生的卡丹/欧拉角,您已经知道如何分解矩阵以获得正确的角度(在某些领域也称为逆运动学),您只需要正确的矩阵。在这个例子中,我对旋转矩阵感兴趣,它将“第 n 个”坐标系中的事物解析为通用框架 U:

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

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

【讨论】:

  • 感谢您回答@willpower2727!我的评论会超过字符限制,所以我在一个新的答案中对你的答案做出了反应。马西
  • 感谢您修改后的评论,它非常详细和直接!我的评论又会花太长时间,所以我必须写一个答案。正如 SO 告诉我只将 answers 用于 real answers 而不是用于问题,我宁愿不添加新答案,我只是编辑/更新我以前的答案。顺便说一句,在计算过程中我使用右手法则,我将正确顺序的旋转链接在一起,并以弧度进行计算。所以希望问题是由其他原因引起的。再次感谢您的耐心和详细解答!
  • @Marci.P 我希望一切顺利。如果您觉得我的回答有用,请点赞并选择,以便其他阅读此问题的人知道该去哪里看。
猜你喜欢
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多