Bulijiojio Blog

日常摸鱼划水的虾皮--如果公式不能正常显示请使用Chrome浏览器并安装Tex All the Things插件

0%

KF

卡尔曼滤波

假设条件

A1 目标动态和观测方程是线性的:

A2 $\mathbf{v}_{k}$ 和 $\mathbf{w}_{k}$ 是均值为突且噪声协方差分别为 $\mathbf{Q}_{k}$ 和 $\mathbf{R}_{k}$ 的高斯白噪声
A3 $k-1$ 时刻后验概率密度 $p\left(\mathbf{x}_{k-1} \mid \mathbf{y}^{k-1}\right)$ 是均值为 $\hat{\mathbf{x}}_{k-1| k-1}$,方差为$\mathbf{P}_{k-1 | k-1}$的高斯形式。

高斯分布与高斯乘积定理

首先规定一下高斯密度函数,由于求解后验概率密度时需要有概率密度函数相乘,所以我们很感兴趣两个概率密度函数相乘后满足怎样的分布

高斯乘积定理: 给定 $\mathbf{x}_{1}, \mathbf{\mu}_{1} \in \mathbb{R}^{d_{1}}, \mathbf{H} \in \mathbb{R}^{d_{2} \times d_{1}}, \mathbf{x}_{2} \in \mathbb{R}^{d_{2}}$ 和正定矩阵$\mathbf{P}_{1}, \mathbf{P}_{2}$

其中

卡尔曼迭代

预测函数

状态转移函数

假定$k-1$时刻的目标状态后验概率密度函数$p(\boldsymbol{x}_{k-1} | \boldsymbol{y}^{k-1}) = N(\boldsymbol{x}_{k-1};\left.\hat{\boldsymbol{x}}_{k-1 \mid k-1}, \boldsymbol{P}_{k-1 \mid k-1}\right)$

预测概率密度函数

应用高斯乘积定理,可以得到预测概率密度的表达式为

这一操作即为标准卡尔曼滤波预测,其伪函数形式可写为

其中

似然函数与归一化因子

似然函数:$p( \boldsymbol{y}_{k}\mid \boldsymbol{x}_{k}) = N(\boldsymbol{y}_{k};\boldsymbol{Hx}_k,\boldsymbol{R}_k)$

归一化因子:

其中$\hat{\boldsymbol{y}}_{k \mid k-1}=\boldsymbol{H} \hat{\boldsymbol{x}}_{k \mid k-1}, \boldsymbol{S}_{k}=\boldsymbol{H} \boldsymbol{P}_{k \mid k-1} \boldsymbol{H}^{\mathrm{T}}+\boldsymbol{R}_{k}$

后验概率密度函数

再次利用高斯乘积定理,后验概率密度可以表示为

其中

到这里其实卡尔曼滤波的迭代估计就结束了,接下来给出一个算法的流程

算法流程

卡尔曼滤波方程:

  1. 计算预测均值和方差矩阵

  2. 计算观测预测 、新息方差矩阵和卡尔曼滤波增益

  3. 计算后验均值和方差矩阵

matlab仿真

根据算法流程可以写出KalmanFilter的一步迭代函数

1
2
3
4
5
6
7
8
9
10
11
function [x_est,P_k_k] = KalmanFilter(z_k,x_est_k_minus1,F,H,P_k,Q,R)
x_pre = F*x_est_k_minus1;
P = F*P_k*F' + Q;

z_pre = H*x_pre;
S = H*P*H' + R;
K = P*H'/(S);

x_est = x_pre + K*(z_k - z_pre);
P_k_k = (eye(size(K*H,1))-K*H)*P;
end

参数的解释
输入参数:

  1. $z_k$ $k$时刻的量测值
  2. $x_est_k_minus1$ $k-1$时刻的状态后验估计
  3. $F$ 系统状态转移矩阵
  4. $H$ 量测矩阵
  5. $P_k$ $k-1$时刻的状态后验估计协方差矩阵
  6. $Q$ 过程噪声协方差矩阵
  7. $R$ 测量噪声协方差矩阵
    输出参数:
  8. $x_est$ $k$时刻状态后验估计
  9. $P_k_k$ $k$时刻状态后验估计协方差矩阵

下面给出一个实际代码的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
clc;close all;clear all

for kk = 1:100

T = 0.01;
L = 1000;

F = [1 T;
0 1];
x(:,1) = [0;1];
y(1) = randn;

H = [1 0];

v = randn(1,L);
w = 1*randn(1,L);

for i =2:L
x(:,i) = F*x(:,i-1)+[T^2/2;T]*v(i);
y(i) = H*x(:,i)+w(i);
end

Q =[1/3*T^3 1/2*T^2; 1/2*T^2 T]*var(v);
R = 2*var(w);

xe = zeros(2,L);
xe(:,1) = randn(2,1);
P = eye(2);

xe = zeros(2,L);

for i=2:L
[xe(:,i),P] = KalmanFilter(y(i),xe(:,i-1),F,H,P,Q,R);
end

Err_e(kk,:) = xe(1,:)-x(1,:);
Err_m(kk,:) = w;

end

%% 对最后一次结果进行展示
figure
hold on
plot(y(1,:),'g');
plot(xe(1,:),'linewidth',2);
plot(x(1,:));
legend('测量位置','预测位置','实际位置');
xlabel('时间序号(0.01s)');
ylabel('距离(m)');
title('kalman滤波位置估计')

figure
hold on
plot(xe(2,:));
plot(x(2,:));
legend('预测速度','实际速度');
xlabel('时间序号(0.01s)');
ylabel('速度(m/s)');
title('kalman滤波速度估计')
%% 计算状态估计误差

Var_E = var(mean(Err_e));
Var_M = var(mean(Err_m));

figure
hold on
plot(abs(mean(Err_e)),'linewidth',2);
plot(abs(mean(Err_m)));
legend('测量误差','预测误差');
xlabel('时间序号(0.01s)');
ylabel('误差(m)');
title(['误差分析 Var_{exp}=' num2str(Var_E) ' Var_{M}=' num2str(Var_M) ' Monte Carlo method(100)'] );

运行可以得到