当前位置:   article > 正文

一维卡尔曼滤波器原理及应用(含C代码)_c语言卡尔曼滤波的详解

c语言卡尔曼滤波的详解

本文介绍一维卡尔曼滤波器原理及应用并用C代码实现。

1.基本概念

卡尔曼滤波(Kalman filter)是一种高效率的递归滤波器(自回归滤波器),它能够从一系列的不完全及包含噪声的测量中,估计动态系统的状态。卡尔曼滤波会根据各测量量在不同时间下的值,考虑各时间下的联合分布,再产生对未知变数的估计,因此会比只以单一测量量为基础的估计方式要准。

简单讲,卡尔曼滤波器既考虑测量值也考虑预测值(根据系统前一次的状态),来决定输出,因此相比传统的滤波器更加准确和可靠。

2.适用范围

卡尔曼滤波适用于线性高斯系统,即该系统必须是线性的,而且噪声服从正态分布(高斯分布)。更详细一些,噪声通常被建模为一个均值为0,方差为常数的正态分布,也就是高斯分布。该正态分布的横坐标是随机变量的取值,纵坐标是对应取值的概率密度。

3.建模

这里的建模是为系统建模,通过建模我们可以清楚的了解,系统是否可以通过卡尔曼滤波器进行处理,模型如下:

其中,

1)xk为k时刻信号值,xk-1为k-1时刻(前一次)信号值

2)uk为控制量,简单应用场景下一般为0

3)A,B,H是与系统有关的矩阵,一般为常数

4)wk为符合高斯分布的过程噪声,其协方差为Q

5)vk为符合高斯分布的测量噪声,其协方差为R

6)zk为测量值

公式1告诉我们信号值xk是前一次信号值xk-1的线性组合加上控制信号及过程噪声,其过程噪声要求符合高斯分布。

公式2告诉我们测量值是信号值的线性组合加上测量噪声,其测量噪声要求符合高斯分布。

通过对系统建模,我们了解系统是否可以通过卡尔曼滤波器进行处理。

4.公式

本文不介绍相关公式的推导,仅列出推导出的结论。想了解其推导过程可参阅其他资料。

其中,

Time Update(prediction)公式:

1) 为根据k-1时刻的值预测k时刻的结果,也写作Xk|k-1

2)为k-1时刻最优值,也写作Xk-1|k-1

3)A为状态下的变换矩阵

4)B为作用在控制量上的变换矩阵

5)uk为控制量,一般情况下为0

6)为根据k-1时刻的值预测k时刻系统协方差矩阵,也写作Pk|k-1

7)为k-1时刻系统协方差矩阵,,也写作Pk-1|k-1

8)Q为系统过程噪声的协方差

Measurement Update(correction)公式:

1)Kk为卡尔曼增益

2)H为对象的预测矩阵,当系统是一维的时候,H=1

3)R为对象测量噪声的协方差矩阵

4)zk为测量值,也就是输入值

5)为k时刻最优值,也就是输出值

A,B,H大多数情况下,它们为常数,系统为一维情况下为1,对于一个卡尔曼滤波器我们需要确定以下参数(难点):

1)R,初始值可根据传感器测量误差进行选择

2)Q,初始值可根据实际调试确定

3)x0,初始值一般可设置为0

4)P0,初始值一般可设置为1,P0=0表示完全相信测量值,P0=1表示完全相信估计值,一般是不能设置为0,否则Pk就一直为0了,可设置为1,在后续迭代的过程中,Pk会不断被修正

参数调节的一般方法:

根据公式,我们可以分析得出:R越大,Kk越小;Q越大,Kk越大。Kk越大我们越相信测量值,当我们使用的传感器比较精密,测量噪声很小时,我们越相信测量值,此时应该调小R,反之则调大,另外,当我们的系统模型越准确时,我们的预测值会越精确,此时我们越信任预测值,则应该调小Q。

5.迭代

与传统的数字滤波器(FIR,IIR)滤波器一样,卡尔曼滤波器也是采用迭代的方法进行计算。其迭代过程如下图所示。

迭代过程:

1)Time Update(prediction)。根据前一次状态预估下一时刻状态(输出值,错误协方差)

