前言
姿态空间插值的一个主要问题是姿态空间的三个自由度是相互耦合的,而不像位置空间一样三个自由度完全解耦正交。所以,直接对欧拉角三个角度分别插值,可能会出现错误的结果。
姿态空间是一个 SO(3)群。当确定姿态空间的空间属性,我们就可以通过数学方法来定义它的空间插值。
Serp 插值可以认为是最短路径插值,类似于位置空间的直线插值。但直线(Slerp)插值只能保证一阶连续,过渡点处的角速度方向会发生突变。
Lerp插值
线性插值(Lerp/Linear Interpolation),即沿着一条直线(也就是圆上的一个弦)进行插值,此种插值方式所得结果并非单位四元数(只有单位四元数才能表示旋转)。
q t = L e r p ( q 0 , q 1 , t ) = ( 1 − t ) q 0 + t q 1 \mathrm{q_t~=Lerp(q_0,q_1,t)=(1-t)q_0~+tq_1} qt =Lerp(q0,q1,t)=(1−t)q0 +tq1
Slerp插值
球面线性插值(SphericalLinearInterpolation)对每一对四元数使用Slerp插值,虽然能够保证每两个四元数之间的角速度是固定的,但是角速度会在切换插值的四元数时出现断点,或者说在切换点不可导.
Slerp球面线性插值是对角度本身进行线性插值,适用于插补角度不接近0度的情况。
Slerp插值公式:
S l e r p ( t ; q 0 , q 1 ) = q 0 sin [ ( 1 − t ) θ ] + q 1 sin ( t θ ) sin θ ( t ∈ [ 0 , 1 ] ) \mathrm{Slerp(t;q_0,q_1)=\frac{q_0\sin\left[(1-t)\theta\right]+q_1\sin(t\theta)}{\sin\theta}\quad(t\in[0,1])} Slerp(t;q0,q1)=sinθq0sin[(1−t)θ]+q1sin(tθ)(t∈[0,1])
对于单位四元数:
q = cos ( θ ) + u ^ sin ( θ ) \mathrm{q}=\cos(\theta)+\hat{\mathrm{u}}\sin(\theta) q=cos(θ)+u^sin(θ)
其中 u ^ \hat{\mathrm{u}} u^为单位三维矢量, u ^ u ^ = − 1 \hat{\mathrm{u}}\hat{\mathrm{u}}=-1 u^u^=−1。
对于单位四元数,该公式可写为:
S l e r p ( t ; q 0 , q 1 ) = q 0 ( q 0 − 1 q 1 ) t \mathrm{Slerp(t;q_0,q_1)=q_0(q_0^{-1}q_1)^t} Slerp(t;q0,q1)=q0(q0−1q1)t
四元数有定理:
e x p ( u ^ θ ) = cos ( θ ) + u ^ sin ( θ ) q t = ( cos ( θ ) + u ^ sin ( θ ) ) t = exp ( u ^ θ t ) l o g ( q ) = l o g ( cos ( θ ) + u ^ sin ( θ ) ) = l o g ( exp ( u ^ θ ) ) = u ^ θ \begin{array}{c}\mathrm{exp(\hat{u}\theta)=\cos(\theta)+\hat{u}\sin(\theta)}\\\mathrm{q^t=(\cos(\theta)+\hat{u}\sin(\theta))^t=\exp(\hat{u}\theta t)}\\\mathrm{log(q)=log(\cos(\theta)+\hat{u}\sin(\theta))=log(\exp(\hat{u}\theta))=\hat{u}\theta}\end{array} exp(u^θ)=cos(θ)+u^sin(θ)qt=(cos(θ)+u^sin(θ))t=exp(u^θt)log(q)=log(cos(θ)+u^sin(θ))=log(exp(u^θ))=u^θ
根据上述定理,可以推得:
( q 0 − 1 q 1 ) t = exp ( u ^ θ t ) = exp ( log ( q 0 − 1 q 1 ) ∗ t ) \mathrm{(q_0^{-1}q_1)^t=\exp(\hat{u}\theta t)=\exp(\log(q_0^{-1}q_1)*t)} (q0−1q1)t=exp(u^θt)=exp(log(q0−1q1)∗t)
Slerp插值可写为
S l e r p ( t ; q 0 , q 1 ) = q 0 e x p ( l o g ( q 0 − 1 q 1 ) ∗ t ) \mathrm{Slerp(t;q_0,q_1)=q_0~exp(log(q_0^{-1}q_1)*t)} Slerp(t;q0,q1)=q0 exp(log(q0−1q1)∗t)
以下4个Slerp公式相等:
如果四元数点积的结果是负值(夹角大于90°),那么后面的插值就会在4D球面上绕远路。为了解决这个问题,先测试点积的结果,当结果是负值时,将2个四元数的其中一个取反(并不会改变它代表的朝向)。而经过这一步操作,可以保证这个旋转走的是最短路径。
当 q 1 q_1 q1和 q 2 q_2 q2的夹角θ差非常小时会导致sinθ→0,这时除法可能会出现问题。为了避免这样的问题,当θ非常小时可以使用简单的线性插值代替(当θ → 0时,sinθ ≈ θ,因此方程退化为线性方程:slerp(p, q, t) = (1−t)p + tq
Nlerp正规化线性插值
正规化线性插值(Normalized LinearInterpolation),是对线性插值的改进,即将线性插值除以其模长,将其转化为一个单位四元数。这种插补算法适用于插补角度接近0度的情况。
q t = L e r p ( q 0 , q 1 , t ) = ( 1 − t ) q 0 + t q 1 ∥ ( 1 − t ) q 0 + t q 1 ∥ \mathrm{q_t=Lerp(q_0,q_1,t)=\frac{(1-t)q_0+tq_1}{\|(1-t)q_0+tq_1\|}} qt=Lerp(q0,q1,t)=∥(1−