(Practical Parameterization of Rotations Using the Exponential Map)
哪吒三太子 2016/3/26 于上海卢湾
下面为本文使用术语表,表中所有词条大多直接采用英文术语,请各位读者自行伸缩去取,笔者在此不做所谓”直译”.
- DOF(degree-of-freedom) 旋转自由度
- ODE(ordinary differential equation) 常微分方程
- transformation matrix 变换矩阵(变换一词包含:平移,旋转,放缩,甚至仿射)
- S3 单位四元数组成的球形表面空间
- SO3 四维空间中的三维子空间集合
- normalize 标准化,通常变模为单位长度1
- end-effector 机械臂末端-与环境交互部分
- singularity 奇点
- hierarchies 层级结构
三维旋转自由的参数化一直不竟如人意,虽如此现有的图形应用方法除了要求我们拥有计算连续位移和物体链接旋转的能力之外,大多数还需要我们能够自行处理微积分方程,DOF的优化,和旋转插值.
(注意:在这里的旋转为 orientation 统称,但不具体指定参数化方法,e.g.欧拉角表示法,四元数表示法,亦或者本文介绍的指数映射法)但广泛使用的欧拉角或四元数参数法因为其自身数学限制,都不能很好的适应上述这些需求.
指数映射法使用旋转轴和旋转量来描述R3中的向量. 一些图形研究员已经把这种方法应用在了旋转插值问题中,但其他却未涉及. 本文就是为了补缺这一片应用方法的空白,详细展现了DOF旋转问题中的计算,微分,积分方法供读者参考使用. 并且这种方法在计算机精度方面呈现出数值稳定,在映射中存在的奇点(singularity)也可以简单的动态重复参数化来解决. 本文将会演示如何使用指数映射法来解决类似万向自由体和DOF空间铰链问题. e.g. 精确地数学建模人体的肩膀,胯等关节的连接运动.
在实验结果中指数映射法相比较于欧拉角和四元数法,有以下优势:更强的鲁棒性,小向量可以被更好的表达,无需明确过多的限制条件,更好的建模能力,ODE简化和更好的插值性能.
为什么我们要使用四元数指数映射?
在图形应用中主要有5种基本方法来描述并控制物体的旋转:
1. forward kinematics
2. inverse kinematics
3. forward dynamics
4. inverse dynamics
5. spacetime optimization
其他方法则基于这五种基本方法之上.
基于这些方法的应用除了在软件大小和复杂度上有差异之外,都必须具有以下能力:
1. 能计算物体(物体的组合)上每个点的旋转和坐标, 这是forward kinematics方法所需要的基础能力.
2. 能计算每个点旋转和坐标的导数,这是inverse kinematics, dynamics,spacetime所需要的基础能力.
3. 能对ODE进行积分运算,这是inverse kinematics, dynamics,spacetime所需能力.
4. 能对两个关键帧进行平滑插值.
5. 能组合多个旋转成为一个操作.
6. 能计算对应旋转的参数逆,找出对应参数. i.e. 上述能力都是以参数计算旋转,而此能力是以旋转计算参数. 故称为逆操作.
上述中3.4.5是参数空间与生俱来的特性. 1,2则需要把旋转表示为4x4的 transformation 矩阵. 并且因为 transformation 具有诸多线性空间变换能力,所以我们可以在方法重穿插使用多种参数方法 e.g.使用旋转矩阵计算偏微分得到点旋转和坐标导数.
既然旋转矩阵能很好的表示一个旋转,并且它也有乘法进行旋转组合的功能,更进一步可以使用优化代码来对矩阵进行快速运算,那我们为什么不用它来对旋转进行参数化表达?
原因是我们必须强加6个非线性的限制条件在旋转矩阵的9个参数上,3个条件限制每个矩阵列向量的模为1,3个条件使他们互相保持正交).所以每一步的运算之前都首先保证矩阵为正交矩阵,这个条件很苛刻.
欧拉角由一个指定坐标系的 x,y,z 轴,决定一个向量在对应坐标轴上的对应旋转. 通常我们可以看到它被表示成矩阵的形式并用 sin cos 正余弦函数来表征对应坐标旋转,虽然对旋转角的参数化是非线性的(sin,cos),但他们的导数非常容易被计算出来.
欧拉角的坏处和好处同样明显,它会遇到一个致命的问题 — 万向节死锁. 讨论死锁问题超出了本文范畴,有兴趣的读者可参考https://en.wikipedia.org/wiki/Gimbal_lock.
虽然欧拉角有致命缺陷,但我们不能忽视它在 2DOFs 旋转问题中表现良好,并在不遇到死锁问题下非常容易使用.
四元数的历史非常离奇,它是在爱尔兰数学家 William Rowan Hamilton和妻子散步时偶然发现的. 它用一个四维向量表示三维旋转,对四元数的详细讨论同样也超出了本文的范畴,请移步参考http://baike.baidu.com/view/319754.htm.
在这里我们只说以下四元数的优缺点. 四元数由于定义及其精妙(其实四元数在群论中表达为一个S3球表面的数域,对乘法封闭(笔者其实是群论的疯狂脑残粉 :P)),用它来表示旋转问题比矩阵运算更快速,比欧拉角而言没有死锁问题,而且非常易于插值计算 e.g.动画的计算.
它的缺点是由于四元数表示四维空间中的向量,而现实世界只有三个维的自由度,所以在进行积分运算的时候,每一步运算都需要把它进行 normalize 以压缩掉一个维度,对积分运算造成了很大的麻烦. 在实际应用中积分步长很难控制,太短则会导致性能下降问题,太长则离开S3球表面,误差就会很大. 还有一种方法由Michael Gleicher 提出,它解决了 normalize 问题,但会导致 Jacobi 矩阵秩缺失,这意味着在四维空间中有一个”子空间”中所有四元数都对应同一个三维旋转 i.e.四元数在这个”奇特的”空间中任意改变并不会导致三维空间中旋转出现变化.(通常来说就是掉进了一个高维流形陷阱之中了). 可能遇到的一个实际问题就是:我们再也无法求出物体的转动惯量了.
总结来说使用四元数确实可以解决很多问题,但当软件需要计算导数来控制和优化系统的时候,事情就会变得很麻烦. 最后毋庸置疑的它是计算3DOF旋转插值的最佳方法.
引入指数映射的原因是四元数只用到了所有四元数集中一个一个子空间,也就是S3球表面. 所以我们希望有一种方法能让R3空间中的点一一对应S3球表面,而不会超出这个球表面空间,通常我们用强加给四元数单位长度的限制来解决这个问题(上面也说明了每步需要 normalize 的开销和积分时候的麻烦).所以我们的需求总结如下:
1. 方法必须没有万向节死锁
2. 旋转插值要很容易实现
3. 组合旋转的能力
4. 容易进行导数与积分运算
Anyway,满足上述所有条件这是不可能的:( 已经有数学家进行过严密的证明R3至SO3(四元数的所有三维子空间的统称,当然也包含球空间)是不可能消除奇点的,也就是说一定会遇到死锁问题,但是我们可以轻而易举地躲开这个不可避免的问题.
下面我们就用数学语言来描述它:
四元数:
其中 v^=v/|v| θ=|v| ,从方程上看出我们把四维向量包装成三维的了,其中 v = ai+bj+ck 而常量 w 则用 v 的模来表示. 上述方程式在数学上需要推导在零处函数的极限,但是在计算机中当|v|接近于 0 时计算结果溢出(因为计算机 float 最多表达1e-38 小数,小于这个数则会栈溢出),会导致计算溢出,那么我们稍许改变一下方程式 θ=|v| . 这样式子就变成 sin(1/2θ)vθ 而 sin(1/2θ)1/2θ=sinc(1/2θ) 为辛格函数 在零处有定义,所以方程式在计算机计算中变得稳定. 而令人沮丧的是标准C库没有辛格函数的定义,所以我们用泰勒展开表达(题外话:其实计算机计算三角函数都是用泰勒展开计算的,因为泰勒展开在三角函数的 [−π,π] 收敛且拉格朗日余项误差可以任意小)
学过《高等数学》的读者一定知道一旦函数的泰勒展开收敛,则当估计项为 n 时,余项误差不会超过第 n+1 项的值,我们只要让 n+1 项为计算机最小精度即可,这样我们就消除了计算机计算误差了. 事实上我们只需前两项即可消误差:
因为四元数的指数是连续函数,所以可以使用链式法则进行求导:
####3.2.1 奇点问题
之前我们一直说该方法是不能避免遇到奇点问题的,而这个问题是可以被躲避的,原因在于该函数的奇点在 2nπ 上. 众所周知当取到 2π 时,旋转其实是绕到了原处,我们只要把取值范围变成 [0,2π) 即可,当 θ 接近 2π 时我们用 2π−θ 也就是-v来代替即可.
因为模拟时间步长内旋转不可能超过 π ,所以每一步模拟我们都检测一下 |v| 如果它接近 π ,那么我们就用 (1−2π/|v|)v 来代替 v,在试验中上面等价的方程更利于倒数的计算.这个动态的重复计算参数理论上来说能完全避免函数掉入奇点之中.当然这也使我们不能在超出规定范围内进行动画插值(e.g. 有两个rotation状态假设沿着x轴正方向旋转,r1=30度,r2=430度,我们不能简单地在这两个状态中插值,因为后者超过了我们规定的范围,所以必须被分割成30-180, 180-360, 360-430 三个部分进行插值计算,这无疑增加了系统的复杂度)
####3.2.2 旋转合并
因为四元数的乘法 ≡ 旋转矩阵的乘法.但是我们把四元数常量 w 整合进了 v 之中导致这个性质被破坏,所以在合并旋转的时候我们必须先把四元数的指数还原成标准四元数(保证模为单位长度1),然后进行乘法合并,最后再映射到四元数的指数之中.
幸运的是我们通常不需要合并指数形式的旋转,因为物体的旋转通常由它的导数来驱动,或者直接修改四元数部分的参数. 当他们转换成 transformation matrix(变换矩阵)并施加在物体上时,它们就以矩阵的形式被合并了. 故除非特殊需要,否则没有额外的运算开销.
磨刀霍霍,我们讨论了那么久就是为了在这里说明它是如何被用来简化实际应用的.请你相信,指数映射在控制,模拟方面都具有非常好的性能.但在插值和优化方面比其他方法复杂.
研究这项工作的主要动机是因为我们想要一个较好的微分控制器,它可以直接控制物体的旋转,进行 inverse kinematics研究和实时的机械臂控制. 为了控制物体或者机械臂的末端(end-effector)(这里使用机械臂泛指用关节链接的物体运动-其实也就是多刚体系统运动),微分控制器只要求 ∂R/∂v 是连续的,并且不存在万向节死锁这两个条件即可. 因为计算机控制发生在离散时间内,而我们之前介绍的动态重复参数化方法可以有效躲过万向节死锁,所以这两项条件总是可以被满足的.
在动力学模拟中,我们不仅要追踪物体某一时刻的位置和姿态,同样需要追踪它的线速度和角速度.
不要忘了电脑模拟是离散时间的,为了正确的计算物体的位移和旋转,我们需要计算导数来进行函数的数值逼近,对一个四元数表示的旋转而言,它对时间的导数为如下公式 (数学推导在这里):
上面我们已经介绍了全自由度下四元数指数映射的使用,现在我们用一个例子来演示带限制条件的铰链关节.
假设现在我们要对手腕进行数学建模,手腕在两个自由度上有角度限制并在”直线”方向上不能扭曲. 我们设直线方向上为 z坐标轴,任意两个互相垂直且垂直于 z轴的坐标轴为 x,y 那么我们就有以下公式: