卡尔曼滤波简介及其算法实现代码.doc

上传人:scccc 文档编号:13144783 上传时间:2021-12-16 格式:DOC 页数:18 大小:107KB
返回 下载 相关 举报
卡尔曼滤波简介及其算法实现代码.doc_第1页
第1页 / 共18页
卡尔曼滤波简介及其算法实现代码.doc_第2页
第2页 / 共18页
卡尔曼滤波简介及其算法实现代码.doc_第3页
第3页 / 共18页
亲,该文档总共18页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《卡尔曼滤波简介及其算法实现代码.doc》由会员分享,可在线阅读,更多相关《卡尔曼滤波简介及其算法实现代码.doc(18页珍藏版)》请在三一文库上搜索。

1、卡尔曼滤波简介及其算法实现代码(C+/C/MATLAB)卡尔曼滤波器简介近来发现有些问题很多人都很感兴趣。所以在这里希望能尽自己能力跟大家讨论一些力所能及的算法。现在先讨论一下卡尔曼滤波器,如果时间和能力允许,我还希望能够写写其他的算法,例如遗传算法,傅立叶变换,数字滤波,神经网络,图像处理等等。因为这里不能写复杂的数学公式,所以也只能形象的描述。希望如果哪位是这方面的专家,欢迎讨论更正。卡尔曼滤波器 Kalman Filter1什么是卡尔曼滤波器( What is the Kalman Filter?)在学习卡尔曼滤波器之前,首先看看为什么叫“卡尔曼”。跟其他著名的理论(例如傅立叶变换,泰勒

2、级数等等)一样,卡尔曼也是一个人的名字,而跟他们不同的是,他是个现代人!卡尔曼全名 Rudolf Emil Kalman ,匈牙利数学家, 1930 年出生于匈牙利首都布达佩斯。1953,1954 年于麻省理工学院分别获得电机工程学士及硕士学位。 1957 年于哥伦比亚大学获得博士学位。我们现在要学习的卡尔曼滤波器,正是源于他的博士论文和 1960 年发表的论文 A NewApproach to Linear Filtering and Prediction Problems (线性滤波与预测问题的新方法)。如果对这编论文有兴趣,可以到这里的地址下载:http:/www.cs.unc.edu/

3、welch/media/pdf/Kalman1960.pdf。简单来说,卡尔曼滤波器是一个“ optimal recursive data processing algorithm (最优化自回归数据处理算法)”。对于解决很大部分的问题,他是最优,效率最高甚至是最有用的。他的广泛应用已经超过 30 年,包括机器人导航,控制,传感器数据融合甚至在军事方面的雷达系统以及导弹追踪等等。近年来更被应用于计算机图像处理,例如头脸识别,图像分割,图像边缘检测等等。2卡尔曼滤波器的介绍( Introduction to the Kalman Filter)为了可以更加容易的理解卡尔曼滤波器,这里会应用形象的

4、描述方法来讲解,而不是像大多数参考书那样罗列一大堆的数学公式和数学符号。但是,他的 5 条公式是其核心内容。结合现代的计算机,其实卡尔曼的程序相当的简单,只要你理解了他的那5 条公式。在介绍他的 5 条公式之前,先让我们来根据下面的例子一步一步的探索。假设我们要研究的对象是一个房间的温度。根据你的经验判断,这个房间的温度是恒定的,也就是下一分钟的温度等于现在这一分钟的温度(假设我们用一分钟来做时间单位)。假设你对你的经验不是 100%的相信,可能会有上下偏差几度。我们把这些偏差看成是高斯白噪声( White Gaussian Noise ),也就是这些偏差跟前后时间是没有关系的而且符合高斯分配

