Unleashing Robotics: Mastering Quaternion Kinematics with Python-Chapter4-2(原创系列教程)ESKF与系统误差状态运动学(2)

第4章:ESKF与IMU驱动系统的误差状态运动学2(Error-State Kalman Filter and IMU-Driven System Error Kinematics

Unleashing Robotics: Mastering Quaternion Kinematics with Python - Chapter4(原创系列教程)
第4章:ESKF与IMU驱动系统的误差状态运动学2(Error-State Kalman Filter and IMU-Driven System Error Kinematics)
本系列教程禁止转载,主要是为了有不同见解的同学可以方便联系我,我的邮箱 fanzexuan135@163.com

终于讲到ESKF了,由于本章内容太多,超过blog字数限制,我分开两部分讲解,这是第二部分,正文开始:

4.8 实践

通过上面的学习,在高级机器人应用中,你就可以使用这部分知识了,假设你有一个四足机器人,其状态由位置 p \mathbf{p} p,速度 v \mathbf{v} v,方向四元数 q \mathbf{q} q,加速度计偏差 a b \mathbf{a}_b ab 和陀螺仪偏差 ω b \boldsymbol{\omega}_b ωb 组成。机器人装备了一个IMU,提供加速度计测量值 a m \mathbf{a}_m am 和陀螺仪测量值 ω m \boldsymbol{\omega}_m ωm。此外,当一条腿着地时,我们可以使用腿部运动学计算足端位置,并将其用作位置和速度的测量值。

ESKF的预测步骤如下:

  1. 使用IMU测量值和当前状态估计值来预测标称状态:

p ← p + v Δ t + 1 2 ( R ( a m − a b ) + g ) Δ t 2 v ← v + ( R ( a m − a b ) + g ) Δ t q ← q ⊗ q { ( ω m − ω b ) Δ t } a b ← a b ω b ← ω b \begin{aligned} \mathbf{p} &\leftarrow \mathbf{p} + \mathbf{v} \Delta t + \frac{1}{2} (\mathbf{R}(\mathbf{a}_m - \mathbf{a}_b) + \mathbf{g}) \Delta t^2 \\ \mathbf{v} &\leftarrow \mathbf{v} + (\mathbf{R}(\mathbf{a}_m - \mathbf{a}_b) + \mathbf{g}) \Delta t \\ \mathbf{q} &\leftarrow \mathbf{q} \otimes \mathbf{q}\{(\boldsymbol{\omega}_m - \boldsymbol{\omega}_b) \Delta t\} \\ \mathbf{a}_b &\leftarrow \mathbf{a}_b \\ \boldsymbol{\omega}_b &\leftarrow \boldsymbol{\omega}_b \end{aligned} pvqabωbp+vΔt+21(R(amab)+g)Δt2v+(R(amab)+g)Δtqq{(ωmωb)Δt}abωb

  1. 预测误差状态的协方差矩阵:

P ← F x P F x ⊤ + F i Q i F i ⊤ \mathbf{P} \leftarrow \mathbf{F}_x \mathbf{P} \mathbf{F}_x^\top + \mathbf{F}_i \mathbf{Q}_i \mathbf{F}_i^\top PFxPFx+FiQiFi

其中 F x \mathbf{F}_x Fx F i \mathbf{F}_i Fi 是误差状态动力学的雅可比矩阵,而 Q i \mathbf{Q}_i Qi 是IMU噪声的协方差矩阵。

如果一条腿着地,我们进入ESKF的更新步骤:

  1. 使用腿部运动学计算足端位置 y \mathbf{y} y,作为位置和速度的观测值。

  2. 计算观测值的雅可比矩阵 H \mathbf{H} H:

H = H x X δ x \mathbf{H} = \mathbf{H}_x \mathbf{X}_{\delta x} H=HxXδx

其中 H x \mathbf{H}_x Hx 是观测值相对于真实状态的雅可比矩阵,而 X δ x \mathbf{X}_{\delta x} Xδx 是真实状态相对于误差状态的雅可比矩阵。

  1. 计算卡尔曼增益:

K = P H ⊤ ( H P H ⊤ + V ) − 1 \mathbf{K} = \mathbf{P}\mathbf{H}^\top(\mathbf{H}\mathbf{P}\mathbf{H}^\top + \mathbf{V})^{-1} K=PH(HPH+V)1

其中 V \mathbf{V} V 是观测噪声的协方差矩阵。

  1. 更新误差状态估计值:

δ x ^ ← K ( y − h ( x ^ t ) ) \hat{\delta \mathbf{x}} \leftarrow \mathbf{K}(\mathbf{y} - h(\hat{\mathbf{x}}_t)) δx^K(yh(x^t))

  1. 将误差状态注入标称状态:

x ← x ⊕ δ x ^ \mathbf{x} \leftarrow \mathbf{x} \oplus \hat{\delta \mathbf{x}} xxδx^

  1. 更新误差状态的协方差矩阵:

P ← ( I − K H ) P \mathbf{P} \leftarrow (\mathbf{I} - \mathbf{K}\mathbf{H})\mathbf{P} P(IKH)P

  1. 重置误差状态:

δ x ^ ← 0 \hat{\delta \mathbf{x}} \leftarrow \mathbf{0} δx^0

P ← G P G ⊤ \mathbf{P} \leftarrow \mathbf{G} \mathbf{P} \mathbf{G}^\top PGPG

其中 G \mathbf{G} G 是重置操作的雅可比矩阵,主要影响方向部分:

G = [ I 6 0 0 0 I − [ 1 2 δ θ ^ ] × 0 0 0 I 6 ] \mathbf{G} = \begin{bmatrix} \mathbf{I}_6 & \mathbf{0} & \mathbf{0} \\ \mathbf{0} & \mathbf{I} - [\frac{1}{2}\hat{\delta\boldsymbol{\theta}}]_\times & \mathbf{0} \\ \mathbf{0} & \mathbf{0} & \mathbf{I}_6 \end{bmatrix} G= I6000I[21δθ^]×000I6

这个过程不断重复,使四足机器人能够估计其状态,即使在IMU存在偏差和噪声的情况下。腿部运动学提供的测量值帮助校正了IMU积分产生的漂移,从而实现了准确的状态估计。

这个示例展示了ESKF在四足机器人状态估计中的核心思想,代码如下。

import numpy as np

# 定义一些辅助函数
def skew(v):
    return np.array([[0, -v[2], v[1]],
                     [v[2], 0, -v[0]],
                     [-v[1], v[0], 0]])

def quaternion_multiply(q1, q2):
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    return np.array([w1*w2 - x1*x2 - y1*y2 - z1*z2,
                     w1*x2 + x1*w2 + y1*z2 - z1*y2,
                     w1*y2 - x1*z2 + y1*w2 + z1*x2,
                     w1*z2 + x1*y2 - y1*x2 + z1*w2])

def quaternion_to_rotation(q):
    return np.array([[q[0]**2+q[1]**2-q[2]**2-q[3]**2, 2*(q[1]*q[2]-q[0]*q[3]), 2*(q[1]*q[3]+q[0]*q[2])],
                     [2*(q[1]*q[2]+q[0]*q[3]), q[0]**2-q[1]**2+q[2]**2-q[3]**2, 2*(q[2]*q[3]-q[0]*q[1])],
                     [2*(q[1]*q[3]-q[0]*q[2]), 2*(q[2]*q[3]+q[0]*q[1]), q[0]**2-q[1]**2-q[2]**2+q[3]**2]])

def quaternion_from_axis_angle(axis, angle):
    axis = axis / np.linalg.norm(axis)
    return np.concatenate(([np.cos(angle/2)], np.sin(angle/2) * axis))

# 设置初始状态和协方差
p = np.zeros(3)
v = np.zeros(3)
q = np.array([1, 0, 0, 0])
a_b = np.zeros(3)
w_b = np.zeros(3)
P = np.eye(15)

# 设置IMU测量值和噪声
a_m = np.array([0, 0, -9.81])  # 重力加速度
w_m = np.array([0, 0, 0])
a_n = np.random.normal(0, 0.1, 3)
w_n = np.random.normal(0, 0.01, 3)
a_w = np.random.normal(0, 0.001, 3)
w_w = np.random.normal(0, 0.0001, 3)

# 设置时间步长和重力向量
dt = 0.01
g = np.array([0, 0, -9.81])

# 预测步骤
R = quaternion_to_rotation(q)
p += v * dt + 0.5 * (R @ (a_m - a_b) + g) * dt**2
v += (R @ (a_m - a_b) + g) * dt
q = quaternion_multiply(q, quaternion_from_axis_angle(w_m - w_b, np.linalg.norm(w_m - w_b) * dt))
F_x = np.eye(15)
F_x[0:3, 3:6] = np.eye(3) * dt
F_x[3:6, 6:9] = -R @ skew(a_m - a_b) * dt
F_x[3:6, 9:12] = -R * dt
F_x[3:6, 12:15] = np.eye(3) * dt
F_x[6:9, 6:9] = R.T @ quaternion_to_rotation(quaternion_from_axis_angle(w_m - w_b, np.linalg.norm(w_m - w_b) * dt))
F_x[6:9, 12:15] = -np.eye(3) * dt
F_i = np.zeros((15, 12))
F_i[3:6, 0:3] = np.eye(3)
F_i[6:9, 3:6] = np.eye(3)
F_i[9:12, 6:9] = np.eye(3)
F_i[12:15, 9:12] = np.eye(3)
Q_i = np.zeros((12, 12))
Q_i[0:3, 0:3] = np.eye(3) * 0.1**2 * dt**2
Q_i[3:6, 3:6] = np.eye(3) * 0.01**2 * dt**2
Q_i[6:9, 6:9] = np.eye(3) * 0.001**2 * dt
Q_i[9:12, 9:12] = np.eye(3) * 0.0001**2 * dt
P = F_x @ P @ F_x.T + F_i @ Q_i @ F_i.T

print("Prediction Step:")
print("p:", p)
print("v:", v)
print("q:", q)
print("P:", P)

# 更新步骤 (假设我们得到了一个位置测量值)
y = np.array([0.1, 0.2, 0.05])  # 模拟一个位置测量值
H_x = np.zeros((3, 15))
H_x[0:3, 0:3] = np.eye(3)
X_dx = np.zeros((15, 15))
X_dx[0:6, 0:6] = np.eye(6)
X_dx[6:9, 6:9] = np.eye(3) - skew(0.5 * np.zeros(3))
X_dx[9:15, 9:15] = np.eye(6)
H = H_x @ X_dx
V = np.eye(3) * 0.01**2
K = P @ H.T @ np.linalg.inv(H @ P @ H.T + V)
delta_x = K @ (y - p)
p += delta_x[0:3]
v += delta_x[3:6]
q = quaternion_multiply(q, quaternion_from_axis_angle(delta_x[6:9], np.linalg.norm(delta_x[6:9])))
a_b += delta_x[9:12]
w_b += delta_x[12:15]
P = (np.eye(15) - K @ H) @ P
G = np.eye(15)
G[6:9, 6:9] = np.eye(3) - skew(0.5 * delta_x[6:9])
P = G @ P @ G.T

print("Update Step:")
print("p:", p)
print("v:", v) 
print("q:", q)
print("a_b:", a_b)
print("w_b:", w_b)
print("P:", P)

这个示例首先进行预测步骤,使用IMU测量值和当前状态估计来预测新的标称状态,并预测误差状态的协方差矩阵。然后模拟了一个位置测量值,并使用这个测量值来更新状态估计。在更新步骤中,计算卡尔曼增益,更新误差状态估计,将误差状态注入标称状态,更新误差状态的协方差矩阵,并重置误差状态。

[1] Bledt, Gerardo, et al. “Contact model fusion for event-based locomotion in unstructured terrains.” 2018 IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS). IEEE, 2018.

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值