卡尔曼滤波是一种高效率的递归滤波器,它能够从一系列的不完全及包含噪声的测量中,估计动态系统的状态。卡尔曼滤波在技术领域有许多的应用,常见的有飞机及太空船的导引、导航及控制。
卡尔曼算法主要可以分为两个步骤进行:预测和更新。基于最小均方误差为最佳估计准则,利用上一时刻的估计值和状态转移矩阵进行预测,用测量值对预测值进行修正,得到当前时刻的估计值。
卡尔曼算法公式
预测:
-
\(\hat s(n|n-1)=A\hat s(n-1|n-1)\)
-
\(P(n)=A\xi(n-1)A^T+Q\)
更新:
-
\(G(n)=P(n)C^T[CP(n)C^T+R]^{-1}\)
-
\(\xi(n)=(I-G(n)C)P(n)\)
-
\(\hat s(n|n)=\hat s(n|n-1)+G(n)[x(n)-C\hat s(n|n-1)]\)
利用上面五个式子可以递推得到状态的估计值\(\hat s(n|n)\)。
文章的组织如下:
1.基本模型及假设
2.卡尔曼算法原理及推导
3.卡尔曼滤波算法举例
4.Matlab程序
1.基本模型与假设
状态方程(描述物体运动状态)
测量方程(利用探测器等器件获取物体状态参数)
其中\(w(n)\)为过程噪声,\(v(n)\)为测量噪声。
假设:
\(w(n)\),\(v(n)\),为独立零均值的白噪声过程,即
\(v(n)\)和\(s(n)\)、\(w(n)\)不相关,即
2.卡尔曼算法原理及推导
基于最小均方误差准则,通过观测值\(x(n)\)求真实信号\(s(n)\)的线性无偏最优估计。
已知上一时刻的估计值\(\hat s(n-1|n-1)\)
利用状态方程对\(s(n)\)进行预测,最佳预测为
利用测量方程对\(x(n)\)进行预测,最佳预测为
噪声不参与预测。
当n时刻到来时,已知\(x(n)\),可以得到预测误差(新息)
选择合适的系数\(G(n)\)对预测误差进行加权,作为对预测值\(\hat s(n|n-1)\)的修正值。修正后得到对信号的最佳估计为
其中\(G(n)\)是未知的,因此要求出\(G(n)\)的关系式。
最佳估计使得均方误差最小,即
求\(\xi(n)\)对\(G(n)\)的偏导数并令其等于零,有
对公式中的两项分别进行变换,有
令一步预测误差
预测误差功率
有
则有
由上式可解得
\(E[e(n)x^T(n)]=0\),\(E[e(n)\hat s(n|n-1)]=0\),有
有
均方误差
将其展开并且\(v(n)\)和\(e_1(n)\)不相关,有
可以看出,通过对信号进行修正,最小均方误差比预测误差功率小\(G(n)CP(n)\)
其中
要求\(E[e(n)w^T(n)]=0\)
即所有公式都得到。
预测:
-
\(\hat s(n|n-1)=A\hat s(n-1|n-1)\)
-
\(P(n)=A\xi(n-1)A^T+Q\)
更新:
-
\(G(n)=P(n)C^T[CP(n)C^T+R]^{-1}\)
-
\(\xi(n)=(I-G(n)C)P(n)\)
-
\(\hat s(n|n)=\hat s(n|n-1)+G(n)[x(n)-C\hat s(n|n-1)]\)
设定初始值\(\hat s(n-1|n-1)\)、\(\xi(n-1)\),(可以设为0)
A,C,Q,R通过测量方程、状态方程以及噪声方差得到。
3.卡尔曼滤波算法应用
假设有一匀速转动模型,角度量为\(\alpha\),角速度为\(\omega\)
由匀速运动的运动学方程可以得到
假定状态量为\(s(n)=\begin{bmatrix} \alpha(n)\\ \omega(n) \end{bmatrix}\)
由运动学方程可以得到状态方程
假设过程噪声方差为\(\sigma_1=0.1\),则\(Q=\begin{bmatrix}0&0\\ 0&\sigma_1 \end{bmatrix}\)
测量值可以看作状态值加上一个测量噪声得到
测量方程
假设测量噪声方差为\(\sigma_a=1\),则\(R=\sigma_a\)
设定初始角度为10,角速度为2。
初始预测值设为0,即\(\hat s(0|0)=0\),\(\xi(0)=\begin{bmatrix}0&0\\ 0&0\end{bmatrix}\)
其中蓝色直线表示的是真实轨迹,可以看到测量值相对于真实轨迹有很大的噪声,Kalman算法收敛后可以比较好的贴近真实值。
4.Matlab代码
clc;clear all;
T = 0.01; %采样间隔
sigma_1 = 0.1;
sigma_a = 1;
N = 200;
A = [1 T; 0 1];
C = [1 0];
Q = [0 0; 0 sigma_1];
R = sigma_a;
%v = sqrt(sigma_a)*randn(1,N);
%save('v01','v')
load('v01');
s = zeros(2,N);
s_estimate = zeros(2,N);
x = zeros(1,N);
xi = zeros(2);
%给定初始值
s(:,1) = [10 2]';
s_estimate(:,1) = [0 0];
%% Kalman 算法
for n=2:N
s(:,n) = A*s(:,n-1); %状态方程
x(:,n) = C*s(:,n)+v(n); %测量方程
%kalman滤波算法
P = A*xi*A'+Q;
G = P*C'*(C*P*C'+R)^(-1);
s_estimate(:,n) = A*s_estimate(:,n-1)+G*(x(:,n)-C*A*s_estimate(:,n-1));
xi = P-G*C*P;
end
t = 1:200;
figure;
plot(t,s(1,:),t,x,t,s_estimate(1,:));
legend('真实轨迹','测量值','kalman估计值');
xlabel('取样点数/ ×0.01s');
ylabel('幅值');
error1 = s(1,:)-x;
error2 = s(1,:)-s_estimate(1,:);
figure;
plot(t,error1,t,error2);
xlabel('取样点数/ ×0.01s');
ylabel('幅值');
legend('测量值-真实值','估计值-真实值');
title(['过程噪声方差为',num2str(sigma_1)]);
这是我学习Kalman算法时整理的内容,也算是一个总结,供大家参考。如有不当之处,还请多多见谅。