5、( Gaussian Distribution )。另外,我们在房间里放一个温度计,但是这个温度计也不准确的,测量值会比实际值偏差。我们也把这些偏差看成是高斯白噪声。好了,现在对于某一分钟我们有两个有关于该房间的温度值:你根据经验的预测值(系统的预测值)和温度计的值(测量值)。下面我们要用这两个值结合他们各自的噪声来估算出房间的实际温度值。假如我们要估算 k 时刻的是实际温度值。首先你要根据 k-1 时刻的温度值,来预测 k 时刻的温度。因为你相信温度是恒定的,所以你会得到 k 时刻的温度预测值是跟 k-1 时刻一样的,假设是 23 度,同时该值的高斯噪声的偏差是 5 度(5是这样得到的: 如

6、果 k-1 时刻估算出的最优温度值的偏差是 3,你对自己预测的不确定度是 4 度,他们平方相加再开方,就是 5)。然后,你从温度计那里得到了 k 时刻的温度值,假设是 25 度,同时该值的偏差是 4 度。由于我们用于估算 k 时刻的实际温度有两个温度值,分别是23 度和 25 度。究竟实际温度是多少呢?相信自己还是相信温度计呢?究竟相信谁多一点,我们可以用他们的 covariance(协方差)来判断。因为 Kg2=52/(52+42) ,所以Kg=0.78,我们可以估算出k 时刻的实际温度值是: 23+0.78*(25-23)=24.56 度。可以看出,因为温度计的covariance 比较小

7、(比较相信温度计),所以估算出的最优温度值偏向温度计的值。现在我们已经得到 k 时刻的最优温度值了,下一步就是要进入k+1 时刻,进行新的最优估算。到现在为止,好像还没看到什么自回归的东西出现。对了,在进入 k+1 时刻之前,我们还要算出k 时刻那个最优值( 24.56 度)的偏差。算法如下: (1-Kg)*52)0.5=2.35。这里的 5 就是上面的 k 时刻你预测的那个 23度温度值的偏差,得出的2.35 就是进入 k+1 时刻以后 k 时刻估算出的最优温度值的偏差(对应于上面的3)。就是这样,卡尔曼滤波器就不断的把covariance递归,从而估算出最优的温度值。他运行的很快,而且它只

8、保留了上一时刻的covariance。上面的 Kg,就是卡尔曼增益( Kalman Gain )。他可以随不同的时刻而改变他自己的值,是不是很神奇!下面就要言归正传,讨论真正工程系统上的卡尔曼。3卡尔曼滤波器算法( The Kalman Filter Algorithm)在这一部分,我们就来描述源于 Dr Kalman 的卡尔曼滤波器。下面的描述,会涉及一些基本的概念知识,包括概率( Probability ),随即变量( RandomVariable ),高斯或正态分配(Gaussian Distribution )还有 State-space Model 等等。但对于卡尔曼滤波器的详细证明

9、,这里不能一一描述。首先,我们先要引入一个离散控制过程的系统。该系统可用一个线性随机微分方程( Linear Stochastic Difference equation)来描述:X(k)=A X(k-1)+B U(k)+W(k)再加上系统的测量值:Z(k)=H X(k)+V(k)上两式子中, X(k) 是 k 时刻的系统状态, U(k) 是 k 时刻对系统的控制量。 A 和 B 是系统参数,对于多模型系统,他们为矩阵。 Z(k) 是 k 时刻的测量值, H 是测量系统的参数,对于多测量系统, H为矩阵。 W(k)和 V(k) 分别表示过程和测量的噪声。他们被假设成高斯白噪声 (White G

10、aussian Noise) ,他们的 covariance 分别是 Q, R(这里我们假设他们不随系统状态变化而变化)。对于满足上面的条件 ( 线性随机微分系统,过程和测量都是高斯白噪声) ,卡尔曼滤波器是最优的信息处理器。下面我们来用他们结合他们的 covariances 来估算系统的最优化输出(类似上一节那个温度的例子)。首先我们要利用系统的过程模型,来预测下一状态的系统。假设现在的系统状态是 k,根据系统的模型,可以基于系统的上一状态而预测出现在状态:X(k|k-1)=A X(k-1|k-1)+B U(k). (1)式 (1) 中,X(k|k-1) 是利用上一状态预测的结果, X(k-

11、1|k-1) 结果, U(k) 为现在状态的控制量,如果没有控制量,它可以为是上一状态最优的0。到现在为止,我们的系统结果已经更新了, 可是,对应于 X(k|k-1)的 covariance还没更新。我们用P 表示 covariance :P(k|k-1)=A P(k-1|k-1) A +Q(2)式 (2) 中,P(k|k-1) 是 X(k|k-1) 对应的 covariance ,P(k-1|k-1) 是 X(k-1|k-1) 对应的 covariance ,A表示 A 的转置矩阵, Q是系统过程的 covariance 。式子 1,2 就是卡尔曼滤波器 5 个公式当中的前两个,也就是对系统

