注:本文为 “卡尔曼滤波器 · 姿态解算” 相关合辑。
略作重排,如有内容异常,请看原文。
浅谈基于卡尔曼滤波器的姿态解算(一)
争取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+1−HT+RPk+1−HT
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+1−Hx^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=(I−Kk+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=T⋅I3= 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+1−HT+RPk+1−HT(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+1−Hx^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=(I−Kk+1H)Pk+1−(10)
总结
基于卡尔曼滤波器的 IMU 姿态解算流程可概括为:
- 读取 IMU 的三轴角速度与三轴加速度数据;
- 通过公式(1)计算欧拉角导数;
- 通过公式(5)计算先验估计,公式(6)计算先验误差协方差矩阵;
- 通过公式(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ϕkqk−sinϕ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+1−pθ,k+1−pψ,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+1−Hx^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=(1−k1,k+1)ϕ^k+1−+k1,k+1ϕm,k+1=(1−k2,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=(1−k1,k+1)pϕ,k+1−=(1−k2,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θ010−sinθ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 =RY−1(θ)RX−1(ϕ) 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*} RY−1(θ)RX−1(ϕ)=RYT(θ)= cosθ0−sinθ010sinθ0cosθ =RXT(ϕ)= 1000cosϕsinϕ0−sinϕ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θ0−sinθ010sinθ0cosθ 1000cosϕsinϕ0−sinϕ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θ0−Sθ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,x−mmin,x)/2mraw,x−(mmax,x+mmin,x)/2mb,y=(mmax,y−mmin,y)/2mraw,y−(mmax,y+mmin,y)/2mb,z=(mmax,z−mmin,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,y−Sϕ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ϕkqk−Sϕ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=(1−k1,k+1)ϕ^k+1−+k1,k+1ϕm,k+1θ^k+1=(1−k2,k+1)θ^k+1−+k2,k+1θm,k+1ψ^k+1=(1−k3,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=(1−k1,k+1)Pϕ,k+1−Pθ,k+1=(1−k2,k+1)Pθ,k+1−Pψ,k+1=(1−k3,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:
-
浅谈基于卡尔曼滤波器的姿态解算(一)_卡尔曼滤波姿态解算-优快云博客
https://blog.youkuaiyun.com/m0_37835056/article/details/137972765 -
浅谈基于卡尔曼滤波器的姿态解算(二)——代码实现及效果演示_卡尔曼姿态解算代码-优快云博客
https://blog.youkuaiyun.com/m0_37835056/article/details/138134235 -
浅谈基于卡尔曼滤波器的姿态解算(三)——磁力计标定航向角_航向角卡尔曼滤波-优快云博客
https://blog.youkuaiyun.com/m0_37835056/article/details/138168711
10万+

被折叠的 条评论
为什么被折叠?



