1. 程式人生 > >MATLAB-卡爾曼濾波簡單運用示例

MATLAB-卡爾曼濾波簡單運用示例

south noi 增加 jacob mage 影響 方差 sqrt mark

1、角度和弧度之間的轉換公式?
設角度為 angle,弧度為 radian
radian = angle * pi / 180;
angle = radian * 180 / pi;
所以在matlab中經常設置一個參數,用於角度與弧度之間的轉換:deg_rad=0.01745329252e0;

2、註意下面角度Angint的表示方法:
Angint=[0,10,0]*deg_rad;
則:Angint(0) = 0;Angint(1) = 0.0175;Angint(2) = 0;
這種表示方法可以在四元數中應用:
例如:
q=[cos(Angint(3)/2)*sin(Angint(2)/2)*cos(Angint(1)/2)+sin(Angint(3)/2)*cos(Angint(2)/2)*sin(Angint(1)/2)
cos(Angint(3)/2)*cos(Angint(2)/2)*sin(Angint(1)/2)-sin(Angint(3)/2)*sin(Angint(2)/2)*cos(Angint(1)/2)
-sin(Angint(3)/2)*cos(Angint(2)/2)*cos(Angint(1)/2)+cos(Angint(3)/2)*sin(Angint(2)/2)*sin(Angint(1)/2)
cos(Angint(3)/2)*cos(Angint(2)/2)*cos(Angint(1)/2)+sin(Angint(3)/2)*sin(Angint(2)/2)*sin(Angint(1)/2)];
可以用q(0)、q(1)、q(2)、q(3)來代入公式計算三軸姿態角。

3、在濾波的過程中,要明確濾波時間和采樣頻率;

4、IMU數據仿真分析:
(1)先模擬加速度計和陀螺儀的真實輸出:
[ Angle,Wibb,Fb ] = imu_true_out( tt,ynong,T );%tt=tt+TT;TT=1/f為時間間隔
註意:加速度計的輸出要進行坐標轉換: ao=Cnb*([0,0,g]’,
其中:Cnb

技術分享圖片

如果你要在加速度計的輸出上添加一個隨機幹擾(可模擬非重力加速度幹擾),可以使用函數awgn(); %Add white Gaussian noise to a signal.
ao=Cnb*([0,0,g]’+[0,awgn(0,ynong),0]’); %如果在指點的時間內添加這種幹擾,可以加一個if函數

2)模擬加速度計和陀螺儀的誤差:
[Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(tt,TT,Gyro_b,Gyro_r,Gyro_wg,Acc_r);

function [Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(t,T,Gyro_b,Gyro_r,Gyro_wg,Acc_r)

g=9.7803698;         %重力加速度    (單位:米/秒/秒)
Wie=7.292115147e-5;  %地球自轉角速度(單位:弧度/秒)
deg_rad=0.01745329252e0;% Transfer from
angle degree to rad Da_bias=[0.001; 0.001; 0.001]*g; %加速度零偏(應與非隨機性誤差中的加速度零偏保持一致) Ta=1800.0; %加速度一階馬爾可夫過程相關時間 Tg=3600.0; %陀螺一階馬爾可夫過程相關時間 %%%%%%%%%%%%%%%%%%隨機性誤差%%%%%%%%%%%%%%% if( t==0 ) Acc_r=Da_bias.*randn(3,1); %加速度一階馬爾可夫過程1.0e-4g Gyro_b=0.01*deg_rad/3600.0*randn(3,1); %隨機常數0.1(deg/h) Gyro_r=0.01*deg_rad/3600.0*randn(3,1); %陀螺一階馬爾可夫過程0.1(deg/h) Gyro_wg=0.01*deg_rad/3600.0*randn(3,1);%陀螺白噪聲0.1(deg/h) else Acc_wa=sqrt(2*T/Ta)*Da_bias.*randn(3,1);%加速度一階馬爾可夫過程白噪聲 Acc_r=exp(-1.0*T/Ta)*Acc_r; %加速度一階馬爾可夫過程 Gyro_wr=0.01*sqrt(2*T/Tg)*deg_rad/3600.0*randn(3,1);%陀螺一階馬爾可夫過程白噪聲0.1(deg/h) Gyro_r=exp(-1.0*T/Tg)*Gyro_r+Gyro_wr;%陀螺一階馬爾可夫過程0.1(deg/h) Gyro_wg=0.01*deg_rad/3600.0*randn(3,1);%陀螺白噪聲0.1(deg/h) end

然後再在while(1)中將真實值+誤差值按時間序列存儲在數組中以備用,如下:

while tt<=T;
    [ Angle,Wibb,Fb ] = imu_true_out( tt,ynong,T );
    [Gyro_b,Gyro_r,Gyro_wg,Acc_r]=imu_err_random(tt,TT,Gyro_b,Gyro_r,Gyro_wg,Acc_r);
    Ture_Angle(:,kk)=Angle/deg_rad;%模擬輸出的三軸姿態角
    gyro(:,kk)=Wibb+Gyro_b+Gyro_r+Gyro_wg;%模擬輸出的陀螺儀輸出
    acc(:,kk)=Fb+Acc_r;%模擬輸出的加速度計輸出
    tt=tt+TT;
    kk=kk+1;%這裏TT=1/f=1/100為采樣時間間隔,f為采樣頻率,T為采樣時間,文中設置為30s
end

5、函數randn的意思:
R = randn(3,1);%產生3行1列的隨機R矩陣,R矩陣滿足方差為1,均值為0;註意這裏不是說這三個數的方差為1,均值為0,而是每次運行randn時,當運行的量足夠大時,所有的R(0)的方差為1,均值為0,R(1)、R(2)同理。
例如1. randn(1) ;%生成一個隨機數,要想滿足方差為1,均值為0,也必須運行足夠多的次數
例如2. x = .6 + sqrt(0.1) * randn(1);%產生均值為0.6,方差為0.1的一個5*5的隨機數;sqrt(0.1)對0.1進行開方,直接寫0.1那這裏就是表示標準差了

randi([m,n],a,b) %[m,n] 的 a*b 隨機數

6、axis()函數的用法:
axis([xmin xmax ymin ymax]);%定義x軸和y軸之間的間距

7、set()函數的用法:
plot(t,acc(2,:),linewidth,1.3); set(gcf,Position,[100 100 400 300]); %這裏的100是指生成的圖片距離左下角的距離,400和300分別表示長和寬 axis([0 T -4.9 2.0]); set(gca, YTick, [-4.9 -2.4 -0.1 2.0]) set(gca,fontname,宋體,fontsize,10); %用於改變坐標軸坐標大小,10代表坐標大小; xlabel(時間/s,fontname,宋體,fontsize,10);%用於改變x軸標註的文字和大小; ylabel(加速度計數據/(g),fontname,宋體,fontsize,10);%用於改變y軸標註的文字和大小; legend(accy);%標註
技術分享圖片



8、EKF的matlab實現:

kalman的前提條件:

1)線性系統
2)系統噪聲和測量噪聲服從高斯分布


