rpy角与旋转矩阵之间的转换(附完整代码)


  根据绕轴旋转的次序不同,易知姿态的rpy(roll, pitch, yaw)表示总共有12种,分别为:XYZ, XZY, XYX, XZX; YXZ, YZX, YXY, YZY; ZXY, ZYX, ZXZ, ZYZ。同样的,姿态的欧拉角表示也有12种。在实际应用中,没必要掌握所有情况,只需认准一种,能够实现rpy角与旋转矩阵之间的转换即可。姿态的rpy表示中,ZYX最为常见,下面推导该情况下,rpy角与旋转矩阵之间的转换。

一、 rpy角转换为旋转矩阵

  ZYX rpy角转换为旋转矩阵:
R = R o t z ( c ) ∗ R o t y ( b ) ∗ R o t x ( a ) (1) R = Rotz(c)*Roty(b)*Rotx(a) \tag 1 R=Rotz(c)Roty(b)Rotx(a)(1)
  符号表达式MATLAB代码:

clc
clear

syms a b c real;

rotx_a = [sym(1), sym(0), sym(0)
        sym(0), cos(a), -sin(a)
        sym(0), sin(a), cos(a)]
    
roty_b = [cos(b), sym(0), sin(b)
        sym(0), sym(1), sym(0)
        -sin(b), sym(0), cos(b)]      
 
rotz_c = [cos(c), -sin(c), sym(0)
        sin(c), cos(c), sym(0)
        sym(0), sym(0), sym(1)]

R = rotz_c * roty_b * rotx_a


b = sym(-pi/2);
simplify(eval(R))

b = sym(pi/2);
simplify(eval(R))

在这里插入图片描述

二、 旋转矩阵转换为rpy角

  设已知旋转矩阵:
R = [ r 11 r 12 r 13 r 21 r 22 r 23 r 31 r 32 r 33 ] (2) R = \left[ \begin{matrix} r_{11} & r_{12} & r_{13} \\ r_{21} &r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \\ \end{matrix} \tag 2 \right] R=r11r21r31r12r22r32r13r23r33(2)
  设rpy角 a , b , c ∈ [ − π , π ] a,b,c\in[-\pi,\pi] a,b,c[π,π],根据旋转矩阵关于rpy角 a , b , c a,b,c a,b,c的解析表达式,以最简单一项( r 31 r_{31} r31)为突破口。
  1)若 r 31 = 1 r_{31}=1 r31=1,则 b = − π / 2 b=-\pi/2 b=π/2,此时有:
