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



前言

  • 第一篇博客对基于卡尔曼滤波器的姿态解算进行了原理简述和公式推导,传送门
  • 第二篇博客在第一篇的基础上实现代码并观察解算效果,传送门
  • 在第二篇博客中,提到了由于重力加速度数据无法对航向角yaw进行标定,导致陀螺仪数据噪声会在姿态解算过程中累积误差,使航向角yaw漂移。
  • 本博客将引入磁力计传感器,来对航向角yaw进行标定,并介绍相关原理和公式推导过程。

磁力计传感器

原理

磁力计又称电子罗盘,其与指南针原理相似,都是通过地球磁场信息来确定惯性系方向。
在这里插入图片描述
磁感线从地磁南极指向地磁北极,而磁力计会将经过其的磁感线分解为机体系 X Y Z XYZ XYZ三个轴的分量。利用这组数据,与加速度计类似的原理,用来对航向角进行标定,从而获得准确且稳定的航向信息,最终解决航向角漂移问题。

问题

磁力计本身是由三组霍尔元件堆叠而成,因此由于设计或加工等问题,常常会出现磁力计输出数据不对称的问题。

  • 地球磁场向量在惯性系 中是一个固定的向量,因此当机体系转动时,在理想情况下,磁力计三轴数据应始终位于一个中心点在坐标原点球面上
  • 实际上磁力计三轴数据输出产生的面是一个中心点不在坐标原点椭球面,并且根据不同的芯片情况和工况环境,产生的椭球面不同。
    因此在进行数据读取后需要对三轴磁力计数据进行归一化处理,后续详述。

磁力计标定航向角原理

惯性系定义

通常,惯性系的 X Y Z XYZ XYZ轴分别对应北东天,即惯性系 X X X轴指向北, Y Y Y轴指向东, Z Z Z轴指向天。因此,地球磁感线方向向量始终在惯性系平面 X O Z XOZ XOZ磁感线始终由南指向北,其在 X X X轴和 Z Z Z轴的分量比例取决于在地球的位置:

  • 若在地球赤道附近,则 X X X轴占比较大;
  • 若在南北极附近,则 Z Z Z轴占比较大;

