搜索
bottom↓
回复: 219

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

  [复制链接]

出0入0汤圆

发表于 2014-3-5 11:21:49 | 显示全部楼层 |阅读模式
本帖最后由 jackk 于 2014-3-5 13:00 编辑

前段时间在论坛里简单地发了一些关于kalman的理解。
有很多网友顶贴的,趁着今天休息,整理一下前段时间的工作。

有些理解和说法可能不正确,以此抛砖引玉吧。

1,
在google上搜索卡尔曼滤波,很容易找到以下这个帖子:

http://blog.csdn.net/lanbing510/article/details/8828109

这里面很简单形象的解释了kalman的作用。

但是帖子后半段,将kalman回归到了一大堆数学推理、推导上,对非数学专业,或者数学基础尤其是概率和随机过程基础不好的同学来讲实在太过头痛。
帖子最后用matlab实现了kalman,其中很简单地用i,j,k来命名,可能不是太妥当,新手理解的时候,脑袋里面要运行着一个很深的堆栈。
当然,原作者毫无疑问对kalman有着极其深刻的理解,才能实现得如此游刃有余。

在此,只是对第一次接触kalman的同学简单介绍一下自己的理解。帮得到诸君为好,帮不到请勿喷。

2,
首先,kalman是一个数字滤波器。

我们可以用硬件搭建一个模拟滤波器,将叠加了噪声的模拟信号输入到滤波器中,滤波器给出一个响应。
我们把这个响应作为输入信号踢掉噪声之后的真值。
当然,可以通过调整滤波器参数,使得响应尽可能接近客观真值,亦即尽可能多地衰减噪声。

进一步讲,我们用AD将模拟信号数字化之后,因为模拟信号本身包含了噪声,即使AD没有误差,数字化之后的数字量也是含有噪声的。
况且,不可避免的,还要考虑AD的误差。我们把这种误差就叫做测量误差。

数字化之后,最简单的,我们可以测100组数据,排序,删掉前20个,删掉后20个,剩下60个取均值。这样会排除了一些偶然误差。
kalman滤波器和上面的均值方法工作模式类似,只不过他的工作过程比较复杂,通过算法里面的五条公式过后,会很好的给出真值。

网上很多的是关于多维kalman实现。理解多维的比较费劲。
参照网上的一些代码,实现了一个一维地滤波,对于有C语言基础的同学来讲,理解起来应该很容易了。

3,
百度百科里面有这个帖子:

http://wenku.baidu.com/view/8523cb6eaf1ffc4ffe47ac24.html

讲解的是一维kalman滤波器,但是最后printf出来的都是分立的值,看不出来什么。

我参考那段代码,改写成了下面这段代码,在labwindows里面绘制了一段曲线,效果就很直观了:

/*-------------------------------------------------------------------------------------------------------------*/
void KalmanFilter(unsigned int ResrcDataCnt,const double *ResrcData,double *FilterOutput,double ProcessNiose_Q,double MeasureNoise_R,double InitialPrediction)
{
        unsigned int i;
        double R = MeasureNoise_R;
        double Q = ProcessNiose_Q;
        double x_last = *ResrcData;
        double x_mid = x_last;
        double x_now;
        double p_last = InitialPrediction;
        double p_mid ;
        double p_now;
        double kg;

        for(i=0;i<ResrcDataCnt;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为噪声
                x_now=x_mid+kg*(*(ResrcData+i)-x_mid);//估计出的最优值
                p_now=(1-kg)*p_mid;//最优值对应的covariance
               
                *(FilterOutput + i)  = x_now;

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

}
/*-------------------------------------------------------------------------------------------------------------*/

上面是滤波器部分,然后,我模拟了一段AD的数据,输给这个滤波器,然后看一下这个滤波器的响应,效果如下所示:


从图上可以看出,真值为5,,1000组数据,每组随机叠加10%的噪声,可以观察一下kalman的收敛速度和收敛精度。
收敛速度和收敛精度就是kalman的两个重要衡量指标。
收敛速度和收敛精度是矛盾着的。

4,
参考上面的代码,我优化了一下之后,运行在了STM32上面:

/*-------------------------------------------------------------------------------------------------------------*/
/*       
        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;               
}

/*-------------------------------------------------------------------------------------------------------------*/

5,
我是希望用加速度计测出加速度,然后加速度积分得出速度,然后速度积分得位移。
硬件用的freescale的MMA7361,模拟加速度计,STM32 片上AD,如下:洞洞板右上角为MMA7361


LCD上面曲线为加速度计曲线,下面那条线为速度曲线,第三条没处理。

没有kalman可以看到加速度那条线很粗:


用了kalman之后,效果如下:



6,
kalman需要根据具体的应用来调整滤波器参数的。
主要是:测量噪声系数,系统噪声系数,初始估计。这三个。
我问了一下老师,老师的意思是,这些参数很多时候是经验值,没有很好地系统的估计方法。
我个人感觉这是kalman理论发展的方向,估计很多人在研究这个吧。

7,
附件是一个labwindows 仿真的C代码,一个STM32 的MDK工程代码,正点原子的板子,和一些文档。

感觉有个这些,再参考一下网上的资料,应用方面应该没什么问题了。

至于理论本质,实在力不能及,路漫漫其修远啊。

8,
听了小伙伴的意思,换成数字MPU6000了。

吃饭啦,就这样吧。希望能帮到大家。

我是学生党,在学习,很多东西做的很粗糙,勿喷。







本帖子中包含更多资源

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

x

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

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2019-12-15 20:44:28 | 显示全部楼层
在这里Mark一下!@

出0入4汤圆

发表于 2019-11-29 21:18:18 来自手机 | 显示全部楼层
Mark 卡尔曼一维

出0入0汤圆

发表于 2019-10-9 13:38:14 | 显示全部楼层
学习了,谢谢分享

出0入0汤圆

发表于 2019-9-29 18:56:59 | 显示全部楼层
学习一下

出0入0汤圆

发表于 2019-7-18 17:47:31 | 显示全部楼层
有分量的帖子!必须顶!

出0入0汤圆

发表于 2019-7-18 14:00:34 | 显示全部楼层

这个必须顶!!!!!!!!!!

出0入0汤圆

发表于 2019-5-23 10:59:52 来自手机 | 显示全部楼层
感谢楼主分享,卡尔曼滤波

出0入0汤圆

发表于 2019-5-23 09:31:44 | 显示全部楼层
先留个坐标

出0入0汤圆

发表于 2019-5-23 09:11:37 | 显示全部楼层
谢谢分享!!!

出0入0汤圆

发表于 2018-12-19 09:55:22 | 显示全部楼层
mark 卡尔曼滤波

出0入0汤圆

发表于 2018-12-19 09:42:45 | 显示全部楼层
顶!楼主好人

出0入0汤圆

发表于 2018-12-19 09:35:01 | 显示全部楼层
太感谢了,刚好用到,直接用楼主的代码,只改了R值,完美滤波

出0入0汤圆

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

出0入0汤圆

发表于 2018-11-27 11:20:13 | 显示全部楼层
不错,感谢楼主分享!

出0入16汤圆

发表于 2018-10-30 08:54:02 | 显示全部楼层
谢谢楼主,学习一下

出0入0汤圆

发表于 2018-9-25 15:46:44 | 显示全部楼层
说得比较直白,对应用来说很好

出0入0汤圆

发表于 2018-9-18 15:44:27 | 显示全部楼层
厉害,路漫漫其修远兮

出0入0汤圆

发表于 2018-9-11 10:42:26 | 显示全部楼层
学习了,谢谢楼主分享!!

出0入0汤圆

发表于 2018-9-11 10:05:39 | 显示全部楼层
谢谢,你辛苦了

出0入0汤圆

发表于 2018-8-14 13:59:26 | 显示全部楼层
深度好帖,收藏备用了,谢谢版主。

出0入0汤圆

发表于 2018-8-10 13:46:38 | 显示全部楼层
学习了,谢谢楼主分享!!

出0入0汤圆

发表于 2018-7-30 14:02:57 | 显示全部楼层
不错,卡尔曼滤波,mark下!

出0入0汤圆

发表于 2018-7-13 19:17:03 | 显示全部楼层
看起来不错  楼主用心了

出0入0汤圆

发表于 2018-7-6 16:34:34 来自手机 | 显示全部楼层
毕业快十年了,这个还没整明白。。。

出0入0汤圆

发表于 2018-6-30 10:55:20 | 显示全部楼层
收藏了,这个工程验证过没

出0入0汤圆

发表于 2018-6-30 10:02:55 | 显示全部楼层
学习了,谢谢楼主分享!!

出100入0汤圆

发表于 2018-6-13 22:01:05 | 显示全部楼层
还有一些问题没解决呢,咋就沉了,同问如何确定Q,R。

出0入0汤圆

发表于 2018-5-8 23:16:34 | 显示全部楼层
新人,学习一下

出0入0汤圆

发表于 2018-4-2 12:43:19 | 显示全部楼层
正好在学这块 ,谢啦

出0入0汤圆

发表于 2018-3-31 16:48:52 | 显示全部楼层
感谢楼主的解释

出0入0汤圆

发表于 2017-7-20 05:44:59 来自手机 | 显示全部楼层
正需要,谢谢

出0入0汤圆

发表于 2017-6-13 10:01:15 | 显示全部楼层
讨论得很热闹,学习了

出0入0汤圆

发表于 2017-1-20 09:31:56 | 显示全部楼层
多谢分享~~~~~~

出0入0汤圆

发表于 2016-11-30 18:09:01 | 显示全部楼层
jorry 发表于 2016-11-30 16:10
楼主,初值估计值好像在您的滤波程序中没使用

看上楼的讨论知道了,谢谢分享!!

出0入0汤圆

发表于 2016-11-30 16:10:00 | 显示全部楼层
楼主,初值估计值好像在您的滤波程序中没使用

出0入0汤圆

发表于 2016-11-29 21:38:26 | 显示全部楼层
mark,谢谢楼主

出0入0汤圆

发表于 2016-11-29 20:43:01 | 显示全部楼层
mark,谢谢楼主

出0入0汤圆

发表于 2016-11-2 20:38:26 | 显示全部楼层
有浮点 运行太慢  不符合现实情况呀

出0入0汤圆

发表于 2016-11-2 20:11:52 | 显示全部楼层
谢谢,学习!!!

出0入0汤圆

发表于 2016-11-2 18:43:24 | 显示全部楼层
MARK下,以后调试试试!

出0入0汤圆

发表于 2016-9-28 23:06:42 | 显示全部楼层
谢谢楼主分享!!

出0入4汤圆

发表于 2016-9-28 11:43:50 | 显示全部楼层
xuexueaibeibei 发表于 2014-5-11 10:49
看了楼主的程序,有几个问题,希望楼主解答!

1.我采集的三轴角度传感器的X Y Z三个通道的AD值,用DMA传输 ...

能不能分享下硬件 滤波的经验

出0入0汤圆

发表于 2016-9-28 10:52:18 | 显示全部楼层
收藏学习一下。卡尔曼滤波还是很有用的。

出0入0汤圆

发表于 2016-9-22 17:11:25 | 显示全部楼层
卡尔曼滤波,,学习学习

出0入0汤圆

发表于 2016-7-21 14:49:26 | 显示全部楼层
非常不错,赶快收藏

出0入0汤圆

发表于 2016-6-23 10:44:31 | 显示全部楼层
楼主我使用你上面的代码在AVR单片机上使用,结果出来的是一条上升的直线,楼主能不能耐心讲解一下如何补充

出0入0汤圆

发表于 2016-6-22 11:39:25 | 显示全部楼层

#define KALMAN_Q        0.0000001
#define KALMAN_R        10.0000

#define KALMAN_P0        2210.0000
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;
        p_mid=p_last+Q;
        kg=p_mid/(p_mid+R);
        x_now=x_mid+kg*(ResrcData-x_mid);
               
        p_now=(1-kg)*p_mid;

        p_last = p_now;
        x_last = x_now;

        return x_now;               
}
上面是滤波函数
下面是AD采集值,KXR94.AXIS_X = (unsigned int)KalmanFilter((double)KXR94.AXIS_X,KALMAN_Q,KALMAN_R,KALMAN_P0);
我测出的图像如图,跟你的差距很大,是我哪里应用不当吗
            

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2016-5-10 14:04:22 | 显示全部楼层
不错,卡尔曼滤波,mark下

