卡尔曼滤波器 · 姿态解算 | 原理 / 公式推导 / 代码示例

注:本文为 “卡尔曼滤波器 · 姿态解算” 相关合辑。
略作重排,如有内容异常,请看原文。


浅谈基于卡尔曼滤波器的姿态解算(一)

争取35岁退休 已于 2024-04-24 21:44:28 修改

前言

在工程实践中,用于机器人姿态解算的算法种类较多,例如 Mahony 互补滤波算法、卡尔曼滤波算法等。此类算法均基于惯性测量单元(IMU)的输出数据实现,即利用 IMU 中的三轴加速度计与三轴角速度传感器(基于机体坐标系),通过坐标系转换关系完成姿态解算。(默认读者已掌握 IMU 的工作原理,相关内容不再赘述。)

卡尔曼滤波器

卡尔曼滤波器作为一种最优预测的数据融合算法,可有效融合加速度计与陀螺仪数据,获取理想的姿态信息。

对于线性状态系统:
X ˙ = A X + B U Y = C X \begin{aligned} \dot{\mathbf{X}}&=A\mathbf{X}+B\mathbf{U} \\ \mathbf{Y}&=C\mathbf{X} \end{aligned} X˙Y=AX+BU=CX

Step 1:利用上一时刻的后验误差协方差矩阵计算先验误差协方差矩阵
P k + 1 − = A P k A T + Q P_{k+1}^{-}=A P_{k} A^{T}+Q Pk+1=APkAT+Q

Step 2:先验估计
x ^ k + 1 − = A x ^ k + B u k \hat{x}_{k+1}^{-}=A\hat{x}_{k}+Bu_{k} x^k+1=Ax^k+Buk

Step 3:计算卡尔曼增益
K k + 1 = P k + 1 − H T H P k + 1 − H T + R K_{k+1}=\frac{P_{k+1}^{-}H^{T}}{HP_{k+1}^{-}H^{T}+R} Kk+1=HPk+1HT+RPk+1HT

Step 4:后验估计
x ^ k + 1 = x ^ k + 1 − + K k + 1 ( z k + 1 − H x ^ k + 1 − ) \hat{x}_{k+1}=\hat{x}_{k+1}^{-}+K_{k+1}(z_{k+1}-H\hat{x}_{k+1}^{-}) x^k+1=x^k+1+Kk+1(zk+1Hx^k+1)

Step 5:计算后验误差协方差矩阵
P k + 1 = ( I − K k + 1 H ) P k + 1 − P_{k+1}=(I-K_{k+1}H)P_{k+1}^{-} Pk+1=(IKk+1H)Pk+1

基于卡尔曼滤波器的姿态解算

卡尔曼滤波器使用方法

卡尔曼滤波器的应用需明确以下两点,再代入公式完成数据融合:

  • 状态转移关系(先验估计):确定状态转移方程的矩阵 A A A B B B 及系统噪声 Q Q Q
  • 状态测量值(由传感器观测获取):确定观测值 z k \mathbf{z_k} zk 与测量噪声 R R R

给定初始后验协方差矩阵 P 0 P_0 P0,经迭代计算后,卡尔曼滤波器将收敛至最优区间,实现数据融合与预测。

IMU 数据解析

  • 定义惯性系与机体系的坐标变换矩阵 R \mathbf{R} R(由惯性系至机体系),即:

R = R X ( ϕ ) R Y ( θ ) R Z ( ψ ) = [ C ψ C θ S ψ C θ − S θ C ψ S θ S ϕ − S ψ C ϕ S ψ S θ S ϕ + C ψ C ϕ C θ S ϕ C ψ S θ C ϕ + S ψ S ϕ S ψ S θ C ϕ − C ψ S ϕ C θ C ϕ ] \mathbf{R} = \mathbf{R}_X(\phi)\mathbf{R}_Y(\theta)\mathbf{R}_Z(\psi) = \begin{bmatrix} C_\psi C_\theta & S_\psi C_\theta & -S_\theta \\ C_\psi S_\theta S_\phi - S_\psi C_\phi & S_\psi S_\theta S_\phi + C_\psi C_\phi & C_\theta S_\phi \\ C_\psi S_\theta C_\phi + S_\psi S_\phi & S_\psi S_\theta C_\phi - C_\psi S_\phi & C_\theta C_\phi \end{bmatrix} R=RX(ϕ)RY(θ)RZ(ψ)= CψCθCψSθSϕSψCϕCψSθCϕ+SψSϕSψCθSψSθSϕ+CψCϕSψSθCϕCψSϕSθCθSϕCθCϕ

(注:式中 C ⋅ = cos ⁡ ( ⋅ ) C_\cdot = \cos(\cdot) C=cos() S ⋅ = sin ⁡ ( ⋅ ) S_\cdot = \sin(\cdot) S=sin()。此处“点”符号(·)用作通配符或占位符,泛指任意角度变量。)

  • 机体系下角速度向量 [ p , q , r ] T [p, q, r]^T [p,q,r]T 与惯性系下欧拉角向量 [ ϕ , θ , ψ ] T [\phi, \theta, \psi]^T [ϕ,θ,ψ]T 满足特定关系(陀螺仪可提供欧拉角的变化率——欧拉角导数)。
    [ ϕ ˙ θ ˙ ψ ˙ ] = [ 1 S ϕ T θ C ϕ T θ 0 C ϕ − S ϕ 0 S ϕ / C θ C ϕ / C θ ] [ p q r ] \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix} = \begin{bmatrix} 1 & S_\phi T_\theta & C_\phi T_\theta \\ 0 & C_\phi & -S_\phi \\ 0 & S_\phi/C_\theta & C_\phi/C_\theta \end{bmatrix} \begin{bmatrix} p \\ q \\ r \end{bmatrix} ϕ˙θ˙ψ˙ = 100SϕTθCϕSϕ/CθCϕTθSϕCϕ/Cθ pqr

  • 静止或匀速运动状态下,加速度计采样的三轴数据为重力加速度在机体系中的投影。设惯性系下重力加速度向量为 [ 0 , 0 , − g ] T [0 , 0 , -g]^T [0,0,g]T,机体系下为 [ a x , a y , a z ] T [a_x,a_y, a_z]^T [ax,ay,az]T,由坐标系转换的几何关系可得:
    ϕ = arctan ⁡ ( a y / a z ) θ = − arctan ⁡ ( a x / a y 2 + a z 2 ) \begin{aligned} \mathbf{\phi}&=\arctan(a_y/a_z) \\ \mathbf{\theta}&=-\arctan(a_x/\sqrt{a_y^2+a_z^2}) \end{aligned} ϕθ=arctan(ay/az)=arctan(ax/ay2+az2 )
    上述几何关系基于 Z→Y→X 的旋转变换顺序推导,可通过绘制坐标系旋转变换示意图辅助理解。

卡尔曼滤波器模型

先假设初始的欧拉角为
[ ϕ θ ψ ] = [ 0 0 0 ] \begin{bmatrix} \phi \\ \theta \\ \psi \end{bmatrix} = \begin{bmatrix} 0 \\ 0 \\ 0 \end{bmatrix} ϕθψ = 000
由于初始数据可能存在较大偏差,初始的后验协方差矩阵可设置为较大值,具体需根据实际情况调整。

step1:先验估计

