在看PhysX源码的时候,看到四元数公式,想知道怎么推导过来的,因为网上一大片帖子都是直接写上这个公式。最主要是纠结公式中角度的一半是如何来的
公式
参考[2] 10.4.3
q=[cos(θ/2),sin(θ/2)n]=[cos(θ/2),sin(θ/2)nx,sin(θ/2)ny,sin(θ/2)nz]
推导
参考[6]直接给出了证明,下面自己推导一遍
三维空间旋转公式
先抛开四元数,我们去求一个三位空间向量绕固定轴旋转之后的向量的公式是什么?也就是参考[2]书中提到的轴-角式旋转。而四元数是跟轴-角式的旋转相关的,先以这个为基础,再去推导四元数的公式会容易理解一些。
和参考[6]一样,用的右手坐标系,主要是用的绘图软件[9],右手坐标系好看点。
设定:
- 任意向量vvv(向量用粗体小写字母表示)
- 绕经过原点的旋转轴uuu=(x,y,z)T
- 右手坐标系,绕向量pmbu从箭头到原点方向逆时针旋转角度θ
-
uuu是单位向量:∥uuu∥=x2+y2+z2=1
为了简单起见,看下图所示

1.向量分解
将vvv分解为平行于uuu的vvv∥,和垂直于uuu的vvv⊥
vvv=vvv∥+vvv⊥
分别旋转这两个分向量,再把最后旋转的两个分量相加,得到旋转后的向量vvv′
vvv′=vvv∥′+vvv⊥′
如下图所示:

根据正交投影公式
vvv∥=uuu.uuuuuu.vvvuuu=(uuu.vvv)uuu(∥uuu∥=1)
因为vvv=vvv∥+vvv⊥,所以
vvv⊥=vvv−vvv∥=vvv−(uuu.vvv)uuu
接下来分别计算~
2.水平方向vvv∥的旋转
因为平行向量vvv∥绕uuu旋转任意角度之后还是自身,所以有:
vvv∥′=vvv∥
3.垂直方向vvv⊥的旋转
三维空间如图所示:

用2D的俯视图,会更容易看到清楚,对应于上图的下面一个虚线的圆

