前言
最近在学习计算机图形学中的物理仿真算法,发现里面很多的涉及到物体旋转的地方都会使用四元数去进行运算,因此便希望能够从解析几何的角度去理解四元数和三维旋转的关系。网上的很多有关四元数的资料都是直接扔出四元数的定义和计算公式,然后说四元数能够解决万向节死锁(Gimbal Lock)问题,也有一些视频资料从很抽象的角度去解释和理解四元数,让人很难形象地看清四元数是如何表示旋转这种变化的。
在翻阅的诸多资料中,以下两篇资料让我受益匪浅:
第一篇是1998年的一篇关于四元数的论文 Quaternions, Interpolation and Animation ,该论文详细的介绍了四元数的来源、旋转的表示方式、四元数的代数运算、四元数和旋转的关系和推导过程、四元数的优缺点、四元数的插值等;
第二篇是GitHub上关于四元数的一篇教程,对应的GitHub仓库还给出了一些Demo,这篇教程在四元数的代数运算以及和三维旋转的关系的阐述上和上一篇类似,另外还从复数与二维旋转的关系出发,让人更容易理解四元数。
我的这篇博文实际上是一篇学习笔记,以便于我理解和记忆的方式去总结四元数的几何意义,同时方便我以后在需要用到的时候能快速查阅。因此,一方面我主要会以第二篇参考资料为基础去进行总结,另一方面后面用到的一部分附图会直接使用资料中的附图(在图注中会说明),特此声明,仅做学习用途。
三维旋转的表示方法
我们的三维旋转的参考点往往都是原点,参考轴往往都是过原点的一条向量,这么做是因为其他的旋转形式都可以先平移到原点处再进行旋转再平移回去,因此这么做能够更加方便进行定义和推导,同时不影响实际运用。
欧拉角
欧拉角是一种最为形象的表示旋转的方法,它使用三个自由度 ( θ x , θ y , θ z ) (\theta_x,\theta_y,\theta_z) (θx,θy,θz) 分别表示物体绕着 x x x 轴、 y y y 轴和 z z z 轴旋转的角度。我们在《航空航天概论》中接触到的俯仰(pitch)、偏航(yaw)和滚转(roll)其实也是用欧拉角表示的旋转变换。
欧拉角虽然非常直观,但是在使用过程中需要定义旋转的顺序,比如以 x − y − z x-y-z x−y−z 的顺序进行旋转,否则不同顺序将会得到不同的结果,另外好像还有内旋和外旋的区别。
从欧拉角旋转的顺序依赖可以隐约看出,当旋转过程中某两个旋转轴重合在一起时,会造成旋转自由度缺失,这就是万向节死锁(Gimbal Lock)问题,具体的解释可以参考这篇文章 。
旋转矩阵
用旋转矩阵表示旋转变换就更多的是一种代数形式,说明绕着原点的旋转也是一种线性变换,很难直接从旋转矩阵看出其表达的几何意义。旋转矩阵其实就是用矩阵的方式去表示欧拉角这种旋转变换,假设旋转的欧拉角为
(
θ
x
,
θ
y
,
θ
z
)
(\theta_x,\theta_y,\theta_z)
(θx,θy,θz),那么绕
x
x
x 轴、
y
y
y 轴和
z
z
z 轴的旋转矩阵分别表示为
R
x
=
[
1
0
0
0
cos
θ
x
sin
θ
x
0
−
sin
θ
x
cos
θ
x
]
,
R
y
=
[
cos
θ
y
0
−
sin
θ
y
0
1
0
sin
θ
y
0
cos
θ
y
]
,
R
z
=
[
cos
θ
z
sin
θ
z
0
−
sin
θ
z
cos
θ
z
0
0
0
1
]
,
R_x= \left[\begin{matrix} 1&0&0\\0&\cos\theta_x & \sin\theta_x\\0&-\sin\theta_x &\cos\theta_x \end{matrix}\right] , R_y= \left[\begin{matrix} \cos\theta_y&0&-\sin\theta_y\\0&1&0\\ \sin\theta_y&0&\cos\theta_y \end{matrix}\right] , R_z= \left[\begin{matrix} \cos\theta_z&\sin\theta_z&0\\-\sin\theta_z&\cos\theta_z&0\\0&0&1 \end{matrix}\right] ,
Rx=⎣⎡1000cosθx−sinθx0sinθxcosθx⎦⎤,Ry=⎣⎡cosθy0sinθy010−sinθy0cosθy⎦⎤,Rz=⎣⎡cosθz−sinθz0sinθzcosθz0001⎦⎤,
寻常以
x
−
y
−
z
x-y-z
x−y−z 的顺序进行旋转的旋转矩阵
R
=
R
z
R
y
R
x
R=R_zR_yR_x
R=RzRyRx 。
三维向量 v \boldsymbol{v} v 在旋转矩阵 R R R 的作用下会变成 v ′ = R v \boldsymbol{v}'=R\boldsymbol{v} v′=Rv,几何角度的旋转变换对应着欧拉角表示的变换。
实际的使用中往往用 4 × 4 4\times4 4×4 的矩阵同时包含旋转和平移操作,可以看到旋转矩阵表示的旋转变换会占用更多的存储空间。
轴-角的向量表示法
著名的罗德里格旋转公式(Rodrigues’ Rotation Formula):
v
′
=
cos
θ
v
+
(
1
−
cos
θ
)
(
u
⋅
v
)
u
+
sin
θ
(
u
×
v
)
(1)
\boldsymbol{v}'=\cos\theta\boldsymbol{v}+(1-\cos\theta)(\boldsymbol{u}\cdot\boldsymbol{v})\boldsymbol{u}+\sin\theta(\boldsymbol{u}\times\boldsymbol{v}) \tag{1}
v′=cosθv+(1−cosθ)(u⋅v)u+sinθ(u×v)(1)
表示的是将向量
v
\boldsymbol{v}
v 绕着过原点的旋转轴——单位向量
u
\boldsymbol{u}
u 旋转
θ
\theta
θ 角度会得到什么向量。

