听说现在搞空间控制都得学四元数,于是找了几篇文章看了看,但是一直二蒙二蒙的,前几天看到了《Understanding Quaternions 理解四元数》http://www.qiujiawei.com/understanding-quaternions/ 这篇文章,茅塞顿开,自己拿纸笔画了画,终于搞明白了。搞明白了以后,我觉得其实还可以写得再直观一点,再简洁一点,所以我决定写一篇博客试着挑战一下,一来巩固自己的理解,二来试一试用新学的LaTex写公式。
四元数的发明者的历史什么的就不多说了,相信大家都看了很多了,我们还是聚焦于四元数本身吧。不过呢,说到四元数,还不得不先从复数说起。我们都知道复数,或者说虚数单位“”这个东西的来历,是因为实在在已知的数轴上找不到一个数来对应这个东西了,这个问题困扰了思想质朴的古代数学学们几千年,特别是在解方程的时候,二次方程判别式小于0时就无解,这还罢了,到了三次方程,好不容易鼓捣出了通用求根公式,却发现经常会遇到开负数平方的情况,如果还像二次方程那样认为它无解吧,又偏偏很多情况下实际上是有实解的,现在我们知道,很多情况下求根公式中间过程中会产生一对共轭复根,最后它们的虚部会抵消掉,但是那时的数学家虽然已经知道偷偷摸摸的加入这么一个中间变量,但还是不能接受这也是一种数的概念,只能自欺欺人的说这只不过是个无意义的临时变量,没有实际意义,所以叫“虚数”。最后终于有那么位比较离经叛道的某人不管三七二十一地说“我觉得不要偷偷摸摸拐弯抹角的用他又不承认他,应该给他个名分”。这个做法真是石破天惊,一下子打开了一扇通往一 个神秘新世界的大门。
现在终于有了个名分了,可是,实数可以用数轴上的一个点来表示,那虚数怎么办呢?数轴上,或者严格说实轴上可是没有他的位子的。也不知道是哪位先贤,某天在纸上画了一条线,这个是大家都知道的实轴,当他想画一个复数时,他的眼光停留在了数轴上下方广阔的空白空间上,突然想到了既然可以用平面直角座标系来表示一个二元函数x,y的关系,为什么不用来表示复数中的实部和虚部这一对二元关系呢?于是用平面直角座标系来表示复数的方法诞生了,复数从此与平面空间联系了起来,人们逐渐发现用复数来表示二维平面的关系有非常大的便利,因此复数的使用越来越广,复变成为一种重要的数学分支。
这里我们不讲太多复变函数方面的东西,只关注一下复数与二维平面的关系。一个实数,比如1吧,乘以 ,就变成了一个纯虚数 ,从复平面图上来看,就是从实轴上跳到了虚轴上,再乘以一个 ,×=-1,又跳到了负实轴上,接着乘下去,就会一直绕着原点逆时针转圈圈,所以可以看出每乘一次 ,就是逆时钟转 。那么如果乘 呢,就是顺时针转(注意这个结论)。那么是不是任意一个复数乘 都是转呢?结论大家其实都知道,只是我这里还是要用一个比较特别的思路说一下。
假设一个复数,我们可以把它拆开来,看作是两个相互垂直的矢量和矢量的和,这里是实轴方向的单位矢量,是虚轴方向的单位矢量,a ,b是实系数,代表矢量的长度。一个复数就可以看作是这么两个矢量的矢量和。那么将这个z去乘i , 也可以看作是将两个分量 和分别去乘 i再加起来。此时 变成了 ,旋转了,变成了 ,也旋转了,它们之间的相对位置和大小都没有变,只是整体旋转了,因此他们的合矢量当然也就旋转了,其它都没有变。所以我们可以得到结论,任意复数 ,它乘以 都是逆时针旋转。
为什么要这样解释这个的转动呢?因为这样比较好理解如何旋转任意角度。我们可以把一个矢量的旋转过程分成两个过程,比如要把矢量 旋转 角度,我们可以先把 旋转,并且把它的长度缩短为 ,这个过程相当于 ,然后,再将原来的矢量缩短为倍大小,并加上这个旋转并缩小过后的矢量,也就是 , 最终的结果就是将旋转了角度。而
,所以旋转 角度就相当于乘以一个复数 。
好了,说了这么多,总算把复数的有关知识复习完了,之所以先说这些,是因为四元数的思想,其实和这个是相同的。接下来我们正式开始四元数的介绍。
自从发现了复数可以表示二维平面后,很多人就在想三维空间能不能也用一种复数来表示,能不能也有像二维复数这样方便的表示旋转、拉申等操作的方法。一个很自然的想法是把复数空间简单的扩展成三维的,比如在实轴、虚轴 之外,再扩展一个与这两个轴正交的轴 轴,顺便说一下,这个轴的正方向如果朝背离我们的方向而去,就是一个左手系,如果朝着我们的方向就是一个右手系。两种定义都有人用,我们从小学习的数学书上一般都是左手系,而上面引的那篇文章用的是右手系。我个人习惯还是倾向左手系。
好了,我们现在得到了一个三维空间,有三个轴,分别是实轴、轴 和 轴。等会我们就会发现这种定义并不好。 在二维复数里实数乘以 ,可以认为从实轴向虚轴转动了,再乘一次,就又转,转到了负方向上去。那么现在多了一个轴,从实轴转也就多了一个转动方向,可以转到轴 ,也可以转到 轴,(其实现在是多了无数个转动方向,可以转到 ,平面上的任意一个方向上,这里我们只考虑两个相互正交的方向,即轴方向 和 轴方向),那么乘 就是向轴转动,乘 就是向轴转,乘一次转,乘两次就转到原来的对面去了。根据这个可以写出下面两个式子:
,
现在有了两个方向的转动,可是三维空间,有三个方向的转动,还有一 个方向是从轴到 轴的转动,就用 来表示这个转动吧。通过这个定义又可以写出两 个式子:
根据以上这些式子,我们可以进一步推导出以下的式子:
于是我们得到了四元数的基本运算规则:
在这个基本规则上还可以推导出以下的规则
我们发现这个运算和顺序是有关系的,是不满足交换率的,如果顺序交换了,就要变符号。
好了,这就是直接从二维复数推广到三维空间的情况了。在这种座标定义下,绕着 轴旋转是乘 ,绕 轴旋转是乘 ,而绕实轴旋转是乘 ,一个在这个座标系下的矢量的座标是, 是看不到的。这种情况看着是不是很别扭?实际上在做运算的时候其含义也很不好解释。总之这种直接从二维复数推广的方式很不直观方便,在看完本文后大家可以自己试试,看是不是比下面的定义要麻烦多了。既然三维空间里有三个方向的旋转,需要定义三个虚数,那何不就把三个轴定义为 轴,轴和 轴,把绕 轴旋转定义为乘 ,绕 轴旋转定义为乘 ,绕 轴旋转定义为乘 呢?这样就得到了以下的座标系定义,以及他们的转换关系,这里转动的正方向是从转动轴正方向往负方向看的逆时针方向:
根据这几个旋转关系,通过推导,我们同样能得到 这个基本关系以及其它的推论。在这种座标系定义下,一个矢量的座标表示就变成了,如果以矢量形式来写就是 。,,来代表三个方向的单位矢量。
现在开始研究一下在这个座标系下,两个四元数的乘法代表什么意义。我们先从简单的情况一点一点的开始。先只考虑没有实部的四元数,称为纯四元数的乘法。我们假设一个在 j-k 平面上的纯四元数 ,以及一个长度为1,方向为 轴方向的纯四元数 ,显然,和是垂直的。现在计算×的结果:为了区分四元数乘法和普通乘法,以后用来代表四元数乘法。
分量绕 轴逆时针旋转了变成了, 分量绕 轴逆时针旋转了变成了,结果是整体绕着 向逆时针方向转了了。如果换一个角度看,其实也可以看作是 绕着 顺时针方向转了。
如果再交换一下和的顺序,结果就变成了:
变到和刚才相反的方向上去了。同样,这可以有两种解释,一种可解释为 绕着 逆时针方向转了,也可以解释为 绕着 顺时针方向转了。
通过这个简单的例子我们可以知道,这两个比较特殊的互相垂直的纯四元数相乘,可以看作是前面那个数绕着后面那个数逆时针旋转了,也可以认为是后面那个数绕前面那个数顺时针旋转了。那么是不是任何相互垂直的纯四元数相乘都是这样的?结论是肯定的。我们可以写出任意两个垂直的纯四元数 和, 并且假设 ,则
我们看到实际上两个纯四元数的乘法结果,它可能会出现一个实数部分,而这个实数部分的值,就是两个纯四元数矢量的点积乘-1,而它的虚部则是它们的叉积。因为我们已经假设了,所以=0 ,所以结果仍然是一个纯四元数,此时的虚部的值是,正好就是 绕着 向逆时针方向转了,或者说 绕着 顺时针方向转了。如果 和都为1,则结果的长度也是1。如果 和的长度不为1,则结果的长度就是。
现在我们知道了两个互相垂直的纯四元数,它们的积仍然是一个纯四元数,并且是第一个数绕第二个数逆时针旋转了。那么如果我们想让它旋转另外一个角度 呢?其实也可以按前面所说的二维复数的旋转方法来实现。我们假设要把一个四元数绕 旋转 角度,这里 是表示 的方向的单位向量 ,则是一个与 垂直的单位向量。同样,把这个旋转过程分为两步:第一步先把 旋转π/2,并且把它的长度缩短为 ,这个过程相当于 ,然后,再将原来的矢量缩短为倍大小,并加上这个旋转并缩小过后的矢量,也就是 , 最终的结果就是将旋转了角度。而
所以旋转 角度就相当于乘以一个四元数 ,这个形式和二维复数的形式“ ”是一样的。现在我们终于理解为什么说四元数的乘法是一个转动了。如果把两个数乘法的顺序反过来,结果是什么样子的呢?
可见如果交换了顺序,就相当于把向相反的方向转了 角度。
另外如果我们先乘一个,正转角度,再乘一个,反转角度,显然就又转回来了,等于没有转动,于是可知
此时称 和 为共轭,和二维复数的定义很类似。根据以上推导可知,一个纯四元数和一个转动四元数,当它们的虚部垂直时,可得到以下的结果:
另外再说一下,当、 是纯四元数时,我们可以说 是绕着 逆时针转,也可以说是绕着 顺时针转,但当带有实部,不再是一个纯四元数时,就不好再说怎么绕着 转了。
接下来要进入四元数最麻烦的地方了。向量与旋转轴垂直的情况已经知道了,那如果不垂直呢?我们还是先从简单的例子开始。我们设一个纯四元数 需要绕着 单位向量 旋转,但 并不与 完全垂直。我们可以把 分解成两个向量的和,一个向量是 在与 垂直的平面上的投影 ,另一个分量 与 平行,即令 ,那么根据前面的两个纯四元数乘积的结果的结论,会产生一个实部和一个虚部,实部的值是负的两个数的点积,虚部是两个数的叉积,则
这里利用到了所以这几个关系。
上面的结果可见,垂直于旋转轴的分量老老实实的转过了,而平行于旋转轴的分量则从这个空间跑了,跑到了一个神秘空间,也就是实轴上去了。如果我们把这个结果继续再乘一个呢,结果是
又把给转出来了,只不过转到对面去了,而且是整个 转到了相对原点对称的地方去了。
如果不是想转,而是想转角度,还是让,现在
这个结果可以看作是将垂直旋转轴方向的分量转了角度,然后还加上了一个平行于旋转轴的分量,最后还有一部分跑到了实轴上,真是够复杂的。看到这个结果脑袋有点大,这可不是我们期望的结果,我们期望的结果是垂直旋转轴方向的分量转角度,而平行旋转轴方向的分量不变,也就是希望得到,现在这个结果可真够乱的。
不管怎样,我们硬着头皮仔细看看这个结果。前一个部分是垂直于的纯四元数,主要看后面这个部分的结果,,注意到有这个关系,这个式子可以变为:
我们发现,是可交换顺序的,而且只要去乘一个,就能把 变回来,并且左乘、右乘都可以。可是如果是右乘的话,实际上因为,就是又转回去了,这很无聊。所以我们试试左乘吧。
首先看后面一项,因为,所以这一项可变为
很好,把 变回来了。然后看第一项。根据前面的推导结果,当一个纯四元数和一个转动四元数,当它们的虚部垂直时,,因此这里:
这相当于把 绕着转了两次,也就是转了两个角度。最后我们把整个结果写下来:
这个结果就是 整体的绕 转了2角度。看到这大家是不是眼睛一亮。虽然转过的角度变成了2,不是我们希望的,但是聪明的你一定马上就想到了办法,把变成转 /2不就行了?于是,想要让纯四元数 围绕一个轴转动角的四元数乘法就变成了:
现在我们终于明白了四元数旋转为什么要用两次乘法了。这篇文章也不打算说更多的东西,其实大部分人也就只利用它来做旋转,了解这些就够了。至于插值等功能,了解了这些基本原理方法后,也很容易推导出来,相关文章很多,就不继续写了。其实继续推导下去还可以得到很多有趣的东西,比如四元数函数、四元数插值等等,甚至还有四元数微分等等,有兴趣的同学可以继续深挖下去,祝大家转得快乐。
最后说一下,本来是想配一些图的,听说现在画图都用MatPlotLib,于是学了一下,可是折腾了两天也没搞明白,画不出理想的图来,暂时就算了吧。以后等我搞懂了MatPlotLib再来把图补上吧。
20201206 今天终于下决心把图给补上了,最后用的是mathematica的绘图功能。开始本来是想把符号标注什么的都用软件生成,后来发现太麻烦了,所以只画了矢量图,符号是用windows画图手标上去的。