欧拉角
3D空间中的任意一个旋转都可以拆分成为沿着物体自身三个正交坐标轴的旋转。欧拉角规定了这三次旋转的角度,我们分别称他们为俯仰角(Pitch)、偏航角(Yaw)、滚转角(Roll)。也就是说3D空间中任意的旋转都可以由三个旋转矩阵相乘的方式得到:
\[E(yaw, pitch,roll)=R_z(yaw)R_y(roll)R_x(pitch)\tag{1} \]\(R_x\)、 \(R_y\)、\(R_z\)是沿着\(x\)、\(y\)、\(z\)轴旋转的旋转矩阵。
\[R_x(\alpha) = \left[ \begin{matrix} 1&0&0\\ 0&\cos\alpha&-\sin\alpha\\ 0&\sin\alpha&\cos\alpha \end{matrix} \right] \\ R_y(\beta)= \left[ \begin{matrix} \cos\beta&0&\sin\beta\\ 0&1&0\\ -\sin\beta&0&\cos\beta \end{matrix} \right]\\ R_z(\gamma)= \left[ \begin{matrix} \cos\gamma&-\sin\gamma&0\\ \sin\gamma&\cos\gamma&0\\ 0&0&1 \end{matrix} \right] \]因为矩阵的乘法一般不满足交换律,所以三次旋转的顺序非常重要,公式1中是按照\(x-y-z\)轴的顺序进行旋转的。
本文使用的是右手坐标系,各个坐标轴的方向如上图所示
Gimbal Lock
百度百科中对于Gimbal Lock的定义如下:
一旦选择\(\pm90^\circ\)作为pitch角,就会导致第一次旋转和第三次旋转等价,整个旋转表示系统被限制在只能绕竖直轴旋转,丢失了一个表示维度。
百科中坐标轴的选取与本文中的并不一样所以会有所出入。
接下来的讨论都固定使用一套旋转顺序(x-y-z):
\[E(yaw, pitch,roll)=R_z(yaw)R_y(roll)R_x(pitch) \]其中,每一次旋转变换就代表着有一个Gimbal(通常译为万向节或者平衡环架)。三个旋转共有固定的三个Gimbal。我们可以改变每次旋转的角度,但旋转的顺序是不能改变的。
大部分情况下,这一套顺序能够对三个不同的轴分别进行三次旋转。然而,在某一些特殊情况下,其中的某两个旋转变换可能变换的是同一个轴(这里指的不是物体自身的轴,而是外部或者说是世界坐标系的轴),这样就导致丧失了一个轴的自由度,从而导致Gimbal Lock的产生。
举例说明
参照维基百科给出下面的例子:
3D空间中的旋转可以通过矩阵表示,下面给出其中的一种表示:
\[R= \left[ \begin{matrix} \cos\gamma&-\sin\gamma&0\\ \sin\gamma&\cos\gamma&0\\ 0&0&1 \end{matrix} \right] \left[ \begin{matrix} \cos\beta&0&\sin\beta\\ 0&1&0\\ -\sin\beta&0&\cos\beta \end{matrix} \right] \left[ \begin{matrix} 1&0&0\\ 0&\cos\alpha&-\sin\alpha\\ 0&\sin\alpha&\cos\alpha \end{matrix} \right] \]一个值得研究的例子是当\(\beta=\frac{\pi}{2}\)时,已知\(\cos\frac{\pi}{2}=0, \sin\frac{\pi}{2}=1\),则上述表达式等于:
\[R= \left[ \begin{matrix} \cos\gamma&-\sin\gamma&0\\ \sin\gamma&\cos\gamma&0\\ 0&0&1 \end{matrix} \right] \left[ \begin{matrix} 0&0&1\\ 0&1&0\\ -1&0&0 \end{matrix} \right] \left[ \begin{matrix} 1&0&0\\ 0&\cos\alpha&-\sin\alpha\\ 0&\sin\alpha&\cos\alpha \end{matrix} \right] \]执行矩阵乘法得到:
\[\begin{eqnarray} R&=& \left[ \begin{matrix} 0&\cos\gamma\sin\alpha-\sin\gamma\cos\alpha&\cos\gamma\cos\alpha+\sin\gamma\sin\alpha\\ 0&\sin\gamma\sin\alpha+\cos\gamma\cos\alpha&\sin\gamma\cos\alpha-\cos\gamma\sin\alpha\\ -1&0&0 \end{matrix} \right]\\ &=&\left[ \begin{matrix} 0&\sin(\alpha-\gamma)&\cos(\alpha-\gamma)\\ 0&\cos(\alpha-\gamma)&-\sin(\alpha-\gamma)\\ -1&0&0 \end{matrix} \right]\\ &=& R_y(\frac{\pi}{2})R_x(\alpha-\gamma) \end{eqnarray} \]通过上面的公式可以看到,上面的矩阵实际上只旋转了x-y两轴,它并没有对初始的z轴进行变换。z轴的自由度消失了,Gimbal Lock产生。
除了使用公式进行直接说明外,我们借助Krasjet的Bonus章节中的图来加深理解:
首先,我们沿着\(x\)轴旋转任意的度数:
然后沿着\(y\)轴旋转\(\pi/2\)弧度:
可以看到在经过\(y\)轴的旋转后,物体坐标系下的\(z\)轴被变换到了原来\(x\)的方向(也就是世界坐标系的\(x\)轴的方向),而原来物体坐标系下\(x\)轴变换到了世界坐标系下的\(-z\)的方向。
\(y\)轴旋转完成后,只剩下一个\(z\)轴的旋转矩阵。然而,当前物体的\(z\)轴与原来的\(x\)轴重合,也就是说此时的\(z\)轴旋转与之前进行的\(x\)轴旋转其实操纵的是同一个轴(这里所指的是世界坐标系中的轴)。三次旋转变换只作用与两个外部轴的旋转,其中一个的自由度丢失了,这也就导致了Gimbal Lock的现象。
这里假设了在初始条件下物体的三个坐标轴与世界坐标轴是重合的。
更详细的建议参考Krasjet的Bonus章节和wiki百科。