easykf-2.04
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
ukf_parameter_ndim.h
Go to the documentation of this file.
1 /* ukf_parameter_ndim.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 UKF_PARAMETER_NDIM_H
21 #define UKF_PARAMETER_NDIM_H
22 
23 #include <gsl/gsl_linalg.h> // For the Cholesky decomposition
24 #include <gsl/gsl_math.h>
25 #include <gsl/gsl_blas.h>
26 
27 #include "ukf_types.h"
28 
29 namespace ukf
30 {
31  namespace parameter
32  {
33 
38  inline void ukf_init(ukf_param &p, ukf_state &s)
39  {
40  // Init the lambda
41  p.lambda = p.alpha * p.alpha * (p.n + p.kpa) - p.n;
42  p.gamma = sqrt(p.n + p.lambda);
43  p.nbSamples = 2 * p.n + 1;
44 
45  // Init the matrices used to iterate
46  s.Kk = gsl_matrix_alloc(p.n,p.no); // Kalman gain
47  gsl_matrix_set_zero(s.Kk);
48 
49  s.Kk_T = gsl_matrix_alloc(p.no,p.n);
50  gsl_matrix_set_zero(s.Kk_T);
51 
52  s.Pwdk = gsl_matrix_alloc(p.n,p.no);
53  gsl_matrix_set_zero(s.Pwdk);
54 
55  // Whatever the type of evolution noise, its covariance is set to evolution_noise
56  s.Prrk = gsl_matrix_alloc(p.n,p.n);
57  p.evolution_noise->init(p,s);
58 
59  // Whatever the type of observation noise, its covariance is set to observation_noise
60  s.Peek = gsl_matrix_alloc(p.no,p.no);
61  gsl_matrix_set_identity(s.Peek);
62  gsl_matrix_scale(s.Peek, p.observation_noise);
63 
64  s.Pddk = gsl_matrix_alloc(p.no, p.no); // Covariance of the output
65  gsl_matrix_set_zero(s.Pddk);
66 
67  s.w = gsl_vector_alloc(p.n); // Parameter vector
68  gsl_vector_set_zero(s.w);
69 
70  s.wk = gsl_vector_alloc(p.n); // Vector holding one sigma point
71  gsl_vector_set_zero(s.wk);
72 
73  s.Pk = gsl_matrix_alloc(p.n,p.n); // Covariance matrix
74  gsl_matrix_set_identity(s.Pk);
75  gsl_matrix_scale(s.Pk,p.prior_pi);
76 
77  s.Sk = gsl_matrix_alloc(p.n,p.n); // Matrix holding the cholesky decomposition of Pk
78  // Initialize Sk to the cholesky decomposition of Pk
79  gsl_matrix_memcpy(s.Sk, s.Pk);
80  gsl_linalg_cholesky_decomp(s.Sk);
81  // Set all the elements of Lpi strictly above the diagonal to zero
82  for(int k = 0 ; k < p.n ; k++)
83  for(int j = 0 ; j < k ; j++)
84  gsl_matrix_set(s.Sk,j,k,0.0);
85 
86  s.cSk = gsl_vector_alloc(p.n); // Vector holding one column of Lpi
87  gsl_vector_set_zero(s.cSk);
88 
89  s.wm = gsl_vector_alloc(p.nbSamples); // Weights used to compute the mean of the sigma points images
90  s.wc = gsl_vector_alloc(p.nbSamples); // Weights used to update the covariance matrices
91 
92  // Set the weights
93  gsl_vector_set(s.wm, 0, p.lambda / (p.n + p.lambda));
94  gsl_vector_set(s.wc, 0, p.lambda / (p.n + p.lambda) + (1.0 - p.alpha*p.alpha + p.beta));
95  for(int j = 1 ; j < p.nbSamples; j ++)
96  {
97  gsl_vector_set(s.wm, j, 1.0 / (2.0 * (p.n + p.lambda)));
98  gsl_vector_set(s.wc, j, 1.0 / (2.0 * (p.n + p.lambda)));
99  }
100 
101  s.dk = gsl_matrix_alloc(p.no, p.nbSamples); // Holds the image of the sigma points
102  gsl_matrix_set_zero(s.dk);
103 
104  s.ino_dk = gsl_vector_alloc(p.no); // Holds the inovation
105  gsl_vector_set_zero(s.ino_dk);
106 
107  s.d_mean = gsl_vector_alloc(p.no); // Holds the mean of the sigma points images
108  gsl_vector_set_zero(s.d_mean);
109 
110  s.sigmaPoints = gsl_matrix_alloc(p.n,p.nbSamples); // Holds the sigma points in the columns
111  gsl_matrix_set_zero(s.sigmaPoints);
112 
113  // Temporary vectors/matrices
114  s.vec_temp_n = gsl_vector_alloc(p.n);
115  s.vec_temp_output = gsl_vector_alloc(p.no);
116 
117  s.mat_temp_n_1 = gsl_matrix_alloc(p.n,1);
118  s.mat_temp_n_output = gsl_matrix_alloc(p.n, p.no);
119  s.mat_temp_output_n = gsl_matrix_alloc(p.no, p.n);
120  s.mat_temp_1_output = gsl_matrix_alloc(1,p.no);
121  s.mat_temp_output_1 = gsl_matrix_alloc(p.no, 1);
122  s.mat_temp_output_output = gsl_matrix_alloc(p.no, p.no);
123  s.mat_temp_n_n = gsl_matrix_alloc(p.n, p.n);
124  }
125 
130  inline void ukf_free(ukf_param &p, ukf_state &s)
131  {
132  gsl_matrix_free(s.Kk);
133  gsl_matrix_free(s.Kk_T);
134  gsl_matrix_free(s.Pwdk);
135  gsl_matrix_free(s.Pddk);
136  gsl_matrix_free(s.Peek);
137  gsl_matrix_free(s.Prrk);
138 
139  gsl_vector_free(s.w);
140  gsl_vector_free(s.wk);
141 
142  gsl_matrix_free(s.Pk);
143  gsl_matrix_free(s.Sk);
144  gsl_vector_free(s.cSk);
145 
146  gsl_vector_free(s.wm);
147  gsl_vector_free(s.wc);
148 
149  gsl_matrix_free(s.dk);
150  gsl_vector_free(s.ino_dk);
151  gsl_vector_free(s.d_mean);
152 
153  gsl_matrix_free(s.sigmaPoints);
154 
155  gsl_vector_free(s.vec_temp_n);
156  gsl_vector_free(s.vec_temp_output);
157 
158  gsl_matrix_free(s.mat_temp_n_1);
159  gsl_matrix_free(s.mat_temp_n_output);
160  gsl_matrix_free(s.mat_temp_output_n);
161  gsl_matrix_free(s.mat_temp_1_output);
162  gsl_matrix_free(s.mat_temp_output_1);
163 
164  gsl_matrix_free(s.mat_temp_output_output);
165  gsl_matrix_free(s.mat_temp_n_n);
166  }
167 
172  template <typename FunctObj>
173  inline void ukf_iterate(ukf_param &p, ukf_state &s, FunctObj g, gsl_vector * xk, gsl_vector* dk)
174  {
175 
176  // Here, we implement the UKF for parameter estimation in the vectorial case
177  // The notations follow p93 of the PhD thesis of Van Der Merwe, "Sigma-Point Kalman Filters for Probabilistic Inference in Dynamic State-Space Models"
178 
179  // ************************************************** //
180  // ************ Time update equations ************ //
181  // ************************************************** //
182  // Add the evolution noise to the parameter covariance Eq 3.137
183  gsl_matrix_add(s.Pk, s.Prrk);
184 
185  // ************************************************** //
186  // ************ Compute the sigma points ************ //
187  // ************************************************** //
188  // Equations 3.138
189  // w_k^j = w_(k-1) <-- this is here denoted s.w
190  // w_k^j = w_(k-1) + gamma Sk_j for 1 <= j <= n
191  // w_k^j = w_(k-1) - gamma Sk_j for n+1 <= j <= 2n
192 
193  // Perform a cholesky decomposition of Pk
194  gsl_matrix_memcpy(s.Sk, s.Pk);
195  gsl_linalg_cholesky_decomp(s.Sk);
196  // Set all the elements of Lpi strictly above the diagonal to zero
197  for(int k = 0 ; k < p.n ; ++k)
198  for(int j = 0 ; j < k ; ++j)
199  gsl_matrix_set(s.Sk,j,k,0.0);
200 
201  gsl_matrix_set_col(s.sigmaPoints,0, s.w);
202  for(int j = 1 ; j < p.n+1 ; ++j)
203  for(int i = 0 ; i < p.n ; ++i)
204  gsl_matrix_set(s.sigmaPoints, i, j, gsl_vector_get(s.w, i) + p.gamma * gsl_matrix_get(s.Sk,i,j-1));
205 
206  for(int j = p.n+1 ; j < p.nbSamples ; ++j)
207  for(int i = 0 ; i < p.n ; ++i)
208  gsl_matrix_set(s.sigmaPoints, i, j, gsl_vector_get(s.w, i) - p.gamma * gsl_matrix_get(s.Sk,i,j-(p.n+1)));
209 
210 
211 
212  /**************************************************/
213  /***** Compute the images of the sigma points *****/
214  /**************************************************/
215 
216  // Compute the images of the sigma points
217  // and the mean of the dk
218  gsl_vector_set_zero(s.d_mean);
219  for(int j = 0 ; j < p.nbSamples ; j++)
220  {
221  // Equation 3.129
222  gsl_matrix_get_col(s.wk, s.sigmaPoints,j);
223  g(s.wk,xk, s.vec_temp_output);
224  gsl_matrix_set_col(s.dk, j, s.vec_temp_output);
225 
226  // Equation 3.140
227  // Update the mean : y_mean = sum_[j=0..2n] w_j y_j
228  gsl_vector_scale(s.vec_temp_output, gsl_vector_get(s.wm,j));
229  gsl_vector_add(s.d_mean, s.vec_temp_output);
230  }
231 
232  /**************************************************/
233  /************** Update the statistics *************/
234  /**************************************************/
235 
236  gsl_matrix_set_zero(s.Pwdk);
237  gsl_matrix_memcpy(s.Pddk, s.Peek); // Add R^e_k to Pddk, Eq 3.142
238  for(int j = 0 ; j < p.nbSamples ; ++j)
239  {
240  // Update of Pwdk
241  // (wk - w)
242  gsl_matrix_get_col(s.wk, s.sigmaPoints,j);
243  gsl_vector_sub(s.wk, s.w);
244  gsl_matrix_set_col(s.mat_temp_n_1, 0, s.wk);
245 
246  // (dk - d_mean)
247  gsl_matrix_get_col(s.vec_temp_output, s.dk, j);
248  gsl_vector_sub(s.vec_temp_output, s.d_mean);
249  gsl_matrix_set_col(s.mat_temp_output_1, 0, s.vec_temp_output);
250 
251  // compute wc_j . (wk - w_mean) * (dk - d_mean)^T
252  gsl_blas_dgemm(CblasNoTrans, CblasTrans, gsl_vector_get(s.wc,j) , s.mat_temp_n_1, s.mat_temp_output_1, 0.0, s.mat_temp_n_output);
253 
254  // Equation 3.142
255  // And add it to Pwdk
256  gsl_matrix_add(s.Pwdk, s.mat_temp_n_output);
257 
258  // Equation 3.143
259  // Update of Pddk
260  gsl_matrix_get_col(s.vec_temp_output, s.dk, j);
261  gsl_vector_sub(s.vec_temp_output, s.d_mean);
262  gsl_matrix_set_col(s.mat_temp_output_1, 0, s.vec_temp_output);
263  gsl_blas_dgemm(CblasNoTrans, CblasTrans, gsl_vector_get(s.wc,j) , s.mat_temp_output_1, s.mat_temp_output_1, 0.0, s.mat_temp_output_output);
264 
265  gsl_matrix_add(s.Pddk, s.mat_temp_output_output);
266  }
267 
268  // ************************************************** //
269  // ******* Kalman gain and parameters update ******** //
270  // ************************************************** //
271 
272  //*** Ki = Pwdk Pddk^-1
273  // Compute the inverse of Pddk
274  gsl_matrix_memcpy(s.mat_temp_output_output, s.Pddk);
275  gsl_linalg_cholesky_decomp(s.mat_temp_output_output);
276  gsl_linalg_cholesky_invert(s.mat_temp_output_output);
277 
278  // Compute the product : Pwdk . Pddk^-1
279  // Equation 3.144
280  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0 , s.Pwdk, s.mat_temp_output_output, 0.0, s.Kk);
281 
282  // Update of the parameters
283  // wk = w_(k-1) + Kk * (dk - d_mean)
284  // Equation 3.145
285 
286  // Set the inovations
287  /*for(int i = 0 ; i < p.no; ++i)
288  s.ino_dk->data[i] = dk->data[i] - s.d_mean->data[i];
289  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0 , s.Kk, &gsl_matrix_view_array(s.ino_dk->data,p.no,1).matrix, 0.0, s.mat_temp_n_1);
290  gsl_matrix_get_col(s.vec_temp_n, s.mat_temp_n_1, 0);
291  gsl_vector_add(s.w, s.vec_temp_n);*/
292 
293  for(int i = 0 ; i < p.no; ++i)
294  s.ino_dk->data[i] = dk->data[i] - s.d_mean->data[i];
295  gsl_blas_dgemv(CblasNoTrans, 1.0, s.Kk, s.ino_dk, 1.0, s.w);
296 
297  // Update of the parameter covariance
298  // Pk = P_(k-1) - Kk Pddk Kk^T
299  // Equation 3.146
300  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0 , s.Kk, s.Pddk, 0.0, s.mat_temp_n_output);
301  gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, s.mat_temp_n_output , s.Kk, 0.0, s.mat_temp_n_n);
302  gsl_matrix_sub(s.Pk, s.mat_temp_n_n);
303 
304  // Update of the evolution noise
306  }
307 
312  template <typename FunctObj>
313  inline void ukf_evaluate(ukf_param &p, ukf_state &s, FunctObj g, gsl_vector * xk, gsl_vector * dk)
314  {
315  // ************************************************** //
316  // ************ Compute the sigma points ************ //
317  // ************************************************** //
318  // Equations 3.138
319  // w_k^j = w_(k-1) <-- this is here denoted s.w
320  // w_k^j = w_(k-1) + gamma Sk_j for 1 <= j <= n
321  // w_k^j = w_(k-1) - gamma Sk_j for n+1 <= j <= 2n
322 
323  // Perform a cholesky decomposition of Pk
324  gsl_matrix_memcpy(s.mat_temp_n_n, s.Pk);
325  gsl_linalg_cholesky_decomp(s.mat_temp_n_n);
326  // Set all the elements of Lpi strictly above the diagonal to zero
327  for(int k = 0 ; k < p.n ; ++k)
328  for(int j = 0 ; j < k ; ++j)
329  gsl_matrix_set(s.mat_temp_n_n,j,k,0.0);
330 
331  gsl_matrix_set_col(s.sigmaPoints,0, s.w);
332  for(int j = 1 ; j < p.n+1 ; ++j)
333  for(int i = 0 ; i < p.n ; ++i)
334  gsl_matrix_set(s.sigmaPoints, i, j, gsl_vector_get(s.w, i) + p.gamma * gsl_matrix_get(s.mat_temp_n_n,i,j-1));
335 
336  for(int j = p.n+1 ; j < p.nbSamples ; ++j)
337  for(int i = 0 ; i < p.n ; ++i)
338  gsl_matrix_set(s.sigmaPoints, i, j, gsl_vector_get(s.w, i) - p.gamma * gsl_matrix_get(s.mat_temp_n_n,i,j-(p.n+1)));
339 
340 
341  /**************************************************/
342  /***** Compute the images of the sigma points *****/
343  /**************************************************/
344 
345  // Compute the images of the sigma points
346  // and the mean of the dk
347  gsl_vector_set_zero(dk);
348  for(int j = 0 ; j < p.nbSamples ; j++)
349  {
350  // Equation 3.129
351  gsl_matrix_get_col(s.wk, s.sigmaPoints,j);
352  g(s.wk,xk, s.vec_temp_output);
353  gsl_matrix_set_col(s.dk, j, s.vec_temp_output);
354 
355  // Equation 3.140
356  // Update the mean : y_mean = sum_[j=0..2n] w_j y_j
357  gsl_vector_scale(s.vec_temp_output, gsl_vector_get(s.wm,j));
358  gsl_vector_add(dk, s.vec_temp_output);
359  }
360  }
361 
365  void getSigmaPoints(ukf_param &p, ukf_state &s, gsl_matrix * sigmaPoints)
366  {
367  //gsl_matrix * sigmaPoints = gsl_matrix_alloc(p.n, p.nbSamples);
368 
369  // ************************************************** //
370  // ************ Compute the sigma points ************ //
371  // ************************************************** //
372  // Equations 3.138
373  // w_k^j = w_(k-1) <-- this is here denoted s.w
374  // w_k^j = w_(k-1) + gamma Sk_j for 1 <= j <= n
375  // w_k^j = w_(k-1) - gamma Sk_j for n+1 <= j <= 2n
376 
377  // Perform a cholesky decomposition of Pk
378  gsl_matrix_memcpy(s.mat_temp_n_n, s.Pk);
379  gsl_linalg_cholesky_decomp(s.mat_temp_n_n);
380  // Set all the elements of Lpi strictly above the diagonal to zero
381  for(int k = 0 ; k < p.n ; ++k)
382  for(int j = 0 ; j < k ; ++j)
383  gsl_matrix_set(s.mat_temp_n_n,j,k,0.0);
384 
385  gsl_matrix_set_col(sigmaPoints,0, s.w);
386  for(int j = 1 ; j < p.n+1 ; ++j)
387  for(int i = 0 ; i < p.n ; ++i)
388  gsl_matrix_set(sigmaPoints, i, j, gsl_vector_get(s.w, i) + p.gamma * gsl_matrix_get(s.mat_temp_n_n,i,j-1));
389 
390  for(int j = p.n+1 ; j < p.nbSamples ; ++j)
391  for(int i = 0 ; i < p.n ; ++i)
392  gsl_matrix_set(sigmaPoints, i, j, gsl_vector_get(s.w, i) - p.gamma * gsl_matrix_get(s.mat_temp_n_n,i,j-(p.n+1)));
393 
394  }
395 
396  } // parameter
397 } // ukf
398 
399 #endif // SL_PARAMETER_NDIM_H
void ukf_iterate(ukf_param &p, ukf_state &s, FunctObj g, gsl_vector *xk, gsl_vector *dk)
Iteration for the statistical linearization.
Definition: ukf_parameter_ndim.h:173
EvolutionNoise * evolution_noise
Parameter used for the evolution noise.
Definition: ukf_types.h:96
gsl_vector * wc
Weights used to update the covariance matrices.
Definition: ukf_types.h:318
void ukf_free(ukf_param &p, ukf_state &s)
Free of memory allocation.
Definition: ukf_parameter_ndim.h:130
gsl_matrix * mat_temp_1_output
Temporary matrix of size .
Definition: ukf_types.h:368
gsl_matrix * Pddk
Covariance of the output, a matrix of size .
Definition: ukf_types.h:269
double kpa
, is a good choice. According to van der Merwe, its value is not critical
Definition: ukf_types.h:60
double observation_noise
Covariance of the observation noise.
Definition: ukf_types.h:101
gsl_matrix * mat_temp_output_1
Temporary matrix of size .
Definition: ukf_types.h:373
gsl_matrix * sigmaPoints
Matrix holding the sigma points in the columns, of size .
Definition: ukf_types.h:338
void getSigmaPoints(ukf_param &p, ukf_state &s, gsl_matrix *sigmaPoints)
Returns a set of sigma points.
Definition: ukf_parameter_ndim.h:365
gsl_matrix * Kk
Kalman gain, a matrix of size .
Definition: ukf_types.h:254
Structure holding the parameters of the Unscented Kalman Filter.
Definition: ukf_types.h:55
gsl_vector * ino_dk
Vector holding the inovation, of size ŝ
Definition: ukf_types.h:333
double beta
Non negative weights used to introduce knowledge about the higher order moments of the distribution...
Definition: ukf_types.h:70
gsl_matrix * mat_temp_output_output
Temporary matrix of size .
Definition: ukf_types.h:378
gsl_vector * d_mean
Vector holding the mean of the sigma points image, of size ŝ
Definition: ukf_types.h:328
gsl_vector * wk
Temporary vector holding one sigma point, of size .
Definition: ukf_types.h:289
int n
Number of parameters to estimate.
Definition: ukf_types.h:111
gsl_vector * w
Parameter vector, of size .
Definition: ukf_types.h:284
gsl_matrix * dk
Temporary matrix holding the image of the sigma points, of size .
Definition: ukf_types.h:323
void ukf_init(ukf_param &p, ukf_state &s)
Allocation of the vectors/matrices and initialization.
Definition: ukf_parameter_ndim.h:38
void init(ukf_param &p, ukf_state &s)
Definition: ukf_types.h:395
gsl_matrix * mat_temp_n_1
Temporary matrix of size .
Definition: ukf_types.h:353
gsl_matrix * Peek
Covariance of the observation noise, of size .
Definition: ukf_types.h:274
int no
Dimension of the output.
Definition: ukf_types.h:121
gsl_vector * cSk
Vector holding one column of Sk, of size .
Definition: ukf_types.h:304
double alpha
: "Size" of sigma-point distribution. Should be small if the function is strongly non-linear ...
Definition: ukf_types.h:65
gsl_matrix * Pk
Covariance matrix of the parameters, of size .
Definition: ukf_types.h:294
gsl_vector * vec_temp_n
Temporary vector of size .
Definition: ukf_types.h:343
gsl_matrix * mat_temp_n_output
Temporary matrix of size .
Definition: ukf_types.h:358
gsl_matrix * Pwdk
Covariance of : , of size .
Definition: ukf_types.h:264
double lambda
Definition: ukf_types.h:75
gsl_matrix * Prrk
Covariance of the evolution noise, of size .
Definition: ukf_types.h:279
virtual void updateEvolutionNoise(ukf_param &p, ukf_state &s)=0
Structure holding the matrices manipulated by the unscented kalman filter in the vectorial case...
Definition: ukf_types.h:249
gsl_matrix * mat_temp_n_n
Temporary matrix of size .
Definition: ukf_types.h:383
gsl_matrix * Kk_T
The tranposed Kalman gain, a vector of size .
Definition: ukf_types.h:259
void ukf_evaluate(ukf_param &p, ukf_state &s, FunctObj g, gsl_vector *xk, gsl_vector *dk)
Evaluation of the output from the sigma points.
Definition: ukf_parameter_ndim.h:313
double prior_pi
Prior estimate of the covariance matrix.
Definition: ukf_types.h:106
gsl_matrix * Sk
Matrix holding the Cholesky decomposition of , of size .
Definition: ukf_types.h:299
gsl_vector * vec_temp_output
Temporary vector of size .
Definition: ukf_types.h:348
double gamma
Definition: ukf_types.h:80
gsl_vector * wm
Weights used to compute the mean of the sigma points' images.
Definition: ukf_types.h:311
gsl_matrix * mat_temp_output_n
Temporary matrix of size .
Definition: ukf_types.h:363
int nbSamples
Number of sigma-points
Definition: ukf_types.h:116