四元数Quaternion的基本运算

2022-10-05 17:30:34 浏览数 (1)

技术背景

在前面一篇文章中我们介绍了欧拉角死锁问题的一些产生背景,还有基于四元数的求解方案。四元数这个概念虽然重要,但是很少会在通识教育课程中涉及到,更多的是一些图形学或者是工程学当中才会进行讲解。本文主要是面向四元数,相比上一篇文章更加详细的介绍和总结一下四元数的一些运算法则,还有基于四元数的插值法。

基本运算

而四元数Quaternion这个概念的提出,更像是对复数的一个扩展,我们通常把四元数写成这样的形式:

`$q=s ix jy kz

$`

其中s,x,y,z都是实数,并满足这样的一些运算规则:

`$i^2=j^2=k^2=ijk=-1

itimes j=k,jtimes k=i,ktimes i=j

jtimes i=-k,ktimes j=-i,itimes k=-j

$`

以上都是四元数的一些基本定义,接下来我们逐一看一下四元数的一些基本运算。

四元数加法

两个四元数的加法就是将“实部虚部”对应位置做元素求和:

`$q_1 q_2=(s_1 ix_1 jy_1 kz_1) (s_2 ix_2 jy_2 kz_2)=(s_1 s_2) i(x_1 x_2) j(y_1 y_2) k(z_1 z_2)

$`

可以简单证明,四元数的加法满足交换律、结合律和分配律,这里不过多展开介绍。

四元数缩放

在系数缩放这一点上,四元数与复数是一致的:

`$lambda q=lambda s ilambda x jlambda y klambda z

$`

逐一对四元数中的各项元素进行缩放即可。

四元数乘法

四元数的乘法是所有元素之前都要运算一遍:

`$begin{align*}

q_1q_2&=(s_1 ix_1 jy_1 kz_1)*(s_2 ix_2 jy_2 kz_2)

&=(s_1s_2-x_1x_2-y_1y_2-z_1z_2)

& i(s_1x_2 s_2x_1 y_1z_2-y_2z_1)

& j(s_1y_2 s_2y_1 x_2z_1-x_1z_2)

& k(s_1z_2 s_2z_1 x_1y_2-x_2y_1)

end{align*}

$`

`$begin{align*}

q_1, q_2&=q_1q_2-q_2q_1

&=(s_1s_2-x_1x_2-y_1y_2-z_1z_2) i(s_1x_2 s_2x_1 y_1z_2-y_2z_1) j(s_1y_2 s_2y_1 x_2z_1-x_1z_2) k(s_1z_2 s_2z_1 x_1y_2-x_2y_1)-(s_2s_1-x_2x_1-y_2y_1-z_2z_1)-i(s_2x_1 s_1x_2 y_2z_1-y_1z_2)-j(s_2y_1 s_1y_2 x_1z_2-x_2z_1)-k(s_2z_1 s_1z_2 x_2y_1-x_1y_2)

&=2i(y_1z_2-y_2z_1) 2j(x_2z_1-x_1z_2) 2k(x_1y_2-x_2y_1)

end{align*}

$`

那么也就是说,这两个四元数q_1,q_2 之间是非对易的,也就是不可交换的。但是,四元数的运算是满足结合律和分配率的

由于上面的这种四元数乘法展开,写起来过于繁杂,我们考虑对其进行一定的简化。如果我们假定2个纯虚数(s=0 ):

`$a=ix_1 jy_1 kz_1

b=ix_2 jy_2 kz_2

$`

其实类似于这种形式的四元数,实际上就是三维空间中的向量,那么这两者的点积和叉积有:

`$acdot b=x_1x_2 y_1y_2 z_1z_2

atimes b=(y_1z_2-y_2z_1)i (z_1x_2-z_2x_1)j (x_1y_2-x_2y_1)k

$`

需要注意的是,这里的叉积是向量叉积,跟四元数中的“虚数单位”相比,最大的一点不同就是:在向量叉积中,itimes i=0 ,但是在四元数的乘法中,itimes i=-1 (非常重要)。

那么在有了以上的两个公式之后,我们就可以对四元数的乘法表示做一个简化:

`$q_1q_2=s_1s_2-acdot b s_ab s_ba atimes b

$`

实四元数和纯四元数

对于一个实四元数而言,就是取x=y=z=0

`$q_r=s

$`

对于一个纯四元数而言,就是取s=0

`$q_i=ix jy kz

$`

四元数共轭

对四元数的所有“虚部”取负数,即是四元数的共轭:

`$q^*=s-ix-jy-kz

$`

单位四元数

四元数的模的定义跟复数是一致的:

`$|q|=sqrt{s^2 x^2 y^2 z^2}=sqrt{qq*}

$`

而单位四元数的定义即是模为1的四元数:

`$s^2 x^2 y^2 z^2=1

$`

