本章目录

三维旋转与姿态更新

在二维平面内讨论刚体运动时,只需一个转角就能完整确定刚体的朝向;然而一旦进入三维空间,刚体便可以绕空间中的任意方向转动,单靠一个标量角度已不足以刻画其空间朝向。不妨以桌上的一本书为例:沿着书本的长边、短边以及封面的外法线方向,可以在书本上固定三根相互垂直的坐标轴。当书本在空间中翻动时,这三根坐标轴也会随着书本一同转动。

只要明确了这三根随体坐标轴在空间中的指向,书本的朝向——即刚体的姿态——也就完全确定了。进一步地,如果我们能够用角速度刻画这三根坐标轴随时间的瞬时变化率,就可以建立起三维姿态的数学表示、微分方程以及时间步更新方法。

坐标约定

全文采用右手坐标系,所有向量均按列向量书写。空间中固定不动的参考系称为世界坐标系,固连在刚体上并随刚体一同运动的参考系称为物体坐标系(或随体坐标系)。推导中的角度统一采用弧度制,转角的正方向遵循右手定则:右手拇指指向旋转轴的正方向,四指弯曲的方向即为正转角方向。

01

旋转矩阵

为了单独研究转动,我们先将书本的中心固定在世界坐标系的原点。在书本上沿着长边、短边和封面法线建立三根相互垂直的单位坐标轴,随着书本转到某个姿态,这三根物体坐标轴在世界坐标系下各自对应一个三维单位向量,依次记为 \boldsymbol b_1,\boldsymbol b_2,\boldsymbol b_3。将这三个列向量按顺序并排组合,便构成一个 3\times 3 矩阵:

R=\begin{bmatrix}\boldsymbol b_1&\boldsymbol b_2&\boldsymbol b_3\end{bmatrix}.
(2.1)

这个矩阵 R 就是描述刚体当前姿态的旋转矩阵。它不仅直接记录了三根物体坐标轴在世界系中的方向,还给出了从物体坐标系到世界坐标系的坐标变换关系。

具体而言,设书本上某一点在物体坐标系中的局部坐标为 \boldsymbol p=(p_1,p_2,p_3)^{\mathsf T},在世界坐标系中的坐标为 \boldsymbol x。由于局部坐标的三个分量分别表示该点沿三根物体坐标轴的位移尺度,将该点的位置向量沿这三根轴展开,即可写出:

\boldsymbol x=p_1\boldsymbol b_1+p_2\boldsymbol b_2+p_3\boldsymbol b_3=R\boldsymbol p.
(2.2)

由此可见,用旋转矩阵 R 左乘局部坐标向量 \boldsymbol p,几何上就是以 p_1,p_2,p_3 为权重对三根物体坐标轴 \boldsymbol b_1,\boldsymbol b_2,\boldsymbol b_3 作线性组合。特别地,若依次取局部单位向量 \boldsymbol p=(1,0,0)^{\mathsf T}、(0,1,0)^{\mathsf T} 和 (0,0,1)^{\mathsf T} 代入式(2.2),乘积结果便分别提取出矩阵 R 的第一列、第二列和第三列。

思考已知旋转矩阵,怎样直接读出物体第二根坐标轴的方向?

物体第二根坐标轴在自身局部坐标系下的坐标为 (0,1,0)^{\mathsf T}。将其代入坐标变换关系 \boldsymbol x=R\boldsymbol p,矩阵乘法恰好只保留 R 的第二列。因此,旋转矩阵的第二列就是物体第二根坐标轴在世界坐标系中的方向向量。在下图的交互实验中选中第二列,可以将矩阵数值与空间中的坐标轴箭头直接对照。

实验 01旋转矩阵与坐标轴

先选择第三根轴作为转轴,将转角设为四分之一周,比较矩阵的三列与物体轴的对应关系。拖动画面可调整视角。

例题:绕坐标轴旋转

假设物体坐标系最初与世界坐标系完全重合。将刚体绕世界系的正 z 轴逆时针转过 \pi/2 后,物体的第一根轴转到了世界系的正 y 方向 (0,1,0)^{\mathsf T},第二根轴转到了世界系的负 x 方向 (-1,0,0)^{\mathsf T},而第三根轴仍保持在正 z 方向 (0,0,1)^{\mathsf T}。将这三个方向按列排成旋转矩阵,并对局部点 (2,-1,3)^{\mathsf T} 作变换,可得:

R_z(\pi/2)=\begin{bmatrix}0&-1&0\\1&0&0\\0&0&1\end{bmatrix},\qquad R_z(\pi/2)\begin{bmatrix}2\\-1\\3\end{bmatrix}=\begin{bmatrix}1\\2\\3\end{bmatrix}.

编写程序实现旋转矩阵时,可以先代入三个坐标轴单位向量以及像上面这样的一般向量,通过检验旋转后的方向和向量长度是否符合几何直觉来排查符号或行列次序错误。

方向变化与坐标换算

对于关系式 \boldsymbol x=R\boldsymbol p,我们可以从两个互补的视角来理解:如果考察的是固连在书本上的一个材料点,那么它的局部坐标 \boldsymbol p 恒定不变,当书本转动即 R 改变时,式(2.2)给出了该点在世界系中的新位置 \boldsymbol x;如果考察的是空间中固定不动的一个点,那么它的世界坐标 \boldsymbol x 恒定不变,当书本转动时,同一空间点在书本坐标系下的读数 \boldsymbol p 会随之改变。无论从哪个视角看待,矩阵 R 的三列始终是书本三根坐标轴在世界系中的方向向量。

这自然引出一个逆向问题:已知空间向量在世界系下的坐标 \boldsymbol x,如何反求它在物体坐标系下的三个分量 p_1,p_2,p_3?由于三根物体坐标轴彼此垂直且长度均为 1,要求 \boldsymbol x 沿第一根物体轴的分量,只需将 \boldsymbol x 向 \boldsymbol b_1 作正交投影,即计算内积 p_1=\boldsymbol b_1^{\mathsf T}\boldsymbol x;同理可得 p_2=\boldsymbol b_2^{\mathsf T}\boldsymbol x 与 p_3=\boldsymbol b_3^{\mathsf T}\boldsymbol x。注意到行向量 \boldsymbol b_1^{\mathsf T},\boldsymbol b_2^{\mathsf T},\boldsymbol b_3^{\mathsf T} 恰好组成了转置矩阵 R^{\mathsf T} 的三行,上述三次投影运算可以合并写为 \boldsymbol p=R^{\mathsf T}\boldsymbol x。在前面的例题中,将世界向量 (1,2,3)^{\mathsf T} 依次向旋转后的三根物体轴作内积投影,得到的分量正是 2,-1,3,恰好还原出最初的局部坐标。

旋转矩阵的性质

刚体在转动过程中不会发生拉伸或剪切变形,因此固连在书本上的三根坐标轴始终保持单位长度、彼此两两正交,并且维持右手系朝向不变。将这三条几何约束翻译成矩阵代数语言,就得到旋转矩阵必须满足的两项基本条件:

R^{\mathsf T}R=I,\qquad \det R=1.
(2.3)

式中 I 为三阶单位矩阵。第一个等式称为正交性条件,它保证了旋转前后向量的长度与向量间的夹角保持不变;第二个等式保证了变换不会把右手坐标系翻转为左手镜像系。所有满足式(2.3)的三阶实矩阵在矩阵乘法下构成一个群,称为三维特殊正交群(Special Orthogonal Group),记作 \mathrm{SO}(3)。后文中写 R\in\mathrm{SO}(3),即表示 R 是一个合法的三维旋转矩阵。

推导正交条件、逆矩阵与行列式R^{-1}=R^{\mathsf T},\quad \det R=1

1. 由坐标轴正交归一性导出 R^{\mathsf T}R=I。由于 R^{\mathsf T} 的第 i 行正是列向量 \boldsymbol b_i 的转置,按分块矩阵乘法展开 R^{\mathsf T}R 可得:

R^{\mathsf T}R=\begin{bmatrix}\boldsymbol b_1^{\mathsf T}\boldsymbol b_1&\boldsymbol b_1^{\mathsf T}\boldsymbol b_2&\boldsymbol b_1^{\mathsf T}\boldsymbol b_3\\\boldsymbol b_2^{\mathsf T}\boldsymbol b_1&\boldsymbol b_2^{\mathsf T}\boldsymbol b_2&\boldsymbol b_2^{\mathsf T}\boldsymbol b_3\\\boldsymbol b_3^{\mathsf T}\boldsymbol b_1&\boldsymbol b_3^{\mathsf T}\boldsymbol b_2&\boldsymbol b_3^{\mathsf T}\boldsymbol b_3\end{bmatrix}=I.

该乘积矩阵的主对角线元素是各根单位轴与自身的内积(即长度平方 \|\boldsymbol b_i\|^2=1),非对角线元素则是不同坐标轴之间的内积(因两两垂直而等于 0)。由此立得 R^{-1}=R^{\mathsf T},说明旋转矩阵的逆矩阵就是它的转置矩阵,反向坐标变换可直接写为 \boldsymbol p=R^{\mathsf T}\boldsymbol x。

2. 证明旋转保持内积、长度与夹角不变。任取两个向量 \boldsymbol u,\boldsymbol v\in\mathbb R^3,计算它们旋转后的内积:

(R\boldsymbol u)^{\mathsf T}(R\boldsymbol v)=\boldsymbol u^{\mathsf T}R^{\mathsf T}R\boldsymbol v=\boldsymbol u^{\mathsf T}\boldsymbol v.

取 \boldsymbol u=\boldsymbol v 即得 \|R\boldsymbol u\|^2=\|\boldsymbol u\|^2,说明向量的长度在旋转下保持不变;再结合内积公式 \boldsymbol u^{\mathsf T}\boldsymbol v=\|\boldsymbol u\|\|\boldsymbol v\|\cos\gamma,可知两向量之间的夹角 \gamma 同样保持不变。

3. 确定行列式的符号。对 R^{\mathsf T}R=I 两边取行列式,利用 \det(R^{\mathsf T})=\det R 可得 (\det R)^2=1,故正交矩阵的行列式只能取 1 或 -1。由于刚体的任意姿态都可以从初始重合姿态 R=I(此时 \det I=1)经由连续转动到达,而在连续变化过程中行列式不可能从 1 跃变到 -1,因此刚体旋转矩阵必满足 \det R=1;行列式为 -1 的正交矩阵对应包含镜像反射的变换,会改变空间的手性。综上,三维旋转矩阵集合定义为:

\mathrm{SO}(3)=\{R\in\mathbb R^{3\times3}:R^{\mathsf T}R=I,\ \det R=1\}.

在物理引擎的实际场景中,刚体除了绕自身参考点转动外,参考点本身还会在空间中平移。设刚体参考点(如质心或局部原点)在世界系中的位置向量为 \boldsymbol c,刚体上某一点的局部坐标为 \boldsymbol p,则该点在世界系中的绝对位置就是先将局部相对位移旋转到世界系、再加上参考点位置,即 \boldsymbol x=\boldsymbol c+R\boldsymbol p。这一表达式将刚体的平移与转动统一为空间点的完整位姿变换。

02

旋转的复合

在二维平面中,先后转过两个角度的结果与次序无关;但在三维空间里,情况截然不同。你可以拿手边的书本做一个简单的试验:先绕桌面横轴(x 轴)将平放的书本向上立起 90^\circ,再绕桌面纵轴(y 轴)转过 90^\circ;随后把书放回原位,调换这两步的先后次序重新操作一次。你会发现,书本最终的朝向完全不同。当我们用旋转矩阵记录连续多次转动时,这种对先后次序的敏感性就直接反映在矩阵乘法的不可交换性上。

设刚体先后经历了两次旋转,对应的旋转矩阵分别为 A 和 B,且两次旋转的转轴都在固定的世界坐标系下指定。对于原处于 \boldsymbol x 处的向量,第一次旋转将其变为 A\boldsymbol x,第二次旋转再对所得结果作用矩阵 B,使其变为 B(A\boldsymbol x)=(BA)\boldsymbol x。因此,两次世界系旋转复合后的总旋转矩阵是 BA——按时间先后依次发生的固定轴旋转,在矩阵乘法中应当从右向左依次左乘,最先执行的旋转排在最右侧。

实验 02旋转次序对姿态的影响

两次转动都绕固定的世界轴进行。分别观察两种次序下,书本法线最后指向哪里;用图例可以单独查看其中一种结果。

在实验 02 中将两个转角均设为 90^\circ,可以清晰地看到两种次序的分歧所在:若先绕世界横轴 x、再绕世界纵轴 y 旋转,书本封面法线在第一步后已经转到了负纵轴方向,恰好与第二步的旋转轴共线,因此第二步旋转不再改变法线方向,使其最终停留在负纵轴;反之,若先绕世界纵轴 y、再绕世界横轴 x 旋转,封面法线在第一步后转到了正横轴方向,从而在第二步绕横轴旋转时保持不动,最终指向正横轴。虽然两次操作使用了完全相同的世界转轴与转角,但第一次转动改变了物体与第二根转轴之间的相对位置,这正是 BA 与 AB 结果不同的几何根源。