综上,通常定义正北方向为零度航向角,即 y a w = 0 yaw=0 yaw=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 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) \boldsymbol{R}=\boldsymbol{R_{X}(\phi)}\boldsymbol{R_{Y}(\theta)}\boldsymbol{R_{Z}(\psi)}=\left[\begin{array}{ccc} 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{array}\right] \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 ( ψ ) = [ c o s ψ s i n ψ 0 − s i n ψ c o s ψ 0 0 0 1 ] (2) \boldsymbol{R_{Z}(\psi)}= \begin{bmatrix} cos\boldsymbol{\psi} & sin\boldsymbol{\psi} &0\\ -sin\boldsymbol{\psi} &cos\boldsymbol{\psi} &0 \\ 0 &0 &1\end{bmatrix} \tag{2} RZ(ψ)= cosψsinψ0sinψcosψ0001 (2)
R Y ( θ ) = [ c o s θ 0 − s i n θ 0 1 0 s i n θ 0 c o s θ ] (3) \boldsymbol{R_{Y}(\theta)}= \begin{bmatrix} cos\boldsymbol{\theta}& 0&-sin\boldsymbol{\theta}\\ 0 &1 &0 \\ sin\boldsymbol{\theta} &0 &cos\boldsymbol{\theta}\end{bmatrix} \tag{3} RY(θ)= cosθ0sinθ010sinθ0cosθ (3)
R X ( ϕ ) = [ 1 0 0 0 c o s ϕ s i n ϕ 0 − s i n ϕ c o s ϕ ] (4) \boldsymbol{R_{X}(\phi)}= \begin{bmatrix} 1 &0 &0\\ 0&cos\boldsymbol{\phi}& sin\boldsymbol{\phi}\\ 0 &-sin\boldsymbol{\phi} &cos\boldsymbol{\phi}\end{bmatrix} \tag{4} RX(ϕ)= 1000cosϕsinϕ0sinϕcosϕ (4)
好了,有了上面这些前提,我要开始表演(公式推导)了
根据上述描述,满足以下关系:
[ 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{bmatrix}m_{b,x}\\m_{b,y}\\m_{b,z}\end{bmatrix} = \boldsymbol{R}\begin{bmatrix}m_{e,x}\\0\\m_{e,z}\end{bmatrix}=\boldsymbol{R_{X}(\phi)}\boldsymbol{R_{Y}(\theta)}\boldsymbol{R_{Z}(\psi)}\begin{bmatrix}m_{e,x}\\0\\m_{e,z}\end{bmatrix} \tag{5} mb,xmb,ymb,z =R me,x0me,z =RX(ϕ)RY(θ)RZ(ψ) me,x0me,z (5)
由于坐标系是按顺序绕轴转动的,而此时磁力计数据的目标是为了解算得到航向角 ψ \boldsymbol{\psi} ψ,因此我们如果能得到惯性系下磁力数据绕 Z Z Z轴转动 ψ \boldsymbol{\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{bmatrix}m_{Z,x}\\m_{Z,y}\\m_{Z,z}\end{bmatrix} =\boldsymbol{R_{Z}(\psi)}\begin{bmatrix}m_{e,x}\\0\\m_{e,z}\end{bmatrix} \tag{6} mZ,xmZ,ymZ,z =RZ(ψ) me,x0me,z (6)
根据坐标系变换的几何关系,可以得到以下关系,
ψ = a t a n ( m Z , x / m Z , y ) (7) \boldsymbol{\psi}=atan(m_{Z,x}/m_{Z,y}) \tag{7} ψ=atan(mZ,x/mZ,y)(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 ] (8) \begin{bmatrix}m_{b,x}\\m_{b,y}\\m_{b,z}\end{bmatrix} =\boldsymbol{R_{X}(\phi)}\boldsymbol{R_{Y}(\theta)}\begin{bmatrix}m_{Z,x}\\m_{Z,y}\\m_{Z,z}\end{bmatrix} \tag{8} 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 ] (9) \begin{bmatrix}m_{Z,x}\\m_{Z,y}\\m_{Z,z}\end{bmatrix}=\boldsymbol{R_{Y}^{-1}(\theta)}\boldsymbol{R_{X}^{-1}(\phi)}\begin{bmatrix}m_{b,x}\\m_{b,y}\\m_{b,z}\end{bmatrix} \tag{9} mZ,xmZ,ymZ,z =RY1(θ)RX1(ϕ) mb,xmb,ymb,z (9)
公式3公式4 所得这几个旋转变换矩阵都是正交矩阵
R Y − 1 ( θ ) = R Y T ( θ ) = [ c o s θ 0 s i n θ 0 1 0 − s i n θ 0 c o s θ ] (10) \boldsymbol{R_{Y}^{-1}(\theta)}=\boldsymbol{R_{Y}^{T}(\theta)}=\begin{bmatrix} cos\boldsymbol{\theta}& 0&sin\boldsymbol{\theta}\\ 0 &1 &0 \\ -sin\boldsymbol{\theta} &0 &cos\boldsymbol{\theta}\end{bmatrix} \tag{10} RY1(θ)=RYT(θ)= cosθ0sinθ010sinθ0cosθ (10)
R X − 1 ( ϕ ) = R X T ( ϕ ) = [ 1 0 0 0 c o s ϕ − s i n ϕ 0 s i n ϕ c o s ϕ ] (11) \boldsymbol{R_{X}^{-1}(\phi)}=\boldsymbol{R_{X}^{T}(\phi)}=\begin{bmatrix} 1 &0 &0\\ 0&cos\boldsymbol{\phi}& -sin\boldsymbol{\phi}\\ 0 &sin\boldsymbol{\phi} &cos\boldsymbol{\phi}\end{bmatrix} \tag{11} RX1(ϕ)=RXT(ϕ)= 1000cosϕsinϕ0sinϕcosϕ (11)
公式10公式11 代入 公式9,得到:
[ m Z , x m Z , y m Z , z ] = [ c o s θ 0 s i n θ 0 1 0 − s i n θ 0 c o s θ ] [ 1 0 0 0 c o s ϕ − s i n ϕ 0 s i n ϕ c o s ϕ ] [ m b , x m b , y m b , z ] (12) \begin{bmatrix}m_{Z,x}\\m_{Z,y}\\m_{Z,z}\end{bmatrix}=\begin{bmatrix} cos\boldsymbol{\theta}& 0&sin\boldsymbol{\theta}\\ 0 &1 &0 \\ -sin\boldsymbol{\theta} &0 &cos\boldsymbol{\theta}\end{bmatrix} \begin{bmatrix} 1 &0 &0\\ 0&cos\boldsymbol{\phi}& -sin\boldsymbol{\phi}\\ 0 &sin\boldsymbol{\phi} &cos\boldsymbol{\phi}\end{bmatrix} \begin{bmatrix}m_{b,x}\\m_{b,y}\\m_{b,z}\end{bmatrix} \tag{12} mZ,xmZ,ymZ,z = cosθ0sinθ010sinθ0cosθ 1000cosϕsinϕ0sinϕcosϕ mb,xmb,ymb,z (12)
整理为:
[ 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 ] (13) \begin{bmatrix}m_{Z,x}\\m_{Z,y}\\m_{Z,z}\end{bmatrix}=\begin{bmatrix} C_{\boldsymbol{\theta}}& S_{\boldsymbol{\theta}}S_{\boldsymbol{\phi}}&S_{\boldsymbol{\theta}}C_{\boldsymbol{\phi}}\\ 0 &C_{\boldsymbol{\phi}} &-S_{\boldsymbol{\phi}} \\ -S_{\boldsymbol{\theta}} &C_{\boldsymbol{\theta}}S_{\boldsymbol{\phi}} &C_{\boldsymbol{\theta}}C_{\boldsymbol{\phi}}\end{bmatrix} \begin{bmatrix}m_{b,x}\\m_{b,y}\\m_{b,z}\end{bmatrix} \tag{13} mZ,xmZ,ymZ,z = Cθ0SθSθSϕCϕCθSϕSθCϕSϕCθCϕ mb,xmb,ymb,z (13)

代码实现

  • s t e p 1 step1 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 ) \left\{ \begin{aligned} &m_{b,x} = (m_{raw,x} - (m_{max,x}+m_{min,x})/2) / (m_{max,x}-m_{min,x})/2)\\ &m_{b,y} = (m_{raw,y} - (m_{max,y}+m_{min,y})/2) / (m_{max,y}-m_{min,y})/2)\\ &m_{b,z} = (m_{raw,z} - (m_{max,z}+m_{min,z})/2) / (m_{max,z}-m_{min,z})/2)\\ \end{aligned} \right. mb,x=(mraw,x(mmax,x+mmin,x)/2)/(mmax,xmmin,x)/2)mb,y=(mraw,y(mmax,y+mmin,y)/2)/(mmax,ymmin,y)/2)mb,z=(mraw,z(mmax,z+mmin,z)/2)/(mmax,zmmin,z)/2)
  • s t e p 2 step2 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) \left\{ \begin{aligned} & m_{Z,x} = C_{\boldsymbol{\theta}}m_{b,x} + S_{\boldsymbol{\theta}}S_{\boldsymbol{\phi}}m_{b,y}+S_{\boldsymbol{\theta}}C_{\boldsymbol{\phi}}m_{b,z}\\ & m_{Z,y} = C_{\boldsymbol{\phi}}m_{b,y}-S_{\boldsymbol{\phi}}m_{b,z}\\ & m_{Z,z} = -S_{\boldsymbol{\theta}}m_{b,x}+C_{\boldsymbol{\theta}}S_{\boldsymbol{\phi}}m_{b,y}+C_{\boldsymbol{\theta}}C_{\boldsymbol{\phi}}m_{b,z}\\ \end{aligned} \right. \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 = a t a n ( m Z , x / m Z , y ) (15) \psi_{m,k}=atan(m_{Z,x}/m_{Z,y}) \tag{15} ψm,k=atan(mZ,x/mZ,y)(15)
    在上一篇的基础上修改测量状态向量 z k z_{k} zk以及测量矩阵 H H H,即令
    { ϕ 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 = a t a n ( m Z , y / m Z , x ) (16) \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}=atan(m_{Z,y}/m_{Z,x})\\ \end{aligned} \right. \tag{16} ϕm,k=atan(ay/az)θm,k=atan(ax/ay2+az2 )ψ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)
  • s t e p 3 step3 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 \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. ϕ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 ˙ \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. ϕ^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 ψ \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. 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 ψ ) \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}=p_{\psi,k+1}^{-}/(p_{\psi,k+1}^{-}+r_{\psi})\\ \end{aligned} \right. 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 \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}}=(1-k_{3,k+1})\boldsymbol{\hat{\psi}_{k+1}^{-}}+k_{3,k+1}\psi_{m,k+1}\\ \end{aligned} \right. ϕ^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 − \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} = (1-k_{3,k+1})p_{\psi,k+1}^{-}\\ \end{aligned} \right. 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语言实现

  • 函数接口说明
    函数输入参数:
    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:加速度计数据,单位不管;
    m x , m y , m z mx,my,mz mx,my,mz:磁力计数据,单位不管;
    注意:要将三组传感器的坐标系对应上,统一方向。
