ThreeJS DOC CN

欧拉角万向节死锁

什么是欧拉角(Eular Angles)?

欧拉角是瑞士数学家莱昂哈德·欧拉(Leonhard Euler)用来描述刚体在三维空间中取向的方法。简单来说,就是任何一个物体的取向,都可以用3个有次序的旋转角度来表示。

欧拉在三维空间中定义了一个静止不动的参考系,即惯性系。还定义了一个运动的坐标系,即物体坐标系。惯性系与物体坐标系的区别在于,当物体取向发生改变之后,物体坐标系也随之改变,而惯性系却不变。

例如,我们认为北极星的位置对于地球上的任意观察点都是不变的,因此可以看作一个静止的参考系。而基于公路上一辆行驶的汽车的坐标系,因为汽车的转弯而不断改变,是一个物体坐标系。

欧拉角的三个旋转是绕物体坐标系的三个轴复合形成。为何不使用惯性系?因为物体坐标系在数学处理上是简单的。为了描述一架飞机的取向,定义航偏角为 yaw, 俯仰为 pitch, 横滚为 roll。假如分别使用矩阵 I1, I2, I3 来表示这三个角度,那么飞机绕自身先转 yaw 角,再绕 pitch 角,最后绕 roll 角的结果可用 I3I2I1 来表示。

万向节死锁(gimbal lock

gimbal3

通常来说,一个物体的取向用欧拉角来表示是简单有效的。但是在某种特殊的情况下,欧拉角将失效,形成所谓的“万向节死锁”。

一个简单直观的例子是炮塔模型。假设地面上的一个炮塔有两个旋转轴:Y垂直于地面,使炮塔可以平行地面360度旋转(正北设为0度);X平行于地面,使炮口可以绕着它上下90度旋转(平行地面使设为0度)。现在,天空中的任意一点就可以使用两个坐标的度数来表示了!

这时,一架敌机从正东面飞来,我们转动炮塔对准它,目前的坐标是(10,90)。因为飞机飞行方向不变,所以Y固定为90,而X由于飞机距离的接近而增大。当飞机恰好飞到炮塔顶端时,即X的角度也达到90度时,飞机忽然向南飞行!我们必须立即改变炮塔朝向,否则即将都丢失目标。但是我们发现,无论是转动X轴还是Y轴,我们都无法让炮塔转向南方了,即炮塔在此时丢失了一个自由度!

为什么不把Y转动到180度的位置继续跟踪呢?注意此时炮塔的状态: 炮口已经对准炮台的正上方, 平行于Y轴,无论Y轴怎样转动,炮口都改变不了朝向的, 即炮台的物体坐标系不会变化了。能转动的只有X轴,但是这样一来,炮口又回到东面了。

欧拉角的万向节死锁就是这样:我们依次绕物体坐标系的X轴、Y轴、Z轴旋转,当Y轴旋转了90度之后,Z就会指向原来的X轴。这样一来,我们事实上只绕了X轴和Y轴两个轴旋转,第三根轴的自由度就丢失了!(值得指出的是,我们在描述的时候使用的是世界坐标系的x, y, z轴,但是旋转的时候却是使用绕物体的)

万向锁的一个有趣实验是当先把飞机 Yaw 45 度,再 Pitch 90 度,与先 Pitch 90 度,再 Roll 45度 的结果完全相同。 这个现象也叫欧拉角的别名现象(同一个惯性系下同一个值有不同的表示方法),这也是很糟糕的。