自动化网论坛 » 技术杂坛 » 卡尔曼滤波算法(附C,C++程序) 转到动态网页
--> 本页主题: 卡尔曼滤波算法(附C,C++程序) 加为IE收藏 | 收藏主题 | 上一主题 | 下一主题

宋小白


级别: 论坛版主
精华: 4
发帖: 981
威望: 990 点
金钱: 13060 Gold
贡献值: 500 点
在线时间:236(小时)
注册时间:2007-07-02


卡尔曼滤波算法(附C,C++程序)


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



现设线性时变系统的离散状态防城和观测方程为:



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)

计算预估计协方差矩阵
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)'

计算卡尔曼增益矩阵
K(k) = C(k)^×H(k)'×[H(k)×C(k)^×H(k)'+R(k)]^(-1)
R(k) = N(k)×N(k)'

更新估计
X(k)~=X(k)^+K(k)×[Y(k)-H(k)×X(k)^]

计算更新后估计协防差矩阵
C(k)~ = [I-K(k)×H(k)]×C(k)^×[I-K(k)×H(k)]'+K(k)×R(k)×K(k)'

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;
    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; a[ii]=0.0;
          for (kk=0; kk<=n-1; kk++)
            a[ii]=a[ii]+p[i*n+kk]*f[j*n+kk];
        }
    for (i=0; i<=n-1; i++)
      for (j=0; j<=n-1; j++)
        { ii=i*n+j; p[ii]=q[ii];
          for (kk=0; kk<=n-1; kk++)
            p[ii]=p[ii]+f[i*n+kk]*a[kk*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; a[jj]=0.0;
            for (kk=0; kk<=n-1; kk++)
              a[jj]=a[jj]+p[i*n+kk]*h[j*n+kk];
          }
        for (i=0; i<=m-1; i++)
        for (j=0; j<=m-1; j++)
          { jj=i*m+j; e[jj]=r[jj];
            for (kk=0; kk<=n-1; kk++)
              e[jj]=e[jj]+h[i*n+kk]*a[kk*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; g[jj]=0.0;
            for (kk=0; kk<=m-1; kk++)
              g[jj]=g[jj]+a[i*l+kk]*e[j*m+kk];
          }
        for (i=0; i<=n-1; i++)
          { jj=(ii-1)*n+i; x[jj]=0.0;
            for (j=0; j<=n-1; j++)
              x[jj]=x[jj]+f[i*n+j]*x[(ii-2)*n+j];
          }
        for (i=0; i<=m-1; i++)
          { jj=i*l; b[jj]=y[(ii-1)*m+i];
            for (j=0; j<=n-1; j++)
              b[jj]=b[jj]-h[i*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++)
              x[jj]=x[jj]+g[i*m+j]*b[j*l];
          }
        if (ii<k)
          { for (i=0; i<=n-1; i++)
            for (j=0; j<=n-1; j++)
              { jj=i*l+j; a[jj]=0.0;
                for (kk=0; kk<=m-1; kk++)
                  a[jj]=a[jj]-g[i*m+kk]*h[kk*n+j];
                if (i==j) a[jj]=1.0+a[jj];
              }
            for (i=0; i<=n-1; i++)
            for (j=0; j<=n-1; j++)
              { jj=i*l+j; b[jj]=0.0;
                for (kk=0; kk<=n-1; kk++)
                  b[jj]=b[jj]+a[i*l+kk]*p[kk*n+j];
              }
            for (i=0; i<=n-1; i++)
            for (j=0; j<=n-1; j++)
              { jj=i*l+j; a[jj]=0.0;
                for (kk=0; kk<=n-1; kk++)
                  a[jj]=a[jj]+b[i*l+kk]*f[j*n+kk];
              }
            for (i=0; i<=n-1; i++)
            for (j=0; j<=n-1; j++)
              { jj=i*n+j; p[jj]=q[jj];
                for (kk=0; kk<=n-1; kk++)
                  p[jj]=p[jj]+f[i*n+kk]*a[j*l+kk];
              }
          }
      }
    free(e); free(a); free(b);
    return(js);
  }


********************************************************************************************************
C++代码:
#include<windows.h>
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<math.h>
#define N_gauss 256 //需要产生的高斯白噪声序列的点的个数

