Changeset 1158 for library

Show
Ignore:
Timestamp:
08/17/10 22:06:50 (14 years ago)
Author:
smidl
Message:

Kalman with UD (bierman, thorton) and tests

Location:
library
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • library/bdm/estim/kalman.cpp

    r1064 r1158  
    436436} 
    437437 
    438 } 
     438void EKF_UD::set_parameters ( const shared_ptr<diffbifn> &pfxu0, const shared_ptr<diffbifn> &phxu0, const mat Q0, const vec R0 ) { 
     439        pfxu = pfxu0; 
     440        phxu = phxu0; 
     441         
     442        set_dim ( pfxu0->_dimx() ); 
     443        dimy = phxu0->dimension(); 
     444        dimc = pfxu0->_dimu(); 
     445         
     446        vec &_mu = est._mu(); 
     447        // if mu is not set, set it to zeros, just for constant terms of A and C 
     448        if ( _mu.length() != dimension() ) _mu = zeros ( dimension() ); 
     449        A = zeros ( dimension(), dimension() ); 
     450        C = zeros ( dimy, dimension() ); 
     451         
     452        //initialize matrices A C, later, these will be only updated! 
     453        pfxu->dfdx_cond ( _mu, zeros ( dimc ), A, true ); 
     454        //      pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true ); 
     455        phxu->dfdx_cond ( _mu, zeros ( dimc ), C, true ); 
     456        //      phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true ); 
     457         
     458        R = R0; 
     459        Q = Q0; 
     460         
     461        //  
     462} 
     463 
     464 
     465void EKF_UD::bayes ( const vec &yt, const vec &cond ) { 
     466        //preparatory 
     467        vec &_mu=est._mu(); 
     468        const vec &u=cond; 
     469        int dim = dimension(); 
     470         
     471        U = est._R()._L().T(); 
     472        D =  est._R()._D(); 
     473         
     474        //////////// 
     475         
     476        pfxu->dfdx_cond ( _mu, u, A, false ); //update A by a derivative of fx 
     477        phxu->dfdx_cond ( _mu, u, C, false ); //update A by a derivative of fx 
     478 
     479        mat PhiU = A*U; 
     480         
     481        vec Din = D; 
     482        int i,j,k; 
     483        double sigma; 
     484        mat G = eye(dim); 
     485        //////// thorton 
     486         
     487        //move mean; 
     488        _mu = pfxu->eval(_mu,u); 
     489         
     490        for (i=dim-1; i>=0;i--){ 
     491                sigma = 0.0;  
     492                for (j=0; j<dim; j++) { 
     493                        sigma += PhiU(i,j)*PhiU(i,j) *Din(j);  
     494                        sigma += G(i,j)*G(i,j) * Q(j,j);  
     495                } 
     496                D(i) = sigma;  
     497                for (j=0;j<i;j++){  
     498                        sigma = 0.0;  
     499                        for (k=0;k<dim;k++){  
     500                                sigma += PhiU(i,k)*Din(k)*PhiU(j,k);  
     501                        } 
     502                        for (k=0;k<dim;k++){  
     503                                sigma += G(i,k)*Q(k,k)*G(j,k);  
     504                        } 
     505                        // 
     506                        U(j,i) = sigma/D(i);  
     507                        for (k=0;k<dim;k++){  
     508                                PhiU(j,k) = PhiU(j,k) - U(j,i)*PhiU(i,k);  
     509                        } 
     510                        for (k=0;k<dim;k++){  
     511                                G(j,k) = G(j,k) - U(j,i)*G(i,k);  
     512                        } 
     513                } 
     514        } 
     515        //cout << "Ut: " << U << endl; 
     516        //cout << "Dt: " << D << endl; 
     517        // bierman 
     518         
     519        double dz,alpha,gamma,beta,lambda; 
     520        vec a; 
     521        vec b; 
     522        vec yp = phxu->eval(_mu,u); 
     523        for (int iy=0; iy<dimy; iy++){ 
     524                a     = U.T()*C.get_row(iy);    // a is not modified, but  
     525                b     = elem_mult(D,a);                          // b is modified to become unscaled Kalman gain.  
     526                dz    = yt(iy) - yp(iy);  
     527 
     528                alpha = R(iy);  
     529                gamma = 1/alpha;  
     530                for (j=0;j<dim;j++){ 
     531                        beta   = alpha;  
     532                        alpha  = alpha + a(j)*b(j);  
     533                        lambda = -a(j)*gamma;  
     534                        gamma  = 1.0/alpha;  
     535                        D(j) = beta*gamma*D(j);  
     536 
     537                        cout << "a: " << alpha << "g: " << gamma << endl; 
     538                        for (i=0;i<j;i++){ 
     539                                beta   = U(i,j);  
     540                                U(i,j) = beta + b(i)*lambda;  
     541                                b(i)   = b(i) + b(j)*beta;  
     542                        } 
     543                } 
     544                double dzs = gamma*dz;  // apply scaling to innovations  
     545                _mu   = _mu + dzs*b; // multiply by unscaled Kalman gain  
     546                 
     547                //cout << "Ub: " << U << endl; 
     548                //cout << "Db: " << D << endl <<endl; 
     549                 
     550        } 
     551                 
     552///// 
     553est._R().__L()=U.T(); 
     554est._R().__D()=D; 
     555 
     556        if ( evalll == true ) { //likelihood of observation y 
     557        } 
     558} 
     559 
     560void EKF_UD::from_setting ( const Setting &set ) { 
     561        BM::from_setting ( set ); 
     562        shared_ptr<diffbifn> IM = UI::build<diffbifn> ( set, "IM", UI::compulsory ); 
     563        shared_ptr<diffbifn> OM = UI::build<diffbifn> ( set, "OM", UI::compulsory ); 
     564         
     565        //statistics 
     566        int dim = IM->dimension(); 
     567        vec mu0; 
     568        if ( !UI::get ( mu0, set, "mu0" ) ) 
     569                mu0 = zeros ( dim ); 
     570         
     571        mat P0; 
     572        vec dP0; 
     573        if ( UI::get ( dP0, set, "dP0" ) ) 
     574                P0 = diag ( dP0 ); 
     575        else if ( !UI::get ( P0, set, "P0" ) ) 
     576                P0 = eye ( dim ); 
     577         
     578        est._mu()=mu0; 
     579        est._R()=ldmat(P0); 
     580         
     581        //parameters 
     582        vec dQ, dR; 
     583        UI::get ( dQ, set, "dQ", UI::compulsory ); 
     584        UI::get ( dR, set, "dR", UI::compulsory ); 
     585        set_parameters ( IM, OM, diag ( dQ ), dR  ); 
     586} 
     587 
     588} 
  • library/bdm/estim/kalman.h

    r1154 r1158  
    362362 
    363363    void validate() { 
    364         KalmanFull::validate(); 
     364       // KalmanFull::validate(); 
    365365 
    366366        // check stats and IM and OM 
     
    426426SHAREDPTR ( EKFCh ); 
    427427 
     428//! EKF using bierman and Thorton code 
     429class EKF_UD : public BM { 
     430        protected: 
     431                //! Internal Model f(x,u) 
     432                shared_ptr<diffbifn> pfxu; 
     433                 
     434                //! Observation Model h(x,u) 
     435                shared_ptr<diffbifn> phxu; 
     436                 
     437                //! U part 
     438                mat U; 
     439                //! D part 
     440                vec D; 
     441                 
     442                mat A; 
     443                mat C; 
     444                mat Q; 
     445                vec R; 
     446 
     447                enorm<ldmat> est; 
     448        public: 
     449                //! copy constructor duplicated  
     450                EKF_UD* _copy() const { 
     451                        return new EKF_UD(*this); 
     452                } 
     453 
     454                const enorm<ldmat>& posterior()const{return est;}; 
     455                 
     456                enorm<ldmat>& prior() { 
     457                        return const_cast<enorm<ldmat>&>(posterior()); 
     458                } 
     459                 
     460 
     461                EKF_UD(){} 
     462                 
     463                EKF_UD(const EKF_UD &E0): pfxu(E0.pfxu),phxu(E0.phxu), U(E0.U), D(E0.D){} 
     464                 
     465                //! Set nonlinear functions for mean values and covariance matrices. 
     466                void set_parameters ( const shared_ptr<diffbifn> &pfxu, const shared_ptr<diffbifn> &phxu, const mat Q0, const vec R0 ); 
     467                 
     468                //! Here dt = [yt;ut] of appropriate dimensions 
     469                void bayes ( const vec &yt, const vec &cond = empty_vec ); 
     470                 
     471                /*! Create object from the following structure 
     472                 
     473                \code 
     474                class = 'EKF_UD'; 
     475                OM = configuration of bdm::diffbifn;    % any offspring of diffbifn, bdm::diffbifn::from_setting 
     476                IM = configuration of bdm::diffbifn;    % any offspring of diffbifn, bdm::diffbifn::from_setting 
     477                dQ = [...];                             % vector containing diagonal of Q 
     478                dR = [...];                             % vector containing diagonal of R 
     479                --- optional fields --- 
     480                mu0 = [...];                            % vector of statistics mu0 
     481                dP0 = [...];                            % vector containing diagonal of P0 
     482                -- or -- 
     483                P0 = [...];                             % full matrix P0 
     484                --- inherited fields --- 
     485                bdm::BM::from_setting 
     486                \endcode 
     487                If the optional fields are not given, they will be filled as follows: 
     488                \code 
     489                mu0 = [0,0,0,....];                     % empty statistics 
     490                P0 = eye( dim );               
     491                \endcode 
     492                */ 
     493                void from_setting ( const Setting &set ); 
     494                 
     495                void validate() {}; 
     496                // TODO dodelat void to_setting( Setting &set ) const; 
     497                 
     498}; 
     499UIREGISTER(EKF_UD); 
     500 
    428501class UKFCh : public EKFCh{ 
    429502        public: 
     
    468541         
    469542                //step 4 
    470                 mat Xpred_dif(dim2,dim); 
     543                mat P4=Q.to_mat(); 
     544                vec tmp; 
    471545                for (i=0;i<dim2;i++){ 
    472                         Xpred_dif.set_row(i, sqrt(w(i)) * (Xik.get_col(i) - xp)); 
     546                        tmp = Xik.get_col(i)-xp; 
     547                        P4+=w(i)*outer_product(tmp,tmp); 
    473548                }                
    474                  
    475                 // NEW Sigma points 
    476                 mat tmp; 
    477                 qr(concat_vertical(Xpred_dif,Q._Ch()), tmp); 
    478                 mat Ppred=tmp.get_rows(0,dim-1); 
    479                 // New Xi(k+1) 
    480                 Xik.set_col(0,xp); 
    481                 for ( i=0;i<dim; i++){ 
    482                         vec tmp=sqrt(npk)*Ppred.get_col(i); 
    483                         Xik.set_col(i+1, _mu+tmp); 
    484                         Xik.set_col(i+1+dim, _mu-tmp); 
    485                 } 
    486                 for (i=0;i<dim2;i++){ 
    487                         Xpred_dif.set_row(i, sqrt(w(i)) * (Xik.get_col(i) - xp)); 
    488                 }                
    489                  
    490                  
    491                  
     549                                         
    492550                //step 5 
    493551                mat Yi(dimy,dim2); 
     
    501559                } 
    502560                //step 7 
    503                 mat Ypred_dif(dim2,dimy); 
    504                  
    505                 for (i=0; i<dim2; i++){ 
    506                         Ypred_dif.set_row(i, sqrt(w(i))*(Yi.get_col(i)-_yp)); 
    507                 } 
    508                 if (!qr(concat_vertical(Ypred_dif,R._Ch()) ,tmp)){ bdm_warning("QR failed");} 
    509                 _Ry._Ch() = tmp.get_rows(0,dimy-1); 
     561                mat Pvv=R.to_mat(); 
     562                for (i=0;i<dim2;i++){ 
     563                        tmp = Yi.get_col(i)-_yp; 
     564                        Pvv+=w(i)*outer_product(tmp,tmp); 
     565                }                
     566                _Ry._Ch() = chol(Pvv); 
    510567                 
    511568                // step 8 
    512                 mat Pxy=Xpred_dif.T()*Ypred_dif; 
     569                mat Pxy=zeros(dim,dimy); 
     570                for (i=0;i<dim2;i++){ 
     571                        Pxy+=w(i)*outer_product(Xi.get_col(i)-xp, Yi.get_col(i)-_yp); 
     572                }                
    513573                mat iRy=inv(_Ry._Ch()); 
    514574                 
     
    516576                mat K=Pxy*iRy*iRy.T(); 
    517577                mat K2=Pxy*inv(_Ry.to_mat()); 
    518                  
     578                                 
    519579                /////////////// new filtering density 
    520580                _mu = xp + K*(yt - _yp); 
     581                 
     582                if ( _mu ( 3 ) >pi ) _mu ( 3 )-=2*pi; 
     583                if ( _mu ( 3 ) <-pi ) _mu ( 3 ) +=2*pi; 
    521584                // fill the space in Ppred; 
    522                 mat Rpred =concat_vertical(Xpred_dif - Ypred_dif*K.T(), _Ry._Ch()*K.T()); 
    523                  
    524                 if(!qr(Rpred,tmp)) {bdm_warning("QR failed");} 
    525                 _P._Ch()=tmp.get_rows(0,dim-1); 
     585                _P._Ch()=chol(P4-K*_Ry.to_mat()*K.T()); 
    526586        } 
    527587        void from_setting(const Setting &set){ 
  • library/tests/stresssuite/kalman_stress.cpp

    r1064 r1158  
    5151    RV ry ( "{y }", vec_1 ( C.rows() ) ); 
    5252 
    53 //      // LDMAT 
    54 //      Kalman<ldmat> KF(rx,ry,ru); 
    55 //      KF.set_parameters(A,B,C,D,ldmat(R),ldmat(Q)); 
    56 //      KF.set_est(mu0,ldmat(P0) ); 
    57 //      epdf& KFep = KF.posterior(); 
    58 //      mat Xt(2,Ndat); 
    59 //      Xt.set_col( 0,KFep.mean() ); 
     53        // LDMAT 
     54        EKF_UD KFu; 
     55        KFu.set_rv(rx); 
     56        KFu.set_yrv(ry); 
     57        KFu.set_rvc(ru); 
     58        shared_ptr<bilinfn> f=new bilinfn; f->set_parameters(A,B); 
     59        shared_ptr<bilinfn> h=new bilinfn; h->set_parameters(C,D); 
     60        KFu.set_parameters(f,h,Q,diag(R)); 
     61        KFu.prior()._mu()=mu0; 
     62        KFu.prior()._R()=ldmat(P0); 
     63        const epdf& KFuep = KFu.posterior(); 
     64        mat Xtu(dimx,Ndat); 
     65        Xtu.set_col( 0,KFuep.mean() ); 
    6066 
    6167    //Chol 
     
    99105    for ( int t = 1; t < Ndat; t++ ) { 
    100106        dt = Dt.get_col ( t ); 
    101         KF.bayes ( dt.get ( 0, C.rows() - 1 ), dt.get ( C.rows(), dt.length() - 1 ) ); 
    102         Xt.set_col ( t, KFep.mean() ); 
     107        KFu.bayes ( dt.get ( 0, C.rows() - 1 ), dt.get ( C.rows(), dt.length() - 1 ) ); 
     108        Xtu.set_col ( t, KFuep.mean() ); 
    103109    } 
    104110    exec_times ( 0 ) = tt.toc(); 
     
    122128 
    123129    it_file fou ( "kalman_stress_res.it" ); 
    124     fou << Name ( "xth" ) << Xt; 
     130    fou << Name ( "xthu" ) << Xtu; 
    125131    fou << Name ( "xth2" ) << Xt2; 
    126132    fou << Name ( "xthE" ) << XtE; 
  • library/tests/stresssuite/kalman_stress.m

    r721 r1158  
    6060        Mu(1:2,t)=mu; 
    6161 
    62         [Oxt,OPt,ll(t)] = Kalman(Oxt,y(:,t),A,C,Q,R,OPt); 
     62%       [Oxt,OPt,ll(t)] = Kalman(Oxt,y(:,t),A,C,Q,R,OPt); 
    6363%       [oxt,oPt,oll(t)] = KalmanSq(oxt,y(:,t),A,C,sQ,sR,oPt); 
    64         MuK(1:2,t) = Oxt; 
     64%       MuK(1:2,t) = Oxt; 
    6565%       MuS(1:2,t) = oxt; 
    6666end 
     
    6868%keyboard 
    6969 
    70 !cd ../;./tests/testKF 
    71 itload('testKF_res.it'); 
     70!./stresssuite kalman_stress 
     71itload('kalman_stress_res.it'); 
    7272 
    7373hold off 
     
    7777plot(xth2','+'); 
    7878plot(xthE','o'); 
    79 plot([zeros(size(xth,1),1) MuK]','d'); % shift the predictions 
     79%plot([zeros(size(xth,1),1) MuK]','d'); % shift the predictions 
    8080 
    8181exec_times