信号处理 --- 卡尔曼滤波在检测气体浓度中的应用

2020-03-08 19:20发布

本帖最后由 会笑的星星 于 2020-1-4 22:15 编辑

在使用气体传感器检测气体浓度时,由于传感器本身受到温度、湿度、以及其它未知因素的影响使得其输出值并不能代表真实的浓度值,也由于这些原因导致气体浓度的检测常常出现偏差。一般而言,为了解决传感器的偏差问题,我们需要加入温度传感器以对其采样值进行补偿,从而减少传感器的偏差,但尽管如此,有些传感器的检测结果依然存在较大偏差。对于这种情况我们有没有什么办法解决呢?我们先把一个带有温度补偿的气体检测系统抽象为一个模型,如下方框图:
clipboard.png
在这个模型中,1式xk表示当前传感器真实值,x(k-1)表示上一次传感器的真实值,μk表示温度补偿值,用于修正当前的真实浓度,A、B可以理解为他们各自的权重值(在实际中A、B是一个矩阵,因为我们只需要求解浓度值,这个矩阵只有一个值,因此可以把他理解为一个普通的数值即可),ω是服从高斯分布的噪音,因此xk也服从高斯分布。事实上,这个式子与数字低通滤波器是有点相似的。2式yk表示传感器的输出值,他的值与xk是成比例关系的,比例系数为C(也是矩阵,但这里也只有一个值,可以等效于一个普通的数值),υ是服从高斯分布的噪音,因此yk也服从高斯分布。

为了方便讨论,我把A、B、C都设为1,具体可能需要在实际使用时做调整。把参数填入模型的各个方程,结果如下:
clipboard1.png

可以看到,上述的抽象系统中,方程1是一个线性方程 --- xk随着x(k-1)以及uk增加而线性增加,同理,方程2也时一个线性方程。对于这样的两个线性方程,我们该怎么知道真实值xk呢,线性卡尔曼滤波器就是为此而生,它利用数学模型结合传感器的输出值(yk)估算出传感器的真实值,从数学上可以证明,卡尔曼滤波器总能逼近真实值,这就是卡尔曼滤波器的伟大之处。
如下图所示的一个线性卡尔曼滤波器模型,这个滤波器的输出^yk等价于真实系统的yk,该滤波器的输出^xk等价于真实系统的xk,^xk、^yk这两个值都服从高斯分布。现在我们的目标就是求得卡尔曼滤波器的估算值^xk,并把这个值做为浓度检测的真实值。
clipboard555.png
要求解这个值^xk,我们需要分两步走,第一步是求解预估值,第二步则是利用传感器的输出值yk修正预估值,这个修正后的结果就是我们要获得的最终估计值。如何求解预估值以及修正预估值?还好伟大的数学家卡尔曼早已经帮我们解决了。我们先来看看第一步求解预估值,它的计算公式如下:
clipboard4.png
看上去很复杂,但仅仅弄明白这个公式各个参数的意义并不难,我们一个一个的来解释。
首先看1式。等式左边的结果就是预估值(预估值服从高斯分布),等式右边^x(k-1)表示上一次最终估计值,μk表示考虑温度补偿后的补偿值。A、B就是上述真实系统中方程1的A、B值,这一个方程理解起来并不难,有些困难的是理解第二个公式。
在第2个公式中,等式的左边表示的是预估值的方差(因为预估值并不是确定的,方差就是用于衡量它的波动性),等式的右边P(k-1)表示上一次最终估计值的方差。A同通方程1中的A,A^T本意是矩阵A的转置矩阵,但我们要解决的问题中A是只有一个元素的矩阵,因此A=A^T。Q表示为了应对更多的不确定性因素而引入的一个方差,以修正公式2等式左边的预估值方差,这个值需要自己估算然后根据情况调整。
由于A、B在我们要解决的问题中其值都是1,因此,上述预估值方程表示如下:
clipboard5.png                  预估值方程

