ShareIdeas

本博客不再更新,欢迎访问我的github,https://github.com/sunke-github/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  最近事情有点多,忙的有点上火,必需要权衡多个方面.下面结合这个网页中的代码修改的卡尔曼算法,便于多个角度的卡尔曼滤波,程序如下:

定义 的结构体

struct GyroKalman
{    
     float angle,angle_dot,val ;         //外部需要引用的变量
     float P[2][2];                                            
     float Pdot[4];
     float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;
     //const int temp=5;    结构体中不能有const
};

滤波算法:

//-------------------------------------------------------
////-------------------------------------------------------
//-------------------------------------------------------

void init_GyroDKalman(struct GyroKalman *G)
{
        G->P[0][0] = 1;
        G->P[0][1] = 0;
        G->P[1][0] = 0;
        G->P[1][1] = 1;
        G->Pdot[0] = 0;
        G->Pdot[1] = 0;
        G->Pdot[2] = 0;
        G->Pdot[3] = 0;
        G->q_bias=0;
      G->angle_err=0; 
        G->PCt_0=0; 
        G->PCt_1=0; 
      G->E=0;
        G->K_0=0;
        G->K_1=0; 
        G->t_0=0;
        G->t_1=0;
}



//注意:dt的取值为kalman滤波器采样时间;
static const float dt=0.005;
static const char C_0 = 1;
static const float Q_angle=0.001, Q_gyro=0.003, R_angle=0.5;
//-------------------------------------------------------
void Kalman_Filter(float angle_m,struct GyroKalman *gyro_m)            //gyro_m:gyro_measure
{                                                    //传递的参数为弧度    

/* X(K|K-1)=AX(K-1|K-1)+BU(K) 公式 1 */
gyro_m->angle+=(gyro_m->val-gyro_m->q_bias) * dt; /*单位 弧度,弧度/秒 */
/* P(K|K-1)=AP(K-1|K-1)A`+Q 公式 2 对协方差求导,进行线性近似*/
gyro_m->Pdot[0]=Q_angle - gyro_m->P[0][1] - gyro_m->P[1][0];
gyro_m->Pdot[1]=- gyro_m->P[1][1];
gyro_m->Pdot[2]=- gyro_m->P[1][1];
gyro_m->Pdot[3]=Q_gyro;
gyro_m->P[0][0] += gyro_m->Pdot[0] * dt;
gyro_m->P[0][1] += gyro_m->Pdot[1] * dt;
gyro_m->P[1][0] += gyro_m->Pdot[2] * dt;
gyro_m->P[1][1] += gyro_m->Pdot[3] * dt;
gyro_m->angle_err = angle_m - gyro_m->angle;
gyro_m->PCt_0 = C_0 * gyro_m->P[0][0];
gyro_m->PCt_1 = C_0 * gyro_m->P[1][0];
gyro_m->E = R_angle + C_0 * gyro_m->PCt_0; /*E=HP(K|(K-1))H'+R */
gyro_m->K_0 = gyro_m->PCt_0 / gyro_m->E; /*Kg(k)=P(K|(K-1)H'/(HP(K|(K-1))H'+R) 公式 4 */
gyro_m->K_1 = gyro_m->PCt_1 / gyro_m->E;
gyro_m->t_0 = gyro_m->PCt_0;
gyro_m->t_1 = C_0 * gyro_m->P[0][1];
gyro_m->P[0][0] -= gyro_m->K_0 * gyro_m->t_0; //P(K|K)=(I-Kg(K)H)*P(K|(K-1)) 公式 5
gyro_m->P[0][1] -= gyro_m->K_0 * gyro_m->t_1;
gyro_m->P[1][0] -= gyro_m->K_1 * gyro_m->t_0;
gyro_m->P[1][1] -= gyro_m->K_1 * gyro_m->t_1;
/*后验估计 X(k|k)=X(K|K-1)+Kg(k)(Z(k)-HX(K|K-1)) 公式 3 ,Z(K)是K 时刻的测量值也就是代码中的 angle_m */
gyro_m->angle += gyro_m->K_0 * gyro_m->angle_err; 

gyro_m->q_bias+= gyro_m->K_1 * gyro_m->angle_err;

gyro_m->angle_dot = gyro_m->val-gyro_m->q_bias; //这里angle_dot与angle在PID控制中会起到作用

        
}

下面进行一下,简单的移动平均滤波,卡尔曼,互补滤波三种滤波方法. 红为 单陀螺仪 积分数据,黄为卡尔曼滤波,蓝为 互补滤波

有振动情况下,不晃动四轴:

 

由振动不晃动到静止不晃动:

振动,晃动

最终:

总结上面这些曲线,得出结论:卡尔曼在 0漂拟制上与互补滤波相当 ,在转动效果上与 单陀螺仪测量的数据相当,不易受振动的影响.

上位机用的自己写的软件,直观观察卡尔曼是首选的滤波算法,但是目前来看只适合单轴,我本想应用到四轴上来,目前还没有找到较

好的方法与四元数结合起来.

 

最左为滑动平均滤波,已经不知道漂到哪里去了,中间是卡尔曼滤波,反应较快,最右则是互补滤波,反应有点迟缓,易受振动影响.

博客为本人所写,转载请表明出处,卡尔曼滤波器之我见(完善中...)

 

posted on 2013-04-08 08:49  ShareIdeas  阅读(947)  评论(0编辑  收藏  举报