1 | #include <itpp/itbase.h> |
---|
2 | #include "libKF.h" |
---|
3 | |
---|
4 | using namespace itpp; |
---|
5 | |
---|
6 | using std::endl; |
---|
7 | |
---|
8 | KalmanFull::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 | |
---|
33 | void 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 | |
---|
56 | std::ostream &operator<< ( std::ostream &os, const KalmanFull &kf ) { |
---|
57 | os << "mu:" << kf.mu << endl << "P:" << kf.P <<endl; |
---|
58 | return os; |
---|
59 | } |
---|
60 | |
---|
61 | void KalmanCh::set_parameters ( const mat &A0,const mat &B0,const mat &C0,const mat &D0,const chmat &R0,const chmat &Q0 ) { |
---|
62 | |
---|
63 | ( ( Kalman<chmat>* ) this )->set_parameters ( A0,B0,C0,D0,R0,Q0 ); |
---|
64 | // Cholesky special! |
---|
65 | preA.clear(); |
---|
66 | preA.set_submatrix ( 0,0,R._Ch() ); |
---|
67 | preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() ); |
---|
68 | } |
---|
69 | |
---|
70 | |
---|
71 | void KalmanCh::bayes ( const vec &dt ) { |
---|
72 | |
---|
73 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
74 | vec y = dt.get ( 0,dimy-1 ); |
---|
75 | |
---|
76 | //TODO get rid of Q in qr()! |
---|
77 | // mat Q; |
---|
78 | |
---|
79 | //R and Q are already set in set_parameters() |
---|
80 | preA.set_submatrix ( dimy,0, ( _P->_Ch() ) *C.T() ); |
---|
81 | //Fixme can be more efficient if .T() is not used |
---|
82 | preA.set_submatrix ( dimy,dimy, ( _P->_Ch() ) *A.T() ); |
---|
83 | |
---|
84 | // if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
85 | if ( !qr ( preA,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
86 | |
---|
87 | ( _Ry->_Ch() ) =postA ( 0,dimy-1, 0,dimy-1 ); |
---|
88 | _K = ( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T(); |
---|
89 | ( _P->_Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 ); |
---|
90 | _Ry->inv ( *_iRy ); |
---|
91 | fy._cached ( true ); |
---|
92 | *_mu = A* ( *_mu ) + B*u + ( _K ) * ( _iRy->_Ch() ).T() * ( y-C* ( *_mu )-D*u ); |
---|
93 | |
---|
94 | /* cout << "P:" <<_P->to_mat() <<endl; |
---|
95 | cout << "Ry:" <<_Ry->to_mat() <<endl; |
---|
96 | cout << "iRy:" <<_iRy->to_mat() <<endl;*/ |
---|
97 | if ( evalll==true ) { //likelihood of observation y |
---|
98 | ll=fy.evalpdflog ( y ); |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | |
---|
103 | EKFCh::EKFCh ( RV rvx0, RV rvy0, RV rvu0 ) : KalmanCh ( rvx0,rvy0,rvu0 ) {} |
---|
104 | |
---|
105 | void EKFCh::set_parameters ( diffbifn* pfxu0, diffbifn* phxu0,const chmat Q0,const chmat R0 ) { |
---|
106 | pfxu = pfxu0; |
---|
107 | phxu = phxu0; |
---|
108 | |
---|
109 | //initialize matrices A C, later, these will be only updated! |
---|
110 | pfxu->dfdx_cond ( *_mu,zeros ( dimu ),A,true ); |
---|
111 | // pfxu->dfdu_cond ( *_mu,zeros ( dimu ),B,true ); |
---|
112 | B.clear(); |
---|
113 | phxu->dfdx_cond ( *_mu,zeros ( dimu ),C,true ); |
---|
114 | // phxu->dfdu_cond ( *_mu,zeros ( dimu ),D,true ); |
---|
115 | D.clear(); |
---|
116 | |
---|
117 | R = R0; |
---|
118 | Q = Q0; |
---|
119 | |
---|
120 | // Cholesky special! |
---|
121 | preA.clear(); |
---|
122 | preA.set_submatrix ( 0,0,R._Ch() ); |
---|
123 | preA.set_submatrix ( dimy+dimx,dimy,Q._Ch() ); |
---|
124 | } |
---|
125 | |
---|
126 | |
---|
127 | void EKFCh::bayes ( const vec &dt ) { |
---|
128 | |
---|
129 | vec u = dt.get ( dimy,dimy+dimu-1 ); |
---|
130 | vec y = dt.get ( 0,dimy-1 ); |
---|
131 | |
---|
132 | pfxu->dfdx_cond ( *_mu,u,A,false ); //update A by a derivative of fx |
---|
133 | phxu->dfdx_cond ( *_mu,u,C,false ); //update A by a derivative of fx |
---|
134 | |
---|
135 | //R and Q are already set in set_parameters() |
---|
136 | preA.set_submatrix ( dimy,0, ( _P->_Ch() ) *C.T() ); |
---|
137 | //Fixme can be more efficient if .T() is not used |
---|
138 | preA.set_submatrix ( dimy,dimy, ( _P->_Ch() ) *A.T() ); |
---|
139 | |
---|
140 | // if ( !qr ( preA,Q,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
141 | if ( !qr ( preA,postA ) ) it_warning ( "QR in kalman unstable!" ); |
---|
142 | |
---|
143 | ( _Ry->_Ch() ) =postA ( 0,dimy-1, 0,dimy-1 ); |
---|
144 | _K = ( postA ( 0,dimy-1 ,dimy,dimy+dimx-1 ) ).T(); |
---|
145 | ( _P->_Ch() ) = postA ( dimy,dimy+dimx-1,dimy,dimy+dimx-1 ); |
---|
146 | _Ry->inv ( *_iRy ); |
---|
147 | fy._cached ( true ); |
---|
148 | *_yp = phxu->eval ( *_mu,u ); |
---|
149 | |
---|
150 | *_mu = pfxu->eval ( *_mu ,u ) + ( _K ) * ( _iRy->_Ch() ).T() * ( y-*_yp ); |
---|
151 | /* _K = (_P->to_mat())*C.transpose() * ( _iRy->to_mat() ); |
---|
152 | *_mu = pfxu->eval ( *_mu ,u ) + ( _K )* ( y-*_yp );*/ |
---|
153 | |
---|
154 | /* cout << "P:" <<_P->to_mat() <<endl; |
---|
155 | cout << "Ry:" <<_Ry->to_mat() <<endl; |
---|
156 | cout << "iRy:" <<_iRy->to_mat() <<endl;*/ |
---|
157 | |
---|
158 | if ( evalll==true ) { //likelihood of observation y |
---|
159 | ll=fy.evalpdflog ( y ); |
---|
160 | } |
---|
161 | } |
---|
162 | |
---|
163 | void KFcondQR::condition ( const vec &QR ) { |
---|
164 | it_assert_debug ( QR.length() == ( rvc.count() ),"KFcondRQ: conditioning by incompatible vector" ); |
---|
165 | |
---|
166 | Q.setD ( QR ( 0, dimx-1 ) ); |
---|
167 | R.setD ( QR ( dimx, -1 ) ); |
---|
168 | }; |
---|
169 | |
---|
170 | void KFcondR::condition ( const vec &R0 ) { |
---|
171 | it_assert_debug ( R0.length() == ( rvc.count() ),"KFcondR: conditioning by incompatible vector" ); |
---|
172 | |
---|
173 | R.setD ( R0 ); |
---|
174 | }; |
---|