先读取陀螺仪的角速度数据 [ p q r ] \begin{bmatrix} p \\ q \\ r \end{bmatrix} pqr ,转换为单位 rad/s \text{rad/s} rad/s,代入以下公式得到欧拉角的导数 [ ϕ ˙ θ ˙ ψ ˙ ] T \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix}^T ϕ˙θ˙ψ˙ T
[ ϕ ˙ θ ˙ ψ ˙ ] = [ 1 S ϕ T θ C ϕ T θ 0 C ϕ − S ϕ 0 S ϕ / C θ C ϕ / C θ ] [ p q r ] (1) \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix} = \begin{bmatrix} 1 & S_\phi T_\theta & C_\phi T_\theta \\ 0 & C_\phi & -S_\phi \\ 0 & S_\phi/C_\theta & C_\phi/C_\theta \end{bmatrix} \begin{bmatrix} p \\ q \\ r \end{bmatrix} \tag{1} ϕ˙θ˙ψ˙ = 100SϕTθCϕSϕ/CθCϕTθSϕCϕ/Cθ pqr (1)
(式中 S ⋅ = sin ⁡ ( ⋅ ) S_\cdot = \sin(\cdot) S=sin() C ⋅ = cos ⁡ ( ⋅ ) C_\cdot = \cos(\cdot) C=cos() T θ = tan ⁡ ( θ ) T_\theta = \tan(\theta) Tθ=tan(θ)

将欧拉角的导数 [ ϕ ˙ θ ˙ ψ ˙ ] T \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix}^T ϕ˙θ˙ψ˙ T 作为系统状态转移方程的输入向量 U \mathbf{U} U,即:
U = [ ϕ ˙ θ ˙ ψ ˙ ] (2) \mathbf{U} = \begin{bmatrix} \dot{\phi} \\ \dot{\theta} \\ \dot{\psi} \end{bmatrix} \tag{2} U= ϕ˙θ˙ψ˙ (2)

设离散周期为 T \mathbf{T} T,离散系统的状态转移方程为:
X k + 1 = A X k + B U k \mathbf{X_{k+1}}=A\mathbf{X_k}+B\mathbf{U_k} Xk+1=AXk+BUk

展开形式为:
[ ϕ ^ k + 1 − θ ^ k + 1 − ψ ^ k + 1 − ] = [ 1 0 0 0 1 0 0 0 1 ] [ ϕ ^ k θ ^ k ψ ^ k ] + [ T 0 0 0 T 0 0 0 T ] [ ϕ ˙ k θ ˙ k ψ ˙ k ] (3) \begin{bmatrix}\hat{\phi}_{k+1}^- \\ \hat{\theta}_{k+1}^- \\ \hat{\psi}_{k+1}^-\end{bmatrix}=\begin{bmatrix}1&0&0 \\ 0&1&0 \\ 0&0&1\end{bmatrix}\begin{bmatrix}\hat{\phi}_k \\ \hat{\theta}_k \\ \hat{\psi}_k\end{bmatrix}+\begin{bmatrix}T&0&0 \\ 0&T&0 \\ 0&0&T\end{bmatrix}\begin{bmatrix}\dot{\phi}_k \\ \dot{\theta}_k \\ \dot{\psi}_k\end{bmatrix} \tag{3} ϕ^k+1θ^k+1ψ^k+1 = 100010001 ϕ^kθ^kψ^k + T000T000T ϕ˙kθ˙kψ˙k (3)

其中,矩阵 A A A 为三阶单位矩阵,矩阵 B B B 为三阶单位矩阵乘以 T T T

A = I 3 = [ 1 0 0 0 1 0 0 0 1 ] , B = T ⋅ I 3 = [ T 0 0 0 T 0 0 0 T ] (4) A =I_3= \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix}, \quad B =T\cdot I_3 =\begin{bmatrix} T & 0 & 0 \\ 0 & T & 0 \\ 0 & 0 & T \end{bmatrix} \tag{4} A=I3= 100010001 ,B=TI3= T000T000T (4)

先验估计公式为:

[ ϕ ^ k + 1 − θ ^ k + 1 − ψ ^ k + 1 − ] = [ 1 0 0 0 1 0 0 0 1 ] [ ϕ ^ k θ ^ k ψ ^ k ] + [ T 0 0 0 T 0 0 0 T ] [ ϕ ˙ k θ ˙ k ψ ˙ k ] (5) \begin{bmatrix} \hat{\phi}_{k+1}^- \\ \hat{\theta}_{k+1}^- \\ \hat{\psi}_{k+1}^- \end{bmatrix} = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} \hat{\phi}_k \\ \hat{\theta}_k \\ \hat{\psi}_k \end{bmatrix} + \begin{bmatrix} T & 0 & 0 \\ 0 & T & 0 \\ 0 & 0 & T \end{bmatrix} \begin{bmatrix} \dot{\phi}_k \\ \dot{\theta}_k \\ \dot{\psi}_k \end{bmatrix} \tag{5} ϕ^k+1θ^k+1ψ^k+1 = 100010001 ϕ^kθ^kψ^k + T000T000T ϕ˙kθ˙kψ˙k (5)

先验误差协方差矩阵计算公式:
P k + 1 − = A P k A T + Q (6) P_{k+1}^-=A P_k A^T+Q \tag{6} Pk+1=APkAT+Q(6)

Step 2:状态测量值

状态测量值与系统状态满足关系:
z k = H X m k z_k=H\mathbf{X}_{mk} zk=HXmk

由加速度计数据转换得到的姿态角向量 z k z_k zk 为:
z k = [ ϕ m k θ m k ψ m k ] z_k=\begin{bmatrix}\phi_{mk} \\ \theta_{mk} \\ \psi_{mk}\end{bmatrix} zk= ϕmkθmkψmk

通过三轴加速度计数据 a = [ a x , a y , a z ] T \mathbf{a}=[a_x,a_y,a_z]^T a=[ax,ay,az]T 计算:
ϕ m k = arctan ⁡ ( a y / a z ) θ m k = − arctan ⁡ ( a x / a y 2 + a z 2 ) (7) \begin{aligned} \mathbf{\phi}_{mk}&=\arctan(a_y/a_z) \\ \mathbf{\theta}_{mk}&=-\arctan(a_x/\sqrt{a_y^2+a_z^2}) \tag{7} \end{aligned} ϕmkθmk=arctan(ay/az)=arctan(ax/ay2+az2 )(7)

