搜索
bottom↓
回复: 70

卡尔曼滤波算法C语言实现(转)

  [复制链接]

出0入0汤圆

发表于 2013-11-19 20:16:59 | 显示全部楼层 |阅读模式
本帖最后由 jackk 于 2013-11-20 14:42 编辑

看了几天的Kalman,感觉概率和矩阵都白学了。
那个经典的温度的例子,这是目前看到的最完整细致的版本了。
看不懂,在学习。

帖子里面公式显示不了,链接如下:
http://wenku.baidu.com/view/8523cb6eaf1ffc4ffe47ac24.html



贴中源程序如下:不明觉厉。
附录:源程序
#include "stdio.h"
#include "stdlib.h"
#include "math.h"
double frand()
{      return 2*((rand()/(double)RAND_MAX) - 0.5);  //随机噪声}  
void main()
{        float x_last=0;   
        float p_last=0.02;
        float Q=0.018;
        float R=0.542;
        float kg;
        float x_mid;
        float x_now;
        float p_mid;
        float p_now;
        float z_real=0.56;//0.56
        float z_measure;
        float sumerror_kalman=0;
        float sumerror_measure=0;
        int i;
        x_last=z_real+frand()*0.03;
        x_mid=x_last;
        for(i=0;i<20;i++)
        {        x_mid=x_last;    //x_last=x(k-1|k-1),x_mid=x(k|k-1)
                p_mid=p_last+Q;  //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
                kg=p_mid/(p_mid+R); //kg为kalman filter,R为噪声
                z_measure=z_real+frand()*0.03;//测量值
                x_now=x_mid+kg*(z_measure-x_mid);//估计出的最优值
                p_now=(1-kg)*p_mid;//最优值对应的covariance
                printf("Real     position: %6.3f \n",z_real);  //显示真值
        printf("Mesaured position: %6.3f [diff:%.3f]\n",z_measure,fabs(z_real-z_measure));  //显示测量值以及真值与测量值之间的误差
        printf("Kalman   position: %6.3f [diff:%.3f]\n",x_now,fabs(z_real - x_now));  //显示kalman估计值以及真值和卡尔曼估计值的误差
        sumerror_kalman += fabs(z_real - x_now);  //kalman估计值的累积误差
        sumerror_measure += fabs(z_real-z_measure);  //真值与测量值的累积误差
        p_last = p_now;  //更新covariance值
        x_last = x_now;  //更新系统状态值
        }
        printf("总体测量误差      : %f\n",sumerror_measure);  //输出测量累积误差
            printf("总体卡尔曼滤波误差: %f\n",sumerror_kalman);   //输出kalman累积误差
    printf("卡尔曼误差所占比例: %d%% \n",100-(int)((sumerror_kalman/sumerror_measure)*100));
}

我现在是希望读取MMA7361加速度计的输出,串口过来的数据跳动很大。
我把帖子的代码稍微改动了一下,好像还不错。
下面的代码没做仔细的验证,风格也不好,抛砖引玉吧。
#include "stdio.h"
#include "stdlib.h"
#include "math.h"

#define ADDataCnt 10

double ADData[ADDataCnt];

void InitADData(double RealValue, unsigned int Cnt)
{
        unsigned int i;
        for( i =0; i < Cnt; i++)
        {
                ADData = RealValue + 0.2*rand()/(double)RAND_MAX - 0.1;
        }       
}

double KalmanFilter(unsigned int DataCnt,double *Data,double ProcessNiose_Q,double MeasureNoise_R,double InitialPrediction)
{
        unsigned int i;
        double R = MeasureNoise_R;
        double Q = ProcessNiose_Q;
        double x_last = *Data;
        double x_mid = x_last;
        double x_now;
        double p_last = InitialPrediction;
        double p_mid ;
        double p_now;
        double kg;

        for(i=0;i<DataCnt;i++)
        {
                x_mid=x_last; //x_last=x(k-1|k-1),x_mid=x(k|k-1)
                p_mid=p_last+Q; //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
                kg=p_mid/(p_mid+R); //kg为kalman filter,R为噪声
//                z_measure=z_real+frand()*0.03;//测量值
                x_now=x_mid+kg*(*(Data+i)-x_mid);//估计出的最优值
                p_now=(1-kg)*p_mid;//最优值对应的covariance

                p_last = p_now; //更新covariance值
                x_last = x_now; //更新系统状态值
        }
        return x_now;

}
void main()
{
        unsigned int i;
        double KalmanFilterReturn;
        InitADData(2.1,ADDataCnt);

        for(i = 0;i < ADDataCnt;i++)
                printf("ADData[%d] Is : %lf\n",i,ADData);

        KalmanFilterReturn = KalmanFilter(ADDataCnt,ADData,0,0.005,10);

        printf("\n Kalman Output : %lf\n",KalmanFilterReturn);
        while(1)
                ;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2013-11-19 23:03:18 来自手机 | 显示全部楼层
收藏一下                  

出0入0汤圆

发表于 2013-11-20 09:12:03 | 显示全部楼层
坐等高手分析

出0入0汤圆

发表于 2013-11-20 09:53:53 | 显示全部楼层
数学还给老师了

出0入0汤圆

 楼主| 发表于 2013-11-20 14:35:28 | 显示全部楼层
xiong57785 发表于 2013-11-19 23:03
收藏一下

这是一个一维的卡尔曼滤波,还好理解一点,不知道这段代码对不对。。。

出0入0汤圆

 楼主| 发表于 2013-11-20 14:35:48 | 显示全部楼层
cmheia 发表于 2013-11-20 09:53
数学还给老师了

这是一个一维的卡尔曼滤波,还好理解一点,不知道这段代码对不对。。。

出0入0汤圆

 楼主| 发表于 2013-11-20 14:36:12 | 显示全部楼层
dongjie135 发表于 2013-11-20 09:12
坐等高手分析

这是一个一维的卡尔曼滤波,还好理解一点,不知道这段代码对不对。。。头像不错,哈哈

出0入0汤圆

发表于 2013-11-20 14:57:25 | 显示全部楼层
试了试,还是不错的,一维的应该可以了吧?

出0入0汤圆

发表于 2013-11-24 21:51:16 | 显示全部楼层
正在学习,很有help!

出0入0汤圆

发表于 2013-11-24 22:00:12 | 显示全部楼层
做个记录,便于今后查找

出0入0汤圆

发表于 2013-11-28 20:03:19 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2013-12-6 16:03:11 | 显示全部楼层
找了好久,今天终于看到了,先标记一下,留着慢慢看

出0入0汤圆

发表于 2013-12-6 18:41:18 | 显示全部楼层
标记一下,方便学习

出0入0汤圆

发表于 2014-2-10 16:54:32 | 显示全部楼层
标记下以后用

出0入0汤圆

发表于 2014-2-13 12:10:25 | 显示全部楼层
不错,多谢分享了。

出0入0汤圆

发表于 2014-2-20 16:02:50 | 显示全部楼层
看过这个,还不错

出0入0汤圆

发表于 2014-2-20 16:19:53 | 显示全部楼层
哪位出来解析一下

出0入0汤圆

 楼主| 发表于 2014-2-21 15:51:58 | 显示全部楼层
zlpvch 发表于 2014-2-20 16:19
哪位出来解析一下

我自己综合上面的一些资料,简化了一个版本,只是一维地用来滤除加速度计的噪声,在STM32上面运行的很流畅,数据也很稳。收敛稳定性较高,收敛速度也快。

#define KALMAN_Q        0.0000001
#define KALMAN_R        10.0000
#define KALMAN_P0        2210.0000
#include"kalman.h"

/*       
        Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
        R:测量噪声,R增大,动态响应变慢,收敛稳定性变好       
*/

double KalmanFilter(const double ResrcData,
                                        double ProcessNiose_Q,double MeasureNoise_R,double InitialPrediction)
{
        double R = MeasureNoise_R;
        double Q = ProcessNiose_Q;

        static        double x_last;

        double x_mid = x_last;
        double x_now;

        static        double p_last;

        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+Q; //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
        kg=p_mid/(p_mid+R); //kg为kalman filter,R为噪声
        x_now=x_mid+kg*(ResrcData-x_mid);//估计出的最优值
               
        p_now=(1-kg)*p_mid;//最优值对应的covariance       

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

        return x_now;               
}




出0入0汤圆

 楼主| 发表于 2014-2-21 15:53:04 | 显示全部楼层
dongjie135 发表于 2013-11-20 14:57
试了试,还是不错的,一维的应该可以了吧?

我自己综合上面的一些资料,简化了一个版本,只是一维地用来滤除加速度计的噪声,在STM32上面运行的很流畅,数据也很稳。收敛稳定性较高,收敛速度也快。

#define KALMAN_Q        0.0000001
#define KALMAN_R        10.0000
#define KALMAN_P0        2210.0000
#include"kalman.h"

/*        
        Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
        R:测量噪声,R增大,动态响应变慢,收敛稳定性变好        
*/

double KalmanFilter(const double ResrcData,
                                        double ProcessNiose_Q,double MeasureNoise_R,double InitialPrediction)
{
        double R = MeasureNoise_R;
        double Q = ProcessNiose_Q;

        static        double x_last;

        double x_mid = x_last;
        double x_now;

        static        double p_last;

        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+Q; //p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
        kg=p_mid/(p_mid+R); //kg为kalman filter,R为噪声
        x_now=x_mid+kg*(ResrcData-x_mid);//估计出的最优值
               
        p_now=(1-kg)*p_mid;//最优值对应的covariance        

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

        return x_now;               
}

出0入0汤圆

发表于 2014-2-21 16:25:59 | 显示全部楼层
mark!标记下

出0入0汤圆

发表于 2014-2-21 18:11:40 | 显示全部楼层
p_last 和x _last的初值的选取应该怎样弄,我用这段代码来滤气压计的数据,效果不错,来滤经纬度,就不行了。

出0入0汤圆

发表于 2014-2-21 18:12:27 | 显示全部楼层
看到你的p_last的初值选取的是0.02,我取的是0,这个有什么影响呢?

出0入0汤圆

发表于 2014-2-22 12:40:33 | 显示全部楼层
非常感谢

出0入0汤圆

发表于 2014-2-27 17:52:55 | 显示全部楼层
这种高档货一定要mark。

出0入0汤圆

发表于 2014-2-27 17:53:23 | 显示全部楼层
fcmer 发表于 2014-2-27 17:52
这种高档货一定要mark。

这种高档货,一定要mark。

出0入0汤圆

发表于 2014-2-27 23:18:49 | 显示全部楼层
卡尔曼滤波 不明觉厉  mark

出0入0汤圆

发表于 2014-2-27 23:44:05 | 显示全部楼层
MARK一下,以后用到

出0入0汤圆

发表于 2014-3-4 10:10:48 | 显示全部楼层

做个记录,便于今后查找

出0入0汤圆

发表于 2014-3-4 20:03:26 | 显示全部楼层
收藏一下!

出0入0汤圆

 楼主| 发表于 2014-3-5 10:21:37 | 显示全部楼层
这是滤波效果。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入4汤圆

发表于 2014-3-5 10:44:23 | 显示全部楼层
看一下,卡尔曼要学习下

出0入0汤圆

 楼主| 发表于 2014-3-5 11:23:27 | 显示全部楼层
整理了一下,看这个帖子吧,这个就别回复啦。

出0入0汤圆

 楼主| 发表于 2014-3-5 11:24:26 | 显示全部楼层
这个不知道怎么删掉,看这个吧:http://www.amobbs.com/thread-5571611-1-1.html

出0入0汤圆

发表于 2014-3-25 22:45:59 | 显示全部楼层
mark,思想值得学习!

出0入0汤圆

发表于 2014-3-25 23:41:30 | 显示全部楼层
ding !!!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-3-26 16:58:26 | 显示全部楼层
z_measure=z_real+frand()*0.03;//测量值
这句文档里面没找到解释

出0入0汤圆

发表于 2014-3-26 21:58:17 | 显示全部楼层
凯尔曼滤波,早晚要啃的硬骨头

出0入0汤圆

发表于 2014-3-27 09:01:12 | 显示全部楼层
jackk 发表于 2014-3-5 11:24
这个不知道怎么删掉,看这个吧:http://www.amobbs.com/thread-5571611-1-1.html


z_measure=z_real+frand()*0.03;//测量值
这句文档里面没找到解释

出0入0汤圆

发表于 2014-3-27 09:17:14 | 显示全部楼层
谢谢楼主分享!

出0入0汤圆

发表于 2014-3-27 10:14:37 | 显示全部楼层
jackk 发表于 2014-2-21 15:53
我自己综合上面的一些资料,简化了一个版本,只是一维地用来滤除加速度计的噪声,在STM32上面运行的很流 ...

请问可以用在AD滤波上吗?

出0入0汤圆

发表于 2014-4-8 16:27:51 | 显示全部楼层
Cool!!!!!!

出10入95汤圆

发表于 2014-4-10 13:14:27 | 显示全部楼层
谢谢分享!

出0入0汤圆

发表于 2014-5-6 13:40:47 | 显示全部楼层
值得收藏啊!

出0入0汤圆

发表于 2014-5-8 11:16:49 | 显示全部楼层
表示看不懂!

出0入0汤圆

发表于 2014-5-8 13:48:41 | 显示全部楼层
正在弄卡尔曼滤波 好东西

出0入0汤圆

发表于 2014-6-9 15:52:04 | 显示全部楼层
mark!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-7-1 10:10:23 | 显示全部楼层
zlpvch 发表于 2014-2-21 18:11
p_last 和x _last的初值的选取应该怎样弄,我用这段代码来滤气压计的数据,效果不错,来滤经纬度,就不行了 ...

哥们,你经纬度滤的怎么样?成功了么?

出0入0汤圆

发表于 2014-7-1 10:28:19 | 显示全部楼层
强!!                              

出0入0汤圆

发表于 2014-7-1 16:13:39 | 显示全部楼层
受益匪浅

出0入0汤圆

发表于 2014-7-1 18:25:13 | 显示全部楼层
mark 有需要用到

出0入0汤圆

发表于 2014-8-7 11:17:32 | 显示全部楼层
RAND_MAX 是多少?

出0入0汤圆

发表于 2014-8-7 11:26:32 | 显示全部楼层
请问过程噪声和 测量噪声是怎么得到的,有什么好的估计或者测量办法么?

出0入0汤圆

发表于 2014-8-20 20:12:16 | 显示全部楼层
标记收藏

出0入0汤圆

发表于 2014-9-11 17:11:01 | 显示全部楼层
学习了一下,对温度、气压等信号采集处理很有用。

出0入0汤圆

发表于 2014-9-15 10:21:08 | 显示全部楼层
收藏一下     谢谢分享

出0入0汤圆

发表于 2014-9-15 11:01:56 | 显示全部楼层
好东西,留名收藏

出0入0汤圆

发表于 2014-9-15 12:52:21 | 显示全部楼层
学习中,还没有看明白

出0入0汤圆

发表于 2014-9-15 17:42:49 | 显示全部楼层
好东西,学习了

出0入0汤圆

发表于 2014-9-17 16:05:05 | 显示全部楼层
收藏一下,谢谢分享~

出0入0汤圆

发表于 2014-9-17 16:09:49 | 显示全部楼层

收藏一下,谢谢分享~

出0入0汤圆

发表于 2014-9-19 18:17:01 | 显示全部楼层
学习了,虽然看不懂,

出0入0汤圆

发表于 2014-9-30 10:38:49 | 显示全部楼层
mark!!!!!!!!!!!!!!!!

出0入0汤圆

发表于 2014-9-30 11:08:06 | 显示全部楼层
mark!!!!!!!!!!!!

出0入0汤圆

发表于 2014-9-30 12:04:30 | 显示全部楼层
mark>>>>>>>>>>>>>>

出0入0汤圆

发表于 2014-12-12 14:44:00 来自手机 | 显示全部楼层
看完这个,终于懂了一点了!谢谢!

出0入0汤圆

发表于 2014-12-14 12:25:55 | 显示全部楼层
已经收藏了,这个对我来说很有价值,比较形象

出0入0汤圆

发表于 2014-12-14 12:33:08 | 显示全部楼层
好帖,收藏了

出0入0汤圆

发表于 2014-12-16 21:37:30 | 显示全部楼层
M3处理得过来吗? 不要用M4了!

出0入0汤圆

发表于 2014-12-23 20:02:16 | 显示全部楼层
谢谢楼主分享

出0入0汤圆

发表于 2014-12-24 17:23:30 | 显示全部楼层
这个用来做一维数据的滤波可以了,不过kalman更厉害的作用还是在数据的融合上

出0入0汤圆

发表于 2015-1-19 21:30:49 | 显示全部楼层
卡尔曼  标志一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 00:06

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表