double *gauss(double ex,double dx,int n_point)//ex:均值;dx:方差;n_point:点数
{ time_t t;
  int i;
  double *mem1;
  mem1=malloc(n_point*sizeof(double));
  srand((unsigned)time(&t));
  for(i=0;i<n_point;i++)
  mem1=(sqrt(-2*log((double)rand()/32768))*cos((double)rand()/32768*2*3.1415926))*sqrt(dx)+ex;
  return(mem1);
}

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
    static TCHAR szAppName[] = TEXT ("LineDemo") ;
    HWND        hwnd ;
    MSG          msg ;
    WNDCLASS    wndclass ;
   
    wndclass.style        = CS_HREDRAW | CS_VREDRAW ;
    wndclass.lpfnWndProc  = WndProc ;
    wndclass.cbClsExtra    = 0 ;
    wndclass.cbWndExtra    = 0 ;
    wndclass.hInstance    = hInstance ;
    wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ;
    wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ;
    wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
    wndclass.lpszMenuName  = NULL ;
    wndclass.lpszClassName = szAppName ;
   
    if (!RegisterClass (&wndclass))
    {
          MessageBox (NULL, TEXT ("Program requires Windows NT!"),
                      szAppName, MB_ICONERROR) ;
          return 0 ;
    }
   
    hwnd = CreateWindow (szAppName, TEXT ("卡尔曼滤波程序。使用VC++编写。姓名: 赵辉, 学号: 200311201"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
   
    ShowWindow (hwnd, iCmdShow) ;
    UpdateWindow (hwnd) ;
   
    while (GetMessage (&msg, NULL, 0, 0))
    {
          TranslateMessage (&msg) ;
          DispatchMessage (&msg) ;
    }
    return msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static int  cxClient, cyClient;
    HDC        hdc;
    PAINTSTRUCT ps;
int        n;
    double      *w,*v;
double      s[N_gauss],x[N_gauss],s_out[N_gauss],k[N_gauss],p[N_gauss];
for(n=0;n<N_gauss;n++)
s[n]=x[n]=s_out[n]=k[n]=p[n]=0;
w=gauss(0,0.82,N_gauss); //产生激励源:w(n)
v=gauss(1,1,N_gauss);    //产生加性噪声:v(n)
    for(n=1;n<N_gauss;n++)  //状态方程
s[n]=s[n-1]+w[n-1]; 
for(n=0;n<N_gauss;n++)  //观测方程
x[n]=s[n]+v[n];
s_out[0]=0;
p[0]=(double)(0.82/0.64);
for(n=1;n<N_gauss;n++)
{
        k[n]=(0.36*p[n-1]+0.82)/(0.36*p[n-1]+0.82+1);
p[n]=(1-k[n])*(0.36*p[n-1]+0.82);
s_out[n]=0.6*s_out[n-1]+k[n]*(x[n]-0.6*s_out[n-1]);
}

    switch (message)
    {
case WM_SIZE:
          cxClient = LOWORD (lParam) ;
          cyClient = HIWORD (lParam) ;
          return 0 ;
         
    case WM_PAINT:
          hdc = BeginPaint (hwnd, &ps) ;
  for(n=0;n<N_gauss;n++)   
          {
  MoveToEx(hdc,n+30,cyClient/2,NULL);
              LineTo(hdc,n+30,cyClient/2+(int)(s[n]*30));
          }
  for(n=0;n<N_gauss;n++)   
          {
  MoveToEx(hdc,n+380,cyClient/2,NULL);
              LineTo(hdc,n+380,cyClient/2+(int)(x[n]*30));
          }
  for(n=0;n<N_gauss;n++)   
          {
  MoveToEx(hdc,n+740,cyClient/2,NULL);
              LineTo(hdc,n+740,cyClient/2+(int)(s_out[n]*30));
          }
  EndPaint (hwnd, &ps) ;
          return 0 ;
         
    case WM_DESTROY:
          PostQuitMessage (0) ;
          return 0 ;
    }
    return DefWindowProc (hwnd, message, wParam, lParam) ;
}

另一种C++

// kalman.h: interface for the kalman class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_KALMAN_H__ED3D740F_01D2_4616_8B74_8BF57636F2C0__INCLUDED_)
#define AFX_KALMAN_H__ED3D740F_01D2_4616_8B74_8BF57636F2C0__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <math.h>
#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(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__INCLUDED_)


============================kalman.cpp================================

#include "kalman.h"
#include <stdio.h>


/* tester de printer toutes les valeurs des vecteurs*/
/* 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 );
    measurement = 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 );

    cvZero( measurement );
   
    cvRandSetRange( &rng, 0, 0.1, 0 );
    rng.disttype = CV_RAND_NORMAL;

    cvRand( &rng, state );

    memcpy( cvkalman->transition_matrix->data.fl, 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, cvRealScalar(1e-5) );   
    //cvSetIdentity( cvkalman->error_cov_post, cvRealScalar(1));
//cvSetIdentity( cvkalman->measurement_noise_cov, cvRealScalar(1e-1) );

    /* choose initial state */

    state->data.fl[0]=x;
    state->data.fl[1]=xv;
    state->data.fl[2]=y;
    state->data.fl[3]=yv;
    cvkalman->state_post->data.fl[0]=x;
    cvkalman->state_post->data.fl[1]=xv;
    cvkalman->state_post->data.fl[2]=y;
    cvkalman->state_post->data.fl[3]=yv;

cvRandSetRange( &rng, 0, sqrt(cvkalman->process_noise_cov->data.fl[0]), 0 );
    cvRand( &rng, process_noise );


    }

   
