RauchTungStriebelHarness.cpp

Go to the documentation of this file.
00001 #include "indii/ml/filter/KalmanFilter.hpp"
00002 #include "indii/ml/filter/RauchTungStriebelSmoother.hpp"
00003 #include "indii/ml/filter/LinearModel.hpp"
00004 
00005 #include "MobileRobot.hpp"
00006 
00007 #include <math.h>
00008 #include <iostream>
00009 #include <fstream>
00010 #include <stack>
00011 
00012 #define STATE_SIZE 5
00013 #define MEAS_SIZE 1
00014 #define ACTUAL_SIZE 3
00015 #define STEPS 100
00016 
00017 using namespace std;
00018 using namespace indii::ml::filter;
00019 
00020 namespace aux = indii::ml::aux;
00021 namespace ublas = boost::numeric::ublas;
00022 
00023 /**
00024  * @file RauchTungStriebelHarness.cpp
00025  *
00026  * Basic test of RauchTungStriebelSmoother.
00027  *
00028  * This test sets up a linear model for testing the
00029  * Rauch-Tung-Striebel (RTS) smoother implementation. It may be
00030  * validated against the Kalman filter and kalman smoother results.
00031  *
00032  * Results are output into files as follows:
00033  *
00034  * @section actualRTS results/RauchTungStriebelHarness_actual.out
00035  *
00036  * Actual state of the robot at each time. Columns are as follows:
00037  *
00038  * @li time
00039  * @li x coordinate
00040  * @li y coordinate
00041  * @li orientation (radians)
00042  *
00043  * @section measRTS results/RauchTungStriebelHarness_meas.out
00044  * 
00045  * Measurement at each time step. Columns are as follows:
00046  *
00047  * @li time
00048  * @li measurement
00049  *
00050  * @section filterRTS results/RauchTungStriebelHarness_filter.out
00051  *
00052  * Predicted state (filtered) at each time step. Columns are as follows:
00053  *
00054  * @li time
00055  * @li mean x coordinate
00056  * @li mean y coordinate
00057  * @li mean orientation
00058  * @li The remaining columns give the covariance matrix between the above
00059  * state variables.
00060  *
00061  * @section smoothRTS results/RauchTungStriebelHarness_smooth.out
00062  *
00063  * Predicted state (smoothed) at each time step. Columns are as follows:
00064  *
00065  * @li time
00066  * @li mean x coordinate
00067  * @li mean y coordinate
00068  * @li mean orientation
00069  * @li The remaining columns give the covariance matrix between the above
00070  * state variables.
00071  *
00072  * Note that as the smoothing is performed in a backwards pass, this file has
00073  * entries in reverse time order.
00074  *
00075  * @section resultsRTS Results
00076  *
00077  * Results are as follows:
00078  *
00079  * \image html RauchTungStriebelHarness.png "Results"
00080  * \image latex RauchTungStriebelHarness.eps "Results"
00081  */
00082 
00083 void outputVector(ofstream& out, aux::vector vec);
00084 
00085 void outputMatrix(ofstream& out, aux::matrix mat);
00086 
00087 /**
00088  * Run tests
00089  */
00090 int main(int argc, const char* argv) {
00091   /* define model */
00092   aux::matrix A(STATE_SIZE,STATE_SIZE);
00093   aux::matrix G(STATE_SIZE,STATE_SIZE);
00094   aux::matrix C(MEAS_SIZE,STATE_SIZE);
00095   aux::symmetric_matrix Q(STATE_SIZE);
00096   aux::symmetric_matrix R(MEAS_SIZE);
00097 
00098   A.clear();
00099   A(0,0) = 1.0;
00100   A(0,3) = cos(0.8);
00101   A(1,1) = 1.0;
00102   A(1,3) = sin(0.8);
00103   A(2,2) = 1.0;
00104   A(3,3) = 1.0;
00105   A(4,4) = 1.0;
00106 
00107   G.clear();
00108   G(0,0) = 1.0;
00109   G(1,1) = 1.0;
00110 
00111   Q.clear();
00112   Q(0,0) = pow(0.01, 2.0);
00113   Q(1,1) = pow(0.01, 2.0);
00114   /* next three just so that Q is Cholesky decomposible, are zeroed by G */
00115   Q(2,2) = 1.0;
00116   Q(3,3) = 1.0;
00117   Q(4,4) = 1.0;
00118 
00119   C.clear();
00120   C(0,1) = 2.0;
00121 
00122   R.clear();
00123   R(0,0) = pow(0.05,2.0);
00124   
00125   LinearModel model(A, G, Q, C, R);
00126 
00127   /* initial state */
00128   aux::vector mu(STATE_SIZE);
00129   aux::symmetric_matrix sigma(STATE_SIZE);
00130 
00131   mu.clear();
00132   mu(0) = -1.0;
00133   mu(1) = 1.0;
00134   mu(2) = 0.8;
00135   mu(3) = 0.1;
00136   mu(4) = 0.0;
00137 
00138   sigma.clear();
00139   sigma(0,0) = 1.0;
00140   sigma(1,1) = 1.0;
00141   sigma(2,2) = 0.1;
00142   sigma(3,3) = 0.1;
00143   sigma(4,4) = 0.1;
00144 
00145   aux::GaussianPdf x0(mu, sigma);
00146 
00147   /* create smoother */
00148   KalmanFilter<unsigned int> filter(&model, x0);
00149 
00150   /* set up robot simulator */
00151   MobileRobot robot(0.1, 5e-3);
00152 
00153   /* estimate and output results */
00154   stack<aux::GaussianPdf> filteredStates;
00155   aux::vector meas(MEAS_SIZE);
00156   aux::vector actual(ACTUAL_SIZE);
00157   aux::GaussianPdf pred(STATE_SIZE);
00158   unsigned int t = 0;
00159 
00160   ofstream fmeas("results/RauchTungStriebelHarness_meas.out");
00161   ofstream factual("results/RauchTungStriebelHarness_actual.out");
00162   ofstream ffilter("results/RauchTungStriebelHarness_filter.out");
00163   ofstream fsmooth("results/RauchTungStriebelHarness_smooth.out");
00164 
00165   /* output initial state */
00166   actual = robot.getState();
00167   pred = filter.getFilteredState();
00168   filteredStates.push(pred);
00169 
00170   cerr << t << ' ';
00171 
00172   factual << t << '\t';
00173   outputVector(factual, actual);
00174   factual << endl;
00175 
00176   ffilter << t << '\t';
00177   outputVector(ffilter, pred.getExpectation());
00178   ffilter << '\t';
00179   outputMatrix(ffilter, pred.getCovariance());
00180   ffilter << endl;
00181 
00182   /* filter */
00183   for (t = 1; t <= STEPS; t++) {
00184     robot.move();
00185 
00186     meas = robot.measure();
00187     filter.filter(t, meas);
00188     pred = filter.getFilteredState();
00189     filteredStates.push(pred);
00190     actual = robot.getState();
00191 
00192     cerr << t << ' ';
00193 
00194     /* output measurement */
00195     fmeas << t << '\t';
00196     outputVector(fmeas, meas);
00197     fmeas << endl;
00198 
00199     /* output actual state */
00200     factual << t << '\t';
00201     outputVector(factual, actual);
00202     factual << endl;
00203 
00204     /* output filtered state */
00205     ffilter << t << '\t';
00206     outputVector(ffilter, pred.getExpectation());
00207     ffilter << '\t';
00208     outputMatrix(ffilter, pred.getCovariance());
00209     ffilter << endl;
00210   }
00211 
00212   /* smooth */
00213   t--;
00214   pred = filter.getFilteredState();
00215   RauchTungStriebelSmoother<unsigned int> smoother(&model, t, pred);
00216 
00217   cerr << t << ' ';
00218   fsmooth << t << '\t';
00219   outputVector(fsmooth, pred.getExpectation());
00220   fsmooth << '\t';
00221   outputMatrix(fsmooth, pred.getCovariance());
00222   fsmooth << endl;
00223 
00224   for (t = STEPS - 1; t >= 1; t--) {
00225     smoother.smooth(t - 1, filteredStates.top());
00226     filteredStates.pop();
00227     pred = smoother.getSmoothedState();
00228 
00229     cerr << t << ' ';
00230 
00231     /* output filtered state */
00232     fsmooth << t << '\t';
00233     outputVector(fsmooth, pred.getExpectation());
00234     fsmooth << '\t';
00235     outputMatrix(fsmooth, pred.getCovariance());
00236     fsmooth << endl;
00237   }
00238 
00239   fmeas.close();
00240   factual.close();
00241   ffilter.close();
00242   fsmooth.close();
00243 
00244   return 0;
00245 }
00246 
00247 void outputVector(ofstream& out, aux::vector vec) {
00248   aux::vector::iterator iter, end;
00249   iter = vec.begin();
00250   end = vec.end();
00251   while (iter != end) {
00252     out << *iter;
00253     iter++;
00254     if (iter != end) {
00255       out << '\t';
00256     }
00257   }
00258 }
00259 
00260 void outputMatrix(ofstream& out, aux::matrix mat) {
00261   unsigned int i, j;
00262   for (j = 0; j < mat.size2(); j++) {
00263     for (i = 0; i < mat.size1(); i++) {
00264       out << mat(i,j);
00265       if (i != mat.size1() - 1 || j != mat.size2() - 1) {
00266   out << '\t';
00267       }
00268     }
00269   }
00270 }

Generated on Wed Dec 17 15:05:50 2008 for dysii Filtering Test Suite by  doxygen 1.5.3