SimpleKalmanFilter.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: SimpleKalmanFilter.cpp 2570 2011-04-21 17:33:49Z yanweignss $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 //  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2007, 2008
00027 //
00028 //============================================================================
00029 
00030 
00031 
00032 #include "SimpleKalmanFilter.hpp"
00033 #include "MatrixFunctors.hpp"
00034 
00035 
00036 namespace gpstk
00037 {
00038 
00039       /* Reset method.
00040        *
00041        * This method will reset the filter, setting new values for initial
00042        * system state vector and the a posteriori error covariance matrix.
00043        *
00044        * @param initialState      Vector setting the initial state of
00045        *                          the system.
00046        * @param initialErrorCovariance    Matrix setting the initial
00047        *                   values of the a posteriori error covariance.
00048        */
00049    void SimpleKalmanFilter::Reset( const Vector<double>& initialState,
00050                                 const Matrix<double>& initialErrorCovariance )
00051    {
00052 
00053       xhat = initialState;
00054       P = initialErrorCovariance;
00055       xhatminus.resize(initialState.size(), 0.0);
00056       Pminus.resize( initialErrorCovariance.rows(),
00057                      initialErrorCovariance.cols(), 0.0);
00058 
00059    }  // End of method 'SimpleKalmanFilter::Reset()'
00060 
00061 
00062 
00063       /* Reset method.
00064        *
00065        * This method will reset the filter, setting new values for initial
00066        * system  state and the a posteriori error variance. Used for
00067        * one-dimensional systems.
00068        *
00069        * @param initialValue      Initial value of system state.
00070        * @param initialErrorVariance  Initial value of the a posteriori
00071        *                              error variance.
00072        */
00073    void SimpleKalmanFilter::Reset( const double& initialValue,
00074                                    const double& initialErrorVariance )
00075    {
00076 
00077       xhat.resize(1, initialValue);
00078       P.resize(1,1, initialErrorVariance);
00079       xhatminus.resize(1, 0.0);
00080       Pminus.resize(1, 1, 0.0);
00081 
00082    }  // End of method 'SimpleKalmanFilter::Reset()'
00083 
00084 
00085 
00086       // Compute the a posteriori estimate of the system state, as well as
00087       // the a posteriori estimate error covariance matrix.
00088       //
00089       // @param phiMatrix         State transition matrix.
00090       // @param controlMatrix     Control matrix.
00091       // @param controlInput      Control input vector.
00092       // @param processNoiseCovariance    Process noise covariance matrix.
00093       // @param measurements      Measurements vector.
00094       // @param measurementsMatrix    Measurements matrix. Called geometry
00095       //                              matrix in GNSS.
00096       // @param measurementsNoiseCovariance   Measurements noise covariance
00097       //                                      matrix.
00098       //
00099       // @return
00100       //  0 if OK
00101       //  -1 if problems arose
00102       //
00103    int SimpleKalmanFilter::Compute( const Matrix<double>& phiMatrix,
00104                                     const Matrix<double>& controlMatrix,
00105                                     const Vector<double>& controlInput,
00106                                  const Matrix<double>& processNoiseCovariance,
00107                                     const Vector<double>& measurements,
00108                                     const Matrix<double>& measurementsMatrix,
00109                             const Matrix<double>& measurementsNoiseCovariance )
00110       throw(InvalidSolver)
00111    {
00112 
00113       try
00114       {
00115          Predict( phiMatrix,
00116                   xhat,
00117                   controlMatrix,
00118                   controlInput,
00119                   processNoiseCovariance );
00120 
00121          Correct( measurements,
00122                   measurementsMatrix,
00123                   measurementsNoiseCovariance );
00124       }
00125       catch(InvalidSolver e)
00126       {
00127          GPSTK_THROW(e);
00128          return -1;
00129       }
00130 
00131       return 0;
00132 
00133    }  // End of method 'SimpleKalmanFilter::Compute()'
00134 
00135 
00136 
00137       // Compute the a posteriori estimate of the system state, as well as
00138       // the a posteriori estimate error covariance matrix. This version
00139       // assumes that no control inputs act on the system.
00140       //
00141       // @param phiMatrix         State transition matrix.
00142       // @param processNoiseCovariance    Process noise covariance matrix.
00143       // @param measurements      Measurements vector.
00144       // @param measurementsMatrix    Measurements matrix. Called geometry
00145       //                              matrix in GNSS.
00146       // @param measurementsNoiseCovariance   Measurements noise covariance
00147       //                                      matrix.
00148       //
00149       // @return
00150       //  0 if OK
00151       //  -1 if problems arose
00152       //
00153    int SimpleKalmanFilter::Compute( const Matrix<double>& phiMatrix,
00154                                  const Matrix<double>& processNoiseCovariance,
00155                                     const Vector<double>& measurements,
00156                                     const Matrix<double>& measurementsMatrix,
00157                             const Matrix<double>& measurementsNoiseCovariance )
00158       throw(InvalidSolver)
00159    {
00160 
00161       try
00162       {
00163          Predict( phiMatrix,
00164                   xhat,
00165                   processNoiseCovariance );
00166 
00167          Correct( measurements,
00168                   measurementsMatrix,
00169                   measurementsNoiseCovariance );
00170       }
00171       catch(InvalidSolver e)
00172       {
00173          GPSTK_THROW(e);
00174          return -1;
00175       }
00176 
00177       return 0;
00178 
00179    }  // End of method 'SimpleKalmanFilter::Compute()'
00180 
00181 
00182 
00183       // Compute the a posteriori estimate of the system state, as well as
00184       // the a posteriori estimate error variance. Version for
00185       // one-dimensional systems.
00186       //
00187       // @param phiValue          State transition gain.
00188       // @param controlGain       Control gain.
00189       // @param controlInput      Control input value.
00190       // @param processNoiseVariance    Process noise variance.
00191       // @param measurement       Measurement value.
00192       // @param measurementsGain  Measurements gain.
00193       // @param measurementsNoiseVariance   Measurements noise variance.
00194       //
00195       // @return
00196       //  0 if OK
00197       //  -1 if problems arose
00198       //
00199    int SimpleKalmanFilter::Compute( const double& phiValue,
00200                                     const double& controlGain,
00201                                     const double& controlInput,
00202                                     const double& processNoiseVariance,
00203                                     const double& measurement,
00204                                     const double& measurementsGain,
00205                                     const double& measurementsNoiseVariance )
00206       throw(InvalidSolver)
00207    {
00208 
00209       try
00210       {
00211          Predict( phiValue,
00212                   xhat(0),
00213                   controlGain,
00214                   controlInput,
00215                   processNoiseVariance );
00216 
00217          Correct( measurement,
00218                   measurementsGain,
00219                   measurementsNoiseVariance );
00220       }
00221       catch(InvalidSolver e)
00222       {
00223          GPSTK_THROW(e);
00224          return -1;
00225       }
00226 
00227       return 0;
00228 
00229    }  // End of method 'SimpleKalmanFilter::Compute()'
00230 
00231 
00232 
00233       // Compute the a posteriori estimate of the system state, as well as
00234       // the a posteriori estimate error variance. Version for
00235       // one-dimensional systems without control input on the system.
00236       //
00237       // @param phiValue          State transition gain.
00238       // @param processNoiseVariance    Process noise variance.
00239       // @param measurement       Measurement value.
00240       // @param measurementsGain  Measurements gain.
00241       // @param measurementsNoiseVariance   Measurements noise variance.
00242       //
00243       // @return
00244       //  0 if OK
00245       //  -1 if problems arose
00246       //
00247    int SimpleKalmanFilter::Compute( const double& phiValue,
00248                                     const double& processNoiseVariance,
00249                                     const double& measurement,
00250                                     const double& measurementsGain,
00251                                     const double& measurementsNoiseVariance )
00252       throw(InvalidSolver)
00253    {
00254 
00255       try
00256       {
00257          Predict( phiValue,
00258                   xhat(0),
00259                   processNoiseVariance );
00260 
00261          Correct( measurement,
00262                   measurementsGain,
00263                   measurementsNoiseVariance );
00264       }
00265       catch(InvalidSolver e)
00266       {
00267          GPSTK_THROW(e);
00268          return -1;
00269       }
00270 
00271       return 0;
00272 
00273    }  // End of method 'SimpleKalmanFilter::Compute()'
00274 
00275 
00276 
00277       /* Predicts (or "time updates") the a priori estimate of the
00278        * system state, as well as the a priori estimate error variance.
00279        * Version for one-dimensional systems.
00280        *
00281        * @param phiValue          State transition gain.
00282        * @param previousState     Previous system state. It is the last
00283        *                          computed xhat.
00284        * @param controlGain       Control gain.
00285        * @param controlInput      Control input value.
00286        * @param processNoiseVariance    Process noise variance.
00287        *
00288        * @return
00289        *  0 if OK
00290        *  -1 if problems arose
00291        */
00292    int SimpleKalmanFilter::Predict( const double& phiValue,
00293                                     const double& previousState,
00294                                     const double& controlGain,
00295                                     const double& controlInput,
00296                                     const double& processNoiseVariance )
00297       throw(InvalidSolver)
00298    {
00299 
00300          // Create dummy matrices and vectors and call the full
00301          // Predict() method
00302       Matrix<double> dummyPhiMatrix(1,1,phiValue);
00303       Vector<double> dummyPreviousState(1,previousState);
00304       Matrix<double> dummyControMatrix(1,1,controlGain);
00305       Vector<double> dummyControlInput(1,controlInput);
00306       Matrix<double> dummyProcessNoiseCovariance(1,1,processNoiseVariance);
00307 
00308       return ( Predict( dummyPhiMatrix,
00309                         dummyPreviousState,
00310                         dummyControMatrix,
00311                         dummyControlInput,
00312                         dummyProcessNoiseCovariance ) );
00313 
00314    }  // End of method 'SimpleKalmanFilter::Predict()'
00315 
00316 
00317 
00318       /* Predicts (or "time updates") the a priori estimate of the
00319        * system state, as well as the a priori estimate error
00320        * covariance matrix.
00321        * This version assumes that no control inputs act on the system.
00322        *
00323        * @param phiMatrix         State transition matrix.
00324        * @param previousState     Previous system state vector. It is
00325        *                          the last computed xhat.
00326        * @param processNoiseCovariance    Process noise covariance matrix.
00327        *
00328        * @return
00329        *  0 if OK
00330        *  -1 if problems arose
00331        */
00332    int SimpleKalmanFilter::Predict( const Matrix<double>& phiMatrix,
00333                                     const Vector<double>& previousState,
00334                                 const Matrix<double>& processNoiseCovariance )
00335       throw(InvalidSolver)
00336    {
00337 
00338          // Create dummy matrices and vectors and call the full
00339          // Predict() method
00340       int stateRow(previousState.size());
00341 
00342       Matrix<double> dummyControMatrix(stateRow,1,0.0);
00343       Vector<double> dummyControlInput(1,0.0);
00344 
00345       return ( Predict( phiMatrix,
00346                         previousState,
00347                         dummyControMatrix,
00348                         dummyControlInput,
00349                         processNoiseCovariance ) );
00350 
00351    }  // End of method 'SimpleKalmanFilter::Predict()'
00352 
00353 
00354 
00355       /* Predicts (or "time updates") the a priori estimate of the
00356        * system state, as well as the a priori estimate error variance.
00357        * Version for one-dimensional systems and no control input acting
00358        * on the system.
00359        *
00360        * @param phiValue          State transition gain.
00361        * @param previousState     Previous system state. It is the last
00362        *                          computed xhat.
00363        * @param processNoiseVariance    Process noise variance.
00364        *
00365        * @return
00366        *  0 if OK
00367        *  -1 if problems arose
00368        */
00369    int SimpleKalmanFilter::Predict( const double& phiValue,
00370                                     const double& previousState,
00371                                     const double& processNoiseVariance )
00372       throw(InvalidSolver)
00373    {
00374 
00375          // Create dummy matrices and vectors and call the full
00376          // Predict() method
00377       Matrix<double> dummyPhiMatrix(1,1,phiValue);
00378       Vector<double> dummyPreviousState(1,previousState);
00379       Matrix<double> dummyControMatrix(1,1,0.0);
00380       Vector<double> dummyControlInput(1,0.0);
00381       Matrix<double> dummyProcessNoiseCovariance(1,1,processNoiseVariance);
00382 
00383       return ( Predict( dummyPhiMatrix,
00384                         dummyPreviousState,
00385                         dummyControMatrix,
00386                         dummyControlInput,
00387                         dummyProcessNoiseCovariance ) );
00388 
00389    }  // End of method 'SimpleKalmanFilter::Predict()'
00390 
00391 
00392 
00393       // Predicts (or "time updates") the a priori estimate of the system
00394       // state, as well as the a priori estimate error covariance matrix.
00395       //
00396       // @param phiMatrix         State transition matrix.
00397       // @param previousState     Previous system state vector. It is the
00398       //                          last computed xhat.
00399       // @param controlMatrix     Control matrix.
00400       // @param controlInput      Control input vector.
00401       // @param processNoiseCovariance    Process noise covariance matrix.
00402       //
00403       // @return
00404       //  0 if OK
00405       //  -1 if problems arose
00406       //
00407    int SimpleKalmanFilter::Predict( const Matrix<double>& phiMatrix,
00408                                     const Vector<double>& previousState,
00409                                     const Matrix<double>& controlMatrix,
00410                                     const Vector<double>& controlInput,
00411                                  const Matrix<double>& processNoiseCovariance )
00412       throw(InvalidSolver)
00413    {
00414          // Let's check sizes before start
00415       int aposterioriStateRow(xhat.size());
00416       int controlInputRow(controlInput.size());
00417 
00418       int phiCol(phiMatrix.cols());
00419       int phiRow(phiMatrix.rows());
00420 
00421       int controlCol(controlMatrix.cols());
00422       int controlRow(controlMatrix.rows());
00423 
00424       int processNoiseRow(processNoiseCovariance.rows());
00425 
00426       if ( phiCol != phiRow )
00427       {
00428          InvalidSolver e("Predict(): State transition matrix is not square, \
00429 and it must be.");
00430          GPSTK_THROW(e);
00431       }
00432 
00433       if ( phiCol != aposterioriStateRow )
00434       {
00435          InvalidSolver e("Predict(): Sizes of state transition matrix and \
00436 a posteriori state estimation vector do not match.");
00437          GPSTK_THROW(e);
00438       }
00439 
00440       if ( controlCol != controlInputRow )
00441       {
00442          InvalidSolver e("Predict(): Sizes of control matrix and a control \
00443 input vector do not match.");
00444          GPSTK_THROW(e);
00445       }
00446 
00447       if ( aposterioriStateRow != controlRow )
00448       {
00449          InvalidSolver e("Predict(): Sizes of control matrix and a \
00450 posteriori state estimation vector do not match.");
00451          GPSTK_THROW(e);
00452       }
00453 
00454       if ( phiRow != processNoiseRow )
00455       {
00456          InvalidSolver e("Predict(): Sizes of state transition matrix and \
00457 process noise covariance matrix do not match.");
00458          GPSTK_THROW(e);
00459       }
00460 
00461          // After checking sizes, lets' do the real prediction work
00462       try
00463       {
00464             // Compute the a priori state vector
00465          xhatminus = phiMatrix*xhat + controlMatrix * controlInput;
00466 
00467          Matrix<double> phiT(transpose(phiMatrix));
00468 
00469             // Compute the a priori estimate error covariance matrix
00470          Pminus = phiMatrix*P*phiT + processNoiseCovariance;
00471       }
00472       catch(...)
00473       {
00474          InvalidSolver e("Predict(): Unable to predict next state.");
00475          GPSTK_THROW(e);
00476          return -1;
00477       }
00478 
00479       return 0;
00480 
00481    }  // End of method 'SimpleKalmanFilter::Predict()'
00482 
00483 
00484 
00485       // Corrects (or "measurement updates") the a posteriori estimate of
00486       // the system state vector, as well as the a posteriori estimate error
00487       // covariance matrix, using as input the predicted a priori state vector
00488       // and error covariance matrix, plus measurements and associated
00489       // matrices.
00490       //
00491       // @param measurements      Measurements vector.
00492       // @param measurementsMatrix    Measurements matrix. Called geometry
00493       //                              matrix in GNSS.
00494       // @param measurementsNoiseCovariance   Measurements noise covariance
00495       //                                      matrix.
00496       //
00497       // @return
00498       //  0 if OK
00499       //  -1 if problems arose
00500       //
00501    int SimpleKalmanFilter::Correct( const Vector<double>& measurements,
00502                                     const Matrix<double>& measurementsMatrix,
00503                            const Matrix<double>& measurementsNoiseCovariance )
00504       throw(InvalidSolver)
00505    {
00506          // Let's check sizes before start
00507       int measRow(measurements.size());
00508       int aprioriStateRow(xhatminus.size());
00509 
00510       int mMRow(measurementsMatrix.rows());
00511 
00512       int mNCCol(measurementsNoiseCovariance.cols());
00513       int mNCRow(measurementsNoiseCovariance.rows());
00514 
00515       int pMCol(Pminus.cols());
00516       int pMRow(Pminus.rows());
00517 
00518       if ( ( mNCCol != mNCRow ) || 
00519            ( pMCol != pMRow )      )
00520       {
00521          InvalidSolver e("Correct(): Either Pminus or measurement covariance \
00522 matrices are not square, and therefore not invertible.");
00523          GPSTK_THROW(e);
00524       }
00525 
00526       if ( mMRow != mNCRow )
00527       {
00528          InvalidSolver e("Correct(): Sizes of measurements matrix and \
00529 measurements noise covariance matrix do not match.");
00530          GPSTK_THROW(e);
00531       }
00532 
00533       if ( mNCCol != measRow )
00534       {
00535          InvalidSolver e("Correct(): Sizes of measurements matrix and \
00536 measurements vector do not match.");
00537          GPSTK_THROW(e);
00538       }
00539 
00540       if ( pMCol != aprioriStateRow )
00541       {
00542          InvalidSolver e("Correct(): Sizes of a priori error covariance \
00543 matrix and a priori state estimation vector do not match.");
00544          GPSTK_THROW(e);
00545       }
00546 
00547          // After checking sizes, let's do the real correction work
00548       Matrix<double> invR;
00549       Matrix<double> invPMinus;
00550       Matrix<double> measMatrixT( transpose(measurementsMatrix) );
00551 
00552       try
00553       {
00554 
00555          invR = inverseChol(measurementsNoiseCovariance);
00556 
00557       }
00558       catch(...)
00559       {
00560          InvalidSolver e("Correct(): Unable to compute invR matrix.");
00561          GPSTK_THROW(e);
00562          return -1;
00563       }
00564 
00565       try
00566       {
00567 
00568          invPMinus = inverseChol(Pminus);
00569 
00570       }
00571       catch(...)
00572       {
00573          InvalidSolver e("Correct(): Unable to compute invPMinus matrix.");
00574          GPSTK_THROW(e);
00575          return -1;
00576       }
00577 
00578       try
00579       {
00580 
00581          Matrix<double> invTemp( measMatrixT*invR*measurementsMatrix +
00582                                  invPMinus );
00583 
00584             // Compute the a posteriori error covariance matrix
00585          P = inverseChol( invTemp );
00586 
00587       }
00588       catch(...)
00589       {
00590          InvalidSolver e("Correct(): Unable to compute P matrix.");
00591          GPSTK_THROW(e);
00592          return -1;
00593       }
00594 
00595       try
00596       {
00597 
00598             // Compute the a posteriori state estimation
00599          xhat = P * ( (measMatrixT * invR * measurements) + 
00600                       (invPMinus * xhatminus) );
00601 
00602       }
00603       catch(Exception e)
00604       {
00605          InvalidSolver eis("Correct(): Unable to compute xhat.");
00606          GPSTK_THROW(eis);
00607          return -1;
00608       }
00609 
00610       xhatminus = xhat;
00611       Pminus = P;
00612 
00613       return 0;
00614 
00615    }  // End of method 'SimpleKalmanFilter::Correct()'
00616 
00617 
00618 
00619       /* Corrects (or "measurement updates") the a posteriori estimate
00620        * of the system state value, as well as the a posteriori estimate
00621        * error variance, using as input the predicted a priori state and
00622        * error variance values, plus measurement and associated gain and
00623        * variance. Version for one-dimensional systems.
00624        *
00625        * @param measurement       Measurement value.
00626        * @param measurementsGain  Measurements gain.
00627        * @param measurementsNoiseVariance   Measurements noise variance.
00628        *
00629        * @return
00630        *  0 if OK
00631        *  -1 if problems arose
00632        */
00633    int SimpleKalmanFilter::Correct( const double& measurement,
00634                                     const double& measurementsGain,
00635                                     const double& measurementsNoiseVariance )
00636       throw(InvalidSolver)
00637    {
00638 
00639          // Create dummy matrices and vectors and call the full
00640          // Correct() method
00641       Vector<double> dummyMeasurements(1,measurement);
00642       Matrix<double> dummyMeasurementsMatrix(1,1,measurementsGain);
00643       Matrix<double> dummyMeasurementsNoise(1,1,measurementsNoiseVariance);
00644 
00645       return ( Correct( dummyMeasurements,
00646                         dummyMeasurementsMatrix,
00647                         dummyMeasurementsNoise ) );
00648 
00649    }  // End of method 'SimpleKalmanFilter::Correct()'
00650 
00651 
00652 
00653 
00654 }  // End of namespace gpstk

Generated on Tue May 22 03:31:01 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1