卡爾曼最初提出的濾波理論只適用於線性系統,Bucy,Sunahara等人提出並研究了擴展卡爾曼濾波(Extended Kalman Filter,簡稱EKF),將卡爾曼濾波理論進一步應用到非線性領域。EKF的基本思想是將非線性系統線性化,然後進行卡爾曼濾波,因此EKF是一種次優濾波。其後,多種二階廣義卡爾曼濾波方法的提出及應用進一步提高了卡爾曼濾波對非線性系統的估計性能。二階濾波方法考慮了Taylor級數展開的二次項,因此減少了由於 線性化所引起的 估計誤差,但大大增加了運算量,因此在實際中反而沒有一階EKF應用廣泛。
在狀態方程或測量方程為非線性時,通常采用擴展卡爾曼濾波(EKF)。EKF對非線性函數的Taylor展開式進行一階線性化截斷,忽略其余高階項,從而將非線性問題轉化為線性,可以將卡爾曼線性濾波算法應用於非線性系統中。這樣一來,解決了非線性問題。EKF雖然應用於非線性狀態估計系統中已經得到了學術界認可並為人廣泛使用,然而該種方法也帶來了兩個缺點,其一是當強非線性時EKF違背局部線性假設,Taylor展開式中被忽略的高階項帶來大的 誤差時,EKF算法可能會使濾波發散;另外,由於EKF在線性化處理時需要用雅克比(Jacobian)矩陣,其繁瑣的計算過程導致該方法實現相對困難。所以,在滿足 線性系統、高斯白噪聲、所有隨機變量服從高斯(Gaussian)分布這3個假設條件時,EKF是最小方差準則下的次優濾波器,其性能依賴於局部非線性度。

%---------------------------EKF算法實現------------------------------------
for k=2:kk-1
%---------------不考慮噪聲時,根據狀態方程預測當前值--------------------------
Ag=AntiMatrix(gyro(:,k-1));%計算陀螺儀輸出的反對稱矩陣
Ag=[-Ag,   gyro(:,k-1)
    -gyro(:,k-1), 0];  
Ag=expm(Ag/2/f); %系統一步轉移矩陣

Tg=AntiMatrix(q(1:3,k-1));
Tg=[Tg+eye(3)*q(4,k-1)
    -(q(1:3,k-1))];
Tg=-0.5*Tg/f; %計算系統噪聲矩陣

q(:,k)=Ag*q(:,k-1);%計算姿態四元數的狀態估計值

