\qquad 本文参考了Matlab对卡尔曼滤波器的官方教程及帮助文档(Kalman Filter)。官方教程的B站链接如下,在此对分享资源的Up主表示感谢。(如不能正常播放或需要看中文字幕,请点击此处B站链接)
【官方教程】卡尔曼滤波器教程与MATLAB仿真(全)(中英字幕)
另外提供友情链接如下:
\qquad 本文不会完全照搬视频中的所有内容,只会介绍有关卡尔曼滤波器关于定位方面的知识。卡尔曼滤波器除最原始的版本(KF)外,其延伸版本主要有三种——扩展卡尔曼滤波器(EKF)、无迹卡尔曼滤波器(UKF)、粒子滤波器(PF)。它们的运算复杂度依次递增,其中KF、EKF、UKF是建立在随机噪声是高斯分布的基础上的;PF理论则没有此预设。它们的关系如下图所示:
\qquad 首先,KF是一种状态观测器。状态观测器是针对可观系统,根据输出 y y y和输入 u u u对系统内部状态 u u u进行观测的结构单元。其构图如下(参考视频链接):
原系统方程为:
{ x ˙ = A x + B u y = C x \begin{cases} \dot{x}=Ax+Bu \\ y=Cx \end{cases} {x˙=Ax+Buy=Cx
采用状态观测器的观测系统方程为:
{ x ^ ˙ = A x ^ + B u + K ( y − y ^ ) y ^ = C x ^ \begin{cases} \dot{\hat{x}}=A\hat{x}+Bu+K(y-\hat{y}) \\ \hat{y}=C\hat{x} \end{cases} {x^˙=Ax^+Bu+K(y−y^)y^=Cx^
为保证观测器的 lim t → ∞ ( x − x ^ ) T ( x − x ^ ) = 0 \lim_{t\rightarrow\infty}(x-\hat{x})^T(x-\hat{x})=0 t→∞lim(x−x^)T(x−x^)=0
需要 A − K C A-KC A−KC是负定的。而卡尔曼滤波器就是一种状态观测器,只不过它是随机系统的状态观测器,其结构框图如下:
在输入 u u u和动态系统Plant中间会引入过程噪声 w w w,而在输出 y y y(即测量)和实际测量 y v y_v yv中间会引入传感器噪声 v v v,而卡尔曼滤波器则是根据 u , y v u,y_v u,yv求得测量的最优估计 y e y_e ye。
\qquad 假设一辆汽车在做匀速直线运动(一维场景),驾驶员通过油门控制了汽车的加速度恒定。忽略汽车所受的阻力、质量变化,并假设驾驶员操作会给汽车的牵引力造成一定的过程噪声。选择汽车的位移和速度为状态变量 x = [ p , v ] T x=[p,v]^T x=[p,v]T,则状态变量导数为汽车的速度和加速度即 x ˙ = [ v , a ] T \dot{x}=[v,a]^T x˙=[v,a]T,选取控制变量 u = a u=a u=a,测量量为汽车的位移。则状态方程如下:
{ x ˙ = [ 0 1 0 0 ] x + [ 0 1 ] u y = [ 0 1 ] x \begin{cases} \dot{x}=\begin{bmatrix} 0 &1\\0 & 0 \end{bmatrix}x+\begin{bmatrix} 0 \\ 1 \end{bmatrix}u\\[2ex] y=\begin{bmatrix} 0 & 1 \end{bmatrix}x \end{cases} ⎩ ⎨ ⎧x˙=[0010]x+[01]uy=[01]x
选取采用间隔 d t dt dt,则状态方程离散化后变为:
{ x ( n ) = [ 1 d t 0 1 ] x ( n − 1 ) + [ 0 d t ] u ( n − 1 ) y ( n ) = [ 0 1 ] x ( n ) \begin{cases} x(n)=\begin{bmatrix} 1 &dt \\ 0 & 1 \end{bmatrix}x(n-1)+\begin{bmatrix} 0 \\ dt \end{bmatrix}u(n-1)\\[2ex] y(n)=\begin{bmatrix} 0 & 1 \end{bmatrix}x(n) \end{cases} ⎩ ⎨ ⎧x(n)=[10dt1]x(n−1)+[0dt]u(n−1)y(n)=[01]x(n)
按照惯例定义
A = [ 1 d t 0 1 ] , B = [ 0 d t ] , C = [ 0 1 ] , I = [ 1 0 0 1 ] A=\begin{bmatrix} 1 &dt \\ 0 & 1 \end{bmatrix},B=\begin{bmatrix} 0 \\ dt \end{bmatrix},C=\begin{bmatrix} 0 & 1 \end{bmatrix}, I=\begin{bmatrix} 1 &0 \\ 0 & 1 \end{bmatrix} A=[10dt1],B=[0dt],C=[01],I=[1001]
由于系统具有一定的过程噪声 w w w和测量噪声 v v v。引入噪声的离散系统状态方程为:
{ x ( n ) = A x ( n − 1 ) + B ( u ( n − 1 ) + w ′ ) = B u ( n ) + w y v ( n ) = C x ( n ) + v \begin{cases} x(n)=Ax(n-1)+B(u(n-1)+w')=Bu(n)+w\\ y_v(n)=Cx(n)+v \end{cases} {x(n)=Ax(n−1)+B(u(n−1)+w′)=Bu(n)+wyv(n)=Cx(n)+v
为加以区别,使用 y v y_v yv在本文中表示含噪声的真实测量。定义随机噪声的方差:
E ( ( w − w ‾ ) T ( w − w ‾ ) ) = Q , E ( ( v − v ‾ ) T ( v − v ‾ ) ) = R E((w-\overline{w})^T(w-\overline{w}))=Q,E((v-\overline{v})^T(v-\overline{v}))=R E((w−w)T(w−w))=Q,E((v−v)T(v−v))=R
汽车的初始真实位移为0.2,真实速度为0即 x 0 = [ 0.2 , 0 ] T x_0=[0.2,0]^T x0=[0.2,0]T.
\qquad 为方便初学者入门,本文不会从贝叶斯估计的角度证明KF的公式,但会将其应用步骤以尽可能简单的手段列出。
\qquad 严格地来说,如果步骤4要成立,需要 E ( ( w − w ‾ ) T ( x − x ‾ ) ) = 0 E((w-\overline{w})^T(x-\overline{x}))=0 E((w−w)T(x−x))=0即 w w w和 v v v下相互独立,且系统方程中直接传输矩阵 D = 0 D=0 D=0,但考虑到本文是写给初学者的,所以在此默认了两个条件是成立的。
\qquad 状态协方差即为P,测量协方差为 C P C T CPC^T CPCT。卡尔曼滤波器算法收敛一般是指的是测量协方差收敛。
在此附上Matlab的仿真代码
% 模拟要求汽车在一维空间的加速和减速过程
% 控制变量u是汽车的加速度
% 状态变量x=[p,v],x^hat=[v,a]
% w为控制变量的随机扰动,v为测量的随机扰动
% Q为w的方差,R为v的方差,假设w与v相互独立
clear
dt = 0.1; % 采样间隔
N = 100; % 仿真数
Q = diag([0,0.05]); R = 1;
A = [1,dt;
0,1];
B = [0;
dt];
C = [1,0];
P = Q;
I = eye(2);
x0 = [0.2;0]; % 初始位置和速度
xh0 = [0;0]; % x0的估计
u = ones(1,N); % 加速度恒定
w = sqrt(Q)*randn(2,N); % 控制变量的误差2*N
v = sqrt(R)*randn(1,N); % 测量误差1*N
ye_list = zeros(size(u)); % 估计值
yv_list = zeros(size(u)); % 测量值
y_list = zeros(size(u)); % 实际值
cov_list = zeros(size(u)); % 测量方差
for i = 1:numel(u)
xreal = A*x0 + B*u(i); % 真实的状态变量
yreal = C*x0; % 真实的测量
x1 = xreal + w(:,i); % 含噪声的状态变量
yv = yreal + v(i); % 含噪声的测量
xfe = A*xh0 + B*u(i); % 先验的状态变量
Pfe = A*P*A'+ Q; % 先验的状态变量协方差
K = Pfe*C'/(C*Pfe*C'+R); % 卡尔曼最优增益
xh1 = xfe + K*(yv-C*xfe); % 当前的状态估计
ye = C*xh1;
P = (I-K*C)*Pfe;
x0 = x1;
xh0 = xh1;
y_list(i) = yreal;
yv_list(i) = yv;
ye_list(i) = ye;
cov_list(i) = C*P*C';
end
ax = (1:N).*dt;
figure(1);
subplot(2,2,1)
plot(ax,y_list,ax,yv_list,ax,ye_list)
legend('实际','测量','估计','Location','best')
title('汽车的位移')
ylabel('位移/m')
xlabel('时间/s')
subplot(2,2,2)
plot(ax,yv_list-y_list,ax,ye_list-y_list)
legend('测量','估计','Location','best')
title('汽车的位移误差')
ylabel('位移/m')
xlabel('时间/s')
subplot(2,2,[3,4])
plot(ax,cov_list)
legend('测量方差','Location','best')
title('测量方差')
ylabel('方差/m^2')
xlabel('时间/s')
本文设定的采样间隔 d t = 0.1 , x 0 = [ 0.2 , 0 ] T , x ^ 0 = [ 0 , 0 ] T dt=0.1,x_0=[0.2,0]^T,\hat{x}_0=[0,0]^T dt=0.1,x0=[0.2,0]T,x^0=[0,0]T,注意由于 w = B w ′ w=Bw' w=Bw′,而B的第一行为0,故 Q Q Q的对角线第一元素必定为0.仿真的效果图如下:
实际值即状态方程的输出 y = C x y=Cx y=Cx,测量值即含噪声的输出 y v = C x + v y_v=Cx+v yv=Cx+v,估计值为卡尔曼滤波器对测量的最优估计值。
\qquad 希望本文对您有所帮助,谢谢阅读!如有异议,欢迎评论区指正!
另外对本话题感兴趣的读者可以继续阅读有关适用于非线性系统的扩展卡尔曼滤波算法的介绍。