搜索
bottom↓
回复: 53

非常好的滤波程序(卡尔曼滤波)

  [复制链接]

出0入0汤圆

发表于 2012-11-12 16:43:23 | 显示全部楼层 |阅读模式
////////////////////Kalman滤波
static float gyro,acceler,Vref=2.048,fangdabeishu=24.6;
static float acc,gg,acce;

static float angle, angle_dot;                
static const float Q_angle = 0.001, Q_gyro = 0.003, R_angle = 0.5, dt = 0.006;
static float PP[2][2] = {{1,0},{0,1}};
static float Pdot[4]  = {0,0,0,0};
static const char C_0 = 1;
static float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;
static float gyro,acceler;

void Kalman_Filter(float angle_m,float gyro_m)               
{
          angle += (gyro_m-q_bias)*dt;

          Pdot[0] = Q_angle-PP[0][1]-PP[1][0];
          Pdot[1] = -PP[1][1];
          Pdot[2] = -PP[1][1];
          Pdot[3] = Q_gyro;

          PP[0][0] += Pdot[0]*dt;
          PP[0][1] += Pdot[1]*dt;
          PP[1][0] += Pdot[2]*dt;
          PP[1][1] += Pdot[3]*dt;

          angle_err = angle_m-angle;

          PCt_0 = C_0*PP[0][0];
          PCt_1 = C_0*PP[1][0];

          E=R_angle+C_0*PCt_0;

          K_0 = PCt_0/E;
          K_1 = PCt_1/E;

          t_0 = PCt_0;
          t_1 = C_0*PP[0][1];

          PP[0][0] -= K_0*t_0;
          PP[0][1] -= K_0*t_1;
          PP[1][0] -= K_1*t_0;
          PP[1][1] -= K_1*t_1;

          angle += K_0*angle_err;
          q_bias += K_1*angle_err;
          angle_dot = (gyro_m-q_bias);
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-11-12 17:10:36 | 显示全部楼层
能否简单介绍一下使用方法?

出0入0汤圆

发表于 2012-11-13 17:06:54 | 显示全部楼层
mark一下

出0入0汤圆

发表于 2012-11-13 17:24:32 | 显示全部楼层
非常难看懂的滤波程序!

出0入0汤圆

 楼主| 发表于 2012-11-13 18:10:16 | 显示全部楼层
我发现是有点乱,发的时候没弄好,非常抱歉,你们可以去百度一下卡尔曼滤波 哪里讲的不错

出0入0汤圆

发表于 2012-11-13 18:27:19 | 显示全部楼层
顶了,谢谢分享

出0入0汤圆

发表于 2012-11-13 19:19:32 | 显示全部楼层
上个图才有说服力

出0入0汤圆

 楼主| 发表于 2012-11-13 21:13:17 | 显示全部楼层
   最佳线性滤波理论起源于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时刻观测噪声



则卡尔曼滤波的算法流程为:





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)^×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;
    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++实现代码如下:

============================kalman.h================================

// 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;
}

出0入0汤圆

 楼主| 发表于 2012-11-13 21:18:34 | 显示全部楼层
有乱码  不影响阅读的 打包好的 想看的慢慢看  

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-11-28 11:25:41 | 显示全部楼层
kan bu dong  ,a

出0入0汤圆

发表于 2012-11-28 12:19:58 | 显示全部楼层
真强啊,学习了

出0入0汤圆

发表于 2012-11-28 17:12:01 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2012-11-28 17:15:11 | 显示全部楼层
今年做二轮平衡车的时候用来卡尔曼,正是此程序。好像是外国人写的

出0入0汤圆

发表于 2012-11-28 19:05:06 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-3-11 23:43:30 | 显示全部楼层
留个记号

出0入0汤圆

发表于 2013-7-13 11:17:33 | 显示全部楼层
太棒了 謝謝

出0入0汤圆

发表于 2013-7-14 17:04:50 | 显示全部楼层

出0入0汤圆

发表于 2013-7-16 16:33:06 | 显示全部楼层
顶                                 

出0入0汤圆

发表于 2013-7-16 19:44:15 | 显示全部楼层
看不懂,有点介绍就好

出0入0汤圆

发表于 2013-7-16 20:43:20 | 显示全部楼层
做个记号先,有时间仔细研究下,感谢楼主的分享

出0入0汤圆

