我目前正在使用旋转矩阵,我遇到以下问题:
给定三个坐标系(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代表第一轮,R2代表第二轮的R2,我们在两个旋转后寻找第二帧相对于初始帧(#0)的角度。这可以通过分解旋转矩阵 R(其中:R = R1*R2
)来完成。有许多文献可供参考,如何通过欧拉和RPY角度来完成,但我没有找到任何,如何在笛卡尔角的情况下解决这个问题。
我有一个 matlab函数,只能通过简单的旋转。如果所有角度的值都不是0(例如下面的例子),那么结果就会变得非常不稳定。
第一帧相对于帧#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];
感谢您的帮助!如果您有一些问题,请不要犹豫!
马尔西
答案 0 :(得分:0)
首先,我假设你正在将一个条件良好的右手旋转矩阵传递给你的函数。我将使用与上面列出的相同的旋转顺序,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轴的旋转,β是围绕Y'轴的旋转,而gamma是围绕Z'轴的角度):
beta = atan2(-1*R(3,1),sqrt(R(1,1)^2+R(2,1)^2))
写得更正式,
现在我们已经解决了β角度,我们可以更简单地解决其他两个角度:
alpha = atan2(R(3,2)/cos(beta),R(3,3)/cos(beta))
gamma = atan2(R(2,1)/cos(beta),R(1,1)/cos(beta))
简化并以更好的格式
上述方法是一种非常强大的方法,可以将Euler角度从旋转矩阵中取出。 atan2功能确实使它更简单。
最后,我将回答一系列旋转后如何求解旋转角度。首先考虑以下符号。矢量或旋转矩阵将以下列方式标记:
这里“U”代表通用框架或全局坐标系。 “Fn”表示与U不同的第n个局部坐标系.R表示旋转矩阵(该表示法也可用于均匀变换)。左侧上标将始终表示旋转矩阵或向量的父参考框架。左侧下标表示子参考框架。例如,如果我在F1中有一个向量,并且我想知道它在通用参考框架中的等效性,那么我将执行以下操作:
为了在通用框架中解析向量,我简单地将它乘以将事物从F1转换为U的旋转矩阵。注意下标中下一项的上标如何“取消”下标。这是一个聪明的符号,可以帮助别人搞清楚事情。如果你还记得,条件良好的旋转矩阵的一个特殊性质是逆矩阵是矩阵的转置,这也是这样的逆变换:
现在说明符号细节已经不在了,我们可以开始考虑解决复杂的旋转系列。假设我有“n”个坐标系(另一种说法是“n”不同的旋转)。为了找出通用框架中“第n”帧中的向量,我将执行以下操作:
要确定由“n”旋转产生的Cardan / Euler角度,您已经知道如何分解矩阵以获得正确的角度(在某些字段中也称为反向运动),您只需要正确的矩阵。在这个例子中,我对旋转矩阵感兴趣,旋转矩阵将事物放在“第n”坐标系中并将它们解析为通用框架U:
有它,我只是通过乘以正确的顺序将所有旋转组合成感兴趣的旋转。这个例子很简单。当有人想要在另一个框架中找到一个刚体的参考框架时,会出现更复杂的情况,这两个刚体的共同点就是它们在通用框架中的测量。
我还要注意,这种表示法和方法也可以用于同构变换,但有一些关键的区别。旋转矩阵的逆是它的转置,对于均匀变换不是这样。
答案 1 :(得分:0)
感谢您回答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表示R2的R1,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
马尔西