opencv kalman滤波学习

20 篇文章 0 订阅

参考网址:https://blog.csdn.net/woaizgw/article/details/73655569?utm_source=blogxgwz1

一、卡尔曼滤波的五个方程

二、opencv中卡尔曼滤波--KalmanFilter类的源码分析

class CV_EXPORTS_W KalmanFilter  
{  
public:      
    CV_WRAP KalmanFilter();                                                                           //构造默认KalmanFilter对象  
    CV_WRAP KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);  //完整构造KalmanFilter对象方法  
    void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F);              //初始化KalmanFilter对象,会替换原来的KF对象  
                                    //dynamParams    过程状态向量的维度
                                    //measureParams    观测向量的维度
                                    //controlParams    控制向量的维度
            
    CV_WRAP const Mat& predict(const Mat& control=Mat());           //计算预测的状态值      
    CV_WRAP const Mat& correct(const Mat& measurement);             //根据测量值更新状态值  
  
    Mat statePre;            //先验估计值 (x'(k)): x'(k)=A*x(k-1)+B*u(k-1) 方程1 
    Mat statePost;           //后验更新值 (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k))  方程4
    Mat transitionMatrix;    //状态转移矩阵 A  
    Mat controlMatrix;       //控制矩阵 B   
    Mat measurementMatrix;   //测量矩阵 H  
    Mat processNoiseCov;     //系统噪声协方差矩阵  Q
    Mat measurementNoiseCov; //测量噪声协方差矩阵  R
    Mat errorCovPre;         //先验协方差矩阵 (P'(k)): P'(k)=A*P(k-1)*At + Q  方程2
    Mat gain;                //卡尔曼增益   (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R)  方程3
    Mat errorCovPost;        //后验协方差矩阵 (P(k)): P(k)=(I-K(k)*H)*P'(k)        方程5
  
    // 临时矩阵  
    Mat temp1;  
    Mat temp2;  
    Mat temp3;  
    Mat temp4;  
    Mat temp5;  
}; 

 1、先看predict()函数的功能
//predict()函数的功能:
//输入形参--控制向量u(k),求出了 先验估计状态向量x'(k) 和 先验估计协方差矩阵p'(k),即求解了方程1、2
    

const Mat& KalmanFilter::predict(const Mat& control)    //此处的control是控制向量u(k)
{
    // update the state: x'(k) = A*x(k)
    statePre = transitionMatrix*statePost;    //当前的后验更新值 作为下一次的 先验估计值
 
    if( !control.empty() )
        // x'(k) = x'(k) + B*u(k)
        statePre += controlMatrix*control;    //到此,完成了方程1
 
    // update error covariance matrices: temp1 = A*P(k)
    temp1 = transitionMatrix*errorCovPost;
 
    // P'(k) = temp1*At + Q
    gemm(temp1, transitionMatrix, 1, processNoiseCov, 1, errorCovPre, GEMM_2_T);    //至此,完成了方程2
 
    // handle the case when there will be measurement before the next predict.
    statePre.copyTo(statePost);
    errorCovPre.copyTo(errorCovPost);
 
    return statePre;
}


其中用到了一个函数gemm(),先将gemm函数原型贴于下面

//gemm()函数的功能

void cv::gemm( InputArray matA, InputArray matB, double alpha,
           InputArray matC, double beta, OutputArray _matD, int flags )


//_matD = matA * InputArray matB * alpha + matC * beta;
//GEMM_2_T 表示对第2个参数矩阵求偏置

2、再看correct()函数原型
//correct()函数的功能:
//输入形参--实际输出z(k),求出了卡尔曼增益Kk、后验更新状态向量x(k) 和 后验更新协方差矩阵p(k),即求解了方程3、4、5

const Mat& KalmanFilter::correct(const Mat& measurement)
{
    // temp2 = H*P'(k)
    temp2 = measurementMatrix * errorCovPre;
 
    // temp3 = temp2*Ht + R
    gemm(temp2, measurementMatrix, 1, measurementNoiseCov, 1, temp3, GEMM_2_T);
 
    // temp4 = inv(temp3)*temp2 = Kt(k)
    solve(temp3, temp2, temp4, DECOMP_SVD);
 
    // K(k)
    gain = temp4.t();    //至此,完成了方程3,求卡尔曼增益
 
    // temp5 = z(k) - H*x'(k)
    temp5 = measurement - measurementMatrix*statePre;
 
    // x(k) = x'(k) + K(k)*temp5
    statePost = statePre + gain*temp5;    //至此,完成了方程4
 
    // P(k) = P'(k) - K(k)*temp2
    errorCovPost = errorCovPre - gain*temp2;    //至此,完成了方程5
 
    return statePost;
}


其中用到了solve函数,将其原型贴于下面
//solve()函数原型
bool cv::solve( InputArray _src, InputArray _src2arg, OutputArray _dst, int method )

3、KalmanFilter类的结构如下
//1.四个成员函数:
CV_WRAP KalmanFilter(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); 
void init(int dynamParams, int measureParams, int controlParams=0, int type=CV_32F); 
CV_WRAP const Mat& predict(const Mat& control=Mat());
CV_WRAP const Mat& correct(const Mat& measurement); 
 
//2.这五个成员变量是调用 上面两个成员函数后,自动求出来的
Mat statePre;
Mat statePost;
Mat gain; 
Mat errorCovPre;      
Mat errorCovPost; 
 
//需要用户自定义的成员变量
Mat transitionMatrix;    //状态转移矩阵 A  
Mat controlMatrix;       //控制矩阵 B   
Mat measurementMatrix;   //测量矩阵 H  
Mat processNoiseCov;     //系统噪声协方差矩阵  Q
Mat measurementNoiseCov; //测量噪声协方差矩阵  R

理解了上述以后,现对卡尔曼滤波的opencv编程步骤做如下总结:
1、定义卡尔曼对象
KalmanFilter KF(int dP, int mP, int cP);//定义状态向量、观测向量、控制向量的维度


2、初始化五个参数 + 三个初始状态
五个参数:
KF.transitionMatrix; //状态转移矩阵 A  //方阵,与状态向量维度相同
KF.controlMatrix; //控制矩阵 B  //若无控制量,B就是0
KF.measurementMatrix; //测量矩阵 H  //行:观测向量的维度;列:状态向量的维度
KF.processNoiseCov; //系统噪声协方差矩阵 Q//方阵,与状态向量维度相同,若为对角阵,表示状态向量各维度之间互不相关
KF.measurementNoiseCov; //测量噪声协方差矩阵 R//方阵,与观测向量维度相同,若为对角阵,表示观测向量各维度之间互不相关
三个初始状态:
KF.statePost; //前一时刻的状态向量x 方便迭代
KF.errorCovPost; //前一时刻的后验协方差矩阵P 方便迭代
//这两个两可以随便给,因为随着卡尔曼滤波的进行,x最终会收敛,但是P初始值不要给0,否则卡尔曼会认为初始化的x(0)就是最优状态
Mat measurement; //当前的观测值y,这个量要自己定义


3、预测
KF.predict; //求出了x'(k) 和 p'(k),该函数输入的是 控制向量u(k),输出是x'(k) 

4、更新
measurement; //更新观测值
KF.correct(measurement); //求出了Kk、x(k) 和p(k),该函数输入的是 观测向量y
 
 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值