[应用相关] 卡尔曼滤波C代码分析

[复制链接]
3120|18
 楼主| cztqwa 发表于 2015-11-28 16:40 | 显示全部楼层 |阅读模式
本帖最后由 cztqwa 于 2015-11-28 16:40 编辑

卡尔曼滤波C代码分析_页面_1.jpg
卡尔曼滤波C代码分析_页面_2.jpg
卡尔曼滤波C代码分析_页面_3.jpg
卡尔曼滤波C代码分析_页面_4.jpg
卡尔曼滤波C代码分析_页面_5.jpg
卡尔曼滤波C代码分析_页面_6.jpg
卡尔曼滤波C代码分析_页面_7.jpg
卡尔曼滤波C代码分析_页面_8.jpg

mmuuss586 发表于 2015-11-28 17:09 | 显示全部楼层

为啥不发PDF资料呢
 楼主| cztqwa 发表于 2015-11-28 21:29 | 显示全部楼层
mmuuss586 发表于 2015-11-28 17:09
为啥不发PDF资料呢

第一次发帖,还不太会弄。
 楼主| cztqwa 发表于 2015-11-28 21:33 | 显示全部楼层
mmuuss586 发表于 2015-11-28 17:09
为啥不发PDF资料呢

好像是权限太低了,以后补上。
奔牛滚滚 发表于 2015-11-28 23:41 | 显示全部楼层
请发pdf资料,权限太低,发到百度网盘然后给个链接也可以啊,发到百度文库也可以赚积分,发到论坛的资料库更好,资料库下载也是要积分的
MJM_WSY 发表于 2015-11-29 16:45 | 显示全部楼层
求PDF文档。还有代码。   这个可以用来稳定电子称的数值不?
 楼主| cztqwa 发表于 2015-11-29 20:21 | 显示全部楼层
奔牛滚滚 发表于 2015-11-28 23:41
请发pdf资料,权限太低,发到百度网盘然后给个链接也可以啊,发到百度文库也可以赚积分,发到论坛的资料库更好, ...

我连发链接的权限都木有,您可以去百度文库搜索,已上传。
 楼主| cztqwa 发表于 2015-11-29 20:25 | 显示全部楼层
MJM_WSY 发表于 2015-11-29 16:45
求PDF文档。还有代码。   这个可以用来稳定电子称的数值不?

不怎么了解电子称的原理。
 楼主| cztqwa 发表于 2015-11-29 20:45 | 显示全部楼层
MJM_WSY 发表于 2015-11-29 16:45
求PDF文档。还有代码。   这个可以用来稳定电子称的数值不?
  1. float Angle=0.0;                //卡尔曼滤波器的输出值,最优估计的角度
  2. //float Gyro_x=0.0;                //卡尔曼滤波器的输出值,最优估计的角速度
  3. float Q_angle=0.001;        //陀螺仪噪声的协方差(估计过程的误差协方差)
  4. float Q_gyro=0.003;                //陀螺仪漂移噪声的协方差(估计过程的误差协方差)
  5. float R_angle=0.5;                //加速度计测量噪声的协方差
  6. float dt=0.005;                //积分时间,dt为滤波器采样时间(秒)
  7. char C_0 = 1;                //H矩阵的一个数
  8. float Q_bias=0, Angle_err=0;        //Q_bias为陀螺仪漂移
  9. float PCt_0=0, PCt_1=0, E=0;        //中间变量
  10. float K_0=0, K_1=0, t_0=0, t_1=0;        //K是卡尔曼增益,t是中间变量
  11. float Pdot[4] ={0,0,0,0};        //计算P矩阵的中间变量
  12. float PP[2][2] = { { 1, 0 },{ 0, 1 } };                //公式中P矩阵,X的协方差

  13. void Kalman_Filter(float Gyro,float Accel)//Gyro陀螺仪的测量值,Accel加速度计的角度计算值
  14. {   
  15.     Angle += (Gyro - Q_bias)*dt;
  16. //角度测量模型方程,角度估计值=上一次的最优角度+(角速度-上一次的最优零漂)*dt      //就漂移来说认为每次都是相同的Q_bias=Q_bias

  17.     Pdot[0]=Q_angle - PP[0][1] - PP[1][0];
  18.     Pdot[1] = -PP[1][1];
  19.     Pdot[2] = -PP[1][1];
  20.     Pdot[3] = Q_gyro;

  21.     PP[0][0] += Pdot[0] * dt;   
  22.     PP[0][1] += Pdot[1] * dt;   
  23.     PP[1][0] += Pdot[2] * dt;
  24. PP[1][1] += Pdot[3] * dt;

  25.     PCt_0 = C_0 * PP[0][0];                //矩阵乘法的中间变量
  26.     PCt_1 = C_0 * PP[1][0];                //C_0=1
  27.     E = R_angle + C_0 * PCt_0;        //分母
  28.     K_0 = PCt_0 / E;        //卡尔曼增益,两个,一个是Angle的,一个是Q_bias的
  29. K_1 = PCt_1 / E;

  30.     Angle_err = Accel - Angle;
  31.     Angle += K_0 * Angle_err;        //计算最优角度   
  32.     Q_bias += K_1 * Angle_err;           //计算最优零漂
  33. //Gyro_x = Gyro - Q_bias;            //计算得最优角速度

  34.     t_0 = PCt_0;                         //矩阵计算中间变量,相当于a
  35.     t_1 = C_0 * PP[0][1];                //矩阵计算中间变量,相当于b
  36.     PP[0][0] -= K_0 * t_0;        
  37.     PP[0][1] -= K_0 * t_1;
  38.     PP[1][0] -= K_1 * t_0;
  39.     PP[1][1] -= K_1 * t_1;
  40. }