借助一个向量www=uuu×vvv⊥
注意:右手坐标系统,叉乘顺序
∥www∥=∥uuu×vvv⊥∥=∥u∥.∥vvv⊥∥.sin(π/2)=∥vvv⊥∥
将vvv⊥′分解到www和vvv⊥上,可以简单算出来下面的等式
vvv⊥′=vvvv′+vvvw′=cos(θ)vvv⊥+sin(θ)www=cos(θ)vvv⊥+sin(θ)(uuu×vvv⊥)
书上说提到用一点三角学的公式,其实主要是下面的这个三个向量的模都相等。按照投影或者分解,本应该是vvvv′=cos(θ)vvv⊥′和vvvw′=sin(θ)vvv⊥′。简单换算一下就是上面的等式了
vvvv′vvvw′=cos(θ)vvv⊥′=cos(θ)∥vvv⊥∥vvv⊥∥vvv⊥′∥=cos(θ)vvv⊥=sin(θ)vvv⊥′=sin(θ)∥www∥www∥vvv⊥′∥=sin(θ)www=sin(θ)(uuu×vvv⊥)
4.向量vvv的旋转公式
再由旋转后的向量组合起来得到
vvv′=vvv∥′+vvv⊥′=vvv∥+cos(θ)vvv⊥+sin(θ)(uuu×vvv⊥)
因为叉乘遵守分配律,有
uuu×vvv⊥=uuu×(vvv−vvv∥)=uuu×vvv−uuu×vvv∥=uuu×vvv(uuu平行于vvv∥)
最后,将vvv∥=(uuu.vvv).uuu和vvv⊥=vvv−(uuu.vvv).uuu代入,得到
vvv′=(uuu.vvv).uuu+cos(θ)(vvv−(uuu.vvv).uuu)+sin(θ)(uuu×vvv)=cos(θ)vvv+(1−cos(θ))(uuu.vvv).uuu+sin(θ)(uuu×vvv)
注意这个公式,参考[6]中叫做叫做「Rodrigues’ Rotation Formula」
四元数的3D旋转公式
接下来,我们要慢慢推导四元数的公式了,那么先要搞清楚四元数喝旋转之前的关系。下面的内容把四元数相关性质省略了,想看的话,看参考[6]或者其他书籍吧。
参考上一节,还是走相同的流程:三维空间旋转公式,也是分解向量v。但是,这次不是用的向量的三维表示,而是再上一个维度,用四元数去表示。高一维度能完全秒杀低一维度的生物,所以想想还是挺厉害的。
先放两个引理,后面还会遇到几个引理,都是为了方便推导公式:
-
引理一 纯四元数
简单来讲呢?现在要用一个四维的向量来表示空间的旋转,表示方法就有了一些对应的变化
如果一个四元数能写成这样的形式,
v=[0,vvv]
那么我们称v为一个纯四元数
注意:这里用非粗体字母表示四元数
直接列出来,如果看推理,参考[6]
对任意的四元数q1=[s,vvv],q2=[t,uuu],q1q2的结果是
q1q2=[st−vvv.uuu,suuu+tvvv+vvv×uuu]
按照引理一,列出所有的四元数表示
v=[0,vvv]v⊥=[0,vvv⊥]v∥=[0,vvv∥]u=[0,uuu]v′=[0,vvv′]v⊥′=[0,vvv⊥′]v∥′=[0,vvv∥′]
并且有:
v=v⊥+v∥v′=v⊥′+v∥′
1.水平方向v∥的旋转
同理,这个旋转没有发生任何变化
v∥′=v∥
2.垂直方向v⊥的旋转
之前推导有
vvv⊥′=cos(θ)vvv⊥+sin(θ)(uuu×vvv⊥)
把向量换成四元数,就可以有四元数表示的公式了,但是向量的叉乘怎么和四元数什么乘积对应起来呢?看下面,可以看到是Graßmann 积
根据引理二的Graßmann 积,假设有两个四元数v=[0,vvv],u=[0,uuu],那么vu=[−vvv.uuu,vvv×uuu]。由此,那么可以算出来推理一中的四元数
uv⊥=[−uuu.vvv⊥,uuu×vvv⊥]=[0,uuu×vvv⊥](uuu.vvv⊥=0)
结果还是一个四元数!所以,上面向量vvv⊥′的表示,用四元数表示为:
v⊥′=cos(θ)v⊥+sin(θ)(uv⊥)
四元数遵循乘法分配律,得到
v⊥′=cos(θ)v⊥+sin(θ)(uv⊥)=(cos(θ)+sin(θ)u)v⊥
接下来做一些数学上常用的技巧。
如果将(cos(θ)+sin(θ)u)看成一个旋转四元数,我们就能将旋转写成四元数的乘积了。到此为止,我们已经将旋转与四元数的积联系起来了
令:q=cos(θ)+sin(θ)u,得到
v⊥′=qv⊥
对q进行变形
q=cos(θ)+sin(θ)u=[cos(θ,000)]+[0,sin(θ)uuu]=[cos(θ),sin(θ)uuu]
到这里,就和最开始的公式有点像了,但是还差个2倍的关系
注意:这里对一个向量vvv⊥绕旋转轴uuu旋转左乘四元数q就可以了。但是,这里的一个前提条件是向量和旋转轴垂直的情况
所以,接下来,我们再回到一般情况
3.四元数v的旋转公式
回到一般情况
v′=v⊥′+v∥′=v∥+qv⊥
这里,我把步骤写下来,完全参考[6],对于中间的证明,可以翻阅参考[6],非常的详细
接下来就是等式各种演变了
如果q=[cos(θ),sin(θ)uuu],如果uuu为单位向量,q2=qq=[cos(2θ),sin(2θ)uuu]
我要找的2倍角出现了,有点苗头了.
v′=v⊥′+v∥′=v∥+qv⊥=1.v∥+qv⊥=pp−1v∥+ppv⊥(令q=p2,则p=[cos(1/2θ),sin(1/2θ)uuu])
因为p也是单位四元数,即∥p∥=1,则有
p−1=p⋆
继续做等式变换
v′=pp−1v∥+ppv⊥=pp⋆v∥+ppv⊥
假设v∥=[0,vvv∥]是一个纯四元数,而q=[α,βuuu],其中uuu是一个单位向量,α,β∈R。在这种情况下,如果vvv∥平行于uuu,那么qv∥=v∥q
假设 v⊥=[0,vvv⊥] 是一个纯四元数,而q=[α,βuuu],其中 uuu 是一个单位向量,α,β∈R.在这种条件下,如果 vvv⊥ 正交于 uuu,那么 qv⊥=v⊥q⋆
则等式可以继续化简
v′=pp⋆v∥+ppv⊥=pv∥p⋆+pv⊥p⋆=p(v∥+v⊥)p⋆
可以看到(v∥+v⊥)=v,则
v′=pvp⋆=pvp−1
其中,q=[cos(θ/2),sin(θ/2)uuu]
小结
- 可以看到如果用四元数去旋转一个向量的话,并不是四元数左乘或者右乘一次就行了,而是后面还要乘以一个四元数的逆
到此,这个公式的证明就结束了,参考[6]说四元数的表示和3D旋转向量表示的「Rodrigues’ Rotation Formula」公式是等价的,虽然没有证明,但是其实证明就是各种三角函数的带入。而且文章中也给出了一个关键的叉乘公式,下面自己就手动证明一下,可以跳过。
两种公式等价证明
为了书写方便,先假设c=cos(θ/2),s=sin(θ/2)。已知v=[0,vvv],q=[c,suuu],Graßmann 积算前面两个
qv=[0−suuu.vvv,cvvv+000+suuu×vvv]=[−suuu.vvv,cvvv+suuu×vvv]
按照四元数性质,可以很容易知道q−1=q⋆=[c,−suuu],继续使用Graßmann 积推导公式
qvq−1=[−scuuu.vvv−(cvvv+suuu×vvv).(−suuu),−suuu.vvv.(−suuu)+c(cvvv+suuu×vvv)+(cvvv+suuu×vvv)×(−suuu)]
分两部算逗号前面的,这样会清洗一点,不然公式写的老长
-
1.逗号前面四元数的实数部分
=−scuuu.vvv−(cvvv+suuu×vvv).(−suuu)=−scuuu.vvv+scvvv.uuu−suuu×vvv.(−suuu)=s2uuu×vvv.uuu=0(向量点积满足交换律:aaa.bbb=bbb.aaa)(uuu×vvv和uuu垂直)
-
2.逗号后面四元数的虚数部分
=−suuu.vvv.(−suuu)+c(cvvv+suuu×vvv)+(cvvv+suuu×vvv)×(−suuu)=s2(uuu.vvv)uuu+c2vvv+csuuu×vvv−csvvv×uuu−s2uuu×vvv×uuu=s2(uuu.vvv)uuu+c2vvv+2csuuu×vvv−s2uuu×vvv×uuu(向量叉乘:aaa×bbb=−bbb×aaa)=s2(uuu.vvv)uuu+c2vvv+2csuuu×vvv−s2[(uuu.uuu)vvv−(uuu.vvv)uuu][(aaa×bbb)×ccc=(aaa.ccc)bbb−(aaa.bbb)ccc]=s2(uuu.vvv)uuu+s2(uuu.vvv)uuu+c2vvv−s2vvv+2csuuu×vvv=cos(θ)vvv+(1−cos(θ))(uuu.vvv)uuu+sin(θ)uuu×vvv(三角函数两倍角公式)
-
3.再合在一起
qvq−1=[0,cos(θ)vvv+(1−cos(θ))(uuu.vvv)uuu+sin(θ)uuu×vvv]
这样就完成证明了
参考
[1]Maths - AxisAngle to Quaternion
[2]3D数学基础图形与游戏开发
[4]四元数与欧拉角(RPY角)的相互转换
[5]Converting to Euler & Tait-Bryan
[6]四元数旋转公式推导
[7]eater.net
[8]四元数与三位旋转
[9]https://www.geogebra.org/classic
[10]geogebra