出0入0汤圆

发表于 2016-5-3 15:55:50 | 显示全部楼层
好的数字滤波器跟初始参数无关,这个算是经典滤波器,不属于自适应滤波器

出0入0汤圆

发表于 2016-3-10 23:25:44 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2016-1-21 09:58:06 | 显示全部楼层
我在四轴上用了kalman,效果的确不错,但是数学功底不够,还是没有完全理解它的推导过程,不知道kalman能否用来滤除固定频率的干扰源

出0入0汤圆

发表于 2016-1-20 12:09:30 | 显示全部楼层
好帖子,谢谢楼主分享……

出0入0汤圆

发表于 2016-1-19 11:07:00 | 显示全部楼层
学习了,收藏!

出0入0汤圆

发表于 2016-1-19 09:31:29 | 显示全部楼层
不错,mark下

出0入0汤圆

发表于 2016-1-19 09:23:16 | 显示全部楼层
还是不大懂,学习了

出0入0汤圆

发表于 2015-12-1 16:33:02 | 显示全部楼层
不错,卡尔曼滤波,mark下

出0入0汤圆

发表于 2015-11-27 21:58:17 | 显示全部楼层
mark~ 卡尔曼滤波
感谢楼主分享

出0入0汤圆

发表于 2015-11-27 12:33:59 | 显示全部楼层
MARK