这里描述的旋转变换涉及到旋转轴和旋转角度 { u , θ } \{\boldsymbol{u},\theta\} {u,θ} ,因为 u \boldsymbol{u} u 只表示一个方向,三维空间中表示方向只需要两个自由度,因此这种旋转变换和欧拉角一样也是三个自由度的。从代数角度解释,单位向量 u \boldsymbol{u} u 说明其模长为 1 1 1,因此 u \boldsymbol{u} u 的三个分量实际上只有两个自由度。
为了后面的四元数做铺垫,这里简单地证明一下罗德里格旋转公式:

我们把待旋转向量
v
\boldsymbol{v}
v 分解为平行和垂直于旋转轴
u
\boldsymbol{u}
u 的两个向量
v
∥
\boldsymbol{v}_{\parallel}
v∥ 和
v
⊥
\boldsymbol{v}_{\bot}
v⊥,那么有:
v
∥
=
(
u
⋅
v
)
u
v
⊥
=
v
−
(
u
⋅
v
)
u
(2)
\begin{aligned} \boldsymbol{v}_{\parallel}&=(\boldsymbol{u}\cdot\boldsymbol{v})\boldsymbol{u} \\ \boldsymbol{v}_{\bot}&=v-(\boldsymbol{u}\cdot\boldsymbol{v})\boldsymbol{u} \end{aligned} \tag{2}
v∥v⊥=(u⋅v)u=v−(u⋅v)u(2)
假设这两个向量旋转之后的向量分别为
v
∥
′
\boldsymbol{v}_{\parallel}'
v∥′ 和
v
⊥
′
\boldsymbol{v}_{\bot}'
v⊥′,那么向量
v
\boldsymbol{v}
v 旋转之后的向量
v
′
=
v
∥
′
+
v
⊥
′
(3)
\boldsymbol{v}'=\boldsymbol{v}_{\parallel}'+\boldsymbol{v}_{\bot}' \tag{3}
v′=v∥′+v⊥′(3)
我们首先考虑平行于
u
\boldsymbol{u}
u 的分量
v
∥
\boldsymbol{v}_{\parallel}
v∥ 的旋转,显然可以发现它旋转之后仍然保持不变,即
v
∥
′
=
v
∥
(4)
\boldsymbol{v}_{\parallel}'=\boldsymbol{v}_{\parallel} \tag{4}
v∥′=v∥(4)
然后考虑垂直于
u
\boldsymbol{u}
u 的分量
v
⊥
\boldsymbol{v}_{\bot}
v⊥ 的旋转,令
w
=
u
×
v
⊥
\boldsymbol{w}=\boldsymbol{u}\times\boldsymbol{v}_{\bot}
w=u×v⊥,则分量
v
⊥
\boldsymbol{v}_{\bot}
v⊥ 的旋转是在
w
\boldsymbol{w}
w 和
v
⊥
\boldsymbol{v}_{\bot}
v⊥ 确定的平面上进行的,这里
w
\boldsymbol{w}
w 和
v
⊥
\boldsymbol{v}_{\bot}
v⊥ 垂直且两者模长相等。有了以上的确定平面,我们可以很容易地计算出
v
⊥
′
=
cos
θ
v
⊥
+
sin
θ
(
u
×
v
⊥
)
(5)
\boldsymbol{v}_{\bot}'=\cos\theta \boldsymbol{v}_{\bot}+\sin\theta(\boldsymbol{u}\times \boldsymbol{v}_{\bot}) \tag{5}
v⊥′=cosθv⊥+sinθ(u×v⊥)(5)
将公式 (4)(5)(2) 带入公式 (3) 就可以得到公式 (1) 的结论:
v
′
=
cos
θ
v
+
(
1
−
cos
θ
)
(
u
⋅
v
)
u
+
sin
θ
(
u
×
v
)
(1)
\boldsymbol{v}'=\cos\theta\boldsymbol{v}+(1-\cos\theta)(\boldsymbol{u}\cdot\boldsymbol{v})\boldsymbol{u}+\sin\theta(\boldsymbol{u}\times\boldsymbol{v})\tag{1}
v′=cosθv+(1−cosθ)(u⋅v)u+sinθ(u×v)(1)
随后引入了四元数的定义之后,可以发现四元数可以非常优美地去计算上述的旋转过程。
四元数
据说四元数是哈密顿于 1843 年在玻洛汉姆桥突然灵光一现想到的,不论之后四元数被怎么称赞或诟病,不论四元数在数学以及量子力学中有怎样的意义,总之现在四元数在图形学的一些分支上运用得挺广泛的。
定义
四元数
q
∈
H
q\in \mathbb{H}
q∈H 写作以下形式
q
=
a
+
b
i
+
c
j
+
d
k
,
(
a
,
b
,
c
,
d
∈
R
)
q=a+bi+cj+dk, \ \ (a,b,c,d\in\mathbb{R})
q=a+bi+cj+dk, (a,b,c,d∈R)
其中
i
2
=
j
2
=
k
2
=
i
j
k
=
−
1
i^2=j^2=k^2=ijk=-1
i2=j2=k2=ijk=−1 (由这个还可以推导出
i
j
=
k
,
j
k
=
i
,
k
i
=
j
ij=k, jk=i,ki=j
ij=k,jk=i,ki=j) 。它有一个实部和三个虚部,因此也经常将其表示为实部标量和虚部向量的有序对形式
q
=
[
s
,
v
]
,
(
s
=
a
,
v
=
[
b
c
d
]
,
a
,
b
,
c
,
d
∈
R
)
q=[s,\boldsymbol{v}], \ \ (s=a,\boldsymbol{v}=\left[\begin{matrix}b\\c\\d\end{matrix}\right], \ a,b,c,d\in\mathbb{R})
q=[s,v], (s=a,v=⎣⎡bcd⎦⎤, a,b,c,d∈R)
接下来说一些有关四元数的常见的定义:
-
模长 ∣ ∣ q ∣ ∣ = a 2 + b 2 + c 2 + d 2 = s 2 + v ⋅ v ||q||=\sqrt{a^2+b^2+c^2+d^2}=\sqrt{s^2+\boldsymbol{v}\cdot\boldsymbol{v}} ∣∣q∣∣=a2+b2+c2+d2=s2+v⋅v
-
加减法: q 1 ± q 2 = [ s 1 ± s 2 , v 1 ± v 2 ] q_1\pm q_2=[s_1\pm s_2,\boldsymbol{v}_1\pm \boldsymbol{v}_2] q1±q2=[s1±s2,v1±v2]
-
标量乘法: α q = q α = [ α s , α v ] \alpha q=q\alpha=[\alpha s,\alpha\boldsymbol{v}] αq=qα=[αs,αv]
-
四元数乘法: q 1 q 2 = [ s 1 s 2 − v 1 ⋅ v 2 , s 1 v 2 + s 2 v 1 + v 1 × v 2 ] q_1q_2=[s_1s_2-\boldsymbol{v}_1\cdot\boldsymbol{v}_2, \ s_1\boldsymbol{v}_2+s_2\boldsymbol{v}_1+\boldsymbol{v}_1\times\boldsymbol{v}_2] q1q2=[s1s2−v1⋅v2, s1v2+s2v1+v1×v2] ,四元数乘法不满足交换律,满足分配率和结合律
-
纯四元数: v = [ 0 , v ] v=[0,\boldsymbol{v}] v=[0,v],也就是只有虚部的四元数,一般将三维向量转换为四元数就会变成纯四元数
- 纯四元数 u = [ 0 , u ] u=[0,\boldsymbol{u}] u=[0,u] 和 v = [ 0 , v ] v=[0,\boldsymbol{v}] v=[0,v] 的乘积 u v = [ − u ⋅ v , u × v ] uv=[-\boldsymbol{u}\cdot\boldsymbol{v},\boldsymbol{u}\times\boldsymbol{v}] uv=[−u⋅v,u×v]
-
共轭:四元数 q = [ s , v ] q=[s,\boldsymbol{v}] q=[s,v] 的共轭 q ∗ = [ s , − v ] q^*=[s,-\boldsymbol{v}] q∗=[s,−v]
- q q ∗ = q ∗ q = [ s 2 + v ⋅ v , 0 ] = ∣ ∣ q ∣ ∣ 2 qq^*=q^*q=[s^2+\boldsymbol{v}\cdot\boldsymbol{v}, \boldsymbol{0}]=||q||^2 qq∗=q∗q=[s2+v⋅v,0]=∣∣q∣∣2
-
逆:四元数 q = [ s , v ] q=[s,\boldsymbol{v}] q=[s,v] 的逆 q − 1 q^{-1} q−1 满足 q q − 1 = 1 qq^{-1}=1 qq−1=1 ,这里我看的资料中都没有提到,但我觉得有必要说明一下四元数中的单位元 1 1 1 在我看来可以理解为标量 1 1 1,也可以理解为四元数 [ 1 , 0 ] [1,\boldsymbol{0}] [1,0],这两者应该是等价的
- q − 1 = q ∗ ∣ ∣ q ∣ ∣ 2 q^{-1}=\frac{q^*}{||q||^2} q−1=∣∣q∣∣2q∗
- 单位四元数 q − 1 = q ∗ q^{-1}=q^* q−1=q∗
从三维旋转到四元数
首先明确一点,四元数描述的三维旋转是轴-角式的,因此会用到轴-角的向量表示法这个部分的 (1)~(5) 公式,这里规定上述公式中向量变为四元数为纯四元数,表示方法为把粗体改成非粗体,例如向量 v ⊥ \boldsymbol{v}_{\bot} v⊥ 对应的四元数 v ⊥ = [ 0 , v ⊥ ] v_{\bot}=[0,\boldsymbol{v}_{\bot}] v⊥=[0,v⊥] ,因此也存在 v = v ∥ + v ⊥ v=v_{\parallel}+v_{\bot} v=v∥+v⊥ 。
这里我们应该可以大致知道四元数如何对向量进行一个旋转变换:首先把一个待旋转向量变成纯四元数,然后用一个表示旋转的四元数去和纯四元数做某种运算,得到了一个新的纯四元数,把新的纯四元数的虚部拿出来变成一个向量,就得到了旋转之后的向量。
接下来同样分别讨论 v ∥ v_{\parallel} v∥ 和 v ⊥ v_{\bot} v⊥ 的旋转公式:
首先同样可以很显然地得到
v
∥
′
=
v
∥
(6)
v_{\parallel}'=v_{\parallel} \tag{6}
v∥′=v∥(6)
然后讨论正交于(垂直于)旋转轴的
v
⊥
v_{\bot}
v⊥ 的旋转公式,我们再一次列出之前推导出来的公式
v
⊥
′
=
cos
θ
v
⊥
+
sin
θ
(
u
×
v
⊥
)
(5)
\boldsymbol{v}_{\bot}'=\cos\theta \boldsymbol{v}_{\bot}+\sin\theta(\boldsymbol{u}\times \boldsymbol{v}_{\bot})\tag{5}
v⊥′=cosθv⊥+sinθ(u×v⊥)(5)
将公式 (5) 涉及到的三个向量写成纯四元数的形式
v
⊥
′
=
[
0
,
v
⊥
′
]
v_{\bot}'=[0,\boldsymbol{v}_{\bot}']
v⊥′=[0,v⊥′],
u
=
[
0
,
u
]
u=[0,\boldsymbol{u}]
u=[0,u],
v
⊥
=
[
0
,
v
⊥
]
v_{\bot}=[0,\boldsymbol{v}_{\bot}]
v⊥=[0,v⊥] ,根据纯四元数的乘积形式,我们可以得到
u
v
⊥
=
[
−
u
⋅
v
⊥
,
u
×
v
⊥
]
=
[
0
,
u
×
v
⊥
]
(7)
uv_{\bot} = [-\boldsymbol{u}\cdot\boldsymbol{v}_{\bot},\boldsymbol{u}\times\boldsymbol{v}_{\bot}] =[0,\boldsymbol{u}\times\boldsymbol{v}_{\bot}] \tag{7}
uv⊥=[−u⋅v⊥,u×v⊥]=[0,u×v⊥](7)
也是一个纯四元数!因此结合公式 (5)(7) 我们可以得到
v
⊥
v_{\bot}
v⊥ 的旋转公式的四元数形式
v
⊥
′
=
cos
θ
v
⊥
+
sin
θ
(
u
v
⊥
)
=
(
cos
θ
+
sin
θ
u
)
v
⊥
=
[
cos
θ
,
sin
θ
u
]
v
⊥
(8)
\begin{aligned} v_{\bot}'&=\cos\theta v_{\bot}+\sin\theta(uv_{\bot}) \\ &=(\cos\theta+\sin\theta u)v_{\bot} \\ &=[\cos\theta,\sin\theta \boldsymbol{u}]v_{\bot} \end{aligned} \tag{8}
v⊥′=cosθv⊥+sinθ(uv⊥)=(cosθ+sinθu)v⊥=[cosθ,sinθu]v⊥(8)
结合 (6)(8) 我们可以得到一般情况下的四元数旋转公式
v
′
=
v
∥
+
[
cos
θ
,
sin
θ
u
]
v
⊥
(9)
v'=v_{\parallel}+[\cos\theta,\sin\theta \boldsymbol{u}]v_{\bot} \tag{9}
v′=v∥+[cosθ,sinθu]v⊥(9)
接下来将会对公式 (9) 进行非常精彩的化简,不过在化简之前,先引入三个引理:
引理1:如果 q = [ cos θ , sin θ u ] q=[\cos\theta,\sin\theta\boldsymbol{u}] q=[cosθ,sinθu],且 u \boldsymbol{u} u 是单位向量,那么 q 2 = [ cos 2 θ , sin 2 θ u ] q^2=[\cos2\theta,\sin2\theta\boldsymbol{u}] q2=[cos2θ,sin2θu] 。
我们观察公式 (8) 的最后一行可以发现,其实如果一个向量垂直于旋转轴,那么对它做旋转的过程可以等价于左乘一个表示旋转的四元数 q q q,所以左乘 q 2 q^2 q2 就等价于同一个角度旋转两次,这就是这个引理表达的意思,当然用四元数乘法的定义也可以很方便的证明这个引理。
引理2: v = [ 0 , v ] v=[0,\boldsymbol{v}] v=[0,v] 是个纯四元数, q = [ α , β u ] q=[\alpha,\beta\boldsymbol{u}] q=[α,βu],其中 u \boldsymbol{u} u 是个单位向量,如果向量 v \boldsymbol{v} v 平行于向量 u \boldsymbol{u} u ,那么 q v = v q qv=vq qv=vq
引理3: v = [ 0 , v ] v=[0,\boldsymbol{v}] v=[0,v] 是个纯四元数, q = [ α , β u ] q=[\alpha,\beta\boldsymbol{u}] q=[α,βu],其中 u \boldsymbol{u} u 是个单位向量,如果向量 v \boldsymbol{v} v 垂直于向量 u \boldsymbol{u} u ,那么 q v = v q ∗ qv=vq^* qv=vq∗
引理2 和引理3 都可以用定义很快证明出来,这里不详细展开。
令
q
=
[
cos
θ
,
sin
θ
u
]
q=[\cos\theta,\sin\theta\boldsymbol{u}]
q=[cosθ,sinθu],
p
=
[
cos
1
2
θ
,
sin
1
2
θ
u
]
p=[\cos\frac{1}{2}\theta,\sin\frac{1}{2}\theta\boldsymbol{u}]
p=[cos21θ,sin21θu],根据引理1可得,
q
=
p
2
q=p^2
q=p2,则公式 (9) 可以变形为
v
′
=
1
⋅
v
∥
+
q
v
⊥
=
p
p
−
1
v
∥
+
p
p
v
⊥
(10)
\begin{aligned} v'&=1\cdot v_{\parallel} + qv_{\bot} \\ &=pp^{-1}v_{\parallel}+ppv_{\bot} \\ \end{aligned} \tag{10}
v′=1⋅v∥+qv⊥=pp−1v∥+ppv⊥(10)
这里
p
p
p 是一个单位四元数,因此
p
−
1
=
p
∗
p^{-1}=p^*
p−1=p∗,带入公式 (10) 同时综合考虑引理 2 和引理 3,我们可以得到
v
′
=
p
p
∗
v
∥
+
p
p
v
⊥
=
p
v
∥
p
∗
+
p
v
⊥
p
∗
=
p
(
v
∥
+
v
⊥
)
p
∗
=
p
v
p
∗
(11)
\begin{aligned} v'&=pp^*v_{\parallel}+ppv_{\bot} \\ &=pv_{\parallel}p^*+pv_{\bot}p^* \\ &=p(v_{\parallel}+v_{\bot})p^* \\ & = pvp^* \end{aligned} \tag{11}
v′=pp∗v∥+ppv⊥=pv∥p∗+pv⊥p∗=p(v∥+v⊥)p∗=pvp∗(11)
至此,轴角式的三维旋转直接演变成了四元数的运算,最终得到了无比简单的旋转公式。
三维旋转公式的四元数形式
对于任意向量
v
\boldsymbol{v}
v 和单位向量定义的旋转轴
u
\boldsymbol{u}
u,
v
\boldsymbol{v}
v 绕着
u
\boldsymbol{u}
u 旋转
2
θ
2\theta
2θ 角得到的向量
v
′
\boldsymbol{v}'
v′ 可以通过四元数乘法获得:令四元数
v
=
[
0
,
v
]
v=[0,\boldsymbol{v}]
v=[0,v],单位四元数
q
=
[
cos
θ
,
sin
θ
u
]
q=[\cos\theta,\sin\theta\boldsymbol{u}]
q=[cosθ,sinθu],那么
v
′
=
q
v
q
∗
=
q
v
q
−
1
(12)
v'=qvq^*=qvq^{-1} \tag{12}
v′=qvq∗=qvq−1(12)
其中
v
′
v'
v′ 将会是一个纯四元数,将其虚部取出得到旋转后的向量
v
′
\boldsymbol{v}'
v′ 。
结合三维旋转公式的向量形式(罗德里格旋转公式)和四元数形式,我们应该得到
q
v
q
∗
=
[
0
,
cos
θ
v
+
(
1
−
cos
θ
)
(
u
⋅
v
)
u
+
sin
θ
(
u
×
v
)
]
(13)
qvq^*=[0,\cos\theta\boldsymbol{v}+(1-\cos\theta)(\boldsymbol{u}\cdot\boldsymbol{v})\boldsymbol{u}+\sin\theta(\boldsymbol{u}\times\boldsymbol{v})] \tag{13}
qvq∗=[0,cosθv+(1−cosθ)(u⋅v)u+sinθ(u×v)](13)
四元数旋转的复合
对于四元数 q 1 , q 2 q_1,q_2 q1,q2,有 ( q 1 q 2 ) ∗ = q 2 ∗ q 1 ∗ (q_1q_2)^*=q_2^*q_1^* (q1q2)∗=q2∗q1∗,因此四元数的复合可以先把单位四元数相乘,然后再进行旋转。
单位四元数的乘积仍然是单位四元数。