推导两次坐标轴旋转的复合R_yR_x\ne R_xR_y

写出绕世界系正 x 轴和正 y 轴分别旋转 \pi/2 的旋转矩阵:

R_x=\begin{bmatrix}1&0&0\\0&0&-1\\0&1&0\end{bmatrix},\qquad R_y=\begin{bmatrix}0&0&1\\0&1&0\\-1&0&0\end{bmatrix}.

追踪书本初始封面法线 \boldsymbol e_z=(0,0,1)^{\mathsf T} 的去向。若先绕 x 轴、后绕 y 轴旋转,法线依次变为:

\boldsymbol e_z\xrightarrow{R_x}-\boldsymbol e_y\xrightarrow{R_y}-\boldsymbol e_y.

若调换次序,先绕 y 轴、后绕 x 轴旋转,法线则依次变为:

\boldsymbol e_z\xrightarrow{R_y}\boldsymbol e_x\xrightarrow{R_x}\boldsymbol e_x.

同一初始向量在两种次序下分别变为 -\boldsymbol e_y 和 \boldsymbol e_x,直接验证了 R_yR_x\ne R_xR_y。因此在三维空间中描述复合旋转时,必须同时指明各次旋转所参考的坐标系与作用次序。

坐标变换的复合

除了在固定世界系下连续施加旋转外,物理引擎中另一类极为常见的复合运算是沿着多体机构的父子层级逐级换算坐标。例如,机器人的手掌连接在前臂末端,手掌的姿态通常是相对于前臂坐标系给出的,而前臂的姿态又是相对于世界坐标系给出的。记前臂相对于世界系的旋转矩阵为 A,手掌相对于前臂系的旋转矩阵为 B。对于手掌上的一个局部方向向量 \boldsymbol p,先左乘 B 可得它在前臂坐标系中的表示 B\boldsymbol p;随后再左乘 A,即可将它从前臂系进一步变换到世界系:

\boldsymbol x=A(B\boldsymbol p)=(AB)\boldsymbol p,\qquad R=AB.
(2.4)

由此可知,将父刚体的世界姿态矩阵 A 与子刚体相对于父刚体的局部姿态矩阵 B 按 AB 次序相乘,所得矩阵 R 就直接给出了子刚体在世界坐标系下的姿态。后续章节在运动学树上由根节点向叶节点递推计算各连杆的世界姿态时,核心运算正是式(2.4)所示的相对变换右乘复合。

思考题

已知前臂的世界姿态 A 和手掌的世界姿态 R,求手掌相对于前臂的姿态 B。

答案相对姿态的计算

利用正交矩阵的性质 A^{\mathsf T}A=I,在关系式 R=AB 两边同时左乘 A^{\mathsf T},即可解出:

A^{\mathsf T}R=A^{\mathsf T}AB=B.

从坐标变换的角度看,乘积 A^{\mathsf T}R 的几何含义十分清晰:右边的 R 先将手掌系下的局部向量变换到世界系,左边的 A^{\mathsf T} 再将世界系下的向量投影回前臂坐标系,两步合起来恰好完成了从手掌系到前臂系的相对姿态变换。

03

轴角表示与 Rodrigues 公式

上一节用三根随体坐标轴的方向拼成了含有九个元素的旋转矩阵。一个自然的问题随之产生:无论刚体经历了多么复杂的转动过程,从初始姿态到当前姿态的净效果,能否等价为绕空间中某一条固定轴的一次单轴旋转?三维欧拉旋转定理给出了肯定的回答:任意三维旋转矩阵 R\in\mathrm{SO}(3) 都存在一条保持方向不变的单位旋转轴 \boldsymbol n,满足 R\boldsymbol n=\boldsymbol n;与此同时,与 \boldsymbol n 垂直的平面在旋转前后仍映射回该平面自身,全部三维旋转都归结为该垂直平面内转过的一个角度 \theta。

推导三维旋转轴的存在R\boldsymbol n=\boldsymbol n,\quad\|\boldsymbol n\|=1

三阶实矩阵 R 的特征多项式是关于 \lambda 的实系数三次多项式,由代数基本定理可知它至少存在一个实特征值 \lambda,不妨取其对应的非零实特征向量 \boldsymbol n\ne\boldsymbol 0。由于旋转矩阵保持向量长度不变,有:

R\boldsymbol n=\lambda\boldsymbol n,\qquad \|R\boldsymbol n\|=\|\boldsymbol n\|=|\lambda|\|\boldsymbol n\|.

因此实特征值 \lambda 只能取 1 或 -1。接下来分两种情形讨论矩阵的三个特征值:若另外两个特征值为一对共轭复数,它们的乘积等于模的平方(恒为正数),而三个特征值的乘积等于 \det R=1,故实特征值必为 \lambda=1;若三个特征值全为实数,则每个特征值只能取 1 或 -1,要使三者乘积为 1,其中至少有一个特征值等于 1(三个 1,或一个 1 配两个 -1)。将 \lambda=1 对应的实特征向量归一化为单位向量,即得到满足 R\boldsymbol n=\boldsymbol n 的旋转轴。

进一步考察与旋转轴 \boldsymbol n 正交的平面。任取满足 \boldsymbol n^{\mathsf T}\boldsymbol x=0 的向量 \boldsymbol x,利用 R^{\mathsf T}\boldsymbol n=R^{-1}\boldsymbol n=\boldsymbol n,计算旋转后向量 R\boldsymbol x 与 \boldsymbol n 的内积:

\boldsymbol n^{\mathsf T}R\boldsymbol x=(R^{\mathsf T}\boldsymbol n)^{\mathsf T}\boldsymbol x=\boldsymbol n^{\mathsf T}\boldsymbol x=0.

这说明垂直于 \boldsymbol n 的平面在旋转下保持不变。在该垂直平面内任取一组与 \boldsymbol n 共同构成右手系的单位正交基,旋转变换限制在该平面上就是一个二阶正交矩阵,且行列式为 1。将第一列记为 (\cos\theta,\sin\theta)^{\mathsf T},由列向量正交归一及行列式为 1 即可唯一确定第二列,得到平面旋转矩阵:

\begin{bmatrix}\cos\theta&-\sin\theta\\\sin\theta&\cos\theta\end{bmatrix}.

综上,平行于 \boldsymbol n 的方向保持不动,垂直于 \boldsymbol n 的平面绕轴转过角度 \theta,合起来便构成了三维旋转的轴角表示。当 R=I(零转角)时,任意单位向量都可作为旋转轴;当转角非零时,旋转轴 \boldsymbol n 的方向与转角 \theta 的正负号按右手定则共同确定同一个转动。

有了旋转轴和转角的概念,我们再来推导:当空间向量 \boldsymbol x 绕单位轴 \boldsymbol n 转过角度 \theta 后,旋转所得的新向量 \boldsymbol x' 应当如何用 \boldsymbol n、\theta 和 \boldsymbol x 表示?(这里旋转前后的向量均在同一个固定坐标系下表示。)既然旋转轴方向上的分量不受转动影响,自然的思路是先将原向量 \boldsymbol x 正交分解为平行于转轴的轴向分量 \boldsymbol x_\parallel 与垂直于转轴的平面分量 \boldsymbol x_\perp:

\boldsymbol x_\parallel=(\boldsymbol n^{\mathsf T}\boldsymbol x)\boldsymbol n,\qquad \boldsymbol x_\perp=\boldsymbol x-\boldsymbol x_\parallel.
(2.5)

在旋转过程中,轴向分量 \boldsymbol x_\parallel 始终保持不变,只有垂直分量 \boldsymbol x_\perp 在正交于 \boldsymbol n 的平面内绕轴画圆。为了写出圆周上的旋转结果,需要在该垂直平面内构造一对相互垂直且等长的基准向量:其中一个现成的方向就是 \boldsymbol x_\perp 本身,而将单位转轴 \boldsymbol n 与原向量 \boldsymbol x 作叉积所得的 \boldsymbol n\times\boldsymbol x,恰好给出了平面内与之正交且等长的第二个方向。

实验 03轴向分解与平面旋转

切换图例,分别显示轴向分量、圆形轨迹与旋转后的向量。改变转角,观察端点轨迹;改变转轴方向,比较向量分解。

当 \boldsymbol x_\perp 在垂直平面内转过角度 \theta 时,它在原方向 \boldsymbol x_\perp 与正交方向 \boldsymbol n\times\boldsymbol x 上的投影系数分别为 \cos\theta 和 \sin\theta。将旋转后的垂直分量与保持不变的轴向分量相加,便得到了著名的 Rodrigues 旋转公式:

\boldsymbol x'=\boldsymbol x_\parallel+\cos\theta\,\boldsymbol x_\perp+\sin\theta\,(\boldsymbol n\times\boldsymbol x).
(2.6)

式(2.6)中,第一项是沿旋转轴保持不动的轴向分量;后两项的线性组合则描述了垂直分量在正交平面内的圆周运动。

结合实验 03 中的几个特殊角度,可以直观地检验式(2.6)中各项的作用:当 \theta=0 时,\cos 0=1、\sin 0=0,后两项还原为 \boldsymbol x_\perp,与 \boldsymbol x_\parallel 相加正好恢复原向量 \boldsymbol x;当转角达到四分之一周(\theta=\pi/2)时,余弦项归零,垂直分量完全转到 \boldsymbol n\times\boldsymbol x 方向;当转角达到半周(\theta=\pi)时,正弦项归零而余弦项取 -1,垂直分量反向为 -\boldsymbol x_\perp,轴向分量依然不变。对于一般转角 \theta,余弦和正弦系数则在这两个正交方向之间平滑地分配权重,使向量端点沿空间圆周连续转动。

推导垂直分量的正交性与等长性\|\boldsymbol n\times\boldsymbol x\|=\|\boldsymbol x_\perp\|

首先验证由式(2.5)定义的 \boldsymbol x_\perp 确实与单位转轴 \boldsymbol n 垂直。利用 \boldsymbol n^{\mathsf T}\boldsymbol n=1 计算内积:

\boldsymbol n^{\mathsf T}\boldsymbol x_\perp=\boldsymbol n^{\mathsf T}\boldsymbol x-(\boldsymbol n^{\mathsf T}\boldsymbol x)(\boldsymbol n^{\mathsf T}\boldsymbol n)=0.

其次,根据向量叉积的定义,\boldsymbol n\times\boldsymbol x 同时垂直于 \boldsymbol n 和 \boldsymbol x,因而也垂直于两者的线性组合 \boldsymbol x_\perp=\boldsymbol x-(\boldsymbol n^{\mathsf T}\boldsymbol x)\boldsymbol n。接下来验证 \boldsymbol n\times\boldsymbol x 与 \boldsymbol x_\perp 具有相同的长度。设 \boldsymbol n 与 \boldsymbol x 的夹角为 \gamma,则叉积模长为 \|\boldsymbol n\|\|\boldsymbol x\|\sin\gamma,内积为 \|\boldsymbol n\|\|\boldsymbol x\|\cos\gamma。利用恒等式 \sin^2\gamma=1-\cos^2\gamma 以及 \|\boldsymbol n\|=1,可得:

\begin{aligned}\|\boldsymbol n\times\boldsymbol x\|^2&=\|\boldsymbol n\|^2\|\boldsymbol x\|^2-(\boldsymbol n^{\mathsf T}\boldsymbol x)^2\\&=\|\boldsymbol x\|^2-\|\boldsymbol x_\parallel\|^2\\&=\|\boldsymbol x_\perp\|^2.\end{aligned}

最后一步用到了正交分解 \boldsymbol x=\boldsymbol x_\parallel+\boldsymbol x_\perp 的勾股定理。这表明只要 \|\boldsymbol x_\perp\|>0,向量 \boldsymbol x_\perp 与 \boldsymbol n\times\boldsymbol x 就在垂直平面内构成一对等长正交基;而当原向量 \boldsymbol x 恰好与转轴共线时,\boldsymbol x_\perp 与 \boldsymbol n\times\boldsymbol x 同时为零向量,式(2.6)自然退化为 \boldsymbol x'=\boldsymbol x_\parallel=\boldsymbol x。

叉乘矩阵

式(2.6)以向量运算的形式给出了单个向量的旋转结果。如果能将它改写为旋转矩阵左乘 \boldsymbol x 的形式,就可以直接得到轴角 (\boldsymbol n,\theta) 所对应的旋转矩阵 R(\boldsymbol n,\theta)。观察式(2.6)可以发现,当单位轴 \boldsymbol n=(n_1,n_2,n_3)^{\mathsf T} 固定时,叉积运算 \boldsymbol n\times\boldsymbol x 对输入向量 \boldsymbol x 是线性的,因而可以用一个三阶矩阵左乘 \boldsymbol x 来表示。这个矩阵称为 \boldsymbol n 的叉乘矩阵(或反对称矩阵):

N=[\boldsymbol n]_\times=\begin{bmatrix}0&-n_3&n_2\\n_3&0&-n_1\\-n_2&n_1&0\end{bmatrix},\qquad N\boldsymbol x=\boldsymbol n\times\boldsymbol x.
(2.7)

