• 四元数Quaternion的基本运算


    技术背景

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

    基本运算

    说到四元数,很多人可能会觉得有点陌生,但是如果说复数,很多人就都有学习过。我们一般用z=x+iy这样的形式去定义一个复数(Complex Number),其中x是实部,而y是虚部,i是虚数单位,并且有i2=1这样的特性。并且对于一个虚数而言,如果取自然指数(运算规则为:eiθ=cosθ+i sinθ),还能够得到一个很美的数学公式:eiπ=1,这就是非常著名的欧拉公式。

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

    q=s+ix+jy+kz

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

    i2=j2=k2=ijk=1i×j=k,j×k=i,k×i=jj×i=k,k×j=i,i×k=j

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

    四元数加法

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

    q1+q2=(s1+ix1+jy1+kz1)+(s2+ix2+jy2+kz2)=(s1+s2)+i(x1+x2)+j(y1+y2)+k(z1+z2)

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

    四元数缩放

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

    λq=λs+iλx+jλy+kλz

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

    四元数乘法

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

    q1q2=(s1+ix1+jy1+kz1)(s2+ix2+jy2+kz2)=(s1s2x1x2y1y2z1z2) +i(s1x2+s2x1+y1z2y2z1) +j(s1y2+s2y1+x2z1x1z2) +k(s1z2+s2z1+x1y2x2y1)

    这个运算过程是这样的,我们令q=q1q2=s+ix+jy+kz,那么这个乘法运算最终组成s这个元素的,分别是s1s2,(ix1)(ix2),(iy1)(iy2),(iz1)(iz2)这些项,而i2=j2=k2=1,因此最终得到s=(s1s2x1x2y1y2z1z2)。但是直到这里为止,我们所涉及到的元素乘法只是在“实部”和相同的“虚数单位”之间的运算,如果一旦涉及到不同的“虚数单位”之间的乘法运算,那就要自动转化成向量叉乘,比如ij=ji=k。因此,我们要计算q中的z项的时候,只需要计算s1z2,s2z1,x1y2,x2y1这些项即可,同时注意符号的变换,那么得到的最终的结果就是如上所示。

    需要注意的是,四元数与复数的最大的一点不同,复数乘法是有交换律的,而四元数没有。举个例子说,我们可以计算一下q1,q2的对易:

    [q1,q2]=q1q2q2q1=(s1s2x1x2y1y2z1z2)+i(s1x2+s2x1+y1z2y2z1)+j(s1y2+s2y1+x2z1x1z2)+k(s1z2+s2z1+x1y2x2y1)(s2s1x2x1y2y1z2z1)i(s2x1+s1x2+y2z1y1z2)j(s2y1+s1y2+x1z2x2z1)k(s2z1+s1z2+x2y1x1y2)=2i(y1z2y2z1)+2j(x2z1x1z2)+2k(x1y2x2y1)

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

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

    a=ix1+jy1+kz1b=ix2+jy2+kz2

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

    ab=x1x2+y1y2+z1z2a×b=(y1z2y2z1)i+(z1x2z2x1)j+(x1y2x2y1)k

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

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

    q1q2=s1s2ab+sab+sba+a×b

    实四元数和纯四元数

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

    qr=s

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

    qi=ix+jy+kz

    四元数共轭

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

    q=sixjykz

    单位四元数

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

    |q|=s2+x2+y2+z2=qq

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

    s2+x2+y2+z2=1

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

    q=qs2+x2+y2+z2

    四元数的逆

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

    q(q1|q|2)=|q|2qq=|q|2q1=q|q|2

    比较特殊地,对于单位四元数q1=q

    四元数的二元表示

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

    q=s+vˆq=[s,vˆq]

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

    q1q2=[s1s2(v1ˆq1)(v2ˆq2),s1v2ˆq2+s2v1ˆq1+(v1ˆq1)×(v2ˆq2)]

    四元数点积

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

    q1q2=s1s2+v1v2

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

    四元数的指数

    我们先来回顾一下复数z=x+iy的指数计算,根据泰勒展开公式f(x)=nf(n)(x0)n!(xx0)n(比较特殊地,ex=k=0xkk!)对ezy=0处的展开有:

    ez=ex+iy=exeiy=ex(1+iy12!y2i3!y3+14!y4+i5!y516!y6i7!y7+...)

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

    sin x=x13!x3+15!x517!x7+...cos x=112!x2+14!x416!x6+...

    代入可得:

    ez=exeiy=ex(cos y+i sin y)

    也即,对于一个纯虚数iθ而言,其指数为:eiθ=cosθ+i sinθ。那么类似的,对于一个二元表示的四元数q=s+vˆq有:

    eq=es+vˆq=es(1+vˆq12!(vˆq)213!(vˆq)3+14!(vˆq)4+15!(vˆq)516!(vˆq)617!(vˆq)7+...)

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

    (vˆq)2=0(vˆq)(vˆq)+0+0+(vˆq)×(vˆq)=|v|2(vˆq)3=|v|2(vˆq)(vˆq)4=|v|4(vˆq)5=|v|4(vˆq)(vˆq)6=|v|6(vˆq)7=|v|6(vˆq)...

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

    eq=es+vˆq=es(1+vˆq12!|v|213!|v|2(vˆq)+14!|v|4+15!|v|4(vˆq)16!|v|617!|v|6(vˆq)+...)=es(cos|v|+vˆq|v|sin|v|)

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

    四元数的指数表示

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

    z=x+iy=x2+y2(xx2+y2+iyx2+y2)=x2+y2eiy|y| arccos(xx2+y2)

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

    q=s+vˆq=s2+|v|2(ss2+|v|2+vˆq|v||v|s2+|v|2)=s2+|v|2eˆqv|v| arccos(ss2+|v|2)

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

    四元数的对数

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

    log(q)=log(s2+|v|2eˆqv|v| arccos(ss2+|v|2))=log(s2+|v|2)+ˆqv|v| arccos(ss2+|v|2)

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

    四元数的幂次

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

    qt=[s2+|v|2eˆqv|v| arccos(ss2+|v|2)]t=(s2+|v|2)t2eˆqvt|v| arccos(ss2+|v|2)

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

    欧拉角旋转四元数

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

    v=qvq

    而如果给定了三维空间中的旋转欧拉角,在四元数中就可以表示为相应的旋转四元数。比如绕X轴旋转β角所对应的四元数为:q=cosβ2+i sinβ2,绕Y轴旋转α角所对应的四元数为:q=cosα2j sinα2,绕Z轴旋转γ角所对应的四元数为:q=cosγ2+k sinγ2。而通常使用的ZXY顺规可表示为:

    q=(cosα2j sinα2)(cosβ2+i sinβ2)(cosγ2+k sinγ2)

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

    向量变换四元数

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

    u=v1×v2cosθ=v1v2|v1||v2|q=cosθ2+i sinθ2ui+j sinθ2uj+k sinθ2uk

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

    旋转四元数和变换四元数的不对等场景

    这里为了区分欧拉角旋转的四元数和绕轴旋转的四元数,我们将其分别称呼为旋转四元数与变换四元数。其实要证明二者是不对等的也很容易,只要举出一个例子来证明二者作用的结果不相等即可。其实在参考链接3中已经给出了类似的案例,这里我们再举一个简单例子来进行探讨。首先我们给定一个初始空间向量:

    v1=i

    我们使其先绕Y轴旋转90度,再绕Z轴旋转90度,那么利用四元数进行计算,得到的结果是:

    qrot=(cosγ2+k sinγ2)(cosβ2j sinβ2)v2=qv1q=k

    也就是说,在这个欧拉角对应的旋转变换下,我们将一个向量从X轴正方向变换到了Z轴的正方向上。那么如果我们考虑使用向量绕轴旋转的公式来计算的话:

    u=v1×v2=i×k=jcosθ=v1v2|v1||v2|=0qtrans=cosθ2+i sinθ2ui+j sinθ2uj+k sinθ2uk=22j22

    显然,qrotqtrans,只是在这个案例下有:

    qrotv1qrot=qtransv1qtrans=v2

    我们只需要换一个初始空间向量,比如我们将初始向量设置为Z轴的负方向,即:v1=k,那么再看看两个变换所对应的结果:

    qrotv1qrot=14(1+ij+k)(k)(1i+jk)=jqtransv1qtrans=12(1j)(k)(1+j)=i

    显然这两个变换之后的结果是不同的。其实道理很简单,iqrot的作用下,先绕Y轴转90度,刚好就到了Z轴正方向上,此时再绕Z轴旋转是不会动的。而qtrans,就只是绕Y轴旋转90度的一个操作,因为从客观的变换来说,qrot作用在i上就等价于只绕Y轴旋转了90度。这就是旋转的特殊性,在很多情况下,欧拉角的旋转跟绕轴旋转是不能画上等号的。

    总结概要

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

    版权声明

    本文首发链接为:https://www.cnblogs.com/dechinphy/p/quaternion-calc.html

    作者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://www.cnblogs.com/dechinphy/p/quaternion.html
  • 相关阅读:
    降价背后,函数计算规格自主选配功能揭秘
    点云从入门到精通技术详解100篇-基于补全点云与图像像素级融合的障碍物识别(中)
    Re:从零开始教你使用 Sublime Text
    举个栗子~Minitab 技巧(5):掌握常用快捷键,提高统计分析效率
    动视是否磨灭了暴雪的灵魂?
    iLogtail 2.0 重大升级,端上支持 SPL
    sqlilabs less-32
    什么是视频剪辑SDK?
    第30集丨本来的面目:认识你自己
    Elasticsearch 之 join 关联查询及使用场景
  • 原文地址:https://www.cnblogs.com/dechinphy/p/quaternion-calc.html