%------------------------計算此時的方差-------------------------------------
p=Ag*p*Ag+Tg*Q*Tg;
%------------------------計算卡爾曼增益-------------------------------------
r=[0,0,g];
qv=q(1:3,k); %狀態方程四元數矢量部分
qs=q(4,k);   %狀態方程四元數標量部分

%計算量測向量
Hg=2*[qv*r*eye(3)+qv*r-r*qv+qs*AntiMatrix(r),qs*r+AntiMatrix(r)*qv];

Kg=p*Hg*(Hg*p*Hg+R)^-1;%計算卡爾曼增益

%------------------根據當前量測值,對預測更新--------------------------------
Cnb=(qs^2-qv*qv)*eye(3)+2*qv*qv-2*qs*AntiMatrix(qv);
h=Cnb*r;
q(:,k)=q(:,k)+Kg*(acc(:,k)-h);

%-----------------------更新估計值方差--------------------------------------
p=(eye(4)-Kg*Hg)*p;

%---------------------------歸一化-----------------------------------------
h(k)=sqrt(q(1,k)^2+q(2,k)^2+q(3,k)^2+q(4,k)^2);
q(:,k)=q(:,k)/h(k);

%----------------------------姿態角計算-------------------------------------
%補償後(-180180)180會出現奇點,-180度正常,但是不影響,實際上-180和180是重合的

T33=(q(3,k))^2-(q(2,k))^2-(q(1,k))^2+(q(4,k))^2;
T13=2*(q(1,k)*q(3,k)-q(4,k)*q(2,k));
T23=2*(q(2,k)*q(3,k)+q(4,k)*q(1,k));
if T33>0  %根據物理意義不可能出現0
    ANGLE0(1,k)=-180/pi*atan(T13/T33);
else
    ANGLE0(1,k)=180/pi*(-pi*sign(T13)-atan(T13/T33));
end

ANGLE0(2,k)=180/pi*asin(T23); %俯仰角,繞X軸轉動

end

註意此程序的特點,需關註以下問題:



1)如何根據陀螺儀輸出計算系統一步轉移矩陣:
技術分享圖片
 


2)如何根據四元數計算系統的噪聲矩陣:技術分享圖片


四元數卡爾曼濾波算法的狀態方程(由陀螺儀技術分享圖片輸出計算得到): 技術分享圖片



四元數卡爾曼濾波的時間輸出過程如下:技術分享圖片

3)如何根據四元數計算系統的量測向量;
Hg=2*[qv’*r*eye(3)+qv*r’-r*qv’+qs*AntiMatrix(r),qs*r+AntiMatrix(r)*qv];

4)如何根據四元數計算系統的轉態轉移矩陣;
Cnb=(qs^2-qv’*qv)*eye(3)+2*qv*qv’-2*qs*AntiMatrix(qv);
註意對預測值(即四元數)的更新過程:
q(:,k)=q(:,k)+Kg*(acc(:,k)-h);
因為是由加速度計構建系統的量測方程的,acc(:,k)表示加速度計的量測值,h=Cnb*r為先驗估計(不考慮誤差,r=[0,0,g]’;),這裏是將地理坐標系轉化為導航坐標系。
實際上,kalman的5個公式一部分是從狀態方程和量測方程上獲取的。

5)如何根據四元數計算系統的姿態角:技術分享圖片

6)反對稱矩陣用函數表示AntiMatrix():     技術分享圖片
function [A] = AntiMatrix(B)
A=[0,-B(3,1),B(2,1)
    B(3,1),0,-B(1,1)
    -B(2,1),B(1,1),0];
end

----------------------------------------------------------------------分割線----------------------------------------------------------------------------

Z=(1:100); %觀測值    
noise=randn(1,100); %方差為1的高斯噪聲    
Z=Z+noise;    
    
X=[0; 0]; %狀態    
Sigma = [1 0; 0 1]; %狀態協方差矩陣    
F=[1 1; 0 1]; %狀態轉移矩陣    
Q=[0.0001, 0; 0 0.0001]; %狀態轉移協方差矩陣    
H=[1 0]; %觀測矩陣    
R=1; %觀測噪聲方差    
    
figure;    
hold on;    
    
for i=1:100    
    
  X_ = F*X;    
  Sigma_ = F*Sigma*F+Q;    
  K = Sigma_*H/(H*Sigma_*H+R);    
  X = X_+K*(Z(i)-H*X_);    
  Sigma = (eye(2)-K*H)*Sigma_;    
      
  plot(X(1), X(2), .,MarkerSize,10); %畫點,橫軸表示位置,縱軸表示速度    
end  
  
plot([0,100],[1,1],r-); 

MATLAB-卡爾曼濾波簡單運用示例