干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)

1105
0
2020年4月23日 20时00分

本文转载自微信公众号ROBOTICS

 

上一篇文章有读者留言说,希望我能整理出一个知识体系,对我自己也有点帮助。不瞒大家说,我觉得写这些东西对我自己的帮助,可能远远大于对其他人的。比如说四元数这个东西,我从来也只记它几个公式、知道怎么用,大抵就够了;可是为了写这一篇文章,我只得四处查资料、找教材,只怕不能把它真正弄清楚。

 

这一查呢,我觉得打开了新天地——原来四元数是数学家变的魔法,用它来表示空间姿态就如同一个天才般的魔术——我不禁感叹,人类的大脑为什么就能有如此的智慧,为什么就能提出虚拟的规则、建立新的只存在于想象中的数学体系、再用它来解决实际问题呢?

 

The concept of quaternion is amazing.

 

用二维向量表示一维旋转


我们知道,一维旋转是很好表示的,反正也只可能有一个旋转轴,我们只需要一个量:旋转角就好了。不过呢,用旋转角也有个问题,我们从零转到360度,叭一下又跳回零,这就带来了在该点不连续的小麻烦,需要一些unwrap操作(这个中文叫啥?)。当然,这个小麻烦比起三维欧拉角的奇异还是要好解决一些的,所以多引入一个数并不是很有必要。

 

不过为了之后引出四元数,我们还是先来看看数学家是怎样用两个数来表示一维旋转的。我说用二维向量来表示一维旋转,你可能不知道我在说什么;但我要是说复数,你大概会想:这个我知道!但这跟旋转又有什么关系?

 

我们先来看看复平面:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图

 

按照右手定则,我们设定从实轴转向虚轴为正方向。很明显地,在复平面上,如果我们规定(1+0i) 表示0度,则(0+1i)表示90度,(-1+0i) 表示180度,(0-1i)表示270度:这说明了我们可以用一个复数来表示一维的物体朝向。如果我们规定只采用单位复数(模为1的复数),也就是只考虑落在我们画的单位圆上的数,运用一下几何大法可以很容易地得出,朝向θ角可以用这样一个复数来表示:(cos⁡θ+i sin⁡θ)。

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(1)

 

如果我们要从30度转到90度,用一维欧拉角,我们加个60度好了;用复数要怎么表示呢?很有趣的,这个操作是“乘法”:用表示30度的复数、乘上表示60度的复数,我们就会得到表示90度的复数。

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(2)

 

对于任意的两个角度,我们都可以用三角函数的积化和差公式证明:表示这两个角度的复数相乘,会得到表示这两个角度之和的复数。这个证明就留给你自己做了。

 

下面让我们用单个字母表示复数,把上面的结论再写一遍:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(3)

 

三维向量的旋转公式


在一维旋转中,我们用复数在复平面上所表示的二维向量来表示朝向,并且找到了一个同样是复数的“转子” (rotor):cosΔθ+i sinΔθ,来把一个复数“旋转”到另一个复数。如果我们在一个xyz坐标系中用向量v=(x, y, z)来表示空间的三维朝向,是否也存在一个同样是三维向量的转子,能够将一个三维向量“旋转”到另一个三维向量呢?

 

我们注意到,在一维情况中,转轴只可能有一种情况,所以我们只需要用同样的复数形式表示转角就够了;但在三维情况中,我们除了转角之外,还需要把转轴也表示出来。由此,我们至少需要四个数:转角θ,以及转轴 k=(kx, ky, kz) 

 

虽然我们可以通过规定k必须是单位向量把四个数减到三个,但此时的三个数也就不是原先设定的“三维向量”了。实际上,用三维向量表示的“转子”并不存在,三维向量的旋转只有一个罗德里格旋转公式(Rodrigues’ rotation formula) 可用:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(4)

 

这个公式的推导,是把需要旋转的向量v分解为与旋转轴k垂直和平行的两个向量v垂直v平行,把v垂直转个θ角变成v垂直rot,加上v平行就能得到v_rot。下面这个图可以把这个推导很清楚地表示出来(注意我们规定k是单位向量):

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(5)

 

公式的推导不难,但是这式子又是叉乘又是点乘的也太不简洁了……

 

用四维向量表示三维旋转


数学家们思考了很久如何将数系从复数(二元数)再扩展到三元数,却始终找不到好的定义方法;最终反倒是找到了四元数。四元数体系可以理解为对复数的扩展:在复数中,我们规定虚数 i=sqrt(-1),或者说 i^2 = -1;为了构建四元数,数学家又引入了两个虚数j和k,并规定

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(6)

 

然后将四元数写作:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(7)

 

为什么要这样规定呢?这个问题你只能去问汉密尔顿了——正是汉密尔顿在长时间冥思苦想之后终于得到的这个表达式,为他、也为我们更好地表示三维旋转,打开了新世界的大门。

 

从对i, j, k的规定中,我们可以进一步得到:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(8)

 

要注意的是,四元数的定义牺牲了乘法交换律,ji并不等于k,而是

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(9)

 

