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



前言

上一篇博客对基于卡尔曼滤波器的姿态解算进行了一定程度的公式推导,这篇博客将进行算法公式的代码实现,并对姿态解算效果进行效果演示。
考虑到有一些单片机上无法直接进行矩阵运算,因此本篇博客的主要内容之一就是将矩阵运算拆解成方程组形式。

公式解析

  • s t e p 1 step1 step1:获取欧拉角的导数
    [ ϕ ˙ θ ˙ ψ ˙ ] = [ 1 S ϕ T θ C ϕ T θ 0 C ϕ − S ϕ 0 S ϕ / C θ C ϕ / C θ ] [ p q r ] \begin{array}{ll} {\left[\begin{array}{c} \dot{\boldsymbol{\phi}} \\ \dot{\boldsymbol{\theta}} \\ \dot{\boldsymbol{\psi}} \end{array}\right]=\left[\begin{array}{ccc} 1 & S_{\phi} T_{\theta} & C_{\phi} T_{\theta} \\ 0 & C_{\phi} & -S_{\phi} \\ 0 & S_{\phi} / C_{\theta} & C_{\phi} / C_{\theta} \end{array}\right]\left[\begin{array}{c} p \\ q \\ r \end{array}\right]} \end{array} ϕ˙θ˙ψ˙ = 100SϕTθCϕSϕ/CθCϕTθSϕCϕ/Cθ pqr
    其中, [ p q r ] \begin{bmatrix}p\\q\\r\end{bmatrix} pqr 是陀螺仪角速度数据。
    整理成离散形式的方程组为:
    { ϕ 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 (1) \left\{ \begin{aligned} & \dot{\boldsymbol{\phi_{k}}} = p_{k}+S_{\phi_{k}}T_{\theta_{k}}q_{k}+C_{\phi_{k}}T_{\theta_{k}}r_{k}\\ & \dot{\boldsymbol{\theta_{k}}} = C_{\phi_{k}}q_{k}-S_{\phi_{k}}r_{k}\\ & \dot{\boldsymbol{\psi_{k}}}= S_{\phi_{k}}q_{k}/C_{\theta_{k}}+C_{\phi_{k}}r_{k}/C_{\theta_{k}}\\ \end{aligned} \right. \tag{1} ϕk˙=pk+SϕkTθkqk+CϕkTθkrkθk˙=CϕkqkSϕkrkψk˙=Sϕkqk/Cθk+Cϕkrk/Cθk(1)

  • s t e p 2 step2 step2:先验估计
    [ ϕ ^ 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}\boldsymbol{\hat{\phi}_{k+1}^{-}} \\ \boldsymbol{\hat{\theta}_{k+1}^{-}} \\ \boldsymbol{\hat{\psi}_{k+1}^{-}}\end{bmatrix} \ =\begin{bmatrix}1 & 0&0 \\ 0&1&0 \\ 0&0&1\end{bmatrix}\ \begin{bmatrix}\boldsymbol{\hat{\phi}_{k}} \\ \boldsymbol{\hat{\theta}_{k}} \\ \boldsymbol{\hat{\psi}_{k}}\end{bmatrix}\ +\begin{bmatrix}T & 0&0 \\ 0&T&0 \\ 0&0&T\end{bmatrix}\ \begin{bmatrix}\dot{\boldsymbol{\phi_{k}}} \\ \dot{\boldsymbol{\theta_{k}}} \\ \dot{\boldsymbol{\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} & \boldsymbol{\hat{\phi}_{k+1}^{-}} = \boldsymbol{\hat{\phi}_{k}} + T\dot{\boldsymbol{\phi_{k}}}\\ &\boldsymbol{\hat{\theta}_{k+1}^{-}} = \boldsymbol{\hat{\theta}_{k}} + T\dot{\boldsymbol{\theta_{k}}} \\ &\boldsymbol{\hat{\psi}_{k+1}^{-}}=\boldsymbol{\hat{\psi}_{k}}+T\dot{\boldsymbol{\psi_{k}}}\\ \end{aligned} \right. \tag{2} ϕ^k+1=ϕ^k+Tϕk˙θ^k+1=θ^k+Tθk˙ψ^k+1=ψ^k+Tψk˙(2)

  • s t e p 3 step3 step3:先验估计误差协方差矩阵(矩阵A是单位矩阵
    P k + 1 − = A P k A T + Q P_{k+1}^{-}=A P_{k} A^{T}+Q Pk+1=APkAT+Q
    令系统噪声协方差矩阵 Q = [ q ϕ 0 0 0 q θ 0 0 0 q ψ ] Q=\begin{bmatrix}q_{\phi}&0&0\\0&q_{\theta}&0\\0&0&q_{\psi}\end{bmatrix} Q= qϕ000qθ000qψ ,先验估计误差协方差矩阵为 P k − = [ p ϕ , k − 0 0 0 p θ , k − 0 0 0 p ψ , k − ] P_{k}^{-}=\begin{bmatrix}p_{\phi,k}^{-}&0&0\\0&p_{\theta,k}^{-}&0\\0&0&p_{\psi,k}^{-}\end{bmatrix} Pk= pϕ,k000pθ,k000pψ,k ,后验估计误差协方差矩阵为 P k = [ p ϕ , k 0 0 0 p θ , k 0 0 0 p ψ , k ] P_{k}=\begin{bmatrix}p_{\phi,k}&0&0\\0&p_{\theta,k}&0\\0&0&p_{\psi,k}\end{bmatrix} Pk= pϕ,k000pθ,k000pψ,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+qϕpθ,k+1=pθ,k+qθpψ,k+1=pψ,k+qψ(3)

  • s t e p 4 step4 step4:卡尔曼增益矩阵计算(矩阵除法即乘以矩阵的逆
    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
    其中, 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 = [ r ϕ 0 0 0 r θ 0 0 0 r ψ ] R=\begin{bmatrix}r_{\phi}&0&0\\0&r_{\theta}&0\\0&0&r_{\psi}\end{bmatrix} R= rϕ000rθ000rψ ,令卡尔曼增益矩阵 K k = [ k 1 , k 0 0 0 k 2 , k 0 0 0 k 3 , k ] K_{k}=\begin{bmatrix}k_{1,k}&0&0\\0&k_{2,k}&0\\0&0&k_{3,k}\end{bmatrix} Kk= k1,k000k2,k000k3,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+1=pϕ,k+1/(pϕ,k+1+rϕ)k2,k+1=pθ,k+1/(pθ,k+1+rθ)k3,k+1=0(4)

  • s t e p 5 step5 step5:获取欧拉角测量值
    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 = a t a n ( a y / a z ) θ m , k = − a t a n ( a x / a y 2 + a z 2 ) ψ m , k = 0 (5) \left\{ \begin{aligned} & \phi_{m,k}=atan(a_{y}/a_{z})\\ & \theta_{m,k}=-atan(a_{x}/\sqrt{a_{y}^{2}+a_{z}^{2}})\\ & \psi_{m,k}=0\\ \end{aligned} \right. \tag{5} ϕm,k=atan(ay/az)θm,k=atan(ax/ay2+az2 )ψm,k=0(5)
    其中, [ a x a y a z ] \begin{bmatrix}a_{x}\\a_{y}\\a_{z}\end{bmatrix} axayaz 是三轴加速度计数据。

  • s t e p 6 step6 step6:后验估计计算
    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}\boldsymbol{\hat{\phi}_{k+1}}\\\boldsymbol{\hat{\theta}_{k+1}}\\\boldsymbol{\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} & \boldsymbol{\hat{\phi}_{k+1}}=(1-k_{1,k+1})\boldsymbol{\hat{\phi}_{k+1}^{-}}+k_{1,k+1}\phi_{m,k+1}\\ & \boldsymbol{\hat{\theta}_{k+1}}=(1-k_{2,k+1})\boldsymbol{\hat{\theta}_{k+1}^{-}}+k_{2,k+1}\theta_{m,k+1}\\ & \boldsymbol{\hat{\psi}_{k+1}}=\boldsymbol{\hat{\psi}_{k+1}^{-}}\\ \end{aligned} \right. \tag{6} ϕ^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=ψ^k+1(6)
    从这组方程里可以看出航向角漂移问题的来源。

  • s t e p 7 step7 step7:后验估计误差协方差矩阵
    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
    可以得到:
    { 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+1=(1k1,k+1)pϕ,k+1pθ,k+1=(1k2,k+1)pθ,k+1pψ,k+1=pψ,k+1(7)

代码实现

  • 函数接口说明
    函数输入参数:
    g x , g y , g z gx,gy,gz gx,gy,gz:陀螺仪角速度数据,单位: r a d / s 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; 
//euro angle
static float Xk_[3] = {0};  
//Prior estimation
static float Xk[3] = {0};
//Posterior estimation
static float Uk[3] = {0};
//system input
static float Zk[3] = {0};
//measure status
static float Pk[3] = {1,1,1};
//Posteriori estimation error covariance
static float Pk_[3] = {0};
//Prior estimation error covariance
static float K[3] = {0};
//kalman gain
static float Q[3] = {1,1,1};
//System noise covariance
static float R[3] = {1,1,1};
//Measure noise covariance
static float T = 0.002f;
//Discrete time

//attitude solution by kalman filter
void kalman_filter_attitude_solution(float gx,float gy,float gz,float ax,float ay,float az)
{
	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]);
	//step1 - system input
	
	Xk_[0] = Xk[0] + T * Uk[0];
	Xk_[1] = Xk[1] + T * Uk[1];
	Xk_[2] = Xk[2] + T * Uk[2];
	//step2 - Prior estimation
	
	Pk_[0] = Pk[0] + Q[0];
	Pk_[1] = Pk[1] + Q[1];
	Pk_[2] = Pk[2] + Q[2];
	//step3 - Prior estimation error covariance
	
	K[0] = Pk_[0] / (Pk_[0] + R[0]);
	K[1] = Pk_[1] / (Pk_[1] + R[1]);
	K[2] = 0;
	//step4 - kalman gain
	
	Zk[0] = atan( ay / az );
	Zk[1] = -atan( ax / (sqrt( ay * ay + az * az )));
	Zk[2] = 0;
	//step5 - measure data
	
	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];
	//step6 - Posterior estimation
	
	Pk[0] = (1 - K[0]) * Pk_[0];
	Pk[1] = (1 - K[1]) * Pk_[1];
	Pk[2] = Pk_[2];
	//step7 - Posteriori estimation error covariance
	
	
	roll = Xk[0] / 3.141f * 180.f;
	pitch = Xk[1] / 3.141f * 180.f;
	yaw = Xk[2] / 3.141f * 180.f;
	//calculate the angle,unit: degree
}

效果演示

本博客采用匿名飞控板 + 匿名上位机来展示姿态解算效果不是广告,刚好手上有一块。

姿态解算

总结

  • 基于卡尔曼滤波器的姿态解算能够获得准确的姿态角,但是由于测量数据无法对航向角yaw进行校正,导致航向角在一定时间累积误差后会出现漂移问题。这种漂移问题在振动大,电磁干扰大的环境下将更为明显。
  • 可以通过初始化时计算平均偏移量来做一定的偏置补偿,但仅能减缓漂移的速度,无法完全抑制。
  • 下一期博客的内容,将针对航向角漂移问题,引入磁力计传感来解决。
    若有需要源代码工程可私信我
  • 15
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

争取35岁退休

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值