easykf-2.04
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
ekf.h
Go to the documentation of this file.
1 /* ekf.h
2  *
3  * Copyright (C) 2011-2014 Jeremy Fix
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #ifndef EKF_H
21 #define EKF_H
22 
23 #include "ekf_types.h"
24 #include <gsl/gsl_vector.h>
25 #include <gsl/gsl_matrix.h>
26 #include <gsl/gsl_blas.h>
27 
28 namespace ekf
29 {
30 
32  {
33 
34  // Matrices for the state
35  s.xk = gsl_vector_alloc(p.n);
36  gsl_vector_set_zero(s.xk);
37 
38  s.xkm = gsl_vector_alloc(p.n);
39  gsl_vector_set_zero(s.xkm);
40 
41  s.Pxk = gsl_matrix_alloc(p.n, p.n);
42  gsl_matrix_set_zero(s.Pxk);
43 
44  s.Fxk = gsl_matrix_alloc(p.n, p.n);
45  gsl_matrix_set_zero(s.Fxk);
46 
47  s.Rv = gsl_matrix_alloc(p.n, p.n);
48  gsl_matrix_set_zero(s.Rv);
49 
50  // Matrices for the observations
51  s.yk = gsl_vector_alloc(p.no);
52  gsl_vector_set_zero(s.yk);
53 
54  s.ino_yk = gsl_vector_alloc(p.no);
55  gsl_vector_set_zero(s.ino_yk);
56 
57  s.Hyk = gsl_matrix_alloc(p.no, p.n);
58  gsl_matrix_set_zero(s.Hyk);
59 
60  s.Rn = gsl_matrix_alloc(p.no, p.no);
61  gsl_matrix_set_zero(s.Rn);
62 
63  // Matrices for the kalman gain and the updates
64  s.Kk = gsl_matrix_alloc(p.n, p.no);
65  gsl_matrix_set_zero(s.Kk);
66 
67  // Temporary matrices
68  s.temp_n_n = gsl_matrix_alloc(p.n, p.n);
69  gsl_matrix_set_zero(s.temp_n_n);
70 
71  s.temp_n_1 = gsl_matrix_alloc(p.n, 1);
72  gsl_matrix_set_zero(s.temp_n_1);
73 
74  s.temp_no_no = gsl_matrix_alloc(p.no, p.no);
75  gsl_matrix_set_zero(s.temp_no_no);
76 
77  s.temp_n_no = gsl_matrix_alloc(p.n, p.no);
78  gsl_matrix_set_zero(s.temp_n_no);
79 
80  s.temp_2_n_n = gsl_matrix_alloc(p.n, p.n);
81  gsl_matrix_set_zero(s.temp_2_n_n);
82 
83  s.temp_no = gsl_vector_alloc(p.no);
84  gsl_vector_set_zero(s.temp_no);
85 
86  // Initialize the noises
87  //gsl_matrix_set_identity(s.Rv);
88  //gsl_matrix_scale(s.Rv, p.evolution_noise);
89  p.evolution_noise->init(p, s);
90  //printf("Evolution noise : max = %e , min = %e \n", gsl_matrix_max(s.Rv), gsl_matrix_min(s.Rv));
91 
92  gsl_matrix_set_identity(s.Rn);
93  gsl_matrix_scale(s.Rn, p.observation_noise);
94 
95  // Initialize the covariance of the parameters
96  gsl_matrix_set_identity(s.Pxk);
97  gsl_matrix_scale(s.Pxk, p.prior_pk);
98 
99  }
100 
102  {
103  gsl_vector_free(s.xk);
104  gsl_vector_free(s.xkm);
105  gsl_matrix_free(s.Pxk);
106  gsl_matrix_free(s.Fxk);
107  gsl_matrix_free(s.Rv);
108 
109  gsl_vector_free(s.yk);
110  gsl_vector_free(s.ino_yk);
111  gsl_matrix_free(s.Hyk);
112  gsl_matrix_free(s.Rn);
113 
114  gsl_matrix_free(s.Kk);
115 
116  gsl_matrix_free(s.temp_n_n);
117  gsl_matrix_free(s.temp_n_1);
118  gsl_matrix_free(s.temp_no_no);
119  gsl_matrix_free(s.temp_n_no);
120  gsl_matrix_free(s.temp_2_n_n);
121  gsl_vector_free(s.temp_no);
122  }
123 
124  template <typename FunctProcess, typename JacobianProcess, typename FunctObservation, typename JacobianObservation>
125  void ekf_iterate(ekf_param &p, ekf_state &s, FunctProcess f, JacobianProcess df, FunctObservation h, JacobianObservation dh, gsl_vector* yk)
126  {
127  /****************************/
128  /***** Prediction step *****/
129  /****************************/
130 
131  // Compute the Jacobian of the evolution
132  // Eq. 2.34
133  df(s.params, s.xk,s.Fxk);
134 
135  // Compute the predicted state mean and covariance
136  // Eq. 2.36
137  // s.xk will now hold the predicted state !
138  f(s.params, s.xk, s.xkm);
139 
140  // Eq. 2.37
141  // s.Pxk will now hold Pxk^-
142  gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, s.Pxk, s.Fxk, 0.0, s.temp_n_n);
143  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, s.Fxk, s.temp_n_n, 0.0, s.Pxk);
144  gsl_matrix_add(s.Pxk, s.Rv);
145 
146  /****************************/
147  /***** Correction step *****/
148  /****************************/
149 
150  // Compute the Jacobian of the observation model
151  // Eq. 2.38
152  dh(s.params, s.xkm, s.Hyk);
153 
155  {
156  // Update the estimates
157  // Eq 2.40
158  // 1 - Compute H.P^-.H^T + Rn
159  gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, s.Pxk, s.Hyk, 0.0, s.temp_n_no);
160  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, s.Hyk, s.temp_n_no, 0.0, s.temp_no_no);
161  gsl_matrix_add(s.temp_no_no, s.Rn);
162  // 2 - Compute its inverse
163  gsl_linalg_cholesky_decomp(s.temp_no_no);
164  gsl_linalg_cholesky_invert(s.temp_no_no);
165 
166  // 3 - Compute P^-.H ^T.( H P H^T + R)^-1
167  gsl_blas_dgemm(CblasTrans, CblasNoTrans, 1.0, s.Hyk, s.temp_no_no, 0.0, s.temp_n_no);
168  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, s.Pxk, s.temp_n_no, 0.0, s.Kk);
169  }
170  else
171  {
172  // We can make some simplifications when computing H P H^T = H P H
173  // and also when computing P . H . (H P H^T + R) ^-1
174 
175  // Update the estimates
176  // Eq 2.40
177  // 1 - Compute H.P^-.H^T + Rn
178  for(int i = 0 ; i < p.no ; ++i)
179  {
180  for(int j = 0 ; j < p.no ; ++j)
181  {
182  gsl_matrix_set(s.temp_no_no, i, j, gsl_matrix_get(s.Hyk, i, i) * gsl_matrix_get(s.Hyk, j, j) * gsl_matrix_get(s.Pxk, i, j) + gsl_matrix_get(s.Rn, i, j));
183  }
184  }
185  // Compute its inverse : U = (H P H^T + R) ^-1
186  gsl_linalg_cholesky_decomp(s.temp_no_no);
187  gsl_linalg_cholesky_invert(s.temp_no_no);
188 
189  // 3 - Compute P^- H^T . U
190 
191  // Compute H^T . U
192  for(int i = 0 ; i < p.no; ++i)
193  for(int j = 0 ; j < p.no ; ++j)
194  gsl_matrix_set(s.temp_n_no, i, j, gsl_matrix_get(s.Hyk, i,i) * gsl_matrix_get(s.temp_no_no, i, j));
195  for(int i = p.no ; i < p.n; ++i)
196  for(int j = 0 ; j < p.no ; ++j)
197  gsl_matrix_set(s.temp_n_no, i, j, 0.0);
198  // Compute P^- . (H^T . U)
199  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, s.Pxk, s.temp_n_no, 0.0, s.Kk);
200 
201  }
202  // Update the current estimate
203  // Eq 2.41
204  // 1 - We need the observations
205  h(s.params, s.xkm, s.yk);
206  gsl_vector_memcpy(s.ino_yk, yk);
207  gsl_vector_sub(s.ino_yk, s.yk);
208  gsl_vector_memcpy(s.xk, s.xkm);
209  gsl_blas_dgemv(CblasNoTrans, 1.0, s.Kk, s.ino_yk, 1.0,s.xk);
210 
211  // Update the variance/covariance matrix
212  // Compute -Kk * Hk
214  {
215  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, -1.0, s.Kk, s.Hyk, 0.0, s.temp_n_n);
216 
217  // Add identity : I - Kk * Hk
218  for(int i = 0 ; i < p.n ; ++i)
219  gsl_matrix_set(s.temp_n_n, i, i,gsl_matrix_get(s.temp_n_n,i,i) + 1.0);
220  }
221  else
222  {
223  // We can make some simplifications when H is diagonal
224  for(int i = 0 ; i < p.n ; ++i)
225  {
226  for(int j = 0 ; j < p.no ; ++j)
227  {
228  gsl_matrix_set(s.temp_n_n, i, j, (i==j?1.0:0.0) - gsl_matrix_get(s.Kk, i,j) * gsl_matrix_get(s.Hyk, j,j) );
229  }
230  for(int j = p.no ; j < p.n ; ++j)
231  {
232  gsl_matrix_set(s.temp_n_n, i, j, (i == j ? 1.0 : 0.0));
233  }
234  }
235  }
236 
237  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, s.temp_n_n, s.Pxk, 0.0, s.temp_2_n_n);
238  gsl_matrix_memcpy(s.Pxk, s.temp_2_n_n);
239 
240  /***********************************/
241  /***** Evolution noise update *****/
242  /***********************************/
243 
245  }
246 }
247 
248 #endif // EKF_H
double observation_noise
Covariance of the observation noise.
Definition: ekf_types.h:50
virtual void updateEvolutionNoise(ekf_param &p, ekf_state &s)=0
int no
Dimension of the output.
Definition: ekf_types.h:65
gsl_matrix * Rv
Variance covariance of the evolution noise.
Definition: ekf_types.h:99
gsl_vector * ino_yk
Current innovations.
Definition: ekf_types.h:109
gsl_matrix * temp_n_no
Definition: ekf_types.h:132
void ekf_free(ekf_param &p, ekf_state &s)
Definition: ekf.h:101
gsl_vector * yk
Current observation.
Definition: ekf_types.h:104
Structure holding the parameters of the statistical linearization.
Definition: ekf_types.h:39
Definition: ekf_types.h:74
gsl_matrix * Rn
Variance covariance of the observation noise.
Definition: ekf_types.h:119
gsl_vector * xkm
Predicted state.
Definition: ekf_types.h:84
gsl_vector * xk
Current estimate of the state.
Definition: ekf_types.h:79
EvolutionNoise * evolution_noise
Evolution noise type.
Definition: ekf_types.h:45
gsl_matrix * temp_n_n
Temporary matrices.
Definition: ekf_types.h:129
gsl_matrix * Hyk
Jacobian of the observation function.
Definition: ekf_types.h:114
gsl_matrix * Kk
Kalman gain.
Definition: ekf_types.h:124
void ekf_init(ekf_param &p, ekf_state &s)
Definition: ekf.h:31
gsl_vector * temp_no
Definition: ekf_types.h:134
void ekf_iterate(ekf_param &p, ekf_state &s, FunctProcess f, JacobianProcess df, FunctObservation h, JacobianObservation dh, gsl_vector *yk)
Definition: ekf.h:125
gsl_matrix * temp_no_no
Definition: ekf_types.h:131
gsl_matrix * temp_n_1
Definition: ekf_types.h:130
gsl_matrix * Fxk
Jacobian of the evolution function.
Definition: ekf_types.h:94
double prior_pk
Prior estimate of the covariance matrix.
Definition: ekf_types.h:55
void init(ekf_param &p, ekf_state &s)
Definition: ekf_types.h:154
gsl_matrix * Pxk
Variance-Covariance of the state.
Definition: ekf_types.h:89
gsl_matrix * temp_2_n_n
Definition: ekf_types.h:133
int n
Number of parameters to estimate.
Definition: ekf_types.h:60
bool observation_gradient_is_diagonal
Is the observation gradient diagonal ? In that case, simplifications can be introduced.
Definition: ekf_types.h:70
gsl_vector * params
Optional parameters (this must be allocated and initialized from the user side!
Definition: ekf_types.h:139