12、的预测。现在我们有了现在状态的预测结果,然后我们再收集现在状态的测量值。结合预测值和测量值,我们可以得到现在状态(k) 的最优化估算值 X(k|k) :X(k|k)= X(k|k-1)+Kg(k)*(Z(k)-H X(k|k-1)(3)其中 Kg 为卡尔曼增益Kg(k)= P(k|k-1) H (Kalman Gain) :/ (H P(k|k- 1) H + R)(4)到现在为止,我们已经得到了 k 状态下最优的估算值 X(k|k) 尔曼滤波器不断的运行下去直到系统过程结束,我们还要更新的 covariance :。但是为了要另卡k 状态下 X(k|k)P(k|k)= (I-Kg(k) H)

13、 P(k|k- 1)(5)其中 I为 1 的矩阵,对于单模型单测量,I=1 。当系统进入 k+1 状态时, P(k|k)就是式子 (2) 的 P(k-1|k-1)。这样,算法就可以自回归的运算下去。卡尔曼滤波器的原理基本描述了,式子 1,2,3,4 和 5 就是他的 5 个基本公式。根据这 5 个公式,可以很容易的实现计算机的程序。下面,我会用程序举一个实际运行的例子。4简单例子( A Simple Example )这里我们结合第二第三节,举一个非常简单的例子来说明卡尔曼滤波器的工作过程。所举的例子是进一步描述第二节的例子,而且还会配以程序模拟结果。根据第二节的描述,把房间看成一个系统,然后

14、对这个系统建模。当然,我们见的模型不需要非常地精确。 我们所知道的这个房间的温度是跟前一时刻的温度相同的,所以 A=1。没有控制量,所以 U(k)=0 。因此得出:X(k|k-1)=X(k-1|k-1). (6)式子( 2)可以改成:P(k|k-1)=P(k-1|k-1) +Q(7 )因为测量的值是温度计的,跟温度直接对应,所以 H=1。式子 3,4,5 可以改成以下:X(k|k)= X(k|k-1)+Kg(k)*(Z(k)-X(k|k-1)(8)Kg(k)= P(k|k-1) / (P(k|k-1)+R)(9)P(k|k)= (1-Kg(k) )P(k|k-1)(10)现在我们模拟一组测量值

15、作为输入。 假设房间的真实温度为 25 度,我模拟了 200 个测量值,这些测量值的平均值为 25 度,但是加入了 标准偏差为几度的高斯白噪声(在图中为蓝线) 。为了令卡尔曼滤波器开始工作,我们需要告诉卡尔曼两个零时刻的初始值,是 X(0|0) 和 P(0|0) 。他们的值不用太在意,随便给一个就可以了,因为随着卡尔曼的工作, X 会逐渐的收敛。但是对于 P,一般不要取 0,因为这样可能会令卡尔曼完全相信你给定的 X(0|0) 是系统最优的,从而使算法不能收敛。我选了 X(0|0)=1 度, P(0|0)=10 。该系统的真实温度为 25 度,图中用黑线表示 。图中 红线是卡尔曼滤波器输出的最

16、优化结果 (该结果在算法中设置了 Q=1e-6,R=1e-1)。最佳线性滤波理论起源于 40 年代美国科学家 Wiener 和前苏联科学家 等人的研究工作, 后人统称为维纳滤波理论。 从理论上说,维纳滤波的最大缺点是必须用到无限过去的数据,不适用于实时处理。为了克服这一缺点, 60 年代 Kalman 把状态空间模型引入滤波理论,并导出了一套递推估计算法,后人称之为卡尔曼滤波理论。卡尔曼滤波是以最小均方误差为估计的最佳准则,来寻求一套递推估计的算法,其基本思想是:采用信号与噪声的状态空间模型,利用前一时刻地估计值和现时刻的观测值来更新对状态变量的估计,求出现时刻的估计值。它适合于实时处理和计算

17、机运算。现设线性时变系统的离散状态防城和观测方程为:X(k) = F(k,k-1) ·X(k -1)+T(k,k-1) ·U(k -1)Y(k) = H(k)·X(k)+N(k)其中, X(k) 和 Y(k) 分别是 k 时刻的状态矢量和观测矢量F(k,k-1)为状态转移矩阵U(k) 为 k 时刻动态噪声T(k,k-1)为系统控制矩阵H(k) 为 k 时刻观测矩阵N(k) 为 k 时刻观测噪声则卡尔曼滤波的算法流程为:预估计 X(k)= F(k,k-1) ·X(k -1)1. 计算预估计协方差矩阵C(k)=F(k,k- 1) ×C(k) 

18、15;F(k,k -1)'+T(k,k- 1) ×Q(k) ×T(k,k -1)' Q(k) = U(k) ×U(k)'2. 计算卡尔曼增益矩阵K(k) = C(k)×H(k)'R(k) = N(k)×N(k)'×H(k)×C(k)×H(k)'+R(k)(-1)3. 更新估计X(k)=X(k)+K(k) ×Y(k) - H(k) ×X(k)4. 计算更新后估计协防差矩阵C(k) =I- K(k) ×H(k) ×C(k) 

19、5;I - K(k) ×H(k)'+K(k)×R(k) ×K(k)'5. X(k+1) = X(k) C(k+1) = C(k)重复以上步骤 atlab实现代码 此码为本人原创,仅供交流,谢决转载!*% Constant Velocity Model Kalman Filter Simulation %= =clear all; close all; clc;% Initial conditionts = 1; % Sampling timet = 0:ts:100;T = length(t);%T表示初始条件t 的长度101% Initial s

20、tate x = 0 40 0 20' x_hat = 0 0 0 0'初始状态% Process noise covarianceq = 5Q = q*eye(2);预测噪声的协方差% Measurement noise covariancer = 5R = r*eye(2);测量噪声的协方差% Process and measurement noise预测以及测量的噪声w = sqrt(Q)*randn(2,T);% Process noisev = sqrt(R)*randn(2,T);% Measurement noise% Estimate error covaria

21、nce initializationp = 5;P(:,:,1) = p*eye(4);预测协方差初始化%= =% Continuous-time state space model%x_dot(t) = Ax(t)+Bu(t)z(t) = Cx(t)+Dn(t)%A=0100;状态空间模型0000;0001;0000;B=00;10;00;01;C=1000;0010;D=10;0 1;% Discrete-time state space model%x(k+1) = Fx(k)+Gw(k)z(k) = Hx(k)+Iv(k)离散状态模型Continuous to discrete for

22、m by zoh%sysc = ss(A,B,C,D);sysd = c2d(sysc, ts, 'zoh');F G H I = ssdata(sysd);连续转为离散% Practice state of targetfor i = 1:T-1x(:,i+1) = F*x(:,i);endx = x+G*w;% State variable with noisez = H*x+I*v; % Measurement value with noise%= =% Kalman Filterfor i = 1:T-1% Prediction phasex_hat(:,i+1) =

23、F*x_hat(:,i);% State estimate predict预测模型P(:,:,i+1) = F*P(:,:,i)*F'+G*Q*G'% Tracking error covariance predictP_predicted(:,:,i+1) = P(:,:,i+1);预测协方差% Kalman gain 卡尔曼增益K = P(:,:,i+1)*H'*inv(H*P(:,:,i+1)*H'+R);% Updata step 状态更新x_hat(:,i+1) =x_hat(:,i+1)+K*(z(:,i+1)-H*x_hat(:,i+1);% St

24、ate estimate update协方差更新P(:,:,i+1) =P(:,:,i+1)-K*H*P(:,:,i+1);% Tracking error covariance updateP_updated(:,:,i+1) =P(:,:,i+1);end%= =% Estimate error预测错误差值x_error = x-x_hat;% Graph 1 practical and tracking position figure(1)plot(x(1,:),x(3,:),'r'); hold on; plot(x_hat(1,:),x_hat(3,:),'g

25、.'); title('2D Target Position') legend('Practical Position','Tracking Position') xlabel('X axis m')ylabel('Y axis m') hold off;% Graph 2figure(2)plot(t,x(1,:),grid on;hold on;plot(t,x_hat(1,:),'r'),grid on;title('Practical and Tracking Positio

26、n on X axis')legend('Practical Position','Tracking Position')xlabel('Time sec')ylabel('Position m')hold off;% Graph 3figure(3)plot(t,x_error(1,:),grid on;title('Position Error on X axis')xlabel('Time sec')ylabel('Position RMSE m')hold off;%

27、 Graph 4figure(4) plot(t,x(2,:),grid on; hold on; plot(t,x_hat(2,:),'r'),grid on;title('Practical and Tracking Velocity on X axis')legend('Practical Velocity','Tracking Velocity')xlabel('Time sec')ylabel('Velocity m/sec')hold off;% Graph 5figure(5)plot

28、(t,x_error(2,:),grid on; title('Velocity Error on X axis') xlabel('Time sec') ylabel('Velocity RMSE m/sec') hold off;%= =* *c 语言实现代码 转-#include "stdlib.h"#include "rinv.c"int lman(n,m,k,f,q,r,h,y,x,p,g)int n,m,k;double f,q,r,h,y,x,p,g; int i,j,kk,ii,l,jj,j

29、s; double *e,*a,*b; e=malloc(m*m*sizeof(double);l=m;if (l<n) l=n;a=malloc(l*l*sizeof(double);b=malloc(l*l*sizeof(double);for (i=0; i<=n-1; i+)for (j=0; j<=n-1; j+) ii=i*l+j; aii=0.0;for (kk=0; kk<=n-1; kk+)aii=aii+pi*n+kk*fj*n+kk;for (i=0; i<=n-1; i+)for (j=0; j<=n-1; j+) ii=i*n+j;

30、 pii=qii;for (kk=0; kk<=n-1; kk+)pii=pii+fi*n+kk*akk*l+j;for (ii=2; ii<=k; ii+) for (i=0; i<=n-1; i+)for (j=0; j<=m-1; j+) jj=i*l+j; ajj=0.0;for (kk=0; kk<=n-1; kk+)ajj=ajj+pi*n+kk*hj*n+kk;for (i=0; i<=m-1; i+)for (j=0; j<=m-1; j+) jj=i*m+j; ejj=rjj;for (kk=0; kk<=n-1; kk+)ej

31、j=ejj+hi*n+kk*akk*l+j;js=rinv(e,m);if (js=0) free(e); free(a); free(b); return(js); for (i=0; i<=n-1; i+)for (j=0; j<=m-1; j+) jj=i*m+j; gjj=0.0;for (kk=0; kk<=m-1; kk+)gjj=gjj+ai*l+kk*ej*m+kk;for (i=0; i<=n-1; i+) jj=(ii-1)*n+i; xjj=0.0; for (j=0; j<=n-1; j+)xjj=xjj+fi*n+j*x(ii-2)*n+

32、j;for (i=0; i<=m-1; i+) jj=i*l; bjj=y(ii-1)*m+i; for (j=0; j<=n-1; j+)bjj=bjj-hi*n+j*x(ii-1)*n+j;for (i=0; i<=n-1; i+) jj=(ii-1)*n+i;for (j=0; j<=m-1; j+)xjj=xjj+gi*m+j*bj*l;if (ii<k) for (i=0; i<=n-1; i+) for (j=0; j<=n-1; j+) jj=i*l+j; ajj=0.0;for (kk=0; kk<=m-1; kk+)ajj=aj

33、j-gi*m+kk*hkk*n+j;if (i=j) ajj=1.0+ajj;for (i=0; i<=n-1; i+)for (j=0; j<=n-1; j+) jj=i*l+j; bjj=0.0;for (kk=0; kk<=n-1; kk+)bjj=bjj+ai*l+kk*pkk*n+j;for (i=0; i<=n-1; i+)for (j=0; j<=n-1; j+) jj=i*l+j; ajj=0.0;for (kk=0; kk<=n-1; kk+)ajj=ajj+bi*l+kk*fj*n+kk;for (i=0; i<=n-1; i+)f

34、or (j=0; j<=n-1; j+) jj=i*n+j; pjj=qjj;for (kk=0; kk<=n-1; kk+)pjj=pjj+fi*n+kk*aj*l+kk;free(e); free(a); free(b);return(js);* *C+实现代码 转-/ kalman.h: interface for the kalman class./#if !defined(AFX_KALMAN_H_ED3D740F_01D2_4616_8B74_8BF57636F2C0_INCL UDED_)#define AFX_KALMAN_H_ED3D740F_01D2_4616_

35、8B74_8BF57636F2C0_INCLUDED_#if _MSC_VER > 1000#pragma once#endif / _MSC_VER > 1000#include <math.h>#include "cv.h"class kalmanpublic:void init_kalman(int x,int xv,int y,int yv);CvKalman* cvkalman;CvMat* state;CvMat* process_noise;CvMat* measurement;const CvMat* prediction;CvPoi

36、nt2D32f get_predict(float x, float y);kalman(int x=0,int xv=0,int y=0,int yv=0);/virtual kalman();#endif/ !defined(AFX_KALMAN_H_ED3D740F_01D2_4616_8B74_8BF57636F2C0_INCLU DED_)=kalman.cpp= =#include "kalman.h"#include <stdio.h>/* tester de printer toutes les valeurs des vecteurs*/ /*

37、 tester de changer les matrices du noises */ /* replace state by cvkalman->state_post ? */CvRandState rng;const double T = 0.1;kalman:kalman(int x,int xv,int y,int yv)cvkalman = cvCreateKalman( 4, 4, 0 );state = cvCreateMat( 4, 1, CV_32FC1 );process_noise = cvCreateMat( 4, 1, CV_32FC1 );measureme

38、nt = cvCreateMat( 4, 1, CV_32FC1 );int code = -1;/* create matrix data */const float A = 1, T, 0, 0,0, 1, 0, 0,0, 0, 1, T,0,0,0,1;const float H = 1, 0, 0, 0,0, 0, 0, 0,0, 0, 1, 0,0,0,0,0;const float P = pow(320,2), pow(320,2)/T, 0, 0,pow(320,2)/T, pow(320,2)/pow(T,2), 0, 0,0, 0, pow(240,2), pow(240,2)/T,0, 0, pow(240,2)/T, pow(240,2)/pow(T,2);const float Q = pow(T,3)/3, pow(T,2)/2, 0, 0,pow(T,2)/2, T, 0, 0,0, 0, pow(T,3)/3, pow(T,2)/2,0, 0, pow(T,2)/2, T;const float R = 1, 0, 0, 0,0, 0, 0, 0,0, 0, 1, 0,0,0,0,0;cvRandInit( &rng, 0, 1, -1, CV_RAND_UNI );

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1