00001
00002
00003 #ifndef FILTER_KALMAN_FILTER_HPP
00004 #define FILTER_KALMAN_FILTER_HPP
00005
00006 #include <iostream>
00007
00008 #include "boost/date_time/posix_time/posix_time_types.hpp"
00009
00010 #include "kernel/jafarDebug.hpp"
00011 #include "kernel/dataLog.hpp"
00012
00013 #include "jmath/jblas.hpp"
00014 #include "jmath/gaussianVector.hpp"
00015
00016 #include "filter/filterException.hpp"
00017 #include "filter/predictModel.hpp"
00018 #include "filter/observeModel.hpp"
00019 #include "filter/constraintModel.hpp"
00020
00021 namespace jafar {
00022 namespace filter {
00023
00029 class BaseKalmanFilter : public jafar::kernel::DataLoggable {
00030
00031 public:
00032
00034 enum CovUpdateType {SIMPLE,
00035 STANDARD,
00036 JOSEPH
00041 };
00042
00044 enum ConsistencyCheckLevel {CONSISTENCY_NONE,
00045 CONSISTENCY_WARNING,
00046 CONSISTENCY_EXCEPTION
00047 };
00048
00049 protected:
00050
00052 CovUpdateType covUpdateType;
00053
00055 jblas::vec x;
00056
00058 jblas::sym_mat P;
00059
00061 boost::posix_time::time_duration p_curTime;
00062
00064 jblas::mat K;
00065
00067 jblas::mat KH_tmp;
00068
00070 ConsistencyCheckLevel consistencyCheckLevel;
00072 double chi2Threshold;
00073
00077 template<class Vec>
00078 void checkConsistency(Vec const& y, jblas::sym_mat const& Sinv)
00079 {
00080 if (consistencyCheckLevel == CONSISTENCY_NONE)
00081 return;
00082
00083 JFR_PRECOND(Sinv.size1() == y.size() && Sinv.size2() == y.size(),
00084 "BaseKalmanFilter::checkConsistency: invalid size of S");
00085
00086 using namespace ublas;
00087 double ySiy = inner_prod(y, prod(Sinv, y) );
00088 checkConsistency(y, Sinv, ySiy);
00089 }
00090
00091 void checkConsistency(double y, double Sinv) {
00092 if (consistencyCheckLevel == CONSISTENCY_NONE)
00093 return;
00094
00095 double ySiy = y * Sinv * y;
00096 checkConsistency(y, Sinv, ySiy);
00097 }
00098
00099 template<typename YType, typename SinvType>
00100 void checkConsistency(YType y, SinvType Sinv, double ySiy) {
00101 if (ySiy > chi2Threshold) {
00102 switch(consistencyCheckLevel) {
00103 case CONSISTENCY_NONE:
00104
00105 break;
00106 case CONSISTENCY_WARNING:
00107 JFR_WARNING("ySiy=" << ySiy << " threshold=" << chi2Threshold
00108 << " y=" << y << " Sinv=" << Sinv << ")");
00109 break;
00110 case CONSISTENCY_EXCEPTION:
00111 std::ostringstream s;
00112 s << "ySiy=" << ySiy << " threshold=" << chi2Threshold
00113 << " y=" << y << " Sinv=" << Sinv << ")";
00114 throw InconsistentUpdateException(ySiy, chi2Threshold, s.str(), __FILE__, __LINE__);
00115 break;
00116 }
00117 }
00118 }
00119
00120
00121 void writeLogHeader(jafar::kernel::DataLogger& log) const;
00122 void writeLogData(jafar::kernel::DataLogger& log) const;
00123
00124 public:
00125
00129 BaseKalmanFilter(std::size_t size_);
00130
00131 virtual ~BaseKalmanFilter();
00132
00133 jblas::vec const& getX() const {return x;};
00134 jblas::vec& getX() {return x;};
00135 jblas::sym_mat const& getP() const {return P;};
00136 jblas::sym_mat& getP() {return P;};
00137
00139 void clear();
00140
00141 boost::posix_time::time_duration const& getCurrentTime() const {return p_curTime;}
00142
00143 void setCovUpdateType(CovUpdateType covUpdateType_);
00144 CovUpdateType getCovUpdateType() const;
00145
00146 void setupConsistencyCheck(ConsistencyCheckLevel level_,
00147 double chi2Threshold_)
00148 {
00149 consistencyCheckLevel = level_; chi2Threshold = chi2Threshold_;
00150 }
00151
00152 ConsistencyCheckLevel getConsistencyCheckLevel() const
00153 {
00154 return consistencyCheckLevel;
00155 }
00156
00157 double getChi2Threshold() const
00158 {
00159 return chi2Threshold;
00160 }
00161
00162
00165 void init(const jblas::vec& state_, const jblas::sym_mat& cov_,
00166 boost::posix_time::time_duration const& curTime);
00167
00171 void init(const jblas::vec& state_, const jblas::sym_mat& cov_);
00172
00175 void init(boost::posix_time::time_duration const& curTime);
00176
00179 virtual std::size_t sizeState() const {return x.size();};
00180
00181
00182
00183 };
00184
00189 class KalmanFilter : public BaseKalmanFilter {
00190
00191 public :
00192
00196 KalmanFilter(std::size_t size_);
00197
00198 virtual ~KalmanFilter();
00199
00204 void predict(const LinearPredictModel& m_);
00205
00206 #ifndef SWIG
00207
00211 void predict(LinearCommandPredictModel& m_, jblas::vec const& u_);
00212 #endif // SWIG
00213
00218 void update(LinearObserveModel& m_, jblas::vec& z_);
00219
00220 protected :
00221
00227 void updateLinear(const jblas::mat_range& H_,
00228 const jblas::vec_range& z_, double R_);
00229
00230 };
00231
00232 #ifndef SWIG
00233
00238 class ExtendedKalmanFilter : public KalmanFilter {
00239
00240 public :
00241
00242 ExtendedKalmanFilter(std::size_t n_);
00243
00244 virtual ~ExtendedKalmanFilter();
00245
00250 void predict(JacobianPredictModel& m_);
00251
00256 void predict(JacobianCommandPredictModel& m_, jblas::vec const& u_);
00257
00263 void update(JacobianObserveModel& m_, const jblas::vec& z_);
00264
00265 protected:
00266
00273 void updateExtended(const jblas::mat_range& H_,
00274 double y_, double R_);
00275
00276 };
00277
00278
00279
00290 class ExtendedKalmanFilterImplicit : public ExtendedKalmanFilter
00291 {
00292 public :
00293
00294 ExtendedKalmanFilterImplicit(std::size_t n_);
00295
00296 virtual ~ExtendedKalmanFilterImplicit();
00297
00298
00305 void update(JacobianImplicitObserveModel& m_,
00306 const jblas::vec& z_);
00307
00308 };
00309
00310
00311
00312
00325 class BlockExtendedKalmanFilter : public BaseKalmanFilter {
00326
00327 public:
00328
00329 jblas::vec_range* x_r;
00330 jblas::sym_mat_range* P_r;
00331
00332 BlockExtendedKalmanFilter(std::size_t sizeMax_, std::size_t size_);
00333
00334 virtual ~BlockExtendedKalmanFilter();
00335
00336 inline std::size_t sizeStateMax() const {return x.size();};
00337 virtual inline std::size_t sizeState() const {return x_r->size();};
00338
00339 void softResize(std::size_t size_);
00340
00345 void predict(std::size_t index1_, std::size_t index2_,
00346 LinearPredictModel const& m_);
00347
00352 void predict(std::size_t index1_, std::size_t index2_,
00353 JacobianBlockPredictModel& m_);
00354
00359 void predict(std::size_t index1_, std::size_t index2_,
00360 JacobianBlockCommandPredictModel& m_,
00361 jblas::vec const& u_);
00362
00363 void update(LinearObserveModel& m_, std::size_t index, const jblas::vec& z_);
00364
00369 void update(JacobianObserveModel& m_, std::size_t index, jblas::vec const& z_);
00370
00371 void update(JacobianObserveModel& m_,
00372 std::size_t index_,
00373 jblas::vec_range& x_,
00374 jblas::sym_mat_range& P_,
00375 jblas::vec const& z_);
00376
00377
00378
00379
00380
00381 void update(BlockObserveModel& m_,
00382 std::size_t index1_, std::size_t index2_,
00383 jblas::vec_range& x1_,
00384 jblas::vec_range& x2_,
00385 jblas::sym_mat_range& P1_,
00386 jblas::sym_mat_range& P2_,
00387 const jblas::vec& z_,
00388 jmath::GaussianVector& zPred);
00389
00390 void applyConstraint(JacobianStrongConstraintModel& model,
00391 std::size_t index_);
00392
00393 void applyConstraint(JacobianStrongConstraintModel& model,
00394 std::size_t index_,
00395 jblas::vec_range& x_,
00396 jblas::sym_mat_range& P_);
00397
00416 double computeMahalanobisDistance(LinearObserveModel& m_,
00417 std::size_t index_,
00418 const jblas::vec& z_);
00419
00420 double computeMahalanobisDistance(LinearObserveModel& m_,
00421 const jblas::vec_range& x_,
00422 const jblas::sym_mat_range& P_,
00423 const jblas::vec& z_);
00424
00425 double computeMahalanobisDistance(BlockObserveModel& m_,
00426 std::size_t index1_,
00427 std::size_t index2_,
00428 const jblas::vec_range& x1_,
00429 const jblas::vec_range& x2_,
00430 const jblas::sym_mat_range& P1_,
00431 const jblas::sym_mat_range& P2_,
00432 const jblas::vec& z_);
00433 protected:
00434
00435 jblas::mat_range* K_r;
00436 jblas::mat_range* KH_tmp_r;
00437
00440 void updateBlockExtended(std::size_t index_,
00441 const jblas::sym_mat_range& P_,
00442 const jblas::sym_mat_range& Pcol_,
00443 const jblas::mat_range& H_,
00444 double y_, double R_);
00445
00446 void updateBlockExtended(std::size_t index_,
00447 const jblas::sym_mat_range& P_,
00448 const jblas::sym_mat_range& Pcol_,
00449 const jblas::mat& H_,
00450 jblas::vec const& y,
00451 jblas::sym_mat const& R_);
00452
00455 void updateBlockExtended(std::size_t index1_, std::size_t index2_,
00456 const jblas::sym_mat_range& P1_,
00457 const jblas::sym_mat_range& P2_,
00458 const jblas::sym_mat_range& P12_,
00459 const jblas::sym_mat_range& P21_,
00460 const jblas::sym_mat_range& Pcol1_,
00461 const jblas::sym_mat_range& Pcol2_,
00462 const jblas::mat_range& H1_,
00463 const jblas::mat_range& H2_,
00464 double y_, double R_);
00465
00466 void updateBlockExtended(std::size_t index1_,
00467 std::size_t index2_,
00468 const jblas::sym_mat_range& P1_,
00469 const jblas::sym_mat_range& P2_,
00470 const jblas::sym_mat_range& P12_,
00471 const jblas::sym_mat_range& P21_,
00472 const jblas::sym_mat_range& Pcol1_,
00473 const jblas::sym_mat_range& Pcol2_,
00474 const jblas::mat& H1_,
00475 const jblas::mat& H2_,
00476 jblas::vec const& y_,
00477 jblas::sym_mat const& R_);
00478
00479
00480 friend std::ostream& operator <<(std::ostream& s,
00481 const BlockExtendedKalmanFilter& f_);
00482
00483 };
00484
00485 std::ostream& operator <<(std::ostream& s,
00486 const BlockExtendedKalmanFilter& f_);
00487
00488 #else // SWIG
00489
00490
00491
00492
00493 class ExtendedKalmanFilter : public BaseKalmanFilter {};
00494
00495 class ExtendedKalmanFilterImplicit : public ExtendedKalmanFilter {};
00496
00497 class BlockExtendedKalmanFilter : public ExtendedKalmanFilter {};
00498
00499 #endif // SWIG
00500
00501 }
00502 }
00503
00504 #endif // FILTER_KALMAN_FILTER_HPP