天天看點

C#實作卡爾曼濾波器

理論部分:

卡爾曼濾波器,是一個最優化自回歸資料處理算法。簡單的說就是通過現有測量值,來預測最優值。

網上的一些教程上來就是一大堆推導公式,很是羞澀難懂。我們先說個例子,來了解:

 假設我們要研究的對象是一個房間的溫度。      

 1.根據經驗,溫度是恒定的,即上一分鐘的溫度等于現在這一分鐘的溫度,經驗即預測,但這并不是完全可信的,即存在一定的誤差。我們假設成高斯白噪聲。      

 2.另外在房間裡放一個溫度計,實時檢測房間的溫度,這是觀測值。同樣地也存在誤差,也是高斯白噪聲。

我們現在的目标就是,用這兩個值,結合它們各自的噪聲,估算出房間的實際溫度。假設要估算k時刻的實際溫度值,首先需要知道k-1時刻的溫度值。      

 (1)預測值,假設k-1時刻房間溫度為23度,則k時刻的溫度應該也為23度(恒定)。同時該值的偏差為5(5是3的平方加上4的平方再開方,其中3為k-1時刻估算出的最優溫度值的偏差3,4為測量的偏差)。        

(2)測量值,假設為25度,同時偏差為4度。        

那麼實際值為多少?相信誰多一點,可用它們的協方差來判斷:

C#實作卡爾曼濾波器

則實際的溫度值是:23+0.78*(25-23) = 24.56度。可以看出溫度計測量的covariance較小,是以實際值比較偏向溫度計。

在進入k+1時刻估算前,需要算出k時刻最優值(24.56)的偏差。算法

C#實作卡爾曼濾波器

,5即k時刻估算所用k-1時刻23度溫度值的偏差。得出的2.35即k時刻最優值的偏差(對應上面k-1時刻的3)。

        這樣卡爾曼濾波器就不斷得把covariance遞歸,進而估算出最優值。而且它隻保留上一刻的covariance。上面的Kg就是卡爾曼增益(Kalman Gain)。

将該例子用數學公式來描述:

 首先引入一個離散控制過程的系統,改系統可用一個線性随機微分方程(linear stochastic difference equation)來描述:

C#實作卡爾曼濾波器

再加上系統的測量值:

C#實作卡爾曼濾波器

其中:X(k)是k時刻的系統狀态,U(k)是k時刻對系統的控制量。A和B是系統參數,對于多模系統,它們為矩陣。

Z(k)是k時刻的測量值,H是測量參數,對于多模系統,H為矩陣。W(k)和V(k)分别表示過程和測量的噪聲,它們被假設成高斯白噪聲,它們的covariance分别是Q,R。

對于滿足上面條件(線性随機微分系統,過程和測量都是高斯白噪聲),卡爾曼濾波器是最優的資訊處理器。

卡爾曼濾波器算法流程及核心公式

首先利用系統過程模型,來預測下一個狀态的系統:

C#實作卡爾曼濾波器

X(k | k-1) 是利用上一狀态預測的結果,X(k-1 | k-1) 是上一狀态最優結果。U(k)為現在狀态的控制量,若沒有,可為0.        

現在更新 X(k | k-1) 的covariance,用P表示:

C#實作卡爾曼濾波器

其中 P(k | k-1) 是 X(k | k-1) 對應的covariance;P(k-1 | k-1) 是 X(k-1 | k-1) 對應的covariance。A' 表示A的轉置矩陣,Q是系統的covariance。      

 式(1)(2)是5各公式的前兩個,用來對系統進行預測。        

然後再收集系統的觀測值 Z(k),則最優值:

C#實作卡爾曼濾波器

其中Kg為卡爾曼增益(Kalman Gain):

C#實作卡爾曼濾波器

到目前為止,已經得到k狀态下最優的估算值 X(k | k-1)。        

但是為了要卡爾曼濾波器不斷得運作下去直到系統過程結束,需要更新k狀态下 X(k | k-1) 的covariance:

C#實作卡爾曼濾波器

其中I為1的矩陣,對于單模系統I = 1。        

當系統進入k+1狀态時,P(k | k) 就是式(2)中的 P(k-1 | k-1)。這樣,算法就可以自回歸地運算下去。

C#程式實作

/*
    % Kalman filter example of temperature measurement in Matlab implementation of Kalman filter algorithm.
    % 房間目前溫度真實值為1.5度,認為下一時刻與目前時刻溫度相同,誤差為0.02度(即認為連續的兩個時刻最多變化0.02度)。
    % 溫度計的測量誤差為0.5度。
    % 開始時,房間溫度的估計為1.2度,誤差為0.5度。         
  */
           

定義變量:

int N = 5000;           //測試資料個數
        float x = 1.5f;         //溫度的真實值
        float Q = 0.0004f;      //過程方差。 (連續兩個時刻溫度方差)
        float R = 0.25f;        //測量方差。 (測量誤差的平方)

        float Z = 0.0f;         //測量值-在真實值的基礎上加上了方差為0.25的高斯噪聲。

        float X_First = 0.0f;   //溫度計的先驗估計
        float P_First = 0.0f;   //溫度計的先驗方差
        float X_End = 1.2f;     //溫度計的後驗估計
        float P_End = 0.5f;     //溫度計的後驗方差

        float K = 0.0f;         //卡爾曼增益,平方
           

計算:

private void KaermanCalc()
        {
            //測量值-在真實值的基礎上加上了方差為0.25的高斯噪聲。
            Z = x + (float)Math.Sqrt(R) * rd.Next(-100, 100) / 20;

            //卡爾曼最優值估計
            X_First = X_End;
            P_First = P_End + Q;
            K = P_First / (P_First + R);
            X_End = X_First + K * (Z - X_First);
            P_End = (1 - K) * P_First;
        }
           

最終實作效果:

C#實作卡爾曼濾波器

完整工程代碼連接配接:

https://download.csdn.net/download/panjinliang066333/12376929

繼續閱讀