好了,说到卡尔曼滤波,才华横溢卡尔曼老先生到去年终于是去世了(此处仅有敬意),而卡尔曼滤波的作用却日益彰显。大概我对卡尔曼滤波的初步理解就是(反正这句话也是抄的,看看就好了,我其实也不懂):根据当前时刻的观测值、上一时刻的预测值及预测误差,计算得到当前的最优量去预测下一刻的量。至于对卡尔曼滤波意义理解的话可以在知乎上搜一下,有个测猪体重的例子感觉十分生动。公式推导的话智商过低的本人也是推不出来的,所以在此仅希望帮助大家学会运用,如果帮得上的话。
首先,我们引入一个离散控制过程的系统。该系统可用一个线性随机微分方程来描述:
X(k)=AX(k-1)+BU(k)+W(k)
Z(k)=HX(k)+V(k)
X(k)是k时刻的系统状态,U(k)是k时刻对系统的控制量。A和B是系统参数,对于多模型系统,他们为矩阵。Z(k)是k时刻的测量值,H是测量系统的参数,对于多测量系统,H为矩阵。W(k)和V(k)分别表示过程和测量的噪声。他们被假设成高斯白噪声,他们的协方差分别是Q,R。由于系统中一般不太有控制量,所以B这个参数一般为0,也就是没有U(K)。
以下是编程需要的五个卡尔曼滤波的迭代方程:
首先利用系统的过程模型来预测系统下一状态,设在k时刻的系统状态为x(k),则可以根据系统模型,由上一状态预测出现在状态:
X(k|k-1)=AX(k-1|k-1)+Bu(k).....................(1)
其中x(k|k-1)是上一时刻的状态对现在时刻状态的预测,x(k-1|k-1)是上一时刻状态的最优结果, u(k)为现在时刻状态的控制量。
(一开始看我也一脸蒙蔽,主要看一下X(k|k-1)这样的变量到底代表什么)
系统的状态已经更新,现在需要更新系统的误差估计协方差矩阵,用p(k|k-1)表示误差估计协方差矩阵:
P(k|k-1)=A*P(k-1|k-1)A'+Q.......................(2)
(这个协方差的由来是由(1)式的预测方程得到的,你看他乘的系数也是A就懂了)
其中p(k|k-1)是在k时刻由上一状态对此状态的预测, p(k-1|k-1)是x(k-1|k-1)对应的误差估计协方差矩阵,Q表示系统过程噪声的协方差。
现在我们得到了预测结果,然后我们根据得到的现在状态的测量值进行修正得到最优的估计量x(k|k):
X(k|k)=X(k|k-1)+Kg(k)*(Z(k)-Hx(k|k-1))....(3)
(常常在编程的时候会直接把(1)式直接代入这个式子,所以你们看不到(1)式)
(3)式中Kg(k)未知,则需要对其就行求解,就引出(4)式:
Kg(k)=P(k|k-1)*H'/(H*P(k|k-1)*H' + R)......(4)
(这个是卡尔曼增益,你只要知道这是用来修正预测值的一个参数就好了)
到现在,我们以及得出的k 时刻的系统状态的最优值x(k|k),为了让卡尔曼滤波器不断地进行下去,我们需要更新 x(k|k) 对应的p(k|k)
p(k|k)=(I-Kg(k)*H)*P(k|k-1).....................(5)
((3)(4)式计算出来的X(k|k)、P(k|k)又会迭代回(1)(2)式中,注意I是单位矩阵)
我们还是先来看看网上大肆流传的一个例子吧。白字是原文,红字是我的吐槽。
假设我们要研究的对象是一个房间的温度。根据你的经验判断,这个房间的温度是恒定的。(这里的假设相当于状态方程的系数A为1)假设你对你的经验不是100%的相信,可能会有上下偏差几度,我们把这些偏差看成是高斯白噪声(这里就是W(k))。另外,我们在房间里放一个温度计,但是这个温度计也不准确的,测量值会比实际值偏差。我们也把这些偏差看成是高斯白噪声。(温度计的测量值就是Z(k),而由于温度测到的温度就是温度,不用再换算,所以系数H就是1,偏差就是V(k))。好了,现在对于某一分钟我们有两个有关于该房间的温度值:你根据经验的预测值(系统的预测值X(k|k-1))和温度计的值(测量值Z(k))。下面我们要用这两个值结合他们各自的噪声来估算出房间的实际温度值。
假如我们要估算k时刻的是实际温度值。首先你要根据k-1时刻的温度值,来预测k时刻的温度。因为你相信温度是恒定的,所以你会得到k时刻的温度预测值是跟k-1时刻一样的,假设是23度,同时该值的高斯噪声的偏差是5度(5是这样得到的:如果k-1时刻估算出的最优温度值的偏差(p(k-1|k-1)就是上一时刻的p(k|k),反正你懂)是3,你对自己预测的不确定度是4度(这个就是Q了,返回去看看黄色标注的Q是什么呗),他们平方相加再开方,就是5(算出来的就是P(k|k-1)))。然后,你从温度计那里得到了k时刻的温度值(测量值Z(k)),假设是25度,同时该值的偏差是4度(这个就是R了)。由于我们用于估算k时刻的实际温度有两个温度值,分别是23 度和25度。究竟实际温度是多少呢?相信自己还是相信温度计呢?究竟相信谁多一点,我们可以用他们的covariance(协方差)来判断。因为 Kg^2=5^2/(5^2+4^2)(该式的计算相当于上面的(4)式子),所以Kg=0.78,我们可以估算出k时刻的实际温度值是:23+0.78*(25-23)=24.56度(该式对应(3)式,就是算出最优估算值)。可以看出,因为温度计的covariance比较小(比较相信温度计),所以估算出的最优温度值偏向温度计的值。(我一直搞不懂这个协方差为什么一定要求几何的误差也就是为什么要平方再开根号,如果有人明白麻烦在评论里告诉我一下)
现在我们已经得到k时刻的最优温度值了,下一步就是要进入 k+1时刻,进行新的最优估算。到现在为止,好像还没看到什么自回归的东西出现。对了,在进入k+1时刻之前,我们还要算出k时刻那个最优值(24.56 度)的偏差。算法如下:((1-Kg)*5^2)^0.5=2.35(该式对应(5)式)。这里的5就是上面的k时刻你预测的那个23度温度值的偏差,得出的2.35就是进入 k+1时刻以后k时刻估算出的最优温度值的偏差(对应于上面的3)。就是这样,卡尔曼滤波器就不断的把 covariance递归,从而估算出最优的温度值。他运行的很快,而且它只保留了上一时刻的covariance。上面的Kg,就是卡尔曼增益(Kalman Gain)。他可以随不同的时刻而改变他自己的值,是不是很神奇!(自学了好久菜看懂这个例子是什么意思)
我觉得应该我的标注应该能让大家看懂这个例子了解整个迭代计算的过程了,下面我们看看程序吧,这个是一个比较简单的波形跟随,希望能给大家一点启示。
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
|
%第一条曲线
% t=0.1:0.1:6;
% X=t.^2;
%第二条曲线
% t=1:1:60;
% X=t.^2;
%第三条曲线
t=1:0.5:60;
X=3*sin(t);
% %第四条曲线
% t=1:0.5:60;
% X=sin(t);
%N=1:60;
figure;
subplot(2,1,1);
plot(1:0.5:60,X,
'r'
);
axis([0 60 -5 5])
hold
on
;
%系统方程:X(k+1)=A*X(k)+w(k)
%观测方程:Z(k)=H*Z(k)+v(k)
%这个是生成高斯噪声的随机数
w=randn(1,length(t));
v=randn(1,length(t));
A=1;
H=1;
X_k(1)=0; %状态估计初值
P_kk(1)=0; %P(k/k)
P_k(1)=0; %P(k/k-1) 这个初始化不需要,就给你们看看变量的对应
Z_k(1)=X_k(1)+w(1) ; %测量值
R=(std(v)).^2;
Q=(std(w)).^2;
Kg(1)=P_kk(1)*H
'/(H*P_kk(1)*H'
+R); %卡尔曼增益 Kg
P_k(1)=A*P_kk(1)*A'+Q ; %方差预测 P_k/k-1
for
i=2:length(t)
Z_k(i)=H*X(i)+w(i) ;
Kg(i)=P_k(i-1)*H
'/((H*P_k(i-1)*H'
+R)) ;
P_k(i)=A*P_kk(i-1)*A'+Q;
P_kk(i)=P_k(i-1)-Kg(i)*H*P_kk(i-1);
X_k(i)=A*X_k(i-1)+Kg(i-1)*(Z_k(i)-H*A*X_k(i-1)); %这边就直接代入式(1),所以没出现
end
n=1:60;
plot(1:0.5:60,X_k);
subplot(2,1,2);
plot(1:0.5:60,Z_k);
axis([0 60 -5 5])
|
后续可能还有关于不同信号类型的卡尔曼滤波分析