Kalman.cpp
上传用户:wyp_nj
上传日期:2022-05-03
资源大小:484k
文件大小:4k
源码类别:

GPS编程

开发平台:

Visual C++

  1. #include "DR_GPS_EKF.h"
  2. // 本程序实现matrix类
  3. // 对matrix类的定义
  4. #include "matrix.h"
  5. #include <stdio.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include <iostream.h>
  9. //将GPS和DR数据进行Kalman滤波,参数是:
  10. //dr导航数组指针,gps导航数组指针,ekf导航数组指针,初始经纬度
  11. void EKF(double *pdr,double *pgps,double *pekf,
  12.  double lon0,double lat0) 
  13. {
  14.     double egps=pgps[0];  //将gps这一时刻的东向位置赋予变量egps
  15.     double ngps=pgps[1];  //将gps这一时刻的北向位置赋予变量ngps
  16.     double edr=pdr[0];    //将dr这一时刻的东向位置赋予变量edr
  17.     double ndr=pdr[1];    //将dr这一时刻的北向位置赋予变量ndr
  18.     double vedr=pdr[2];   //将dr这一时刻的东向速度赋予变量vedr
  19.     double vndr=pdr[3];   //将dr这一时刻的北向速度赋予变量vndr
  20.     double aedr=pdr[4];   //将dr这一时刻的东向加速度赋予变量aedr
  21.     double andr=pdr[5];   //将dr这一时刻的北向加速度赋予变量andr
  22. double yaw=pdr[6];    //将dr这一时刻的航向角赋予变量yaw
  23. double dy=pdr[7];     //将dr这一时刻的航向角速率赋予变量dy
  24. double e,n,lon,lat;
  25.     double detT=10;       //将A阵离散化的时间
  26. double t_ae=0.1,t_an=0.1;//车辆东北向机动加速度变化率的相关时间常数
  27.     double val;           //定义中间变量          
  28. double e_ep,n_ep,v_ep,v_np,a_ep,a_np;//定义中间变量 
  29. //将下面的向量和矩阵都定义为matrix类的对象
  30.     static matrix X(6,1); //状态向量,定义X阵(XX阵)为matrix类的对象
  31.     static matrix P(6,6); //估计误差方差阵,定义P阵(PP阵)为matrix类的对象
  32.     matrix X1(6,1),Z(3,1);//状态一步预测阵和观测阵
  33. matrix h_x(3,1);      //观测方程里非线性函数对x求导
  34. matrix P1(6,6);       //一步预测方差阵
  35.     matrix R(3,3);        //系统观测噪声方差阵
  36. matrix Q(6,6);        //系统过程噪声方差阵
  37. matrix A(6,6);        //状态阵
  38. matrix F(6,6);        //状态阵A的离散化
  39. matrix H(3,6);        //观测阵
  40. matrix K(6,3);        //滤波增益阵
  41. static char define='N';//状态向量和估计误差方差阵的初始定义标识
  42. if (define=='N')     //若X阵和P阵没有初始化则对其进行初始化
  43. {
  44. X=0;
  45. X.set(0,0,edr);X.set(1,0,ndr);X.set(2,0,vedr);
  46. X.set(3,0,vndr);X.set(4,0,aedr);X.set(5,0,andr);
  47. P=0;
  48. P.set(0,0,0.1);P.set(1,1,0.1);P.set(2,2,0.1*0.1);
  49. P.set(3,3,0.1*0.1);P.set(4,4,0.01*0.01);P.set(5,5,0.01*0.01);
  50. define='Y';
  51. cout<<"X,P的初始化:"<<define<<"n";
  52. }
  53. //R,Q,A,H的初始化
  54. R=0;
  55. R.set(0,0,10);R.set(1,1,10);R.set(2,2,1);
  56.     Q=0;
  57. Q.set(0,0,10);Q.set(1,1,10);Q.set(2,2,1);
  58. Q.set(3,3,1);Q.set(4,4,0.1);Q.set(5,5,0.1);
  59. A=0;
  60.     A.set(0,2,1);A.set(1,3,1);A.set(2,4,1);
  61. A.set(3,5,1);A.set(4,4,-t_ae);A.set(5,5,-t_an);
  62.     H=0;
  63.  
  64. F=unit(6)+detT*A+detT*detT*A*A/2; //状态矩阵A的离散化
  65.     //观测向量:GPS东北向位置、角速率陀螺的输出以及dr在一个采样周期的距离
  66. Z.set(0,0,egps); //GPS东向位置
  67.     Z.set(1,0,ngps);        //GPS北向位置
  68.     Z.set(2,0,dy);          //DR航向角速率陀螺的输出  
  69.     //Z.set(3,0,s);         //里程计在一个采样周期的距离
  70. X1=F*X;                 //状态一步预测向量
  71. //将状态一步预测向量对应值分别赋于中间变量
  72.     e_ep=X1(0,0);           
  73.     n_ep=X1(1,0);
  74.     v_ep=X1(2,0);
  75.     v_np=X1(3,0);
  76.     a_ep=X1(4,0);
  77.     a_np=X1(5,0);
  78.     //用状态一步预测向量计算得到Kalman滤波的观测阵H
  79. H.set(0,0,1);
  80. H.set(1,1,1);
  81. val=(a_np*v_ep*v_ep-2*v_ep*v_np*a_ep-a_np*v_np*v_np)/pow((v_ep*v_ep+v_np*v_np),2);
  82.     H.set(2,2,val);
  83. val=(a_ep*v_ep*v_ep+2*v_ep*v_np*a_np-a_ep*v_np*v_np)/pow((v_ep*v_ep+v_np*v_np),2);
  84.     H.set(2,3,val);
  85. val=v_np/(v_ep*v_ep+v_np*v_np);
  86.     H.set(2,4,val);
  87. val=-v_ep/(v_ep*v_ep+v_np*v_np);
  88.     H.set(2,5,val);
  89. //val=dt*v_ep/sqrt(v_ep*v_ep+v_np*v_np);
  90.     //H.set(3,2,val);
  91. //val=dt*v_np/sqrt(v_ep*v_ep+v_np*v_np);
  92.     //H.set(3,3,val);
  93.     P1= F*P*F.t() + Q;            //求一步预测误差方差阵
  94.     K = P1*H.t()*~(H*P1*H.t()+R); //求滤波增益阵
  95. //h2_xPre是非线性观测矩阵H的雅可比矩阵,
  96. //其中使用的速度、加速度都是一步预测估计值
  97.     h_x.set(0,0,e_ep);
  98. h_x.set(1,0,n_ep);
  99. val=dt*(v_np*a_ep-v_ep*a_np)/(v_ep*v_ep+v_np*v_np);
  100. h_x.set(2,0,val);
  101. //val=dt*sqrt(v_ep*v_ep+v_np*v_np);
  102. //h_x.set(3,0,val);
  103.     X = X1 + K*(Z-h_x);          //状态估计
  104.     P= (unit(6)-K*H)*P1;         //估计误差方差阵
  105. e=X(0,0);n=X(1,0);           //更新导航数据
  106. lat=(n/Re+lat0)*180/pi;          //纬度(度)
  107. lon=(e/Re/cos(lat)+lon0)*180/pi; //经度(度)
  108. //用Kalman滤波后的导航数据修正DR的导航数据
  109. //pdr[0]=e;pdr[1]=n;              //东北向位置修正
  110. //pdr[2]=ve;pdr[3]=vn;            //东北向速修正
  111.     //修改指针pekf的内容(位置,速度,加速度,经纬度,航向角)
  112. for (int i=0;i<6;i++)
  113. pekf[i]=X(i,0);             //pekf[]的前6个数与X一样
  114. pekf[i]=lat;pekf[i+1]=lon;pekf[i+2]=yaw*180/pi;//后三个数为经纬度和航向角
  115. }