#include <math.h>
#include <float.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
//float mx_max = FLT_MIN,mx_min = FLT_MAX;
float mx_max = 30.0f,mx_min = -24.9f;
//Maximum and minimum values of magnetometer X-axis
//float my_max = FLT_MIN,my_min = FLT_MAX;
float my_max = 25.2f,my_min = -30.15f;
//Maximum and minimum values of magnetometer Y-axis
//float mz_max = FLT_MIN,mz_min = FLT_MAX;
float mz_max = 33.3f,mz_min = -23.25f;
//Maximum and minimum values of magnetometer Z-axis

//attitude solution by kalman filter
void kalman_filter_attitude_solution_calibyaw(float gx,float gy,float gz,float ax,float ay,float az,float mx,float my,float mz)
{
	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];
	
	if( Xk_[2] > 3.141f ) //if it is greater than PI
	{
		Xk_[2] -= - 3.141f * 2.f;
	}		
	else if( Xk_[2] < -3.141f ) //if it is less than -PI
	{
		Xk_[2] += 3.141f * 2.f;
	}
	
	//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] = Pk_[2] / (Pk_[2] + R[2]);
	//step4 - kalman gain
	
	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;
	//step5 - calculation yaw by magnetometer data
	
	Zk[0] = atan( ay / az );
	Zk[1] = -atan( ax / (sqrt( ay * ay + az * az )));
	Zk[2] = atan2( mZy , mZx );
	//step6 - 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] = (1 - K[2]) * Xk_[2] + K[2] * Zk[2];
	//step6 - Posterior estimation
	
	Pk[0] = (1 - K[0]) * Pk_[0];
	Pk[1] = (1 - K[1]) * Pk_[1];
	Pk[2] = (1 - K[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
}

总结

基于卡尔曼滤波器的姿态解算加入磁力计能够通过地球磁场方向标定航向角,与无磁力计的解算相比,有以下区别:

  • 无磁力计在每次上电时都会以当前位置为0°航向角,即无论以哪个方向上电,解算的航向角yaw均为0,即一个相对的航向信息。
  • 带磁力计的姿态解算,则会在上电后得到一个固定的角度值,即一个绝对的航向信息。

博客中的基于卡尔曼滤波器姿态解算实现代码,更多是为了展示推导信息,因此没有更好的优化的代码实现,读者可以根据实际使用场景来进行优化。
相比于其他的惯性导航姿态解算算法如Mahony姿态解算,基于卡尔曼滤波器计算较为复杂,占用的算力资源较大,使用效率低。`

  • 19
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Mahony算法是一种姿态估计算法,用于利用加速度计和磁力计数据来估计载体的姿态(横滚、俯仰和航向)。该算法的基本思想是将加速度计和磁力计的测量值与陀螺仪测量的速度进行融合,以提高姿态估计的精度和动态性能。 具体的算法流程如下: 1. 初始化姿态估计参数,包括初始四元数、加速度计的偏移量、陀螺仪的偏移量等。 2. 读取加速度计、磁力计和陀螺仪的测量值。 3. 利用加速度计和磁力计的测量值计算出载体的期望重力向量和期望磁场向量。 4. 利用当前的陀螺仪测量值和上一次的姿态估计值,通过积分计算得到当前的姿态估计值。 5. 利用加速度计和磁力计的测量值与当前的姿态估计值进行误差补偿,得到修正后的姿态估计值。 6. 更新姿态估计参数,如偏移量、协方差矩阵等。 7. 重复步骤2至步骤6,以实时更新姿态估计值。 通过将加速度计和磁力计的测量值与陀螺仪的测量值相结合,Mahony算法能够克服陀螺仪的累积误差和加速度计、磁力计的动态响应差的问题,从而提高了姿态估计的精度和系统的动态性能。 参考文献: AHRS的基本思想是,在载体没有平移运动的情况下,通过加速度感知重力分量,可以计算出载体的俯仰和横滚;磁力计可以感知磁北方向,因此可以计算载体的磁北航向;而陀螺仪测量输出载体的旋转速度,通过积分可以计算得到横滚、俯仰、航向增量,但由于陀螺输出值含有误差,采用积分计算,误差会随着时间累积。陀螺仪动态响应特性良好,但计算姿态时会产生累积误差, 磁力计和加速度计测量姿态没有累积误差,但动态响应较差,那么采用加速度计和磁力计的即时输出值对陀螺进行修正,则可以达到优势互补的效果,提高测量精度和系统的动态性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

争取35岁退休

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

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

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

打赏作者

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

抵扣说明:

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

余额充值