出0入0汤圆

发表于 2015-11-27 11:02:53 | 显示全部楼层
支持一下。

出0入0汤圆

发表于 2015-11-2 10:53:13 | 显示全部楼层
不错呀,学习了

出0入0汤圆

发表于 2015-10-29 12:44:31 | 显示全部楼层
好好学习一下。

出0入8汤圆

发表于 2015-10-25 08:54:35 | 显示全部楼层
有几个疑问:
1.有些情况下R、Q是已知的吧
2.卡尔曼滤波应该有一组观测值和一组估计值,然后用这两组数据可以得到融合值
观测值是已知的,估计值应该是用状态方程推出来吧?看程序里写的是当前时刻的估计值就是上一时刻的融合值,如果改成当前时刻的估计值等于上一时刻融合值通过状态方程推出的估计值,这样效果会不会好一点呢?

出0入0汤圆

发表于 2015-10-24 11:11:17 | 显示全部楼层
写得很详细,收藏了

出0入0汤圆

发表于 2015-9-12 02:53:32 来自手机 | 显示全部楼层
不错帖子

出0入0汤圆

发表于 2015-9-10 17:14:38 | 显示全部楼层
标记一下!

出0入0汤圆

发表于 2015-9-10 15:15:47 | 显示全部楼层
mark~写代码时可以参考一下

出0入4汤圆

发表于 2015-9-8 17:28:11 | 显示全部楼层
下下来好好看看

出0入0汤圆

发表于 2015-9-7 22:05:35 来自手机 | 显示全部楼层
楼主,能否发私信过来?因我无法发送私信,谢谢

出0入0汤圆

发表于 2015-8-31 23:50:26 | 显示全部楼层
多谢楼主,学习一下

出0入0汤圆

发表于 2015-8-31 21:43:47 | 显示全部楼层
学习下!

出0入0汤圆

发表于 2015-8-31 21:35:16 | 显示全部楼层
非常有用,感谢楼主的无私分享!

出0入0汤圆

发表于 2015-8-26 16:33:05 | 显示全部楼层
多谢楼主,学习一下

出0入0汤圆

发表于 2015-8-26 16:05:44 | 显示全部楼层
收藏了!

出0入0汤圆

