版权声明(转载)

本文总结归纳自知乎的天下行走 和CSDN的AndrewFan

FCND-Gimbal-Demo 用于讨论万向节死锁(Gimbal Lock)的Unity3D开源项目

前言

四元数

四元数相对于其他形式的优点,大略为:

  1. 解决万向节死锁
  2. 仅需4个浮点数,相比矩阵更轻量
  3. 无论求逆、串联等操作,相比矩阵更高效

本文简要分析“万向节死锁”形成原因。

欧拉角

欧拉角用于表示刚体当前的姿态。
思想:将刚体绕某一轴的一次旋转,分解为依次分别绕X、Y、Z轴的三次旋转。这三个轴分别旋转的转动角度,就是一组三个欧拉角。
图片中即为上述的三次旋转(而其实可以绕某一轴,一次旋转即可达到最终位置)

三次旋转图解

具体旋转过程举例,如图:

旋转过程举例

图中有两组坐标系,我们定义为:

  • x、y、z :世界坐标系(固定不动)
  • X、Y、Z :刚体坐标系(与刚体同步运动)

具体旋转步骤为:

  1. 绕世界坐标系的 z 轴,旋转 α 角。
  2. 绕刚体坐标系的 X 轴,旋转 β 角。
  3. 绕刚体坐标系的 Z 轴,旋转 γ 角。

下面有一个直观的动图展示。图片来源gfycat

动图展示

  • 动图旋转步骤为 zYX

  • 按照顺序标记为 zYX

  • 加上角度即为一个完整欧拉角(ψ,θ,Φ)

万向节死锁(Gimbal Lock)

  • 万向节死锁发生在欧拉角形式下,是由欧拉旋转定义本身造成的。
  • Gimbal Lock 产生的原因不是欧拉角也不是旋转顺序,而是我們的思维方式和程序的执行逻辑没有对应,也就是说是我们的观念导致这个情况的发生。
  • 欧拉旋转的顺规和轴向定义,自然造就了“万向节死锁”问题。本节主要来探索它自然形成的原因。

陀螺仪

首先,我们来了解Gimbal 究竟是个什么玩意儿。下面来自维基百科中关于Gimbal的一段引述:

平衡环架(英语:Gimbal),是一具有枢纽的装置,作用是使得一物体能以单一轴旋转。由彼此垂直的枢纽轴所组成的一组三只平衡环架,则可使架在最内的环架的物体维持旋转轴不变,而应用在船上的陀螺仪、罗盘、饮料杯架等用途上,而不受船体因波浪上下震动、船身转向的影响。
————百度百科

如图:

动图封面

静态图:

img

上图就是一Gimbal装置,是一陀螺仪。中间有一根竖轴,穿过一个金属圆盘。金属圆盘称为转子,竖轴称为旋转轴。转子用金属制成,应该是了增加质量,从而增大惯性。竖轴外侧是三层嵌套的圆环,它们互相交叉,带来了三个方向自由度的旋转。

称作陀螺仪即可。

Pitch、Yaw、Roll

陀螺仪分别绕X、Y、Z三个轴旋转时的旋转角。这里直接等同于欧拉角即可。如图:

img

  • 绕机身右方X 轴旋转,称为pitch,俯仰
  • 绕机头上方Z 轴旋转,称为Yaw,偏航
  • 绕机头前方Y 轴旋转,称为Roll,横滚

可以看出,与欧拉角形式基本相同。

万向节死锁的产生

陀螺仪是用来测量平衡和转速的工具,在载体高速转动的时候,陀螺仪始终要通过自我调节,使得转子保持原有的平衡。

为助于理解,下面是一个简单的陀螺仪示意图(省略了金属圆盘)。

img

把三个Gimbal环用不同的颜色做了标记,底部三个轴向,RGB分别对应XYZ。
假设现在这个陀螺仪被放在一艘船上,船头的方向沿着+Z轴,也就是右前方。

横滚

现在假设,船体发生了摇晃,是沿着前方进行旋转的摇晃,也就是横滚。由于转子和旋转轴具有较大的惯性,只要没有直接施加扭矩,就会保持原有的姿态。由于上图中绿色的活动的连接头处是可以灵活转动的,此时将发生相对旋转,从而出现以下的情形:

动图封面

俯仰

再次假设,船体发生了pitch摇晃,也就是俯仰。同样,由于存在相应方向的可以相对旋转的连接头(红色连接头),转子和旋转轴将仍然保持平衡,如下图:

动图封面

偏航

最后假设,船体发生了yaw摇晃,也就是偏航,此时船体在发生水平旋转。相对旋转发生在蓝色连接头。如下图:

动图封面

最终,在船体发生Pitch、Yaw、Roll的情况下,陀螺仪都可以通过自身的调节,而让转子和旋转轴保持平衡。

死锁的产生

以上陀螺仪一切正常,在船体发生任意方向摇晃都可以通过自身调节来应对。

假如,船体发生了剧烈的变化,此时船首仰起(抬头)了90度,此时的陀螺仪调节状态如下图:

img

此时,船体再次发生转动,沿着当前世界坐标的+Z轴(蓝色轴,应该正指向船底)进行转动,那么来看看发生了什么情况。

动图封面

现在,转子不平衡了,陀螺仪的三板斧不起作用了。它失去了自身的调节能力。那么这是为什么呢?
之前陀螺仪之所以能通过自身调节,保持平衡,是因为存在可以相对旋转的连接头。在这种情况下,已经不存在可以相对旋转的连接头了。
那么连接头呢?去了哪里?显然,它还是在那里,只不过是,连接头可以旋转的相对方向不是现在需要的按着+Z轴方向。从上图中,我们清楚地看到:

  • 红色连接头:可给予一个相对俯仰的自由度。
  • 绿色连接头:可给予一个相对偏航的自由度。
  • 蓝色连接头:可给予一个相对偏航的自由度。

没错,三个连接头,提供的自由度只对应了俯仰和偏航两个自由度,桶滚自由度丢失了。这就是陀螺仪上的“万向节死锁”问题。

总结

总结来说,欧拉角的“万向节死锁”问题,是由于欧拉旋转定义本身造成的。这种围绕选旋转前固定轴的先Z、再X、再Y的旋转操作,与其最终所预期的三个轴向可以旋转的结果并非一定是一对一的映射。某些情况下是多对一的映射,造成一些旋转自由度的缺失,也就是“死锁”。

在编程中很难规避死锁,所以现在更多使用四元数形式进行姿态表示与旋转。