MJM_WSY 发表于 2015-11-30 07:51 | 显示全部楼层

这个代码跟以前我下载的差不多,先谢谢你了,还能单独给我发出来。
这个是导入两个参数的。
现在我这采样回来的只有AD的数值,怎么做才能让AD的数值更平滑?这个函数要怎么用?能指点一下不
犹豫的大三 发表于 2015-11-30 08:44 | 显示全部楼层
MJM_WSY 发表于 2015-11-30 07:51
这个代码跟以前我下载的差不多,先谢谢你了,还能单独给我发出来。
这个是导入两个参数的。
现在我这采样 ...

你的AD采样速度是多少?太慢的话没有必要用。这个算法滞后太严重了,需要人工改变那两个参数值。
 楼主| cztqwa 发表于 2015-11-30 09:18 | 显示全部楼层
MJM_WSY 发表于 2015-11-30 07:51
这个代码跟以前我下载的差不多,先谢谢你了,还能单独给我发出来。
这个是导入两个参数的。
现在我这采样 ...

代码也是从网上下的,主要是文档里对这段代码的实现进行了分析。这段代码一般用于陀螺仪和加速度计融合数据用的。
 楼主| cztqwa 发表于 2015-11-30 10:40 | 显示全部楼层
MJM_WSY 发表于 2015-11-30 07:51
这个代码跟以前我下载的差不多,先谢谢你了,还能单独给我发出来。
这个是导入两个参数的。
现在我这采样 ...

如果只是想让AD的数值更平滑,有很多软件滤波的方法可以参考的,比如:限幅滤波法、递推平均滤波法等。您可搜一下“10中软件滤波算法”,里面也许有您需要的。
309030106 发表于 2015-11-30 20:33 | 显示全部楼层
主要是文档里对这段代码的实现进行了分析

这个资料应该是不错的,期待上传
MJM_WSY 发表于 2015-12-2 14:15 | 显示全部楼层
cztqwa 发表于 2015-11-30 10:40
如果只是想让AD的数值更平滑,有很多软件滤波的方法可以参考的,比如:限幅滤波法、递推平均滤波法等。您 ...

挨个试了一遍。。。都不行。  很不理想
MJM_WSY 发表于 2015-12-2 14:17 | 显示全部楼层
犹豫的大三 发表于 2015-11-30 08:44
你的AD采样速度是多少?太慢的话没有必要用。这个算法滞后太严重了,需要人工改变那两个参数值。 ...

要求就是快。所以以前我也套用了卡尔曼,确实是平滑度很高。但是滞后十分严重。
犹豫的大三 发表于 2015-12-3 08:54 | 显示全部楼层
MJM_WSY 发表于 2015-12-2 14:17
要求就是快。所以以前我也套用了卡尔曼,确实是平滑度很高。但是滞后十分严重。 ...

如果采样速度很快的话,滞后应该会好点。此外设置一个定值,如果两次采样的值之间的差值小于这个定值,用卡尔曼滤波。如果差值大于这个定值,可以修改卡尔曼滤波的参数,让它迅速到当前值。这样滞后应该就会减小了。你可以试一下看看!我的AD采样速度不快,用卡尔曼滤波效果不怎么好,你的采样速度快的话可以试一下这种方法。
jasonell 发表于 2015-12-6 07:23 来自手机 | 显示全部楼层
学习了。
MJM_WSY 发表于 2015-12-9 14:44 | 显示全部楼层
犹豫的大三 发表于 2015-12-3 08:54
如果采样速度很快的话,滞后应该会好点。此外设置一个定值,如果两次采样的值之间的差值小于这个定值,用 ...

我不太了解这个卡尔曼。以下是我以前用过的一个卡尔曼的代码。我不太确定这个是不是卡尔曼。用这个的确是平滑度很高。就是滞后严重。STM32F103ZET6下使用的。

#include "KF.h"


   
double KF_Q = 0.01;                // Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
double KF_R = 0.1;                // R:测量噪声,R增大,动态响应变慢,收敛稳定性变好     



u16 KalmanFilter(u16 v)
{
        static double x_last;
        static double p_last;
        double x_mid;
        double x_now;
        double p_mid;
        double p_now;//协方差
        double kg;   //卡尔曼     
       
       
        x_mid = x_last;                                                 //x_last=x(k-1|k-1), x_mid=x(k|k-1)
        p_mid = p_last + KF_Q;                                 //p_mid=p(k|k-1),p_last=p(k-1|k-1),KF_Q=噪声
        kg = p_mid / (p_mid+KF_R);                 //kg为kalman filter,R为噪声
        x_now = x_mid + kg * (v-x_mid);        //估计出的最优值

        p_now = (1-kg) * p_mid;                                //最优值对应的covariance        

        p_last = p_now; //更新covariance值//协方差
        x_last = x_now; //更新系统状态值              

        return        x_now;
}

//end
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

33

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部