Unleashing Robotics: Mastering Quaternion Kinematics with Python - Chapter6(原创系列教程)

Unleashing Robotics: Mastering Quaternion Kinematics with Python - Chapter6(原创系列教程)(最关键一章)
本系列教程禁止转载,主要是为了有不同见解的同学可以方便联系我,我的邮箱 fanzexuan135@163.com

第6章 旋转的数值积分方法和角误差理论

1.Runge-Kutta数值积分方法

我们的目标是积分形如下式的非线性微分方程:

x ˙ = f ( t , x ) \dot{x} = f(t, x) x˙=f(t,x)

在有限的时间区间 Δ t \Delta t Δt内,将其转化为差分方程,即:

x ( t + Δ t ) = x ( t ) + ∫ t t + Δ t f ( τ , x ( τ ) ) d τ x(t + \Delta t) = x(t) + \int_{t}^{t+\Delta t}f(\tau, x(\tau))d\tau x(t+Δt)=x(t)+tt+Δtf(τ,x(τ))dτ

或等价地,如果假设 t n = n Δ t t_n = n\Delta t tn=nΔt x n ≡ x ( t n ) x_n \equiv x(t_n) xnx(tn),则有:

x n + 1 = x n + ∫ n Δ t ( n + 1 ) Δ t f ( τ , x ( τ ) ) d τ x_{n+1} = x_n + \int_{n\Delta t}^{(n+1)\Delta t}f(\tau, x(\tau))d\tau xn+1=xn+nΔt(n+1)Δtf(τ,x(τ))dτ

最常用的方法之一是Runge-Kutta(简称RK)方法。这些方法使用多次迭代来估计区间内的导数,然后使用该导数在步长 Δ t \Delta t Δt内进行积分。

在下面的小节中,我们将从最简单的方法到最通用的方法介绍几种RK方法,并根据最常见的名称给它们命名。

1.1 Euler方法

Euler方法假设导数 f ( ⋅ ) f(\cdot) f()在区间内是常数,因此有:

x n + 1 = x n + Δ t ⋅ f ( t n , x n ) x_{n+1} = x_n + \Delta t\cdot f(t_n, x_n) xn+1=xn+Δtf(tn,xn)

作为一个通用的RK方法,这相当于单阶段法,可以描述如下。计算初始点的导数:

k 1 = f ( t n , x n ) k_1 = f(t_n, x_n) k1=f(tn,xn)

然后用它计算终点的积分值:

x n + 1 = x n + Δ t ⋅ k 1 x_{n+1} = x_n + \Delta t\cdot k_1 xn+1=xn+Δtk1

代码示例:

def euler(f, x0, t0, dt, N):
    """Euler方法
    
    Args:
        f: 函数 f(t, x) 
        x0: 初始状态
        t0: 初始时间
        dt: 步长
        N: 迭代次数
        
    Returns:
        ts: 时间点数组
        xs: 状态数组
    """
    ts = [t0]
    xs = [x0]
    for i in range(N):
        x = xs[-1]
        t = ts[-1]
        k1 = f(t, x)
        x_new = x + dt * k1
        t_new = t + dt
        xs.append(x_new)
        ts.append(t_new)
    
    return ts, xs

1.2 中点法

中点法假设区间中点处的导数是有效的,并进行一次迭代计算该中点的 x x x值,即:

x n + 1 = x n + Δ t ⋅ f ( t n + 1 2 Δ t , x n + 1 2 Δ t ⋅ f ( t n , x n ) ) x_{n+1} = x_n + \Delta t\cdot f\left(t_n + \frac{1}{2}\Delta t, x_n + \frac{1}{2}\Delta t\cdot f(t_n, x_n)\right) xn+1=xn+Δtf(tn+21Δt,xn+21Δtf(tn,xn))

中点法可以解释为两步法。首先,用Euler方法积分到中点,使用之前定义的 k 1 k_1 k1:

k 1 = f ( t n , x n ) k_1 = f(t_n, x_n) k1=f(tn,xn)

x ( t n + 1 2 Δ t ) = x n + 1 2 Δ t ⋅ k 1 x(t_n + \frac{1}{2}\Delta t) = x_n + \frac{1}{2}\Delta t\cdot k_1 x(tn+21Δt)=xn+21Δtk1

然后用该值计算中点的导数 k 2 k_2 k2,进而得到积分结果:

k 2 = f ( t n + 1 2 Δ t , x ( t n + 1 2 Δ t ) ) k_2 = f(t_n + \frac{1}{2}\Delta t, x(t_n + \frac{1}{2}\Delta t)) k2=f(tn+21Δt,x(tn+21Δt))

x n + 1 = x n + Δ t ⋅ k 2 x_{n+1} = x_n + \Delta t\cdot k_2 xn+1=xn+Δtk2

代码示例:

def midpoint(f, x0, t0, dt, N):
    """中点法
    
    Args:
        f: 函数 f(t, x)
        x0: 初始状态
        t0: 初始时间        
        dt: 步长
        N: 迭代次数
        
    Returns:
        ts: 时间点数组 
        xs: 状态数组
    """
    ts = [t0]
    xs = [x0]
    for i in range(N):
        x = xs[-1]
        t = ts[-1]
        k1 = f(t, x)
        x_mid = x + dt/2 * k1
        t_mid = t + dt/2
        k2 = f(t_mid, x_mid)
        x_new = x + dt * k2
        t_new = t + dt
        xs.append(x_new)
        ts.append(t_new)

    return ts, xs

1.3 RK4方法

这通常被简称为Runge-Kutta方法。它在区间的起点、中点和终点处计算 f ( ) f() f()的值。它使用四个阶段或迭代来计算积分,获得四个导数 k 1 … k 4 k_1 \dots k_4 k1k4,这些导数是按顺序计算的。然后对这些导数进行加权平均,以获得区间内导数的4阶估计值。

RK4方法用一个小算法比用一步公式更好地描述。RK4积分步骤为:

x n + 1 = x n + Δ t 6 ( k 1 + 2 k 2 + 2 k 3 + k 4 ) x_{n+1} = x_n + \frac{\Delta t}{6}(k_1 + 2k_2 + 2k_3 + k_4) xn+1=xn+6Δt(k1+2k2+2k3+k4)

也就是说,增量是通过假设斜率为 k 1 , k 2 , k 3 , k 4 k_1, k_2, k_3, k_4 k1,k2,k3,k4的加权平均值来计算的,其中:

k 1 = f ( t n , x n ) k_1 = f(t_n, x_n) k1=f(tn,xn)

k 2 = f ( t n + 1 2 Δ t , x n + Δ t 2 k 1 ) k_2 = f\left(t_n + \frac{1}{2}\Delta t, x_n + \frac{\Delta t}{2}k_1\right) k2=f(tn+21Δt,xn+2Δtk1)

k 3 = f ( t n + 1 2 Δ t , x n + Δ t 2 k 2 ) k_3 = f\left(t_n + \frac{1}{2}\Delta t, x_n + \frac{\Delta t}{2}k_2\right) k3=f(tn+21Δt,xn+2Δtk2)

k 4 = f ( t n + Δ t , x n + Δ t ⋅ k 3 ) k_4 = f(t_n + \Delta t, x_n + \Delta t\cdot k_3) k4=f(tn+Δt,xn+Δtk3)

不同的斜率有以下解释:

  • k 1 k_1 k1是区间开始时的斜率,使用 x n x_n xn(Euler方法);
  • k 2 k_2 k2是区间中点的斜率,使用 x n + 1 2 Δ t ⋅ k 1 x_n + \frac{1}{2}\Delta t\cdot k_1 xn+21Δtk1(中点法);
  • k 3 k_3 k3再次是中点的斜率,但现在使用 x n + 1 2 Δ t ⋅ k 2 x_n + \frac{1}{2}\Delta t\cdot k_2 xn+21Δtk2;
  • k 4 k_4 k4是区间结束时的斜率,使用 x n + Δ t ⋅ k 3 x_n + \Delta t\cdot k_3 xn+Δtk3

代码示例:

def rk4(f, x0, t0, dt, N):
    """RK4方法
    
    Args:
        f: 函数 f(t, x)
        x0: 初始状态
        t0: 初始时间
        dt: 步长
        N: 迭代次数
        
    Returns:
        ts: 时间点数组
        xs: 状态数组
    """
    ts = [t0]
    xs = [x0]
    for i in range(N):
        x = xs[-1]
        t = ts[-1]
        k1 = f(t, x)
        k2 = f(t + dt/2, x + dt/2*k1)
        k3 = f(t + dt/2, x + dt/2*k2)
        k4 = f(t + dt, x + dt*k3)
        x_new = x + dt/6 * (k1 + 2*k2 + 2*k3 + k4)
        t_new = t + dt
        xs.append(x_new)
        ts.append(t_new)

    return ts, xs

1.4 通用Runge-Kutta方法

可以设计出更精细的RK方法。它们的目标是要么减少误差,要么提高稳定性。它们采用通用形式:

x n + 1 = x n + Δ t ∑ i = 1 s b i k i x_{n+1} = x_n + \Delta t\sum_{i=1}^{s}b_i k_i xn+1=xn+Δti=1sbiki

其中:

k i = f ( t n + Δ t ⋅ c i , x n + Δ t ∑ j = 1 s a i j k j ) k_i = f\left(t_n + \Delta t\cdot c_i, x_n + \Delta t\sum_{j=1}^{s}a_{ij}k_j\right) ki=f(tn+Δtci,xn+Δtj=1saijkj)

也就是说,迭代次数(方法的阶数)为 s s s,平均权重由 b i b_i bi定义,评估时间点由 c i c_i ci定义,斜率 k i k_i ki使用值 a i j a_{ij} aij确定。根据 a i j a_{ij} aij项的结构,可以有显式或隐式的RK方法。

  • 在显式方法中,所有 k i k_i ki都是按顺序计算的,即只使用之前计算的值。这意味着矩阵 [ a i j ] [a_{ij}] [aij]是下三角且对角线元素为零(即对于 j ≥ i j \geq i ji a i j = 0 a_{ij} = 0 aij=0)。Euler、中点和RK4方法都是显式的。

  • 隐式方法具有完整的 [ a i j ] [a_{ij}] [aij]矩阵,需要求解线性方程组才能确定所有 k i k_i ki。因此计算成本更高,但与显式方法相比,它们能够提高精度和稳定性。

2.闭式积分方法

在很多情况下,可以得到积分步骤的闭式表达式。现在我们考虑一阶线性微分方程的情况:

x ˙ ( t ) = A ⋅ x ( t ) \dot{x}(t) = A\cdot x(t) x˙(t)=Ax(t)

也就是说,关系是线性的,在区间内是常数。在这种情况下,在区间 [ t n , t n + Δ t ] [t_n, t_n + \Delta t] [tn,tn+Δt]上积分得到:

x n + 1 = e A ⋅ Δ t x n = Φ x n x_{n+1} = e^{A\cdot \Delta t}x_n = \Phi x_n xn+1=eAΔtxn=Φxn

其中 Φ \Phi Φ称为转移矩阵。该转移矩阵的Taylor展开为:

Φ = e A ⋅ Δ t = I + A Δ t + 1 2 A 2 Δ t 2 + 1 3 ! A 3 Δ t 3 + ⋯ = ∑ k = 0 ∞ 1 k ! A k Δ t k \Phi = e^{A\cdot \Delta t} = I + A\Delta t + \frac{1}{2}A^2 \Delta t^2 + \frac{1}{3!}A^3 \Delta t^3 + \cdots = \sum_{k=0}^{\infty}\frac{1}{k!}A^k \Delta t^k Φ=eAΔt=I+AΔt+21A2Δt2+3!1A3Δt3+=k=0k!1AkΔtk

当为已知 A A A的实例编写此级数时,有时可以在结果中识别已知级数。这允许以闭式形式写出所得积分。下面给出几个示例。

2.1 角误差的积分

例如,考虑没有偏差和噪声的角误差动力学:

δ θ ˙ = − [ ω ] × δ θ \dot{\delta\theta} = -[\omega]_\times \delta\theta δθ˙=[ω]×δθ

它的转移矩阵可以写成Taylor级数:

Φ = e − [ ω ] × Δ t \Phi = e^{-[\omega]_\times \Delta t} Φ=e[ω]×Δt

= I − [ ω ] × Δ t + 1 2 [ ω ] × 2 Δ t 2 − 1 3 ! [ ω ] × 3 Δ t 3 + 1 4 ! [ ω ] × 4 Δ t 4 − ⋯ = I - [\omega]_\times \Delta t + \frac{1}{2}[\omega]_\times^2\Delta t^2 - \frac{1}{3!}[\omega]_\times^3 \Delta t^3 + \frac{1}{4!}[\omega]_\times^4 \Delta t^4 - \cdots =I[ω]×Δt+21[ω]×2Δt23!1[ω]×3Δt3+4!1[ω]×4Δt4

现在定义 ω Δ t ≡ u Δ θ \omega\Delta t \equiv u\Delta\theta ωΔtuΔθ,即旋转轴和旋转角,并应用式(75),我们可以对项进行分组,得到:

Φ = I − [ u ] × Δ θ + 1 2 [ u ] × 2 Δ θ 2 − 1 3 ! [ u ] × 3 Δ θ 3 + 1 4 ! [ u ] × 4 Δ θ 4 − ⋯ = I − [ u ] × ( Δ θ − Δ θ 3 3 ! + Δ θ 5 5 ! − ⋯   ) + [ u ] × 2 ( Δ θ 2 2 ! − Δ θ 4 4 ! + Δ θ 6 6 ! − ⋯   ) = I − [ u ] × sin ⁡ Δ θ + [ u ] × 2 ( 1 − cos ⁡ Δ θ ) \begin{aligned} \Phi &= I - [u]_\times \Delta\theta + \frac{1}{2}[u]_\times^2\Delta\theta^2 - \frac{1}{3!}[u]_\times^3 \Delta \theta^3 + \frac{1}{4!}[u]_\times^4 \Delta\theta^4 - \cdots\\ &= I - [u]_\times (\Delta\theta - \frac{\Delta\theta^3}{3!} + \frac{\Delta\theta^5}{5!} - \cdots) + [u]_\times^2 (\frac{\Delta\theta^2}{2!} - \frac{\Delta\theta^4}{4!} + \frac{\Delta\theta^6}{6!} - \cdots)\\ &= I - [u]_\times \sin\Delta\theta + [u]_\times^2(1 - \cos\Delta\theta) \end{aligned} Φ=I[u]×Δθ+21[u]×2Δθ23!1[u]×3Δθ3+4!1[u]×4Δθ4=I[u]×(Δθ3!Δθ3+5!Δθ5)+[u]×2(2!Δθ24!Δθ4+6!Δθ6)=I[u]×sinΔθ+[u]×2(1cosΔθ)

这是一个闭式解。

该解对应于一个旋转矩阵 Φ = R { − u Δ θ } = R { ω Δ t } ⊤ \Phi = R\{-u\Delta\theta\}=R\{\omega\Delta t\}^\top Φ=R{uΔθ}=R{ωΔt},根据Rodrigues旋转公式(77),可以通过直接检查式(346)并回忆式(69)来获得这一结果。因此,让我们将此作为最终闭式结果:

Φ = R { ω Δ t } ⊤ \Phi = R\{\omega\Delta t\}^\top Φ=R{ωΔt}

2.2 简化IMU示例

考虑由以下误差状态动力学控制的简化IMU驱动系统:

δ p ˙ = δ v δ v ˙ = − R [ a ] × δ θ δ θ ˙ = − [ ω ] × δ θ \begin{aligned} \dot{\delta p} &= \delta v\\ \dot{\delta v} &= -R[a]_\times \delta\theta\\ \dot{\delta\theta} &= -[\omega]_\times \delta\theta \end{aligned} δp˙δv˙δθ˙=δv=R[a]×δθ=[ω]×δθ

其中 ( a , ω ) (a, \omega) (a,ω)是IMU读数,我们省略了重力和传感器偏差。该系统由状态向量和动态矩阵定义:

x = [ δ p δ v δ θ ] , A = [ 0 P v 0 0 0 V θ 0 0 Θ θ ] x = \begin{bmatrix} \delta p\\ \delta v\\ \delta\theta \end{bmatrix},\quad A = \begin{bmatrix} 0 & P_v & 0\\ 0 & 0 & V_\theta\\ 0 & 0 & \Theta_\theta \end{bmatrix} x= δpδvδθ ,A= 000Pv000VθΘθ

其中:

P v = I V θ = − R [ a ] × Θ θ = − [ ω ] × \begin{aligned} P_v &= I\\ V_\theta &= -R[a]_\times\\ \Theta_\theta &= -[\omega]_\times \end{aligned} PvVθΘθ=I=R[a]×=[ω]×

对采样周期 Δ t \Delta t Δt的积分为 x n + 1 = e ( A Δ t ) ⋅ x n = Φ ⋅ x n x_{n+1} = e^{(A\Delta t)}\cdot x_n = \Phi\cdot x_n xn+1=e(AΔt)xn=Φxn。转移矩阵 Φ \Phi Φ可以用Taylor展开(344)来表示,以 A Δ t A\Delta t AΔt的递增幂次表示。我们可以写出 A A A的几个幂次来说明它们的一般形式:

A = [ 0 P v 0 0 0 V θ 0 0 Θ θ ] , A 2 = [ 0 0 P v V θ 0 0 V θ Θ θ 0 0 Θ θ 2 ] A 3 = [ 0 0 P v V θ Θ θ 0 0 V θ Θ θ 2 0 0 Θ θ 3 ] , A 4 = [ 0 0 P v V θ Θ θ 2 0 0 V θ Θ θ 3 0 0 Θ θ 4 ] \begin{aligned} A &= \begin{bmatrix} 0 & P_v & 0\\ 0 & 0 & V_\theta\\ 0 & 0 & \Theta_\theta \end{bmatrix}, \quad A^2 = \begin{bmatrix} 0 & 0 & P_v V_\theta\\ 0 & 0 & V_\theta \Theta_\theta\\ 0 & 0 & \Theta_\theta^2 \end{bmatrix}\\ A^3 &= \begin{bmatrix} 0 & 0 & P_v V_\theta \Theta_\theta\\ 0 & 0 & V_\theta \Theta_\theta^2\\ 0 & 0 & \Theta_\theta^3 \end{bmatrix}, \quad A^4 = \begin{bmatrix} 0 & 0 & P_v V_\theta \Theta_\theta^2\\ 0 & 0 & V_\theta \Theta_\theta^3\\ 0 & 0 & \Theta_\theta^4 \end{bmatrix} \end{aligned} AA3= 000Pv000VθΘθ ,A2= 000000PvVθVθΘθΘθ2 = 000000PvVθΘθVθΘθ2Θθ3 ,A4= 000000PvVθΘθ2VθΘθ3Θθ4

从中我们可以观察到,对于 k > 1 k > 1 k>1有:

A k > 1 = [ 0 0 P v V θ Θ θ k − 2 0 0 V θ Θ θ k − 1 0 0 Θ θ k ] A^{k>1} = \begin{bmatrix} 0 & 0 & P_v V_\theta \Theta_\theta^{k-2}\\ 0 & 0 & V_\theta \Theta_\theta^{k-1}\\ 0 & 0 & \Theta_\theta^k \end{bmatrix} Ak>1= 000000PvVθΘθk2VθΘθk1Θθk

我们可以观察到 A A A递增幂次中的项具有固定部分和 Θ θ \Theta_\theta Θθ的递增幂次。这些幂次可能导致闭式解,就像前一节中那样。

让我们将矩阵 Φ \Phi Φ划分如下:

Φ = [ I Φ p v Φ p θ 0 I Φ v θ 0 0 Φ θ θ ] \Phi = \begin{bmatrix} I & \Phi_{pv} & \Phi_{p\theta}\\ 0 & I & \Phi_{v\theta}\\ 0 & 0 & \Phi_{\theta\theta} \end{bmatrix} Φ= I00ΦpvI0ΦΦvθΦθθ

让我们逐步探索 Φ \Phi Φ的所有非零块。

平凡的对角线项 从对角线上的两个上方项开始,它们如图所示是单位矩阵。

旋转对角线项 接下来是旋转对角线项 Φ θ θ \Phi_{\theta\theta} Φθθ,它将新的角度误差与旧的角度误差相关联。为该项写出完整的Taylor级数导致:

Φ θ θ = ∑ k = 0 ∞ 1 k ! Θ θ k Δ t k = ∑ k = 0 ∞ 1 k ! [ − ω ] × k Δ t k = R { ω Δ t } ⊤ \begin{aligned} \Phi_{\theta\theta} &= \sum_{k=0}^{\infty}\frac{1}{k!}\Theta_\theta^k \Delta t^k = \sum_{k=0}^{\infty}\frac{1}{k!}[-\omega]_\times^k \Delta t^k\\ &= R\{\omega\Delta t\}^\top \end{aligned} Φθθ=k=0k!1ΘθkΔtk=k=0k!1[ω]×kΔtk=R{ωΔt}

正如我们在上一节中看到的,这对应于我们熟知的旋转矩阵。

位置对速度项 最简单的非对角线项是 Φ p v \Phi_{pv} Φpv,它是:

Φ p v = P v Δ t = I Δ t \Phi_{pv} = P_v \Delta t = I\Delta t Φpv=PvΔt=IΔt

速度对角度项 现在让我们转到 Φ v θ \Phi_{v\theta} Φvθ项,通过写出其级数:

Φ v θ = V θ Δ t + 1 2 V θ Θ θ Δ t 2 + 1 3 ! V θ Θ θ 2 Δ t 3 + ⋯ = Δ t V θ ( I + 1 2 Θ θ Δ t + 1 3 ! Θ θ 2 Δ t 2 + ⋯   ) \begin{aligned} \Phi_{v\theta} &= V_\theta \Delta t + \frac{1}{2}V_\theta \Theta_\theta \Delta t^2 + \frac{1}{3!}V_\theta \Theta_\theta^2 \Delta t^3 + \cdots\\ &= \Delta t V_\theta (I + \frac{1}{2}\Theta_\theta \Delta t + \frac{1}{3!}\Theta_\theta^2 \Delta t^2 + \cdots) \end{aligned} Φvθ=VθΔt+21VθΘθΔt2+3!1VθΘθ2Δt3+=ΔtVθ(I+21ΘθΔt+3!1Θθ2Δt2+)

这可以化简为:

Φ v θ = Δ t V θ ( I + ∑ k ≥ 1 ( Θ θ Δ t ) k ( k + 1 ) ! ) \Phi_{v\theta} = \Delta t V_\theta \left(I + \sum_{k\geq 1}\frac{(\Theta_\theta \Delta t)^k}{(k+1)!}\right) Φvθ=ΔtVθ(I+k1(k+1)!(ΘθΔt)k)

此时我们有两个选择。我们可以在第一个显著项处截断级数,得到 Φ v θ = V θ Δ t \Phi_{v\theta} = V_\theta \Delta t Φvθ=VθΔt,但这不是闭式的。下一节将给出使用这种简化方法的结果。或者,让我们将 V θ V_\theta Vθ分离出来并写出:

Φ v θ = V θ Σ 1 \Phi_{v\theta} = V_\theta \Sigma_1 Φvθ=VθΣ1

其中:

Σ 1 = I Δ t + 1 2 Θ θ Δ t 2 + 1 3 ! Θ θ 2 Δ t 3 + ⋯ \Sigma_1 = I\Delta t + \frac{1}{2}\Theta_\theta \Delta t^2 + \frac{1}{3!}\Theta_\theta^2 \Delta t^3 + \cdots Σ1=IΔt+21ΘθΔt2+3!1Θθ2Δt3+

级数 Σ 1 \Sigma_1 Σ1与我们为 Φ θ θ \Phi_{\theta\theta} Φθθ写的级数(358)类似,但有两个例外:

  • Σ 1 \Sigma_1 Σ1中的 Θ θ \Theta_\theta Θθ幂次与 1 k ! \frac{1}{k!} k!1的有理系数和 Δ t \Delta t Δt的幂次不匹配。实际上,这里我们注意到下标"1"表示每个成员缺少一个 Θ θ \Theta_\theta Θθ幂次。

  • 级数开头的一些项丢失了。同样,下标"1"表示缺少这样一项。

产生了恒等式:

Θ θ = [ ω ] × 3 ∥ ω ∥ 2 = − Θ θ 3 ∥ ω ∥ 2 \Theta_\theta = \frac{[\omega]_\times^3}{\|\omega\|^2} = \frac{-\Theta_\theta^3}{\|\omega\|^2} Θθ=ω2[ω]×3=ω2Θθ3

这个表达式允许我们将级数中 Θ θ \Theta_\theta Θθ的指数增加两次,如果 ω ≠ 0 \omega \neq 0 ω=0,可以写成:

Σ 1 = I Δ t − Θ θ ∥ ω ∥ 2 ( 1 2 Θ θ 2 Δ t 2 + 1 3 ! Θ θ 3 Δ t 3 + ⋯   ) \Sigma_1 = I\Delta t - \frac{\Theta_\theta}{\|\omega\|^2}\left(\frac{1}{2}\Theta_\theta^2 \Delta t^2 + \frac{1}{3!}\Theta_\theta^3 \Delta t^3 + \cdots\right) Σ1=IΔtω2Θθ(21Θθ2Δt2+3!1Θθ3Δt3+)

否则 Σ 1 = I Δ t \Sigma_1 = I\Delta t Σ1=IΔt。新级数中的所有幂次都与正确的系数匹配。当然,如前所述,有些项丢失了。第二个问题可以通过添加和减去缺失的项,并将不完整的级数替换为其闭式来解决。我们得到:

Σ 1 = I Δ t − Θ θ ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − I − Θ θ Δ t ) \Sigma_1 = I\Delta t - \frac{\Theta_\theta}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - I - \Theta_\theta \Delta t\right) Σ1=IΔtω2Θθ(R{ωΔt}IΘθΔt)

这是一个闭式解,如果 ω ≠ 0 \omega \neq 0 ω=0则有效。因此我们最终可以写出:

Φ v θ = { − R [ a ] × Δ t ω → 0 − R [ a ] × ( I Δ t + [ ω ] × ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − I + [ ω ] × Δ t ) ) ω ≠ 0 \Phi_{v\theta} = \begin{cases} -R[a]_\times \Delta t & \omega \to 0\\ -R[a]_\times \left(I\Delta t + \frac{[\omega]_\times}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - I + [\omega]_\times \Delta t\right)\right) & \omega \neq 0 \end{cases} Φvθ={R[a]×ΔtR[a]×(IΔt+ω2[ω]×(R{ωΔt}I+[ω]×Δt))ω0ω=0

位置对角度项 最后让我们研究 Φ p θ \Phi_{p\theta} Φ项。它的Taylor级数为:

Φ p θ = 1 2 P v V θ Δ t 2 + 1 3 ! P v V θ Θ θ Δ t 3 + 1 4 ! P v V θ Θ θ 2 Δ t 4 + ⋯ \Phi_{p\theta} = \frac{1}{2}P_v V_\theta \Delta t^2 + \frac{1}{3!}P_v V_\theta \Theta_\theta \Delta t^3 + \frac{1}{4!}P_v V_\theta \Theta_\theta^2 \Delta t^4 + \cdots Φ=21PvVθΔt2+3!1PvVθΘθΔt3+4!1PvVθΘθ2Δt4+

我们将常数项分离出来得到:

Φ p θ = P v V θ Σ 2 \Phi_{p\theta} = P_v V_\theta \Sigma_2 Φ=PvVθΣ2

其中:

Σ 2 = 1 2 I Δ t 2 + 1 3 ! Θ θ Δ t 3 + 1 4 ! Θ θ 2 Δ t 4 + ⋯ \Sigma_2 = \frac{1}{2}I\Delta t^2 + \frac{1}{3!}\Theta_\theta \Delta t^3 + \frac{1}{4!}\Theta_\theta^2 \Delta t^4 + \cdots Σ2=21IΔt2+3!1ΘθΔt3+4!1Θθ2Δt4+

其中我们注意到下标"2"在 Σ 2 \Sigma_2 Σ2中有以下解释:

  • 在级数的每一项中都缺少两个 Θ θ \Theta_\theta Θθ幂次,
  • 级数的前两项丢失。

再次使用式(366)来增加 Θ θ \Theta_\theta Θθ的指数,得到:

Σ 2 = 1 2 I Δ t 2 − 1 ∥ ω ∥ 2 ( 1 3 ! Θ θ 3 Δ t 3 + 1 4 ! Θ θ 4 Δ t 4 + ⋯   ) \Sigma_2 = \frac{1}{2}I\Delta t^2 - \frac{1}{\|\omega\|^2}\left(\frac{1}{3!}\Theta_\theta^3 \Delta t^3 + \frac{1}{4!}\Theta_\theta^4 \Delta t^4 + \cdots\right) Σ2=21IΔt2ω21(3!1Θθ3Δt3+4!1Θθ4Δt4+)

我们将不完整的级数替换为其闭式,得到:

Σ 2 = 1 2 I Δ t 2 − 1 ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − I − Θ θ Δ t − 1 2 Θ θ 2 Δ t 2 ) \Sigma_2 = \frac{1}{2}I\Delta t^2 - \frac{1}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - I - \Theta_\theta \Delta t - \frac{1}{2}\Theta_\theta^2 \Delta t^2\right) Σ2=21IΔt2ω21(R{ωΔt}IΘθΔt21Θθ2Δt2)

这导致最终结果:

Φ p θ = { − R [ a ] × Δ t 2 2 ω → 0 − R [ a ] × ( 1 2 I Δ t 2 − 1 ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − ∑ k = 0 2 ( − [ ω ] × Δ t ) k k ! ) ) ω ≠ 0 \Phi_{p\theta} = \begin{cases} -\frac{R[a]_\times \Delta t^2}{2} & \omega \to 0\\ -R[a]_\times \left(\frac{1}{2}I\Delta t^2 - \frac{1}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - \sum_{k=0}^{2}\frac{(-[\omega]_\times \Delta t)^k}{k!}\right)\right) & \omega \neq 0 \end{cases} Φ= 2R[a]×Δt2R[a]×(21IΔt2ω21(R{ωΔt}k=02k!([ω]×Δt)k))ω0ω=0

2.3 完整IMU示例

为了给出推广前一示例中所述方法的手段,我们需要从更近的距离检查完整IMU情况。

考虑完整IMU系统,它可以写成:

δ x ˙ = A δ x + B w \dot{\delta x} = A\delta x + Bw δx˙=Aδx+Bw

其离散时间积分需要转移矩阵:

Φ = ∑ k = 0 ∞ 1 k ! A k Δ t k = I + A Δ t + 1 2 A 2 Δ t 2 + ⋯ \Phi = \sum_{k=0}^{\infty}\frac{1}{k!}A^k \Delta t^k = I + A\Delta t + \frac{1}{2}A^2 \Delta t^2 + \cdots Φ=k=0k!1AkΔtk=I+AΔt+21A2Δt2+

我们想要计算它。动态矩阵 A A A是块稀疏的,通过检查原始方程可以很容易地确定它的块:

A = [ 0 P v 0 0 0 0 0 0 V θ V a 0 V g 0 0 Θ θ 0 Θ ω 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] A = \begin{bmatrix} 0 & P_v & 0 & 0 & 0 & 0\\ 0 & 0 & V_\theta & V_a & 0 & V_g\\ 0 & 0 & \Theta_\theta & 0 & \Theta_\omega & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} A= 000000Pv000000VθΘθ0000Va000000Θω0000Vg0000

和之前一样,让我们写出 A A A的几个幂次:

A 2 = [ 0 0 P v V θ P v V a 0 P v V g 0 0 V θ Θ θ 0 V θ Θ ω 0 0 0 Θ θ 2 0 Θ θ Θ ω 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] A 3 = [ 0 0 P v V θ Θ θ 0 P v V θ Θ ω 0 0 0 V θ Θ θ 2 0 V θ Θ θ Θ ω 0 0 0 Θ θ 3 0 Θ θ 2 Θ ω 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] A 4 = [ 0 0 P v V θ Θ θ 2 0 P v V θ Θ θ Θ ω 0 0 0 V θ Θ θ 3 0 V θ Θ θ 2 Θ ω 0 0 0 Θ θ 4 0 Θ θ 3 Θ ω 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] \begin{aligned} A^2 &= \begin{bmatrix} 0 & 0 & P_v V_\theta & P_v V_a & 0 & P_v V_g\\ 0 & 0 & V_\theta \Theta_\theta & 0 & V_\theta \Theta_\omega & 0\\ 0 & 0 & \Theta_\theta^2 & 0 & \Theta_\theta \Theta_\omega & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix}\\ A^3 &= \begin{bmatrix} 0 & 0 & P_v V_\theta \Theta_\theta & 0 & P_v V_\theta \Theta_\omega & 0\\ 0 & 0 & V_\theta \Theta_\theta^2 & 0 & V_\theta \Theta_\theta \Theta_\omega & 0\\ 0 & 0 & \Theta_\theta^3 & 0 & \Theta_\theta^2 \Theta_\omega & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix}\\ A^4 &= \begin{bmatrix} 0 & 0 & P_v V_\theta \Theta_\theta^2 & 0 & P_v V_\theta \Theta_\theta \Theta_\omega & 0\\ 0 & 0 & V_\theta \Theta_\theta^3 & 0 & V_\theta \Theta_\theta^2 \Theta_\omega & 0\\ 0 & 0 & \Theta_\theta^4 & 0 & \Theta_\theta^3 \Theta_\omega & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 \end{bmatrix} \end{aligned} A2A3A4= 000000000000PvVθVθΘθΘθ2000PvVa000000VθΘωΘθΘω000PvVg00000 = 000000000000PvVθΘθVθΘθ2Θθ3000000000PvVθΘωVθΘθΘωΘθ2Θω000000000 = 000000000000PvVθΘθ2VθΘθ3Θθ4000000000PvVθΘθΘωVθΘθ2ΘωΘθ3Θω000000000

基本上,我们观察到以下几点:

  • A A A对角线上的唯一项,即旋转项 Θ θ \Theta_\theta Θθ,在 A k A^k Ak序列中向右和向上传播。所有不受这种传播影响的项都消失了。这种传播在以下三个方面影响 { A k } \{A^k\} {Ak}序列的结构:

  • 从第3次幂开始, A A A幂次的稀疏性就稳定下来了。也就是说,对于高于3的 A A A幂次,不再出现或消失非零块。

  • 左上角的 3 × 3 3\times 3 3×3块,对应于前一示例中的简化IMU模型,与该示例相比没有变化。因此,之前为它开发的闭式解仍然成立。- 与陀螺仪偏差误差相关的项(第五列的那些)引入了 Θ θ \Theta_\theta Θθ幂次的类似级数,可以用我们在简化示例中使用的相同技术来求解。

此时,我们有兴趣找到构造转移矩阵 Φ \Phi Φ的闭式元素的通用方法。让我们回顾一下关于级数 Σ 1 \Sigma_1 Σ1 Σ 2 \Sigma_2 Σ2的评论:

  • 下标与每个级数成员中缺少的 Θ θ \Theta_\theta Θθ幂次一致。
  • 下标与级数开头丢失的项数一致。

考虑到这些性质,让我们引入级数 Σ n ( X , y ) \Sigma_n(X, y) Σn(X,y),定义为:

Σ n ( X , y ) ≡ ∑ k = n ∞ 1 k ! X k − n y k = ∑ k = 0 ∞ 1 ( k + n ) ! X k y k + n = y n ∑ k = 0 ∞ 1 ( k + n ) ! X k y k \Sigma_n(X, y) \equiv \sum_{k=n}^{\infty}\frac{1}{k!}X^{k-n}y^k = \sum_{k=0}^{\infty}\frac{1}{(k+n)!}X^k y^{k+n} = y^n \sum_{k=0}^{\infty}\frac{1}{(k+n)!}X^k y^k Σn(X,y)k=nk!1Xknyk=k=0(k+n)!1Xkyk+n=ynk=0(k+n)!1Xkyk

其中求和从第 n n n项开始,项缺少 n n n个矩阵 X X X的幂次。立即可以看出 Σ 1 \Sigma_1 Σ1 Σ 2 \Sigma_2 Σ2满足:

Σ n = Σ n ( Θ θ , Δ t ) \Sigma_n = \Sigma_n(\Theta_\theta, \Delta t) Σn=Σn(Θθ,Δt)

并且 Σ 0 = R { ω Δ t } ⊤ \Sigma_0 = R\{\omega\Delta t\}^\top Σ0=R{ωΔt}。我们现在可以将转移矩阵(377)写成这些级数的函数:

Φ = [ I P v Δ t P v V θ Σ 2 1 2 P v V a Δ t 2 P v V θ Σ 3 , θ ω 1 2 P v V g Δ t 2 0 I V θ Σ 1 V a Δ t V θ Σ 2 , θ ω V g Δ t 0 0 Σ 0 0 Σ 1 , θ ω 0 0 0 0 I 0 0 0 0 0 0 I 0 0 0 0 0 0 I ] \Phi = \begin{bmatrix} I & P_v \Delta t & P_v V_\theta \Sigma_2 & \frac{1}{2}P_v V_a \Delta t^2 & P_v V_\theta \Sigma_{3, \theta\omega} & \frac{1}{2}P_v V_g \Delta t^2\\ 0 & I & V_\theta \Sigma_1 & V_a \Delta t & V_\theta \Sigma_{2,\theta\omega} & V_g \Delta t\\ 0 & 0 & \Sigma_0 & 0 & \Sigma_{1,\theta\omega} & 0\\ 0 & 0 & 0 & I & 0 & 0\\ 0 & 0 & 0 & 0 & I & 0\\ 0 & 0 & 0 & 0 & 0 & I \end{bmatrix} Φ= I00000PvΔtI0000PvVθΣ2VθΣ1Σ000021PvVaΔt2VaΔt0I00PvVθΣ3,θωVθΣ2,θωΣ1,θω0I021PvVgΔt2VgΔt000I

我们的问题现在导出为找到 Σ n \Sigma_n Σn的通用闭式表达式的问题。让我们观察到目前为止得到的 Σ 0 … Σ 3 \Sigma_0 \dots \Sigma_3 Σ0Σ3的闭式结果:

Σ 0 = R { ω Δ t } ⊤ Σ 1 = I Δ t − Θ θ ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − I − Θ θ Δ t ) Σ 2 = 1 2 I Δ t 2 − 1 ∥ ω ∥ 2 ( R { ω Δ t } ⊤ − I − Θ θ Δ t − 1 2 Θ θ 2 Δ t 2 ) Σ 3 = 1 3 ! I Δ t 3 + Θ θ ∥ ω ∥ 4 ( R { ω Δ t } ⊤ − I − Θ θ Δ t − 1 2 Θ θ 2 Δ t 2 − 1 3 ! Θ θ 3 Δ t 3 ) \begin{aligned} \Sigma_0 &= R\{\omega\Delta t\}^\top\\ \Sigma_1 &= I\Delta t - \frac{\Theta_\theta}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - I - \Theta_\theta \Delta t\right)\\ \Sigma_2 &= \frac{1}{2}I\Delta t^2 - \frac{1}{\|\omega\|^2}\left(R\{\omega\Delta t\}^\top - I - \Theta_\theta \Delta t - \frac{1}{2}\Theta_\theta^2 \Delta t^2\right)\\ \Sigma_3 &= \frac{1}{3!}I\Delta t^3 + \frac{\Theta_\theta}{\|\omega\|^4}\left(R\{\omega\Delta t\}^\top - I - \Theta_\theta \Delta t - \frac{1}{2}\Theta_\theta^2 \Delta t^2 - \frac{1}{3!}\Theta_\theta^3 \Delta t^3\right) \end{aligned} Σ0Σ1Σ2Σ3=R{ωΔt}=IΔtω2Θθ(R{ωΔt}IΘθΔt)=21IΔt2ω21(R{ωΔt}IΘθΔt21Θθ2Δt2)=3!1IΔt3+ω4Θθ(R{ωΔt}IΘθΔt21Θθ2Δt23!1Θθ3Δt3)

通过仔细检查 Σ 0 … Σ 3 \Sigma_0 \dots \Sigma_3 Σ0Σ3的级数,我们现在可以为 Σ n \Sigma_n Σn导出通用的闭式表达式,如下所示:

Σ n = { 1 n ! I Δ t n ω → 0 R { ω Δ t } ⊤ n = 0 1 n ! I Δ t n − ( − 1 ) n + 1 2 [ ω ] × ∥ ω ∥ n + 1 ( R { ω Δ t } ⊤ − ∑ k = 0 n ( − [ ω ] × Δ t ) k k ! ) n  odd 1 n ! I Δ t n + ( − 1 ) n 2 ∥ ω ∥ n ( R { ω Δ t } ⊤ − ∑ k = 0 n ( − [ ω ] × Δ t ) k k ! ) n  even \Sigma_n = \begin{cases} \frac{1}{n!}I\Delta t^n & \omega \to 0\\ R\{\omega\Delta t\}^\top & n = 0\\ \frac{1}{n!}I\Delta t^n - \frac{(-1)^\frac{n+1}{2}[\omega]_\times}{\|\omega\|^{n+1}}\left(R\{\omega\Delta t\}^\top - \sum_{k=0}^{n}\frac{(-[\omega]_\times \Delta t)^k}{k!}\right) & n \text{ odd}\\ \frac{1}{n!}I\Delta t^n + \frac{(-1)^\frac{n}{2}}{\|\omega\|^n}\left(R\{\omega\Delta t\}^\top - \sum_{k=0}^{n}\frac{(-[\omega]_\times \Delta t)^k}{k!}\right) & n \text{ even} \end{cases} Σn= n!1IΔtnR{ωΔt}n!1IΔtnωn+1(1)2n+1[ω]×(R{ωΔt}k=0nk!([ω]×Δt)k)n!1IΔtn+ωn(1)2n(R{ωΔt}k=0nk!([ω]×Δt)k)ω0n=0n oddn even

Φ \Phi Φ的最终结果可以通过将 Σ n , n ∈ { 0 , 1 , 2 , 3 } \Sigma_n, n \in \{0,1,2,3\} Σn,n{0,1,2,3}的适当值代入(381)中的相应位置立即得到。

值得注意的是,现在出现在这些新表达式中的级数具有有限个项,因此可以有效计算。也就是说,只要 n < ∞ n < \infty n<, Σ n \Sigma_n Σn的表达式就是闭式的,而这在实际中总是成立的。对于当前示例,我们有 n ≤ 3 n \leq 3 n3

简单来说,在第3节中的完整IMU示例主要是为了说明如何在实际的惯性导航系统中应用前面所推导的旋转理论和积分方法。

在惯性导航中,我们通常使用IMU(惯性测量单元)来估计物体的姿态、速度和位置。一个典型的IMU包含三轴陀螺仪和三轴加速度计,分别测量物体的角速度和加速度。然而,由于传感器存在偏差和噪声,直接对测量值进行积分会导致估计误差快速累积。因此,我们需要设计一个状态估计器(如卡尔曼滤波器)来融合IMU数据,并估计和校正这些误差。

我们首先定义了IMU系统的误差状态向量:

δ x = [ δ p ⊤ , δ v ⊤ , δ θ ⊤ , δ a b ⊤ , δ ω b ⊤ , δ g ⊤ ] ⊤ \delta x = [\delta p^\top, \delta v^\top, \delta \theta^\top, \delta a_b^\top, \delta \omega_b^\top, \delta g^\top]^\top δx=[δp,δv,δθ,δab,δωb,δg]

其中 δ p , δ v , δ θ \delta p, \delta v, \delta \theta δp,δv,δθ分别是位置、速度和姿态的误差, δ a b , δ ω b \delta a_b, \delta \omega_b δab,δωb是加速度计和陀螺仪的偏差误差, δ g \delta g δg是重力向量的误差。

然后,我们给出了这些误差状态的微分方程:

δ p ˙ = δ v δ v ˙ = − R [ a ] × δ θ − R δ a b + δ g − R a n δ θ ˙ = − [ ω ] × δ θ − δ ω b − ω n δ a ˙ b = a w δ ω ˙ b = ω w δ g ˙ = 0 \begin{aligned} \delta\dot{p} &= \delta v\\ \delta\dot{v} &= -R[a]_\times \delta\theta - R\delta a_b + \delta g - Ra_n\\ \delta\dot{\theta} &= -[\omega]_\times \delta\theta - \delta\omega_b - \omega_n\\ \delta\dot{a}_b &= a_w\\ \delta\dot{\omega}_b &= \omega_w\\ \delta\dot{g} &= 0 \end{aligned} δp˙δv˙δθ˙δa˙bδω˙bδg˙=δv=R[a]×δθRδab+δgRan=[ω]×δθδωbωn=aw=ωw=0

这里的 a n , ω n , a w , ω w a_n, \omega_n, a_w, \omega_w an,ωn,aw,ωw分别是加速度计噪声、陀螺仪噪声、加速度计偏差噪声和陀螺仪偏差噪声。

为了在离散时间下实现状态估计器,我们需要对这些微分方程进行积分。这就是这节的主要内容。通过使用前面推导的指数映射和齐次积分方法,我们可以得到误差状态转移矩阵 Φ \Phi Φ的闭式解,从而实现精确而高效的状态传播。

下面是一个简化版的Python实现,演示如何使用转移矩阵进行状态传播:

import numpy as np

def imu_predict(delta_x_prev, P_prev, a_m, omega_m, dt, Q):
    """IMU误差状态预测。

    Args:
        delta_x_prev: 上一时刻的误差状态估计值, shape为(15,)。
        P_prev: 上一时刻的误差状态协方差矩阵, shape为(15, 15)。
        a_m: 当前时刻的加速度计测量值, shape为(3,)。
        omega_m: 当前时刻的陀螺仪测量值, shape为(3,)。
        dt: 采样时间。
        Q: 过程噪声协方差矩阵, shape为(12, 12)。

    Returns:
        delta_x_pred: 当前时刻的误差状态预测值, shape为(15,)。
        P_pred: 当前时刻的误差状态协方差矩阵, shape为(15, 15)。
    """
    # 提取状态变量
    delta_p, delta_v, delta_theta, delta_a_b, delta_omega_b, delta_g = np.split(delta_x_prev, [3, 6, 9, 12, 15])
    
    # 计算状态转移矩阵
    F = np.eye(15)
    F[0:3, 3:6] = np.eye(3) * dt
    F[3:6, 6:9] = -skew(a_m - delta_a_b) * dt
    F[3:6, 9:12] = -np.eye(3) * dt
    F[3:6, 12:15] = np.eye(3) * dt
    F[6:9, 6:9] = exp_so3(-omega_m * dt).T
    F[6:9, 12:15] = -np.eye(3) * dt
    
    # 预测误差状态和协方差
    delta_x_pred = F @ delta_x_prev
    P_pred = F @ P_prev @ F.T + Q
    
    return delta_x_pred, P_pred

在这个实现中,我们首先从误差状态向量中提取出各个分量。然后,我们根据这节中给出的公式计算状态转移矩阵 Φ \Phi Φ(这里记为F)。需要注意的是,我们使用了前面定义的exp_so3函数来计算旋转矩阵的指数映射。最后,我们使用转移矩阵来预测新的误差状态和协方差矩阵。

这个函数可以作为一个基本的IMU预测步骤,与卡尔曼滤波器的更新步骤相结合,就可以实现一个完整的惯性导航系统。当然,实际系统中还需要考虑更多的因素,如初始对准、坐标系转换、零偏补偿等,这里不再赘述。

总之,第3节的主要目的是展示如何将抽象的旋转理论应用到实际的工程问题中。通过对IMU误差状态进行建模和积分,我们可以设计出鲁棒和高效的状态估计算法,这是现代惯性导航系统的基础。

机器人IMU应用实例:

让我们考虑一个常见的机器人应用 - 使用IMU进行航位推算。假设我们有一个小型移动机器人,配备了一个六轴IMU(3个加速度计和3个陀螺仪)。我们的目标是使用IMU数据估计机器人的位置、速度和姿态。

我们可以设置如下误差状态系统:

δ p ˙ = δ v δ v ˙ = − R [ a ] × δ θ − R δ a b + δ g − R a n δ θ ˙ = − [ ω ] × δ θ − δ ω b − ω n δ a ˙ b = a w δ ω ˙ b = ω w δ g ˙ = 0 \begin{aligned} \delta\dot{p} &= \delta v\\ \delta\dot{v} &= -R[a]_\times \delta\theta - R\delta a_b + \delta g - Ra_n\\ \delta\dot{\theta} &= -[\omega]_\times \delta\theta - \delta\omega_b - \omega_n\\ \delta\dot{a}_b &= a_w\\ \delta\dot{\omega}_b &= \omega_w\\ \delta\dot{g} &= 0 \end{aligned} δp˙δv˙δθ˙δa˙bδω˙bδg˙=δv=R[a]×δθRδab+δgRan=[ω]×δθδωbωn=aw=ωw=0

其中 δ p , δ v , δ θ \delta p, \delta v, \delta \theta δp,δv,δθ分别是位置、速度和姿态误差, δ a b , δ ω b \delta a_b, \delta \omega_b δab,δωb是加速度计和陀螺仪偏差误差, δ g \delta g δg是重力误差。 a n , ω n , a w , ω w a_n, \omega_n, a_w, \omega_w an,ωn,aw,ωw分别是加速度计噪声、陀螺仪噪声、加速度计偏差噪声和陀螺仪偏差噪声。

使用前面推导的结果,我们可以计算转移矩阵 Φ \Phi Φ并进行离散化:

δ x n + 1 = Φ n δ x n + F i ⋅ i \delta x_{n+1} = \Phi_n \delta x_n + F_i \cdot i δxn+1=Φnδxn+Fii

其中 δ x = [ δ p ⊤ , δ v ⊤ , δ θ ⊤ , δ a b ⊤ , δ ω b ⊤ , δ g ⊤ ] ⊤ \delta x = [\delta p^\top, \delta v^\top, \delta \theta^\top, \delta a_b^\top, \delta \omega_b^\top, \delta g^\top]^\top δx=[δp,δv,δθ,δab,δωb,δg]是误差状态向量, i i i是过程噪声。

然后我们可以设计一个误差状态卡尔曼滤波器:

预测步骤:
δ x ^ n + 1 = Φ n δ x ^ n P n + 1 = Φ n P n Φ n ⊤ + F i Q i F i ⊤ \begin{aligned} \hat{\delta x}_{n+1} &= \Phi_n \hat{\delta x}_n\\ P_{n+1} &= \Phi_n P_n \Phi_n^\top + F_i Q_i F_i^\top \end{aligned} δx^n+1Pn+1=Φnδx^n=ΦnPnΦn+FiQiFi

更新步骤(假设有位置测量 y n y_n yn):
K n = P n H ⊤ ( H P n H ⊤ + R ) − 1 δ x ^ n = K n ( y n − h ( x ^ n ) ) P n = ( I − K n H ) P n \begin{aligned} K_n &= P_n H^\top (H P_n H^\top + R)^{-1}\\ \hat{\delta x}_n &= K_n(y_n - h(\hat{x}_n))\\ P_n &= (I - K_n H) P_n \end{aligned} Knδx^nPn=PnH(HPnH+R)1=Kn(ynh(x^n))=(IKnH)Pn

其中 H H H是观测模型, R R R是观测噪声协方差。

最后,我们使用估计的误差状态来校正名义状态:

x ^ n ← x ^ n ⊕ δ x ^ n \hat{x}_n \leftarrow \hat{x}_n \oplus \hat{\delta x}_n x^nx^nδx^n

其中 ⊕ \oplus 表示状态流形上的加法。

通过这种方式,我们可以递归地估计机器人的位置、速度和姿态,从而实现IMU的航位推算。闭式解和精确的离散化保证了估计器的精度和数值稳定性。

这只是IMU在机器人中应用的一个简单例子。实际系统通常会融合IMU与其他传感器如视觉、激光等,形成更鲁棒和准确的状态估计。但核心的状态传播部分通常与这里描述的类似。

综上,我们系统地推导了旋转矩阵和四元数的指数映射、闭式解和近似解,并讨论了它们在IMU积分和误差状态卡尔曼滤波中的应用。这些技术构成了许多现代机器人导航系统的基础。

这里我给出使用Python的代码示例,并解释角误差积分的用途和应用场景。

首先,让我们看一下角误差积分的Python实现:

import numpy as np

def exp_so3(phi):
    """李代数so3到李群SO3的指数映射。

    Args:
        phi: 角度误差向量, shape为(3,)。

    Returns:
        R: 旋转矩阵, shape为(3, 3)。
    """
    phi_norm = np.linalg.norm(phi)
    if phi_norm < 1e-8:
        return np.eye(3)
    else:
        phi_skew = np.array([[0, -phi[2], phi[1]], 
                             [phi[2], 0, -phi[0]], 
                             [-phi[1], phi[0], 0]])
        return np.eye(3) + np.sin(phi_norm)/phi_norm*phi_skew + (1-np.cos(phi_norm))/phi_norm**2*phi_skew@phi_skew

def right_jacobian_so3(phi):
    """SO3上的右雅可比矩阵。

    Args:
        phi: 角度误差向量, shape为(3,)。

    Returns:
        Jr: 右雅可比矩阵, shape为(3, 3)。
    """
    phi_norm = np.linalg.norm(phi)
    if phi_norm < 1e-8:
        return np.eye(3)
    else:
        phi_skew = np.array([[0, -phi[2], phi[1]], 
                             [phi[2], 0, -phi[0]], 
                             [-phi[1], phi[0], 0]])
        return np.eye(3) - (1-np.cos(phi_norm))/phi_norm**2*phi_skew + (phi_norm-np.sin(phi_norm))/phi_norm**3*phi_skew@phi_skew

在上面的代码中:

  • exp_so3函数实现了从so3到SO3的指数映射,即将角误差向量转换为旋转矩阵。它使用了罗德里格斯公式的闭式解。

  • right_jacobian_so3函数计算SO3流形上的右雅可比矩阵。该矩阵将局部角误差的变化映射到流形上旋转矩阵的变化。

这些函数在实现涉及3D旋转的状态估计器(如Extended Kalman Filter)时非常有用。

那么,什么时候需要用到角误差的积分呢?主要有以下几个场景:

  1. 姿态估计: 在使用IMU进行姿态估计时,我们通常会积分陀螺仪数据得到姿态的增量。然而,由于陀螺仪存在偏差和噪声,直接积分会导致估计误差快速增长。这时,我们可以在估计器中引入角误差状态,并使用如上所示的闭式解进行更新,以得到更准确和稳定的姿态估计。

  2. 视觉里程计: 在视觉里程计中,相机姿态通常用旋转矩阵或四元数表示。当我们优化姿态时,使用李代数so3作为局部参数化,可以避免过度参数化和奇异性问题。这时,需要在so3和SO3之间进行映射,也就是上面的指数映射和对数映射。

  3. 机器人运动学: 对于许多关节式机器人,其关节运动通常用旋转来描述。当我们进行运动学计算或控制时,需要在关节角速度(在so3中)和关节姿态(在SO3中)之间进行转换,这也需要用到指数映射。

  4. 轨迹优化: 在一些轨迹优化问题中,机器人的姿态也是需要优化的变量。为了保证优化过程中姿态的有效性,通常使用李代数参数化姿态,并在每次迭代后将优化结果投影回SO3。这个投影过程就是通过指数映射实现的。
    好的,让我详细说明一下为什么引入角误差状态,并使用闭式解进行更新可以得到更准确和稳定的姿态估计。

Q&A

角误差理论到底是什么

我们知道IMU的陀螺仪测量的是角速度,要得到姿态需要对角速度进行积分。最简单的方法是使用欧拉积分:

R t + Δ t = R t exp ⁡ ( ω t Δ t ) R_{t+\Delta t} = R_t \exp(\omega_t \Delta t) Rt+Δt=Rtexp(ωtΔt)

其中 R t R_t Rt是时刻 t t t的旋转矩阵, ω t \omega_t ωt是陀螺仪测量的角速度, Δ t \Delta t Δt是采样时间。

然而,这种直接积分的方法有以下问题:

  1. 陀螺仪存在偏差和噪声,直接积分会导致误差快速累积。
  2. 欧拉积分本身是一阶近似,也会引入数值误差。
  3. 旋转矩阵必须满足正交性约束,但数值积分无法保证积分结果满足此约束。

为了解决这些问题,我们引入角误差状态。假设我们有一个姿态的估计值 R ^ t \hat{R}_t R^t,它与真实值 R t R_t Rt之间存在一个小的误差 δ R t \delta R_t δRt:

R t = δ R t R ^ t R_t = \delta R_t \hat{R}_t Rt=δRtR^t

我们将 δ R t \delta R_t δRt参数化为一个李代数向量 ϕ t \phi_t ϕt:

δ R t = exp ⁡ ( ϕ t ) \delta R_t = \exp(\phi_t) δRt=exp(ϕt)

这里的 exp ⁡ \exp exp是指从so3到SO3的指数映射。

现在,我们的目标是估计误差状态 ϕ t \phi_t ϕt,而不是直接估计 R t R_t Rt。假设我们已经有了一个估计器(如EKF),它给出了 ϕ t \phi_t ϕt的估计值 ϕ ^ t \hat{\phi}_t ϕ^t和协方差矩阵 P t P_t Pt

当新的陀螺仪测量值 ω t + 1 \omega_{t+1} ωt+1到来时,我们首先更新姿态的估计值:

R ^ t + 1 = R ^ t exp ⁡ ( ω t + 1 Δ t ) \hat{R}_{t+1} = \hat{R}_t \exp(\omega_{t+1} \Delta t) R^t+1=R^texp(ωt+1Δt)

然后,我们使用角误差状态的闭式解来更新 ϕ ^ t \hat{\phi}_t ϕ^t P t P_t Pt:

ϕ ^ t + 1 = exp ⁡ ( − ω t + 1 Δ t ) ϕ ^ t \hat{\phi}_{t+1} = \exp(-\omega_{t+1} \Delta t) \hat{\phi}_t ϕ^t+1=exp(ωt+1Δt)ϕ^t

P t + 1 = F t P t F t ⊤ + Q t P_{t+1} = F_t P_t F_t^\top + Q_t Pt+1=FtPtFt+Qt

其中 F t F_t Ft是状态转移矩阵,可以使用 exp ⁡ ( ω t + 1 Δ t ) \exp(\omega_{t+1} \Delta t) exp(ωt+1Δt)的右雅可比矩阵来近似:

F t ≈ I − [ ω t + 1 ] × Δ t F_t \approx I - [\omega_{t+1}]_\times \Delta t FtI[ωt+1]×Δt

Q t Q_t Qt是过程噪声协方差矩阵。

最后,我们使用更新后的 ϕ ^ t + 1 \hat{\phi}_{t+1} ϕ^t+1来修正姿态估计值:

R ^ t + 1 ← exp ⁡ ( ϕ ^ t + 1 ) R ^ t + 1 \hat{R}_{t+1} \leftarrow \exp(\hat{\phi}_{t+1}) \hat{R}_{t+1} R^t+1exp(ϕ^t+1)R^t+1

这样,我们就得到了新的姿态估计值 R ^ t + 1 \hat{R}_{t+1} R^t+1

下面是一个简单的Python实现:

import numpy as np

def attitude_estimation(R_prev, omega, dt, phi_prev, P_prev, Q):
    """使用角误差状态的姿态估计。

    Args:
        R_prev: 上一时刻的姿态估计值, shape为(3, 3)。
        omega: 当前时刻的角速度测量值, shape为(3,)。
        dt: 采样时间。
        phi_prev: 上一时刻的角误差状态估计值, shape为(3,)。
        P_prev: 上一时刻的角误差状态协方差矩阵, shape为(3, 3)。
        Q: 过程噪声协方差矩阵, shape为(3, 3)。

    Returns:
        R_curr: 当前时刻的姿态估计值, shape为(3, 3)。
        phi_curr: 当前时刻的角误差状态估计值, shape为(3,)。
        P_curr: 当前时刻的角误差状态协方差矩阵, shape为(3, 3)。
    """
    # 预测
    R_pred = R_prev @ exp_so3(omega * dt)
    phi_pred = exp_so3(-omega * dt) @ phi_prev
    
    # 更新
    F = np.eye(3) - dt * skew(omega)
    P_pred = F @ P_prev @ F.T + Q
    
    # 修正
    R_curr = exp_so3(phi_pred) @ R_pred
    phi_curr = np.zeros(3)
    P_curr = P_pred
    
    return R_curr, phi_curr, P_curr

在这个实现中,我们首先使用上一时刻的姿态估计值 R ^ t − 1 \hat{R}_{t-1} R^t1和当前的角速度测量值 ω t \omega_t ωt来预测当前时刻的姿态 R ^ t \hat{R}_t R^t。然后,我们使用角误差状态的闭式解来预测当前时刻的角误差状态 ϕ ^ t \hat{\phi}_t ϕ^t。接下来,我们计算状态转移矩阵 F F F,并用它来更新角误差状态的协方差矩阵 P t P_t Pt。最后,我们使用预测的角误差状态 ϕ ^ t \hat{\phi}_t ϕ^t来修正预测的姿态 R ^ t \hat{R}_t R^t,得到最终的姿态估计值。

这种方法之所以有效,是因为它利用了SO3流形的几何结构。通过在局部切平面(即so3)上进行估计和更新,然后再映射回SO3,我们可以保证估计结果总是一个有效的旋转矩阵,同时避免了欧拉积分的数值误差问题。此外,由于角误差状态通常很小,我们可以使用一阶近似(即指数映射的一阶泰勒展开)来简化计算,提高效率。

当然,实际的姿态估计器通常会更加复杂,需要处理更多的状态量(如速度、位置等),并融合多种传感器的测量值(如加速度计、磁力计等)。但角误差状态的使用几乎是所有这些估计器的核心组件之一。

闭式解(Closed-form solution)

闭式解(Closed-form solution)是一种可以用有限个基本操作(如算术运算、根式运算、指数、对数等)显式表示的解。与之相对的是数值解或近似解,它们通常需要使用迭代算法来逐步逼近真实的解。

在许多工程和科学问题中,我们经常需要求解微分方程、积分方程或优化问题。如果能找到闭式解,那么问题就可以一次性地得到精确的答案,而不需要进行数值计算。这不仅可以提高计算效率,还能避免数值方法引入的误差。

举几个例子:

  1. 一阶线性常微分方程 x ˙ ( t ) = a x ( t ) + b \dot{x}(t) = ax(t) + b x˙(t)=ax(t)+b的闭式解为 x ( t ) = C e a t + b a x(t) = Ce^{at} + \frac{b}{a} x(t)=Ceat+ab,其中 C C C是由初值条件确定的常数。

  2. 几何级数 S n = ∑ i = 0 n − 1 a r i S_n = \sum_{i=0}^{n-1} ar^i Sn=i=0n1ari的闭式解为 S n = a ( 1 − r n ) 1 − r S_n = \frac{a(1-r^n)}{1-r} Sn=1ra(1rn) (当 r ≠ 1 r \neq 1 r=1时)。

  3. 旋转矩阵 R R R的指数映射 R = exp ⁡ ( [ ω ] × ) R=\exp([\omega]_\times) R=exp([ω]×)有闭式解 R = I + sin ⁡ θ [ ω ] × + ( 1 − cos ⁡ θ ) [ ω ] × 2 R=I+\sin\theta[\omega]_\times+(1-\cos\theta)[\omega]_\times^2 R=I+sinθ[ω]×+(1cosθ)[ω]×2,其中 θ = ∥ ω ∥ \theta=\|\omega\| θ=ω

  4. 最小二乘问题 min ⁡ x ∥ A x − b ∥ 2 \min_x \|Ax-b\|^2 minxAxb2的闭式解为 x = ( A ⊤ A ) − 1 A ⊤ b x=(A^\top A)^{-1}A^\top b x=(AA)1Ab(当 A A A列满秩时)。

然而,并非所有问题都有闭式解。很多复杂的微分方程、积分方程和优化问题都需要使用数值方法来求解。即使存在闭式解,其形式也可能非常复杂,以至于实际计算时还是需要借助数值近似。

在状态估计领域,许多估计器(如卡尔曼滤波器)都涉及到矩阵指数 e A t e^{At} eAt的计算。如果能找到 e A t e^{At} eAt的闭式解(如B.1节所示),那么就可以显著提高估计器的计算效率和精度。相比之下,如果使用泰勒展开等数值方法来近似 e A t e^{At} eAt,就会引入截断误差和舍入误差。

因此,掌握常见问题的闭式解,并在可能的情况下将其应用到实际算法中,是提高计算效率和精度的重要手段。当然,这也需要在理论分析和工程实践之间进行权衡。有时候,即使存在闭式解,使用数值方法可能还是更加简单和鲁棒。

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值