找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7684|回復(fù): 5
收起左側(cè)

STM32單片機(jī)卡爾曼濾波程序分享

  [復(fù)制鏈接]
ID:582568 發(fā)表于 2019-8-6 17:42 | 顯示全部樓層 |閱讀模式
在網(wǎng)上找的卡爾曼濾波在自己理解的基礎(chǔ)上更改了一下代碼!實測有用

單片機(jī)源程序如下:
  1. /* Includes ------------------------------------------------------------------*/
  2. #include "stm32f10x.h"       
  3. #include "kalman.h"       
  4. #include "matrix.h"                                                                                 

  5. /*==============================================================================
  6. 1.預(yù)估計
  7.    X(k|k-1) = F(k,k-1)*X(k-1|k-1)        //控制量為0


  8. 2.計算預(yù)估計協(xié)方差矩陣
  9.    P(k|k-1) = F(k,k-1)*P(k-1|k-1)*F(k,k-1)'+Q(k)
  10.    Q(k) = U(k)×U(k)'


  11. 3.計算卡爾曼增益矩陣
  12.    Kg(k) = P(k|k-1)*H' / (H*P(k|k-1)*H' + R(k))
  13.    R(k) = N(k)×N(k)'


  14. 4.更新估計
  15.    X(k|k) = X(k|k-1)+Kg(k)*(Z(k)-H*X(k|k-1))


  16. 5.計算更新后估計協(xié)防差矩陣
  17.    P(k|k) =(I-Kg(k)*H)*P(k|k-1)


  18. 6. 更新最優(yōu)值


  19. F(k,k-1):     狀態(tài)轉(zhuǎn)移矩陣
  20. X(k|k-1):     根據(jù)k-1時刻的最優(yōu)值估計k時刻的值
  21. X(k-1|k-1):   k-1時刻的最優(yōu)值
  22. P(k|k-1):     X(k|k-1)對應(yīng)的covariance
  23. P(k-1|k-1):   X(k-1|k-1)對應(yīng)的covariance
  24. Q(k):         系統(tǒng)過程的covariance
  25. R(k):         測量過程的協(xié)方差
  26. H(k):         觀測矩陣轉(zhuǎn)移矩陣
  27. Z(k):         k時刻的測量值


  28. 基本思路: 首先根據(jù)上一次(如果是第一次則根據(jù)預(yù)賦值計算)的數(shù)據(jù)計算出本次的估計值,
  29.           同理,根據(jù)上一次的數(shù)據(jù)計算出本次估計值的協(xié)方差;  接著,由本次估計值的協(xié)
  30.           方差計算出卡爾曼增益;  最后,根據(jù)估測值和測量值計算當(dāng)前最優(yōu)值及其協(xié)方差
  31. ==============================================================================*/



  32. //================================================//
  33. //==             最優(yōu)值方差結(jié)構(gòu)體               ==//
  34. //================================================//
  35. typedef struct  _tCovariance
  36. {
  37.   float PNowOpt[LENGTH];
  38.   float PPreOpt[LENGTH];
  39. }tCovariance;







  40. static tOptimal      tOpt;
  41. static tCovariance   tCov;
  42. //float         Z[LENGTH]  = {4000};           //  測量值(每次測量的數(shù)據(jù)需要存入該數(shù)組)
  43. static float         I[LENGTH]  = {1};              //  單位矩陣
  44. static float         X[LENGTH]  = {9.8};              //  當(dāng)前狀態(tài)的預(yù)測值
  45. static float         P[LENGTH]  = {0};              //  當(dāng)前狀態(tài)的預(yù)測值的協(xié)方差
  46. static float         K[LENGTH]  = {0};              //  卡爾曼增益
  47. static float         Temp3[LENGTH] = {0};           //  輔助變量
  48. //============================================================================//
  49. //==                    卡爾曼濾波需要配置的變量                            ==//
  50. //============================================================================//
  51. static float         F[LENGTH]  = {1};              //  狀態(tài)轉(zhuǎn)移矩陣   即:堅信當(dāng)前的狀態(tài)與上一次狀態(tài)的關(guān)系,如果堅信是一樣的,則狀態(tài)轉(zhuǎn)移矩陣就為單位矩陣
  52. static float         Q[LENGTH]  = {0.0001f};//0.0001f              //  系統(tǒng)過程的協(xié)方差        協(xié)方差的定義:真實值與期望值之差的平方的期望值
  53. static float         R[LENGTH]  = {2};              //  測量過程的協(xié)方差        協(xié)方差的定義:真實值與期望值之差的平方的期望值   
  54. //如果你需要濾波結(jié)果更依賴于觀測量,那就調(diào)小R,增大Q;反之,調(diào)大R,調(diào)小Q,這樣估計值就取決于系統(tǒng)。
  55. //如果R大Q小,就是說,狀態(tài)估計值比測量值要可靠,這時,所得出的結(jié)果就是更接近估計值;
  56. //如果R小Q大,這時,計算出來的結(jié)果就會更接近測量值。
  57. static float         H[LENGTH]  = {1};              //  觀測矩陣轉(zhuǎn)移矩陣        測量值與狀態(tài)預(yù)測值之間的單位換算關(guān)系,即把預(yù)測值單位換算成測量值單位
  58. static float         Temp1[LENGTH] = {1};           //  輔助變量, 同時保存tOpt.XPreOpt[]的初始化值
  59. static float         Temp2[LENGTH] = {10000};       //  輔助變量, 同時保存tCov.PPreOpt[]的初始化值


  60. void KalMan_PramInit(void)
  61. {
  62.   unsigned char   i;
  63.   
  64.   for (i=0; i<LENGTH; i++)
  65.   {
  66.     tOpt.XPreOpt[i] = Temp1[i];           //零值初始化
  67.   }
  68.   for (i=0; i<LENGTH; i++)
  69.   {
  70.     tCov.PPreOpt[i] = Temp2[i];           //零值初始化
  71.   }
  72. }


  73. //============================================================================//
  74. //==                          卡爾曼濾波                                    ==//
  75. //============================================================================//
  76. //==入口參數(shù): 當(dāng)前時刻的測量值                                                            ==//
  77. //==出口參數(shù): 當(dāng)前時刻的最優(yōu)值                                                            ==//
  78. //==返回值:   當(dāng)前時刻的最優(yōu)值                                                            ==//
  79. //============================================================================//
  80. float KalMan_Update(float *Z)
  81. {
  82.         u8 i;  
  83.         MatrixMul(F, tOpt.XPreOpt, X, ORDER, ORDER, ORDER);       //  基于系統(tǒng)的上一狀態(tài)而預(yù)測現(xiàn)在狀態(tài); X(k|k-1) = F(k,k-1)*X(k-1|k-1)

  84.         MatrixCal(F, tCov.PPreOpt, Temp1, ORDER);
  85.         MatrixAdd(Temp1, Q, P, ORDER, ORDER);                     //  預(yù)測數(shù)據(jù)的協(xié)方差矩陣; P(k|k-1) = F(k,k-1)*P(k-1|k-1)*F(k,k-1)'+Q

  86.         MatrixCal(H, P, Temp1, ORDER);
  87.         MatrixAdd(Temp1, R, Temp1, ORDER, ORDER);
  88.         Gauss_Jordan(Temp1, ORDER);
  89.         MatrixTrans(H, Temp2, ORDER, ORDER);
  90.         MatrixMul(P, Temp2, Temp3, ORDER, ORDER, ORDER);
  91.         MatrixMul(Temp1, Temp3, K, ORDER, ORDER, ORDER);          //  計算卡爾曼增益; Kg(k) = P(k|k-1)*H' / (H*P(k|k-1)*H' + R)

  92.         MatrixMul(H, X, Temp1, ORDER, ORDER, ORDER);
  93.         MatrixMinus(Z, Temp1, Temp1, ORDER, ORDER);
  94.         MatrixMul(K, Temp1, Temp2, ORDER, ORDER, ORDER);
  95.         MatrixAdd(X, Temp2, tOpt.XNowOpt, ORDER, ORDER);          //  根據(jù)估測值和測量值計算當(dāng)前最優(yōu)值; X(k|k) = X(k|k-1)+Kg(k)*(Z(k)-H*X(k|k-1))

  96.         MatrixMul(K, H, Temp1, ORDER, ORDER, ORDER);
  97.         MatrixMinus(I, Temp1, Temp1, ORDER, ORDER);
  98.         MatrixMul(Temp1, P, tCov.PNowOpt, ORDER, ORDER, ORDER);   //  計算更新后估計協(xié)防差矩陣; P(k|k) =(I-Kg(k)*H)*P(k|k-1)

  99.         for (i=0; i<LENGTH; i++)
  100.         {
  101.           tOpt.XPreOpt[i] = tOpt.XNowOpt[i];
  102.           tCov.PPreOpt[i] = tCov.PNowOpt[i];
  103.         }
  104.        
  105.         return tOpt.XNowOpt[0];
  106. }
復(fù)制代碼

所有資料51hei提供下載:
kalman.7z (3.71 KB, 下載次數(shù): 252)


回復(fù)

使用道具 舉報

ID:261849 發(fā)表于 2020-3-23 15:24 | 顯示全部樓層
謝謝分享,比較容易理解.
回復(fù)

使用道具 舉報

ID:401936 發(fā)表于 2020-4-2 20:14 | 顯示全部樓層
首先感謝樓主分享!然后小白想問下卡爾曼濾波返回值不應(yīng)該是下一時刻的最優(yōu)值嗎
回復(fù)

使用道具 舉報

ID:920454 發(fā)表于 2021-5-13 09:52 | 顯示全部樓層
tOptimal 這個結(jié)構(gòu)體的定義在哪兒?
回復(fù)

使用道具 舉報

ID:319585 發(fā)表于 2021-5-13 17:38 來自手機(jī) | 顯示全部樓層
這個不錯,感覺論壇代碼的質(zhì)量越來越高了。
回復(fù)

使用道具 舉報

ID:829464 發(fā)表于 2021-7-21 16:07 | 顯示全部樓層
6啊 樓主
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表