如果给定的一个四元数不是单位四元数,那么我们可以对其进行规范化:

`$q'=frac{q}{sqrt{s^2 x^2 y^2 z^2}}

$`

四元数的逆

对于一个单位四元数而言,因为有qq^*=1 ,所以单位四元数的逆就是其共轭四元数。如果是对于更加一般的场景,我们可以这样考虑:

`$q(q^{-1}*|q|^2)=|q|^2

qq^*=|q|^2

q^{-1}=frac{q^*}{|q|^2}

$`

比较特殊地,对于单位四元数q^{-1}=q^*

四元数的二元表示

类似于复数的二元形式,通常一个四元数也可以被表示成如下的二元形式:

`$q=s vhat{q}=s,vhat{q}

$`

其中v=[x,y,z],hat{q}=[i,j,k] 。关于此处的乘法描述,其实有一定的不严谨性,因为它既不是点积,也不是叉积,也不是外积,而是普通的元素乘。这种元素乘的概念在计算机领域是很常用的,但是在数学上其实并不是很常用。在这种二元描述下,四元数的乘法形式会略有调整:

`$q_1q_2=s_1s_2-(v_1hat{q}_1)cdot (v_2hat{q}_2), s_1v_2hat{q}_2 s_2v_1hat{q}_1 (v_1hat{q}_1)times(v_2hat{q}_2)

$`

四元数点积

上面的章节中提到过四元数的普通乘法,但其实四元数也像普通的向量一样可以进行点积运算:

`$q_1cdot q_2=s_1s_2 v_1cdot v_2

$`

这也是受益于四元数的二元表示,使得我们在书写结果的时候可以更加的简练。

四元数的指数

我们先来回顾一下复数z=x iy

的指数计算,根据泰勒展开公式

f(x)=sum_nfrac{f^{(n)}(x_0)}{n!}(x-x_0)^n

(比较特殊地,e^x=sum_{k=0}^inftyfrac{x^k}{k!} )对e^zy=0

处的展开有:

`$begin{align*}

e^{z}&=e^{x iy}=e^xe^{iy}

&=e^xleft(

1 iy-frac{1}{2!}y^2-frac{i}{3!}y^3 frac{1}{4!}y^4 frac{i}{5!}y^5-frac{1}{6!}y^6-frac{i}{7!}y^7 ...

right)

end{align*}

$`

对比一下常用的三角函数的泰勒展开式(相关证明见参考链接2):

`$sin x=x-frac{1}{3!}x^3 frac{1}{5!}x^5-frac{1}{7!}x^7 ...

cos x=1-frac{1}{2!}x^2 frac{1}{4!}x^4-frac{1}{6!}x^6 ...

$`

`$begin{align*}

e^q&=e^{s vhat{q}}

&=e^sleft(

1 vhat{q}-frac{1}{2!}(vhat{q})^2-frac{1}{3!}(vhat{q})^3 frac{1}{4!}(vhat{q})^4 frac{1}{5!}(vhat{q})^5-frac{1}{6!}(vhat{q})^6-frac{1}{7!}(vhat{q})^7 ...

right)

end{align*}

$`

这里有一点不同的是,我们计算四元数的幂次的时候需要谨慎,可以先手动计算一下:

`$begin{align*}

(vhat{q})^2&=0-(vhat{q})cdot (vhat{q}) 0 0 (vhat{q})times(vhat{q})=-|v|^2

(vhat{q})^3&=-|v|^2(vhat{q})

(vhat{q})^4&=|v|^4

(vhat{q})^5&=|v|^4(vhat{q})

(vhat{q})^6&=-|v|^6

(vhat{q})^7&=-|v|^6(vhat{q})

&...

end{align*}

$`

代入四元数的指数部分进行计算可得:

`$begin{align*}

e^q&=e^{s vhat{q}}

&=e^sleft(

1 vhat{q}-frac{1}{2!}|v|^2-frac{1}{3!}|v|^2(vhat{q}) frac{1}{4!}|v|^4 frac{1}{5!}|v|^4(vhat{q})-frac{1}{6!}|v|^6-frac{1}{7!}|v|^6(vhat{q}) ...

right)

&=e^sleft(

cos|v| frac{vhat{q}}{|v|}sin|v|

right)

end{align*}

$`

这就是四元数的指数运算。

四元数的指数表示

区分于上一个章节中的四元数的指数运算,这个章节我们是要用一个指数形式去表示任意给定的一个四元数。因为在上一个章节中我们发现,一个四元数的指数形式是另外一个四元数,因此,理论上说我们可以用一个指数形式来表示任意的一个四元数。我们首先还是参考一下复数的指数表示:

`$z=x iy=sqrt{x^2 y^2}left(frac{x}{sqrt{x^2 y^2}} ifrac{y}{sqrt{x^2 y^2}}right)=sqrt{x^2 y^2}e^{ifrac{y}{|y|} arccosleft(frac{x}{sqrt{x^2 y^2}}right)}

$`

类似地,一个四元数可以表示为:

`$q=s vhat{q}=sqrt{s^2 |v|^2}left(

frac{s}{sqrt{s^2 |v|^2}} frac{vhat{q}}{|v|}frac{|v|}{sqrt{s^2 |v|^2}}

right)=sqrt{s^2 |v|^2}e^{hat{q}frac{v}{|v|} arccosleft(frac{s}{sqrt{s^2 |v|^2}}right)}

$`

比较有意思的是,如果我们取q=s ix jy kz 中的y=0,z=0时,我们发现v=pm|v|,hat{q}=i ,这样一来,四元数的指数表示形式就和复数的指数表示形式完全对应上了。

四元数的对数

在上一个章节中,如果我们把一个四元数表示成一个指数的形式,就会很大程度上方便我们去计算一个四元数q=s vhat{q} 的对数:

`$begin{align*}

log(q)&=logleft(sqrt{s^2 |v|^2}e^{hat{q}frac{v}{|v|} arccosleft(frac{s}{sqrt{s^2 |v|^2}}right)}right)

&=logleft(sqrt{s^2 |v|^2}right) hat{q}frac{v}{|v|} arccosleft(frac{s}{sqrt{s^2 |v|^2}}right)

end{align*}

$`

这样就得到了四元数的对数的二元表示形式。

四元数的幂次

了解了四元数的指数和对数的计算模块之后,我们可以计算一个四元数的幂次。正是由于四元数的指数表示形式,使得我们可以将四元数的幂次简单的转化成乘法的表示形式:

`$q^t=leftsqrt{s^2 |v|^2}e^{hat{q}frac{v}{|v|} arccosleft(frac{s}{sqrt{s^2 |v|^2}}right)}right^t=

left(s^2 |v|^2right)^{frac{t}{2}}e^{hat{q}frac{vt}{|v|} arccosleft(frac{s}{sqrt{s^2 |v|^2}}right)}

$`

那么这就得到了四元数的幂次表达形式。

欧拉角旋转四元数

在上一篇文章中我们提到过,每一个四元数其实都可以对应于三维空间的一个向量旋转,一个四元数q作用在一个空间向量v 上就会旋转得到一个新的空间向量:

`$v'=qvq^*

$`

`$q=left(cosfrac{alpha}{2}-j sinfrac{alpha}{2}right)left(cosfrac{beta}{2} i sinfrac{beta}{2}right)left(cosfrac{gamma}{2} k sinfrac{gamma}{2}right)

$`

关于更多的旋转四元数的内容,可以阅读一下参考链接3中的内容。

向量变换四元数

这个问题的定义是比较清晰的,如果给定空间中的两个不同的向量,能否直接获得这两个向量之间变换的四元数呢?如果用公式来表示就是:已知textbf{v}_1,textbf{v}_2 两个空间向量,求q使得textbf{v}_2=qtextbf{v}_1q^* 。关于这个问题的求解,在参考链接3中也是有介绍的,这里再简单提一下计算方法:

`$textbf{u}=textbf{v}_1timestextbf{v}_2

costheta=frac{textbf{v}_1cdottextbf{v}_2}{|textbf{v}_1||textbf{v}_2|}

q=cosfrac{theta}{2} i sinfrac{theta}{2}textbf{u}cdot i j sinfrac{theta}{2}textbf{u}cdot j k sinfrac{theta}{2}textbf{u}cdot k

$`

这个算法的本质,其实就是先用向量叉乘找到旋转轴,然后计算两个向量之间的夹角,最后再使用四元数的绕旋转轴旋转指定角度的公式计算,就可以得到对应的空间向量变换的四元数。

总结概要

本文主要介绍四元数Quaternion的一些基本运算法则。四元数的概念,更像是复数的一个推广,在图形学和工程学中有大量的应用,在蛋白质结构预测软件AlphaFold和MEGA-Protein中都大量的使用了四元数的计算。而大部分的四元数的教材中写的计算法则,经常把各类乘法混在一起使用,阅读起来非常难受,因此只好自己总结一下四元数的相关运算。并且跟我们所熟悉的复数运算有一定的对比,更加容易去理解四元数的概念。

版权声明

本文首发链接为:https://cloud.tencent.com/developer/article/2134846

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

打赏专用链接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

腾讯云专栏同步:https://cloud.tencent.com/developer/column/91958

CSDN同步链接:https://blog.csdn.net/baidu_37157624?spm=1008.2028.3001.5343

51CTO同步链接:https://blog.51cto.com/u_15561675

参考链接

  1. https://www.qiujiawei.com/understanding-quaternions/
  2. http://www.songho.ca/math/taylor/taylor_tri.html
  3. https://cloud.tencent.com/developer/article/2147861

0 人点赞