注:本文为 “三维空间刚体运动” 相关合辑。
图片清晰度受引文原图所限。
略作重排,如有内容异常,请看原文。
三维空间刚体运动 1:旋转矩阵与变换矩阵(详解加代码示例)
龙焰智能 于 2024-07-09 16:53:19 修改
序
本系列文章参照高翔老师《视觉 SLAM 十四讲:从理论到实践》,系统讲解三维空间刚体运动的相关理论,为读者构建扎实的数学基础。
在正式讲解内容前,分享学习体会如下:此前学习 SLAM 相关知识时,因前期基础概念理解不透彻,推进至第六讲时被迫中断;在完成强化学习相关内容的学习后,重新沉下心来研读 SLAM,方才取得进展。因此建议学习 SLAM 的读者:高翔博士在书中已涵盖知识点,仅表述较为精简。笔者反复研读第三、四讲共计四次,方能形成系统理解。由此可见,学习 SLAM 的关键在于温故知新,持续总结梳理,将前后关联的知识点融会贯通,方可理解后续进阶内容。
本文首先介绍向量及其坐标表示,以及向量间的基本运算;其次,采用欧式变换描述坐标系间的运动关系,该变换由旋转与平移两部分构成,其中旋转通过旋转矩阵 S O ( 3 ) SO (3) SO(3) 描述,平移则直接由 R 3 \mathbb {R}^3 R3 空间中的向量描述;最后,将旋转与平移整合至同一矩阵中,形成变换矩阵 S E ( 3 ) SE (3) SE(3)(文中将对陌生符号逐一解释)。此外,在欧式变换的基础上,进一步讲解相似变换、仿射变换与射影变换的相关内容。
1. 点、向量和坐标系
本节阐述刚体、点、向量、坐标、坐标系、内积与外积的基本概念,为引入符号 a ∧ a^\wedge a∧ 奠定基础。
1.1 基本定义
-刚体:形状与尺寸不发生改变的物体。三维空间中,空间点的位置可由 3 个坐标参数确定;刚体除位置外,还具有姿态属性,姿态用于描述物体的朝向。
-点:空间中的基本几何元素,无长度、无体积。两个点的连线可构成向量。
-向量:可直观理解为从某一点指向另一点的有向线段,是空间中的几何实体。向量在坐标系中以坐标形式表示,同一向量在不同坐标系下的坐标取值不同。
-坐标:设线性空间中存在一组基(张成该空间的线性无关向量组,亦称为基底),记为
(
e
1
,
e
2
,
e
3
)
(e_1, e_2, e_3)
(e1,e2,e3),则任意向量
a
a
a 在该组基下的坐标满足:
a
=
[
e
1
,
e
2
,
e
3
]
[
a
1
a
2
a
3
]
=
a
1
e
1
+
a
2
e
2
+
a
3
e
3
.
(1.1)
a = [e_1, e_2, e_3] \begin {bmatrix} a_1 \\ a_2 \\ a_3 \end {bmatrix} = a_1 e_1 + a_2 e_2 + a_3 e_3. \tag {1.1}
a=[e1,e2,e3]
a1a2a3
=a1e1+a2e2+a3e3.(1.1)
其中
(
a
1
,
a
2
,
a
3
)
T
(a_1, a_2, a_3)^T
(a1,a2,a3)T 称为向量
a
a
a 在此基下的坐标。坐标的具体取值由两方面因素决定:一是向量本身的属性,二是坐标系(基)的选取方式。注:本文中所有向量均采用列向量形式表示,与通用数学教材规范一致。
-坐标系:通常由 3 个正交的坐标轴构成。给定
x
x
x 轴与
y
y
y 轴后,
z
z
z 轴可通过右手(或左手)法则由
x
×
y
x \times y
x×y 确定。根据坐标轴定义方式的不同,坐标系分为左手系与右手系:右手系中,大拇指指向
x
x
x 轴正方向,食指指向
y
y
y 轴正方向,中指所指方向即为
z
z
z 轴正方向。多数 3D 程序库采用右手系(如 OpenGL、3D Max 等),部分库采用左手系(如 Unity、Direct3D 等)。
1.2 向量运算
-内积:向量的数乘、加减法运算不再赘述。常规定义下,内积的表达式为:
a
⋅
b
=
a
T
b
=
∑
i
=
1
3
a
i
b
i
=
∣
a
∣
∣
b
∣
cos
⟨
a
,
b
⟩
.
(1.2)
a \cdot b = a^T b = \sum_{i=1}^3 a_i b_i = \vert a \vert \vert b \vert \cos \langle a, b \rangle. \tag {1.2}
a⋅b=aTb=i=1∑3aibi=∣a∣∣b∣cos⟨a,b⟩.(1.2)
其中
⟨
a
,
b
⟩
\langle a, b \rangle
⟨a,b⟩ 表示向量
a
a
a 与
b
b
b 的夹角。内积可用于描述向量间的投影关系。
-外积:外积的数学表达式为:
a
×
b
=
∣
e
1
e
2
e
3
a
1
a
2
a
3
b
1
b
2
b
3
∣
=
[
a
2
b
3
−
a
3
b
2
a
3
b
1
−
a
1
b
3
a
1
b
2
−
a
2
b
1
]
=
[
0
−
a
3
a
2
a
3
0
−
a
1
−
a
2
a
1
0
]
b
=
def
a
∧
b
.
(1.3)
a \times b = \begin {vmatrix} e_1 & e_2 & e_3 \\ a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3 \end {vmatrix} = \begin {bmatrix} a_2 b_3 - a_3 b_2 \\ a_3 b_1 - a_1 b_3 \\ a_1 b_2 - a_2 b_1 \end {bmatrix} = \begin {bmatrix} 0 & -a_3 & a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0 \end {bmatrix} b \xlongequal {\text {def}} a^\wedge b. \tag {1.3}
a×b=
e1a1b1e2a2b2e3a3b3
=
a2b3−a3b2a3b1−a1b3a1b2−a2b1
=
0a3−a2−a30a1a2−a10
bdefa∧b.(1.3)
外积的运算结果为向量,其方向垂直于参与运算的两个向量,模长为
∣
a
∣
∣
b
∣
sin
⟨
a
,
b
⟩
\vert a \vert \vert b \vert \sin \langle a, b \rangle
∣a∣∣b∣sin⟨a,b⟩,等于两个向量张成的四边形的有向面积。引入符号
∧
^\wedge
∧ 可将向量
a
a
a 转换为反对称矩阵(满足
A
T
=
−
A
A^T = -A
AT=−A),该符号读作 “hat”,由此可将外积运算
a
×
b
a \times b
a×b 转化为矩阵与向量的乘法运算
a
∧
b
a^\wedge b
a∧b,使其成为线性运算。该符号具有一一映射特性:任意向量对应唯一的反对称矩阵,反之亦然,其具体形式为:
a
∧
=
[
0
−
a
3
a
2
a
3
0
−
a
1
−
a
2
a
1
0
]
.
(1.4)
a^\wedge = \begin {bmatrix} 0 & -a_3 & a_2 \\ a_3 & 0 & -a_1 \\ -a_2 & a_1 & 0 \end {bmatrix}. \tag {1.4}
a∧=
0a3−a2−a30a1a2−a10
.(1.4)
2. 坐标系间的欧式变换
本节内容是本文乃至相关知识体系的重要组成部分,需重点理解与掌握。首先从刚体运动出发,引入欧式变换的概念。
实际应用场景中常需定义多个坐标系,以运动的机器人(或相机)为例,通常设定一个固定不动的惯性坐标系(亦称为世界坐标系)。此时需解决的问题为:相机视野中的某一向量 p p p,其在相机坐标系下的坐标为 p c p_c pc,在世界坐标系下的坐标为 p w p_w pw,如何描述这两个坐标之间的转换关系?解决思路为:先确定该点在机器人坐标系下的坐标,再依据机器人的位姿将其变换至世界坐标系,这一过程可通过变换矩阵 T T T 实现数学描述。
2.1 刚体运动与欧式变换
刚体运动:两个坐标系之间的运动变换由旋转与平移共同构成,此类运动称为刚体运动,相机的运动即为典型的刚体运动。刚体运动过程中,同一向量在不同坐标系下的长度与夹角保持不变。此时,称相机坐标系与世界坐标系之间存在一个欧式变换(Euclidean Transform),该变换由旋转和平移两部分组成。
2.2 旋转
首先分析旋转过程,由此引出旋转矩阵与特殊正交群 S O ( n ) SO (n) SO(n) 的概念。
-旋转矩阵:设某一单位正交基
e
=
(
e
1
,
e
2
,
e
3
)
e = (e_1, e_2, e_3)
e=(e1,e2,e3) 经过旋转后变为
e
′
=
(
e
1
′
,
e
2
′
,
e
3
′
)
e' = (e_1', e_2', e_3')
e′=(e1′,e2′,e3′)。对于同一向量
a
a
a,其在两个坐标系下的坐标分别为
[
a
1
,
a
2
,
a
3
]
[a_1, a_2, a_3]
[a1,a2,a3] 与
[
a
1
′
,
a
2
′
,
a
3
′
]
[a_1', a_2', a_3']
[a1′,a2′,a3′]。由于向量本身未发生变化,根据坐标的定义可得:
[
e
1
,
e
2
,
e
3
]
[
a
1
a
2
a
3
]
=
[
e
1
′
,
e
2
′
,
e
3
′
]
[
a
1
′
a
2
′
a
3
′
]
.
(2.1)
[e_1, e_2, e_3] \begin {bmatrix} a_1 \\ a_2 \\ a_3 \end {bmatrix} = [e_1', e_2', e_3'] \begin {bmatrix} a_1' \\ a_2' \\ a_3' \end {bmatrix}. \tag {2.1}
[e1,e2,e3]
a1a2a3
=[e1′,e2′,e3′]
a1′a2′a3′
.(2.1)
为描述两个坐标之间的关系,对上式两端左乘
e
T
e^T
eT,左侧系数矩阵将变为单位矩阵,因此:
[
a
1
a
2
a
3
]
=
[
e
1
T
e
1
′
e
1
T
e
2
′
e
1
T
e
3
′
e
2
T
e
1
′
e
2
T
e
2
′
e
2
T
e
3
′
e
3
T
e
1
′
e
3
T
e
2
′
e
3
T
e
3
′
]
[
a
1
′
a
2
′
a
3
′
]
=
def
R
a
′
.
(2.2)
\begin {bmatrix} a_1 \\ a_2 \\ a_3 \end {bmatrix} = \begin {bmatrix} e_1^T e_1' & e_1^T e_2' & e_1^T e_3' \\ e_2^T e_1' & e_2^T e_2' & e_2^T e_3' \\ e_3^T e_1' & e_3^T e_2' & e_3^T e_3' \end {bmatrix} \begin {bmatrix} a_1' \\ a_2' \\ a_3' \end {bmatrix} \xlongequal {\text {def}} \mathbf {R} a'. \tag {2.2}
a1a2a3
=
e1Te1′e2Te1′e3Te1′e1Te2′e2Te2′e3Te2′e1Te3′e2Te3′e3Te3′
a1′a2′a3′
defRa′.(2.2)
矩阵
R
\mathbf {R}
R 由两组基的内积构成,刻画了旋转前后同一向量的坐标变换关系,因此将其称为旋转矩阵(Rotation Matrix)。由于该矩阵的各元素为两个坐标系基向量的内积,本质上是基向量夹角的余弦值,故也称为方向余弦矩阵(Direction Cosine Matrix)。
旋转矩阵
R
\mathbf {R}
R 为正交矩阵,其逆矩阵(即转置矩阵)描述反向的旋转过程。根据上述定义可得:
a
′
=
R
−
1
a
=
R
T
a
.
(2.3)
a' = \mathbf {R}^{-1} a = \mathbf {R}^T a. \tag {2.3}
a′=R−1a=RTa.(2.3)
显然,
R
−
1
\mathbf {R}^{-1}
R−1 与
R
T
\mathbf {R}^T
RT 对应反向的旋转变换。
-特殊正交群
S
O
(
n
)
SO (n)
SO(n):旋转矩阵
R
\mathbf {R}
R 是行列式为 1 的正交矩阵(满足
A
−
1
=
A
T
A^{-1} = A^T
A−1=AT);反之,行列式为 1 的正交矩阵也可表示旋转矩阵。据此,
n
n
n 维旋转矩阵的集合定义为:
S
O
(
n
)
=
{
R
∈
R
n
×
n
∣
R
R
T
=
I
,
det
(
R
)
=
1
}
.
(2.4)
SO (n) = \left\{ \mathbf {R} \in \mathbb {R}^{n \times n} \vert \mathbf {R} \mathbf {R}^T = \mathbf {I}, \det (\mathbf {R}) = 1 \right\}. \tag {2.4}
SO(n)={R∈Rn×n∣RRT=I,det(R)=1}.(2.4)
S
O
(
n
)
SO (n)
SO(n) 为特殊正交群(Special Orthogonal Group)的缩写,该集合包含
n
n
n 维空间中的所有旋转矩阵,其中
S
O
(
3
)
SO (3)
SO(3) 特指三维空间的旋转矩阵。通过旋转矩阵,可直接描述两个坐标系之间的旋转变换,无需再从基向量的角度分析。
2.3 平移
欧式变换中除旋转外,还包含平移分量。
考虑世界坐标系中的向量
a
a
a,经过旋转矩阵
R
\mathbf {R}
R 旋转与平移向量
t
\mathbf {t}
t 平移后得到向量
a
′
a'
a′,将旋转与平移整合可得:
a
′
=
R
a
+
t
.
(2.5)
\mathbf {a}' = \mathbf {R} \mathbf {a} + \mathbf {t}. \tag {2.5}
a′=Ra+t.(2.5)
通过上式,可利用旋转矩阵
R
\mathbf {R}
R 与平移向量
t
\mathbf {t}
t 完整描述欧式空间中的坐标变换关系。
关于下标标注的说明:实际应用中常定义坐标系 1 与坐标系 2,向量
a
a
a 在两个坐标系下的坐标分别为
a
1
a_1
a1 与
a
2
a_2
a2,二者满足如下关系:
a
1
=
R
12
a
2
+
t
12
.
(2.6)
a_1 = \mathbf {R}_{12} a_2 + \mathbf {t}_{12}. \tag {2.6}
a1=R12a2+t12.(2.6)
其中
R
12
\mathbf {R}_{12}
R12 表示 “将坐标系 2 中的向量变换至坐标系 1”,即 “从坐标系 2 到坐标系 1 的旋转矩阵”。由于向量置于矩阵右侧进行乘法运算,因此其下标需从右向左解读。对于平移向量
t
12
\mathbf {t}_{12}
t12,其物理意义为坐标系 1 原点指向坐标系 2 原点的向量在坐标系 1 下的坐标,建议将其记为 “从坐标系 1 到坐标系 2 的向量”,下标需从左向右解读,但需注意
t
12
≠
−
t
21
\mathbf {t}_{12} \neq -\mathbf {t}_{21}
t12=−t21。
3. 齐次坐标和变换矩阵
式(2.5)所描述的欧式空间旋转与平移变换存在一定局限性:该变换关系为线性关系,若进行多次变换(如依次进行
R
1
,
t
1
\mathbf {R}_1, \mathbf {t}_1
R1,t1 与
R
2
,
t
2
\mathbf {R}_2, \mathbf {t}_2
R2,t2 变换):
b
=
R
1
a
+
t
1
,
c
=
R
2
b
+
t
2
.
(3.1)
\mathbf {b} = \mathbf {R}_1 \mathbf {a} + \mathbf {t}_1, \quad \mathbf {c} = \mathbf {R}_2 \mathbf {b} + \mathbf {t}_2. \tag {3.1}
b=R1a+t1,c=R2b+t2.(3.1)
则从
a
\mathbf {a}
a 到
c
\mathbf {c}
c 的变换关系为:
c
=
R
2
(
R
1
a
+
t
1
)
+
t
2
.
(3.2)
\mathbf {c} = \mathbf {R}_2 (\mathbf {R}_1 \mathbf {a} + \mathbf {t}_1) + \mathbf {t}_2. \tag {3.2}
c=R2(R1a+t1)+t2.(3.2)
多次变换后,表达式会变得繁琐。为此,引入齐次坐标与变换矩阵的概念。
3.1 齐次坐标
采用如下数学技巧:在三维向量末尾添加 1,将其转换为四维向量 a ~ = [ a 1 ] \tilde {a} = \begin {bmatrix} a \\ 1 \end {bmatrix} a~=[a1],该向量称为齐次坐标。齐次坐标表示法是利用 n + 1 n+1 n+1 维向量描述 n n n 维向量。
n n n 维空间中点的位置向量,非齐次坐标表示为 ( P 1 , P 2 , … , P n ) (P_1, P_2, \dots, P_n) (P1,P2,…,Pn),该表示形式具有 n n n 个分量且唯一;齐次坐标表示为 ( h P 1 , h P 2 , … , h P n , h ) (hP_1, hP_2, \dots, hP_n, h) (hP1,hP2,…,hPn,h),该表示形式具有 n + 1 n+1 n+1 个分量且不唯一。
对于参数 h h h,通常取 h = 1 h=1 h=1;若 h ≠ 1 h \neq 1 h=1 且 h ≠ 0 h \neq 0 h=0,可将齐次坐标各分量除以 h h h,该操作称为齐次坐标的规范化;若 h = 0 h=0 h=0,则该点表示无穷远点。三元组 ( 0 , 0 , 0 ) (0,0,0) (0,0,0) 不表示任何空间点,原点的齐次坐标为 ( 0 , 0 , 0 , 1 ) (0,0,0,1) (0,0,0,1)。
3.2 变换矩阵
对于齐次坐标,可将旋转与平移整合至同一矩阵中,使变换关系转化为线性关系:
a
~
′
=
[
a
′
1
]
=
[
R
t
0
T
1
]
[
a
1
]
=
def
T
[
a
1
]
=
[
R
a
+
t
1
]
.
(3.3)
\tilde {a}' = \begin {bmatrix} a' \\ 1 \end {bmatrix} = \begin {bmatrix} \mathbf {R} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} \begin {bmatrix} a \\ 1 \end {bmatrix} \xlongequal {\text {def}} \mathbf {T} \begin {bmatrix} a \\ 1 \end {bmatrix} = \begin {bmatrix} \mathbf {R} a + \mathbf {t} \\ 1 \end {bmatrix}. \tag {3.3}
a~′=[a′1]=[R0Tt1][a1]defT[a1]=[Ra+t1].(3.3)
式中矩阵
T
\mathbf {T}
T 称为变换矩阵(Transform Matrix)。
借助齐次坐标与变换矩阵,多次变换的叠加可简化为简洁的形式:
b
~
=
T
1
a
~
,
c
~
=
T
2
b
~
⇒
c
~
=
T
2
T
1
a
~
.
(3.4)
\tilde {b} = \mathbf {T}_1 \tilde {a}, \quad \tilde {c} = \mathbf {T}_2 \tilde {b} \Rightarrow \tilde {c} = \mathbf {T}_2 \mathbf {T}_1 \tilde {a}. \tag {3.4}
b~=T1a~,c~=T2b~⇒c~=T2T1a~.(3.4)
为简化表述,在无歧义的情况下,后续直接将其写作 b = T a \mathbf {b} = \mathbf {T} \mathbf {a} b=Ta 的形式,默认已完成齐次坐标的转换。
3.3 特殊欧式群 S E ( 3 ) SE (3) SE(3)
变换矩阵
T
\mathbf {T}
T 具有特定的结构:左上角为旋转矩阵,右上角为平移向量,左下角为零向量,右下角为 1。此类矩阵构成的集合称为特殊欧式群(Special Euclidean Group),定义为:
S
E
(
3
)
=
{
T
E
=
[
R
t
0
T
1
]
∈
R
4
×
4
∣
R
∈
S
O
(
3
)
,
t
∈
R
3
}
.
(3.5)
SE (3) = \left\{ \mathbf {T}_E = \begin {bmatrix} \mathbf {R} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} \in \mathbb {R}^{4 \times 4} \vert \mathbf {R} \in SO (3), \mathbf {t} \in \mathbb {R}^3 \right\}. \tag {3.5}
SE(3)={TE=[R0Tt1]∈R4×4∣R∈SO(3),t∈R3}.(3.5)
与
S
O
(
3
)
SO (3)
SO(3) 类似,变换矩阵的逆矩阵
T
−
1
\mathbf {T}^{-1}
T−1 对应反向的变换,其表达式为:
T
−
1
=
[
R
T
−
R
T
t
0
T
1
]
.
(3.6)
\mathbf {T}^{-1} = \begin {bmatrix} \mathbf {R}^T & -\mathbf {R}^T \mathbf {t} \\ 0^T & 1 \end {bmatrix}. \tag {3.6}
T−1=[RT0T−RTt1].(3.6)
同样,采用 T 12 \mathbf {T}_{12} T12 表示从坐标系 2 到坐标系 1 的变换矩阵。在无歧义时,后续不再区分齐次坐标与普通坐标的符号,默认使用符合运算法则的坐标形式,因齐次坐标与非齐次坐标之间的转换操作较为简便。
4. 相似、仿射和射影变换
除欧式变换外,三维空间还存在其他变换形式,欧式变换是其中最为简单的一种。部分变换与测量几何相关,后续讲解中可能涉及,故在此先行罗列。欧式变换保持向量的长度与夹角不变,相当于将刚体进行平移或旋转操作,不改变其几何形态;但实际场景中,由于视角等因素的影响,物体往往会产生畸变,因此需引入相似变换、仿射变换与射影变换,这些变换会改变物体的外形,且均具有类似的矩阵表示形式。
4.1 相似变换
相似变换相比欧式变换增加了一个自由度,允许物体进行均匀缩放,其矩阵表示形式为:
T
S
=
[
s
R
t
0
T
1
]
(4.1)
\mathbf {T}_S = \begin {bmatrix} s\mathbf {R} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} \tag {4.1}
TS=[sR0Tt1](4.1)
需注意,旋转部分新增缩放因子
s
s
s,表示向量经旋转后,可在
x
、
y
、
z
x、y、z
x、y、z 三个坐标轴方向进行均匀缩放。由于包含缩放操作,相似变换不再保持图形的面积不变(例如边长为 1 的立方体经相似变换后可变为边长为 10 的立方体)。
三维相似变换的集合称为相似变换群,记作 S i m ( 3 ) Sim (3) Sim(3)。
4.2 仿射变换
仿射变换的矩阵形式为:
T
A
=
[
A
t
0
T
1
]
(4.2)
\mathbf {T}_A = \begin {bmatrix} \mathbf {A} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} \tag {4.2}
TA=[A0Tt1](4.2)
与欧式变换不同,仿射变换仅要求矩阵
A
\mathbf {A}
A 为可逆矩阵,无需满足正交性。仿射变换也称为正交投影,立方体经仿射变换后不再为立方体,但各面仍保持为平行四边形。
4.3 射影变换
射影变换是形式最一般的变换,亦称为投影变换,其矩阵形式为:
T
P
=
[
A
t
a
T
v
]
(4.3)
\mathbf {T}_P = \begin {bmatrix} \mathbf {A} & \mathbf {t} \\ \mathbf {a}^T & v \end {bmatrix} \tag {4.3}
TP=[AaTtv](4.3)
该矩阵左上角为可逆矩阵
A
\mathbf {A}
A,右上角为平移向量
t
\mathbf {t}
t,左下角为缩放向量
a
T
\mathbf {a}^T
aT,右下角为整体变换比例
v
v
v。由于采用齐次坐标表示,当
v
≠
0
v \neq 0
v=0 时,可将整个矩阵除以
v
v
v,使右下角元素变为 1;当
v
=
0
v=0
v=0 时,右下角元素为 0。因此,二维射影变换具有 8 个自由度,三维射影变换具有 15 个自由度。
射影变换是前文所述变换中形式最通用的一种,从真实世界到相机照片的变换可视为射影变换。例如,方形的地板砖在相机照片中不再是方形,受近大远小的透视效应影响,甚至不再是平行四边形,而是呈现为不规则四边形,这是位姿估计中常见的场景。
4.4 变换性质总结
下表对比总结上述四种变换的性质,需注意 “不变性质” 列中,从上至下存在包含关系(例如欧式变换除保持体积不变外,同时具有保平行、保相交等性质)。
表 4-1 常见变换的性质比较
| 变换名称 | 矩阵形式 | 自由度 | 不变性质 | 变换形态 |
|---|---|---|---|---|
| 欧氏变换 | T E = [ R t 0 T 1 ] \mathbf {T}_E = \begin {bmatrix} \mathbf {R} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} TE=[R0Tt1] | 6 | 长度、夹角、体积 | 位置、方向改变 |
| 相似变换 | T S = [ s R t 0 T 1 ] \mathbf {T}_S = \begin {bmatrix} s\mathbf {R} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} TS=[sR0Tt1] | 7 | 体积比 | 按比例缩放 |
| 仿射变换 | T A = [ A t 0 T 1 ] \mathbf {T}_A = \begin {bmatrix} \mathbf {A} & \mathbf {t} \\ 0^T & 1 \end {bmatrix} TA=[A0Tt1] | 12 | 平行性、体积比 | 正交投影,平行性不变 |
| 射影变换 | T P = [ A t a T v ] \mathbf {T}_P = \begin {bmatrix} \mathbf {A} & \mathbf {t} \\ \mathbf {a}^T & v \end {bmatrix} TP=[AaTtv] | 15 | 接触平面的相交和相切 | 大小、平行性均发生改变 |
从真实世界到相机照片的变换为射影变换;若相机焦距为无穷远,则该变换退化为仿射变换。在深入学习相机模型前,只需对这些变换建立基本认知即可。
5. 实践:Eigen
本节讲解如何使用 Eigen 库表示矩阵与向量,并进一步实现旋转矩阵与变换矩阵的相关运算。KDevelop 工程形式的代码文件见附件。
5.1 Eigen 库简介
Eigen 是一款开源的 C++ 线性代数库,提供高效的矩阵线性代数运算功能,同时支持解方程等高级操作。众多上层软件库(如 g2o、Sophus)均基于 Eigen 实现矩阵运算。Eigen 的显著特点是纯头文件库,仅包含头文件,无.so 或.a 等二进制库文件,使用时只需引入头文件,无需链接库文件。本节示例仅涵盖基础矩阵运算,更多功能可参考 Eigen 官网教程 。
5.2 Eigen 库安装
若未安装 Eigen 库,可执行以下命令完成安装:
sudo apt install libeigen3-dev
5.3 代码示例
以下代码演示 Eigen 库的基本使用方法(含详细注释):
#include<iostream>
using namespace std;
#include<ctime>
#include<eigen3/Eigen/Core>
#include<eigen3/Eigen/Dense> // 稠密矩阵的代数运算,如逆、特征值等
using namespace Eigen;
#define MATRIX_SIZE 50
int main (int argc, char**argv){
// Eigen 中所有向量和矩阵均基于 Eigen::Matrix 模板类实现,前三个模板参数依次为数据类型、行数、列数
// 声明一个 2×3 的 float 类型矩阵
Matrix<float, 2, 3> matrix_23f;
// Eigen 通过 typedef 提供了多种内置类型,底层仍为 Eigen::Matrix
// 例如 Vector3d 等价于 Eigen::Matrix<double, 3, 1>(三维向量)
Vector3d v_3d;
Matrix<float, 3, 1> matrix_31f;
// 初始化 3×3 的 double 类型矩阵,所有元素置 0
Matrix3d matrix_33d = Matrix3d::Zero ();
// 动态大小矩阵:Matrix<double, Dynamic, Dynamic> 与 MatrixXd 等价
Matrix<double, Dynamic, Dynamic> matrix_dynamic;
MatrixXd matrix_x;
// 矩阵初始化:逐行输入数据
matrix_23f << 1, 2, 3, 4, 5, 6;
cout << "matrix 2*3 from 1 to 6:\n" << matrix_23f << endl;
// 通过 () 运算符访问矩阵元素
cout << "print matrix 2*3:" << endl;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
cout << matrix_23f (i, j) << "\t";
}
cout << endl;
}
// 向量初始化
v_3d << 3, 2, 1;
matrix_31f << 4, 5, 6;
// Eigen 不支持不同数据类型矩阵的混合运算,需显式类型转换;同时需保证矩阵维度匹配
Matrix<double, 2, 1> result = matrix_23f.cast<double>() * v_3d;
cout << "[1,2,3;4,5,6]*[3,2,1]=" << result.transpose () << endl;
Matrix<float, 2, 1> result2 = matrix_23f * matrix_31f;
cout << "[1,2,3;4,5,6]*[4,5,6]=" << result2.transpose () << endl;
// 维度不匹配会导致编译错误,以下为错误示例(注释掉)
// Eigen::Matrix<double, 2, 3> result_wrong_dimension = matrix_23f.cast<double>() * v_31d;
// 矩阵基本运算
matrix_33d = Matrix3d::Random (); // 生成随机数矩阵
cout << "random matrix: \n" << matrix_33d << endl;
cout << "transpose: \n" << matrix_33d.transpose () << endl; // 转置
cout << "sum:" << matrix_33d.sum () << endl; // 所有元素求和
cout << "trace:" << matrix_33d.trace () << endl; // 迹(主对角线元素和)
cout << "times 10: \n" << 10 * matrix_33d << endl; // 数乘
cout << "inverse: \n" << matrix_33d.inverse () << endl; // 逆矩阵
cout << "det:" << matrix_33d.determinant () << endl; // 行列式
// 特征值与特征向量求解(实对称矩阵可保证对角化成功)
SelfAdjointEigenSolver<Matrix3d> eigen_solver (matrix_33d.transpose () * matrix_33d);
cout << "Eigen values=\n" << eigen_solver.eigenvalues () << endl;
cout << "Eigen vectors=\n" << eigen_solver.eigenvectors () << endl;
// 求解线性方程组:matrix_NN * x = v_N1d
Matrix<double, MATRIX_SIZE, MATRIX_SIZE> matrix_NN = MatrixXd::Random (MATRIX_SIZE, MATRIX_SIZE);
matrix_NN = matrix_NN * matrix_NN.transpose (); // 构造正定矩阵
Matrix<double, MATRIX_SIZE, 1> v_N1d = MatrixXd::Random (MATRIX_SIZE, 1);
// 计时:直接求逆法
clock_t time_stt = clock ();
Matrix<double, MATRIX_SIZE, 1> x = matrix_NN.inverse () * v_N1d;
cout << "time of normal inverse is" << 1000 * (clock () - time_stt) / (double) CLOCKS_PER_SEC << "ms" << endl;
cout << "x =" << x.transpose () << endl;
// 计时:QR 分解法(速度更快)
time_stt = clock ();
x = matrix_NN.colPivHouseholderQr ().solve (v_N1d);
cout << "time of Qr decomposition is" << 1000 * (clock () - time_stt) / (double) CLOCKS_PER_SEC << "ms" << endl;
cout << "x =" << x.transpose () << endl;
// 计时:Cholesky 分解法(适用于正定矩阵)
time_stt = clock ();
x = matrix_NN.ldlt ().solve (v_N1d);
cout << "time of ldlt decomposition is" << 1000 * (clock () - time_stt) / (double) CLOCKS_PER_SEC << "ms" << endl;
cout << "x =" << x.transpose () << endl;
// 计时:LU 分解法
time_stt = clock ();
x = matrix_NN.lu ().solve (v_N1d);
cout << "time of lu decomposition is" << 1000 * (clock () - time_stt) / (double) CLOCKS_PER_SEC << "ms" << endl;
cout << "x =" << x.transpose () << endl;
return 0;
}
5.4 CMakeLists.txt 配置
cmake_minimum_required (VERSION 3.0)
project (rigidMotion)
add_executable (useEigen useEigen.cpp)
set (CMAKE_BUILD_TYPE "Debug")
5.5 运行结果
编译并运行程序后,输出结果示例如下:
matrix 2*3 from 1 to 6:
1 2 3
4 5 6
print matrix 2*3:
1 2 3
4 5 6
[1,2,3;4,5,6]*[3,2,1]=10 28
[1,2,3;4,5,6]*[4,5,6]=32 77
random matrix:
0.680375 0.59688 -0.329554
-0.211234 0.823295 0.536459
0.566198 -0.604897 -0.444451
transpose:
0.680375 -0.211234 0.566198
0.59688 0.823295 -0.604897
-0.329554 0.536459 -0.444451
sum: 1.61307
trace: 1.05922
times 10:
6.80375 5.9688 -3.29554
-2.11234 8.23295 5.36459
5.66198 -6.04897 -4.44451
inverse:
-0.198521 2.22739 2.8357
1.00605 -0.555135 -1.41603
-1.62213 3.59308 3.28973
det: 0.208598
Eigen values=
0.0242899
0.992154
1.80558
Eigen vectors=
-0.549013 -0.735943 0.396198
0.253452 -0.598296 -0.760134
-0.796459 0.316906 -0.514998
time of normal inverse is 1.967ms
x = -55.7896 -298.793 130.113 -388.455 -159.312 160.654 -40.0416 -193.561 155.844 181.144 185.125 -62.7786 19.8333 -30.8772 -200.746 55.8385 -206.604 26.3559 -14.6789 122.719 -221.449 26.233 -318.95 -78.6931 50.1446 87.1986 -194.922 132.319 -171.78 -4.19736 11.876 -171.779 48.3047 84.1812 -104.958 -47.2103 -57.4502 -48.9477 -19.4237 28.9419 111.421 92.1237 -288.248 -23.3478 -275.22 -292.062 -92.698 5.96847 -93.6244 109.734
time of Qr decomposition is 2.409ms
x = -55.7896 -298.793 130.113 -388.455 -159.312 160.654 -40.0416 -193.561 155.844 181.144 185.125 -62.7786 19.8333 -30.8772 -200.746 55.8385 -206.604 26.3559 -14.6789 122.719 -221.449 26.233 -318.95 -78.6931 50.1446 87.1986 -194.922 132.319 -171.78 -4.19736 11.876 -171.779 48.3047 84.1812 -104.958 -47.2103 -57.4502 -48.9477 -19.4237 28.9419 111.421 92.1237 -288.248 -23.3478 -275.22 -292.062 -92.698 5.96847 -93.6244 109.734
time of ldlt decomposition is 0.667ms
x = -55.7896 -298.793 130.113 -388.455 -159.312 160.654 -40.0416 -193.561 155.844 181.144 185.125 -62.7786 19.8333 -30.8772 -200.746 55.8385 -206.604 26.3559 -14.6789 122.719 -221.449 26.233 -318.95 -78.6931 50.1446 87.1986 -194.922 132.319 -171.78 -4.19736 11.876 -171.779 48.3047 84.1812 -104.958 -47.2103 -57.4502 -48.9477 -19.4237 28.9419 111.421 92.1237 -288.248 -23.3478 -275.22 -292.062 -92.698 5.96847 -93.6244 109.734
time of lu decomposition is 0.787ms
x = -55.7896 -298.793 130.113 -388.455 -159.312 160.654 -40.0416 -193.561 155.844 181.144 185.125 -62.7786 19.8333 -30.8772 -200.746 55.8385 -206.604 26.3559 -14.6789 122.719 -221.449 26.233 -318.95 -78.6931 50.1446 87.1986 -194.922 132.319 -171.78 -4.19736 11.876 -171.779 48.3047 84.1812 -104.958 -47.2103 -57.4502 -48.9477 -19.4237 28.9419 111.421 92.1237 -288.248 -23.3478 -275.22 -292.062 -92.698 5.96847 -93.6244 109.734
附件包含本讲所有相关代码。后续将讲解刚体运动第二部分(旋转向量与欧拉角)及第三部分(四元数表示旋转),欢迎留言讨论,您的关注是内容更新的动力。
本文基于《视觉 SLAM 十四讲:从理论到实践》与《Quaternions, Interpolation and Animation》编写,在原文基础上进行适当精简,并结合网络优质资源与作者理解补充注解及扩展知识点。
三维空间刚体运动 2:旋转向量与罗德里格斯公式(最详细推导)
龙焰智能 于 2024-11-08 20:34:10 修改
序
本系列文章参照高翔老师《视觉 SLAM 十四讲:从理论到实践》,系统讲解三维空间刚体运动的相关理论,为读者构建扎实的数学基础。
1. 旋转向量定义
旋转矩阵的表示方式存在以下两方面局限:
1.
S
O
(
3
)
SO (3)
SO(3) 中的旋转矩阵包含 9 个元素,但一次三维旋转仅需 3 个自由度即可描述,因此这种表示存在冗余;同理,
S
E
(
4
)
SE (4)
SE(4) 也存在类似冗余问题。是否存在更紧凑的表示方式?
2. 旋转矩阵与变换矩阵具有固有约束:旋转矩阵需满足正交性且行列式为 1,变换矩阵需维持特定结构。这些约束会增加旋转矩阵或变换矩阵的估计与优化难度。
基于上述问题,需要一种更紧凑的方式描述旋转与平移。
旋转向量:任意旋转均可由旋转轴与旋转角共同刻画。定义单位向量 u u u(方向与旋转轴一致,也可采用 n n n、 k k k 等符号表示),旋转角为 θ \theta θ,则向量 θ u \theta u θu 可完整描述该旋转,此类向量称为旋转向量(或轴角 / 角轴,Axis-Angle),仅需三维向量即可表征旋转过程。
三维空间中,一个方向可由两个参数确定(如地球经纬度),第三个参数可用于表示旋转角度。对于变换过程,采用一个旋转向量与一个平移向量即可完整描述,变量维度恰好为六维,无冗余信息。
2. 罗德里格斯公式 - 向量转换为矩阵
2.1 定义
罗德里格斯公式:旋转向量与旋转矩阵之间的转换可通过罗德里格斯公式(Rodrigues’s Formula)实现。由于任意旋转由旋转轴
u
u
u 与旋转角
θ
\theta
θ 刻画,罗德里格斯公式的具体形式如下:
R
=
cos
θ
⋅
I
+
(
1
−
cos
θ
)
⋅
u
u
T
+
sin
θ
⋅
u
∧
(2.1)
R = \cos \theta \cdot I + (1 - \cos \theta) \cdot uu^T + \sin \theta \cdot u^\wedge \tag {2.1}
R=cosθ⋅I+(1−cosθ)⋅uuT+sinθ⋅u∧(2.1)
其中符号
∧
^\wedge
∧ 为向量到反对称矩阵的转换运算符,具体定义见上一篇博客《三维空间刚体运动 1:旋转矩阵与变换矩阵》的公式(1.4)。该公式也可表示为:
R
=
I
+
(
1
−
cos
θ
)
U
2
+
sin
θ
⋅
U
(2.2)
R = I + (1 - \cos \theta) U^2 + \sin \theta \cdot U \tag {2.2}
R=I+(1−cosθ)U2+sinθ⋅U(2.2)
式中
U
U
U 为向量
u
u
u 对应的反对称矩阵
u
∧
u^\wedge
u∧。假设单位旋转向量
u
u
u 的坐标为
u
=
[
u
x
u
y
u
z
]
u = \begin {bmatrix} u_x \\ u_y \\ u_z \end {bmatrix}
u=
uxuyuz
,旋转角为
θ
\theta
θ,则旋转矩阵
R
R
R 的展开式为:
R
=
[
cos
θ
+
u
x
2
(
1
−
cos
θ
)
u
x
u
y
(
1
−
cos
θ
)
−
u
z
sin
θ
u
y
sin
θ
+
u
x
u
z
(
1
−
cos
θ
)
u
z
sin
θ
+
u
x
u
y
(
1
−
cos
θ
)
cos
θ
+
u
y
2
(
1
−
cos
θ
)
−
u
x
sin
θ
+
u
y
u
z
(
1
−
cos
θ
)
−
u
y
sin
θ
+
u
x
u
z
(
1
−
cos
θ
)
u
x
sin
θ
+
u
y
u
z
(
1
−
cos
θ
)
cos
θ
+
u
z
2
(
1
−
cos
θ
)
]
(2.3)
R = \begin {bmatrix} \cos\theta + u_x^2 (1 - \cos\theta) & u_x u_y (1 - \cos\theta) - u_z \sin\theta & u_y \sin\theta + u_x u_z (1 - \cos\theta) \\ u_z \sin\theta + u_x u_y (1 - \cos\theta) & \cos\theta + u_y^2 (1 - \cos\theta) & -u_x \sin\theta + u_y u_z (1 - \cos\theta) \\ -u_y \sin\theta + u_x u_z (1 - \cos\theta) & u_x \sin\theta + u_y u_z (1 - \cos\theta) & \cos\theta + u_z^2 (1 - \cos\theta) \end {bmatrix} \tag {2.3}
R=
cosθ+ux2(1−cosθ)uzsinθ+uxuy(1−cosθ)−uysinθ+uxuz(1−cosθ)uxuy(1−cosθ)−uzsinθcosθ+uy2(1−cosθ)uxsinθ+uyuz(1−cosθ)uysinθ+uxuz(1−cosθ)−uxsinθ+uyuz(1−cosθ)cosθ+uz2(1−cosθ)
(2.3)
2.2 推导
首先明确几何模型:定义 u u u 为旋转轴的单位向量, v v v 为待旋转向量, w w w 为 u × v u \times v u×v 方向的单位向量。向量 v v v 绕 u u u 旋转角度 θ \theta θ 后得到 v r o t v_{rot} vrot。将 v v v 分解为平行于旋转轴 u u u 的分量 v ∥ v_{\parallel} v∥ 与正交于 u u u 的分量 v ⊥ v_{\perp} v⊥;同理, v r o t v_{rot} vrot 分解为 v r o t ∥ v_{rot\parallel} vrot∥ 与 v r o t ⊥ v_{rot\perp} vrot⊥,其中 v r o t ∥ = v ∥ v_{rot\parallel} = v_{\parallel} vrot∥=v∥(旋转不改变平行于旋转轴的分量)。向量 a a a 与 b b b 分别为 v r o t ⊥ v_{rot\perp} vrot⊥ 在 w w w 与 v ⊥ v_{\perp} v⊥ 方向上的分量。
图 2.1:旋转向量 3D 图(数学绘图软件推荐 geogebra)
罗德里格斯公式建立 v r o t v_{rot} vrot 与 v v v 的线性关系 v r o t = R v v_{rot} = Rv vrot=Rv,进而推导旋转矩阵 R R R。该公式存在两种表达形式,对应两种推导方法,差异在于 v ⊥ v_{\perp} v⊥ 的表示方式,具体推导过程如下。
2.2.1 推导一
1.向量分解:
待旋转向量
v
v
v 可分解为平行于旋转轴的分量与正交分量之和:
v
=
v
⊥
+
v
∥
(2.4)
v = v_{\perp} + v_{\parallel} \tag {2.4}
v=v⊥+v∥(2.4)
移项可得正交分量:
v
⊥
=
v
−
v
∥
v_{\perp} = v - v_{\parallel}
v⊥=v−v∥
旋转后向量
v
r
o
t
v_{rot}
vrot 的分解形式为:
v
r
o
t
=
v
r
o
t
∥
+
v
r
o
t
⊥
(2.5)
v_{rot} = v_{rot\parallel} + v_{rot\perp} \tag {2.5}
vrot=vrot∥+vrot⊥(2.5)
后续需分别推导
v
r
o
t
∥
v_{rot\parallel}
vrot∥ 与
v
r
o
t
⊥
v_{rot\perp}
vrot⊥。
2.平行分量
v
r
o
t
∥
v_{rot\parallel}
vrot∥:
由于旋转过程中平行于旋转轴的向量保持不变,故
v
r
o
t
∥
=
v
∥
v_{rot\parallel} = v_{\parallel}
vrot∥=v∥。
v
∥
v_{\parallel}
v∥ 为
v
v
v 在
u
u
u 上的正交投影,根据正交投影公式:
v
∥
=
proj
u
(
v
)
=
u
⋅
v
u
⋅
u
u
=
(
u
⋅
v
)
u
(2.6)
v_{\parallel} = \text {proj}_u (v) = \frac {u \cdot v}{u \cdot u} u = (u \cdot v) u \tag {2.6}
v∥=proju(v)=u⋅uu⋅vu=(u⋅v)u(2.6)
其中
u
u
u 为单位向量(
∣
∣
u
∣
∣
=
1
||u|| = 1
∣∣u∣∣=1),故
u
⋅
u
=
∣
∣
u
∣
∣
2
=
1
u \cdot u = ||u||^2 = 1
u⋅u=∣∣u∣∣2=1,点积
u
⋅
v
u \cdot v
u⋅v 为标量,与
u
u
u 相乘后得到向量。
3.正交分量
v
r
o
t
⊥
v_{rot\perp}
vrot⊥:
正交分量的旋转可视为二维平面内的旋转(旋转轴
u
u
u 垂直于该平面)。为描述该旋转,需构造平面内的正交基向量
w
w
w,满足同时正交于
u
u
u 与
v
⊥
v_{\perp}
v⊥,通过叉乘可得:
w
=
u
×
v
⊥
(2.7)
w = u \times v_{\perp} \tag {2.7}
w=u×v⊥(2.7)
基于右手坐标系,
w
w
w 指向
v
⊥
v_{\perp}
v⊥ 逆时针旋转
π
/
2
\pi/2
π/2 后的方向,且与
v
⊥
v_{\perp}
v⊥ 同处于垂直于
u
u
u 的平面内。由于
∣
∣
u
∣
∣
=
1
||u|| = 1
∣∣u∣∣=1 且
u
u
u 与
v
⊥
v_{\perp}
v⊥ 正交,根据叉乘模长公式:
∣
∣
w
∣
∣
=
∣
∣
u
×
v
⊥
∣
∣
=
∣
∣
u
∣
∣
⋅
∣
∣
v
⊥
∣
∣
⋅
sin
(
π
2
)
=
∣
∣
v
⊥
∣
∣
(2.8)
||w|| = ||u \times v_{\perp}|| = ||u|| \cdot ||v_{\perp}|| \cdot \sin (\frac {\pi}{2}) = ||v_{\perp}|| \tag {2.8}
∣∣w∣∣=∣∣u×v⊥∣∣=∣∣u∣∣⋅∣∣v⊥∣∣⋅sin(2π)=∣∣v⊥∣∣(2.8)
即
w
w
w 与
v
⊥
v_{\perp}
v⊥ 模长相等,构成平面内的一组正交单位基。
利用三角关系,
v
r
o
t
⊥
v_{rot\perp}
vrot⊥ 可分解为
w
w
w 与
v
⊥
v_{\perp}
v⊥ 方向的分量之和:
v
r
o
t
⊥
=
a
+
b
=
sin
θ
⋅
w
+
cos
θ
⋅
v
⊥
=
sin
θ
(
u
×
v
⊥
)
+
cos
θ
⋅
v
⊥
(2.9)
v_{rot\perp} = a + b = \sin\theta \cdot w + \cos\theta \cdot v_{\perp} = \sin\theta (u \times v_{\perp}) + \cos\theta \cdot v_{\perp} \tag {2.9}
vrot⊥=a+b=sinθ⋅w+cosθ⋅v⊥=sinθ(u×v⊥)+cosθ⋅v⊥(2.9)
由叉乘分配律及
u
u
u 与
v
∥
v_{\parallel}
v∥ 平行(叉乘结果为零向量),可得:
u
×
v
⊥
=
u
×
(
v
−
v
∥
)
=
u
×
v
−
u
×
v
∥
=
u
×
v
(2.10)
u \times v_{\perp} = u \times (v - v_{\parallel}) = u \times v - u \times v_{\parallel} = u \times v \tag {2.10}
u×v⊥=u×(v−v∥)=u×v−u×v∥=u×v(2.10)
4.合并推导:
将
v
r
o
t
∥
v_{rot\parallel}
vrot∥ 与
v
r
o
t
⊥
v_{rot\perp}
vrot⊥ 代入
v
r
o
t
v_{rot}
vrot 的分解式:
v
r
o
t
=
v
r
o
t
⊥
+
v
r
o
t
∥
=
sin
θ
(
u
×
v
)
+
cos
θ
⋅
v
⊥
+
(
u
⋅
v
)
u
=
sin
θ
(
u
×
v
)
+
cos
θ
(
v
−
v
∥
)
+
(
u
⋅
v
)
u
=
sin
θ
(
u
×
v
)
+
cos
θ
(
v
−
(
u
⋅
v
)
u
)
+
(
u
⋅
v
)
u
=
cos
θ
⋅
v
+
(
1
−
cos
θ
)
(
u
⋅
v
)
u
+
sin
θ
(
u
×
v
)
(2.11)
\begin {aligned} v_{rot} &= v_{rot\perp} + v_{rot\parallel} \\ &= \sin\theta (u \times v) + \cos\theta \cdot v_{\perp} + (u \cdot v) u \\ &= \sin\theta (u \times v) + \cos\theta (v - v_{\parallel}) + (u \cdot v) u \\ &= \sin\theta (u \times v) + \cos\theta (v - (u \cdot v) u) + (u \cdot v) u \\ &= \cos\theta \cdot v + (1 - \cos\theta) (u \cdot v) u + \sin\theta (u \times v) \end {aligned} \tag {2.11}
vrot=vrot⊥+vrot∥=sinθ(u×v)+cosθ⋅v⊥+(u⋅v)u=sinθ(u×v)+cosθ(v−v∥)+(u⋅v)u=sinθ(u×v)+cosθ(v−(u⋅v)u)+(u⋅v)u=cosθ⋅v+(1−cosθ)(u⋅v)u+sinθ(u×v)(2.11)
5.矩阵形式转换:
为将上式转化为矩阵乘法形式,需对两项进行矩阵表示:
- 对于
(
u
⋅
v
)
u
(u \cdot v) u
(u⋅v)u:由于向量为列向量,点积
u
⋅
v
=
u
T
v
u \cdot v = u^T v
u⋅v=uTv,因此:
( u ⋅ v ) u = u ( u T v ) = ( u u T ) v (2.12) (u \cdot v) u = u (u^T v) = (uu^T) v \tag {2.12} (u⋅v)u=u(uTv)=(uuT)v(2.12) - 对于
u
×
v
u \times v
u×v:利用反对称矩阵
U
=
u
∧
U = u^\wedge
U=u∧,叉乘可表示为矩阵与向量的乘法:
u × v = U v (2.13) u \times v = U v \tag {2.13} u×v=Uv(2.13)
其中 KaTeX parse error: \tag works only in display equations
将上述矩阵表示代入式(2.11),整理得:
v
r
o
t
=
cos
θ
⋅
I
v
+
(
1
−
cos
θ
)
⋅
u
u
T
v
+
sin
θ
⋅
U
v
=
(
cos
θ
⋅
I
+
(
1
−
cos
θ
)
u
u
T
+
sin
θ
⋅
U
)
v
(2.15)
\begin {aligned} v_{rot} &= \cos\theta \cdot I v + (1 - \cos\theta) \cdot uu^T v + \sin\theta \cdot U v \\ &= \left ( \cos\theta \cdot I + (1 - \cos\theta) uu^T + \sin\theta \cdot U \right) v \end {aligned} \tag {2.15}
vrot=cosθ⋅Iv+(1−cosθ)⋅uuTv+sinθ⋅Uv=(cosθ⋅I+(1−cosθ)uuT+sinθ⋅U)v(2.15)
因此,旋转矩阵为:
R
=
cos
θ
⋅
I
+
(
1
−
cos
θ
)
u
u
T
+
sin
θ
⋅
U
(2.16)
R = \cos\theta \cdot I + (1 - \cos\theta) uu^T + \sin\theta \cdot U \tag {2.16}
R=cosθ⋅I+(1−cosθ)uuT+sinθ⋅U(2.16)
其中
I
I
I 为三维单位矩阵。
2.2.2 推导二
该推导方法是利用叉乘表示正交分量
v
⊥
v_{\perp}
v⊥,具体过程如下:
由向量叉乘的性质,正交分量
v
⊥
v_{\perp}
v⊥ 可表示为:
v
⊥
=
−
u
×
(
u
×
v
)
(2.17)
v_{\perp} = -u \times (u \times v) \tag {2.17}
v⊥=−u×(u×v)(2.17)
将其代入推导一中
v
r
o
t
v_{rot}
vrot 的表达式,结合
U
=
u
∧
U = u^\wedge
U=u∧ 及反对称矩阵的性质
U
2
=
u
u
T
−
I
U^2 = uu^T - I
U2=uuT−I(可通过矩阵乘法验证),推导如下:
v
r
o
t
=
v
r
o
t
⊥
+
v
r
o
t
∥
=
sin
θ
(
u
×
v
)
+
cos
θ
⋅
v
⊥
+
v
−
v
⊥
=
v
+
sin
θ
(
u
×
v
)
+
(
c
o
s
θ
−
1
)
v
⊥
=
v
+
sin
θ
⋅
U
v
−
(
1
−
cos
θ
)
⋅
u
×
(
u
×
v
)
=
v
+
sin
θ
⋅
U
v
+
(
1
−
cos
θ
)
⋅
U
2
v
=
(
I
+
(
1
−
cos
θ
)
U
2
+
sin
θ
⋅
U
)
v
(2.18)
\begin {aligned} v_{rot} &= v_{rot\perp} + v_{rot\parallel} \\ &= \sin\theta (u \times v) + \cos\theta \cdot v_{\perp} + v - v_{\perp} \\ &= v + \sin\theta (u \times v) + (cos\theta - 1) v_{\perp} \\ &= v + \sin\theta \cdot U v - (1 - \cos\theta) \cdot u \times (u \times v) \\ &= v + \sin\theta \cdot U v + (1 - \cos\theta) \cdot U^2 v \\ &= \left ( I + (1 - \cos\theta) U^2 + \sin\theta \cdot U \right) v \end {aligned} \tag {2.18}
vrot=vrot⊥+vrot∥=sinθ(u×v)+cosθ⋅v⊥+v−v⊥=v+sinθ(u×v)+(cosθ−1)v⊥=v+sinθ⋅Uv−(1−cosθ)⋅u×(u×v)=v+sinθ⋅Uv+(1−cosθ)⋅U2v=(I+(1−cosθ)U2+sinθ⋅U)v(2.18)
由此得到旋转矩阵的另一种表达式:
R
=
I
+
(
1
−
cos
θ
)
U
2
+
sin
θ
⋅
U
(2.19)
R = I + (1 - \cos\theta) U^2 + \sin\theta \cdot U \tag {2.19}
R=I+(1−cosθ)U2+sinθ⋅U(2.19)
该形式在计算中涉及的参数更少,是实际旋转操作中常用的表达式。
2.2.3 推导向量 a a a 和 b b b
向量 a a a 与 b b b 是 v r o t ⊥ v_{rot\perp} vrot⊥ 在 w w w 与 v ⊥ v_{\perp} v⊥ 方向的正交分量,需分别求解其大小与方向:
-向量 a a a:
- 大小:设
θ
1
=
π
−
θ
\theta_1 = \pi - \theta
θ1=π−θ,
θ
2
\theta_2
θ2 为
v
v
v 与
u
u
u 的夹角,由三角关系及叉乘模长公式
∣
u
×
v
∣
=
∣
u
∣
∣
v
∣
sin
θ
2
=
∣
v
∣
sin
θ
2
|u \times v| = |u||v|\sin\theta_2 = |v|\sin\theta_2
∣u×v∣=∣u∣∣v∣sinθ2=∣v∣sinθ2,可得:
∣ a ∣ = sin θ 1 ∣ v r o t ⊥ ∣ = sin ( π − θ ) ∣ v ⊥ ∣ = sin θ ⋅ ∣ v ∣ sin θ 2 = sin θ ⋅ ∣ u × v ∣ (2.20) |a| = \sin\theta_1 |v_{rot\perp}| = \sin (\pi - \theta) |v_{\perp}| = \sin\theta \cdot |v|\sin\theta_2 = \sin\theta \cdot |u \times v| \tag {2.20} ∣a∣=sinθ1∣vrot⊥∣=sin(π−θ)∣v⊥∣=sinθ⋅∣v∣sinθ2=sinθ⋅∣u×v∣(2.20) - 方向:与 u × v u \times v u×v 一致,单位方向向量为 u × v ∣ u × v ∣ \frac {u \times v}{|u \times v|} ∣u×v∣u×v。
- 综上:KaTeX parse error: \tag works only in display equations
-向量 b b b:
- 大小:由图中几何关系, ∣ b ∣ = cos θ 1 ∣ v r o t ⊥ ∣ = cos ( π − θ ) ∣ v ⊥ ∣ = − cos θ ∣ v ⊥ ∣ |b| = \cos\theta_1 |v_{rot\perp}| = \cos (\pi - \theta) |v_{\perp}| = -\cos\theta |v_{\perp}| ∣b∣=cosθ1∣vrot⊥∣=cos(π−θ)∣v⊥∣=−cosθ∣v⊥∣(负号表示方向与 v ⊥ v_{\perp} v⊥ 相反)。
- 方向:与 v ⊥ v_{\perp} v⊥ 相反,单位方向向量为 − v ⊥ ∣ v ⊥ ∣ -\frac {v_{\perp}}{|v_{\perp}|} −∣v⊥∣v⊥。
- 综上:KaTeX parse error: \tag works only in display equations
至此,罗德里格斯公式的两种形式均推导完成。若需了解 Oxyz 坐标系下的旋转变换关系,可参考博客《图形变换之旋转变换公式推导》。
罗德里格斯公式描述了旋转向量到旋转矩阵的正向转换,下文将推导旋转矩阵到旋转向量的反向转换方法。
3. 旋转矩阵到旋转向量
3.1 旋转角 θ \theta θ 的求解
对旋转矩阵
R
R
R 取迹(主对角线元素之和),结合罗德里格斯公式:
tr
(
R
)
=
cos
θ
⋅
tr
(
I
)
+
(
1
−
cos
θ
)
⋅
tr
(
u
u
T
)
+
sin
θ
⋅
tr
(
u
∧
)
=
3
cos
θ
+
(
1
−
cos
θ
)
+
0
=
1
+
2
cos
θ
(3.1)
\begin {aligned} \text {tr}(R) &= \cos\theta \cdot \text {tr}(I) + (1 - \cos\theta) \cdot \text {tr}(uu^T) + \sin\theta \cdot \text {tr}(u^\wedge) \\ &= 3\cos\theta + (1 - \cos\theta) + 0 \\ &= 1 + 2\cos\theta \end {aligned} \tag {3.1}
tr(R)=cosθ⋅tr(I)+(1−cosθ)⋅tr(uuT)+sinθ⋅tr(u∧)=3cosθ+(1−cosθ)+0=1+2cosθ(3.1)
其中:
-
tr
(
I
)
=
3
\text {tr}(I) = 3
tr(I)=3(单位矩阵主对角线元素和为 3);
-
tr
(
u
u
T
)
=
u
T
u
=
1
\text {tr}(uu^T) = u^T u = 1
tr(uuT)=uTu=1(
u
u
T
uu^T
uuT 为秩 1 矩阵,迹等于主对角线元素和
u
x
2
+
u
y
2
+
u
z
2
=
1
u_x^2 + u_y^2 + u_z^2 = 1
ux2+uy2+uz2=1);
-
tr
(
u
∧
)
=
0
\text {tr}(u^\wedge) = 0
tr(u∧)=0(反对称矩阵主对角线元素均为 0)。
整理可得旋转角:
θ
=
arccos
(
tr
(
R
)
−
1
2
)
(3.2)
\theta = \arccos\left ( \frac {\text {tr}(R) - 1}{2} \right) \tag {3.2}
θ=arccos(2tr(R)−1)(3.2)
3.2 旋转轴 u u u 的求解
旋转轴上的向量在旋转后保持不变,即满足:
R
u
=
u
(3.3)
R u = u \tag {3.3}
Ru=u(3.3)
该式表明
u
u
u 是旋转矩阵
R
R
R 特征值为 1 对应的特征向量。通过求解特征方程
(
R
−
I
)
u
=
0
(R - I) u = 0
(R−I)u=0,得到特征向量后进行归一化处理,即可得到单位旋转轴
u
u
u。
结合旋转角 θ \theta θ 与旋转轴 u u u,旋转向量为 v = θ u v = \theta u v=θu。
实践部分的代码将在第三部分(四元数表示旋转)中统一演示。
本文基于《视觉 SLAM 十四讲:从理论到实践》与《Quaternions, Interpolation and Animation》编写,在原文基础上进行适当精简,并结合网络优质资源与作者理解补充注解及扩展知识点。
三维空间刚体运动 3:欧拉角表示旋转(全面理解万向锁、RPY 角和欧拉角)
龙焰智能 于 2024-07-09 16:52:33 修改
序
本系列文章参照高翔老师《视觉 SLAM 十四讲:从理论到实践》,系统讲解三维空间刚体运动的相关理论,为读者构建扎实的数学基础。
1. 欧拉角
1.1 定义
旋转矩阵与旋转向量虽能准确描述旋转,但缺乏直观性,而欧拉角通过三个分离的转角,将一次旋转分解为三次绕不同轴的旋转操作,提供了更符合人类认知习惯的描述方式。
欧拉角:在三维空间中,欧拉角用于描述从固定参考系的初始方向,经一系列基本旋转后,得到另一参考系方向的过程。该过程仅涉及姿态变换,原点位置保持不变。
在讨论欧拉角具体形式前,需明确以下概念:
1.坐标系类型:旋转描述依赖坐标系定义,本文统一采用右手坐标系进行讨论,不同坐标系类型(左手 / 右手)会导致数据呈现结果存在差异。
2.旋转形式:旋转可分为绕定点、绕坐标轴、绕任意轴等多种类型,本文聚焦三维空间中绕坐标轴的旋转操作,不同旋转形式对应不同数学表达方法。
3.欧拉角顺规:欧拉角的旋转次序称为顺规(Rotation Sequence),即三次旋转的轴顺序规定。相同转角 ( α , β , γ ) (\alpha, \beta, \gamma) (α,β,γ) 在不同顺规下会产生不同旋转结果,本文将根据具体旋转方式采用对应顺规。
4.静态与动态欧拉角:按参考坐标系分类,静态欧拉角以固定不变的绝对坐标系为参考(通常用小写 x x x- y y y- z z z 表示);动态欧拉角以随刚体运动的物体坐标系为参考(通常用大写 X X X- Y Y Y- Z Z Z 表示)。
1.2 RPY 角与 Z-Y-X 欧拉角
描述坐标系 B B B 相对于参考坐标系 A A A 的姿态,常用两种欧拉角形式:RPY 角与 Z-Y-X 欧拉角。
RPY 角(Roll-Pitch-Yaw):绕固定参考坐标系
A
A
A 的旋转过程,又称
X
X
X-
Y
Y
Y-
Z
Z
Z 固定角。初始状态下两坐标系重合,依次绕
A
A
A 的
X
X
X 轴旋转
α
\alpha
α(滚转角 Roll)、
Y
Y
Y 轴旋转
β
\beta
β(俯仰角 Pitch)、
Z
Z
Z 轴旋转
γ
\gamma
γ(偏航角 Yaw),最终得到目标姿态。其旋转矩阵满足:
R
X
Y
Z
(
α
,
β
,
γ
)
=
R
Z
(
γ
)
R
Y
(
β
)
R
X
(
α
)
(1.1)
R_{XYZ}(\alpha, \beta, \gamma) = R_Z (\gamma) R_Y (\beta) R_X (\alpha) \tag {1.1}
RXYZ(α,β,γ)=RZ(γ)RY(β)RX(α)(1.1)
旋转矩阵的乘法顺序与旋转操作顺序相反(从右至左),即先执行
R
X
(
α
)
R_X (\alpha)
RX(α),再执行
R
Y
(
β
)
R_Y (\beta)
RY(β),最后执行
R
Z
(
γ
)
R_Z (\gamma)
RZ(γ)。
Z-Y-X 欧拉角:绕刚体自身坐标系
B
B
B 的旋转过程,又称动态欧拉角。初始状态下两坐标系重合,依次绕
B
B
B 的
Z
Z
Z 轴旋转
γ
\gamma
γ、
Y
Y
Y 轴旋转
β
\beta
β、
X
X
X 轴旋转
α
\alpha
α,最终得到目标姿态。其旋转矩阵满足:
R
X
′
Y
′
Z
′
(
α
,
β
,
γ
)
=
R
Z
′
(
γ
)
R
Y
′
(
β
)
R
X
′
(
α
)
(1.2)
R_{X'Y'Z'}(\alpha, \beta, \gamma) = R_{Z'}(\gamma) R_{Y'}(\beta) R_{X'}(\alpha) \tag {1.2}
RX′Y′Z′(α,β,γ)=RZ′(γ)RY′(β)RX′(α)(1.2)
旋转矩阵的乘法顺序与旋转操作顺序一致(从左至右),即先执行
R
Z
′
(
γ
)
R_{Z'}(\gamma)
RZ′(γ),再执行
R
Y
′
(
β
)
R_{Y'}(\beta)
RY′(β),最后执行
R
X
′
(
α
)
R_{X'}(\alpha)
RX′(α)。
需要注意的是,上述两种旋转方式的展开式完全相等,即绕固定坐标系 X X X- Y Y Y- Z Z Z 的 RPY 角旋转,与绕动态坐标系 Z Z Z- Y Y Y- X X X 的欧拉角旋转等价。
结合航空领域常用定义进一步阐释:RPY 角(偏航 - 俯仰 - 滚转,Yaw-Pitch-Roll)的旋转顺序为绕固定坐标系 Z Z Z 轴(偏航 Yaw)→ Y Y Y 轴(俯仰 Pitch)→ X X X 轴(滚转 Roll),对应顺规为 Z Z Z- Y Y Y- X X X,与上述 Z-Y-X 欧拉角的旋转效果一致。此时可通过三维向量 [ r , p , y ] T [r, p, y]^T [r,p,y]T(滚转角、俯仰角、偏航角)描述任意旋转。为减少万向锁发生概率,实际应用中常采用 Z Z Z- X X X- Y Y Y 顺规,但无法完全消除该问题,具体原因将在后续章节说明。
图 1.1 Oxyz 坐标轴旋转
2. 欧拉角到旋转矩阵
旋转矩阵具有三个自由度,可与欧拉角相互转换。欧拉角对应的旋转矩阵可通过三次基本旋转矩阵(绕 X X X、 Y Y Y、 Z Z Z 轴的旋转矩阵)的乘积得到,以下为具体推导过程:
2.1 二维基本旋转矩阵推导
以绕 Z Z Z 轴旋转为例,推导二维旋转矩阵,再扩展至三维。设平面内点 P ( x , y ) P (x, y) P(x,y) 绕原点旋转 θ \theta θ 后得到 P ′ ( x ′ , y ′ ) P'(x', y') P′(x′,y′), O P = O P ′ = d = x 2 + y 2 OP = OP' = d = \sqrt {x^2 + y^2} OP=OP′=d=x2+y2,初始角度为 α \alpha α( P P P 与 X X X 轴夹角)。
根据三角函数定义:
{
sin
α
=
y
d
cos
α
=
x
d
(2.1)
\begin {cases} \sin\alpha = \frac {y}{d} \\ \cos\alpha = \frac {x}{d} \end {cases} \tag {2.1}
{sinα=dycosα=dx(2.1)
{
sin
(
α
+
θ
)
=
y
′
d
cos
(
α
+
θ
)
=
x
′
d
(2.2)
\begin {cases} \sin (\alpha + \theta) = \frac {y'}{d} \\ \cos (\alpha + \theta) = \frac {x'}{d} \end {cases} \tag {2.2}
{sin(α+θ)=dy′cos(α+θ)=dx′(2.2)
利用两角和差公式展开:
{
sin
(
α
+
θ
)
=
sin
α
cos
θ
+
cos
α
sin
θ
cos
(
α
+
θ
)
=
cos
α
cos
θ
−
sin
α
sin
θ
(2.3)
\begin {cases} \sin (\alpha + \theta) = \sin\alpha\cos\theta + \cos\alpha\sin\theta \\ \cos (\alpha + \theta) = \cos\alpha\cos\theta - \sin\alpha\sin\theta \end {cases} \tag {2.3}
{sin(α+θ)=sinαcosθ+cosαsinθcos(α+θ)=cosαcosθ−sinαsinθ(2.3)
将式(2.1)代入式(2.3),消去
d
d
d 与
α
\alpha
α,得到:
{
x
′
=
x
cos
θ
−
y
sin
θ
y
′
=
x
sin
θ
+
y
cos
θ
(2.4)
\begin {cases} x' = x\cos\theta - y\sin\theta \\ y' = x\sin\theta + y\cos\theta \end {cases} \tag {2.4}
{x′=xcosθ−ysinθy′=xsinθ+ycosθ(2.4)
以齐次坐标表示,旋转过程可写为矩阵乘法形式:
P
′
~
=
[
x
′
y
′
1
]
=
[
cos
θ
−
sin
θ
0
sin
θ
cos
θ
0
0
0
1
]
[
x
y
1
]
=
R
Z
(
θ
)
P
~
(2.5)
\tilde {P'} = \begin {bmatrix} x' \\ y' \\ 1 \end {bmatrix} = \begin {bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end {bmatrix} \begin {bmatrix} x \\ y \\ 1 \end {bmatrix} = R_Z (\theta) \tilde {P} \tag {2.5}
P′~=
x′y′1
=
cosθsinθ0−sinθcosθ0001
xy1
=RZ(θ)P~(2.5)
因此,绕
Z
Z
Z 轴的三维旋转矩阵为:
R
Z
(
θ
)
=
[
cos
θ
−
sin
θ
0
sin
θ
cos
θ
0
0
0
1
]
(2.6)
R_Z (\theta) = \begin {bmatrix} \cos\theta & -\sin\theta & 0 \\ \sin\theta & \cos\theta & 0 \\ 0 & 0 & 1 \end {bmatrix} \tag {2.6}
RZ(θ)=
cosθsinθ0−sinθcosθ0001
(2.6)
2.2 绕 X X X、 Y Y Y 轴的旋转矩阵
同理,可推导出绕 X X X 轴与 Y Y Y 轴的三维旋转矩阵:
- 绕
X
X
X 轴旋转矩阵:
R X ( θ ) = [ 1 0 0 0 cos θ − sin θ 0 sin θ cos θ ] (2.7) R_X (\theta) = \begin {bmatrix} 1 & 0 & 0 \\ 0 & \cos\theta & -\sin\theta \\ 0 & \sin\theta & \cos\theta \end {bmatrix} \tag {2.7} RX(θ)= 1000cosθsinθ0−sinθcosθ (2.7) - 绕
Y
Y
Y 轴旋转矩阵:
R Y ( θ ) = [ cos θ 0 sin θ 0 1 0 − sin θ 0 cos θ ] (2.8) R_Y (\theta) = \begin {bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end {bmatrix} \tag {2.8} RY(θ)= cosθ0−sinθ010sinθ0cosθ (2.8)
2.3 组合旋转矩阵
欧拉角对应的组合旋转矩阵为三次基本旋转矩阵的乘积,乘法顺序与旋转操作顺序相反(从右至左)。对于
Z
Z
Z-
Y
Y
Y-
X
X
X 顺规(先绕
Z
Z
Z 轴,再绕
Y
Y
Y 轴,最后绕
X
X
X 轴),组合旋转矩阵为:
R
Z
Y
X
(
α
,
β
,
γ
)
=
R
X
(
α
)
R
Y
(
β
)
R
Z
(
γ
)
(2.9)
R_{ZYX}(\alpha, \beta, \gamma) = R_X (\alpha) R_Y (\beta) R_Z (\gamma) \tag {2.9}
RZYX(α,β,γ)=RX(α)RY(β)RZ(γ)(2.9)
其中
α
\alpha
α 为绕
X
X
X 轴的滚转角,
β
\beta
β 为绕
Y
Y
Y 轴的俯仰角,
γ
\gamma
γ 为绕
Z
Z
Z 轴的偏航角。
3. 旋转矩阵到欧拉角
已知旋转矩阵
R
R
R,可通过矩阵元素与三角函数的对应关系求解欧拉角。将式(2.9)展开,得到
Z
Z
Z-
Y
Y
Y-
X
X
X 顺规下旋转矩阵的具体形式:
R
=
[
R
11
R
12
R
13
R
21
R
22
R
23
R
31
R
32
R
33
]
=
[
cos
β
cos
γ
−
cos
β
sin
γ
sin
β
sin
α
sin
β
cos
γ
+
cos
α
sin
γ
−
sin
α
sin
β
sin
γ
+
cos
α
cos
γ
−
sin
α
cos
β
−
cos
α
sin
β
cos
γ
+
sin
α
sin
γ
cos
α
sin
β
sin
γ
+
sin
α
cos
γ
cos
α
cos
β
]
(3.1)
\begin {aligned} R &= \begin {bmatrix} R_{11} & R_{12} & R_{13} \\ R_{21} & R_{22} & R_{23} \\ R_{31} & R_{32} & R_{33} \end {bmatrix} \\&= \begin {bmatrix} \cos\beta\cos\gamma & -\cos\beta\sin\gamma & \sin\beta \\ \sin\alpha\sin\beta\cos\gamma + \cos\alpha\sin\gamma & -\sin\alpha\sin\beta\sin\gamma + \cos\alpha\cos\gamma & -\sin\alpha\cos\beta \\ -\cos\alpha\sin\beta\cos\gamma + \sin\alpha\sin\gamma & \cos\alpha\sin\beta\sin\gamma + \sin\alpha\cos\gamma & \cos\alpha\cos\beta \end {bmatrix} \tag {3.1} \end {aligned}
R=
R11R21R31R12R22R32R13R23R33
=
cosβcosγsinαsinβcosγ+cosαsinγ−cosαsinβcosγ+sinαsinγ−cosβsinγ−sinαsinβsinγ+cosαcosγcosαsinβsinγ+sinαcosγsinβ−sinαcosβcosαcosβ
(3.1)
通过矩阵元素求解欧拉角:
- 由
R
13
=
sin
β
R_{13} = \sin\beta
R13=sinβ,得俯仰角:
β = arcsin ( R 13 ) (3.2) \beta = \arcsin (R_{13}) \tag {3.2} β=arcsin(R13)(3.2) - 由
−
R
23
R
33
=
tan
α
-\frac {R_{23}}{R_{33}} = \tan\alpha
−R33R23=tanα,得滚转角:
α = arctan ( − R 23 R 33 ) (3.3) \alpha = \arctan\left (-\frac {R_{23}}{R_{33}}\right) \tag {3.3} α=arctan(−R33R23)(3.3) - 由
−
R
12
R
11
=
tan
γ
-\frac {R_{12}}{R_{11}} = \tan\gamma
−R11R12=tanγ,得偏航角:
γ = arctan ( − R 12 R 11 ) (3.4) \gamma = \arctan\left (-\frac {R_{12}}{R_{11}}\right) \tag {3.4} γ=arctan(−R11R12)(3.4)
上述推导过程中,当 β = ± 9 0 ∘ \beta = \pm 90^\circ β=±90∘ 时会出现奇异值,即万向锁问题,具体分析如下。
4. 万向锁
4.1 定义
万向锁问题(Gimbal Lock):欧拉角的本质是通过三次绕轴旋转描述三维姿态,但当中间轴的旋转角度为 ± 9 0 ∘ \pm 90^\circ ±90∘ 时,第一次旋转与第三次旋转的轴会重合,导致系统丢失一个自由度(三次旋转退化为两次旋转),这种奇异现象称为万向锁。
理论上,任何通过三个实数描述三维旋转的方式都无法避免奇异性问题。因此,欧拉角不适用于插值、迭代等需要连续姿态变化的场景,仅常用于人机交互等对直观性要求较高的场景,在 SLAM 程序、滤波与优化算法中较少使用。
4.2 Z-Y-X 顺规下的万向锁分析
以 Z Z Z- Y Y Y- X X X 顺规为例,结合几何原理与数学推导说明万向锁的产生机制:
4.2.1 几何解释
Z Z Z- Y Y Y- X X X 顺规的旋转轴存在层级关系: Z Z Z 轴为 Y Y Y 轴的父级, Y Y Y 轴为 X X X 轴的父级。绕 Z Z Z 轴旋转时, Y Y Y 轴与 X X X 轴随刚体同步旋转;绕 Y Y Y 轴旋转时,仅 X X X 轴随刚体旋转;绕 X X X 轴旋转时, Z Z Z 轴与 Y Y Y 轴保持固定。
当绕 Y Y Y 轴旋转 β = 9 0 ∘ \beta = 90^\circ β=90∘ 时, X X X 轴会旋转至与初始 Z Z Z 轴重合的位置,此时绕 X X X 轴的旋转与绕 Z Z Z 轴的旋转效果等价,原本独立的三个自由度退化为两个,导致无法实现绕初始 X X X 轴的独立旋转,即丢失一个自由度。
图 4.1 ZYX 欧拉旋转 - 1
图 4.2 ZYX 欧拉旋转 - 2
图 4.3 ZYX 欧拉旋转 - 3
4.2.2 数学验证
将 β = π 2 \beta = \frac {\pi}{2} β=2π 代入式(2.9),展开旋转矩阵:
R Z Y X ( α , π 2 , γ ) = R X ( γ ) R Y ( π 2 ) R Z ( α ) = [ 0 0 1 sin α cos γ + cos α sin γ − sin α sin γ + cos α cos γ 0 − cos α cos γ + sin α sin γ cos α sin γ + sin α cos γ 0 ] = [ 0 0 1 sin ( α + γ ) cos ( α + γ ) 0 − cos ( α + γ ) sin ( α + γ ) 0 ] = R Y ( π 2 ) R Z ( α + γ ) (4.1) \begin{aligned} R_{ZYX}\left(\alpha, \frac{\pi}{2}, \gamma\right) &= R_X(\gamma) R_Y\left(\frac{\pi}{2}\right) R_Z(\alpha) \\ &= \begin{bmatrix} 0 & 0 & 1 \\ \sin\alpha\cos\gamma + \cos\alpha\sin\gamma & -\sin\alpha\sin\gamma + \cos\alpha\cos\gamma & 0 \\ -\cos\alpha\cos\gamma + \sin\alpha\sin\gamma & \cos\alpha\sin\gamma + \sin\alpha\cos\gamma & 0 \end{bmatrix} \\ &= \begin{bmatrix} 0 & 0 & 1 \\ \sin(\alpha + \gamma) & \cos(\alpha + \gamma) & 0 \\ -\cos(\alpha + \gamma) & \sin(\alpha + \gamma) & 0 \end{bmatrix} \\ &= R_Y\left(\frac{\pi}{2}\right) R_Z(\alpha + \gamma) \end{aligned} \tag{4.1} RZYX(α,2π,γ)=RX(γ)RY(2π)RZ(α)= 0sinαcosγ+cosαsinγ−cosαcosγ+sinαsinγ0−sinαsinγ+cosαcosγcosαsinγ+sinαcosγ100 = 0sin(α+γ)−cos(α+γ)0cos(α+γ)sin(α+γ)100 =RY(2π)RZ(α+γ)(4.1)
推导结果表明,原本由三个旋转矩阵组成的组合变换,退化为两个旋转矩阵的乘积, α \alpha α 与 γ \gamma γ 合并为一个角度 α + γ \alpha + \gamma α+γ,证明系统丢失一个自由度。
对于其他顺规(如 X X X- Y Y Y- Z Z Z、 Z Z Z- X X X- Y Y Y 等),当中间轴旋转角度为 ± 9 0 ∘ \pm 90^\circ ±90∘ 时,均会出现类似的轴重合现象,导致万向锁。
4.3 解决方法
针对万向锁问题,常用两种应对策略:
1.优化顺规规避风险:选择刚体运动中较少出现中间轴旋转至 ± 9 0 ∘ \pm 90^\circ ±90∘ 的顺规,可最大程度减少万向锁发生概率,但无法完全避免。例如,相机姿态描述中常用 Z Z Z- X X X- Y Y Y 顺规,利用相机较少朝天 / 朝地拍摄的使用场景,降低俯仰角达到 ± 9 0 ∘ \pm 90^\circ ±90∘ 的可能性。
2.采用四元数描述旋转:四元数通过四个实数描述三维旋转,不存在奇异性问题,可彻底解决万向锁。具体做法为:将欧拉角转换为四元数,通过球面线性插值(SLERP)获取连续姿态,再将四元数转回欧拉角应用于刚体。该方法的缺点是需额外存储四元数参数,消耗一定内存,四元数的详细讲解见后续文章。
5. 实践:Eigen 几何模块
本节通过 Eigen 库演示旋转向量、欧拉角与旋转矩阵之间的转换操作,代码包含详细注释,可直接编译运行。
5.1 代码实现
#include <iostream>
#include <cmath>
using namespace std;
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Geometry>
using namespace Eigen;
// 本程序演示 Eigen 几何模块的旋转表示与转换
int main (int argc, char**argv) {
// 1. 初始化旋转矩阵(单位矩阵)
Matrix3d rotation_matrix = Matrix3d::Identity ();
// 2. 定义旋转向量(绕 Z 轴旋转 45°,即 M_PI/4 弧度)
AngleAxisd rotation_vector (M_PI / 4, Vector3d (0, 0, 1));
cout.precision (3); // 设置输出精度为 3 位小数
cout << "旋转向量对应的矩阵:\n" << rotation_vector.matrix () << endl;
// 3. 旋转向量转换为旋转矩阵
rotation_matrix = rotation_vector.toRotationMatrix ();
cout << "旋转向量转旋转矩阵:\n" << rotation_matrix << endl;
// 4. 坐标变换(使用旋转向量与旋转矩阵)
Vector3d v (1, 0, 0); // 初始向量
Vector3d v_rotated_by_vector = rotation_vector * v;
Vector3d v_rotated_by_matrix = rotation_matrix * v;
cout << "初始向量 (1,0,0) 经旋转向量变换后:" << v_rotated_by_vector.transpose () << endl;
cout << "初始向量 (1,0,0) 经旋转矩阵变换后:" << v_rotated_by_matrix.transpose () << endl;
// 5. 旋转矩阵转换为欧拉角(顺规:Z-Y-X,对应 yaw-pitch-roll)
Vector3d euler_angles = rotation_matrix.eulerAngles (2, 1, 0);
cout << "欧拉角 (yaw, pitch, roll):" << euler_angles.transpose () << endl;
// 6. 定义欧式变换矩阵(包含旋转与平移)
Isometry3d T = Isometry3d::Identity (); // 初始为单位矩阵
T.rotate (rotation_vector); // 加入旋转
T.pretranslate (Vector3d (1, 3, 4)); // 加入平移(x=1, y=3, z=4)
cout << "欧式变换矩阵:\n" << T.matrix () << endl;
// 7. 欧式变换矩阵进行坐标变换
Vector3d v_transformed = T * v; // 注意:Eigen 中乘法已重载,无需显式转换为齐次坐标
cout << "初始向量 (1,0,0) 经欧式变换后:" << v_transformed.transpose () << endl;
return 0;
}
5.2 运行结果
rotation matrix =
1 0 0
0 1 0
0 0 1
rotation vector =
0.707 -0.707 0
0.707 0.707 0
0 0 1
rotation vector to Matrix =
0.707 -0.707 0
0.707 0.707 0
0 0 1
(1,0,0) after rotation (by angle axis) = 0.707 0.707 0
(1,0,0) after rotation (by matrix) = 0.707 0.707 0
yaw pitch roll = 0.785 -0 0
Isometry3d T =
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
T rotate rotation_vector =
0.707 -0.707 0 0
0.707 0.707 0 0
0 0 1 0
0 0 0 1
Transform matrix =
0.707 -0.707 0 1
0.707 0.707 0 3
0 0 1 4
0 0 0 1
v = 1 0 0
v transofrmed = 1.71 3.71 4
5.3 结果分析
- 旋转向量与旋转矩阵对同一向量的变换结果一致,验证了两者的等价性;
- 欧拉角输出中,yaw = 0.785 rad(即 45°),pitch 与 roll 为 0,符合绕 Z 轴旋转 45° 的设定;
- 欧式变换矩阵同时包含旋转(上左 3×3 子矩阵)与平移(上右 3×1 子矩阵),变换后向量的坐标为旋转与平移的叠加结果。
参考文献
- 《视觉 SLAM 十四讲:从理论到实践》,高翔、张涛等著,中国工信出版社
- 罗德里格斯公式推导
- 四元数与三维旋转
- 四元数与欧拉角(RPY 角)的相互转换
- 图形变换之旋转变换公式推导
- Bonus: Gimbal Lock By Krasjet
via:
- 三维空间刚体运动 1:旋转矩阵与变换矩阵(详解加代码示例)_二维平面刚体变换矩阵 - 优快云 博客
https://blog.youkuaiyun.com/shao918516/article/details/105062787 - 三维空间刚体运动 2:旋转向量与罗德里格斯公式(最详细推导)_空间刚体位移计算公式 - 优快云 博客
https://blog.youkuaiyun.com/shao918516/article/details/105109278 - 三维空间刚体运动 3:欧拉角表示旋转(全面理解万向锁、RPY 角和欧拉角)-优快云 博客
https://blog.youkuaiyun.com/shao918516/article/details/105172829





2万+

被折叠的 条评论
为什么被折叠?



