00001 #pragma ident "$Id: SimpleKalmanFilter.cpp 2570 2011-04-21 17:33:49Z yanweignss $"
00002
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "SimpleKalmanFilter.hpp"
00033 #include "MatrixFunctors.hpp"
00034
00035
00036 namespace gpstk
00037 {
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
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 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
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 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
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 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
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 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
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 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
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 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
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
00301
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 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
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
00339
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 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369 int SimpleKalmanFilter::Predict( const double& phiValue,
00370 const double& previousState,
00371 const double& processNoiseVariance )
00372 throw(InvalidSolver)
00373 {
00374
00375
00376
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 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
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
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
00462 try
00463 {
00464
00465 xhatminus = phiMatrix*xhat + controlMatrix * controlInput;
00466
00467 Matrix<double> phiT(transpose(phiMatrix));
00468
00469
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 }
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 int SimpleKalmanFilter::Correct( const Vector<double>& measurements,
00502 const Matrix<double>& measurementsMatrix,
00503 const Matrix<double>& measurementsNoiseCovariance )
00504 throw(InvalidSolver)
00505 {
00506
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
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
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
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 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 int SimpleKalmanFilter::Correct( const double& measurement,
00634 const double& measurementsGain,
00635 const double& measurementsNoiseVariance )
00636 throw(InvalidSolver)
00637 {
00638
00639
00640
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 }
00650
00651
00652
00653
00654 }