root/bdm/estim/libKF.cpp @ 67

Revision 67, 6.5 kB (checked in by smidl, 16 years ago)

opavy

Line 
1#include <itpp/itbase.h>
2#include "libKF.h"
3
4using namespace itpp;
5
6using std::endl;
7
8KalmanFull::KalmanFull ( mat A0, mat B0, mat C0, mat D0, mat R0, mat Q0, mat P0, vec mu0 ) {
9        dimx = A0.rows();
10        dimu = B0.cols();
11        dimy = C0.rows();
12
13        it_assert_debug ( A0.cols() ==dimx, "KalmanFull: A is not square" );
14        it_assert_debug ( B0.rows() ==dimx, "KalmanFull: B is not compatible" );
15        it_assert_debug ( C0.cols() ==dimx, "KalmanFull: C is not square" );
16        it_assert_debug ( ( D0.rows() ==dimy ) || ( D0.cols() ==dimu ), "KalmanFull: D is not compatible" );
17        it_assert_debug ( ( R0.cols() ==dimy ) || ( R0.rows() ==dimy ), "KalmanFull: R is not compatible" );
18        it_assert_debug ( ( Q0.cols() ==dimx ) || ( Q0.rows() ==dimx ), "KalmanFull: Q is not compatible" );
19
20        A = A0;
21        B = B0;
22        C = C0;
23        D = D0;
24        R = R0;
25        Q = Q0;
26        mu = mu0;
27        P = P0;
28       
29        ll = 0.0;
30        evalll=true;
31}
32
33void KalmanFull::bayes ( const vec &dt ) {
34        it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
35
36        vec u = dt.get ( dimy,dimy+dimu-1 );
37        vec y = dt.get ( 0,dimy-1 );
38        //Time update
39        mu = A*mu + B*u;
40        P  = A*P*A.transpose() + Q;
41
42        //Data update
43        _Ry = C*P*C.transpose() + R;
44        _iRy = inv ( _Ry );
45        _K = P*C.transpose() *_iRy;
46        P -= _K*C*P; // P = P -KCP;
47        mu += _K* ( y-C*mu-D*u );
48
49        if ( evalll ) {
50                //from enorm
51                vec x=y-C*mu-D*u;
52                ll = -0.5* ( R.cols() * 1.83787706640935 +log ( det ( _Ry ) ) +x* ( _iRy*x ) );
53        }
54};
55
56std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf ) {
57        os << "mu:" << kf.mu << endl << "P:" << kf.P <<endl;
58        return os;
59}
60
61
62
63 /////////////////////////////// EKFS
64EKFfull::EKFfull ( RV rvx0, RV rvy0, RV rvu0 ) : BM ( rvx0 ),E(rvx0) {};
65
66void EKFfull::set_parameters ( diffbifn* pfxu0,  diffbifn* phxu0,const mat Q0,const mat R0 ) {
67        pfxu = pfxu0;
68        phxu = phxu0;
69
70        dimx = rv.count();
71        dimy = phxu0->_dimy();
72        dimu = phxu0->_dimu();
73
74        A.set_size(dimx,dimx);
75        C.set_size(dimy,dimx);
76        //initialize matrices A C, later, these will be only updated!
77        pfxu->dfdx_cond ( mu,zeros ( dimu ),A,true );
78        B.clear();
79        phxu->dfdx_cond ( mu,zeros ( dimu ),C,true );
80        D.clear();
81
82        R = R0;
83        Q = Q0;
84}
85
86void EKFfull::bayes ( const vec &dt ) {
87        it_assert_debug ( dt.length() == ( dimy+dimu ),"KalmanFull::bayes wrong size of dt" );
88
89        vec u = dt.get ( dimy,dimy+dimu-1 );
90        vec y = dt.get ( 0,dimy-1 );
91       
92        pfxu->dfdx_cond ( mu,zeros ( dimu ),A,true );
93        phxu->dfdx_cond ( mu,zeros ( dimu ),C,true );
94
95        //Time update
96        mu = pfxu->eval(mu,u);// A*mu + B*u;
97        P  = A*P*A.transpose() + Q;
98
99        //Data update
100        _Ry = C*P*C.transpose() + R;
101        _iRy = inv ( _Ry );
102        _K = P*C.transpose() *_iRy;
103        P -= _K*C*P; // P = P -KCP;
104        vec yp = phxu->eval(mu,u);
105        mu += _K* ( y-yp );
106
107        E.set_mu(mu);
108
109        if ( BM::evalll ) {
110                //from enorm
111                vec x=y-yp;
112                BM::ll = -0.5* ( R.cols() * 1.83787706640935 +log ( det ( _Ry ) ) +x* ( _iRy*x ) );
113        }
114};
115
116
117
118void KalmanCh::set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const chmat &R0,const chmat &Q0 ) {
119
120        ( ( Kalman<chmat>* ) this )->set_parameters ( A0,B0,C0,D0,R0,Q0 );
121        // Cholesky special!
122        preA.clear();
123        preA.set_submatrix ( 0,0,R._Ch() );
124        preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() );
125}
126
127
128void KalmanCh::bayes ( const vec &dt ) {
129
130        vec u = dt.get ( dimy,dimy+dimu-1 );
131        vec y = dt.get ( 0,dimy-1 );
132
133        //TODO get rid of Q in qr()!
134//      mat Q;
135
136        //R and Q are already set in set_parameters()
137        preA.set_submatrix ( dimy,0, ( _P->_Ch() ) *C.T() );
138        //Fixme can be more efficient if .T() is not used
139        preA.set_submatrix ( dimy,dimy, ( _P->_Ch() ) *A.T() );
140
141//      if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" );
142        if ( !qr ( preA,postA ) ) it_warning ( "QR in kalman unstable!" );
143
144        ( _Ry->_Ch() ) =postA ( 0,dimy-1, 0,dimy-1 );
145        _K = ( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T();
146        ( _P->_Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 );
147        _Ry->inv ( *_iRy );
148        fy._cached ( true );
149        *_mu = A* ( *_mu ) + B*u + ( _K ) * ( _iRy->_Ch() ).T() * ( y-C* ( *_mu )-D*u );
150
151        /*      cout << "P:" <<_P->to_mat() <<endl;
152                cout << "Ry:" <<_Ry->to_mat() <<endl;
153                cout << "iRy:" <<_iRy->to_mat() <<endl;*/
154        if ( evalll==true ) { //likelihood of observation y
155                ll=fy.evalpdflog ( y );
156        }
157}
158
159
160EKFCh::EKFCh ( RV rvx0, RV rvy0, RV rvu0 ) : KalmanCh ( rvx0,rvy0,rvu0 ) {}
161
162void EKFCh::set_parameters ( diffbifn* pfxu0,  diffbifn* phxu0,const chmat Q0,const chmat R0 ) {
163        pfxu = pfxu0;
164        phxu = phxu0;
165
166        //initialize matrices A C, later, these will be only updated!
167        pfxu->dfdx_cond ( *_mu,zeros ( dimu ),A,true );
168//      pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true );
169        B.clear();
170        phxu->dfdx_cond ( *_mu,zeros ( dimu ),C,true );
171//      phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true );
172        D.clear();
173
174        R = R0;
175        Q = Q0;
176
177        // Cholesky special!
178        preA.clear();
179        preA.set_submatrix ( 0,0,R._Ch() );
180        preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() );
181}
182
183
184void EKFCh::bayes ( const vec &dt ) {
185
186        vec u = dt.get ( dimy,dimy+dimu-1 );
187        vec y = dt.get ( 0,dimy-1 );
188
189        pfxu->dfdx_cond ( *_mu,u,A,false ); //update A by a derivative of fx
190        phxu->dfdx_cond ( *_mu,u,C,false ); //update A by a derivative of fx
191
192        //R and Q are already set in set_parameters()
193        preA.set_submatrix ( dimy,0, ( _P->_Ch() ) *C.T() );
194        //Fixme can be more efficient if .T() is not used
195        preA.set_submatrix ( dimy,dimy, ( _P->_Ch() ) *A.T() );
196
197//      mat Sttm = _P->to_mat();
198
199//      if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" );
200        if ( !qr ( preA,postA ) ) it_warning ( "QR in kalman unstable!" );
201
202        ( _Ry->_Ch() ) =postA ( 0,dimy-1, 0,dimy-1 );
203        _K = inv(A)*( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T();
204        ( _P->_Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 );
205        _Ry->inv ( *_iRy );
206        fy._cached ( true );
207       
208//      mat iRY = inv(_Ry->to_mat());
209//      mat Stt = Sttm - Sttm * C.T() * iRY * C * Sttm;
210//      mat _K2 = Stt*C.T()*inv(R.to_mat());
211
212        // prediction
213        *_mu = pfxu->eval ( *_mu ,u );
214
215        *_yp = phxu->eval ( *_mu,u );
216       
217/*      vec mu2 = *_mu + ( _K2 ) * ( y-*_yp );*/
218       
219        //correction //= initial value is already prediction!
220        *_mu += ( _K ) * ( _iRy->_Ch() ).T() * ( y-*_yp );
221
222/*      _K = (_P->to_mat())*C.transpose() * ( _iRy->to_mat() );
223        *_mu = pfxu->eval ( *_mu ,u ) + ( _K )* ( y-*_yp );*/
224       
225        /*      cout << "P:" <<_P->to_mat() <<endl;
226                cout << "Ry:" <<_Ry->to_mat() <<endl;
227                cout << "iRy:" <<_iRy->to_mat() <<endl;*/
228
229        if ( evalll==true ) { //likelihood of observation y
230                ll=fy.evalpdflog ( y );
231        }
232}
233
234void KFcondQR::condition ( const vec &QR ) {
235        it_assert_debug ( QR.length() == ( rvc.count() ),"KFcondRQ: conditioning by incompatible vector" );
236
237        Q.setD ( QR ( 0, dimx-1 ) );
238        R.setD ( QR ( dimx, -1 ) );
239};
240
241void KFcondR::condition ( const vec &R0 ) {
242        it_assert_debug ( R0.length() == ( rvc.count() ),"KFcondR: conditioning by incompatible vector" );
243
244        R.setD ( R0 );
245};
246
Note: See TracBrowser for help on using the browser.