kalman.cc

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 
00037 // Measurement Update
00038 void KalmanFiltTimeInvariantMstUpdate(const ssm& lds, const Vector& y_t, 
00039                                       const Vector& x_pred_t, 
00040                                       const Matrix& p_pred_t,
00041                                       const Vector& y_pred_t, 
00042                                       const Matrix& inno_cov_t, 
00043                                       Vector& x_hat_t, Matrix& p_hat_t, 
00044                                       Matrix& k_gain_t) {
00045   // create some params to be used later
00046   // tempm's are temp. matrices
00047   // temp's are temp vectors 
00048   int ny = lds.c_mat.n_rows();
00049   int nx = lds.a_mat.n_rows(); 
00050   Matrix c_trans; la::TransposeInit(lds.c_mat, &c_trans); 
00051   Matrix tempm_0, tempm_1, tempm_2, tempm_3; 
00052   Vector temp_1; 
00053 
00054   // create required square-root matrices
00055   // a sqrt-matrix is s.t. x = x_sqrt*x_sqrt_trans
00056   // want: r_sqrt, r_sqrt_trans
00057   // want: p_pred_t_sqrt, p_pred_t_sqrt_trans
00058   Matrix r_sqrt, r_sqrt_trans; 
00059   Matrix p_pred_t_sqrt, p_pred_t_sqrt_trans;
00060   la::CholeskyInit(lds.r_mat, &r_sqrt_trans); 
00061   la::TransposeInit(r_sqrt_trans, &r_sqrt); 
00062   la::CholeskyInit(p_pred_t, &p_pred_t_sqrt_trans); 
00063   la::TransposeInit(p_pred_t_sqrt_trans, &p_pred_t_sqrt);
00064 
00065   // form pre-array
00066   // pre_mat = [r_sqrt_trans                , 0; 
00067   //            p_red_t_sqrt_trans*c_trans' , P_pred_t_sqrt_trans]
00068   // pre_mat of size (nx + ny, nx + ny)
00069   Matrix pre_mat(ny + nx, ny + nx); pre_mat.SetZero();
00070   set_portion_of_matrix(r_sqrt_trans, 0, ny-1, 0, ny-1, &pre_mat);
00071   set_portion_of_matrix(p_pred_t_sqrt_trans, ny, ny + nx - 1, ny, ny + nx - 1, 
00072                         &pre_mat);
00073   la::MulInit(p_pred_t_sqrt_trans, c_trans, &tempm_0);
00074   set_portion_of_matrix(tempm_0, ny, ny + nx-1, 0, ny - 1, &pre_mat); 
00075 
00076   // form post-array
00077   // post_mat = [inno_cov_t_sqrt, 0;
00078   //             tempm_1,        p_hat_t_sqrt];
00079   // post_mat of size (nx + ny, nx + ny)
00080   Matrix qq, rr; la::QRInit(pre_mat, &qq, &rr);  
00081   Matrix post_mat; la::TransposeInit(rr, &post_mat);
00082   
00083   // extract p_hat_t_sqrt, k_gain_t  from post-array
00084   // k_gain_t = tempm_1*inv(inno_cov_t_sqrt)
00085   extract_sub_matrix_init(post_mat, ny, ny + nx - 1, 0, ny-1, &tempm_1);
00086   extract_sub_matrix_init(post_mat, 0, ny-1, 0, ny-1, &tempm_2);
00087   la::InverseInit(tempm_2, &tempm_3); 
00088   la::MulOverwrite(tempm_1,tempm_3, &k_gain_t); 
00089   Matrix p_hat_t_sqrt;
00090   extract_sub_matrix_init(post_mat, ny, ny + nx - 1, ny, ny + nx - 1, &p_hat_t_sqrt);   
00091   la::MulTransBOverwrite(p_hat_t_sqrt, p_hat_t_sqrt, &p_hat_t); 
00092   
00093   // Get state-estimates
00094   // x_hat_t = x_pred_t + k_gain_t*(y_t - y_pred_t); 
00095   // temp_1 = y_t - y_pred_t = innovations;
00096   la::ScaleInit(-1, y_pred_t, &temp_1); 
00097   la::AddTo(y_t, &temp_1); 
00098   la::MulOverwrite(k_gain_t, temp_1, &x_hat_t); 
00099   la::AddTo(x_pred_t, &x_hat_t); 
00100 }; 
00101 
00102 // Time Update
00103 void KalmanFiltTimeInvariantTimeUpdate(const ssm& lds, const Vector& x_hat_t, 
00104                                        const Matrix& p_hat_t, 
00105                                        const Vector& y_t, const Vector& u_t, 
00106                                        Vector& x_pred_t_next, 
00107                                        Vector& y_pred_t_next, 
00108                                        Matrix& p_pred_t_next, 
00109                                        Matrix& inno_cov_t_next) {
00110   // create some params to be used later
00111   // tempm's are temp. matrices
00112   // temp's are temp vectors 
00113   Matrix tempm_1, tempm_2; 
00114   Vector temp_1, temp_2; 
00115   int nx = lds.a_mat.n_cols(); 
00116 
00117   // Due to non-zero s_mat, must compute a_eff_mat, q_eff_mat, e_mat
00118   // a_eff_mat = a_mat - s_mat*inv(r_mat)*c_mat
00119   // q_eff_mat = q_mat - s_mat*inv(r_mat)*(s_mat)'
00120   // e_mat     = s_mat*inv(r_mat)
00121   Matrix a_eff_mat(lds.a_mat.n_rows(), lds.a_mat.n_cols()); 
00122   Matrix q_eff_mat(lds.q_mat.n_rows(), lds.q_mat.n_cols()); 
00123   Matrix e_mat; 
00124   
00125   // a_eff_mat
00126   schur(lds.a_mat, lds.s_mat,  lds.r_mat, lds.c_mat, &a_eff_mat);
00127   
00128   // e_mat
00129   Matrix inv_r_mat; la::InverseInit(lds.r_mat, &inv_r_mat); 
00130   la::MulInit(lds.s_mat, inv_r_mat, &e_mat); 
00131 
00132   // q_eff_mat
00133   Matrix s_trans; 
00134   la::TransposeInit(lds.s_mat, &s_trans);
00135   schur(lds.q_mat, lds.s_mat, lds.r_mat, s_trans, &q_eff_mat);
00136     
00137   // Also create a_eff_trans to be used later
00138   Matrix a_eff_trans;  
00139   la::TransposeInit(a_eff_mat, &a_eff_trans);
00140 
00141   // form pre-array
00142   // pre_mat = [p_hat_t_sqrt_trans*a_eff_trans; q_eff_sqrt_trans]
00143   Matrix pre_mat(nx + nx, nx);
00144   Matrix q_eff_sqrt_trans;
00145   Matrix  p_hat_t_sqrt_trans;
00146   la::CholeskyInit(q_eff_mat, & q_eff_sqrt_trans);  
00147   la::CholeskyInit(p_hat_t, &p_hat_t_sqrt_trans);  
00148   la::MulInit(p_hat_t_sqrt_trans, a_eff_trans, &tempm_1);
00149   set_portion_of_matrix(tempm_1, 0, nx-1, 0, nx-1, &pre_mat);
00150   set_portion_of_matrix(q_eff_sqrt_trans, nx, 2*nx-1, 0, nx-1, &pre_mat);
00151 
00152   // Form post-array via QR decomp.
00153   Matrix qq, rr;
00154   la::QRInit(pre_mat, &qq, &rr); 
00155   Matrix post_mat;
00156   la::TransposeInit(rr, &post_mat);
00157 
00158   // Extract p_pred_t_next_sqrt from post-array
00159   Matrix p_pred_t_next_sqrt;
00160   extract_sub_matrix_init(post_mat, 0, nx-1, 0, nx-1, &p_pred_t_next_sqrt);
00161   la::MulTransBOverwrite(p_pred_t_next_sqrt, p_pred_t_next_sqrt, 
00162                          &p_pred_t_next);
00163   // Generate inno_cov_t_next  = r_mat + c_mat*p_pred_t_next*c_mat';
00164   la::MulInit(lds.c_mat, p_pred_t_next_sqrt, &tempm_2); 
00165   la::MulTransBOverwrite(tempm_2, tempm_2, &inno_cov_t_next); 
00166   la::AddTo(lds.r_mat, &inno_cov_t_next); 
00167 
00168   // Generate x_pred_t_next = a_eff_mat*x_hat_t + e_mat*y_t + b_mat*u_t; 
00169   // y_pred_t_next = C*x_pred_t_next;
00170   la::MulInit(a_eff_mat, x_hat_t, &temp_1); 
00171   la::MulInit(e_mat, y_t, &temp_2); 
00172   la::AddTo(temp_1, &temp_2);
00173   la::MulOverwrite(lds.b_mat, u_t, &x_pred_t_next); 
00174   la::AddTo(temp_2, &x_pred_t_next); 
00175   la::MulOverwrite(lds.c_mat, x_pred_t_next, &y_pred_t_next);
00176 };
Generated on Mon Jan 24 12:04:38 2011 for FASTlib by  doxygen 1.6.3