2)Measurement Update(correction)。计算卡尔曼增益,根据测量值(zk)及预估状态,计算当前最优估计值(输出值)

3)将当前状态赋予下一次状态(输出值,错误协方差),便于下一次计算

6.代码

一维的情况下各矩阵(A,H,I)为1,uk为0,要简单许多,直接套用公式即可,这里为了方便描述直接用float数据,如果MCU计算能力有限,也可以用整型数据进行计算,C代码如下:

  1. typedef struct _KALMAN_FILTER
  2. {
  3. float xk_1; //x(k-1|k-1)
  4. float Pk_1; //P(k-1|k-1)
  5. float xkk_1; //x(k|k-1)
  6. float Pkk_1; //P(k|k-1)
  7. float Kk; //Kk
  8. float xk; //x(k|k)
  9. float Pk; //P(k|k)
  10. float Q;
  11. float R;
  12. }KALMAN_FILTER;
  13. static void InitKalmanFilter(KALMAN_FILTER *pKalmanFilter);
  14. static float CalcKalmanFilter(KALMAN_FILTER *pKalmanFilter, float zk);
  15. static void InitKalmanFilter(KALMAN_FILTER *pKalmanFilter)
  16. {
  17. pKalmanFilter->xk_1 = 0;
  18. pKalmanFilter->Pk_1 = 1;
  19. pKalmanFilter->xkk_1 = 0;
  20. pKalmanFilter->Pkk_1 = 0;
  21. pKalmanFilter->Kk = 0;
  22. pKalmanFilter->xk = 0;
  23. pKalmanFilter->Pk = 0;
  24. pKalmanFilter->Q = 0;
  25. pKalmanFilter->R = 0.1f;
  26. }
  27. static float CalcKalmanFilter(KALMAN_FILTER *pKalmanFilter, float zk)
  28. {
  29. //prediction
  30. pKalmanFilter->xkk_1 = pKalmanFilter->xk_1;
  31. pKalmanFilter->Pkk_1 = pKalmanFilter->Pk_1 + pKalmanFilter->Q;
  32. //correction
  33. pKalmanFilter->Kk = pKalmanFilter->Pkk_1 / (pKalmanFilter->Pkk_1 + pKalmanFilter->R);
  34. pKalmanFilter->xk = pKalmanFilter->xkk_1 + pKalmanFilter->Kk * (zk - pKalmanFilter->xkk_1);
  35. pKalmanFilter->Pk = (1.0f - pKalmanFilter->Kk) * pKalmanFilter->Pkk_1;
  36. pKalmanFilter->xk_1 = pKalmanFilter->xk;
  37. pKalmanFilter->Pk_1 = pKalmanFilter->Pk;
  38. return pKalmanFilter->xk;
  39. }

7.应用

这里自行构造了一组数据,并比较原始数据和经过卡尔曼滤波后的数据。

  1. int main()
  2. {
  3. KALMAN_FILTER KalmanFilter;
  4. float rawData[10]= {0.39f, 0.50f, 0.48f, 0.29f, 0.25f, 0.32f, 0.34f, 0.48f, 0.41f, 0.45f};
  5. float filteredData[10] = {0};
  6. unsigned int i = 0;
  7. InitKalmanFilter(&KalmanFilter);
  8. for (i = 0; i < 10; i++)
  9. {
  10. filteredData[i] = CalcKalmanFilter(&KalmanFilter, rawData[i]);
  11. }
  12. printf("raw data:\r\n");
  13. for (i = 0; i < 10; i++)
  14. {
  15. printf("%.3f ", (double)rawData[i]);
  16. }
  17. printf("\r\n");
  18. printf("filtered data:\r\n");
  19. for (i = 0; i < 10; i++)
  20. {
  21. printf("%.3f ", (double)filteredData[i]);
  22. }
  23. printf("\r\n");
  24. return 0;
  25. }

8.输出结果

将输出数据复制到Excel中,绘制图像如下。

从图中可以明显看出经过卡尔曼滤波后的数据要比原始数据要平滑,且更符合实际情况。

总结,本文介绍了一维卡尔曼滤波器原理及应用并用C代码实现它。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/493740
推荐阅读
相关标签
  

闽ICP备14008679号