从上面的这两个式子我们可以发现,如果我们用i, j, k来表示三维坐标系的三个轴的单位向量,把两个虚数的相乘理解为叉乘,那么这些关系就都能成立了:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(10)

 

所以,我们可以用一个s=0的四元数,来表示三维向量 (x, y, z) 所指向的三维朝向:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(11)

 

看到这里,你大概会猜到,既然前面说不存在“三元数转子”,那将一个实部为0的四元数、转到另一个实部为0的四元数的“四元数转子”存在吗?如果存在,那不正可以用来表示两个三维向量之间的旋转?

 

在寻找这个转子之前,我们先来看看四元数的纯虚数相乘。为了方便,我们把四元数写成实数+虚数的形式:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(12)

 

要求四元数的纯虚数相乘,我们可以暴力地把所有数写出来,用乘法交换律和上面几条基本式子得到如下的关系(虚数部分太长不写了,如果你自己写出来,就会发现那正好是叉乘的形式)

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(13)

 

实数和四元数的纯虚数相乘可以理解为标量和向量相乘,这里就不把所有的四元数运算规则都说一遍了。

 

现在,我们需要一点想象力和类比能力来寻找这个转子。在一维旋转中,我们的转子长这样:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(14)

 

既然四元数是复数的扩展,同样也有实数部分和虚数部分,那我们不妨猜测四元数的转子和复数转子长得很像:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(15)

 

一维情况旋转是一个乘法运算,我们不妨就认为四元数的旋转也是一个乘法运算好了。

 

比较特殊的一点是,前面说四元数里乘法交换律被牺牲掉了,那么我们的转子到底应该是放在左边,还是放在右边呢?这里好像不太好猜了,所以我们两种都试试看再做决定……

 

左乘

我们首先试试左乘。依照前面“三维向量的旋转公式”的变量名称,设定需要旋转的向量为v,旋转轴为向量k,旋转的角度为θ;那么用转子乘向量v可以得到:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(16)

 

你可能没看出什么特别的来,让我来提醒你一下,这是我们的罗德里格旋转公式:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(17)

 

再回顾一下这个公式的推导过程,我们把向量v分解成了于旋转轴垂直的向量v垂直和平行于转轴的v平行,同样的方式用在上面的式子里,我们有:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(18)

 

我们发现,对于v的垂直分量(把它代入旋转公式看看),运算的结果实数部分为0,而虚数部分正好就是旋转后的向量!这说明这个“四元数转子”对与它垂直的向量所发挥的作用正如我们所期待的一样。

 

但对v的平行分量 ,这个左乘的结果虚数部分向量的方向是对的,但它的实数部分不为0;就好像虽然在三维空间它没有任何旋转,但在四维空间里,它却被转到另一个位置去了!

 

我们可以猜测,应该有某种办法可以把它转回来——在找到这个方法之前,我们不妨先看看右乘转子的结果。

 

右乘

按照同上面一样的方法,我们可以得到

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(19)

 

注意v垂直和k叉乘的顺序变了,而a x b = – b x a,sin(-θ)= – sin(θ),我们发现右乘的操作会把垂直方向的向量给转回去(转-θ角),而平行方向的运算结果与左乘是一样的。

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(20)

 

既然这样,那我们右乘 -θ 角的四元数不就可以了吗!这样,垂直方向的分量会继续转个θ角,而平行方向分量的实数部分会与之前正好相反,这样是不是正好可以把左乘时转到神秘四维空间的那个量给转回来呢?(我们的目标是让实数变为0)

 

基于这样的理解,我们来算一下,你也可以借机复习一下向量叉乘点乘的各种运算:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(21)

 

最后一行这个式子,有没有觉得很眼熟呀——没错,这就是我们的罗德里格旋转公式,只不过转角变成了2θ——这个好办,只要把我们的转子角度变成θ/2就好了!

 

经过以上奇妙的推导,我们最终得到了一个“四元数转子”:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(22)

 

它是一个“单位四元数”(Unit quaternion),它的逆等于它的共轭,也就是我们用于右乘的那个数:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(23)

 

在三维空间,围绕转轴u旋转θ角的操作可以由如下运算完成(v向量需要转成纯虚四元数的形式):

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(24)

 

最后,我们可以做一个类似的表格:

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(25)

干货 | 欧拉角,四元数?晕头转向的空间姿态表示法(下篇)插图(26)

 

小结


这个问题太有趣啦,忍不住为它写了这么多。我认为这样用这种角度去看待以四元数来表示旋转的方式,可能是我能想到最直观、最具物理意义的理解方式了。CC明显数学不好,所以常常倾向于把一些抽象概念具体化……我们还是要感谢数学家的奇思妙想,拓展了人类的数系,让我们有了这样一个好工具。这篇文章如果有不严谨的地方,欢迎大家指正。

 

关于姿态误差的计算、四元数的实际应用、四元数究竟好在哪里、各种空间姿态表示方法的相互转换……就留给下一篇吧。

 


参考资料

https://www.3dgep.com/understanding-quaternions/

https://www.zhihu.com/question/23005815

https://en.wikipedia.org/wiki/Rodrigues%27_rotation_formula

发表评论

后才能评论