00001 
00013 #ifndef KF_H
00014 #define KF_H
00015 
00016 
00017 #include "../stat/libFN.h"
00018 #include "../stat/libEF.h"
00019 #include "../math/chmat.h"
00020 
00021 namespace bdm{
00022 
00027 class KalmanFull {
00028 protected:
00029         int dimx, dimy, dimu;
00030         mat A, B, C, D, R, Q;
00031 
00032         
00033         mat _Pp, _Ry, _iRy, _K;
00034 public:
00035         
00037         vec mu;
00039         mat P;
00040 
00041         bool evalll;
00042         double ll;
00043 public:
00045         KalmanFull ( mat A, mat B, mat C, mat D, mat R, mat Q, mat P0, vec mu0 );
00047         void bayes ( const vec &dt );
00049         friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf );
00051         KalmanFull(){};
00052 };
00053 
00054 
00062 template<class sq_T>
00063 
00064 class Kalman : public BM {
00065 protected:
00067         RV rvy;
00069         RV rvu;
00071         int dimx;
00073         int dimy;
00075         int dimu;
00077         mat A;
00079         mat B; 
00081         mat C;
00083         mat D;
00085         sq_T Q;
00087         sq_T R;
00088 
00090         enorm<sq_T> est;
00092         enorm<sq_T> fy;
00093 
00095         mat _K;
00097         vec& _yp;
00099         sq_T& _Ry;
00101         vec& _mu;
00103         sq_T& _P;
00104 
00105 public:
00107         Kalman ( );
00109         Kalman ( const Kalman<sq_T> &K0 );
00111         void set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const sq_T &Q0,const sq_T &R0 );
00113         void set_est ( const vec &mu0, const sq_T &P0 ) {
00114                 sq_T pom(dimy);
00115                 est.set_parameters ( mu0,P0 );
00116                 P0.mult_sym(C,pom);
00117                 fy.set_parameters ( C*mu0, pom );
00118         };
00119 
00121         void bayes ( const vec &dt );
00123         const epdf& posterior() const {return est;}
00124         const enorm<sq_T>* _e() const {return &est;}
00126         mat& __K() {return _K;}
00128         vec _dP() {return _P->getD();}
00129 };
00130 
00137 class KalmanCh : public Kalman<chmat>{
00138 protected:
00140 mat preA;
00142 mat postA;
00143 
00144 public:
00146         KalmanCh ():Kalman<chmat>(),preA(),postA(){};
00148         void set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const chmat &Q0,const chmat &R0 );
00149         void set_statistics ( const vec &mu0, const chmat &P0 ) {
00150                 est.set_parameters ( mu0,P0 );
00151         };
00152         
00153         
00167         void bayes ( const vec &dt );
00168 };
00169 
00175 class EKFfull : public KalmanFull, public BM {
00176 
00178         diffbifn* pfxu;
00180         diffbifn* phxu;
00181         
00182         enorm<fsqmat> E; 
00183 public:
00185         EKFfull ( );
00187         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const mat Q0, const mat R0 );
00189         void bayes ( const vec &dt );
00191         void set_est (vec mu0, mat P0){mu=mu0;P=P0;};
00193         const epdf& posterior()const{return E;};
00194         const enorm<fsqmat>* _e()const{return &E;};
00195         const mat _R(){return P;}
00196 };
00197 
00203 template<class sq_T>
00204 class EKF : public Kalman<fsqmat> {
00206         diffbifn* pfxu;
00208         diffbifn* phxu;
00209 public:
00211         EKF ( RV rvx, RV rvy, RV rvu );
00213         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const sq_T Q0, const sq_T R0 );
00215         void bayes ( const vec &dt );
00216 };
00217 
00224 class EKFCh : public KalmanCh {
00225         protected:
00227         diffbifn* pfxu;
00229         diffbifn* phxu;
00230 public:
00232         EKFCh ();
00234         void set_parameters ( diffbifn* pfxu, diffbifn* phxu, const chmat Q0, const chmat R0 );
00236         void bayes ( const vec &dt );
00237 };
00238 
00243 class KFcondQR : public Kalman<ldmat>, public BMcond {
00244 
00245 public:
00247         KFcondQR ( ) : Kalman<ldmat> ( ),BMcond ( ) {};
00248 
00249         void condition ( const vec &RQ );
00250 };
00251 
00256 class KFcondR : public Kalman<ldmat>, public BMcond {
00257 
00258 public:
00260         KFcondR ( ) : Kalman<ldmat> ( ),BMcond ( ) {};
00261 
00262         void condition ( const vec &R );
00263 };
00264 
00266 
00267 template<class sq_T>
00268 Kalman<sq_T>::Kalman ( const Kalman<sq_T> &K0 ) : BM ( ),rvy ( K0.rvy ),rvu ( K0.rvu ),
00269                 dimx ( K0.dimx ), dimy ( K0.dimy ),dimu ( K0.dimu ),
00270                 A ( K0.A ), B ( K0.B ), C ( K0.C ), D ( K0.D ),
00271                 Q(K0.Q), R(K0.R),
00272                 est ( K0.est ), fy ( K0.fy ), _yp(fy._mu()),_Ry(fy._R()), _mu(est._mu()), _P(est._R()) {
00273 
00274 
00275 
00276 
00277 
00278 
00279 
00280 }
00281 
00282 template<class sq_T>
00283 Kalman<sq_T>::Kalman ( ) : BM (), est ( ), fy (),  _yp(fy._mu()), _Ry(fy._R()), _mu(est._mu()), _P(est._R()) {
00284 };
00285 
00286 template<class sq_T>
00287 void Kalman<sq_T>::set_parameters ( const mat &A0,const  mat &B0, const mat &C0, const mat &D0, const sq_T &Q0, const sq_T &R0 ) {
00288         dimx = A0.rows();
00289         dimy = C0.rows();
00290         dimu = B0.cols();
00291         
00292         it_assert_debug ( A0.cols() ==dimx, "Kalman: A is not square" );
00293         it_assert_debug ( B0.rows() ==dimx, "Kalman: B is not compatible" );
00294         it_assert_debug ( C0.cols() ==dimx, "Kalman: C is not square" );
00295         it_assert_debug ( ( D0.rows() ==dimy ) || ( D0.cols() ==dimu ), "Kalman: D is not compatible" );
00296         it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "Kalman: R is not compatible" );
00297         it_assert_debug ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "Kalman: Q is not compatible" );
00298 
00299         A = A0;
00300         B = B0;
00301         C = C0;
00302         D = D0;
00303         R = R0;
00304         Q = Q0;
00305 }
00306 
00307 template<class sq_T>
00308 void Kalman<sq_T>::bayes ( const vec &dt ) {
00309         it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00310 
00311         sq_T iRy(dimy);
00312         vec u = dt.get ( dimy,dimy+dimu-1 );
00313         vec y = dt.get ( 0,dimy-1 );
00314         
00315         _mu = A* _mu + B*u;
00316         
00317         _P.mult_sym ( A );
00318         _P  +=Q;
00319 
00320         
00321         
00322         _P.mult_sym ( C, _Ry );
00323         _Ry  +=R;
00324 
00325         mat Pfull = _P.to_mat();
00326 
00327         _Ry.inv ( iRy ); 
00328         _K = Pfull*C.transpose() * ( iRy.to_mat() );
00329 
00330         sq_T pom ( ( int ) Pfull.rows() );
00331         iRy.mult_sym_t ( C*Pfull,pom );
00332         (_P ) -= pom; 
00333         (_yp ) = C* _mu  +D*u; 
00334         (_mu ) += _K* ( y- _yp  );
00335 
00336 
00337         if ( evalll==true ) { 
00338                 ll=fy.evallog ( y );
00339         }
00340 
00341 
00342 
00343 };
00344  
00345 
00346 
00347 
00348 
00349 template<class sq_T>
00350 EKF<sq_T>::EKF ( RV rvx0, RV rvy0, RV rvu0 ) : Kalman<sq_T> ( rvx0,rvy0,rvu0 ) {}
00351 
00352 template<class sq_T>
00353 void EKF<sq_T>::set_parameters ( diffbifn* pfxu0,  diffbifn* phxu0,const sq_T Q0,const sq_T R0 ) {
00354         pfxu = pfxu0;
00355         phxu = phxu0;
00356 
00357         
00358         pfxu->dfdx_cond ( _mu,zeros ( dimu ),A,true );
00359 
00360         B.clear();
00361         phxu->dfdx_cond ( _mu,zeros ( dimu ),C,true );
00362 
00363         D.clear();
00364 
00365         R = R0;
00366         Q = Q0;
00367 }
00368 
00369 template<class sq_T>
00370 void EKF<sq_T>::bayes ( const vec &dt ) {
00371         it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00372 
00373         sq_T iRy(dimy,dimy);
00374         vec u = dt.get ( dimy,dimy+dimu-1 );
00375         vec y = dt.get ( 0,dimy-1 );
00376         
00377         _mu = pfxu->eval ( _mu, u );
00378         pfxu->dfdx_cond ( _mu,u,A,false ); 
00379 
00380         
00381         _P.mult_sym ( A );
00382         _P +=Q;
00383 
00384         
00385         phxu->dfdx_cond ( _mu,u,C,false ); 
00386         
00387         _P.mult_sym ( C, _Ry );
00388         ( _Ry ) +=R;
00389 
00390         mat Pfull = _P.to_mat();
00391 
00392         _Ry.inv ( iRy ); 
00393         _K = Pfull*C.transpose() * ( iRy.to_mat() );
00394 
00395         sq_T pom ( ( int ) Pfull.rows() );
00396         iRy.mult_sym_t ( C*Pfull,pom );
00397         (_P ) -= pom; 
00398         _yp = phxu->eval ( _mu,u ); 
00399         ( _mu ) += _K* ( y-_yp );
00400 
00401         if ( evalll==true ) {ll+=fy.evallog ( y );}
00402 };
00403 
00404 
00405 }
00406 #endif // KF_H
00407 
00408