CvPoint2D32f kalman::get_predict(float x, float y){
   

    /* update state with current position */
    state->data.fl[0]=x;
    state->data.fl[2]=y;

   
    /* predict point position */
    /* x'k=A鈥k+B鈥k
      P'k=A鈥k-1*AT + Q */
    cvRandSetRange( &rng, 0, sqrt(cvkalman->measurement_noise_cov->data.fl[0]), 0 );
    cvRand( &rng, measurement );
   
    /* xk=A?xk-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=P'k鈥T鈥?H鈥'k鈥T+R)-1
      xk=x'k+Kk鈥?zk-H鈥'k)
      Pk=(I-Kk鈥)鈥'k */
    cvKalmanCorrect( cvkalman, measurement );
    float measured_value_x = measurement->data.fl[0];
    float measured_value_y = measurement->data.fl[2];

   
const CvMat* prediction = cvKalmanPredict( cvkalman, 0 );
    float predict_value_x = prediction->data.fl[0];
    float predict_value_y = prediction->data.fl[2];

    return(cvPoint2D32f(predict_value_x,predict_value_y));
}

void kalman::init_kalman(int x,int xv,int y,int yv)
{
state->data.fl[0]=x;
    state->data.fl[1]=xv;
    state->data.fl[2]=y;
    state->data.fl[3]=yv;
    cvkalman->state_post->data.fl[0]=x;
    cvkalman->state_post->data.fl[1]=xv;
    cvkalman->state_post->data.fl[2]=y;
    cvkalman->state_post->data.fl[3]=yv;
}



自动化网六周年庆,我们将“知识性、创造性、建设性、包容性”作为我们编辑工作的核心思想、理念。
顶端 Posted:2007-08-17 10:19 | [楼 主]
guest



级别: *
精华: *
发帖: *
威望: * 点
金钱: * Gold
贡献值: * 点
在线时间:(小时)
注册时间:*



小妹在做毕业设计,跪求kalman滤波完整程序,你说到卡尔曼滤波的另一种C++ 有完整的程序吗? 包含"cv.h "文件,你提供的代码,在调试的时候找不到"cv.h"文件。如果有完整的程序,麻烦大哥发送到l最好采用winrar压缩文件格式,gp_my@163.com,或者QQ:329426587,谢谢。

自动化网六周年庆,我们将“知识性、创造性、建设性、包容性”作为我们编辑工作的核心思想、理念。
顶端 Posted:2008-05-11 12:29 | 1 楼

 自动化网论坛 -> 技术杂坛
快速发帖 顶端
内容
HTML 代码不可用

使用签名
Wind Code自动转换

字数检查 恢复数据
 认证码:  
按 Ctrl+Enter 直接提交
表情 [更多]


Powered by PHPWind v5.3 Code © 2003-05 PHPWind
This is html template view this page faster