1、最佳线性滤波理论起源于 40 年代美国科学家 Wiener 和前苏联科学家 等人的研究工作,后人统称为维纳滤波理论。从理论上说,维纳滤波的最大缺点是必须用到无限过去的数据,不适用于实时处理。为了克服这一缺点,60 年代 Kalman 把状态空间模型引入滤波理论,并导出了一套递推估计算法,后人称之为卡尔曼滤波理论。卡尔曼滤波是以最小均方误差为估计的最佳准则,来寻求一套递推估计的算法,其基本思想是:采用信号与噪声的状态空间模型,利用前一时刻地估计值和现时刻的观测值来更新对状态变量的估计,求出现时刻的估计值。它适合于实时处理和计算机运算。现设线性时变系统的离散状态防城和观测方程为:X(k) = F(
2、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 时刻观测噪声则卡尔曼滤波的算法流程为:1. 预估计 X(k)= F(k,k-1)X(k-1) 2. 计算预估计协方差矩阵C(k)=F(k,k-1)C(k)F(k,k-1)+T(k,k-1)Q(k)T(k,k-1)Q(k) = U(k)U(k) 3. 计算卡尔曼增益矩阵K(k) = C(k)H(k)H(k)C(k)
3、H(k)+R(k)(-1)R(k) = N(k)N(k) 4. 更新估计X(k)=X(k)+K(k)Y(k)-H(k)X(k) 5. 计算更新后估计协防差矩阵C(k) = I-K(k)H(k)C(k)I-K(k)H(k)+K(k)R(k)K(k) 6. X(k+1) = X(k)C(k+1) = C(k)重复以上步骤 其 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,js;doub
4、le *e,*a,*b;e=malloc(m*m*sizeof(double);l=m;if (l 1000#pragma once#endif / _MSC_VER 1000#include #include “cv.h“class kalman public:void init_kalman(int x,int xv,int y,int yv);CvKalman* cvkalman;CvMat* state; CvMat* process_noise;CvMat* measurement;const CvMat* prediction;CvPoint2D32f get_predict(fl
5、oat 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_INCLUDED_)=kalman.cpp=#include “kalman.h“#include /* tester de printer toutes les valeurs des vecteurs */* tester de changer les matrices du noises */* repl
6、ace 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 );measurement = cvCreateMat( 4, 1, CV_32FC1 );int code = -1;/* cre
7、ate 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);cons
8、t 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( cvZero( measurement );cvRandSetRange( rng.disttype = CV_RAND_NORMAL;cvRand( memcpy( cvkalman-transition_matrix-data.fl
9、, A, sizeof(A);memcpy( cvkalman-measurement_matrix-data.fl, H, sizeof(H);memcpy( cvkalman-process_noise_cov-data.fl, Q, sizeof(Q);memcpy( cvkalman-error_cov_post-data.fl, P, sizeof(P);memcpy( cvkalman-measurement_noise_cov-data.fl, R, sizeof(R);/cvSetIdentity( cvkalman-process_noise_cov, cvRealScala
10、r(1e-5) ); /cvSetIdentity( cvkalman-error_cov_post, cvRealScalar(1);/cvSetIdentity( cvkalman-measurement_noise_cov, cvRealScalar(1e-1) );/* choose initial state */state-data.fl0=x;state-data.fl1=xv;state-data.fl2=y;state-data.fl3=yv;cvkalman-state_post-data.fl0=x;cvkalman-state_post-data.fl1=xv;cvka
11、lman-state_post-data.fl2=y;cvkalman-state_post-data.fl3=yv;cvRandSetRange( cvRand( CvPoint2D32f kalman:get_predict(float x, float y)/* update state with current position */state-data.fl0=x;state-data.fl2=y;/* predict point position */* xk=A 鈥k+B 鈥kPk=A 鈥k-1*AT + Q */cvRandSetRange( cvRand( /* xk=A?x
12、k-1+B?uk+wk */cvMatMulAdd( cvkalman-transition_matrix, state, process_noise, cvkalman-state_post );/* zk=H?xk+vk */cvMatMulAdd( cvkalman-measurement_matrix, cvkalman-state_post, measurement, measurement );/* adjust Kalman filter state */* Kk=Pk 鈥T 鈥?H 鈥 k 鈥T+R)-1xk=xk+Kk 鈥?zk-H 鈥 k)Pk=(I-Kk 鈥) 鈥k */
13、cvKalmanCorrect( cvkalman, measurement );float measured_value_x = measurement-data.fl0;float measured_value_y = measurement-data.fl2;const CvMat* prediction = cvKalmanPredict( cvkalman, 0 );float predict_value_x = prediction-data.fl0;float predict_value_y = prediction-data.fl2;return(cvPoint2D32f(predict_value_x,predict_value_y);void kalman:init_kalman(int x,int xv,int y,int yv)state-data.fl0=x;state-data.fl1=xv;state-data.fl2=y;state-data.fl3=yv;cvkalman-state_post-data.fl0=x;cvkalman-state_post-data.fl1=xv;cvkalman-state_post-data.fl2=y;cvkalman-state_post-data.fl3=yv;