万向节死锁 gimbal lock

,如下图一,把灰色箭头想象成是一架飞机,红,绿蓝三个圈看作是三个外围控制器,外圈带动所有里圈运动,里圈的运动不影响外圈。

1,首先,绕Y轴旋转(旋转绿圈),来确定前进的方向。这时红圈与蓝圈都跟着旋转。

2,然后,绕x轴旋转(旋转红圈),让飞机仰视或俯视。这时蓝圈跟着一起旋转,绿圈不动。

3,最后,绕z轴旋转(旋转蓝圈),让飞机左右倾斜。这时只有蓝圈在转,红绿圈不动。

经过这三个步骤,我们可以把飞机调整到任意想要的角度。这也是FPS相机中常用的 yaw, pitch, row三个操作。

在步骤2中,若旋转红圈过程中,恰巧旋转到了图二所示状态,然后进行步骤3时会发现,旋转蓝圈与绿圈效果一样。

也就是这种状态下,旋转Y或Z轴效果一样了,都只能使飞机左右倾斜,而不能再俯视或仰视(它只能头朝天),这下坏了,飞机操作失灵了,只能向上直冲。这就所谓的万向节死锁,gimbal lock.

可见,欧拉角旋转使用的是物体的局部坐标系,旋转过程是对局部坐标的三个轴X,Y,Z分别进行的旋转。

【所谓的死锁,仅是在一个操作单元,即XYZ组成的任意一个次序中出现了无法控制的现象,如上面飞机失灵的情况,我们可以继续操作X轴(红圈)来调整飞机的仰视和俯视,这时飞机又可以回到水平飞行的正常轨道上来了】

【但是,对于使用欧拉角旋转的程序,没有人会去专门写逻辑来判断是否发生了万向节死锁,D3D底层API更不会去管,因此我们的程序就会出BUG]

yaw 是左右看,pitch是俯视或仰视,roll就是左右倾斜。

如果我们写了一个FPS的飞机控制程序,当发生上面的死锁时,调用pitch就与调用roll一样了,当发现飞机朝上飞时,于是调用pitch想调整机头朝下,结果却发现飞机只是左右倾斜而机头仍然朝上直飞!出BUG了。

 参考:http://www.cnitblog.com/luckydmz/archive/2010/09/07/68674.html

按上述方法在U3D编辑器中可以试验出万向节死锁,如下图,物体先绕X轴旋转90度后,再去调节Y轴和Z轴的旋转角时,发现物体只能绕Z轴旋转了,调节Y轴的旋转值时物体还是在绕Z轴转,死锁了。

欧拉旋转的计算可以有许多次序,每种次序得到的结果都不一样,U3D为YXZ次序,如果不按此次序来旋转,你就会看不懂它的表现

死锁的的情况是与欧拉旋转的计算次序有关的。如YXZ次序时,只要绕X轴的旋转为90度,不管绕Y,Z旋转多少,都是死锁;XYZ次序时,只要绕Y的旋转为90度,不管绕X,Z的旋转是多少,都是死锁;其它类推,死锁取决于中间次序的那个轴。

 如上面U3D中的试验当我们先给rotation的Y设置90度,再调节X和Z的旋转值时,只要X不为90度就无死锁,这说明U3D在计算欧拉角时使用的计算顺序正是上面的YXZ顺序。

PS,欧拉角并不是个特殊算法的产物,它和矩阵旋转本质相同,就是说利用矩阵来实现旋转也会有死锁,参考下面的这篇文章:

旋转变换(二)欧拉角

posted @ 2016-10-07 16:54  时空观察者9号  阅读(5099)  评论(0编辑  收藏  举报