欧拉角 Euler Angle

1. 定义

  欧拉角通过基于三个基础坐标轴的旋转角度生成一个矩阵,用于对坐标或坐标系的旋转。首先我们需要规定一个旋转顺序,这里按照Real-Time Rendering (4th Edition)中的规定,按照如下顺序进行旋转:

$\textbf{E}(h,p,r)=\textbf{R}_z(r)\textbf{R}_x(p)\textbf{R}_y(h)$

  一般定义:
    Yaw(偏航):y
    Pitch(俯仰):x
    Roll(翻滚): z

  这里即可以看出其中一个问题,即旋转顺序对结果会产生影响,因此在不同的系统中若要进行移植需要确定坐标系朝向,以及相应的欧拉角顺序。此外该方法可能出现万向锁(Gimbal Lock),说明该问题前,我们先把$\textbf{E}(h,p,r)$展开:

$\textbf{E}(h,p,r)=\left[\begin{array}{cccc} c_z c_y - s_z s_x s_y & -s_z c_x & c_z s_y + s_z s_x c_y \\ s_z c_y + c_z s_x s_y & c_z c_x & s_z s_y - c_z s_x c_y \\ -c_x s_y & s_x & c_x c_y \end{array}\right] $
这里当$c_x=0, s_x=\pm 1$时,上式可以转换为:
$\textbf{E}(h,p,r)=\left[\begin{array}{cccc} c_z c_y \mp s_z s_y & 0 & c_z s_y \pm s_z s_x c_y \\ s_z c_y \pm c_z s_x s_y & 0 & s_z s_y \mp c_z s_x c_y \\ 0 & \pm 1 & 0 \end{array}\right] = \left[\begin{array}{cccc} cos(r\pm h) & 0 & sin(r\pm h) \\ sin(r\pm h) & 0 & -cos(r\pm h) \\ 0 & \pm1 & 0 \end{array}\right] $

可以看出这种情况下$r$和$h$是绕着同一个轴同向或反向旋转。

2. 求解参数

  很容易发现,当我们有欧拉角时,计算相应的旋转矩阵会很容易。但当我们有旋转矩阵,希望得到欧拉角就很难直观地想到结果,假如我们得到如下的旋转矩阵:

$\textbf{E}=\left[\begin{array}{cccc} e_{00} & e_{01} & e_{02} \\ e_{10} & e_{11} & e_{11} \\ e_{20} & e_{21} & e_{22} \end{array}\right] $

  根据上述推导,很容易有:

$\frac{e_{01}}{e_{11}} = \frac{-s_z}{c_z}=-tan_z$

$\frac{e_{20}}{e_{22}} = \frac{-s_y}{c_y}=-tan_y$

$e_{21}=sin_x$

  于是可以得到:

$h = atan2(-e_{20}, e_{22}) \\ p = arcsin(e_{21}) \\ r = atan2(-e_{01}, e_{11})$

  于是由于死锁的存在, 在死锁中或死锁附近时,上述结果可能有很多组解,就可能准确插值变得困难,比如对于起点A和重点B,每次插值选择一个近似解,在死锁附近时,这个解的取值范围可能很广(如死锁时可以有无数组r-h解),那么我们插出来的结果就可能产生抖动。

参考文献

Real-Time Rendering (4th Edition)

本文标题:欧拉角 Euler Angle

文章作者:000ddd00dd0d

原始链接:http://000ddd00dd0d.github.io/2019/04/27/Euler-Transform/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。