由式(2.7)的元素排布一眼可以看出,它的主对角线全为零,上下三角关于主对角线互为相反数,满足 N^{\mathsf T}=-N。借助叉乘矩阵 N,不仅叉积项可写为 N\boldsymbol x,垂直分量 \boldsymbol x_\perp 也可表示为 -N^2\boldsymbol x。将其代回式(2.6)并把右端的公因式 \boldsymbol x 提取出来,便得到 Rodrigues 公式的矩阵形式:

R(\boldsymbol n,\theta)=I+\sin\theta\,N+(1-\cos\theta)N^2.
(2.8)
推导Rodrigues 公式的矩阵形式R=I+\sin\theta\,N+(1-\cos\theta)N^2

1. 计算叉乘矩阵的平方 N^2。将式(2.7)中的矩阵 N 与自身相乘,并利用单位向量条件 n_1^2+n_2^2+n_3^2=1 化简对角线元素:

N^2=\begin{bmatrix}-n_2^2-n_3^2&n_1n_2&n_1n_3\\n_1n_2&-n_1^2-n_3^2&n_2n_3\\n_1n_3&n_2n_3&-n_1^2-n_2^2\end{bmatrix}=\boldsymbol n\boldsymbol n^{\mathsf T}-I.

将其作用于向量 \boldsymbol x,注意外积项 (\boldsymbol n\boldsymbol n^{\mathsf T})\boldsymbol x=\boldsymbol n(\boldsymbol n^{\mathsf T}\boldsymbol x)=\boldsymbol x_\parallel,故有 N^2\boldsymbol x=\boldsymbol x_\parallel-\boldsymbol x=-\boldsymbol x_\perp。

2. 代入向量形式的 Rodrigues 公式并提取 \boldsymbol x。将 \boldsymbol x_\parallel=\boldsymbol n\boldsymbol n^{\mathsf T}\boldsymbol x=(I+N^2)\boldsymbol x 以及 \boldsymbol n\times\boldsymbol x=N\boldsymbol x 代入式(2.6),逐行整理可得:

\begin{aligned}\boldsymbol x'&=\boldsymbol x_\parallel+\cos\theta(\boldsymbol x-\boldsymbol x_\parallel)+\sin\theta\,N\boldsymbol x\\&=\cos\theta\,\boldsymbol x+(1-\cos\theta)\boldsymbol n\boldsymbol n^{\mathsf T}\boldsymbol x+\sin\theta\,N\boldsymbol x\\&=[\cos\theta\,I+(1-\cos\theta)(I+N^2)+\sin\theta\,N]\boldsymbol x\\&=[I+\sin\theta\,N+(1-\cos\theta)N^2]\boldsymbol x.\end{aligned}

由于该等式对任意输入向量 \boldsymbol x\in\mathbb R^3 恒成立,方括号内的三阶矩阵就是旋转矩阵 R(\boldsymbol n,\theta)。此外,注意到向量与自身的叉积为零(N\boldsymbol n=\boldsymbol 0),在 N^2=\boldsymbol n\boldsymbol n^{\mathsf T}-I 两边左乘 N 立得高次幂递推关系 N^3=N(\boldsymbol n\boldsymbol n^{\mathsf T}-I)=-N。这一性质稍后将在矩阵指数级数的求和推导中发挥关键作用。

为了检验式(2.8)的计算过程,我们可以考察一个三根坐标轴同时发生变化的具体例子:将刚体绕第一卦限的立方体主对角线方向 (1,1,1)^{\mathsf T} 逆时针旋转三分之一周(即 \theta=2\pi/3)。从空间对称性不难看出,这次旋转应当使 x,y,z 三根坐标轴发生循环轮换(x\to y\to z\to x),因此最终算出的旋转矩阵应该是一个每行每列只有一个 1 的置换矩阵。下面展开式(2.8)的各项予以验证,计算结果也可直接与实验 01 中的斜轴旋转对照。

计算绕立方体对角线的旋转R\boldsymbol e_x=\boldsymbol e_y,\quad R\boldsymbol e_y=\boldsymbol e_z

将转轴方向归一化为单位向量 \boldsymbol n=(1,1,1)^{\mathsf T}/\sqrt3,转角取 \theta=2\pi/3。先写出对应的叉乘矩阵 N 及其平方 N^2=\boldsymbol n\boldsymbol n^{\mathsf T}-I:

N=\frac1{\sqrt3}\begin{bmatrix}0&-1&1\\1&0&-1\\-1&1&0\end{bmatrix},\quad N^2=\frac13\begin{bmatrix}-2&1&1\\1&-2&1\\1&1&-2\end{bmatrix}.

将三角函数值 \sin(2\pi/3)=\sqrt3/2 与 1-\cos(2\pi/3)=3/2 代入式(2.8),矩阵中的根号因子恰好约去:

R=I+\frac12\begin{bmatrix}0&-1&1\\1&0&-1\\-1&1&0\end{bmatrix}+\frac12\begin{bmatrix}-2&1&1\\1&-2&1\\1&1&-2\end{bmatrix}=\begin{bmatrix}0&0&1\\1&0&0\\0&1&0\end{bmatrix}.

依次读出所得矩阵的三列,可以看到 \boldsymbol e_x\mapsto\boldsymbol e_y、\boldsymbol e_y\mapsto\boldsymbol e_z、\boldsymbol e_z\mapsto\boldsymbol e_x,与几何预期完全吻合。在实验 01 中将转轴切换为斜轴并将转角设为 120^\circ,即可观察到这三根物体轴的循环换位。

04

角速度与姿态微分方程

前几节讨论的旋转矩阵和轴角公式,描述的都是两个离散姿态之间的有限转动。而在动力学仿真中,刚体的姿态随时间连续演化,我们需要进一步刻画姿态在每一瞬间的变化率。想象刚体正在绕过原点的某一瞬时转轴转动,固连在刚体上的任意一点都会沿着垂直于转轴的圆弧切线方向运动:该点离转轴越远,线速度越大;速度的切向方向则由右手定则确定。

为此,我们引入角速度向量:它的方向沿着瞬时旋转轴的正方向,它的模长表示单位时间内转过的弧度数(单位为 \mathrm{rad/s})。先在世界坐标系下表示这一角速度向量,记作 \boldsymbol\omega。在极小的时间步长 h 内,刚体绕单位轴 \boldsymbol n=\boldsymbol\omega/\|\boldsymbol\omega\| 转过的微元角度约为 \theta=h\|\boldsymbol\omega\|。将 Rodrigues 公式(2.6)按时间步长 h 展开并保留到一阶项(此时 \cos\theta\approx 1、\sin\theta\approx h\|\boldsymbol\omega\|),可得刚体上固定向量 \boldsymbol x(t) 在 t+h 时刻的位置:

\boldsymbol x(t+h)=\boldsymbol x(t)+h\,\boldsymbol\omega\times\boldsymbol x(t)+O(h^2).

将等式两边减去 \boldsymbol x(t) 后同除以时间间隔 h,再令 h\to 0 取极限,便得到随刚体一同转动的向量对时间的导数公式:

\dot{\boldsymbol x}=\boldsymbol\omega\times\boldsymbol x.
(2.9)

式(2.9)中的叉积 \boldsymbol\omega\times\boldsymbol x 既垂直于转轴 \boldsymbol\omega,又垂直于位置向量 \boldsymbol x,因而严格指向端点圆周轨迹的切线方向;其模长 \|\boldsymbol\omega\|\|\boldsymbol x_\perp\| 则等于角速度大小与点到转轴距离(圆周半径)的乘积。在前面的轴向分解与平面旋转实验中勾选“切向方向”,即可直观地观察这一瞬时速度方向如何始终与圆轨迹相切。

推导刚体转动速度公式\dot{\boldsymbol x}=\boldsymbol\omega\times\boldsymbol x

我们先回顾正弦和余弦函数在 \theta=0 附近的泰勒展开。光滑函数 f(\theta) 在零点附近的泰勒多项式为 f(\theta)=f(0)+f'(0)\theta+f''(0)\theta^2/2!+\cdots。由于 \sin\theta 在零点处的各阶导数循环取 0,1,0,-1,\ldots,而 \cos\theta 的各阶导数循环取 1,0,-1,0,\ldots,代入可得:

\sin\theta=\theta-\frac{\theta^3}{3!}+O(\theta^5),\qquad 1-\cos\theta=\frac{\theta^2}{2!}-\frac{\theta^4}{4!}+O(\theta^6).

其中记号 O(\theta^k) 表示当 \theta\to 0 时,余项的绝对值不大于某个正常数乘以 |\theta|^k。

现在设刚体以非零瞬时角速度 \boldsymbol\omega 转动,对应的单位转轴为 \boldsymbol n=\boldsymbol\omega/\|\boldsymbol\omega\|,在极短时间 h 内转过的角度为 \theta=h\|\boldsymbol\omega\|。将 \theta=h\|\boldsymbol\omega\| 代入上述三角函数展开式,可得:

\begin{aligned}\sin\theta&=h\|\boldsymbol\omega\|+O(h^3),\\1-\cos\theta&=\frac{h^2\|\boldsymbol\omega\|^2}{2}+O(h^4).\end{aligned}

将其代回矩阵形式的 Rodrigues 公式(2.8),并利用叉乘矩阵的线性性质 \|\boldsymbol\omega\|[\boldsymbol n]_\times=[\boldsymbol\omega]_\times 合并标量因子,可得:

\begin{aligned}\boldsymbol x(t+h)&=\left[I+h[\boldsymbol\omega]_\times+\frac{h^2}{2}[\boldsymbol\omega]_\times^2+O(h^3)\right]\boldsymbol x(t),\\\frac{\boldsymbol x(t+h)-\boldsymbol x(t)}h&=[\boldsymbol\omega]_\times\boldsymbol x(t)+O(h).\end{aligned}

令 h\to 0,高阶项 O(h) 趋于零,即得 \dot{\boldsymbol x}=[\boldsymbol\omega]_\times\boldsymbol x=\boldsymbol\omega\times\boldsymbol x。当 \boldsymbol\omega=\boldsymbol 0 时,向量静止不动,式(2.9)两端同为零向量,依然成立。对于随时间平滑变化的角速度 \boldsymbol\omega(t),在時刻 t 的一阶无穷小邻域内同样由瞬时角速度 \boldsymbol\omega(t) 决定一阶变化率,导数公式保持不变。

既然固连在刚体上的任意向量都满足式(2.9),构成旋转矩阵 R=[\boldsymbol b_1\ \boldsymbol b_2\ \boldsymbol b_3] 的三根随体坐标轴自然也分别满足 \dot{\boldsymbol b}_i=\boldsymbol\omega\times\boldsymbol b_i=[\boldsymbol\omega]_\times\boldsymbol b_i。将这三列的变化率重新并排拼成一个 3\times 3 矩阵,便得到了旋转矩阵对时间的微分方程。此外,在动力学计算和传感器测量(如陀螺仪)中,角速度常常是在随刚体运动的物体坐标系下给出的,记作体坐标角速度 \boldsymbol\omega_b。这两种角速度表示下的姿态微分方程分别为:

\dot R=[\boldsymbol\omega]_\times R=R[\boldsymbol\omega_b]_\times.
(2.10)

这里 \boldsymbol\omega 与 \boldsymbol\omega_b 描述的是同一个物理角速度向量在不同坐标系下的分量,满足坐标变换关系 \boldsymbol\omega=R\boldsymbol\omega_b。值得特别留意的是式(2.10)中叉乘矩阵的位置规律:使用世界系角速度 \boldsymbol\omega 时,叉乘矩阵 [\boldsymbol\omega]_\times 左乘在 R 的左侧;使用物体坐标系角速度 \boldsymbol\omega_b 时,叉乘矩阵 [\boldsymbol\omega_b]_\times 右乘在 R 的右侧。

推导姿态微分方程的两种形式\dot R=[\boldsymbol\omega]_\times R=R[\boldsymbol\omega_b]_\times

1. 导出世界系角速度下的左乘形式。对旋转矩阵的三列 \boldsymbol b_1,\boldsymbol b_2,\boldsymbol b_3 分别应用式(2.9):

\dot{\boldsymbol b}_i=\boldsymbol\omega\times\boldsymbol b_i=[\boldsymbol\omega]_\times\boldsymbol b_i,\quad i=1,2,3.

按列合并为一个矩阵方程,即得:

\dot R=[\dot{\boldsymbol b}_1\ \dot{\boldsymbol b}_2\ \dot{\boldsymbol b}_3]=[\boldsymbol\omega]_\times[\boldsymbol b_1\ \boldsymbol b_2\ \boldsymbol b_3]=[\boldsymbol\omega]_\times R.

2. 导出叉乘矩阵的旋转相似变换恒等式。由于三维旋转 R\in\mathrm{SO}(3) 保持向量长度、夹角以及右手系方向不变,先将两个向量 \boldsymbol a,\boldsymbol b 旋转后再作叉积,等价于先作叉积再将结果整体旋转:

(R\boldsymbol a)\times(R\boldsymbol b)=R(\boldsymbol a\times\boldsymbol b).

在等式两边令 \boldsymbol b=R^{\mathsf T}\boldsymbol x,注意 R\boldsymbol b=RR^{\mathsf T}\boldsymbol x=\boldsymbol x,上式即写为 [R\boldsymbol a]_\times\boldsymbol x=R[\boldsymbol a]_\times R^{\mathsf T}\boldsymbol x。由于 \boldsymbol x 是任意向量,两边消去 \boldsymbol x 即得叉乘矩阵的坐标变换恒等式:

[R\boldsymbol a]_\times=R[\boldsymbol a]_\times R^{\mathsf T}.

3. 导出物体坐标系角速度下的右乘形式。将 \boldsymbol\omega=R\boldsymbol\omega_b 代入左乘形式,并应用上述恒等式与正交性条件 R^{\mathsf T}R=I:

\begin{aligned}\dot R&=[R\boldsymbol\omega_b]_\times R\\&=R[\boldsymbol\omega_b]_\times R^{\mathsf T}R\\&=R[\boldsymbol\omega_b]_\times.\end{aligned}

由姿态变化恢复角速度

反过来,如果已知刚体在某时刻的姿态矩阵 R 及其时间导数 \dot R,我们也可以在式(2.10)两边右乘 R^{\mathsf T},直接反解出世界系角速度的叉乘矩阵 \Omega=[\boldsymbol\omega]_\times。这一逆向关系同时揭示了一个重要事实:尽管 \dot R 含有九个导数元素,但由于正交性约束,\dot R R^{\mathsf T} 必然是一个只有三个独立分量的反对称矩阵:

\Omega=\dot R R^{\mathsf T},\qquad \boldsymbol\omega=(\Omega_{32},\Omega_{13},\Omega_{21})^{\mathsf T}.
推导姿态导数的反对称结构\Omega^{\mathsf T}=-\Omega

对恒等式 RR^{\mathsf T}=I 两边关于时间 t 求导,由乘积求导法则可得:

\dot R R^{\mathsf T}+R\dot R^{\mathsf T}=0.

记第一项为 \Omega=\dot R R^{\mathsf T},注意到第二项 R\dot R^{\mathsf T}=(\dot R R^{\mathsf T})^{\mathsf T}=\Omega^{\mathsf T},上式即写作 \Omega+\Omega^{\mathsf T}=0,证明了 \Omega 必为三阶反对称矩阵。任意三阶反对称矩阵的主对角元必为零,非对角元成对互为相反数,因此总可以唯一地对应到一个三维向量 \boldsymbol\omega=(\omega_1,\omega_2,\omega_3)^{\mathsf T} 的叉乘矩阵:

\Omega=\begin{bmatrix}0&-\omega_3&\omega_2\\\omega_3&0&-\omega_1\\-\omega_2&\omega_1&0\end{bmatrix}=[\boldsymbol\omega]_\times.

对照矩阵下标可知,依次取出 \Omega_{32},\Omega_{13},\Omega_{21} 三个元素,便恢复出角速度向量 \boldsymbol\omega;而在 \Omega=\dot R R^{\mathsf T} 两边右乘 R,又立即回到 \dot R=\Omega R=[\boldsymbol\omega]_\times R。这从纯矩阵代数的角度再次印证了瞬时姿态变化只有三个独立自由度。

例题:角速度的坐标变换

设书本已从初始重合姿态绕世界系正 z 轴转过了 \pi/2,此时书本的第一根随体轴指向世界系的正 y 方向。若此刻让书本绕其自身的第一根随体轴以 1\,\mathrm{rad/s} 的角速率转动,则它在物体坐标系和世界坐标系下的角速度向量分别为:

R=R_z(\pi/2),\qquad\boldsymbol\omega_b=\begin{bmatrix}1\\0\\0\end{bmatrix},\qquad\boldsymbol\omega=R\boldsymbol\omega_b=\begin{bmatrix}0\\1\\0\end{bmatrix}\ \mathrm{rad/s}.

可以看到,同一根旋转轴在物体坐标系下是第一根坐标轴 (1,0,0)^{\mathsf T},而在世界坐标系下则是正 y 轴 (0,1,0)^{\mathsf T}。将 \boldsymbol\omega 与 \boldsymbol\omega_b 分别代入式(2.10)的左乘与右乘形式,算出的姿态变化率 \dot R 完全一致。

最后,我们将刚体参考点的平移运动也纳入进来。设刚体参考点在世界系中的位置为 \boldsymbol c(t),线速度为 \boldsymbol v=\dot{\boldsymbol c}。对于固连在刚体上的任意材料点,其局部坐标 \boldsymbol p 不随时间改变,对世界位置关系式 \boldsymbol x(t)=\boldsymbol c(t)+R(t)\boldsymbol p 两边关于时间求导,并代入 \dot R=[\boldsymbol\omega]_\times R,即得刚体上任意一点的世界速度公式:

\dot{\boldsymbol x}=\boldsymbol v+\boldsymbol\omega\times(R\boldsymbol p).

该式表明,刚体上任一点的绝对速度等于参考点的平移速度 \boldsymbol v 与绕参考点转动所产生的切向速度 \boldsymbol\omega\times(R\boldsymbol p) 的矢量和。后续章节推导关节空间雅可比矩阵和接触点速度约束时,都将以这一公式作为起点。

下面的交互实验将参考点平移速度 \boldsymbol v、转动切向速度 \boldsymbol\omega\times(R\boldsymbol p) 以及两者的合速度 \dot{\boldsymbol x} 放在同一三维场景中,便于直观比较材料点的到轴距离与沿轴高度对速度的影响。

实验 04材料点速度的平移与转动分解

改变角速度、到轴距离和沿轴高度,比较平移贡献、转动贡献与合速度。

在实验 04 中调节滑块可以看到:当材料点仅沿着平行于旋转轴的方向上下移动时,相对位置向量 R\boldsymbol p 的轴向分量与 \boldsymbol\omega 平行,在叉积 \boldsymbol\omega\times(R\boldsymbol p) 中恰好消去,因此转动速度的大小和方向都保持不变;而当增大材料点到转轴的垂直距离时,转动速度的大小随之成正比增大。第 4 章将进一步从圆弧弧长与转角的关系出发,利用这一速度分布计算整个刚体的转动动能。

05

指数映射与姿态积分

姿态微分方程(2.10)刻画了旋转矩阵在某一时刻的瞬时变化率。要在物理引擎中将刚体姿态从当前时刻 t 推进到下一时刻 t+h,就需要对这一微分方程在时间步长 h 上积分。我们先从角速度在一个时间步内保持恒定的情形入手。

在微积分中,一阶常系数线性标量微分方程 \dot y=ay 的解析解可以写成指数函数 y(t+h)=e^{ha}y(t)。与之完全类似,当世界系角速度 \boldsymbol\omega 为常向量时,线性矩阵微分方程 \dot R=[\boldsymbol\omega]_\times R 的解析解也可以用矩阵指数(Matrix Exponential)写出,其中三阶矩阵的指数函数由收敛的无穷幂级数定义:

\exp(h[\boldsymbol\omega]_\times)=I+h[\boldsymbol\omega]_\times+\frac{h^2}{2!}[\boldsymbol\omega]_\times^2+\cdots.
(2.11)

将式(2.11)给出的旋转增量左乘在当前姿态 R(t) 的左侧,就把恒定世界角速度在时间步 h 内产生的有限转动累积到了姿态上;反之,如果给定的是在一个时间步内保持恒定的体坐标角速度 \boldsymbol\omega_b,则对应于右乘微分方程 \dot R=R[\boldsymbol\omega_b]_\times,旋转增量应当右乘在当前姿态的右侧:

\begin{aligned}R(t+h)&=\exp\!\left(h[\boldsymbol\omega]_\times\right)R(t),\\R(t+h)&=R(t)\exp\!\left(h[\boldsymbol\omega_b]_\times\right).\end{aligned}
(2.12)

在真实的多体动力学仿真中,刚体的角速度通常会随时间连续变化。此时我们在每个离散时间步 h 内取该步的角速度代表值(如步末或步初的角速度),将这一小段时间近似视为恒定角速度运动,再调用式(2.12)更新姿态。虽然步内角速度取常值是一种时间离散近似,会影响旋转轨迹的时间精度,但由矩阵指数构造出的增量本身始终是一个严格的正交旋转矩阵。

这里需要注意,式(2.12)的左乘与右乘两种更新方式,分别要求角速度在世界坐标系下恒定或在物体坐标系下恒定:当转轴固定在世界空间中时使用左乘,当转轴固连在刚体上随体转动时使用右乘。在一般的动力学步进循环中,求解器先根据当前步的受力算出新的角速度,随后通过式(2.12)生成当前步的有限旋转增量并完成姿态更新,从而把动力学速度求解与几何姿态推进衔接起来。

为什么矩阵指数生成的增量一定能严格保持正交性?我们可以从导数的角度给出一个简洁的证明。记反对称矩阵 \Omega=[\boldsymbol\omega]_\times,并设 E(h)=\exp(h\Omega)。由于 E(h) 对步长 h 的导数满足 E'=\Omega E,结合反对称性质 \Omega^{\mathsf T}+\Omega=0,对乘积 E^{\mathsf T}E 求导可得:

\frac{\mathrm d}{\mathrm dh}(E^{\mathsf T}E)=(E')^{\mathsf T}E+E^{\mathsf T}E'=E^{\mathsf T}(\Omega^{\mathsf T}+\Omega)E=0.

这说明 E(h)^{\mathsf T}E(h) 不随时间步长 h 变化。又因为初始时刻 E(0)=I 满足 E(0)^{\mathsf T}E(0)=I,故对任意步长 h 恒有 E(h)^{\mathsf T}E(h)=I;再由行列式随 h 的连续性以及 \det E(0)=1,可知 \det E(h)=1 始终成立。下面的折叠推导从幂级数逐项求导出发,严格验证上面用到的求导性质 E'=\Omega E。

推导恒定角速度下的姿态积分R(t+h)=\exp(h\Omega)R(t)

在本推导中,将常值反对称矩阵 [\boldsymbol\omega]_\times 简记为 \Omega,并令 E(h)=\exp(h\Omega)。将式(2.11)的矩阵幂级数对时间步长 h 逐项求导,并提取左公因式 \Omega:

\begin{aligned}\frac{\mathrm dE}{\mathrm dh}&=\Omega+h\Omega^2+\frac{h^2\Omega^3}{2!}+\cdots\\&=\Omega\left(I+h\Omega+\frac{h^2\Omega^2}{2!}+\cdots\right)=\Omega E(h).\end{aligned}

由此可知,R(t+h)=E(h)R(t) 对 h 的导数满足 \frac{\mathrm d}{\mathrm dh}R(t+h)=\Omega E(h)R(t)=\Omega R(t+h),且在 h=0 时还原为初值 R(t),因而确实是恒定世界角速度下姿态微分方程的唯一解析解。同理,将 R(t)\exp(h[\boldsymbol\omega_b]_\times) 逐项求导并把公因式 [\boldsymbol\omega_b]_\times 提取到右侧,即可验证体坐标下的右乘积分形式。

此外,我们也可以把有限时间步 h 等分为 m 个极小的时间步 h/m 来理解矩阵指数:

\exp(h\Omega)=\lim_{m\to\infty}\left(I+\frac{h}{m}\Omega\right)^m.

在每个微元步 h/m 内作一阶线性近似 I+(h/m)\Omega,再将这 m 次无穷小转动连乘起来;当分割步数 m\to\infty 时,无穷小转动的累积极限就收敛为精确的有限旋转 \exp(h\Omega)。

指数映射与 Rodrigues 公式的关系

式(2.11)是用无穷级数定义的,在实际编写程序时显然不能直接累加无穷多项。为了得到有限项的闭合计算式,我们将单位旋转轴 \boldsymbol n 与转角 \theta 合并记为一个三维旋转向量 \boldsymbol\phi=\theta\boldsymbol n(在一步姿态积分中即取 \boldsymbol\phi=h\boldsymbol\omega 或 h\boldsymbol\omega_b),它的方向代表转轴,模长 \|\boldsymbol\phi\|=\theta 代表转角。利用第 3 节导出过的叉乘矩阵递推性质 N^3=-N(其中 N=[\boldsymbol n]_\times),矩阵指数级数中所有三次及以上的高次幂都可以归并到 N 和 N^2 两项上,合并同类项后恰好还原为 Rodrigues 公式:

\exp([\boldsymbol\phi]_\times)=I+\sin\theta\,N+(1-\cos\theta)N^2.
(2.13)

这一结果说明,计算矩阵指数 \exp([\boldsymbol\phi]_\times) 只需做右侧的三项矩阵加法。至此,第 3 节基于空间向量正交分解的几何推导,与本节基于姿态微分方程积分的分析推导殊途同归:从反对称矩阵 [\boldsymbol\phi]_\times 到旋转矩阵 R\in\mathrm{SO}(3) 的映射 \exp([\boldsymbol\phi]_\times) 称为三维旋转群的指数映射(Exponential Map)。

推导矩阵指数的级数化简\exp(\theta N)=I+\sin\theta\,N+(1-\cos\theta)N^2

在关系式 N^3=-N 两边连续乘以 N,依次可得 N^4=-N^2、N^5=N、N^6=N^2,奇次幂在 \pm N 之间交替,偶次幂在 \pm N^2 之间交替。将 [\boldsymbol\phi]_\times=\theta N 代入幂级数(2.11)并按 N 与 N^2 分组整理:

\begin{aligned}\exp(\theta N)&=I+\theta N+\frac{\theta^2}{2!}N^2-\frac{\theta^3}{3!}N-\frac{\theta^4}{4!}N^2+\cdots\\&=I+\left(\theta-\frac{\theta^3}{3!}+\frac{\theta^5}{5!}-\cdots\right)N\\&\quad+\left(\frac{\theta^2}{2!}-\frac{\theta^4}{4!}+\frac{\theta^6}{6!}-\cdots\right)N^2\\&=I+\sin\theta\,N+(1-\cos\theta)N^2.\end{aligned}

圆括号内的两个标量幂级数正是 \sin\theta 与 1-\cos\theta 的泰勒级数。这就证明了指数映射 \exp([\boldsymbol\phi]_\times) 与矩阵形式的 Rodrigues 公式(2.8)恒等。

小角度下的数值计算

在仿真器的单步更新中,时间步长 h 往往只有毫秒量级,因此单步转角 \theta=\|\boldsymbol\phi\| 通常非常接近于零(甚至在刚体静止时严格等于零)。如果直接先用 \boldsymbol n=\boldsymbol\phi/\theta 归一化求单位转轴,当 \theta\to 0 时就会遇到除以零或浮点下溢的问题。为了直接以未归一化的旋转向量 \boldsymbol\phi(及其叉乘矩阵 A=[\boldsymbol\phi]_\times=\theta N)作为输入,我们可以将 N=A/\theta 代入式(2.13),把指数映射改写为:

\begin{gathered}A=[\boldsymbol\phi]_\times,\qquad\theta=\|\boldsymbol\phi\|,\\R=\exp(A)=I+\frac{\sin\theta}{\theta}A+\frac{1-\cos\theta}{\theta^2}A^2.\end{gathered}
(2.14)

观察式(2.14)中的两个标量系数 a(\theta)=\frac{\sin\theta}{\theta} 和 b(\theta)=\frac{1-\cos\theta}{\theta^2}:当 \theta\to 0 时,两者的分子与分母同时趋于零,但在数学上各自存在光滑的有限极限 a(0)=1 和 b(0)=1/2。因此,在 \theta 很小时改用这两个系数的泰勒级数求值,就能彻底避开 0/0 型浮点除法,保证零角附近的数值稳定性。

在实际代码实现中,我们先根据 \theta=\|\boldsymbol\phi\| 的大小独立算出标量系数 a(\theta) 和 b(\theta),再组合出 R=I+a(\theta)A+b(\theta)A^2。尤其方便的是,即便输入严格为零向量 \boldsymbol\phi=\boldsymbol 0,此时虽然 a(0)=1、b(0)=1/2,但由于 A=0,式(2.14)依然能平滑地给出单位矩阵 R=I,无需为静止刚体单独编写跳过归一化的特判逻辑。

实验 05小角系数与级数近似

在零点附近,原函数与二阶近似逐渐重合。沿曲线观察系数的极限,再与下方展开式逐项对照。

从实验 05 的曲线可以看到,a(\theta) 与 b(\theta) 在 \theta=0 附近都是关于 \theta 的偶函数,图像在零点处十分平缓,偏离极限值的主导项均为二次项 \theta^2。以 \theta=0.1\,\mathrm{rad} 为例,两个系数的二阶泰勒近似分别为 1-0.01/6 和 1/2-0.01/24,而被截断的下一个四次项分别为 10^{-4}/120\approx 8.3\times 10^{-7} 和 10^{-4}/720\approx 1.4\times 10^{-7}。将这一截断余项的数量级与双精度浮点数的机器精度对比,便能清楚地确定切换泰勒展开的角度阈值与所需的展开阶数。

推导小角系数的级数展开\frac{\sin\theta}{\theta}=1-\frac{\theta^2}{6}+O(\theta^4)

沿用第 4 节中的零点泰勒展开,将 \sin\theta 保留至五次项、将 \cos\theta 保留至六次项:

\sin\theta=\theta-\frac{\theta^3}{6}+\frac{\theta^5}{120}+O(\theta^7),\qquad \cos\theta=1-\frac{\theta^2}{2}+\frac{\theta^4}{24}-\frac{\theta^6}{720}+O(\theta^8).

将两式分别配成式(2.14)所需的分式并除以 \theta 和 \theta^2,即得两个小角系数的偶次幂展开:

\frac{\sin\theta}{\theta}=1-\frac{\theta^2}{6}+\frac{\theta^4}{120}+O(\theta^6),\qquad \frac{1-\cos\theta}{\theta^2}=\frac12-\frac{\theta^2}{24}+\frac{\theta^4}{720}+O(\theta^6).

此外,当 \theta 处于阈值之外的普通角度区间时,为了避免在 \cos\theta 接近 1 时因两个相近浮点数相减(1-\cos\theta)造成有效数字抵消,第二个系数的分子还可改用半角恒等式 1-\cos\theta=2\sin^2(\theta/2) 求值。本章配套的示例程序同时结合了小角泰勒展开与半角公式这两种技巧。

姿态积分的正交误差

既然单步转角很小,如果我们在幂级数(2.11)中只保留前两项(即一阶线性项),直接对旋转矩阵作显式欧拉(Euler)步进,结果会怎样?以体坐标角速度为例,单步显式 Euler 更新写为:

R_E=R\left(I+h[\boldsymbol\omega_b]_\times\right).

式中 R_E 表示一步 Euler 更新后的矩阵。从几何上看,增量 h[\boldsymbol\omega_b]_\times\boldsymbol p 沿着圆周的切线方向迈步,而切线上的步进点必然落在圆周外侧,因此每走一步都会使垂直于转轴的随体坐标轴被拉长一点。固定角速度大小和总仿真时长后,我们可以在下面的实验中调节时间步长 h,直观对比显式 Euler 更新与指数更新的长期表现。

实验 06Euler 更新与指数更新

图中追踪一根单位轴的端点。播放动画,观察两种更新方法怎样逐步积累差异;改变时间步,比较轨迹与正交误差。

实验 06 使用 Frobenius 范数 \varepsilon=\|R^{\mathsf T}R-I\|_F 来定量衡量矩阵偏离正交群 \mathrm{SO}(3) 的程度(其中下标 F 表示将矩阵全部九个元素的平方求和后再开方,同时反映了坐标轴长度偏离 1 以及轴间夹角偏离直角的误差)。可以看到,指数映射更新的正交误差始终維持在 10^{-15} 量级的浮点舍入误差附近;而显式 Euler 更新则会不断累积来自一阶截断的几何变形误差。

具体而言,对于垂直于固定转轴的初始单位向量,显式 Euler 更新每走一步都会像直角三角形求斜边一样将其长度放大为原来的 \sqrt{1+h^2\omega^2} 倍;连续执行 k 步后,该轴的长度便膨胀为 r_k=(1+h^2\omega^2)^{k/2},在图上表现为端点沿向外发散的螺线飞离单位圆。当固定总时长 T 并缩小时间步长 h 时,虽然总步数 k=T/h 增加了,但每一步的伸长因子 1+h^2\omega^2 以 h^2 的高阶速度趋于 1,将 k=T/h 代入即可看出累积膨胀随步长缩小而减弱。

推导Euler 更新的累计误差r_k=(1+h^2\omega^2)^{k/2}

设更新前的姿态矩阵满足 R^{\mathsf T}R=I,记 \Omega=[\boldsymbol\omega_b]_\times。利用反对称性 \Omega^{\mathsf T}=-\Omega,计算一步显式 Euler 更新后的 R_E^{\mathsf T}R_E:

\begin{aligned}R_E^{\mathsf T}R_E&=(I+h\Omega)^{\mathsf T}R^{\mathsf T}R(I+h\Omega)\\&=(I-h\Omega)(I+h\Omega)\\&=I-h^2\Omega^2=I+h^2\Omega^{\mathsf T}\Omega.\end{aligned}

不妨设刚体绕第三根随体轴以常角速度 \boldsymbol\omega_b=(0,0,\omega)^{\mathsf T} 转动。此时在垂直于转轴的前两维平面内,单步 Euler 增量矩阵为:

E=\begin{bmatrix}1&-h\omega\\h\omega&1\end{bmatrix},\qquad E^{\mathsf T}E=(1+h^2\omega^2)I_2.

这说明每经过一步,垂直平面内任意向量的长度都会乘以因子 \sqrt{1+h^2\omega^2}。连续更新 k 步后,R_k^{\mathsf T}R_k=\operatorname{diag}((1+h^2\omega^2)^k,(1+h^2\omega^2)^k,1),因此平面内单位坐标轴的长度 r_k 与三维姿态矩阵的正交误差 \varepsilon_k=\|R_k^{\mathsf T}R_k-I\|_F 分别为:

r_k=(1+h^2\omega^2)^{k/2},\qquad\varepsilon_k=\sqrt2\left[(1+h^2\omega^2)^k-1\right].

与之相对,指数映射增量在垂直平面内就是标准的二维正交旋转矩阵,每一步都严格保持向量长度不变。因此在恒定角速度下,无论时间步长 h 取多大,指数更新都能一步直达采样时刻的精确姿态;仅当角速度随时间变化时,才需要考虑步内将角速度取为常值所带来的时间离散误差。

06

相对旋转与对数映射

在姿态控制与运动规划中,我们经常需要比较两个姿态之间的偏差:设刚体的当前姿态为 R,期望到达的目标姿态为 S(两者均表示从物体坐标系到世界坐标系的旋转)。如果要在世界坐标系下施加一次旋转 Q,把当前姿态 R 直接转到目标姿态 S,那么按世界系旋转左乘的复合规则应有 QR=S。在等式两边同时右乘 R^{\mathsf T},即可解出:

Q=SR^{\mathsf T}.
(2.15)

矩阵 Q 就称为从当前姿态 R 到目标姿态 S 的相对旋转(在世界系下表示)。一旦从矩阵 Q 中反解出对应的旋转轴和转角,就能用三维旋转向量定量刻画当前姿态与目标姿态之间的朝向误差。

同样地,如果希望在当前刚体的物体坐标系下表示这一姿态偏差,则按相对变换右乘的复合规则应满足 RQ_b=S,两边左乘 R^{\mathsf T} 即得体坐标下的相对旋转矩阵 Q_b=R^{\mathsf T}S。由于两种相对旋转描述的是同一次空间转动,它们所对应的世界系旋转向量 \boldsymbol\phi 与物体坐标系旋转向量 \boldsymbol\phi_b 满足坐标变换关系 \boldsymbol\phi=R\boldsymbol\phi_b。下一章介绍四元数时,“目标四元数右乘当前四元数之逆”与“当前四元数之逆左乘目标四元数”这两种姿态差公式,分别对应的正是这里的左乘增量 Q=SR^{\mathsf T} 与右乘增量 Q_b=R^{\mathsf T}S。

推导相对旋转的体坐标表达Q_b=R^{\mathsf T}S,\quad\boldsymbol\phi=R\boldsymbol\phi_b

将体坐标旋转增量 Q_b 右乘在当前姿态 R 的右侧,使之满足 RQ_b=S。在等式两边左乘 R^{\mathsf T},并结合式(2.15)的 S=QR,可得 Q 与 Q_b 之间的相似变换关系:

Q_b=R^{\mathsf T}S,\qquad RQ_b=S,\qquad Q=RQ_bR^{\mathsf T}.

这表明世界系增量 Q 与体坐标系增量 Q_b 通过当前姿态矩阵 R 相互转换。设体坐标增量由旋转向量 \boldsymbol\phi_b 经指数映射生成,即 Q_b=\exp([\boldsymbol\phi_b]_\times),将矩阵指数按幂级数展开并代入 Q=RQ_bR^{\mathsf T}:

\begin{aligned}RQ_bR^{\mathsf T}&=I+R[\boldsymbol\phi_b]_\times R^{\mathsf T}+\frac12R[\boldsymbol\phi_b]_\times^2R^{\mathsf T}+\cdots\\&=I+[R\boldsymbol\phi_b]_\times+\frac12[R\boldsymbol\phi_b]_\times^2+\cdots\\&=\exp([R\boldsymbol\phi_b]_\times).\end{aligned}

中间步骤利用了 R[\boldsymbol\phi_b]_\times^2R^{\mathsf T}=(R[\boldsymbol\phi_b]_\times R^{\mathsf T})(R[\boldsymbol\phi_b]_\times R^{\mathsf T}) 以及第 4 节证明过的叉乘矩阵变换恒等式 R[\boldsymbol\phi_b]_\times R^{\mathsf T}=[R\boldsymbol\phi_b]_\times。因此,在同一转角主值分支下(半周处选取相互对应的轴向),世界系旋转向量与体坐标系旋转向量满足 \boldsymbol\phi=R\boldsymbol\phi_b,与角速度向量的坐标变换规律 \boldsymbol\omega=R\boldsymbol\omega_b 完全一致。

从旋转矩阵求轴角

给定一个旋转矩阵 Q\in\mathrm{SO}(3),如何反过来求出它的旋转角 \theta 与单位旋转轴 \boldsymbol n?观察 Rodrigues 公式 Q=I+\sin\theta\,[\boldsymbol n]_\times+(1-\cos\theta)[\boldsymbol n]_\times^2 可以发现:右侧三项中,I 和 [\boldsymbol n]_\times^2 都是对称矩阵,唯独 \sin\theta\,[\boldsymbol n]_\times 是反对称矩阵。因此,对矩阵 Q 分别取迹(即主对角线三个元素之和 \operatorname{tr}Q)和反对称部分 Q-Q^{\mathsf T},就能把 \cos\theta 与 \sin\theta\,[\boldsymbol n]_\times 干净地分离出来:

\begin{aligned}\operatorname{tr}Q&=1+2\cos\theta,\\Q-Q^{\mathsf T}&=2\sin\theta\,[\boldsymbol n]_\times.\end{aligned}
(2.16)

将主值转角 \theta 约定在闭区间 [0,\pi] 内,由式(2.16)第一式即可通过反余弦函数求出转角 \theta=\arccos((\operatorname{tr}Q-1)/2);由第二式的三个独立非对角元差值则可提取出旋转轴 \boldsymbol n 的三个分量。当 0<\theta<\pi 时,\sin\theta>0,由此合成的旋转向量 \boldsymbol\phi=\theta\boldsymbol n 为:

\boldsymbol\phi=\frac{\theta}{2\sin\theta}\begin{bmatrix}Q_{32}-Q_{23}\\Q_{13}-Q_{31}\\Q_{21}-Q_{12}\end{bmatrix}.
(2.17)

式中 Q_{ij} 表示矩阵 Q 的第 i 行、第 j 列元素。这一从旋转矩阵 Q 反求反对称矩阵 [\boldsymbol\phi]_\times(或旋转向量 \boldsymbol\phi)的运算,称为旋转群上的对数映射(Logarithmic Map),它是第 5 节指数映射的逆运算:

\log Q=[\boldsymbol\phi]_\times,\qquad\exp([\boldsymbol\phi]_\times)=Q.

之所以需要先规定主值区间 \theta\in[0,\pi],是因为从旋转向量到旋转矩阵的指数映射是多对一的:绕同一根轴多转整数圈(\theta+2k\pi),或者把转轴反向的同时把转角取负(-\boldsymbol n,-\theta),得到的都是同一个旋转矩阵:

R(\boldsymbol n,\theta)=R(\boldsymbol n,\theta+2k\pi)=R(-\boldsymbol n,-\theta),\qquad k\in\mathbb Z.

将转角 \theta 限制在主值区间 [0,\pi] 后,在开区间 (0,\pi) 内的任意普通转角都对应唯一确定的单位转轴 \boldsymbol n。而在区间的两个端点处则出现几何退化:当 \theta=0(即 Q=I)时,没有发生转动,旋转轴可以任意选取,旋转向量始终唯一地取为零向量 \boldsymbol\phi=\boldsymbol 0;当 \theta=\pi(半周旋转)时,绕 \boldsymbol n 转过 \pi 与绕 -\boldsymbol n 转过 \pi 完全等价,因此存在一对互为相反数的旋转向量 \pm\pi\boldsymbol n 对应同一个半周姿态(当旋转连续跨过 \theta=\pi 时,主值旋转向量会在这对反向端点之间切换,但所表示的三维姿态本身依然连续)。接下来我们就专门讨论这两个端点附近的数值求值策略。

推导旋转角与旋转轴的恢复\operatorname{tr}Q=1+2\cos\theta

1. 计算旋转矩阵的迹。记 N=[\boldsymbol n]_\times。反对称矩阵 N 的三个主对角元均为零,而 N^2=\boldsymbol n\boldsymbol n^{\mathsf T}-I 的主对角元之和等于 (n_1^2+n_2^2+n_3^2)-3=1-3=-2:

\operatorname{tr}N=0,\qquad\operatorname{tr}(N^2)=\boldsymbol n^{\mathsf T}\boldsymbol n-3=-2.

利用迹算子的线性性质,对 Rodrigues 公式 Q=I+\sin\theta\,N+(1-\cos\theta)N^2 两边取迹,立得:

\operatorname{tr}Q=3+\sin\theta\cdot0+(1-\cos\theta)(-2)=1+2\cos\theta.

2. 提取反对称部分。利用 N^{\mathsf T}=-N 以及对称性 (N^2)^{\mathsf T}=(\boldsymbol n\boldsymbol n^{\mathsf T}-I)^{\mathsf T}=N^2,写出 Q^{\mathsf T} 并与 Q 相减,对称项 I 和 N^2 完全抵消:

\begin{aligned}Q^{\mathsf T}&=I-\sin\theta\,N+(1-\cos\theta)N^2,\\Q-Q^{\mathsf T}&=2\sin\theta\,N.\end{aligned}

3. 逐分量还原旋转向量。对照式(2.7)中叉乘矩阵 N=[\boldsymbol n]_\times 的元素排布,依次读取矩阵 Q-Q^{\mathsf T} 的第 (3,2)、(1,3)、(2,1) 位置元素:

\begin{aligned}Q_{32}-Q_{23}&=2\sin\theta\,n_1,\\Q_{13}-Q_{31}&=2\sin\theta\,n_2,\\Q_{21}-Q_{12}&=2\sin\theta\,n_3.\end{aligned}

当 \sin\theta\ne 0 时,将以上三式同除以 2\sin\theta 即得单位转轴 \boldsymbol n=(n_1,n_2,n_3)^{\mathsf T},再乘以转角 \theta 便得到式(2.17)的旋转向量 \boldsymbol\phi=\theta\boldsymbol n。

例题:同轴旋转的姿态差

设刚体当前姿态与目标姿态分别为绕世界系正 z 轴转过 \pi/6 和 \pi/2,即 R=R_z(\pi/6)、S=R_z(\pi/2)。由式(2.15)计算相对旋转矩阵:

Q=SR^{\mathsf T}=R_z(\pi/2)R_z(-\pi/6)=R_z(\pi/3).

该矩阵的迹为 \operatorname{tr}Q=\cos(\pi/3)+\cos(\pi/3)+1=2,故 \cos\theta=(2-1)/2=1/2,主值转角 \theta=\pi/3。同时,式(2.17)右端的非对角元差值向量为 (0,0,2\sin(\pi/3))^{\mathsf T}=(0,0,\sqrt3)^{\mathsf T},代入式(2.17)得:

\boldsymbol\phi=\frac{\pi/3}{2\sin(\pi/3)}\begin{bmatrix}0\\0\\\sqrt3\end{bmatrix}=\begin{bmatrix}0\\0\\\pi/3\end{bmatrix}.

计算结果直观地表明:从当前姿态出发,只需绕世界系正 z 轴继续逆时针转过 \pi/3(即 60^\circ),就能到达目标姿态 S。

零角与半周附近的数值处理

在编写通用对数映射函数时,直接套用式(2.17)会在主值区间的两个端点 \theta\to 0 和 \theta\to\pi 处遇到分母 2\sin\theta\to 0 的数值困难。针对两端不同的退化机理,我们需要分别采用对应的稳定算法:在 \theta=0 处直接返回零向量 \boldsymbol 0,在接近零角的小角度区间内利用泰勒展开计算比例系数 \theta/\sin\theta\to 1;而在转角接近半周(\theta\to\pi)时,反对称部分 Q-Q^{\mathsf T} 因 \sin\theta\to 0 而趋于零矩阵,此时需要改从矩阵的对称部分 Q+Q^{\mathsf T} 中提取旋转轴 \boldsymbol n。

为什么连转角 \theta 本身的求法也需要改进?这源于余弦函数 c=\cos\theta 在 \theta=0 和 \theta=\pi 两个端点处的导数 -\sin\theta 均为零,函数曲线在两端极其平缓:哪怕矩阵的迹因为浮点舍入混入了极微小的余弦误差 \delta,反余弦函数 \arccos(c+\delta) 也会在端点附近将角度误差放大到 \sqrt{|\delta|} 量级。反之,如果先从反对称部分算出 s=\sin\theta\ge 0,再把正弦 s 与余弦 c 一起送入双参数反正切函数 \theta=\operatorname{atan2}(s,c),就能充分利用正弦函数在两端斜率最大的优势,在整个 [0,\pi] 区间内准确地恢复转角。

实验 07转角恢复与端点附近的数值特性

蓝线表示余弦,棕线表示正弦,绿线表示对称部分中的系数。紫色辅助线展示余弦扰动如何传到转角;切换局部范围可观察端点附近的变化。

在实验 07 中,我们记 s=\sin\theta、c=\cos\theta,并通过滑块向余弦值人为注入一个可控扰动 \delta(同时保持正弦值 s 不变,并在求反余弦前将 c+\delta 截断到 [-1,1] 定义域内),以便单独观察余弦误差向转角传播的放大效应。虽然实际浮点计算中反对称部分也会带有微小舍入误差,但图中这一对照清晰地展示了为什么在端点附近不能单靠 \arccos c 定角。

定出转角 \theta 之后,下一步是恢复单位转轴 \boldsymbol n。对照实验 07 中的棕线与绿线可以看到:反对称部分所含的因子 \sin\theta(棕线)在半周 \theta=\pi 处衰减为零,导致式(2.17)完全丧失轴向信噪比;与此同时,对称部分所含的因子 1-\cos\theta(绿线)却在 \theta=\pi 处达到最大值 2。因此,当转角逼近 \pi 时,改从对称矩阵中提取轴向就能获得最充沛的数值信号。

推导端点附近的角度误差\mathrm d\theta=-\mathrm dc/\sin\theta

先考察开区间 (0,\pi) 内部的一阶误差传播。对 c=\cos\theta 两边求微分,可得:

\mathrm dc=-\sin\theta\,\mathrm d\theta,\qquad \mathrm d\theta=-\frac{\mathrm dc}{\sin\theta}.

可见当 \theta 靠近 0 或 \pi 时,分母 \sin\theta\to 0,余弦值上的微小误差 \mathrm dc 会被急剧放大。以半周端点为例,令 \theta=\pi-\varepsilon(其中 \varepsilon>0 很小),将余弦在此处作泰勒展开:

\begin{aligned}\cos(\pi-\varepsilon)&=-\cos\varepsilon\\&=-1+\frac{\varepsilon^2}{2}+O(\varepsilon^4).\end{aligned}

若真实转角为 \pi(精确余弦为 -1),而计算出的余弦值混入了正扰动 \delta>0 变为 -1+\delta,则由 \delta\approx\varepsilon^2/2 解得反余弦给出的角度偏差高達 \varepsilon\approx\sqrt{2\delta}。例如在实验 07 中取微小的扰动 \delta=0.002,反余弦算出的角度偏差就达到 \varepsilon\approx\sqrt{0.004}\approx 0.0632\,\mathrm{rad}\approx 3.62^\circ。

反观 \theta=\operatorname{atan2}(s,c) 的误差特性:设受扰动后的 (c,s) 写成极坐标形式 c=r\cos\theta、s=r\sin\theta(其中 r=\sqrt{c^2+s^2}>0),对两式分别求微分:

\mathrm dc=\cos\theta\,\mathrm dr-r\sin\theta\,\mathrm d\theta,\qquad \mathrm ds=\sin\theta\,\mathrm dr+r\cos\theta\,\mathrm d\theta.

将第一式乘以 -s、第二式乘以 c 后相加,消去径向变化项 \mathrm dr,即得角度微分与 (\mathrm dc,\mathrm ds) 的完整一阶关系:

c\,\mathrm ds-s\,\mathrm dc=r^2\mathrm d\theta,\qquad \mathrm d\theta=\frac{c\,\mathrm ds-s\,\mathrm dc}{s^2+c^2}.

在单位圆 s^2+c^2=1 附近,分母恒为 1,彻底消除了除以 \sin\theta 的奇异性。特别地,在实验 07 固定 \mathrm ds=0、仅给余弦施加扰动 \mathrm dc=\delta 的条件下,一阶角度误差仅为 \mathrm d\theta=-s\delta,在两端点(s\to 0)处反而趋于零;即便在真实计算中 \mathrm ds 与 \mathrm dc 同时存在同量级的浮点舍入误差,\operatorname{atan2}(s,c) 的角度误差也始终与输入舍入误差保持同一数量级。

综合实验 07 的三条曲线,完整的旋转对数映射算法可以清晰地归纳为两步:第一步,先从反对称部分 Q-Q^{\mathsf T} 构造向量 \boldsymbol a=\sin\theta\,\boldsymbol n,以其模长 s=\|\boldsymbol a\| 作为正弦、以 c=(\operatorname{tr}Q-1)/2 作为余弦,调用 \theta=\operatorname{atan2}(s,c) 求出稳定转角;第二步,根据 \theta 所在的区间分三支恢复旋转向量——小角度区间用 \theta/\sin\theta 的泰勒级数缩放 \boldsymbol a,中间普通角度区间直接按式(2.17)计算 (\theta/s)\boldsymbol a,而在接近 \pi 的半周区间则改从对称矩阵 Q+Q^{\mathsf T} 提取单位轴 \boldsymbol n。这套分支策略的核心思想,就是在每一个角度区间都挑选数值幅度最大、条件数最好的矩阵部分来提取几何信息。

例题:半周旋转的轴信息

考察绕单位轴 \boldsymbol n=(1,1,0)^{\mathsf T}/\sqrt2 转过半周(\theta=\pi)的旋转矩阵。将 \sin\pi=0、\cos\pi=-1 代入 Rodrigues 公式,可得 Q=I+2N^2=2\boldsymbol n\boldsymbol n^{\mathsf T}-I,具体矩阵及半周对称矩阵 (Q+I)/2 分别为:

Q=\begin{bmatrix}0&1&0\\1&0&0\\0&0&-1\end{bmatrix},\qquad \frac{Q+I}{2}=\begin{bmatrix}1/2&1/2&0\\1/2&1/2&0\\0&0&0\end{bmatrix}.

此时 Q 本身是对称矩阵,反对称部分 Q-Q^{\mathsf T}=0 不含任何轴向信息;而右侧的 (Q+I)/2=\boldsymbol n\boldsymbol n^{\mathsf T} 则完整保留了旋转轴的外积矩阵。由其第一个主对角元 n_1^2=1/2 可取 n_1=1/\sqrt2,再将该矩阵的第一列元素除以 n_1,立即还原出 n_2=(1/2)/n_1=1/\sqrt2、n_3=0/n_1=0,准确找回了旋转轴 \boldsymbol n。

计算主值转角与特殊角度的计算\theta=\operatorname{atan2}(s,c)

1. 由正弦与余弦联合求主值转角。将反对称部分 Q-Q^{\mathsf T} 的三个独立元素除以 2,组装为轴向正弦向量:

\boldsymbol a=\frac12\begin{bmatrix}Q_{32}-Q_{23}\\Q_{13}-Q_{31}\\Q_{21}-Q_{12}\end{bmatrix}=\sin\theta\,\boldsymbol n.

由于 \|\boldsymbol n\|=1 且主值转角满足 \theta\in[0,\pi],故向量 \boldsymbol a 的模长直接给出非负正弦值 \|\boldsymbol a\|=\sin\theta\ge 0。由此定义:

s=\|\boldsymbol a\|,\qquad c=\frac{\operatorname{tr}Q-1}{2},\qquad\theta=\operatorname{atan2}(s,c).

该式在零角附近直接依靠 s=\|\boldsymbol a\|\approx\theta 保持一阶精度。实际编程时,可先将 c 限制在 [-1,1] 范围内,以防浮点误差使其略微越界。

2. 零角附近的泰勒展开求值。当 \theta 很小时,直接利用 \boldsymbol\phi=(\theta/\sin\theta)\boldsymbol a 并对系数 \theta/\sin\theta 作偶次幂级数展开:

\boldsymbol\phi=\frac\theta{\sin\theta}\boldsymbol a,\qquad\frac\theta{\sin\theta}=1+\frac{\theta^2}{6}+\frac{7\theta^4}{360}+O(\theta^6).

这里展开式的系数可由待定系数法直接导出:已知 \sin\theta/\theta=1-\theta^2/6+\theta^4/120+O(\theta^6),设其倒数展开为 1+u\theta^2+v\theta^4+O(\theta^6),将两级数相乘并令乘积中 \theta^2 项与 \theta^4 项的系数为零:

u-\frac16=0,\qquad v-\frac u6+\frac1{120}=0.

由第一式得 u=1/6,代入第二式即得 v=1/36-1/120=7/360。

3. 半周附近从对称部分提取旋转轴。将 Rodrigues 公式 Q=I+\sin\theta\,N+(1-\cos\theta)N^2 与其转置 Q^{\mathsf T} 相加,消去反对称项 N 并代入 N^2=\boldsymbol n\boldsymbol n^{\mathsf T}-I 与 c=\cos\theta:

Q+Q^{\mathsf T}=2cI+2(1-c)\boldsymbol n\boldsymbol n^{\mathsf T}.

当 \theta 接近 \pi 时,1-c\approx 2,移项除以 2(1-c) 即可分离出单位轴的秩一外积矩阵 P:

P=\frac{Q+Q^{\mathsf T}-2cI}{2(1-c)}=\boldsymbol n\boldsymbol n^{\mathsf T}.

特别地,当严格处于半周(c=-1,Q=Q^{\mathsf T})时,上式简化为 P=(Q+I)/2。外积矩阵 P 的三个主对角元分别为 P_{11}=n_1^2、P_{22}=n_2^2、P_{33}=n_3^2,三者之和等于 1。为了避免除以接近零的分量,先在三个对角元中找出最大者 P_{kk}=\max_i P_{ii}(由鸽巢原理知必有 P_{kk}\ge 1/3),开方求出主分量 n_k=\sqrt{P_{kk}},再由第 k 列的非对角元 P_{jk}=n_jn_k 除以 n_k 确定其余两个分量的大小与相对符号:

n_j=\frac{P_{jk}}{n_k},\qquad j\ne k.

由于 (-\boldsymbol n)(-\boldsymbol n)^{\mathsf T}=\boldsymbol n\boldsymbol n^{\mathsf T},外积矩阵 P 只能将单位轴定到正负号 \pm\boldsymbol n:当 \theta<\pi(接近但未到达半周)时,只需检验内积 \boldsymbol n^{\mathsf T}\boldsymbol a 的符号,若为负则将 \boldsymbol n 整体取反,即可使其与反对称部分 \boldsymbol a=\sin\theta\,\boldsymbol n 的正向保持一致;当严格等于 \theta=\pi 时,\pm\boldsymbol n 给出完全相同的旋转,配套程序统一约定令最大绝对值分量 n_k>0。当旋转连续越过 \theta=\pi 时,主值旋转向量可能跳变到反向轴,但经指数映射还原出的旋转矩阵 Q 依然平滑连续。

07

MuJoCo 中的旋转运算

前面建立的旋转矩阵坐标变换、相对旋转复合以及指数映射积分,在物理引擎底层都有直接对应的实现。本节对照 MuJoCo 3.10.0 的 C 语言源码(版本号声明见 mujoco/CMakeLists.txt 第 32 行),看看这些数学运算在引擎内核中是如何组织与调用的。

旋转矩阵的存储方式

在内存中,MuJoCo 使用一个长度为 9 的一维连续浮点数组,按行优先(Row-Major)次序存储 3\times 3 旋转矩阵。因此,数学上代表第一根随体坐标轴的第一列 (r_{11},r_{21},r_{31})^{\mathsf T},在数组中的下标依次为 0, 3, 6;要读取某一根随体坐标轴在世界系中的方向向量,只需按步长 3 跨行取数即可:

R=\begin{bmatrix}r_{11}&r_{12}&r_{13}\\r_{21}&r_{22}&r_{23}\\r_{31}&r_{32}&r_{33}\end{bmatrix}\quad\longleftrightarrow\quad[\,r_{11},r_{12},r_{13},r_{21},r_{22},r_{23},r_{31},r_{32},r_{33}\,].

例如,在 engine_util_blas.c 第 153 行定义的 mju_mulMatVec3 函数实现了正向坐标变换 \boldsymbol x=R\boldsymbol p,其内部直接用矩阵的每一行与输入向量作内积,计算出三个输出分量:

// mju_mulMatVec3 中的三个输出分量
mat[0]*vec[0] + mat[1]*vec[1] + mat[2]*vec[2]
mat[3]*vec[0] + mat[4]*vec[1] + mat[5]*vec[2]
mat[6]*vec[0] + mat[7]*vec[1] + mat[8]*vec[2]

紧随其后的 mju_mulMatTVec3 函数则按列跨步取数,用矩阵的每一列与输入向量作内积以计算 \boldsymbol p=R^{\mathsf T}\boldsymbol x。当传入的矩阵为旋转矩阵时,该函数便直接完成了从世界坐标系到物体坐标系的逆向坐标变换。

世界姿态的计算与存储

在每个仿真步的前向运动学阶段,MuJoCo 沿着运动学树从根节点向叶节点递推复合各层变换,并将算出的每个刚体的世界位姿缓存在数据结构 mjData 中:其中 mjData.xquat 存放各刚体的世界姿态四元数,mjData.xmat 存放由四元数转换而来的 3\times 3 世界姿态旋转矩阵,mjData.xpos 则存放刚体局部原点在世界系下的三维位置。在 engine_core_smooth.c 第 182 行附近,可以看到将第 i 个刚体的计算结果写入全局缓存并同步生成旋转矩阵的代码:

// 每个刚体分别占四个、三个、九个数
mji_copy4(d->xquat + 4*i, xquat);
mji_copy3(d->xpos + 3*i, xpos);
mju_quat2Mat(d->xmat + 9*i, xquat);

之所以在保存四元数的同时预先算出旋转矩阵 xmat,是因为后续的碰撞检测与渲染模块需要将大量局部几何顶点快速变换到世界系;直接调用缓存好的 xpos 与 xmat 执行 \boldsymbol x=\boldsymbol c+R\boldsymbol p,可以避免对同一个刚体重复进行四元数到矩阵的转换。

体坐标角速度与右乘更新

关于三维转动的速度参考系,doc/overview.rst 自第 1013 行起明确规定了自由关节(Free Joint)与球关节(Ball Joint)的速度约定:刚体的线速度分量在世界坐标系下表示,而角速度分量则在随刚体运动的物体坐标系下表示(即本章的 \boldsymbol\omega_b)。当时间积分函数 mj_integratePos 推进自由关节或球关节的姿态时,会在内部调用 mju_quatIntegrate 完成单步旋转更新。

打开 engine_util_spatial.c 第 234 行可以看到,mju_quatIntegrate 先根据体坐标角速度与时间步长 h 构造出单步旋转增量 qrot,随后调用 mju_mulQuat(quat, quat, qrot) 将该增量右乘在当前姿态四元数 quat 的右侧。转换成矩阵语言,这一右乘次序对应的正是式(2.12)的第二式:

R(t+h)=R(t)\exp\!\left(h[\boldsymbol\omega_b]_\times\right).

有关这两个函数的接口参数说明,可进一步查阅官方文档中的 mj_integratePos 与 mju_quatIntegrate。

08

实现与练习

将本章推导的指数映射装入代码后,单步姿态更新函数只需接收当前姿态矩阵 R、体坐标角速度 omega_body 和时间步长 h,先算出单步旋转向量 \boldsymbol\phi=h\boldsymbol\omega_b,再将指数映射生成的增量矩阵右乘到 R 上即可,直接对应式(2.12):

def step_body(R, omega_body, h):
    phi = [h * w for w in omega_body]
    return mul(R, exp_so3(phi))

本章配套的示例脚本 rotation.py 完整实现了三阶矩阵乘法、叉乘矩阵、指数映射、对数映射以及世界系和物体坐标系下的姿态步进;测试脚本 check_rotation.py 则使用解析已知的特殊轴旋转、随机轴角样本以及零角和半周边界角度对实现进行逐项校验。两个脚本均仅依赖 Python 标准库。

在学习笔记根目录下运行以下命令即可执行全部校验:

python3 examples/check_rotation.py

建议读者动手依次实现 skew、mul 和 exp_so3,先用正文中的直角旋转与立方体对角线旋转两个例题检验旋转方向是否正确,再实现单步姿态更新;最后实现包含小角与半周分支的 log_so3,验证从任意旋转矩阵提取出旋转向量 \boldsymbol\phi 后,能否通过 \exp([\boldsymbol\phi]_\times) 精确重建原矩阵。

练习 1 · 坐标变换与逆变换

设刚体从初始重合姿态绕世界系正 z 轴转过 \pi/2,且刚体局部原点位于世界系下的 \boldsymbol c=(2,1,0)^{\mathsf T}\,\mathrm m 处。试写出此时的姿态矩阵 R,求刚体上局部坐标为 \boldsymbol p=(1,2,0)^{\mathsf T}\,\mathrm m 的点在世界系下的位置 \boldsymbol x,并用逆变换从 \boldsymbol x 还原出 \boldsymbol p。

答案矩阵的列与坐标恢复

绕世界系正 z 轴旋转 \pi/2 后,三根随体坐标轴在世界系中依次指向正 y 轴、负 x 轴和正 z 轴。将这三个单位方向按列排成旋转矩阵 R,并计算局部点的旋转后位移 R\boldsymbol p:

R=\begin{bmatrix}0&-1&0\\1&0&0\\0&0&1\end{bmatrix},\qquad R\boldsymbol p=\begin{bmatrix}-2\\1\\0\end{bmatrix}\mathrm m.

加上刚体原点的世界位置 \boldsymbol c 即得该点的世界坐标 \boldsymbol x;反过来,先从 \boldsymbol x 中减去原点位置 \boldsymbol c,再左乘转置矩阵 R^{\mathsf T},即可还原出局部坐标 \boldsymbol p:

\boldsymbol x=\boldsymbol c+R\boldsymbol p=\begin{bmatrix}0\\2\\0\end{bmatrix}\mathrm m,\qquad R^{\mathsf T}(\boldsymbol x-\boldsymbol c)=\begin{bmatrix}1\\2\\0\end{bmatrix}\mathrm m.

注意正向变换是“先旋转、后加上原点平移”,因此逆向变换应当按相反顺序“先减去原点平移、后左乘 R^{\mathsf T} 逆向旋转”。

练习 2 · 旋转复合的次序

空间中有一根初始指向世界系正 z 轴的单位向量 \boldsymbol e_z=(0,0,1)^{\mathsf T}。若先绕世界系正 x 轴转过 \pi/2,再绕世界系正 y 轴转过 \pi/2,求该向量的最终指向;若调换两次旋转的先后次序,最终指向又如何?请分别写出两种次序对应的矩阵乘法表达式。

答案中间方向与最终方向

追踪单位向量 \boldsymbol e_z 在两种次序下经过第一步旋转后的中间方向与经过第二步旋转后的最终方向:

\begin{aligned}\boldsymbol e_z&\xrightarrow{R_x(\pi/2)}-\boldsymbol e_y\xrightarrow{R_y(\pi/2)}-\boldsymbol e_y,\\\boldsymbol e_z&\xrightarrow{R_y(\pi/2)}\boldsymbol e_x\xrightarrow{R_x(\pi/2)}\boldsymbol e_x.\end{aligned}

由于绕固定世界轴的连续旋转按时间顺序从右向左依次左乘,后发生的旋转矩阵排在左侧,因此两种次序对应的矩阵乘积分别为:

R_y(\pi/2)R_x(\pi/2)\boldsymbol e_z=\begin{bmatrix}0\\-1\\0\end{bmatrix},\qquad R_x(\pi/2)R_y(\pi/2)\boldsymbol e_z=\begin{bmatrix}1\\0\\0\end{bmatrix}.

在正文实验 02 中将动画进度条分别拖动到 0.5(第一步结束)和 1.0(第二步结束),即可直观核对上述中间方向与最终方向。

练习 3 · Rodrigues 公式

将向量 \boldsymbol x=(1,0,2)^{\mathsf T} 绕正 z 轴单位向量 \boldsymbol n=(0,0,1)^{\mathsf T} 旋转 \theta=\pi/3。请分别写出它的轴向分量 \boldsymbol x_\parallel、垂直分量 \boldsymbol x_\perp、正交方向 \boldsymbol n\times\boldsymbol x 以及旋转后的最终向量 \boldsymbol x'。

答案向量分解与旋转结果

由式(2.5)计算轴向投影、垂直分量以及叉积向量:

\boldsymbol x_\parallel=\begin{bmatrix}0\\0\\2\end{bmatrix},\quad\boldsymbol x_\perp=\begin{bmatrix}1\\0\\0\end{bmatrix},\quad\boldsymbol n\times\boldsymbol x=\begin{bmatrix}0\\1\\0\end{bmatrix}.

将 \cos(\pi/3)=1/2 与 \sin(\pi/3)=\sqrt3/2 代入 Rodrigues 公式(2.6),可得:

\boldsymbol x'=\begin{bmatrix}0\\0\\2\end{bmatrix}+\frac12\begin{bmatrix}1\\0\\0\end{bmatrix}+\frac{\sqrt3}{2}\begin{bmatrix}0\\1\\0\end{bmatrix}=\begin{bmatrix}1/2\\\sqrt3/2\\2\end{bmatrix}.

可以看到,平行于 z 轴的分量 2 保持不变,而水平面内的垂直分量在半径为 1 的圆周上转过了 60^\circ;旋转前后向量的模长平方均为 1/4+3/4+4=5。

练习 4 · 刚体上的点速度

某时刻刚体的姿态为 R=R_z(\pi/2),参考点平移速度为 \boldsymbol v=(1,0,0)^{\mathsf T}\,\mathrm{m/s},世界系角速度为 \boldsymbol\omega=(0,0,3)^{\mathsf T}\,\mathrm{rad/s}。求刚体上局部坐标为 \boldsymbol p=(2,0,0)^{\mathsf T}\,\mathrm m 的材料点在世界系下的速度 \dot{\boldsymbol x},并说明转动速度分量的几何方向。

答案平移速度与切向速度

在做叉积运算前,必须先用当前姿态矩阵 R 将局部相对位置 \boldsymbol p 变换到世界坐标系,使两个向量在同一坐标系下表示:

R\boldsymbol p=\begin{bmatrix}0\\2\\0\end{bmatrix}\mathrm m,\qquad\boldsymbol\omega\times R\boldsymbol p=\begin{bmatrix}-6\\0\\0\end{bmatrix}\mathrm{m/s}.

将参考点平移速度 \boldsymbol v 与转动切向速度相加,即得该材料点的世界速度:

\dot{\boldsymbol x}=\boldsymbol v+\boldsymbol\omega\times R\boldsymbol p=\begin{bmatrix}-5\\0\\0\end{bmatrix}\mathrm{m/s}.

此时该点位于世界系正 y 轴上(距离转轴 2\,\mathrm m),绕正 z 轴逆时针转动产生的切向速度垂直于转轴和半径,指向负 x 方向,大小为 3\times 2=6\,\mathrm{m/s};与正 x 方向 1\,\mathrm{m/s} 的平移速度合成后,净速度沿负 x 方向、大小为 5\,\mathrm{m/s}。

练习 5 · 姿态更新的等价性

设刚体当前姿态为 R=R_z(\pi/2),恒定体坐标角速度为 \boldsymbol\omega_b=(1,0,0)^{\mathsf T}\,\mathrm{rad/s},时间步长为 h=\pi/2\,\mathrm s。请分别使用式(2.12)的世界系左乘公式和物体坐标系右乘公式计算下一时刻的姿态矩阵 R(t+h),验证两者结果一致。

答案左右两种更新的计算结果

先将体坐标角速度变换到世界系:\boldsymbol\omega=R\boldsymbol\omega_b=(0,1,0)^{\mathsf T}\,\mathrm{rad/s},说明该转动在世界系下是绕正 y 轴转过 h\|\boldsymbol\omega\|=\pi/2,而在物体系下是绕第一根随体轴转过 \pi/2。分别按左乘和右乘计算:

R(t+h)=R_y(\pi/2)R_z(\pi/2)=R_z(\pi/2)R_x(\pi/2)=\begin{bmatrix}0&0&1\\1&0&0\\0&1&0\end{bmatrix}.

两种方式算出的最终姿态矩阵完全相同,其三列依次为旋转后的三根随体坐标轴方向(恰好等价于第 3 节例题中绕立方体对角线 (1,1,1)^{\mathsf T} 旋转 2\pi/3 的置换矩阵)。

练习 6 · 相对旋转与旋转向量

已知刚体的当前姿态矩阵 R 和目标姿态矩阵 S 分别为:

R=\begin{bmatrix}0&0&1\\0&1&0\\-1&0&0\end{bmatrix},\qquad S=\begin{bmatrix}0&-1&0\\0&0&1\\-1&0&0\end{bmatrix}.

求世界系下的相对旋转矩阵 Q 以及对应的主值旋转向量 \boldsymbol\phi,并通过矩阵乘法核对 QR=S。

答案相对矩阵与轴角恢复

由式(2.15)计算世界系下的相对旋转矩阵:

Q=SR^{\mathsf T}=\begin{bmatrix}0&-1&0\\1&0&0\\0&0&1\end{bmatrix}.

该矩阵的迹为 \operatorname{tr}Q=0+0+1=1,因此 \cos\theta=(1-1)/2=0,主值转角为 \theta=\pi/2。读取反对称部分并代入式(2.17):

\begin{bmatrix}Q_{32}-Q_{23}\\Q_{13}-Q_{31}\\Q_{21}-Q_{12}\end{bmatrix}=\begin{bmatrix}0\\0\\2\end{bmatrix},\qquad\boldsymbol\phi=\begin{bmatrix}0\\0\\\pi/2\end{bmatrix}.

这表明从当前姿态 R 出发,绕世界系正 z 轴逆时针转过 \pi/2 即可到达目标姿态 S。将 Q 左乘 R,可以看到 R 的三列依次被绕 z 轴转过 90^\circ 变为 (0,0,-1)^{\mathsf T}、(-1,0,0)^{\mathsf T} 和 (0,1,0)^{\mathsf T},恰好拼成目标矩阵 S。

练习 7 · 小角与半周的计算分支

(1)对于绕正 z 轴转过极小角度 \theta=10^{-6}\,\mathrm{rad} 的旋转矩阵,写出系数 \theta/\sin\theta 的二阶泰勒近似值及对应的旋转向量 \boldsymbol\phi。(2)对于下面给出的半周旋转矩阵 Q,从对称部分求出一根单位旋转轴 \boldsymbol n 及对应的主值旋转向量 \boldsymbol\phi:

Q=\begin{bmatrix}0&1&0\\1&0&0\\0&0&-1\end{bmatrix}.
答案级数求值与对称部分求轴

(1)在小角度 \theta=10^{-6} 处,反对称部分给出 \boldsymbol a=(0,0,\sin\theta)^{\mathsf T}。使用二阶泰勒展开求值:

\frac{\theta}{\sin\theta}\approx1+\frac{\theta^2}{6}=1+\frac{10^{-12}}6,\qquad\boldsymbol\phi=\frac{\theta}{\sin\theta}\boldsymbol a\approx\begin{bmatrix}0\\0\\10^{-6}\end{bmatrix}.

(2)所给矩阵 Q 的迹为 \operatorname{tr}Q=-1,故 \cos\theta=(-1-1)/2=-1,主值转角为半周 \theta=\pi。此时反对称部分 Q-Q^{\mathsf T}=0,需由对称部分构造外积矩阵 P=(Q+I)/2:

P=\frac{Q+I}{2}=\begin{bmatrix}1/2&1/2&0\\1/2&1/2&0\\0&0&0\end{bmatrix}.

取第一个最大主对角元开方得 n_1=\sqrt{P_{11}}=1/\sqrt2,再由第一列非对角元除以 n_1 得 n_2=P_{21}/n_1=1/\sqrt2、n_3=P_{31}/n_1=0。因此单位旋转轴与主值旋转向量分别为:

\boldsymbol n=\frac{(1,1,0)^{\mathsf T}}{\sqrt2},\qquad\boldsymbol\phi=\frac{\pi(1,1,0)^{\mathsf T}}{\sqrt2}.

由于半周旋转正反双向等价,取反向轴 -\boldsymbol n 配上转角 \pi 同样能还原出该矩阵。

练习 8 · 姿态积分的误差

固定总仿真时长为 T=6\,\mathrm s,体坐标角速度恒为 \boldsymbol\omega_b=(0,0,2)^{\mathsf T}\,\mathrm{rad/s}。分别取时间步长 h=0.1\,\mathrm s 和 h=0.01\,\mathrm s,对比显式 Euler 更新与指数映射更新在期末的正交误差 \varepsilon=\|R^{\mathsf T}R-I\|_F。请先用解析公式预测误差数值,再编写简短的 Python 循环予以核对。

答案步长与累计误差

在 h=0.1\,\mathrm s 和 h=0.01\,\mathrm s 下,总步数分别为 k=60 步和 k=600 步,单步因子 1+h^2\omega^2 分别为 1+0.04=1.04 和 1+0.0004=1.0004。代入第 5 节导出的显式 Euler 累积正交误差公式:

\begin{aligned}\varepsilon_{60}&=\sqrt2[(1.04)^{60}-1]\approx13.46,\\\varepsilon_{600}&=\sqrt2[(1.0004)^{600}-1]\approx0.384.\end{aligned}

可以看到,将步长缩小为原来的十分之一后,显式 Euler 的正交误差显著下降,但仍高达 0.384;而指数映射更新在两种步长下都严格保持正交性,期末误差仅在 10^{-15} 量级(纯浮点舍入误差)。将以下脚本与 rotation.py 放在同一目录下运行即可复算核对:

from math import sqrt
from rotation import identity, mul, transpose, skew, exp_so3

def compare(h):
    steps = round(6 / h)
    K = skew([0, 0, 2])
    increments = [
        [a + h * b for a, b in zip(identity(), K)],
        exp_so3([0, 0, 2 * h]),
    ]
    for increment in increments:
        R = identity()
        for _ in range(steps):
            R = mul(R, increment)
        gram = mul(transpose(R), R)
        error = sqrt(sum((a - b) ** 2
                         for a, b in zip(gram, identity())))
        print(f"{error:.6g}")

compare(0.1)
compare(0.01)