kalman_main.cc

Go to the documentation of this file.
00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00032 #include <iostream>
00033 #include "fastlib/fastlib.h"
00034 #include "kalman_helper.h"
00035 #include "kalman.h"
00036 using namespace std;
00037 
00070 int main(int argc, char* argv[]) {
00071 
00072   fx_init(argc, argv, NULL);
00073  
00075 
00076   // User-specified: duration of experiment 
00077   // Note that the experiment will run from t=0 to t_tot
00078   const char* t_in = fx_param_str(NULL, "t_in", "t_in");
00079   Matrix t_tot_mat; data::Load(t_in, &t_tot_mat);
00080   int t_tot = (int)t_tot_mat.get(0, 0);
00081   
00082   // User-specified: system parameters. Stored in *.csv files 
00083   // a_mat, b_mat, c_mat, d_mat, q_mat, r_mat, s_mat
00084   // are the typical time-invariant system params
00085   // Proceed to Load init matrices within a struct called lds
00086   const char* a_in = fx_param_str(NULL, "a_in", "a_in");
00087   const char* b_in = fx_param_str(NULL, "b_in", "b_in");
00088   const char* c_in = fx_param_str(NULL, "c_in", "c_in");
00089   const char* q_in = fx_param_str(NULL, "q_in", "q_in");
00090   const char* r_in = fx_param_str(NULL, "r_in", "r_in");
00091   const char* s_in = fx_param_str(NULL, "s_in", "s_in");  
00092   
00093   ssm lds;
00094   data::Load(a_in, &lds.a_mat); 
00095   data::Load(b_in, &lds.b_mat); 
00096   data::Load(c_in, &lds.c_mat); 
00097   data::Load(q_in, &lds.q_mat); 
00098   data::Load(r_in, &lds.r_mat); 
00099   data::Load(s_in, &lds.s_mat);  
00100              
00101   // User-specified: kf parameters. Stored in *.csv files 
00102   // Includes x_{0|-1}, p_pred_{0|-1}, y_{0|-1}, inno_cov_{0|-1}
00103   // {t|t-1} means var. at time t given info. up to t-1
00104   const char* x_pred_0_in = fx_param_str(NULL, "x_pred_0_in", "x_pred_0_in");
00105   const char* p_pred_0_in = fx_param_str(NULL, "p_pred_0_in", "p_pred_0_in");
00106   const char* y_pred_0_in = fx_param_str(NULL, "y_pred_0_in", "y_pred_0_in");
00107   const char* inno_cov_0_in = fx_param_str(NULL, "inno_cov_0_in", 
00108                                            "inno_cov_0_in");
00109   
00110   Matrix x_pred_0; data::Load(x_pred_0_in, &x_pred_0);
00111   Matrix y_pred_0; data::Load(y_pred_0_in, &y_pred_0); 
00112   Matrix p_pred_0; data::Load(p_pred_0_in, &p_pred_0);
00113   Matrix inno_cov_0; data::Load(inno_cov_0_in, &inno_cov_0);
00114 
00115   // Set up parameters to be used by signal generator. 
00116   // Assumed to be an lds with the same params. as the KF
00117   // for the purpose of demonstration
00118   // assume that x is initially zero
00119   int nx = lds.a_mat.n_rows(); 
00120   int ny = lds.c_mat.n_rows(); 
00121   int nu = lds.b_mat.n_cols();
00122   Matrix x(nx, t_tot + 1); x.SetZero();
00123   Matrix y(ny, t_tot + 1); 
00124   Matrix u(nu, t_tot + 1); 
00125   Matrix w(nx, t_tot + 1); 
00126   Matrix v(ny, t_tot + 1); 
00127 
00128   // Set up params. for the KF including:
00129   // estimates: x_{t|t-1}, x_{t|t}, y_{t|t-1}
00130   // error covariances: p_pred_{t|t-1}, p_hat{t|t-1}, inno_cov_{t|t-1}
00131   // Kalman gain
00132   // Also initialize values and sizes where appropriate
00133   Matrix x_pred(nx, t_tot + 1); 
00134   Matrix x_hat(nx, t_tot + 1);
00135   Matrix y_pred(ny, t_tot + 1);
00136   Matrix p_pred[t_tot + 1]; 
00137   Matrix p_hat[t_tot + 1];
00138   Matrix inno_cov[t_tot + 1];
00139   Matrix k_gain[t_tot + 1];
00140   set_portion_of_matrix(x_pred_0, 0, nx-1, 0, 0, &x_pred);
00141   set_portion_of_matrix(y_pred_0, 0, ny-1, 0, 0, &y_pred);
00142   for (int t =0; t<=t_tot; t++ ) {
00143     p_pred[t].Init(nx, nx);
00144     p_hat[t].Init(nx, nx);
00145     k_gain[t].Init(nx, ny);
00146     inno_cov[t].Init(ny, ny);
00147   };    
00148   p_pred[0]   = p_pred_0;
00149   inno_cov[0] = inno_cov_0;
00150 
00151   // Define other params. to be used
00152   // noise_matrix = [q_mat s_mat; s_mat' r_mat]
00153   Matrix noise_mat(nx + ny, nx + ny), s_trans;
00154   la:: TransposeInit(lds.s_mat, &s_trans);
00155   set_portion_of_matrix(lds.q_mat, 0, nx - 1, 0, nx - 1, &noise_mat);
00156   set_portion_of_matrix(lds.s_mat, 0, nx - 1, nx, nx + ny -1, &noise_mat);
00157   set_portion_of_matrix(s_trans, nx, nx + ny - 1,0, nx - 1, &noise_mat);
00158   set_portion_of_matrix(lds.r_mat, nx, nx + ny - 1, nx, nx + ny - 1, &noise_mat); 
00159 
00160 
00162   for (int t=0; t<=t_tot; t++) {
00163     /*
00164       Signal generation. As a demo, the system will also 
00165       be an lds with the same parameters as the k.f. 
00166       although this doesn't need to be necessarily true */
00167     
00168     // Generate noise
00169     // Also make aliases which do not need to be init'd
00170     Vector w_t; w.MakeColumnVector(t, &w_t); 
00171     Vector v_t; v.MakeColumnVector(t, &v_t);    
00172     Vector w_v_t; w_v_t.Init(nx+ny);
00173     RandVector(noise_mat, w_v_t);
00174     extract_sub_vector_of_vector(w_v_t, 0, nx-1, &w_t);
00175     extract_sub_vector_of_vector(w_v_t, nx, nx+ny-1, &v_t);  
00176 
00177     // y_t = c_mat*x_{t} +  v_t 
00178     // Also make aliases which do not need to be init'd
00179     Vector x_t; x.MakeColumnVector(t, &x_t);
00180     Vector y_t; y.MakeColumnVector(t, &y_t);
00181     propagate_one_step(lds.c_mat, x_t, v_t, &y_t);
00182 
00183     /*
00184       Perform measurement update */
00185     // Alg. takes (lds, y_t, x_{t|t-1}, p_{t|t-1}, inno_cov_{t|t-1})
00186     // outputs (x_{t|t}, p_{t|t}, k_gain{t})
00187     // Also make aliases which do not need to  be init'd
00188     Vector x_pred_t; x_pred.MakeColumnVector(t, &x_pred_t);
00189     Vector y_pred_t; y_pred.MakeColumnVector(t, &y_pred_t);
00190     Vector x_hat_t; x_hat.MakeColumnVector(t, &x_hat_t);
00191     KalmanFiltTimeInvariantMstUpdate(lds, y_t, x_pred_t, p_pred[t], 
00192                                      y_pred_t, inno_cov[t], x_hat_t, 
00193                                      p_hat[t], k_gain[t]);
00194 
00195     /* The system might want to do sth. here
00196        Ex. u_t = f(x_{t|t})
00197        Here, u_t is assumed to be a normally distributed vec.
00198        Also make aliases*/
00199     Vector u_t; 
00200     u.MakeColumnVector(t, &u_t);
00201     RandVector(u_t);
00202 
00203 
00204     /* Perform Time update 
00205      Alg. takes (lds, x_{t|t}, p_{t|t}, y_t, u_t)
00206      outputs (x_{t+1|t}, y_{t+1|t}, p_{t+1|t}, inno_cov{t+1|t}) 
00207      Also make aliases that do not need to be init'd. 
00208      But do so if not at final time step */
00209     if (t <  t_tot) { 
00210       Vector x_pred_t_next; x_pred.MakeColumnVector(t + 1, &x_pred_t_next);
00211       Vector y_pred_t_next; y_pred.MakeColumnVector(t + 1, &y_pred_t_next);
00212       KalmanFiltTimeInvariantTimeUpdate(lds, x_hat_t, p_hat[t], y_t, u_t, 
00213                                         x_pred_t_next, y_pred_t_next, 
00214                                         p_pred[t + 1], inno_cov[t + 1]);      
00215       
00216     };
00217     /* Propagate states 1-step forward 
00218        Again the true plant/ system is up to the user to define
00219        x_{t+1} = a_mat*x_{t} + b_mat*u_{t} + w_{t} 
00220        unless we are at the last time step */      
00221     if (t <  t_tot) { 
00222       Vector x_t_next; x.MakeColumnVector(t+1, &x_t_next);
00223       propagate_one_step(lds.a_mat, lds.b_mat, x_t, u_t, w_t, &x_t_next);
00224     };
00225   }; /* demo */
00226   
00228   
00229   /* We will store the results so that a similar Matlab
00230      implementation can be used as a comparison
00231      To save:
00232      w, v (stochastic realizations)
00233      u, x, y (actions)
00234      x_pred, p_pred[t_tot] (expect this to converge)
00235      x_hat, p_hat[t_tot] (expect this to converge)
00236      y_pred, inno_cov[t_tot] (expect this to converge)
00237      k_gain[t_tot] (expect this to converge)
00238      
00239      These will be saved as separate *.csv files
00240      See test_kf.m for comparison tests 
00241      and plotting capabilities */
00242   
00243   Matrix w_trans, v_trans; 
00244   Matrix u_trans, x_trans, y_trans; 
00245   Matrix x_pred_trans;
00246   Matrix x_hat_trans; 
00247   Matrix y_pred_trans; 
00248   Matrix k_gain_end_trans;
00249     
00250   la::TransposeInit(w, &w_trans);
00251   la::TransposeInit(v, &v_trans);
00252   la::TransposeInit(u, &u_trans);
00253   la::TransposeInit(x, &x_trans);
00254   la::TransposeInit(y, &y_trans);
00255   la::TransposeInit(x_pred, &x_pred_trans);
00256   la::TransposeInit(x_hat, &x_hat_trans);
00257   la::TransposeInit(y_pred, &y_pred_trans);
00258   la::TransposeInit(k_gain[t_tot], &k_gain_end_trans);
00259   
00260   data::Save("w_out", w_trans);
00261   data::Save("v_out", v_trans);
00262   data::Save("u_out", u_trans);
00263   data::Save("x_out", x_trans);
00264   data::Save("y_out", y_trans);
00265   data::Save("x_pred_out", x_pred_trans);
00266   data::Save("p_pred_end_out", p_pred[t_tot]);
00267   data::Save("x_hat_out", x_hat_trans);
00268   data::Save("p_hat_end_out", p_hat[t_tot]);
00269   data::Save("y_pred_out", y_pred_trans);
00270   data::Save("inno_cov_end_out", inno_cov[t_tot]);
00271   data::Save("k_gain_end_out", k_gain_end_trans);             
00272   
00273   fx_done(fx_root);
00274 }; /* main */
Generated on Mon Jan 24 12:04:38 2011 for FASTlib by  doxygen 1.6.3