发表于 2015-8-26 14:14:46 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2015-8-9 18:11:22 | 显示全部楼层
噢噢噢噢学习学习·~~~~感谢楼主

出0入0汤圆

发表于 2015-5-25 23:01:27 | 显示全部楼层
K.O.Carnivist 发表于 2014-4-18 19:18
应该是只要求噪声是是独立的高斯分布,没有要求平稳性。噪声协方差阵可以是时变的。 ...

如果是在要求高,必须用UKF

出0入0汤圆

发表于 2015-5-24 20:05:36 | 显示全部楼层
mark   mark   觉得卡尔曼有点难理解。

出0入0汤圆

发表于 2015-5-24 19:29:31 | 显示全部楼层
学习一下。

出0入0汤圆

发表于 2015-5-24 19:22:14 | 显示全部楼层
学习了,留下记号。

出0入0汤圆

发表于 2015-5-20 19:43:43 | 显示全部楼层
收藏了,哈哈

出0入0汤圆

发表于 2015-5-14 16:28:23 | 显示全部楼层
很专业的描述,算法是靠自己领悟的,但是需要更多的专业和应用知识。
卡尔曼滤波,不错。

出0入0汤圆

发表于 2015-5-3 09:47:08 | 显示全部楼层
收藏一个,不错!

出0入0汤圆

发表于 2015-4-28 20:31:09 | 显示全部楼层
不错,卡尔曼滤波,mark下

出0入0汤圆

发表于 2015-4-28 20:10:26 | 显示全部楼层
正在学习,不知道代码移植过来效果怎么样

出0入0汤圆

发表于 2015-4-28 15:56:50 | 显示全部楼层
楼主好样的,帮了我大忙了,谢谢。

出0入0汤圆

发表于 2015-3-20 13:48:40 | 显示全部楼层
看了一下,不过没有太明白,正在学习。
楼主在北京不?

出0入0汤圆

发表于 2015-3-19 17:14:05 | 显示全部楼层
学习了,谢谢分享

出0入0汤圆

发表于 2015-2-26 10:50:26 | 显示全部楼层
第一次听说这个滤波算法。标记一下,谢谢!

出0入0汤圆

发表于 2015-2-23 17:54:14 | 显示全部楼层
学习了,谢谢楼主分享

出0入0汤圆

发表于 2015-2-23 17:44:58 | 显示全部楼层
您这个不能算是真正的卡尔曼滤波哦

出0入0汤圆

发表于 2015-2-10 21:23:12 | 显示全部楼层
非常不错,收藏学习

出0入0汤圆

发表于 2015-2-7 23:33:04 | 显示全部楼层
谢谢分享,学到很多

出0入0汤圆

发表于 2015-1-19 21:35:27 | 显示全部楼层
make  卡尔曼

出0入0汤圆

发表于 2015-1-7 15:57:55 | 显示全部楼层
很不错,下载备用

出0入0汤圆

发表于 2015-1-7 15:44:59 | 显示全部楼层
这次总算看明白了!请问R和Q怎么确定,根据经验吗?

出0入0汤圆

发表于 2015-1-5 09:35:19 | 显示全部楼层
楼主厉害  下来学习学习

出0入0汤圆

发表于 2015-1-2 21:33:03 | 显示全部楼层
首先感谢楼主的奉献
看了好多遍,理论是看懂了,有个问题,想请教一个各位大侠。      
        
        
        double R = MeasureNoise_R;  R:测量噪声,R增大,动态响应变慢,收敛稳定性变好        
        double Q = ProcessNiose_Q;  Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
对于一个系统,比如说,室内温度测量系统吧,测温范围在0-30度,我知道我传感器+AD转换,总的精度是1%,
具体怎么确定Q 和 R 的值呢,或者说怎么估算呢?
虚心求教,请指点

出0入0汤圆

发表于 2014-12-31 23:49:35 | 显示全部楼层
看了很久的这个卡尔曼,还是没有搞明白!

出0入0汤圆

发表于 2014-12-31 23:31:51 | 显示全部楼层
先收藏一下

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-5-17 01:33

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

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