前言
在许多路线追踪实例中,所采用的追踪算法大多是卡尔曼滤波器(KF)或者是扩展的卡尔曼滤波器(EKF),亦或者是基于EKF的优化算法。因此,理解并掌握EKF的思路并熟练运用便成为了涉足追踪领域的基础,本文就是记录笔者在学习EKF后的一些感想及仿真实现。
一、EKF的来源
在信号处理中,我们总是假设一个变量遵循着一个确定的表达式进行随时间的变化,比如最简单的一个表达式之一
这个式子就表示对于任意一个时刻t,x的值永远是t的2倍。但在实际生活中,这样理想的情况几乎是不存在的,总会有一些干扰项影响我们最终得到的x,那么我们现在便有了两种情况,一是理想的状态方程,如下(由矢量高斯马尔可夫方程简化而来):
二则是实际的观测方程:
其中的u和w都表示对应的噪声,都是为了模拟真实情况而引入的,其中u应该尽可能小。我们的目的就是通过已知的观测量x去推导出对应的状态量s,因此我们所求得的s并不是理想状态的s,而只是它的一个估计量,这种估计方法我们便成为卡尔曼滤波(KF),估计值与理想值之间的偏差我们用最小均方误差(MSE)去衡量。
以上是一般的一阶高斯马尔可夫状态方程的情况,当状态方程变为多阶时,情况略有不同,但思路类似,依旧可以用KF的方法进行计算。但在实际中,我们经常面对的状态方程和观测方程都是非线性的,这个时候KF的方法就不太准确了,我们需要将其转换为线性方程再用KF的方法,这个转换过程就是一阶泰勒近似,所求得的矩阵(也可为向量)便称为雅可比矩阵,这种操作也让KF摇身一变为EKF,也就是扩展的卡尔曼滤波,这便是EKF来源的简单介绍。
二、EKF的算法流程
接下来就是如何建立观测值与估计值之间的联系了,鉴于推导过程异常复杂,这里就不展开解释了,只讲解大致思路。
首先我们有两个方程,含义见上文:
A和H均是对应的状态转移矩阵,其与s的乘积我们可以将其简化,写成s的函数,即a(s[n-1])和h(s[n]),此时的函数不一定是线性函数,而为了将其变为线性函数,我们需要用到泰勒展开并忽略高阶项,如下:
这样我们便换成了线性高斯马尔可夫状态方程的形式,再用KF的方法进行估计就可。也就是先估计状态量和MSE矩阵,得到卡尔曼增益,再根据观测量对用卡尔曼增益对估计的状态量和MSE进行修正,作为下一时刻的初始值,循环往复,这样便完成了整个预测流程。
三、仿真实现
完成EKF的建模后,我们代入具体的场景对其进行仿真测试。
我们这里假设有一个飞行物或者任何什么运动的物体,它本身遵循一定的状态方程在二维平面内进行运动,我们只能观测到他在二维平面中与原点的距离和对应的角度,根据这些观测量预测出他在二维平面内的运动轨迹,尽可能的减弱各种噪声的影响从而实现跟踪。
我们先设定物体的一些运动参数:
%% 参数设置
Vx = -0.2;
Vy = 0.2;
Ay = -0.005;
deltau = 0.01;
Ux = normrnd(0,deltau,[1,length(n)]);
Uy = normrnd(0,deltau,[1,length(n)]);
for t = 2:length(n)
Vx(t) = Vx(t-1);
Vy(t) = Vy(t-1) + Ay ;
end
画图即为:
接下来我们对该理想轨迹加入噪声即为我们的观测值:
for t = 2:length(n)
rx(t) = rx(t-1) + Vx(1)*delta;
ry(t) = ry(t-1) + Vy(t)*delta;
R(t) = sqrt(rx(t)^2+ry(t)^2);
beta(t) = atan(ry(t)/rx(t));
Rhat(t) = R(t) + wR(t);
betahat(t) = beta(t) + wbeta(t);
if rx(t)<=0 && ry(t)<=0
rx_hat(t) = -Rhat(t)*cos(betahat(t));
ry_hat(t) = -Rhat(t)*sin(betahat(t));
else if rx(t)>0 && ry(t)<=0
rx_hat(t) = Rhat(t)*cos(betahat(t));
ry_hat(t) = -Rhat(t)*sin(betahat(t));
end
rx_hat(t) = Rhat(t)*cos(betahat(t));
ry_hat(t) = Rhat(t)*sin(betahat(t));
end
end
画图即为:
可以看到加入噪声后轨迹明显扭曲了起来,虽然x、y坐标的尺度都比较小,但我们仍然希望能将轨迹进行去噪,使轨迹尽可能的平滑,于是我们便用这些观测值带入我们的EKF算法,获得轨迹的估计值:
%% 算法过程
for t= 2:length(n)
s_temp(:,t) = A*s_hat(:,t-1);
MM_temp = A*MM*A.'+Q;
rx_hat_t = s_temp(1,t);
ry_hat_t = s_temp(2,t);
R_temp = sqrt(rx_hat_t^2 + ry_hat_t^2);
HH_temp = [rx_hat_t/R_temp,ry_hat_t/R_temp,0,0;
-ry_hat_t/(R_temp^2),rx_hat_t/(R_temp^2),0,0];
KK = MM_temp*HH_temp.'*inv(CC + HH_temp*MM_temp*HH_temp.');%KK:4x2
h_temp = [R_temp;
atan(ry_hat_t/rx_hat_t)];%h_temp:2x1
s_hat(:,t) = s_temp(:,t)+KK*(xx(:,t)-h_temp);
MM = (eye(4,4)-KK*HH_temp)*MM_temp;
end
画图即为:
可以看到,由于估计的初始值与理想的状态值区别较大,亦即MSE较大,估计轨迹并不能与理想值近似重合,但在经过一段时间的观测后,估计值明显好很多,达到了直接观测所没有的效果。接下来我们再做一组对比实验,进一步直观的分析EKF:
由此即可明显的看到观测值经过EKF的滤波后与理想值极为接近,在一定程度上可以作为预测依据,至此我们的实验也做完了,也可以画一些mse的图进一步分析,整个就交给读者自己完成了。
遗憾的是,当观测值与状态量之间的非线性程度增加时,EKF的效果急速下降:
且观测值本身的误差也会影响EKF的精度,随着时间的积累,这样的误差会越来越大,导致EKF的效果已经微乎其微,当然这也为了我们提供了一些优化EKF的思路,在追踪算法领域已有不少学者进行了更为深入的研究,以后有机会笔者也将对他们的成果进行分析和复现。
四、小结
本次实验我们简单地分析了EKF的由来和计算流程,也用简单的例子做了仿真实现,发现了EKF的些许不足,为将来的深入分析和改进提供了思路。
ps:笔者又来求打赏啦,看在笔者辛苦看了好几天书外加敲了好几天代码再加调了好久的bug份上,读者大大们可以点击下方链接慷慨解囊一下嘛~谢谢支持啦~打赏截图发邮箱后可获得源码一份哦~