(重力加速度数据无法解算航向角 ψ \psi ψ

测量矩阵 H H H 为:
H = [ 1 0 0 0 1 0 0 0 0 ] H=\begin{bmatrix}1&0&0 \\ 0&1&0 \\ 0&0&0\end{bmatrix} H= 100010000

Step 3:后验估计

基于先验估计(公式 5)与先验协方差矩阵(公式 6),计算卡尔曼增益:
K k + 1 = P k + 1 − H T H P k + 1 − H T + R (8) K_{k+1}=\frac{P_{k+1}^-H^T}{HP_{k+1}^-H^T+R} \tag{8} Kk+1=HPk+1HT+RPk+1HT(8)

后验估计:
x ^ k + 1 = x ^ k + 1 − + K k + 1 ( z k + 1 − H x ^ k + 1 − ) (9) \hat{x}_{k+1}=\hat{x}_{k+1}^-+K_{k+1}(z_{k+1}-H\hat{x}_{k+1}^-) \tag{9} x^k+1=x^k+1+Kk+1(zk+1Hx^k+1)(9)

后验误差协方差矩阵:
P k + 1 = ( I − K k + 1 H ) P k + 1 − (10) P_{k+1}=(I-K_{k+1}H)P_{k+1}^- \tag{10} Pk+1=(IKk+1H)Pk+1(10)

总结

基于卡尔曼滤波器的 IMU 姿态解算流程可概括为:

  1. 读取 IMU 的三轴角速度与三轴加速度数据;
  2. 通过公式(1)计算欧拉角导数;
  3. 通过公式(5)计算先验估计,公式(6)计算先验误差协方差矩阵;
  4. 通过公式(7)获取状态测量值,公式(8)计算卡尔曼增益,代入公式(9)完成后验估计,公式(10)计算后验误差协方差矩阵,完成一个卡尔曼滤波周期。

浅谈基于卡尔曼滤波器的姿态解算(二)——代码实现及效果演示

争取35岁退休 已于 2024-04-25 02:53:38 修改

本文承接上篇内容,对基于卡尔曼滤波器的姿态解算进行代码实现与效果验证。主要内容包括算法公式解析、函数输入参数说明,并指出该解算方法可获取准确的横滚角与俯仰角,但航向角存在漂移问题,后续将引入磁力计予以解决。

前言

上篇博客完成了基于卡尔曼滤波器姿态解算的公式推导,本文将实现算法代码并演示解算效果。考虑到部分单片机不支持直接矩阵运算,需将矩阵运算拆解为方程组形式。

公式解析

Step 1:获取欧拉角导数

陀螺仪角速度数据 ω = [ p , q , r ] T \mathbf{\omega}=[p,q,r]^T ω=[p,q,r]T 与欧拉角导数的关系为:
[ ϕ ˙ θ ˙ ψ ˙ ] = [ 1 sin ⁡ ϕ tan ⁡ θ cos ⁡ ϕ tan ⁡ θ 0 cos ⁡ ϕ − sin ⁡ ϕ 0 sin ⁡ ϕ / cos ⁡ θ cos ⁡ ϕ / cos ⁡ θ ] [ p q r ] \begin{bmatrix}\dot{\mathbf{\phi}} \\ \dot{\mathbf{\theta}} \\ \dot{\mathbf{\psi}}\end{bmatrix}=\begin{bmatrix}1 & \sin\phi\tan\theta & \cos\phi\tan\theta \\ 0 & \cos\phi & -\sin\phi \\ 0 & \sin\phi/\cos\theta & \cos\phi/\cos\theta\end{bmatrix}\begin{bmatrix}p \\ q \\ r\end{bmatrix} ϕ˙θ˙ψ˙ = 100sinϕtanθcosϕsinϕ/cosθcosϕtanθsinϕcosϕ/cosθ pqr

离散形式方程组:
{ ϕ k ˙ = p k + sin ⁡ ϕ k tan ⁡ θ k q k + cos ⁡ ϕ k tan ⁡ θ k r k θ k ˙ = cos ⁡ ϕ k q k − sin ⁡ ϕ k r k ψ k ˙ = sin ⁡ ϕ k q k / cos ⁡ θ k + cos ⁡ ϕ k r k / cos ⁡ θ k (1) \left\{ \begin{aligned} \dot{\mathbf{\phi}_k} &= p_k+\sin\phi_k\tan\theta_k q_k+\cos\phi_k\tan\theta_k r_k \\ \dot{\mathbf{\theta}_k} &= \cos\phi_k q_k-\sin\phi_k r_k \\ \dot{\mathbf{\psi}_k} &= \sin\phi_k q_k/\cos\theta_k+\cos\phi_k r_k/\cos\theta_k \\ \end{aligned} \right. \tag{1} ϕk˙θk˙ψk˙=pk+sinϕktanθkqk+cosϕktanθkrk=cosϕkqksinϕkrk=sinϕkqk/cosθk+cosϕkrk/cosθk(1)

Step 2:先验估计

先验估计公式:
[ ϕ ^ k + 1 − θ ^ k + 1 − ψ ^ k + 1 − ] = [ 1 0 0 0 1 0 0 0 1 ] [ ϕ ^ k θ ^ k ψ ^ k ] + [ T 0 0 0 T 0 0 0 T ] [ ϕ ˙ k θ ˙ k ψ ˙ k ] \begin{bmatrix}\hat{\phi}_{k+1}^- \\ \hat{\theta}_{k+1}^- \\ \hat{\psi}_{k+1}^-\end{bmatrix}=\begin{bmatrix}1&0&0 \\ 0&1&0 \\ 0&0&1\end{bmatrix}\begin{bmatrix}\hat{\phi}_k \\ \hat{\theta}_k \\ \hat{\psi}_k\end{bmatrix}+\begin{bmatrix}T&0&0 \\ 0&T&0 \\ 0&0&T\end{bmatrix}\begin{bmatrix}\dot{\phi}_k \\ \dot{\theta}_k \\ \dot{\psi}_k\end{bmatrix} ϕ^k+1θ^k+1ψ^k+1 = 100010001 ϕ^kθ^kψ^k + T000T000T ϕ˙kθ˙kψ˙k

离散形式方程组:
{ ϕ ^ k + 1 − = ϕ ^ k + T ϕ ˙ k θ ^ k + 1 − = θ ^ k + T θ ˙ k ψ ^ k + 1 − = ψ ^ k + T ψ ˙ k (2) \left\{ \begin{aligned} \hat{\mathbf{\phi}}_{k+1}^- &= \hat{\mathbf{\phi}}_k + T\dot{\mathbf{\phi}}_k \\ \hat{\mathbf{\theta}}_{k+1}^- &= \hat{\mathbf{\theta}}_k + T\dot{\mathbf{\theta}}_k \\ \hat{\mathbf{\psi}}_{k+1}^- &= \hat{\mathbf{\psi}}_k + T\dot{\mathbf{\psi}}_k \\ \end{aligned} \right. \tag{2} ϕ^k+1θ^k+1ψ^k+1=ϕ^k+Tϕ˙k=θ^k+Tθ˙k=ψ^k+Tψ˙k(2)

Step 3:先验估计误差协方差矩阵

设系统噪声协方差矩阵 Q = diag ( q ϕ , q θ , q ψ ) Q=\text{diag}(q_\phi,q_\theta,q_\psi) Q=diag(qϕ,qθ,qψ)

先验误差协方差矩阵 P k − = diag ( p ϕ , k − , p θ , k − , p ψ , k − ) P_k^-=\text{diag}(p_{\phi,k}^-,p_{\theta,k}^-,p_{\psi,k}^-) Pk=diag(pϕ,k,pθ,k,pψ,k)

后验误差协方差矩阵 P k = diag ( p ϕ , k , p θ , k , p ψ , k ) P_k=\text{diag}(p_{\phi,k},p_{\theta,k},p_{\psi,k}) Pk=diag(pϕ,k,pθ,k,pψ,k),则:

{ p ϕ , k + 1 − = p ϕ , k + q ϕ p θ , k + 1 − = p θ , k + q θ p ψ , k + 1 − = p ψ , k + q ψ (3) \left\{ \begin{aligned} p_{\phi,k+1}^- &= p_{\phi,k} + q_\phi \\ p_{\theta,k+1}^- &= p_{\theta,k} + q_\theta \\ p_{\psi,k+1}^- &= p_{\psi,k} + q_\psi \\ \end{aligned} \right. \tag{3} pϕ,k+1pθ,k+1pψ,k+1=pϕ,k+qϕ=pθ,k+qθ=pψ,k+qψ(3)

Step 4:卡尔曼增益矩阵计算

测量矩阵 H = [ 1 0 0 0 1 0 0 0 0 ] H=\begin{bmatrix}1&0&0 \\ 0&1&0 \\ 0&0&0\end{bmatrix} H= 100010000 ,测量噪声协方差矩阵 R = diag ( r ϕ , r θ , r ψ ) R=\text{diag}(r_\phi,r_\theta,r_\psi) R=diag(rϕ,rθ,rψ),卡尔曼增益矩阵 K k = diag ( k 1 , k , k 2 , k , k 3 , k ) K_k=\text{diag}(k_{1,k},k_{2,k},k_{3,k}) Kk=diag(k1,k,k2,k,k3,k),则:
{ k 1 , k + 1 = p ϕ , k + 1 − / ( p ϕ , k + 1 − + r ϕ ) k 2 , k + 1 = p θ , k + 1 − / ( p θ , k + 1 − + r θ ) k 3 , k + 1 = 0 (4) \left\{ \begin{aligned} k_{1,k+1} &= p_{\phi,k+1}^-/(p_{\phi,k+1}^-+r_\phi) \\ k_{2,k+1} &= p_{\theta,k+1}^-/(p_{\theta,k+1}^-+r_\theta) \\ k_{3,k+1} &= 0 \\ \end{aligned} \right. \tag{4} k1,k+1k2,k+1k3,k+1=pϕ,k+1/(pϕ,k+1+rϕ)=pθ,k+1/(pθ,k+1+rθ)=0(4)

Step 5:获取欧拉角测量值

测量向量 z k = [ ϕ m , k θ m , k ψ m , k ] z_k=\begin{bmatrix}\phi_{m,k} \\ \theta_{m,k} \\ \psi_{m,k}\end{bmatrix} zk= ϕm,kθm,kψm,k ,其中:
{ ϕ m , k = arctan ⁡ ( a y / a z ) θ m , k = − arctan ⁡ ( a x / a y 2 + a z 2 ) ψ m , k = 0 (5) \left\{ \begin{aligned} \phi_{m,k} &= \arctan(a_y/a_z) \\ \theta_{m,k} &= -\arctan(a_x/\sqrt{a_y^2+a_z^2}) \\ \psi_{m,k} &= 0 \\ \end{aligned} \right. \tag{5} ϕm,kθm,kψm,k=arctan(ay/az)=arctan(ax/ay2+az2 )=0(5)
其中, [ a x , a y , a z ] T [ a_x, a_y, a_z ]^T [ax,ay,az]T 是三轴加速度计数据。

step 6:后验估计计算

后验估计的计算公式为:
x ^ k + 1 = x ^ k + 1 − + K k + 1 ( z k + 1 − H x ^ k + 1 − ) \hat{x}_{k+1} = \hat{x}_{k+1}^{-} + K_{k+1}(z_{k+1} - H\hat{x}_{k+1}^{-}) x^k+1=x^k+1+Kk+1(zk+1Hx^k+1)

令后验估计状态为 [ ϕ ^ k + 1 θ ^ k + 1 ψ ^ k + 1 ] \begin{bmatrix} \hat{\phi}_{k+1} \\ \hat{\theta}_{k+1} \\ \hat{\psi}_{k+1} \end{bmatrix} ϕ^k+1θ^k+1ψ^k+1 ,可得离散形式方程组:
{ ϕ ^ k + 1 = ( 1 − k 1 , k + 1 ) ϕ ^ k + 1 − + k 1 , k + 1 ϕ m , k + 1 θ ^ k + 1 = ( 1 − k 2 , k + 1 ) θ ^ k + 1 − + k 2 , k + 1 θ m , k + 1 ψ ^ k + 1 = ψ ^ k + 1 − (6) \left\{ \begin{aligned} \hat{\phi}_{k+1} &= (1 - k_{1,k+1})\hat{\phi}_{k+1}^{-} + k_{1,k+1}\phi_{m,k+1} \\ \hat{\theta}_{k+1} &= (1 - k_{2,k+1})\hat{\theta}_{k+1}^{-} + k_{2,k+1}\theta_{m,k+1} \\ \hat{\psi}_{k+1} &= \hat{\psi}_{k+1}^{-} \end{aligned} \right. \tag{6} ϕ^k+1θ^k+1ψ^k+1=(1k1,k+1)ϕ^k+1+k1,k+1ϕm,k+1=(1k2,k+1)θ^k+1+k2,k+1θm,k+1=ψ^k+1(6)

航向角漂移问题源于未引入测量数据校正,仅沿用先验估计结果,导致陀螺仪累计误差使航向角逐渐漂移。其根本原因是测量值中 ψ m , k = 0 \psi_{m,k} = 0 ψm,k=0,无法对航向角进行校正。

Step 7:后验估计误差协方差矩阵

{ p ϕ , k + 1 = ( 1 − k 1 , k + 1 ) p ϕ , k + 1 − p θ , k + 1 = ( 1 − k 2 , k + 1 ) p θ , k + 1 − p ψ , k + 1 = p ψ , k + 1 − (7) \left\{ \begin{aligned} p_{\phi,k+1} &= (1-k_{1,k+1})p_{\phi,k+1}^- \\ p_{\theta,k+1} &= (1-k_{2,k+1})p_{\theta,k+1}^- \\ p_{\psi,k+1} &= p_{\psi,k+1}^- \\ \end{aligned} \right. \tag{7} pϕ,k+1pθ,k+1pψ,k+1=(1k1,k+1)pϕ,k+1=(1k2,k+1)pθ,k+1=pψ,k+1(7)

代码实现

函数接口说明

输入参数:

  • g x , g y , g z gx,gy,gz gx,gy,gz:陀螺仪角速度数据,单位 rad/s \text{rad/s} rad/s
  • a x , a y , a z ax,ay,az ax,ay,az:加速度计数据(单位不限);

(需确保角速度坐标系与加速度坐标系方向一致)

#include <math.h>
float roll = 0, pitch = 0, yaw = 0; 
// 欧拉角存储变量
static float Xk_[3] = {0};  
// 先验估计值
static float Xk[3] = {0};
// 后验估计值
static float Uk[3] = {0};
// 系统输入向量
static float Zk[3] = {0};
// 测量状态向量
static float Pk[3] = {1, 1, 1};
// 后验误差协方差矩阵
static float Pk_[3] = {0};
// 先验误差协方差矩阵
static float K[3] = {0};
// 卡尔曼增益矩阵
static float Q[3] = {1, 1, 1};
// 系统噪声协方差矩阵
static float R[3] = {1, 1, 1};
// 测量噪声协方差矩阵
static float T = 0.002f;
// 离散周期

// 基于卡尔曼滤波器的姿态解算函数
void kalman_filter_attitude_solution(float gx, float gy, float gz, float ax, float ay, float az)
{
    // Step 1:计算系统输入向量(欧拉角导数)
    Uk[0] = gx + sin(Xk[0]) * tan(Xk[1]) * gy + cos(Xk[0]) * tan(Xk[1]) * gz;
    Uk[1] = cos(Xk[0]) * gy - sin(Xk[0]) * gz;
    Uk[2] = sin(Xk[0]) * gy / cos(Xk[1]) + cos(Xk[0]) * gz / cos(Xk[1]);

    // Step 2:先验估计
    Xk_[0] = Xk[0] + T * Uk[0];
    Xk_[1] = Xk[1] + T * Uk[1];
    Xk_[2] = Xk[2] + T * Uk[2];

    // Step 3:先验误差协方差矩阵
    Pk_[0] = Pk[0] + Q[0];
    Pk_[1] = Pk[1] + Q[1];
    Pk_[2] = Pk[2] + Q[2];

    // Step 4:计算卡尔曼增益
    K[0] = Pk_[0] / (Pk_[0] + R[0]);
    K[1] = Pk_[1] / (Pk_[1] + R[1]);
    K[2] = 0;

    // Step 5:获取测量数据
    Zk[0] = atan(ay / az);
    Zk[1] = -atan(ax / (sqrt(ay * ay + az * az)));
    Zk[2] = 0;

    // Step 6:后验估计
    Xk[0] = (1 - K[0]) * Xk_[0] + K[0] * Zk[0];
    Xk[1] = (1 - K[1]) * Xk_[1] + K[1] * Zk[1];
    Xk[2] = Xk_[2];

    // Step 7:后验误差协方差矩阵
    Pk[0] = (1 - K[0]) * Pk_[0];
    Pk[1] = (1 - K[1]) * Pk_[1];
    Pk[2] = Pk_[2];

    // 转换为角度制
    roll = Xk[0] / 3.141f * 180.f;
    pitch = Xk[1] / 3.141f * 180.f;
    yaw = Xk[2] / 3.141f * 180.f;
}

效果演示

采用匿名飞控板与匿名上位机验证姿态解算效果(非商业推广,仅为实验器材)。

总结

  • 基于卡尔曼滤波器的姿态解算可获得高精度的横滚角与俯仰角,但航向角因缺乏测量校正存在漂移,且在振动、电磁干扰环境下漂移加剧;
  • 初始化时可通过计算平均偏移量进行偏置补偿,但无法彻底消除漂移;
  • 后续将引入磁力计传感器解决航向角漂移问题。

浅谈基于卡尔曼滤波器的姿态解算(三)——磁力计标定航向角

争取35岁退休 已于 2024-04-25 16:41:50 修改

前言

经过前两篇博客的研究,第一篇基于卡尔曼滤波器完成了姿态解算的原理推导,第二篇实现了算法代码并验证了解算效果。

但第二篇博客发现航向角存在漂移问题,分析原因是重力加速度数据无法对航向角 yaw 进行标定,导致陀螺仪数据噪声在姿态解算过程中累积误差,引发航向角 yaw 漂移。

针对这一问题,本文将引入磁力计传感器来标定航向角 yaw,并介绍相关原理和公式推导过程。

磁力计传感器

原理

磁力计(电子罗盘)基于地球磁场确定惯性系方向,其原理与指南针类似。地球磁感线由地磁南极指向地磁北极,磁力计将磁感线分解为机体系 X Y Z XYZ XYZ 三轴分量,利用该数据标定航向角,解决漂移问题。

问题

磁力计由三组霍尔元件构成,受设计、加工等因素影响,输出数据常存在不对称性:

  • 理想情况下,机体系转动时磁力计三轴数据应分布于以坐标原点为中心的球面上;
  • 实际输出数据分布于中心偏离原点的椭球面上,需对数据进行归一化校正。

磁力计标定航向角原理

惯性系定义

惯性系 X Y Z XYZ XYZ 轴分别对应北、东、天(NED 坐标系),地球磁感线位于惯性系 X O Z XOZ XOZ 平面内(由南向北),其在 X X X 轴与 Z Z Z 轴的分量比例随地理位置变化:赤道附近 X X X 轴分量占优,两极附近 Z Z Z 轴分量占优。

通常定义正北方向为航向角零度( ψ = 0 \psi=0 ψ=0),航向角正负由右手法则判定。

公式推导

在不考虑磁场干扰的前提下,地球磁场在惯性系中的向量可表示为 [ m e , x 0 m e , z ] \begin{bmatrix} m_{e,x} \\ 0 \\ m_{e,z} \end{bmatrix} me,x0me,z ;经坐标系变换后,其在机体系中的向量为 [ m b , x m b , y m b , z ] \begin{bmatrix} m_{b,x} \\ m_{b,y} \\ m_{b,z} \end{bmatrix} mb,xmb,ymb,z 。其中,从惯性系到机体系的坐标系变换矩阵 R \mathbf{R} R 定义如下:

R = R X ( ϕ ) R Y ( θ ) R Z ( ψ ) = [ C ψ C θ S ψ C θ − S θ C ψ S θ S ϕ − S ψ C ϕ S ψ S θ S ϕ + C ψ C ϕ C θ S ϕ C ψ S θ C ϕ + S ψ S ϕ S ψ S θ C ϕ − C ψ S ϕ C θ C ϕ ] (1) \mathbf{R} = \mathbf{R}_X(\phi) \mathbf{R}_Y(\theta) \mathbf{R}_Z(\psi) = \begin{bmatrix} C_\psi C_\theta & S_\psi C_\theta & -S_\theta \\ C_\psi S_\theta S_\phi - S_\psi C_\phi & S_\psi S_\theta S_\phi + C_\psi C_\phi & C_\theta S_\phi \\ C_\psi S_\theta C_\phi + S_\psi S_\phi & S_\psi S_\theta C_\phi - C_\psi S_\phi & C_\theta C_\phi \end{bmatrix} \tag{1} R=RX(ϕ)RY(θ)RZ(ψ)= CψCθCψSθSϕSψCϕCψSθCϕ+SψSϕSψCθSψSθSϕ+CψCϕSψSθCϕCψSϕSθCθSϕCθCϕ (1)

式中各旋转矩阵的定义为:
R Z ( ψ ) = [ cos ⁡ ψ sin ⁡ ψ 0 − sin ⁡ ψ cos ⁡ ψ 0 0 0 1 ] (2) \mathbf{R}_Z(\psi) = \begin{bmatrix} \cos\psi & \sin\psi & 0 \\ -\sin\psi & \cos\psi & 0 \\ 0 & 0 & 1 \end{bmatrix} \tag{2} RZ(ψ)= cosψsinψ0sinψcosψ0001 (2)

R Y ( θ ) = [ cos ⁡ θ 0 − sin ⁡ θ 0 1 0 sin ⁡ θ 0 cos ⁡ θ ] (3) \mathbf{R}_Y(\theta) = \begin{bmatrix} \cos\theta & 0 & -\sin\theta \\ 0 & 1 & 0 \\ \sin\theta & 0 & \cos\theta \end{bmatrix} \tag{3} RY(θ)= cosθ0sinθ010sinθ0cosθ (3)

R X ( ϕ ) = [ 1 0 0 0 cos ⁡ ϕ sin ⁡ ϕ 0 − sin ⁡ ϕ cos ⁡ ϕ ] (4) \mathbf{R}_X(\phi) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\phi & \sin\phi \\ 0 & -\sin\phi & \cos\phi \end{bmatrix} \tag{4} RX(ϕ)= 1000cosϕsinϕ0sinϕcosϕ (4)

(说明:上述表达式中, C ⋅ C_\cdot C 代表 cos ⁡ ( ⋅ ) \cos(\cdot) cos() S ⋅ S_\cdot S 代表 sin ⁡ ( ⋅ ) \sin(\cdot) sin()

机体系磁场向量与惯性系磁场向量满足:
[ m b , x m b , y m b , z ] = R [ m e , x 0 m e , z ] = R X ( ϕ ) R Y ( θ ) R Z ( ψ ) [ m e , x 0 m e , z ] (5) \begin{align*} \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} &= \mathbf{R} \begin{bmatrix}m_{e,x} \\0 \\m_{e,z}\end{bmatrix} = \mathbf{R}_X(\phi)\mathbf{R}_Y(\theta)\mathbf{R}_Z(\psi) \begin{bmatrix}m_{e,x} \\0 \\m_{e,z}\end{bmatrix} \end{align*}\tag{5} mb,xmb,ymb,z =R me,x0me,z =RX(ϕ)RY(θ)RZ(ψ) me,x0me,z (5)

为解算航向角 ψ \psi ψ,定义惯性系磁场向量绕 Z Z Z 轴旋转 ψ \psi ψ 后的向量为 [ m Z , x m Z , y m Z , z ] \begin{bmatrix} m_{Z,x} \\ m_{Z,y} \\ m_{Z,z} \end{bmatrix} mZ,xmZ,ymZ,z

[ m Z , x m Z , y m Z , z ] = R Z ( ψ ) [ m e , x 0 m e , z ] (6) \begin{align*} \begin{bmatrix}m_{Z,x} \\m_{Z,y} \\m_{Z,z}\end{bmatrix} &= \mathbf{R}_Z(\psi) \begin{bmatrix}m_{e,x} \\0 \\m_{e,z}\end{bmatrix} \end{align*}\tag{6} mZ,xmZ,ymZ,z =RZ(ψ) me,x0me,z (6)

在分析地球磁场的坐标系变换时,为了降低计算复杂度,会选择惯性系的坐标轴方向:将惯性系的 y y y 轴调整至“与地球磁场向量垂直”的方向,此时地球磁场在该系的 y y y 方向上没有投影,因此其 y y y 分量自然为 0。

由几何关系得航向角:

ψ = atan ( m Z , x m Z , y ) \begin{align*} \psi &= \text{atan}\left(\frac{m_{Z,x}}{m_{Z,y}}\right) \tag{7} \end{align*} ψ=atan(mZ,ymZ,x)(7)
联立公式(5)与(6),可得:
[ m b , x m b , y m b , z ] = R X ( ϕ ) R Y ( θ ) [ m Z , x m Z , y m Z , z ] \begin{align*} \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} &= \mathbf{R}_X(\phi)\mathbf{R}_Y(\theta) \begin{bmatrix}m_{Z,x} \\m_{Z,y} \\m_{Z,z}\end{bmatrix} \tag{8} \end{align*} mb,xmb,ymb,z =RX(ϕ)RY(θ) mZ,xmZ,ymZ,z (8)
整理后得到:

[ m Z , x m Z , y m Z , z ] = R Y − 1 ( θ ) R X − 1 ( ϕ ) [ m b , x m b , y m b , z ] \begin{align*} \begin{bmatrix}m_{Z,x} \\m_{Z,y} \\m_{Z,z}\end{bmatrix} &= \mathbf{R}_Y^{-1}(\theta) \mathbf{R}_X^{-1}(\phi) \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} \tag{9} \end{align*} mZ,xmZ,ymZ,z =RY1(θ)RX1(ϕ) mb,xmb,ymb,z (9)

由公式 3 和公式 4 所得旋转变换矩阵为正交矩阵,其逆等于转置:

R Y − 1 ( θ ) = R Y T ( θ ) = [ cos ⁡ θ 0 sin ⁡ θ 0 1 0 − sin ⁡ θ 0 cos ⁡ θ ] R X − 1 ( ϕ ) = R X T ( ϕ ) = [ 1 0 0 0 cos ⁡ ϕ − sin ⁡ ϕ 0 sin ⁡ ϕ cos ⁡ ϕ ] \begin{align*} \mathbf{R}_Y^{-1}(\theta) &= \mathbf{R}_Y^T(\theta) = \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix} \tag{10} \\ \\ \mathbf{R}_X^{-1}(\phi) &= \mathbf{R}_X^T(\phi) = \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\phi & -\sin\phi \\ 0 & \sin\phi & \cos\phi \end{bmatrix} \tag{11} \end{align*} RY1(θ)RX1(ϕ)=RYT(θ)= cosθ0sinθ010sinθ0cosθ =RXT(ϕ)= 1000cosϕsinϕ0sinϕcosϕ (10)(11)

将 公式10 和 公式11 代入公式(9)得:

[ m Z , x m Z , y m Z , z ] = [ cos ⁡ θ 0 sin ⁡ θ 0 1 0 − sin ⁡ θ 0 cos ⁡ θ ] [ 1 0 0 0 cos ⁡ ϕ − sin ⁡ ϕ 0 sin ⁡ ϕ cos ⁡ ϕ ] [ m b , x m b , y m b , z ] \begin{align*} \begin{bmatrix}m_{Z,x} \\m_{Z,y} \\m_{Z,z}\end{bmatrix} &= \begin{bmatrix} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \\ 0 & \cos\phi & -\sin\phi \\ 0 & \sin\phi & \cos\phi \end{bmatrix} \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} \tag{12} \end{align*} mZ,xmZ,ymZ,z = cosθ0sinθ010sinθ0cosθ 1000cosϕsinϕ0sinϕcosϕ mb,xmb,ymb,z (12)

整理为(记 C θ = cos ⁡ θ , S θ = sin ⁡ θ ; C ϕ = cos ⁡ ϕ , S ϕ = sin ⁡ ϕ C_\theta=\cos\theta, S_\theta=\sin\theta; C_\phi=\cos\phi, S_\phi=\sin\phi Cθ=cosθ,Sθ=sinθ;Cϕ=cosϕ,Sϕ=sinϕ):
[ m Z , x m Z , y m Z , z ] = [ C θ S θ S ϕ S θ C ϕ 0 C ϕ − S ϕ − S θ C θ S ϕ C θ C ϕ ] [ m b , x m b , y m b , z ] \begin{align*} \begin{bmatrix}m_{Z,x} \\m_{Z,y} \\m_{Z,z}\end{bmatrix} &= \begin{bmatrix} C_\theta & S_\theta S_\phi & S_\theta C_\phi \\ 0 & C_\phi & -S_\phi \\ -S_\theta & C_\theta S_\phi & C_\theta C_\phi \end{bmatrix} \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} \tag{13} \end{align*} mZ,xmZ,ymZ,z = Cθ0SθSθSϕCϕCθSϕSθCϕSϕCθCϕ mb,xmb,ymb,z (13)

代码实现

step1:读取并处理磁力计数据

令读取到的磁力计原始数据为 [ m r a w , x m r a w , y m r a w , z ] \begin{bmatrix}m_{raw,x} \\m_{raw,y} \\m_{raw,z}\end{bmatrix} mraw,xmraw,ymraw,z ,分别绕 X , Y , Z X,Y,Z X,Y,Z 轴完整旋转一圈,记录各轴上的最大及最小值,记为 [ m m a x , x m m a x , y m m a x , z ] \begin{bmatrix}m_{max,x} \\m_{max,y} \\m_{max,z}\end{bmatrix} mmax,xmmax,ymmax,z [ m m i n , x m m i n , y m m i n , z ] \begin{bmatrix}m_{min,x} \\m_{min,y} \\m_{min,z}\end{bmatrix} mmin,xmmin,ymmin,z

设校准后的磁力计数据为 [ m b , x m b , y m b , z ] \begin{bmatrix}m_{b,x} \\m_{b,y} \\m_{b,z}\end{bmatrix} mb,xmb,ymb,z ,满足以下关系:
{ m b , x = m r a w , x − ( m m a x , x + m m i n , x ) / 2 ( m m a x , x − m m i n , x ) / 2 m b , y = m r a w , y − ( m m a x , y + m m i n , y ) / 2 ( m m a x , y − m m i n , y ) / 2 m b , z = m r a w , z − ( m m a x , z + m m i n , z ) / 2 ( m m a x , z − m m i n , z ) / 2 \begin{cases} m_{b,x} = \displaystyle \frac{m_{raw,x} - (m_{max,x} + m_{min,x})/2}{(m_{max,x} - m_{min,x})/2} \\ m_{b,y} = \displaystyle \frac{m_{raw,y} - (m_{max,y} + m_{min,y})/2}{(m_{max,y} - m_{min,y})/2} \\ m_{b,z} = \displaystyle \frac{m_{raw,z} - (m_{max,z} + m_{min,z})/2}{(m_{max,z} - m_{min,z})/2} \end{cases} mb,x=(mmax,xmmin,x)/2mraw,x(mmax,x+mmin,x)/2mb,y=(mmax,ymmin,y)/2mraw,y(mmax,y+mmin,y)/2mb,z=(mmax,zmmin,z)/2mraw,z(mmax,z+mmin,z)/2

step2:计算由磁力计解算的航向角

由公式 13 可得:
{ m Z , x = C θ m b , x + S θ S ϕ m b , y + S θ C ϕ m b , z m Z , y = C ϕ m b , y − S ϕ m b , z m Z , z = − S θ m b , x + C θ S ϕ m b , y + C θ C ϕ m b , z (14) \begin{cases} m_{Z,x} = C_\theta m_{b,x} + S_\theta S_\phi m_{b,y} + S_\theta C_\phi m_{b,z} \\ m_{Z,y} = C_\phi m_{b,y} - S_\phi m_{b,z} \\ m_{Z,z} = -S_\theta m_{b,x} + C_\theta S_\phi m_{b,y} + C_\theta C_\phi m_{b,z} \end{cases} \tag{14} mZ,x=Cθmb,x+SθSϕmb,y+SθCϕmb,zmZ,y=Cϕmb,ySϕmb,zmZ,z=Sθmb,x+CθSϕmb,y+CθCϕmb,z(14)

由公式 7 得到航向角在卡尔曼滤波器中的测量值,即:
ψ m , k = atan ( m Z , x / m Z , y ) (15) \psi_{m,k} = \text{atan}(m_{Z,x}/m_{Z,y}) \tag{15} ψm,k=atan(mZ,x/mZ,y)(15)

在上一篇的基础上修改测量状态向量 z ^ k \hat{z}_k z^k 以及测量矩阵 H H H,即令:
{ ϕ m , k = atan ( a y / a x ) θ m , k = − atan ( a z / a y 2 + a x 2 ) ψ m , k = atan ( m Z , y / m Z , x ) (16) \begin{cases} \phi_{m,k} = \text{atan}(a_y/a_x) \\ \theta_{m,k} = -\text{atan}\left(a_z/\sqrt{a_y^2 + a_x^2}\right) \\ \psi_{m,k} = \text{atan}(m_{Z,y}/m_{Z,x}) \end{cases} \tag{16} ϕm,k=atan(ay/ax)θm,k=atan(az/ay2+ax2 )ψm,k=atan(mZ,y/mZ,x)(16)
H = [ 1 0 0 0 1 0 0 0 1 ] (17) H = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \tag{17} H= 100010001 (17)

step3:完成卡尔曼滤波计算

一、状态转移

陀螺仪数据计算欧拉角变化率

{ ϕ ˙ k = p k + S ϕ k T θ k q k + C ϕ k T θ k r k θ ˙ k = C ϕ k q k − S ϕ k r k ψ ˙ k = S ϕ k q k / C θ k + C ϕ k r k / C θ k \begin{cases} \dot{\phi}_k = p_k + S_{\phi_k} T_{\theta_k} q_k + C_{\phi_k} T_{\theta_k} r_k \\ \dot{\theta}_k = C_{\phi_k} q_k - S_{\phi_k} r_k \\ \dot{\psi}_k = S_{\phi_k} q_k/C_{\theta_k} + C_{\phi_k} r_k/C_{\theta_k} \end{cases} ϕ˙k=pk+SϕkTθkqk+CϕkTθkrkθ˙k=CϕkqkSϕkrkψ˙k=Sϕkqk/Cθk+Cϕkrk/Cθk

二、先验估计计算

{ ϕ ^ k + 1 − = ϕ ^ k + T ϕ ˙ k θ ^ k + 1 − = θ ^ k + T θ ˙ k ψ ^ k + 1 − = ψ ^ k + T ψ ˙ k \begin{cases} \hat{\phi}_{k+1}^- = \hat{\phi}_k + T \dot{\phi}_k \\ \hat{\theta}_{k+1}^- = \hat{\theta}_k + T \dot{\theta}_k \\ \hat{\psi}_{k+1}^- = \hat{\psi}_k + T \dot{\psi}_k \end{cases} ϕ^k+1=ϕ^k+Tϕ˙kθ^k+1=θ^k+Tθ˙kψ^k+1=ψ^k+Tψ˙k

三、先验估计误差协方差矩阵计算

{ P ϕ , k + 1 − = P ϕ , k + q ϕ P θ , k + 1 − = P θ , k + q θ P ψ , k + 1 − = P ψ , k + q ψ \begin{cases} P_{\phi,k+1}^- = P_{\phi,k} + q_\phi \\ P_{\theta,k+1}^- = P_{\theta,k} + q_\theta \\ P_{\psi,k+1}^- = P_{\psi,k} + q_\psi \end{cases} Pϕ,k+1=Pϕ,k+qϕPθ,k+1=Pθ,k+qθPψ,k+1=Pψ,k+qψ

四、卡尔曼增益矩阵计算

{ k 1 , k + 1 = P ϕ , k + 1 − / ( P ϕ , k + 1 − + r ϕ ) k 2 , k + 1 = P θ , k + 1 − / ( P θ , k + 1 − + r θ ) k 3 , k + 1 = P ψ , k + 1 − / ( P ψ , k + 1 − + r ψ ) \begin{cases} k_{1,k+1} = P_{\phi,k+1}^- / (P_{\phi,k+1}^- + r_\phi) \\ k_{2,k+1} = P_{\theta,k+1}^- / (P_{\theta,k+1}^- + r_\theta) \\ k_{3,k+1} = P_{\psi,k+1}^- / (P_{\psi,k+1}^- + r_\psi) \end{cases} k1,k+1=Pϕ,k+1/(Pϕ,k+1+rϕ)k2,k+1=Pθ,k+1/(Pθ,k+1+rθ)k3,k+1=Pψ,k+1/(Pψ,k+1+rψ)

五、后验估计计算(测量状态向量参考公式 16)

{ ϕ ^ k + 1 = ( 1 − k 1 , k + 1 ) ϕ ^ k + 1 − + k 1 , k + 1 ϕ m , k + 1 θ ^ k + 1 = ( 1 − k 2 , k + 1 ) θ ^ k + 1 − + k 2 , k + 1 θ m , k + 1 ψ ^ k + 1 = ( 1 − k 3 , k + 1 ) ψ ^ k + 1 − + k 3 , k + 1 ψ m , k + 1 \begin{cases} \hat{\phi}_{k+1} = (1 - k_{1,k+1})\hat{\phi}_{k+1}^- + k_{1,k+1} \phi_{m,k+1} \\ \hat{\theta}_{k+1} = (1 - k_{2,k+1})\hat{\theta}_{k+1}^- + k_{2,k+1} \theta_{m,k+1} \\ \hat{\psi}_{k+1} = (1 - k_{3,k+1})\hat{\psi}_{k+1}^- + k_{3,k+1} \psi_{m,k+1} \end{cases} ϕ^k+1=(1k1,k+1)ϕ^k+1+k1,k+1ϕm,k+1θ^k+1=(1k2,k+1)θ^k+1+k2,k+1θm,k+1ψ^k+1=(1k3,k+1)ψ^k+1+k3,k+1ψm,k+1

六、后验估计误差协方差矩阵

{ P ϕ , k + 1 = ( 1 − k 1 , k + 1 ) P ϕ , k + 1 − P θ , k + 1 = ( 1 − k 2 , k + 1 ) P θ , k + 1 − P ψ , k + 1 = ( 1 − k 3 , k + 1 ) P ψ , k + 1 − \begin{cases} P_{\phi,k+1} = (1 - k_{1,k+1})P_{\phi,k+1}^- \\ P_{\theta,k+1} = (1 - k_{2,k+1})P_{\theta,k+1}^- \\ P_{\psi,k+1} = (1 - k_{3,k+1})P_{\psi,k+1}^- \end{cases} Pϕ,k+1=(1k1,k+1)Pϕ,k+1Pθ,k+1=(1k2,k+1)Pθ,k+1Pψ,k+1=(1k3,k+1)Pψ,k+1

上述步骤的 C 语言实现

函数接口说明

函数输入参数:

  • gx, gy, gz:陀螺仪角速度数据,单位: rad/s \text{rad/s} rad/s
  • ax, ay, az:加速度计数据,单位不管;
  • mx, my, mz:磁力计数据,单位不管;

注意:要将三组传感器的坐标系对应上,统一方向。

要不要我帮你补充一份传感器坐标系统一的校验要点,避免数据方向错误?

C 语言实现代码
#include <math.h>
#include <float.h>

float roll = 0, pitch = 0, yaw = 0; 
// Euler angle storage variables
static float Xk_[3] = {0};  
// A priori estimate values
static float Xk[3] = {0};
// A posteriori estimate values
static float Uk[3] = {0};
// System input vector
static float Zk[3] = {0};
// Measurement state vector
static float Pk[3] = {1, 1, 1};
// A posteriori error covariance matrix
static float Pk_[3] = {0};
// A priori error covariance matrix
static float K[3] = {0};
// Kalman gain matrix
static float Q[3] = {1, 1, 1};
// System noise covariance matrix
static float R[3] = {1, 1, 1};
// Measurement noise covariance matrix
static float T = 0.002f;
// Discrete period

// Magnetometer calibration parameters (example values, need actual calibration)
float mx_max = 30.0f, mx_min = -24.9f;
float my_max = 25.2f, my_min = -30.15f;
float mz_max = 33.3f, mz_min = -23.25f;

// Kalman filter attitude solution function with magnetometer calibration for yaw
void kalman_filter_attitude_solution_calibyaw(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz)
{
    // Step 1: Calculate system input vector (Euler angle derivatives)
    Uk[0] = gx + sin(Xk[0]) * tan(Xk[1]) * gy + cos(Xk[0]) * tan(Xk[1]) * gz;
    Uk[1] = cos(Xk[0]) * gy - sin(Xk[0]) * gz;
    Uk[2] = sin(Xk[0]) * gy / cos(Xk[1]) + cos(Xk[0]) * gz / cos(Xk[1]);

    // Step 2: A priori estimation
    Xk_[0] = Xk[0] + T * Uk[0];
    Xk_[1] = Xk[1] + T * Uk[1];
    Xk_[2] = Xk[2] + T * Uk[2];

    // Yaw angle range constraint (-π~π)
    if (Xk_[2] > 3.141f) Xk_[2] -= 2 * 3.141f;
    else if (Xk_[2] < -3.141f) Xk_[2] += 2 * 3.141f;

    // Step 3: Calculate a priori error covariance matrix
    Pk_[0] = Pk[0] + Q[0];
    Pk_[1] = Pk[1] + Q[1];
    Pk_[2] = Pk[2] + Q[2];

    // Step 4: Calculate Kalman gain
    K[0] = Pk_[0] / (Pk_[0] + R[0]);
    K[1] = Pk_[1] / (Pk_[1] + R[1]);
    K[2] = Pk_[2] / (Pk_[2] + R[2]);

    // Step 5: Magnetometer data calibration and yaw angle calculation
    float mbx, mby, mbz;
    float mZx, mZy, mZz;

    mbx = (mx - (mx_max + mx_min) / 2.f) / ((mx_max - mx_min) / 2.f);
    mby = (my - (my_max + my_min) / 2.f) / ((my_max - my_min) / 2.f);
    mbz = (mz - (mz_max + mz_min) / 2.f) / ((mz_max - mz_min) / 2.f);

    mZx = cos(Xk[1]) * mbx + sin(Xk[1]) * sin(Xk[0]) * mby + sin(Xk[1]) * cos(Xk[0]) * mbz;
    mZy = cos(Xk[0]) * mby - sin(Xk[0]) * mbz;
    mZz = -sin(Xk[1]) * mbx + cos(Xk[1]) * sin(Xk[0]) * mby + cos(Xk[1]) * cos(Xk[0]) * mbz;

    // Step 6: Get measurement data
    Zk[0] = atan(ay / az);
    Zk[1] = -atan(ax / (sqrt(ay * ay + az * az)));
    Zk[2] = atan2(mZy, mZx);

    // Step 7: A posteriori estimation
    Xk[0] = (1 - K[0]) * Xk_[0] + K[0] * Zk[0];
    Xk[1] = (1 - K[1]) * Xk_[1] + K[1] * Zk[1];
    Xk[2] = (1 - K[2]) * Xk_[2] + K[2] * Zk[2];

    // Step 8: Update a posteriori error covariance matrix
    Pk[0] = (1 - K[0]) * Pk_[0];
    Pk[1] = (1 - K[1]) * Pk_[1];
    Pk[2] = (1 - K[2]) * Pk_[2];

    // Convert to degrees
    roll = Xk[0] / 3.141f * 180.f;
    pitch = Xk[1] / 3.141f * 180.f;
    yaw = Xk[2] / 3.141f * 180.f;
}

总结

引入磁力计的卡尔曼滤波姿态解算与无磁力计方案的区别:

  • 无磁力计方案以上电时的航向为零度,输出相对航向角;
  • 带磁力计方案基于地球磁场输出绝对航向角。

博客中基于卡尔曼滤波器的姿态解算实现代码,主要侧重于算法推导过程的具象化呈现,尚未针对工程应用场景进行深度优化,使用者可结合具体的硬件平台与实际需求开展针对性的性能优化工作。

相较于 Mahony 互补滤波等其他惯性导航姿态解算算法,卡尔曼滤波器通过多步骤的矩阵运算与误差协方差迭代完成数据融合,其算法逻辑复杂度更高,在实际运行过程中对硬件算力资源的占用量相对较大,导致其在部分资源受限场景下的运行效率略低。


via:

同步定位与地图构建(SLAM)技术为移动机器人或自主载具在未知空间中的导航提供了核心支撑。借助该技术,机器人能够在探索过程中实时构建环境地图并确定自身位置。典型的SLAM流程涵盖传感器数据采集、数据处理、状态估计及地图生成等环节,其核心挑战在于有效处理定位与环境建模中的各类不确定性。 Matlab作为工程计与数据可视化领域广泛应用的数学软件,具备丰富的内置函数与专用工具箱,尤其适用于法开发与仿真验证。在SLAM研究方面,Matlab可用于模拟传感器输出、实现定位建图法,并进行系统性能评估。其仿真环境能显著降低实验成本,加速法开发与验证周期。 本次“SLAM-基于Matlab的同步定位与建图仿真实践项目”通过Matlab平台完整再现了SLAM的关键流程,包括数据采集、滤波估计、特征提取、数据关联与地图更新等核心模块。该项目不仅呈现了SLAM技术的实际应用场景,更为机器人导航与自主移动领域的研究人员提供了系统的实践参考。 项目涉及的核心技术要点主要包括:传感器模型(如激光雷达与视觉传感器)的建立与应用、特征匹配与数据关联方法、滤波器设计(如扩展卡尔曼滤波与粒子滤波)、图优化框架(如GTSAM与Ceres Solver)以及路径规划与避障策略。通过项目实践,参与者可深入掌握SLAM法的实现原理,并提升相关法的设计与调试能力。 该项目同时注重理论向工程实践的转化,为机器人技术领域的学习者提供了宝贵的实操经验。Matlab仿真环境将复杂的技术问题可视化与可操作化,显著降低了学习门槛,提升了学习效率与质量。 实践过程中,学习者将直面SLAM技术在实际应用中遇到的典型问题,包括传感器误差补偿、动态环境下的建图定位挑战以及计资源优化等。这些问题的决对推动SLAM技术的产业化应用具有重要价值。 SLAM技术在工业自动化、服务机器人、自动驾驶及无人机等领域的应用前景广阔。掌握该项技术不仅有助于提升个人专业能力,也为相关行业的技术发展提供了重要支撑。随着技术进步与应用场景的持续拓展,SLAM技术的重要性将日益凸显。 本实践项目作为综合性学习资源,为机器人技术领域的专业人员提供了深入研习SLAM技术的实践平台。通过Matlab这一高效工具,参与者能够直观理SLAM的实现过程,掌握关键法,并将理论知识系统应用于实际工程问题的决之中。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值