00001
00013 #ifndef KF_H
00014 #define KF_H
00015
00016 #include <itpp/itbase.h>
00017 #include "../stat/libFN.h"
00018 #include "../math/libDC.h"
00019
00020
00021 using namespace itpp;
00022
00026 class KalmanFull : public BM {
00027 int dimx, dimy, dimu;
00028 mat A, B, C, D, R, Q;
00029
00030
00031 mat _Pp, _Ry, _iRy, _K;
00032 public:
00033
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, bool evalll=true);
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 int dimx, dimy, dimu;
00057 mat A, B, C, D;
00058 sq_T R, Q;
00059
00060
00061 mat _K;
00062 vec _yp;
00063 sq_T _Ry,_iRy;
00064 public:
00065
00067 vec mu;
00069 sq_T P;
00070
00071 public:
00073 Kalman (int dimx, int dimu, int dimy);
00075 Kalman ( mat A0, mat B0, mat C0, mat D0, sq_T R0, sq_T Q0, sq_T P0, vec mu0 );
00077 void bayes(const vec &dt, bool evalll=true);
00078
00079 friend std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf );
00080
00081 };
00082
00088 template<class sq_T>
00089 class EKF : public Kalman<fsqmat> {
00091 diffbifn* pfxu;
00093 diffbifn* phxu;
00094 public:
00096 EKF (diffbifn* pfxu, diffbifn* phxu, sq_T Q0, sq_T R0, vec mu0, mat P0);
00098 void bayes(const vec &dt, bool evalll=true);
00099 };
00100
00102
00103 template<class sq_T>
00104 Kalman<sq_T>::Kalman( int dx, int du, int dy): BM(), dimx(dx),dimy(dy),dimu(du){
00105 A = mat(dimx,dimx);
00106 B = mat(dimx,dimu);
00107 C = mat(dimy,dimx);
00108 D = mat(dimy,dimu);
00109
00110 mu = vec(dimx);
00111
00112 };
00113
00114 template<class sq_T>
00115 Kalman<sq_T>::Kalman(const mat A0,const mat B0, const mat C0, const mat D0, const sq_T R0, const sq_T Q0, const sq_T P0, const vec mu0 ): BM() {
00116 dimx = A0.rows();
00117 dimu = B0.cols();
00118 dimy = C0.rows();
00119
00120 it_assert_debug( A0.cols()==dimx, "Kalman: A is not square" );
00121 it_assert_debug( B0.rows()==dimx, "Kalman: B is not compatible" );
00122 it_assert_debug( C0.cols()==dimx, "Kalman: C is not square" );
00123 it_assert_debug(( D0.rows()==dimy ) || ( D0.cols()==dimu ), "Kalman: D is not compatible" );
00124 it_assert_debug(( R0.cols()==dimy ) || ( R0.rows()==dimy ), "Kalman: R is not compatible" );
00125 it_assert_debug(( Q0.cols()==dimx ) || ( Q0.rows()==dimx ), "Kalman: Q is not compatible" );
00126
00127 A = A0;
00128 B = B0;
00129 C = C0;
00130 D = D0;
00131 R = R0;
00132 Q = Q0;
00133 mu = mu0;
00134 P = P0;
00135
00136
00137 _iRy = eye(dimy);
00138 _Ry = eye(dimy);
00139 }
00140
00141 template<class sq_T>
00142 void Kalman<sq_T>::bayes( const vec &dt , bool evalll) {
00143 it_assert_debug( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00144
00145 vec u = dt.get( dimy,dimy+dimu-1 );
00146 vec y = dt.get( 0,dimy-1 );
00147
00148 mu = A*mu + B*u;
00149
00150 P.mult_sym( A );
00151 P+=Q;
00152
00153
00154
00155 P.mult_sym( C, _Ry);
00156 _Ry+=R;
00157
00158 mat Pfull = P.to_mat();
00159
00160 _Ry.inv( _iRy );
00161 _K = Pfull*C.transpose()*(_iRy.to_mat());
00162 P -= _K*C*Pfull;
00163 _yp = y-C*mu-D*u;
00164 mu += _K*( _yp );
00165
00166 if (evalll==true) {
00167 ll+= -0.5*(_Ry.cols()*0.79817986835811504957 \
00168 +_Ry.logdet() +_iRy.qform(_yp));
00169 }
00170 };
00171
00172
00173
00174 template<class sq_T>
00175 EKF<sq_T>::EKF( diffbifn* pfxu0, diffbifn* phxu0, sq_T Q0, sq_T R0, vec mu0, mat P0): pfxu(pfxu0), phxu(phxu0), Kalman<fsqmat>(pfxu0->_dimx(),pfxu0->_dimu(),phxu0->_dimy()) {
00176
00177
00178 pfxu->dfdx_cond(mu,zeros(dimu),A,true);
00179 pfxu->dfdu_cond(mu,zeros(dimu),B,true);
00180 phxu->dfdx_cond(mu,zeros(dimu),C,true);
00181 phxu->dfdu_cond(mu,zeros(dimu),D,true);
00182
00183
00184 R = R0;
00185 Q = Q0;
00186 mu = mu0;
00187 P = P0;
00188
00189 using std::cout;
00190 cout<<A<<std::endl;
00191 cout<<B<<std::endl;
00192 cout<<C<<std::endl;
00193 cout<<D<<std::endl;
00194
00195 }
00196
00197 template<class sq_T>
00198 void EKF<sq_T>::bayes( const vec &dt , bool evalll) {
00199 it_assert_debug( dt.length()==( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
00200
00201 vec u = dt.get( dimy,dimy+dimu-1 );
00202 vec y = dt.get( 0,dimy-1 );
00203
00204 mu = pfxu->eval(mu, u);
00205 pfxu->dfdx_cond(mu,u,A,false);
00206
00207
00208 P.mult_sym( A );
00209 P+=Q;
00210
00211
00212 phxu->dfdx_cond(mu,u,C,false);
00213
00214 P.mult_sym( C, _Ry);
00215 _Ry+=R;
00216
00217 mat Pfull = P.to_mat();
00218
00219 _Ry.inv( _iRy );
00220 _K = Pfull*C.transpose()*(_iRy.to_mat());
00221 P -= _K*C*Pfull;
00222 _yp = y-phxu->eval(mu,u);
00223 mu += _K*( _yp );
00224
00225 if (evalll==true) {
00226 ll+= -0.5*(_Ry.cols()*0.79817986835811504957 \
00227 +_Ry.logdet() +_iRy.qform(_yp));
00228 }
00229 };
00230
00231
00232 #endif // KF_H
00233
00234