欧拉角与旋转矩阵之间的相互转化(推导和Python代码)

11 篇文章 0 订阅

欧拉角与旋转矩阵之间的相互转化(推导和Python代码)

表示三维空间中的旋转可以有多种表示的方法(旋转矩阵,欧拉角,四元素,轴角,李群李代数)。欧拉角表示法,分别是指定了三个角度yaw,roll,pitch,分别是绕z轴,x轴,y轴的转动的角度。

1. 欧拉角 -> 旋转矩阵

欧拉角来合成旋转矩阵的过程需要指定顺规,我们常用的顺规是 Z Y X ZYX ZYX,即分别将旋转矩阵 R z R_z Rz R y R_y Ry R x R_x Rx相乘。

参考机器人学的知识,根据下图所示,

Image

z , y , x z,y,x z,y,x轴旋转角度分别为 α , β , γ \alpha,\beta,\gamma α,β,γ,我们可以获得绕 z , y , x z,y,x z,y,x轴的旋转矩阵分别为:
R z ( α ) = [ 1 0 0 0 cos ⁡ α − sin ⁡ α 0 sin ⁡ α cos ⁡ α ] R y ( β ) = [ cos ⁡ β 0 sin ⁡ β 0 1 0 − sin ⁡ β 0 cos ⁡ β ] R x ( γ ) = [ cos ⁡ γ − sin ⁡ γ 0 sin ⁡ γ cos ⁡ γ 0 0 0 1 ] R_z(\alpha) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\alpha & -\sin\alpha \\ 0 & \sin\alpha & \cos\alpha \end{bmatrix} \\ R_y(\beta) = \begin{bmatrix} \cos\beta & 0 & \sin\beta \\ 0 & 1 & 0 \\ -\sin\beta & 0 & \cos\beta \end{bmatrix} \\ R_x(\gamma) = \begin{bmatrix} \cos\gamma & -\sin\gamma & 0 \\ \sin\gamma & \cos\gamma & 0 \\ 0 & 0 & 1 \end{bmatrix} Rz(α)= 1000cosαsinα0sinαcosα Ry(β)= cosβ0sinβ010sinβ0cosβ Rx(γ)= cosγsinγ0sinγcosγ0001
然后按照 Z Y X ZYX ZYX顺规合成旋转矩阵
R a b ( α , β , γ ) = R z ( α ) R y ( β ) R x ( γ ) = [ c α c β − s α c γ + c α s β s γ s α s γ + c α s β c γ s α c β c α c γ + s α s β s γ − c α s γ + s α s β c γ − s β c β s γ c β c γ ] = [ r 11 r 12 r 13 r 21 r 22 r 23 r 31 r 32 r 33 ] \begin{align*} R_{ab}(\alpha, \beta, \gamma) & = R_z(\alpha)R_y(\beta)R_x(\gamma) \\ & = \begin{bmatrix} c_\alpha c_\beta & -s_\alpha c_\gamma + c_\alpha s_\beta s_\gamma & s_\alpha s_\gamma + c_\alpha s_\beta c_\gamma \\ s_\alpha c_\beta & c_\alpha c_\gamma + s_\alpha s_\beta s_\gamma & -c_\alpha s_\gamma + s_\alpha s_\beta c_\gamma \\ -s_\beta & c_\beta s_\gamma & c_\beta c_\gamma \end{bmatrix} \\ & = \begin{bmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \end{bmatrix} \end{align*} Rab(α,β,γ)=Rz(α)Ry(β)Rx(γ)= cαcβsαcβsβsαcγ+cαsβsγcαcγ+sαsβsγcβsγsαsγ+cαsβcγcαsγ+sαsβcγcβcγ = r11r21r31r12r22r32r13r23r33
其中, c α = cos ⁡ α , s β = sin ⁡ β c_\alpha=\cos\alpha, s_\beta=\sin\beta cα=cosα,sβ=sinβ,别的符号以此类推。

如果已知欧拉角求旋转矩阵,这个非常好求,我们直接求出 R z ( α ) , R y ( β ) , R x ( γ ) R_z(\alpha),R_y(\beta), R_x(\gamma) Rz(α),Ry(β),Rx(γ)然后矩阵相乘即可。

Python

import math
import numpy as np
def rpy2R(rpy): # [r,p,y] 单位rad
    rot_x = np.array([[1, 0, 0],
                    [0, math.cos(rpy[0]), -math.sin(rpy[0])],
                    [0, math.sin(rpy[0]), math.cos(rpy[0])]])
    rot_y = np.array([[math.cos(rpy[1]), 0, math.sin(rpy[1])],
                    [0, 1, 0],
                    [-math.sin(rpy[1]), 0, math.cos(rpy[1])]])
    rot_z = np.array([[math.cos(rpy[2]), -math.sin(rpy[2]), 0],
                    [math.sin(rpy[2]), math.cos(rpy[2]), 0],
                    [0, 0, 1]])
    R = np.dot(rot_z, np.dot(rot_y, rot_x))
    return R

alpha = 0.25 * np.pi
beta = 0.4 * np.pi
gamma = 0.3 * np.pi
rpy = [alpha, beta, gamma]
print('rpy:', str(rpy))
print('R:', str(rpy2R(rpy)))

结果如下:

rpy: [0.7853981633974483, 1.2566370614359172, 0.9424777960769379]
R: [[ 0.18163563 -0.1767767   0.96734611]
 [ 0.25        0.95968966  0.12843579]
 [-0.95105652  0.21850801  0.21850801]]

2. 旋转矩阵 -> 欧拉角

如果已知旋转矩阵求欧拉角,就是求解如下方程的过程
[ c α c β − s α c γ + c α s β s γ s α s γ + c α s β c γ s α c β c α c γ + s α s β s γ − c α s γ + s α s β c γ − s β c β s γ c β c γ ] = [ r 11 r 12 r 13 r 21 r 22 r 23 r 31 r 32 r 33 ] \begin{bmatrix} c_\alpha c_\beta & -s_\alpha c_\gamma + c_\alpha s_\beta s_\gamma & s_\alpha s_\gamma + c_\alpha s_\beta c_\gamma \\ s_\alpha c_\beta & c_\alpha c_\gamma + s_\alpha s_\beta s_\gamma & -c_\alpha s_\gamma + s_\alpha s_\beta c_\gamma \\ -s_\beta & c_\beta s_\gamma & c_\beta c_\gamma \end{bmatrix}= \begin{bmatrix} r_{11} & r_{12} & r_{13} \\ r_{21} & r_{22} & r_{23} \\ r_{31} & r_{32} & r_{33} \end{bmatrix} cαcβsαcβsβsαcγ+cαsβsγcαcγ+sαsβsγcβsγsαsγ+cαsβcγcαsγ+sαsβcγcβcγ = r11r21r31r12r22r32r13r23r33
整理一下可以得到

{ − sin ⁡ β = r 31 cos ⁡ 2 β sin ⁡ 2 γ + cos ⁡ 2 β cos ⁡ 2 γ = r 32 2 + r 33 2 \left\{\begin{align*} & -\sin\beta = r_{31} \\ & \cos^2\beta\sin^2\gamma + \cos^2\beta\cos^2\gamma = r_{32}^2 + r_{33}^2 \\ \end{align*}\right. {sinβ=r31cos2βsin2γ+cos2βcos2γ=r322+r332

所以可以得到

{ α = arctan ⁡ ( r 21 / c β , r 11 / c β ) β = arctan ⁡ ( − r 31 , r 32 2 + r 33 2 ) γ = arctan ⁡ ( r 32 / c β , r 33 / c β ) \left\{\begin{align*} & \alpha = \arctan(r_{21}/c_\beta, r_{11}/c_\beta) \\ & \beta = \arctan(-r_{31}, \sqrt{r_{32}^2 + r_{33}^2}) \\ & \gamma = \arctan(r_{32}/c_\beta, r_{33}/c_\beta) \end{align*}\right. α=arctan(r21/cβ,r11/cβ)β=arctan(r31,r322+r332 )γ=arctan(r32/cβ,r33/cβ)

β = π 2 \beta=\frac{\pi}{2} β=2π的时候, cos ⁡ β = 0 \cos\beta=0 cosβ=0,这时为奇异点(singular)不能解出欧拉角,这也是欧拉角表示法的一个弊端。

Python

import math
import numpy as np
# Checks if a matrix is a valid rotation matrix.
def isRotationMatrix(R) :
    Rt = np.transpose(R)
    shouldBeIdentity = np.dot(Rt, R)
    I = np.identity(3, dtype = R.dtype)
    n = np.linalg.norm(I - shouldBeIdentity)
    return n < 1e-6


# Calculates rotation matrix to euler angles
# The result is the same as MATLAB except the order
# of the euler angles ( x and z are swapped ).
def rotationMatrixToEulerAngles(R) :

    assert(isRotationMatrix(R))
    
    sy = math.sqrt(R[0,0] * R[0,0] +  R[1,0] * R[1,0])
    
    singular = sy < 1e-6

    if  not singular :
        x = math.atan2(R[2,1] , R[2,2])
        y = math.atan2(-R[2,0], sy)
        z = math.atan2(R[1,0], R[0,0])
    else :
        x = math.atan2(-R[1,2], R[1,1])
        y = math.atan2(-R[2,0], sy)
        z = 0

    return np.array([x, y, z])

R = np.array([[ 0.18163563, -0.1767767,   0.96734611],
 [ 0.25,        0.95968966,  0.12843579],
 [-0.95105652,  0.21850801,  0.21850801]])

print('R:', str(R))
print('rpy:', str(rotationMatrixToEulerAngles(R)))

结果如下

R: [[ 0.18163563 -0.1767767   0.96734611]
 [ 0.25        0.95968966  0.12843579]
 [-0.95105652  0.21850801  0.21850801]]
rpy: [0.78539816 1.25663706 0.9424778 ]

可以看到结果和我们之前转换的结果保持一致。

Reference

[1]旋转矩阵与欧拉角的相互转换及代码

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值