有了预估值方程,第二步就是利用传感器的输出值修正预估值。怎么做呢,我们就需要用到卡尔曼滤波的第二组公式:
clipboard6.png
这一组公式更为复杂,不过也不用担心,就我们要解决的问题来说并不难懂。首先看方程1,这个方程的左边被称为卡尔曼增益,方程右边Pk^-就是预估值方差,这在前面说了。参数C是真实系统方程2中xk的系数,对我们的问题而言它是只有一个元素的矩阵,C^T则是C的转置矩阵,在这里C=C^T=1。参数R比较简单,表示的是传感器检测值方差(这个值可以从传感器规格书或者自己实验得知)。
再看方程2,这个方程左边^xk就是我们最终估计值。方程右边由两项组成,第一项就是我们第一步需要求出来的传感器预估值,第二项自身由两部分构成,一个是卡尔曼增益Kr,另一部分就是传感器的检测值yk与卡尔曼模型输出的估计值^yk的差,然后将这两部分相乘得到第二项。
在看方程3,这个方程的左边就是本次最终估计值方差,方程右边涉及的参数上面都解释了,这里不在赘述。
由于C=C^T=1,由此卡尔曼滤波的第二组公式表示如下:
clipboard7.png                 预估值修正方程
卡尔曼模型的整个原理就说完了,接着我们看看怎么用卡尔曼波滤来解决我们的问题 --- 估算真实浓度值,先举一个具体的例子帮助理解,最后再实现程序。
我们首先看预估值方程。在方程1中,^x(k-1)的值是我们上一步求出来的最终估计值,我们假设其值为20。μk则是温度补偿值(获取此刻温度后确定此温度下应该补偿多少浓度值,这个需要试验或者传感器规格书中获知),我们假设此时传感器的补偿量为5,这样我们就知道了此时的预估值= 5+20 = 25。
接下来计算预估值方程2的方差值,同样的我们假设上一步最终估计值方差P(k-1)=3,引入的不确定性方差Q = 2,这样,我们就知道了预估值方差Pk^- = 5。
我们求出了预估值方程的所有值,接下来就可以使用更新预估值方程更新预估值,我们先看更新方程1,这个方程只有一个未知数即传感器检测方差R,这里假设R=5,那么Kr = 5/(5 + 5) = 0.5。
接着我们看看方程2,由于Kr已经求出,yk为传感器的输出值,假设此时yk = 40,那么最终估计值^xk = 25 + 0.5*(40-25) = 32.5,这个值就是我们要求出来的目标值,同时也将用于下一次的预估值运算中。

最后就是利用方程3,更新最终估计值方差 Pk = (1-0.5)*5 = 2.5,这个方差也将用在下一次的预估值方差计算中。
有了上述分析以及例子,我们实现使用卡尔曼滤波来预测真实的浓度值就相对简单了,代码如下:
  1. //kalman filter
  2. //设卡尔曼模型的初始浓度值^x0 = 0,人为引入方差Q=2,传感器方差R=5。
  3. //在我们的真实系统模型中,A、B、C都是取1

  4. uint8_t R = 5; //传感器检测方差
  5. uint8_t Q = 2;  //为应对不确定性人为引入的方差

  6. uint8_t  xk_pre = 0; //预估值
  7. float  pk_pre = 0;   //预估值方差

  8. uint8_t  xk_updata = 0;     //最终浓度估计值
  9. float pk_updata = 0;        //最终浓度估计值方差

  10. float Kr = 0;  //卡尔曼增益

  11. uint8_t real_con = 0; //最终估计的浓度值

  12. //获得特定温度下的温度补偿值
  13. extern uint8_t app_get_temp_compensation_value(uint8_t temp);
  14. //获取传感器的浓度值
  15. extern uint8_t app_get_sensor_value();

  16. uint8_t  app_kalman_filter(uint8_t yk, int compensation_v)
  17. {
  18.   //计算预估值
  19.   xk_pre = xk_updata + compensation_v;
  20.   pk_pre = pk_updata + Q;
  21.   //更新预估值
  22.   Kr = pk_pre / (pk_pre + R);
  23.   xk_updata = xk_pre + Kr*(yk-xk_pre);
  24.   pk_updata = (1-Kr)*pk_pre;
  25.   
  26.   return xk_updata;
  27. }

  28. void app_get_cur_concentration(void )
  29. {
  30.   uint8_t yk;
  31.   int c_v; //之所以为int是因为这个补偿值可能是负值
  32.   uint8_t con;
  33.   
  34.   //获取温度补偿值
  35.   c_v= app_get_temp_compensation_value(cur_temprature)
  36.   //获取当前传感器值
  37.   yk = app_get_sensor_value();
  38.   //使用卡尔曼滤波得到浓度估计值
  39.   con = app_kalman_filter(yk,c_v);
  40.   
  41.   return con;
  42. }

  43. void app_clk_100ms(void )
  44. {  
  45.   real_con = app_get_cur_concentration()  
  46. }
复制代码我们分析卡尔曼滤波的原理花了很大的篇幅,但是据此写的代码却很简单。在使用卡尔曼滤波器时,对我们来说最大的困难在于未滤波器选择合适的参数,比如A、B、C以及方差R、Q,这些无疑需要在实际中根据情况来更改,这也是在实际中应用卡尔曼滤波器的难点所在。

事实上,卡尔曼滤波又被称为传感器融合算法,它可以融合多个传感器得出一个最佳估计。这到是给我一个想法,能否使用两个便宜且不同厂家的同种气体传感器达到一个识别同种气体但性能很好(也很贵,价格可能是便宜的传感器的几倍)的传感器相同效果呢?俗话说3个臭皮匠能顶过一个诸葛亮。假如我们真的要这么做的话对卡尔曼滤波来说是不难的,限于篇幅,这里我就不再展开了,如果你有兴趣,我可以再写一篇关于融合2个以上传感器的卡尔曼滤波算法。
总结一下,什么是卡尔曼滤波器 ? 利用传感器的输出值估算出真实值的滤波器就是卡尔曼滤波器。什么时候可以考虑使用它?当系统的检测值受到噪音影响导致传感器的检测值并不可信,这时为了得到真实值,我们可以考虑使用卡尔曼滤波器来估算真实值。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。