卡尔曼滤波(Kalman filtering)是一种利用线性系统状态方程,通过系统输入输出观测数据,对系统状态进行最优估计的算法。由于观测数据中包括系统中的噪声和干扰的影响,所以最优估计也可看作是滤波过程。

卡尔曼滤波器也叫做最佳线性滤波器,其优点有很多:简单、占用内存小、速度快。同时卡尔曼滤波器还是时域滤波器(不需要进行频域的变换)。

用一个简单的例子来介绍卡尔曼滤波器的原理

假设一台汽车在路上行驶,要描述这台汽车的状态一般通过位置速度来表示:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差


卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_02表示当前状态,卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_03代表当前位置,卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_04代表当前速度。同时用运动学公式描述当前时刻与前一时刻的状态:

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_05


用矩阵的形式来表示:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差矩阵_06


卡尔曼滤波假设两个变量(位置和速度)都是服从高斯分布的随机变量。每个变量都有一个均值 μ,表示随机分布的中心(最可能的状态),以及方差表示变量的不确定性。在本例中,可以发现,位置和速度这两个随机变量是相关的。因为速度越大,理论上下一时刻的位置变化也就越大。所以这种相关性使用协方差矩阵来表示。

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_07


卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_08为预测矩阵,我们可以通过前面提到的运动学公式来更新卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_02的状态,但协方差矩阵应该如何更新呢?这里需要引入一个关于协方差的公式:

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波算法_10

因此可以得到:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_11

若在此基础上有外部因素对汽车进行控制(如踩油门),我们还需要引入一个加速度a,因此,位置与速度的方程可表示为:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差矩阵_12


通过观察可以发现,当前时刻的位置和速度都是上一时刻位置和速度的线性组合,若用矩阵的形式来表示:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差矩阵_13


卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_08为预测矩阵,卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_15为控制矩阵。此时预测的状态卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_02并非就是准确的,还需要考虑外部干扰,如摩擦力、阻力等。所以再每次预测之后,我们需要增加一些“不确定性”。

原始估计中的每个状态变量更新到新的状态后,仍然服从高斯分布。我们可以说卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波算法_17的每个状态变量移动到了一个新的服从高斯分布的区域,协方差为卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_18。也就是将这些没有被跟踪的干扰当作协方差为卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_18的噪声来处理。得到新的预测公式:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差矩阵_20


用观测值来修正预测值:

假设使用一个传感器来测量汽车当前的状态,传感器读取的数据的单位和尺度有可能与我们要跟踪的状态的单位和尺度不一样,我们用矩阵卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_21来表示传感器的数据。同时由于观测到的数据也并非完全正确,因此同样增加一个噪声v。那么同样,观测值的协方差矩阵也相应要加上一个噪声R。

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_22

之前所说的预测公式也不能百分之百确定下一时刻的状态,所以要用观测值进行修正。这里涉及到卡尔曼增益,由于过程略复杂,在这里先跳过,日后再补充。这里直接给出修正后的状态方程:

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_23


其中卡尔曼增益系数卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_24为:

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_25

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_26


该项为实际观测值与预期观测值之间的残差,卡尔曼增益可以调节模型依赖观测值多一些还是预测值多一些。至此,我们得到了卡尔曼滤波器的所有五个方程

卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差矩阵_20


卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波 python例子_23


卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_25

有了这五个方程,就可以在代码中应用。具体matlab实现代码如下:

Z=(1:100);
noise=randn(1,100);%随机生成一个1*100的噪声
Z=Z+noise;

X=[0;0];%初始状态均为0
P=[1 0;0 1];%初始化协方差矩阵
F=[1 1;0 1];%时间间隔Δt为1
Q=[0.0001 0;0 0.0001];
H=[1 0];%观测矩阵
R=1;

figure;
hold on;

for i=1:100
    X_=F*X;
    P_=F*P*F'+Q;
    K=P_*H'/(H*P_*H'+R);
    X=X_+K*(Z(i)-H*X_);
    P=(eye(2)-K*H)*P_;
    
    plot(X(1),X(2),'x');
end

这里将观测矩阵卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_30设置为[1 0],卡尔曼滤波 python例子 卡尔曼滤波 实现_协方差_30卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波_02相乘后得到汽车的位置。

卡尔曼滤波 python例子 卡尔曼滤波 实现_卡尔曼滤波算法_33