Edinburgh Speech Tools  2.1-release
EST_kalman.cc
Go to the documentation of this file.
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1995,1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Simon King */
34 /* Date : June 1998 */
35 /*-----------------------------------------------------------------------*/
36 /* Kalman filtering, i.e. linear model fitting */
37 /* */
38 /*=======================================================================*/
39 
40 #include <cstdlib>
41 #include <cstdio>
42 #include <fstream>
43 #include "EST.h"
44 #include "EST_kalman.h"
45 
46 using namespace std;
47 
48 static bool kalman_filter_param_check(EST_FVector &x,
49  EST_FMatrix &P,
50  EST_FMatrix &Q,
51  EST_FMatrix &R,
52  EST_FMatrix &A,
53  EST_FMatrix &H,
54  EST_FVector &z);
55 
56 
57 
59  EST_FMatrix &P,
60  EST_FMatrix &Q,
61  EST_FMatrix &R,
62  EST_FMatrix &A,
63  EST_FMatrix &H,
64  EST_FVector &z)
65 {
66  // see kalman.h for meaning of args
67 
68  if(!kalman_filter_param_check(x,P,Q,R,A,H,z))
69  {
70  cerr << "Kalman filter parameters inconsistent !" << endl;
71  return FALSE;
72  }
73 
74  EST_FMatrix K,I,At,Ht,PHt,HPHt_R,HPHt_R_inv;
75  int state_dim=x.length();
76  int singularity;
77  eye(I,state_dim);
78  transpose(A,At);
79 
80  cerr << "predict" << endl;
81 
82  // predict
83  // =======
84  // if A is the identity matrix we could speed this up a LOT
85  x = A * x;
86  P = A * P * At + Q;
87 
88  cerr << "correct" << endl;
89 
90 
91  // correct
92  // =======
93  // T T -1
94  // K = P H ( H P H + R )
95  transpose(H,Ht);
96  PHt = P * Ht;
97  HPHt_R=(H * PHt) + R;
98 
99  if(!inverse( HPHt_R , HPHt_R_inv, singularity))
100  {
101  if(singularity != -1)
102  {
103  cerr << " H * P * Ht + R is singular !" << endl;
104  return FALSE;
105  }
106  cerr << "Matrix inversion failed for an unknown reason !" << endl;
107  return FALSE;
108  }
109 
110  K = PHt * HPHt_R_inv;
111  x = add(x, K * subtract(z,H * x));
112  P = (I - K * H) * P;
113 
114  // try and remedy numerical errors
115  symmetrize(P);
116 
117  //cerr << "done" << endl;
118 
119  return TRUE;
120 }
121 
122 
123 
125  EST_FMatrix &Pinv,
126  EST_FMatrix &Q,
127  EST_FMatrix &Rinv,
128  EST_FMatrix &A,
129  EST_FMatrix &H,
130  EST_FVector &z)
131 {
132 
133  // a different formulation, using the inverse
134  // covariance matrix, and a more stable update
135  // equation
136 
137  // from:
138  // Intro. to Random Signals and Kalman Applied Filtering
139  // Brown & Hwang (Wiley,1997)
140  // p. 248
141 
142  if(!kalman_filter_param_check(x,Pinv,Q,Rinv,A,H,z))
143  {
144  cerr << "Kalman filter parameters inconsistent !" << endl;
145  return FALSE;
146  }
147 
148 
149  EST_FMatrix K,I,At,Ht,P;
150  int singularity;
151  int state_dim=x.length();
152  eye(I,state_dim);
153  transpose(A,At);
154  transpose(H,Ht);
155 
156  cerr << "Compute P" << endl;
157 
158 
159  // update error covariance
160  // =======================
161  Pinv = Pinv + (Ht * Rinv * H);
162 
163  if(!inverse(Pinv,P,singularity))
164  {
165  if(singularity != -1)
166  {
167  cerr << "P is singular !" << endl;
168  return FALSE;
169  }
170  cerr << "Matrix inversion failed for an unknown reason !" << endl;
171  return FALSE;
172  }
173 
174  // compute gain
175  // ============
176  K = P * Ht * Rinv;
177 
178  // update state
179  // ============
180  x = add(x, K * subtract(z,H*x));
181 
182  // project ahead
183  // =============
184  x = A * x;
185  P = A * P * At + Q;
186  if(!inverse(P,Pinv,singularity))
187  {
188  if(singularity != -1)
189  {
190  cerr << "Pinv is singular !" << endl;
191  return FALSE;
192  }
193  cerr << "Matrix inversion failed for an unknown reason !" << endl;
194  return FALSE;
195  }
196 
197  // try and remedy numerical errors
198  //symmetrize(P);
199 
200  //cerr << "done" << endl;
201 
202  return TRUE;
203 
204 }
205 
206 
207 
208 bool kalman_filter_param_check(EST_FVector &x,
209  EST_FMatrix &P,
210  EST_FMatrix &Q,
211  EST_FMatrix &R,
212  EST_FMatrix &A,
213  EST_FMatrix &H,
214  EST_FVector &z)
215 {
216 
217 
218  int state_dim=x.length();
219  int measurement_dim=z.length();
220 
221 
222  // sanity checks
223  if((state_dim <= 0) ||
224  (measurement_dim <= 0))
225  {
226  cerr << "No state or measurements !!" << endl;
227  return FALSE;
228  }
229 
230  // dimensionality
231 
232  // P is error covariance
233  if((P.num_rows() != state_dim) ||
234  (P.num_columns() != state_dim) )
235  {
236  cerr << "P, or Pinv, must be a symmetrical square matrix of the same dimension" << endl;
237  cerr << "as the state vector, x" << endl;
238  return FALSE;
239  }
240 
241  // Q is process noise covariance
242  if((Q.num_rows() != state_dim) ||
243  (Q.num_columns() != state_dim) )
244  {
245  cerr << "Q must be a symmetrical square matrix of the same dimension" << endl;
246  cerr << "as the state vector, x" << endl;
247  return FALSE;
248  }
249 
250  // R is measurement noise covariance
251  if((R.num_rows() != measurement_dim) ||
252  (R.num_columns() != measurement_dim) )
253  {
254  cerr << "R, or Rinv, must be a symmetrical square matrix of the same dimension" << endl;
255  cerr << "as the measurement vector, z" << endl;
256  return FALSE;
257  }
258 
259  if((A.num_rows() != state_dim) ||
260  (A.num_columns() != state_dim) )
261  {
262  cerr << "A must be a square matrix of the same dimension" << endl;
263  cerr << "as the state vector, x" << endl;
264  return FALSE;
265  }
266 
267  if((H.num_rows() != measurement_dim) ||
268  (H.num_columns() != state_dim) )
269  {
270  cerr << "H must have dimensions to fit z = Hx" << endl;
271  return FALSE;
272  }
273 
274  return TRUE;
275 }
EST_FVector subtract(const EST_FVector &a, const EST_FVector &b)
elementwise subtract
Definition: vec_mat_aux.cc:519
ssize_t num_columns() const
return number of columns
Definition: EST_TMatrix.h:179
A vector class for floating point numbers. EST_FVector x should be used instead of float *x wherever ...
Definition: EST_FMatrix.h:119
ssize_t num_rows() const
return number of rows
Definition: EST_TMatrix.h:177
void eye(EST_FMatrix &a, const ssize_t n)
some useful matrix creators make an identity matrix of dimension n
Definition: vec_mat_aux.cc:473
STATIC HISTORY H
Definition: editline.c:120
void symmetrize(EST_FMatrix &a)
enforce symmetry
Definition: vec_mat_aux.cc:564
EST_FVector add(const EST_FVector &a, const EST_FVector &b)
elementwise add
Definition: vec_mat_aux.cc:501
INLINE ssize_t length() const
number of items in vector.
Definition: EST_TVector.h:249
#define FALSE
Definition: EST_bool.h:119
void transpose(const EST_FMatrix &a, EST_FMatrix &b)
exchange rows and columns
Definition: vec_mat_aux.cc:244
bool kalman_filter(EST_FVector &x, EST_FMatrix &P, EST_FMatrix &Q, EST_FMatrix &R, EST_FMatrix &A, EST_FMatrix &H, EST_FVector &z)
Definition: EST_kalman.cc:58
bool kalman_filter_Pinv(EST_FVector &x, EST_FMatrix &Pinv, EST_FMatrix &Q, EST_FMatrix &Rinv, EST_FMatrix &A, EST_FMatrix &H, EST_FVector &z)
Definition: EST_kalman.cc:124
#define TRUE
Definition: EST_bool.h:118
int inverse(const EST_FMatrix &a, EST_FMatrix &inv)
inverse
Definition: vec_mat_aux.cc:298