work/mixpp/bdm/estim/libKF.h

Go to the documentation of this file.
00001 
00013 #ifndef KF_H
00014 #define KF_H
00015 
00016 #include <itpp/itbase.h>
00017 #include "../stat/libFN.h"
00018 #include "../stat/libEF.h"
00019 
00020 
00021 using namespace itpp;
00022 
00026 class KalmanFull { 
00027         int dimx, dimy, dimu;
00028         mat A, B, C, D, R, Q;
00029         
00030         //cache 
00031         mat _Pp, _Ry, _iRy, _K;
00032 public:
00033         //posterior 
00035         vec mu;
00037         mat P;
00038 
00039 public:
00041         KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0);
00043         void bayes(const vec &dt); 
00044 
00045         friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf );
00046 
00047 };
00048 
00049 
00053 template<class sq_T>
00054 class Kalman : public BM { 
00055 protected:
00056         RV rvy;
00057         RV rvu;
00058         int dimx, dimy, dimu;
00059         mat A, B, C, D;
00060         sq_T R, Q;
00061         
00063         enorm<sq_T> est;
00065         enorm<sq_T> fy;
00066         
00067         mat _K;
00068         //cache of fy
00069         vec* _yp; 
00070         sq_T* _Ry,*_iRy;
00071         //cache of est
00072         vec* _mu;
00073         sq_T* _P, *_iP;
00074         
00075 public:
00077         Kalman (RV rvx0, RV rvy0, RV rvu0);
00079         Kalman (const Kalman<sq_T> &K0);
00081         void set_parameters (const mat &A0,const mat &B0,const mat &C0,const mat &D0,const sq_T &R0,const sq_T &Q0);
00083         void set_est(const vec &mu0, const sq_T &P0 ){est.set_parameters(mu0,P0);};
00085         void bayes(const vec &dt); 
00086         epdf& _epdf(){return est;}
00087 //      friend std::ostream &operator<< ( std::ostream &os, const Kalman<sq_T> &kf );
00088 
00090 };
00091 
00097 template<class sq_T>
00098 class EKF : public Kalman<ldmat> {
00100         diffbifn* pfxu;
00102         diffbifn* phxu;
00103 public: 
00105         EKF (RV rvx, RV rvy, RV rvu);
00106         void set_parameters(diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0);
00108         void bayes(const vec &dt);      
00109 };
00110 
00114 class KFcondQR : public Kalman<ldmat>, public BMcond {
00115 //protected:
00116 public:
00117 KFcondQR(RV rvx, RV rvy, RV rvu): Kalman<ldmat>(rvx, rvy,rvu){};
00118 void condition(const vec &RQ);
00119 };
00120 
00122 
00123 template<class sq_T>
00124 Kalman<sq_T>::Kalman(const Kalman<sq_T> &K0): BM(K0.rv),rvy(K0.rvy),rvu(K0.rvu),
00125 dimx(rv.count()), dimy(rvy.count()),dimu(rvu.count()), 
00126  A(dimx,dimx), B(dimx,dimu), C(dimy,dimx), D(dimy,dimu),est(rv), fy(rvy){
00127 this->set_parameters(K0.A, K0.B, K0.C, K0.D, K0.R, K0.Q);
00128 //reset copy values in pointers
00129 *_mu = *K0._mu;
00130 *_P = *K0._P;
00131 *_iP = *K0._iP;
00132 *_yp = *K0._yp;
00133 *_iRy = *K0._iRy;
00134 *_Ry = *K0._Ry;
00135 
00136 }
00137 
00138 template<class sq_T>
00139 Kalman<sq_T>::Kalman(RV rvx, RV rvy0, RV rvu0): BM(rvx),rvy(rvy0),rvu(rvu0),
00140 dimx(rvx.count()), dimy(rvy.count()),dimu(rvu.count()), 
00141  A(dimx,dimx), B(dimx,dimu), C(dimy,dimx), D(dimy,dimu),est(rvx), fy(rvy){
00142 //assign cache
00143 //est
00144 _mu = est._mu();
00145 est._R(_P,_iP);
00146 
00147 //fy
00148 _yp = fy._mu();
00149 fy._R(_Ry,_iRy);
00150 };
00151 
00152 template<class sq_T>
00153 void Kalman<sq_T>::set_parameters(const mat &A0,const  mat &B0, const mat &C0, const mat &D0, const sq_T &R0, const sq_T &Q0) {
00154         it_assert_debug( A0.cols()==dimx, "Kalman: A is not square" );
00155         it_assert_debug( B0.rows()==dimx, "Kalman: B is not compatible" );
00156         it_assert_debug( C0.cols()==dimx, "Kalman: C is not square" );
00157         it_assert_debug(( D0.rows()==dimy ) || ( D0.cols()==dimu ),     "Kalman: D is not compatible" );
00158         it_assert_debug(( R0.cols()==dimy ) || ( R0.rows()==dimy ), "Kalman: R is not compatible" );
00159         it_assert_debug(( Q0.cols()==dimx ) || ( Q0.rows()==dimx ), "Kalman: Q is not compatible" );
00160 
00161         A = A0;
00162         B = B0;
00163         C = C0;
00164         D = D0;
00165         R = R0;
00166         Q = Q0; 
00167 }
00168 
00169 template<class sq_T>
00170 void Kalman<sq_T>::bayes( const vec &dt) {
00171         it_assert_debug( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00172 
00173         vec u = dt.get( dimy,dimy+dimu-1 );
00174         vec y = dt.get( 0,dimy-1 );
00175         //Time update
00176         *_mu = A*(*_mu) + B*u;
00177         //P  = A*P*A.transpose() + Q; in sq_T
00178         _P->mult_sym( A );
00179         (*_P)+=Q;
00180 
00181         //Data update
00182         //_Ry = C*P*C.transpose() + R; in sq_T
00183         _P->mult_sym( C, *_Ry);
00184         (*_Ry)+=R;
00185 
00186         mat Pfull = _P->to_mat();
00187         
00188         _Ry->inv( *_iRy ); // result is in _iRy;
00189         _K = Pfull*C.transpose()*(_iRy->to_mat());
00190         
00191         sq_T pom((int)Pfull.rows());
00192         _iRy->mult_sym_t(C*Pfull,pom);
00193         (*_P) -= pom; // P = P -PC'iRy*CP;
00194         (*_yp) = C*(*_mu)+D*u; //y prediction
00195         (*_mu) += _K*( y-(*_yp) );
00196         
00197         if (evalll==true) {
00198                 ll+=fy.evalpdflog(*_yp);
00199         }
00200 };
00201 
00202 //TODO why not const pointer??
00203 
00204 template<class sq_T>
00205 EKF<sq_T>::EKF(RV rvx0, RV rvy0, RV rvu0): Kalman<ldmat>(rvx0,rvy0,rvu0){}
00206 
00207 template<class sq_T>
00208 void EKF<sq_T>::set_parameters(diffbifn* pfxu0,  diffbifn* phxu0,const sq_T Q0,const sq_T R0) {
00209                 pfxu = pfxu0;
00210                 phxu = phxu0;
00211                 
00212                 //initialize matrices A C, later, these will be only updated!
00213                 pfxu->dfdx_cond(*_mu,zeros(dimu),A,true);
00214                 pfxu->dfdu_cond(*_mu,zeros(dimu),B,true);
00215                 phxu->dfdx_cond(*_mu,zeros(dimu),C,true);
00216                 phxu->dfdu_cond(*_mu,zeros(dimu),D,true);
00217 
00218                 R = R0;
00219                 Q = Q0;
00220 
00221         using std::cout;
00222         cout<<A<<std::endl;
00223         cout<<B<<std::endl;
00224         cout<<C<<std::endl;
00225         cout<<D<<std::endl;
00226 
00227 }
00228 
00229 template<class sq_T>
00230 void EKF<sq_T>::bayes( const vec &dt) {
00231         it_assert_debug( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00232 
00233         vec u = dt.get( dimy,dimy+dimu-1 );
00234         vec y = dt.get( 0,dimy-1 );
00235         //Time update
00236         *_mu = pfxu->eval(*_mu, u);
00237         pfxu->dfdx_cond(*_mu,u,A,false); //update A by a derivative of fx
00238         
00239         //P  = A*P*A.transpose() + Q; in sq_T
00240         _P->mult_sym( A );
00241         (*_P)+=Q;
00242 
00243         //Data update
00244         phxu->dfdx_cond(*_mu,u,C,false); //update C by a derivative hx
00245         //_Ry = C*P*C.transpose() + R; in sq_T
00246         _P->mult_sym( C, *_Ry);
00247         (*_Ry)+=R;
00248 
00249         mat Pfull = _P->to_mat();
00250         
00251         _Ry->inv( *_iRy ); // result is in _iRy;
00252         _K = Pfull*C.transpose()*(_iRy->to_mat());
00253         
00254         sq_T pom((int)Pfull.rows());
00255         _iRy->mult_sym_t(C*Pfull,pom);
00256         (*_P) -= pom; // P = P -PC'iRy*CP;
00257         *_yp = phxu->eval(*_mu,u); //y prediction
00258         (*_mu) += _K*( y-*_yp );
00259         
00260         if (evalll==true) {ll+=est.evalpdflog(y);}
00261 };
00262 
00263 
00264 #endif // KF_H
00265 
00266 

Generated on Thu Feb 28 16:54:39 2008 for mixpp by  doxygen 1.5.3