发表于 2013-7-16 20:54:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-7-16 21:04:30 | 显示全部楼层
马克下

出0入0汤圆

发表于 2013-7-16 21:27:23 | 显示全部楼层
先记着。这个高级,以后慢慢消化

出0入0汤圆

发表于 2013-8-27 11:30:01 | 显示全部楼层
MARK                       

出0入0汤圆

发表于 2013-8-27 13:12:24 | 显示全部楼层
算法还是最难的

出0入0汤圆

发表于 2013-8-30 11:20:00 | 显示全部楼层
实验过,回应速度慢....

出0入0汤圆

发表于 2013-8-30 13:38:22 | 显示全部楼层
水平有限只能先收藏以后学习了

出0入0汤圆

发表于 2013-8-30 15:07:13 | 显示全部楼层
先mark         

出0入0汤圆

发表于 2013-8-30 17:06:20 | 显示全部楼层
必须mark

出0入0汤圆

发表于 2013-8-31 10:06:07 | 显示全部楼层
谢谢无私贡献,mark

出0入0汤圆

发表于 2013-8-31 13:01:09 | 显示全部楼层
看不大懂!            

出0入0汤圆

发表于 2013-11-16 08:39:43 | 显示全部楼层
A practical approach to Kalman filter and how to implement it   这是一篇英文方面介绍这个算法的文章.

出0入0汤圆

发表于 2013-11-17 10:55:46 | 显示全部楼层
搜藏下,不过请问这个程序和论坛里Zlstone大大程序里用的滤波函数是一样的么?

出0入0汤圆

发表于 2013-11-20 21:08:18 | 显示全部楼层
xl1736 发表于 2013-11-17 10:55
搜藏下,不过请问这个程序和论坛里Zlstone大大程序里用的滤波函数是一样的么? ...

原理一样的吧,只是zlstone是浓缩版的好像。

出0入0汤圆

发表于 2013-11-20 21:51:18 | 显示全部楼层
MARK有用

出0入0汤圆

发表于 2013-11-20 21:52:20 来自手机 | 显示全部楼层
马克,学习

出0入0汤圆

发表于 2013-11-22 01:44:02 来自手机 | 显示全部楼层
先mark存下来

出0入0汤圆

发表于 2013-11-25 22:48:03 | 显示全部楼层
高深东西,收藏下便于以后用到时再看

出0入0汤圆

发表于 2014-8-28 18:17:00 | 显示全部楼层
先mark存下来,好难懂

出0入0汤圆

发表于 2014-8-29 17:16:25 | 显示全部楼层
不错啊。。。

出0入0汤圆

发表于 2014-9-8 13:09:57 | 显示全部楼层
晦涩难懂啊,不过先mark。留有日后在用

出0入0汤圆

发表于 2014-9-8 13:21:46 | 显示全部楼层
谢谢 分享。。。

出0入0汤圆

发表于 2014-9-8 15:28:33 | 显示全部楼层
谢谢楼主。

出0入0汤圆

发表于 2015-4-5 10:53:23 | 显示全部楼层
楼主加点中文注释就完美了

出0入0汤圆

发表于 2015-4-5 10:59:32 | 显示全部楼层
技术含量很高的原码,谢谢楼主分享。

出0入0汤圆

发表于 2016-11-30 18:34:20 | 显示全部楼层
mark!!

出0入0汤圆

发表于 2016-12-6 00:01:26 | 显示全部楼层
还是没有特么理解

出0入0汤圆

发表于 2016-12-6 02:07:30 | 显示全部楼层
先MARK一下。

出0入4汤圆

发表于 2016-12-6 08:22:41 | 显示全部楼层
多谢楼主

出0入4汤圆

发表于 2016-12-6 08:55:21 | 显示全部楼层
MARK!不过水平有限只能先收藏以后学习了

出0入0汤圆

发表于 2016-12-6 08:56:20 | 显示全部楼层
标记    收藏 以后要用

出0入0汤圆

发表于 2016-12-18 21:53:38 | 显示全部楼层
多谢楼主分享!mark一下

出0入0汤圆

发表于 2016-12-19 18:54:29 | 显示全部楼层
高端的算法,马克

出0入0汤圆

发表于 2018-3-31 16:51:53 | 显示全部楼层
谢谢楼主!留痕学习
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-4 05:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表