万向节死锁的根本原因是因为轴的连带旋转导致的,至于为什么,让我们一步步的来理解
为什么用欧拉角来表示旋转首先,我们先从一开始去思考,假设这个世界还没有欧拉角,现在,让你想办法用数字去表示一个摄像机的旋转,要求能表示它在空间内的任意角度,你会怎么去表示它?
事实上,我们只需要两个轴,x y轴,就可以做到让我们的摄像机旋转到空间内的任意一个角度,也就是上下左右。想象下,我们的头不正是这么旋转的吗?我们可以左右转头,可以抬头低头,如果脖子允许,我们完全可以不动身体,就看到世界中的任何方向。但在实际过程中,我们发现一个问题,只用两个轴来表示的话,不具备唯一性,也就是任意一个角度,都会存在两个不同的x y能够代表它。比如,我们把我们的头抬到最高,然后再向后偏一点,也就是抬头100度,此时,我们是应该用(0,100)来表示,还是用(180,80)来表示呢?看来,我们还需要再引入一个轴z,用来表示我们脸的旋转(当然,我们脸是没法转的,这里只假设下),即,如果z是0度,就是(0,100,0),如果z是180度,那就是(180,80,180),如此一来,好像就没什么问题了,我们可以用xyz来表示空间内的任意角度,且是唯一的,但事实上真的如此吗?
欧拉角的旋转规则欧拉角的旋转方式就两种,一种是世界坐标系旋转,一种是局部坐标系旋转,前一种没问题,而就是后一种,导致了万向节死锁。
局部坐标系旋转的意思就是,假如你的头歪了(z轴歪了),那么再让你抬头,你抬的方向就不是正上方了,而是按照你的头顶所指的方向为上方。但问题是,并不是每个轴歪了都会导致这种情况,比如左右转头(y轴歪了),那么你再抬头,方向还是正上方。所以这里就引入了一个关键的信息,轴旋转的连带关系,具体如下
y - x y z
x - x z (就是这里导致的万向节死锁)(这里暂称它为死锁轴)
z - z
这个意思指的是
旋转y轴,会连带着把x z轴一起转了
旋转x轴,会连带着把z轴一起转了
旋转z轴,只会影响自己
关键就是x轴,如果你转的过程中,把其他轴都带着转,或者你只转你自己的,都没什么影响,唯独x轴,只带着其中一个转,就会导致z轴和y轴,会有重合的可能。
比如,现在想象下,把你的头抬起来,垂直指向天,此时你的脸的旋转(z轴),和你的脖子的旋转(y轴)是不是重合了,在这种情况下,唯一性又被打破了。比如,在unity里,创建两个物体,分别给rotation赋值为(-90,-45,0)(-90,180,135),你会发现,两个物体的旋转是一模一样的。这就是万向节死锁
死锁角一定是x轴吗?这个不一定,xyz中只会存在一个死锁轴,你可以把z当成死锁轴,那就是这样
y - x y z
x - x
z - x z
为什么非要留一个死锁角?直接让每个轴都影响其他两个轴不香吗?
但其实,全都连带和全都不连带,都是世界坐标系的旋转方式
为什么还要用欧拉角虽然欧拉角会死锁,但只存在于x轴为±90的情况,所以我们只需要注意下这两个角度,那么欧拉角就不存在问题了,至于为什么大家都约定把x轴作为死锁轴,是因为这两个角度,我们看的少,对比把y z轴作为死锁轴来说,x轴是瘸子里面选将军,也是最符合我们习惯的方案。
比如你观察2轴的摄像头,他们如果向后方看,它们绝不会直接把头仰到后面,而是向后转180,再抬头低头,他们不会跨越x轴的±90度
不得不用欧拉角的原因,就是因为他直观,所以,unity在编辑器面板显示时,使用欧拉角,而内部的旋转使用四元数
万向节死锁总结欧拉角的局部旋转方式,会不可避免的存在一个死锁轴(x轴),而死锁轴会在特定的条件下(±90度),导致欧拉角的表示变得不再唯一,这就是万向节死锁



