Kalman Filter(卡爾曼濾波)的個人筆記以及程序實現


簡單的介紹一下卡爾曼濾波器的關鍵的5個公式。

引入一個離散控制過程的系統。該系統可用一個線性隨機微分方程來描述:

  X(k)=A X(k-1)+B U(k)+W(k)

  再加上系統的測量值:

  Z(k)=H X(k)+V(k)

上兩式子中,X(k)是k時刻的系統狀態,U(k)是k時刻對系統的控制量。A和B是系統參數,對於多模型系統,他們為矩陣。Z(k)是k時刻的測量值,H是測量系統的參數,對於多測量系統,H為矩陣。W(k)和V(k)分別表示過程和測量的噪聲。他們被假設成高斯白噪聲,他們的協方差(covariance )分別是Q,R(這里我們假設他們不隨系統狀態變化而變化)

首先利用系統的過程模型來預測系統下一狀態,設在k時刻的系統狀態為x(k),則可以根據系統模型,由上一狀態預測出現在狀態:

x(k|k-1) = A x(k-1|k-1) + B u(k).....(1)

其中x(k|k-1)是上一時刻的狀態對現在時刻狀態的預測,x(k-1|k-1)是上一時刻狀態的最優結果, u(k)為現在時刻狀態的控制量。

系統的狀態已經更新,現在需要更新系統的誤差估計協方差矩陣,用p(k|k-1)表示誤差估計協方差矩陣:

p(k|k-1) = A p(k-1|k-1)A' + Q........(2)

其中p(k|k-1)是在k時刻由上一狀態對此狀態的預測, p(k-1|k-1)是x(k-1|k-1)對應的誤差估計協方差矩陣,A' 是A 的轉置。Q 表示系統過程噪聲的covariance。

現在我們得到了預測結果,然后我們根據得到的現在狀態的測量值進行更新(修正)(預測得到的)現在的狀態 x(k|k):

x(k|k) = x(k|k-1) + Kg(k) (Z(k)-Hx(k|k-1))....(3)

(3)式中 Kg(k)未知,則需要對其就行求解,就引出(4)式:

 Kg(k) = p(k|k-1) H' /(H p(k|k-1)H' + R)...(4)

到現在,我們以及得出的k 時刻的系統狀態的最優值x(k|k),為了讓卡爾曼濾波器不斷地進行下去,我們需要更新 x(k|k) 對應的p(k|k) (應用於式(2)):

p(k|k) = (I-Kg(k) H) p(k|k-1).....(5)

 

卡爾曼濾波實現的小程序:opencv+ C++

  1 #include "opencv2/video/tracking.hpp"
  2 #include "opencv2/highgui/highgui.hpp"
  3 #include <cmath>  
  4 #include <vector>
  5 #include <stdio.h>
  6 #include <iostream>
  7 
  8 using namespace cv;
  9 using namespace std;
 10 const int winHeight=600;  
 11 const int winWidth=800;
 12 
 13 Point move_mouse = Point(winWidth>>1,winHeight>>1);
 14 //mouse event callback  
 15 
 16 void mouseEvent(int event, int x, int y, int flags, void *param )
 17 {
 18     if (event==CV_EVENT_MOUSEMOVE)
 19     {  
 20         move_mouse=Point(x,y);  
 21     } 
 22 }
 23 
 24 
 25 int main()
 26 {
 27     
 28     ////1.kalman filter setup
 29 
 30     const int stateNum=4;  
 31     const int measureNum=2;
 32 
 33     KalmanFilter kalman(stateNum,measureNum,0);
 34     Mat processNoise(stateNum,1,CV_32F);
 35     Mat measureNoise(stateNum,1,CV_32F);
 36     Mat measurement (measureNum,1,CV_32F);
 37     float A[stateNum][stateNum] ={//transition matrix  
 38         1,0,1,0,  
 39         0,1,0,1,  
 40         0,0,1,0,  
 41         0,0,0,1  
 42     };  
 43 
 48     memcpy( kalman.transitionMatrix.data,A,sizeof(A));
 49     cout<<kalman.transitionMatrix<<endl;
 50     setIdentity(kalman.measurementMatrix);
 51     setIdentity(kalman.processNoiseCov,Scalar::all(1e-5));
 52     setIdentity(kalman.measurementNoiseCov,Scalar::all(1e-1));
 53     setIdentity(kalman.errorCovPost,Scalar::all(1));
 54 
 55     //initialize post state of kalman filter at random 
 56     randn(kalman.statePost,Scalar::all(0), Scalar::all(0.1));
 57     CvFont font;  
 58     cvInitFont(&font,CV_FONT_HERSHEY_SCRIPT_COMPLEX,1,1);  
 59 
 60    
 62     namedWindow("kalman",1);
 63     setMouseCallback("kalman",mouseEvent);
 64     
 65     Mat img(500, 500, CV_8UC3);
 66     while (1)
 67     {
 68         //2.kalman prediction
 69         Mat prediction = kalman.predict();
 70         Point predict_pt = Point(prediction.at<float>(0),prediction.at<float>(1));
 71  
 72        //3.update measurement 
 73 
 74         measurement.at<float>(0) = (float)move_mouse.x;
 75         measurement.at<float>(1) = (float)move_mouse.y;
 76 
 77         //4.update
 78         kalman.correct(measurement);
 79 
 80 
 81         //5.draw
 82 
 84         img = Scalar::all(0);
 85         circle(img,predict_pt,4,CV_RGB(0,255,0),2);//predicted point with green 
 86         circle(img,move_mouse,4,CV_RGB(255,0,0),2);//current position with red
 87      
 93     imshow("kalman", img);  
 94         int key=cvWaitKey(3);  
 95         if (key==27)
 96         {
 97             break;    
 98         }
 99     }
101     system("pause");
102     return 0;
103 }

程序說明:

本程序由http://blog.sina.com.cn/s/blog_9db9f81901015wuo.html 稍作修改適應新版本的opencv。

程序主要由以下幾個部分:

1.實例化一個 KalmanFilter 的對象kalman,聲明並初始化矩陣processNoise,measureNoise, measurement ;

注意:要設置的變量主要是KalmanFilter的成員,否則會出現跟蹤效果不好或者出錯

Mat statePre;    //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k)
Mat statePost;    //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))
Mat transitionMatrix;    //!< state transition matrix (A)
Mat controlMatrix;    //!< control matrix (B) (not used if there is no control) 
Mat measurementMatrix;    //!< measurement matrix (H)
Mat processNoiseCov;   //!< process noise covariance matrix (Q)
Mat measurementNoiseCov;  //!< measurement noise covariance matrix (R)
Mat errorCovPre;   //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/
Mat gain;  //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)
Mat errorCovPost;    //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k)

2.預測KalmanPredict,只需要調用函數 predict() ,然后讀出自己需要的值

3.根據采集到的數據更新觀測數據

4.用觀測數據來更新預測狀態值。

 

 

參考資料:http://blog.sina.com.cn/s/blog_4c2b25550100b8yq.html

http://blog.csdn.net/yangtrees/article/details/8075911#comments 學習OpenCV——Kalman濾波


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM