本文假设读者知晓什么是复数、向量内积、向量外积。
什么是四元数?为什么需要它?
三维空间中物体的朝向经常会使用欧拉角系统用来表示。
欧拉提出,一条直线在空间中的朝向可以通过其与空间坐标系的 3 条轴的夹角来确定。
过原点的两条直线,一定可以通过对其中一条施加绕 x 轴、y 轴、z 轴的 3
次旋转来使它们重合。
旋转角度的正方向由坐标系的手性确定,在右手系中,使用右手大拇指指向坐标轴的正方向,
其余手指弯曲的方向就是旋转角度的正方向。
现代工程中的万向节使用的就是这套系统,航空系统也是使用欧拉角来表示飞机的朝向。
下图就是一个使用万向节来调整机头朝向的飞机模型。
万向节常规状态
来源:https://computergraphics.stack…
这里我们使用计算机的屏幕坐标系来分析问题。红、绿、蓝 3 条转轴(RGB)
分别对应 x、y、z 方向。飞行的初始状态是机身轴线与 z 轴重合,
机翼面与 y 轴垂直,在此基础上,使用 3 个角度来表示飞机的飞行姿态:
- 偏航角(yaw),机身绕 y 轴旋转的角度。
- 俯仰角(pitch),x 轴经过上一步旋转后得到新坐标轴 x′,绕该轴的旋转角度
- 横滚角(roll),z 轴经过前两步旋转后得到新坐标轴 z′,绕该轴的旋转角度。
这一套系统简单直接,在实际的操作中也非常好应用。但是有一个非常大的问题——假如机头
朝向正上方或者正下方,旋转轴 y 与 z′ 就会重合,导致这种状态下一个
姿态有多种不同的三角度组合表示法。更致命的是在图示中万向节框架下,只要机身进入
xOy 平面,机头就只有笔直向上、笔直向下两个可能的方向了。
万向节锁定
来源:https://computergraphics.stack…
万向节不再万向的这个问题叫作万向节锁。在一部分早期的 3D 游戏里,玩家看向天空之后,
就能感受到左右移动鼠标无法让人物转向的无力感,甚至在 3D 游戏开发的过程中,有悄悄
把玩家的俯仰角限制在 1° 到 89° 的范围内这样的做法。
四元数是一种用来表示三维空间中绕任意轴旋转操作的数,在其诞生之后的一百多
年里,人类文明因为很少有绕任意轴进行空间内旋转的工程需求,四元数一直处于被应用界
冷落的状态。现代机器人、软件中的 3D 场景变多之后,工程师们也开始在意起了这种奇妙
的代数产物。
引子——复数
复数,作为一种代数上的定义是让人费解的:
z=a+bia,b∈R,i=−1学生通常在二次方程的学习过程中接触到复数,他们在学到这一概念时,手头上有限的数学
知识无法支撑他们对复数解进行应用,大家也就自然而然地觉得复数解是无意义的东西。
复数是伴随着明确的代数需求出现的,三次方程求根公式出现时,人们发现在这个求根
公式中经常需要进行负数的开放运算——是的,并不是二次方程。
最开始,数学家们还没有对负数开方的勇气,认为求根公式进行到这一步就失效了。在负数
开方的首次尝试中,−1 的平方根被用类似于“◌”的空洞符号表示,在使用“◌”化简求根
公式的过程中,表达式中的“◌”竟然全部被消去了。
数学家们开始意识到,对负数的开方是有代数意义的。
但是仅仅是为了进行求根公式就加入一种新的代数符号,是否是合理的处理方式呢?在古
希腊时期,所有的代数公式都需要转化成几何形状的变化、关系来表示,才能被人
接受——因为只有几何形状才是看得见摸得着的,数字这样的符号太飘渺了。对于三次求根
公式被发现的那个时代的数学家们来说,一个唯一的作用就是平方能得到负数的数,何尝不
是一样的飘渺呢?在接下来的时间里,数学家开始寻找复数单位 i 真正的意义。
慢慢地他们开始发现,复数的意义其实是几何性的,它是一种建立在几何图景上的精妙代数
结构。渐渐出现了使用复平面来表示复数的方法,复数被表示成复平面上的一个点,就像在
迪卡尔坐标系中使用横比例坐标表示一个点那样。平面上相互垂直的实轴、虚轴分别用对应
一个复数带有多少虚数分量和实数分量,复数的实部与虚部被当成了复数点的坐标。
复平面
来源:https://en.wikipedia.org/wiki/…
更进一步,复数出现了极坐标表达,被表示成了方向、长度的复合量。长度指的是复数
在复平面上到原点的距离 r,这叫模长;而方向指的是复数点与原点连线,同实轴之间
的夹角 θ,这叫辐角。
这样一来复数可以被表示成下面的形式:
z=r(cosθ+sinθi)其乘法就可以表示为:
r1(cosθ1+sinθ1i)×r2(cosθ2+sinθ2i)=r1r2(cosθ1cosθ2−sinθ1sinθ2)+r1r2(cosθ1sinθ2+cosθ2sinθ1)i=r1r2[cos(θ1+θ2)+sin(θ1+θ2)i]可以发现,复数的乘法是二维空间中的伸缩与旋转。
两个复数相乘的结果的长度是两个参与乘法的复数的模长之积,这是伸缩变换;
结果的辐角大小是参与乘法的复数的辐角和,这是旋转变换。尤其是当我们刻意选用模长是
1 的复数与其它复数相乘时,就可以计算出给定的复数绕原点旋转某个角度之后的结果。
比如 i 就是一个长度为 1 的复数:i=cos2π+sin2πi。
一个数乘上 i,就是在复平面上绕原点旋转 90°;乘两次 i 就是旋转 180°。这正是
i2=1 在复平面上呈现出的几何意义。
几何与代数的结构通过复数精妙地联系在了一起,告诉数学家们,他们有一片比数轴更广扩
的空间可以探索。
在学习完复数的坐标化、极坐标化之后,可能会有读者觉得复数不过是向量的简化版。笔者
在学习复平面这一概念时,教材是把复平面安排在平面向量的内容之后。当时笔者觉得非常
困惑,为什么学完向量之后还要特意讲一个运算、几何应用都不如向量多的知识。在高中阶
段看复数确实也就是这样的。
其实在历史上,复平面才是向量的表示被标准化的开端。尽管在物理上,人们早已开始使用
带有方向的量,但是对向量正式的计算表示,却没有那么早。
正是复数的代数结构表现出来的几何性催生了四元数,再由四元数的概念中衍生出了现代的向量分析。
四元数的提出
四元数最初的目的就是为了使用代数的形式,对三维空间中的旋转进行描述。这是一种为了
几何目的提出的代数结构。四元数使用以下形式定义:
q=a+bi+cj+dk其中 a, b, c, d 为实数,i, j, k 为虚数单位,满足:
i2=j2=k2=ijk=−1a 被称为四元数的实部,如果一个四元数的实部是 0,就称这个四元数是一个纯
四元数。而四元数的模长,定义为 a2+b2+c2+d2。
表示三维空间中旋转的关键就是这 3 个虚数单位。它们各自在表示一个四元数的同时,也
用他们的乘法表示了绕 3 个坐标轴之一旋转 2π 的操作。
习惯上,i 对应 x 轴;j 对应 y 轴;k 对应 z 轴。
也就是说,复数中的虚数单位 i 在四元数中对应的是 k,不过这只是字母表示
的不同罢了,在代数上没有区别。就像 plus one 与 + 1 表示是的是相同操作一样。
要注意,四元数中 3 个虚单位已经把三维空间中的 3 个轴占满了,实部所表示的坐标分量
已经升到了四维空间中。想要把四元数作为一个整体进行几何想像的话,就必须动用四维空间,
而要描述我们所处的世界,我们就只需要将 3 个虚单位所在的虚部系数当作三维空间中的
坐标就可以了。
起初,发明四元数的哈密尔顿先生想的是,既然使用 1 个虚数单位可以表示二维空间中的
旋转,那么使用 2 个虚数单位应该就可以表示三维空间中的旋转了。但是在这个思路下,
他花了很长时间也没有得出来结果。
在脚踩前人肩膀的今天,笔者马后炮地说,可能是因为哈密尔顿先生最开始并没有注意
到实部 a 只能用于表示伸缩,而不能表示旋转,所以才在三元数上花了这么长时间思考。
在二维空间中,旋转轴只有一条——也就是 z 轴,尽管从三维空间才能看到这条轴。
但是到了三维空间中,情况就不一样了。空间中可用的转轴一下变成了 3 条,所以使用 3
个虚数单位分别对应最简单的 3 种旋转是合理的。
四元数的代数规则
我们现在从代数的角度来看一看,这 3 个虚数单位是如何表示绕 x, y, z 轴
的旋转的。
首先,同复数的情形一样。如果两轴互相垂直,其中一者绕另一者旋转 180° 后,进行旋转
的一方就会反向,比如:iij=−j,这就是复数单位平方的含意。
i2=j2=k2=−1接下来,ijk=−1 表示的是旋转的另一个性质,从这一条代数定义我们可以推导出:
ijikjkjikikj=k=i∗ij=i2j=−j=−ik∗k=−i∗k2=i=j∗jk=j2k=−k=−ij=ij∗i=i∗ji=−ik=ij∗j=−i=−jk整理一下:
ijkijk=−ji=k=−ik=j=−kj=i除了能看出来 i, j, k 三条轴之间的轮转关系之外,我们还能看出来这 3 个
虚数单位间的乘法是不满足交换律的,这使得四元数的乘法在全体层面也是不满足交换律的。
这很好地反映了三维空间中旋转的性质,绕 x 轴
旋转 2π 再绕 z 轴旋转 2π,与先绕 z 轴
旋转 2π 再绕 x 轴旋转 2π 结果是不一样的。
如果我们把四元数 (a1+b1i+c1j+d1k) 与 (a2+b2i+c2j+d2k)
相乘,结果是:
+++a1a2−b1b2−c1c2−d1d2(a1b2+b1a2+c1d2−d1c2)i(a1c2−b1d2+c1a2+d1b2)j(a1d2+b1c2−c1b2+d1a2)k这是一个十分片繁琐的算式,并不是很适合进行定性分析。好在当下完善的向量体系能
够极大简化这个表达式。让我们使用向量重新给出一个四元数的书写形式:
q=(a,u)其中四元数 q 是一个有序对;
a 是实数,是四元数 q 的实部;
u 是一个三维实向量,3 个分量分别代表四元数的 3 个虚单位的系数。
借助向量的内积、外积,四元数 (a,u) 与 (b,v) 的乘积可以表示
为:
(ab−u⋅v,av+bu+u×v)可以看到四元数的乘法不满足交换律的部分就包含在 u×v 这个小
小的部分。
四元数的这种向量记法不仅简化表达式,还把四元数中呈现出不同运算性质的两个部分分开展示,
是一个相当不错的记法。
罗德里格旋转公式
在介绍四元数如何表示三维空间中的旋转之前,我们先来看一看使用常规的坐标计算是如何
得到点绕定轴旋转的结果的。
这里我们使用向量法来进行罗德里格旋转公式的推导。
设坐标原点为 O,ON 是一个过原点的旋转轴,点 P 要绕该轴旋转 θ 角,而 N 为
P 到转轴的垂线的垂足。
设旋转得到的点为 P′,过 P′ 向 NP 做垂线,其垂足为 Q。
又设 ON 与 OP 之间的夹角为 α,
n 为 ON 的单位方向向量。
欲求 P′ 坐标,即是要求得向量 OP′:
OP′=ON+NQ+QP′根据 NP 与 ON 的垂直关系可以得到:
∣ON∣=cosα⋅∣OP∣=n⋅OP即:
ON=(n⋅OP)n记 r=NP,从圆上的三角关系可以得到:
NQ=cosθr接下来,利用 QP′ 与 n×OP 的平行关系,
可以得到:
QP′=∣QP′∣∣n×OP∣n×OP=sinθ∣r∣sinα∣OP∣n×OP=sinθ∣r∣∣r∣n×OP=sinθ(n×OP)综上可得:
OP′=ON+NQ+QP′=(n⋅OP)n+cosθr+sinθ(n×OP)记 p=OP,将 r=p−ON=p−(n⋅p)n
代入并进行化简可得:
OP′=(n⋅p)n+cosθ[p−(n⋅p)n]+sinθ(n×p)=cosθp+(1−cosθ)(n⋅p)n+sinθ(n×p)从这一公式我们可以看出,如果 p 与 n 平行,旋转对向量不会
有任何作用;如果 p 垂直于 n,p 与 n×p
就都处于 p 旋转时经过的平面内,且长度相等。二者能张成一个坐标系,旋转
的结果就在这个坐标平面中。
在罗德里格旋转公式中,关键的向量内积、外积运算都是满足分配率的。
这意味着 p 分解成与 n 平行的分量 p∥ 与垂直于
n 的分量 p⊥,然后将二者分别进行旋转,再将他们各自旋转
和结果合成,合成结果就是 p 直接进行旋转所得到的向量。
OP′=cosθp∥+(1−cosθ)(n⋅p∥)n+sinθ(n×p∥)+cosθp⊥+(1−cosθ)(n⋅p⊥)n+sinθ(n×p⊥)
旋转分解
来源:https://en.wikipedia.org/wiki/…
四元数的运算性质
接下来,让我们一边推导四元数的运算性质,一边观察它如何表示旋转。
本节中,我们主要使用这两个四元数进行讨论:
qp=(a,u)=(b,v)基本运算
首先我们是相对简单的两个性质:
λqp±q=(λa,λu)λ∈R=(a+b,u+v)如果我们仿照复数,我们使用模长与方向的形式来表示四元数,就能得到以下记法:
q=λ(cosθ,sinθu)其中的 u 是一个单位向量。
那么对于一般的四元数乘法,我们可以得到:
qp其中RI=λ1λ2(R,I)=cosθ1cosθ2−sinθ1sinθ2u⋅v=cosθ1sinθ2v+cosθ2sinθ1u+sinθ1sinθ2u×v能够轻松看出,两个四元数之积的模长是两个四元数的模长的积,表明了四元数的乘法在
四维的空间中会带来伸缩效果,如果想要用四元数来表示纯粹的旋转,就一定要注意使用
单位长度的四元数。但是光看这一结果,还不是很好看出四元数的乘法在表示旋转方面的作用。
共轭与逆
接下来看共轭四元数。
在复平面中共轭的两个复数各自与实轴之间的夹角是互为相反数的,
代表了一对相反方向、相同角度大小的旋转。在四元数中表示旋转的部分只有虚部,
因此我们也类似地给出共轭四元数的定义:若有四元数 q=(a,u),定义四元
数 q∗=(a,−u) 为其共轭四元数。
观察四元数与其共轭四元数之间的乘法我们可以得到:
qq∗(pq)∗=(a2+u2,0)=q∗q=∣q∣2=(ab−u⋅v,−(av+bu+u×v))=(ab−(−u⋅−v),a(−v)+b(−u)+(−v×−u))=q∗p∗结合上面的观察我们不难发现,非 0 四元数是有逆的——即,对于任意非 0 四元数 q,
一定存在一个非 0 四元数 q−1,使得 qq−1=1。结合上面对共轭四元
乘法的计算,我们可以得到:
q−1=qq∗q∗如果 p 是一个单位四元数,那它的共轭四元数就是它的逆。
逆元是很重要的,逆元的存在性告诉我们,只要是通过四元数产生的变化,就一定可以通过
另一个四元数乘法将这一变化消除:
q−1qp=(q−1q)p=p如果四元数乘法能用于表示三维旋转,那四元数就必须要有乘法逆元,因为旋转操作是可逆的。
而且在观察到四元数的逆与其共轭之间明显的关系之后,虽然四元数之间的乘法不满足交换
律,但是我们可以得到以下结论:
pq−1=p∣q∣q∗=∣q∣1(−q∗)p=∣q∣1[q−(2a,0)]p也就是说,左乘 q 与右乘 q−1 之间的差距主要体现在伸缩变换与实部带来的
乘法影响上。如果 q 是一个单位长度的纯四元数,就会得到 pq−1=qp。
单位四元数与旋转
现在,我们已经有足够多的分析结论可以用来观察的四元数能否用于表示三维旋转。本节中
我们将会使用两个特殊的四元数来进行讨论:一个单位四元数,用于表示没有伸缩的变化;
一个纯四元数,用于对应三维空间中的点。
qp=(cosθ,sinθu)=(0,v)特别注意:
q−1=q∗=(cosθ,−sinθu)首先,他们相乘的结果如下:
qppqpq−1=(−sinθu⋅v,cosθv+sinθu×v)=(−sinθu⋅v,cosθv−sinθu×v)=(sinθu⋅v,cosθv+sinθu×v)我们可以看到乘法结果的虚部有非常明显的几何意义,v 与 u×v
恰好张成一个坐标系,虚部明显表示了一个与它们共面的新向量。遗憾的是两个四元数的乘积
在实部上也产生了影响,我们的结果向量虽然整体模长没有发生改变,但是有一部分长度伸
向了空间的第四维。
对垂直情况的考察
q 与 p 乘积的实部大小由两个四元数的虚部向量之内积决定。我们不妨看看两虚部向量互相垂直时
乘法的结果。此时,实部上的内积值会因为向量垂直而变为 0:
qp=(0,cosθv+sinθu×v)由于 ∣u∣=1 且 u⊥v,我们可以知道 ∣v∣=∣u×v∣。
向量 (cosθv+sinθu×v) 就是 v 以 u
为轴,旋转 θ 角的结果。
并且在 u⊥v 时 qp=pq−1。
同一个三维旋转在四元数空间中可以使用两个不同的四元数来表示,这种现象被称为双重
覆盖(double cover)。关于这一点,本文就不展开叙述了。
回想在罗德里格旋转公式中,我们已经发现利用内积、外积的分配律,可以将一个需要进行
旋转的向量分解成垂直于转轴、平行于转轴的两个向量各自进行旋转,通过合成两个分量的
旋转结果来得到原向量旋转的结果。
四元数的乘积同样也是使用内积、外积来表示的,意味着同样的分解技巧也可以应用在
四元数 p 上。
对平行情况的考察
那么我们来看看,如果 u 与 v 平行,两个四元数的乘积会是什么:
qp=(−sinθ∣v∣,cosθv)乘积的结果已经显然不再是一个三维中能表示的几何量了,我们直接使用向量分析在四维中
看乘积与 p 的几何关系。
设四元数 p 所对应的四维向量为 α=(0,vx,vy,vz),乘积结果
对应的四维向量为 β,α 与 β 之间的
夹角为 γ。我们可以得到如下关系:
cosγ=∣α∣∣β∣α⋅β=∣p∣∣p∣(−sinθ∣v∣∗0)+cosθv⋅v=∣v∣2cosθ∣v∣2=cosθ这真是意料之外(或者在你意料之中)的结果。与 (cosθ,sinθu) 相乘
使得 p 在四维空间中旋转了 θ 角。在四维空间中与已知的两个向量垂直的向量
有整整一个平面,所以我们不能像在三维时一样使用外积来简单地得到转轴,有兴趣的读者
可以自行探索。
在之前的小节里,我们就已经发现了 qp 与 pq−1 的差别主要体现在第四维空间
维上,在 u 与 v 平行的条件下,我们可以把这个结论更进一步:
pq−1=(sinθ∣v∣,cosθv)=(−sin(−θ)∣v∣,cos(−θ)v)可以看到 pq−1 的乘积结果与 p 夹角为 −θ。通过左乘 q 产生的
旋转,可以通过右乘 q−1 来逆转:
qpq−1=(−sinθ∣v∣,cosθv)∗(cosθ,−sinθu)记结果的实部为 R,虚部为 I:
RI=−sinθcosθ∣v∣−(−sinθcosθv⋅u)=0=cos2θv+sin2θ∣v∣u−cosθsinθv×u=cos2θv+sin2θv=v即,在 u 与 v 平行时:
qpq−1=p对一般情形进行分解旋转
我们把 p 分解成使用与 u 平行、垂直的两个分量来表示:
p=p∥+p⊥=(0,v∥)+(0,v⊥)为了消除四元数乘法在 p 的平行分量上产生作用效果,我们采用下面的形式来把旋转
限制到 p 的垂直分量上:
qpq−1=qp∥p−1+qp⊥p−1=p∥+(0,cosθv+sinθu×v)∗(cosθ,−sinθu)=p∥+(0,cos2θv+sinθcosθu×v+[cosθv+sinθu×v]×[−sinθu])=p∥+(0,cos2θv+2sinθcosθ[u×v]−sin2θv)=p∥+(0,cos2θv+sin2θ[u×v])可以看到,qpq−1 成功让 p 的向量部分以 q 的向量部分为轴,在三维空间
中进行了角度为 2θ 的旋转。
那么,我们就可以得出结论:
对于三维向量 v,与表示旋转轴的单位向量 u。若要计算 v
绕 u 旋转 θ 角的结果,只需构造纯四元数 p=(0,v) 与
单位四元数 q=(cos2θ,sin2θu),乘积
qpq−1 仍然 是一个纯四元数,且其向量部分就是 v 绕 u 旋转 θ
角所对应的向量。
结语
到此,我们已经完成了使用四元数的运算来计算三维空间中旋转结果的全部工作了。
需要补充的一点是,文中所有的转轴向量、被旋转向量,都是从原点引出的。这种讨论要迁移
到实际应用是不难的。不论转轴的起点在什么地方,只需要一个平移变换就可以将其移动到
原点上,如此平移之后就可以用四元数运算进行旋转。旋转完成之后再做一次逆平移,
就可以把所有的点还原到初始坐标系中。
笔者本来想就四元数的旋转结论再进行一些具体应用的展开,但是不论怎么想,脑海中的例子
都会与具体的代码挂钩。这样的内容对于没有相关开发经验的读者来说也许不太友好,故而
干脆删去了四元数旋转公式的后续展开。
在大约两个世纪前,在还没有向量分析的时代,我们的前人能够用自己的智慧和不厌其烦对
算式进行化简的努力,将四元数系统构造出来,实在是非常值得敬佩。
笔者在了解了四元数的性质之后,曾数度夜里在床上翻身感叹前人的智慧真是了不起。
低维度中的几何结构,居然可以用高维度中的代数行为来表示,实在是太美了。
笔力尽于此,真心地希望这种美也能传达到作为读者的你的心里。