Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ExampleIEKF.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 /** @example ExampleIEKF.cpp
27  @relates IteratedExtendedKalman
28  @ingroup g_examples
29  @ingroup g_stateestimation
30  @brief Example using the iterated extended kalman filter
31  @author MIP
32 */
33 
34 #include <StateEstimator/IteratedExtendedKalman.hh>
35 #include <Base/Math/Random.hh>
36 
37 #include <fstream>
38 
39 using namespace std;
40 using namespace BIAS;
41 /** \cond HIDDEN_SYMBOLS */
42 /// specialized kalman filter for example
43 class OwnKF : public IteratedExtendedKalman {
44 
45 public:
46 
47  OwnKF() : IteratedExtendedKalman(100, 1e-8, true) {
48  }
49 
50  /// specialization for state transition function
51  /// simple one dimesional movement (position + speed)
52  virtual void StateTransition(const BIAS::Vector<double>& state,
53  const BIAS::Vector<double>& control,
54  BIAS::Vector<double>& prediction)
55  {
56  /// newPos = olsPos + deltaT*oldVel
57  prediction[0] = state[0] + control[0]*state[1];
58  /// newVel = oldVel
59  prediction[1] = state[1];
60  }
61 
62  /// specialization for jacobian matrices for state transition
63  virtual void GetTransitionJacobian(const BIAS::Vector<double>& state,
64  const BIAS::Vector<double>& control,
65  BIAS::Matrix<double>& transJacobian,
66  BIAS::Matrix<double>& transErrorJacobian)
67  {
68  /// delta_StateTransition/delta_state
69  transJacobian[0][0] = 1;
70  transJacobian[0][1] = control[0];
71  transJacobian[1][0] = 0;
72  transJacobian[1][1] = 1;
73 
74  /// delta_StateTransition/delta_processNoise
75  /// process noise additive for position and speed
76  transErrorJacobian[0][0] = 1;
77  transErrorJacobian[0][1] = 0;
78  transErrorJacobian[1][0] = 0;
79  transErrorJacobian[1][1] = 1;
80  }
81 
82  /// specialization for measurement prediction function
83  virtual void MeasurementPrediction(const BIAS::Vector<double>& state,
84  BIAS::Vector<double>& measurePred,
85  const unsigned int index=1)
86  {
87  switch(index) {
88  case 1:
89  /// first observation = sin(position)
90  measurePred[0] = state[0]*state[0]*state[0];
91  break;
92  case 2:
93  /// second observation = velocity^3
94  measurePred[0] = state[1]*state[1]*state[1]+10*state[1];
95  break;
96  default:
97  BIASERR("Unknown measurement called!");
98  BIASABORT;
99  }
100  }
101 
102  /// specialization for measurement prediction jacobian
103  virtual void GetMeasureJacobian(const BIAS::Vector<double> &state,
104  BIAS::Matrix<double> &measJacobian,
105  BIAS::Matrix<double> &measErrorJacobian,
106  const unsigned int index=1)
107  {
108  switch(index) {
109  case 1:
110  /// first observation = position^3, no velocity -> jac = [3*pos | 0]
111  measJacobian[0][0] = 3*state[0];
112  measJacobian[0][1] = 0;
113  /// additive noise
114  measErrorJacobian[0][0] = 1;
115  break;
116  case 2:
117  /// first observation = no position, vel^3 + 10*vel -> jac = [0|3*vel+10]
118  measJacobian[0][0] = 0;
119  measJacobian[0][1] = 3*state[1]+10;
120  /// additive noise
121  measErrorJacobian[0][0] = 1;
122  break;
123  default:
124  BIASERR("Unknown measurement called!");
125  BIASABORT;
126  }
127  }
128 };
129 /** \endcond */
130 
131 int main(int argc, char *argv[]) {
132 
133  if (argc != 5) {
134  cout << "Usage: " << argv[0]
135  << " stateHistFile truePosFile measure1File measure2File!" << endl;
136  exit(-1);
137  }
138 
139  OwnKF estimator; /// IEKF estimator, see above
140  unsigned int simLength = 500; /// length of dataset
141  unsigned int rSeed = 0; /// seed for randomizer
142 
143  /// ground truth position
144  BIAS::Vector<double> posTrue(simLength);
145  /// ground truth velocity
146  BIAS::Vector<double> velTrue(simLength);
147  /// ground truth for first observation
148  vector< BIAS::Vector<double> > measTrue1(simLength);
149  /// ground truth for second observation
150  vector< BIAS::Vector<double> > measTrue2(simLength);
151  /// first noisy observation
152  vector< BIAS::Vector<double> > measNoise1(simLength);
153  /// second noisy observation
154  vector< BIAS::Vector<double> > measNoise2(simLength);
155  /// history of estimated state
156  vector< BIAS::Vector<double> > stateHist(simLength);
157  /// history of estimated state standard deviation
158  vector< BIAS::Matrix<double> > covHist(simLength);
159 
160  /// set sigma for first observation
161  double sigmaM1 = 0.1;
162  /// set sigma for second observation
163  double sigmaM2 = 0.01;
164 
165  /// create process noise covariance
166  Matrix<double> Q(2,2);
167  Q[0][0] = 0.001; Q[0][1] = 0.0; Q[1][0] = 0.0; Q[1][1] = 1e-5;
168  /// create initial state covariance
169  Matrix<double> PI(2,2);
170  PI[0][0] = 0.001; PI[0][1] = 0.0; PI[1][0] = 0.0; PI[1][1] = 1;
171  /// create noise covariance for first observation
172  Matrix<double> R_1(1,1); R_1[0][0] = sigmaM1;
173  /// create noise covariance for second observation
174  Matrix<double> R_2(1,1); R_2[0][0] = sigmaM2;
175 
176  /// create randomizer using given seed
177  Random rand(rSeed);
178 
179  //generate ground truth
180  for (unsigned int i=0; i<simLength; i++) {
181  /// positions = 5 periods of the function 0.25*sin^2+1
182  posTrue[i] = sin(10*M_PI*double(i)/double(simLength));
183  posTrue[i] = 0.25*posTrue[i]*posTrue[i]+1.0;
184  /// velocity = delta_pos/delta_i;
185  velTrue[i] = 5.0*M_PI/double(simLength)
186  *sin(10*M_PI*double(i)/double(simLength))
187  *cos(10*M_PI*double(i)/double(simLength));
188  //first observation = sin(position)
189  measTrue1[i].newsize(1);
190  measTrue1[i][0] = posTrue[i]*posTrue[i]*posTrue[i];
191  //second observation = velocity^3
192  measTrue2[i].newsize(1);
193  measTrue2[i][0] = velTrue[i]*velTrue[i]*velTrue[i]+10*velTrue[i];
194  //posTrue[i]*posTrue[i]*posTrue[i];
195  //init state history
196  stateHist[i].newsize(2);
197  covHist[i] = BIAS::Matrix<double>(2,2);
198  }
199 
200  //generate noisy measurements
201  for (unsigned int i=0; i<simLength; i++) {
202  measNoise1[i].newsize(1);
203  measNoise1[i][0] = measTrue1[i][0] +
204  rand.GetNormalDistributed (0.0, sigmaM1);
205  measNoise2[i].newsize(1);
206  measNoise2[i][0] = measTrue2[i][0] +
207  rand.GetNormalDistributed (0.0, sigmaM2);
208  }
209 
210  /// create control vector (deltaT allways 1)
211  BIAS::Vector<double> control(1);
212  control[0] = 1;
213 
214  /// set initial state
215  Vector<double> initial(2);
216  initial[0] = posTrue[0]; initial[1] = 0.0;
217  estimator.Init(initial, PI, Q);
218 
219  //start estimation
220  for (unsigned int i=0; i<simLength; i++) {
221  /// update using first observation
222  estimator.Update(measNoise1[i], R_1, 1);
223  /// update using second observation
224  estimator.Update(measNoise2[i], R_2, 2);
225  /// record state history
226  estimator.GetPosterioriState(stateHist[i]);
227  estimator.GetPosterioriCovariance(covHist[i]);
228  /// predict state
229  estimator.Predict(control);
230  }
231 
232  /// write state history and ground truth position to given files
233  ofstream estFile(argv[1]);
234  ofstream gtFile(argv[2]);
235  ofstream meas1File(argv[3]);
236  ofstream meas2File(argv[4]);
237  for (unsigned int i=0; i < simLength; i++) {
238  estFile << stateHist[i][0] << " " << stateHist[i][1] << " "
239  << sqrt(covHist[i][0][0]) << sqrt(covHist[i][1][1]) << endl;
240  gtFile << posTrue[i] << " " << velTrue[i] << endl;
241  meas1File << measNoise1[i][0] << endl;
242  meas2File << measNoise2[i][0] << endl;
243  }
244  estFile.close();
245  gtFile.close();
246  meas1File.close();
247  meas2File.close();
248 
249  exit(0);
250 }
Iterated Extended Kalman-filter (IEKF).
Matrix< T > & newsize(Subscript M, Subscript N)
Definition: cmat.h:269
class for producing random numbers from different distributions
Definition: Random.hh:51