R = [ 0 − s i n ( a + c ) − c o s ( a + c ) 0 c o s ( a + c ) − s i n ( a + c ) 1 0 0 ] (3) R = \left[ \begin{matrix} 0 & -sin(a+c) & -cos(a+c) \\ 0 & cos(a+c) & -sin(a+c) \\ 1 & 0 &0 \\ \end{matrix} \tag 3 \right] R=001sin(a+c)cos(a+c)0cos(a+c)sin(a+c)0(3)
  姿态奇异,无法计算 a , c a,c a,c,只能计算 a + c a+c a+c
  取 a = 0 a=0 a=0,则有:
{ r 12 = − s i n ( c ) r 13 = − c o s ( c ) (4) \begin{cases} r_{12}=-sin(c)\\ r_{13}=-cos(c)\\ \tag 4 \end{cases} {r12=sin(c)r13=cos(c)(4)
  故有:
c = a t a n 2 ( − r 12 , − r 13 ) (5) c=atan2(-r_{12},-r_{13}) \tag 5 c=atan2(r12,r13)(5)
  2)若 r 31 = − 1 r_{31}=-1 r31=1,则 b = π / 2 b=\pi/2 b=π/2,此时有:
R = [ 0 s i n ( a − c ) c o s ( a − c ) 0 c o s ( a − c ) − s i n ( a − c ) − 1 0 0 ] (6) R = \left[ \begin{matrix} 0 & sin(a-c) & cos(a-c) \\ 0 & cos(a-c) & -sin(a-c) \\ -1 & 0 &0 \\ \end{matrix} \tag 6 \right] R=001sin(ac)cos(ac)0cos(ac)sin(ac)0(6)
  姿态奇异,无法计算 a , c a,c a,c,只能计算 a − c a-c ac
  取 a = 0 a=0 a=0,则有:
{ r 12 = s i n ( − c ) = − s i n ( c ) r 13 = c o s ( − c ) = c o s ( c ) (7) \begin{cases} r_{12}=sin(-c)=-sin(c)\\ r_{13}=cos(-c)=cos(c)\\ \tag 7 \end{cases} {r12=sin(c)=sin(c)r13=cos(c)=cos(c)(7)
  故有:
c = a t a n 2 ( − r 12 , r 13 ) (8) c=atan2(-r_{12},r_{13}) \tag 8 c=atan2(r12,r13)(8)
  3)若 r 31 ≠ ± 1 r_{31}\ne\pm1 r31=±1,则 b ≠ ± π / 2 b\ne\pm \pi/2 b=±π/2 c o s ( b ) ≠ 0 cos(b)\ne0 cos(b)=0
   a , c a,c a,c的一个解:
{ a = a t a n 2 ( r 32 , r 33 ) c = a t a n 2 ( r 21 , r 11 ) (9) \begin{cases} a= atan2(r_{32},r_{33})\\ c= atan2(r_{21},r_{11})\\ \tag 9 \end{cases} {a=atan2(r32,r33)c=atan2(r21,r11)(9)
   a , c a,c a,c的另一个解:
{ a = a t a n 2 ( − r 32 , − r 33 ) c = a t a n 2 ( − r 21 , − r 11 ) (10) \begin{cases} a=atan2(-r_{32},-r_{33})\\ c= atan2(-r_{21},-r_{11}) \\ \tag {10} \end{cases} {a=atan2(r32,r33)c=atan2(r21,r11)(10)
  若 ∣ c o s ( c ) ∣ > ∣ s i n ( c ) ∣ |cos(c)|>|sin(c)| cos(c)>sin(c),
b = a t a n 2 ( − r 31 , r 11 / c o s ( c ) ) (11) b=atan2(-r_{31},r_{11}/cos(c)) \tag {11} b=atan2(r31,r11/cos(c))(11)
  否则,
b = a t a n 2 ( − r 31 , r 21 / s i n ( c ) ) (12) b=atan2(-r_{31},r_{21}/sin(c)) \tag {12} b=atan2(r31,r21/sin(c))(12)

%{
Function: rpy2rotm
Description: rpy转旋转矩阵R, R= rotz(c) * roty(b) * rotx(a)
Input: rpy角度(单位rad)
Output: 旋转矩阵R
Author: Marc Pony(marc_pony@163.com)
%}
function R = rpy2rotm(rpy)

a = rpy(1);
b = rpy(2);
c = rpy(3);

sinA = sin(a);
cosA = cos(a);
sinB = sin(b);
cosB = cos(b);
sinC = sin(c);
cosC = cos(c);

R = [cosB*cosC,  cosC*sinA*sinB - cosA*sinC,  sinA*sinC + cosA*cosC*sinB
    cosB*sinC, cosA*cosC + sinA*sinB*sinC, cosA*sinB*sinC - cosC*sinA
    -sinB, cosB*sinA,  cosA*cosB];

end
%{
Function: rotm2rpy
Description: 旋转矩阵R转rpy, R= rotz(c) * roty(b) * rotx(a)
Input: 旋转矩阵R
Output: rpy角度(单位rad)
Author: Marc Pony(marc_pony@163.com)
%}
function rpy = rotm2rpy( R )

if abs(R(3 ,1) - 1.0) < 1.0e-15   % singularity
    a = 0.0;
    b = -pi / 2.0;
    c = atan2(-R(1, 2), -R(1, 3));
elseif abs(R(3, 1) + 1.0) < 1.0e-15   % singularity
    a = 0.0;
    b = pi / 2.0;
    c = -atan2(R(1, 2), R(1, 3));
else
    a = atan2(R(3, 2), R(3, 3));
    c = atan2(R(2, 1), R(1, 1));
    %     a = atan2(-R(3, 2), -R(3, 3));  %a另一个解
    %     c = atan2(-R(2, 1), -R(1, 1));  %c另一个解
    cosC = cos(c);
    sinC = sin(c);
    
    if abs(cosC) > abs(sinC)
        b = atan2(-R(3, 1), R(1, 1) / cosC);
    else
        b = atan2(-R(3, 1), R(2, 1) / sinC);
    end
end

rpy = [a, b, c];

end


clc
clear

n = 0;
while 1
    
    rpy = -pi + 2*pi * rand(1, 3);
    %rpy(2) = -pi/2; %奇异:+-pi
    R = rotz(rpy(3)) * roty(rpy(2)) * rotx(rpy(1));
    
    rpy1 = rotm2rpy(R);
    R1 = rpy2rotm(rpy1);
    
    rpy2 = rotm2rpy(R1);
    R2 = rpy2rotm(rpy2);
    
    if sum(sum(abs(R - R1))) > 1.0e-8 || sum(sum(abs(R - R2))) > 1.0e-8 || sum(sum(abs(R1 - R2))) > 1.0e-8
        break;
    end
    
    %    同样旋转矩阵R可能对应不同的rpy角度
    %     if sum(abs(rpy - rpy1)) > 1.0e-8 || sum(abs(rpy - rpy2)) > 1.0e-8 || sum(abs(rpy1 - rpy2)) > 1.0e-8
    %         break;
    %     end
    
    n = n + 1
end

三、 小结

  (1)旋转矩阵中,当 r 31 = 1 或 − 1 r_{31}=1或-1 r31=11时,姿态奇异,只能计算 a + c 或 a − c a+c或a-c a+cac的值,此时通常的做法是令 a = 0 a=0 a=0
  (2)当 r 31 ≠ ± 1 r_{31}\ne\pm1 r31=±1时,rpy角有两组解。类似地,当旋转矩阵用轴角表示时,有两组解:绕轴 k k k旋转 θ \theta θ角度与绕轴 − k -k k旋转 − θ -\theta θ角度;当旋转矩阵用单位四元数表示时,有两组解:单位四元数 q q q与单位四元数的相反数 − q -q q。因而,在姿态的单位四元数SLERP插补中,有必要选取较短的“姿态路径”,使得机器人姿态动作看起来柔顺一些。
  (3)当 r 31 = 1 或 − 1 r_{31}=1或-1 r31=11时,一个旋转矩阵对应无穷多组rpy角。当 r 31 ≠ ± 1 r_{31}\ne\pm1 r31=±1时,一个旋转矩阵对应两组rpy角。由于通常姿态插补为轴角插补或单位四元数SLERP插补,rpy角只作界面显示,在实际编程中,当姿态不奇异时,只需考虑一组解即可。机器人末端姿态的旋转矩阵R通过正解得到,旋转矩阵转换成rpy显示在界面上,上位机下发rpy角后,将rpy角转换成旋转矩阵R,再用轴角插补或单位四元数SLERP插补。也就是说,只要保证程序中的rpy角与旋转矩阵之间的变换关系是一一对应就可以,不需要也没必要去讨论选取哪一组rpy角。
  姿态插补中,RPY与旋转矩阵R之间转换的一个坑:
  轴角插补或单位四元数插补后,将轴角或单位四元数转换为旋转矩阵R,再把位置插补的位置XYZ合起来,写成一个4*4的齐次变换矩阵,作为机器人逆解的位姿输入。
  有时候,为了节省内存空间,将旋转矩阵R转换为RPY角,再把位置插补的位置XYZ合起来,写成一个6维向量,作为机器人逆解的位姿输入(注意:做逆解时需要将RPY转换为旋转矩阵R)。
  如果轴角或单位四元数转换为旋转矩阵R时,均为单精度浮点运算,导致旋转矩阵R丢失了些精度。由于RPY的姿态表示方法存在姿态奇异(万向节锁),当旋转矩阵R转换为RPY角时,在奇异点附近计算的 RPY角误差比较大,从而导致RPY转换而成的旋转矩阵R跳变。
  如何避坑:
  (1)轴角/单位四元数 -> 旋转矩阵 -> RPY -> 旋转矩阵,均采用双精度浮点数运算。
  (2)旋转矩阵转换为RPY时,判断奇异点的容差值尽可能小。

  • 25
    点赞
  • 103
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值