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 | |
---|
62 | |
---|
63 | /////////////////////////////// EKFS |
---|
64 | EKFfull::EKFfull ( RV rvx0, RV rvy0, RV rvu0 ) : BM ( rvx0 ),E(rvx0) {}; |
---|
65 | |
---|
66 | void 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 | |
---|
86 | void 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 | |
---|
118 | void 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 | |
---|
128 | void 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 | |
---|
160 | EKFCh::EKFCh ( RV rvx0, RV rvy0, RV rvu0 ) : KalmanCh ( rvx0,rvy0,rvu0 ) {} |
---|
161 | |
---|
162 | void 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 | |
---|
184 | void 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 | |
---|
234 | void 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 | |
---|
241 | void 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 | |
---|