00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef CKalmanFilterCapable_H
00029 #define CKalmanFilterCapable_H
00030
00031 #include <mrpt/math/CMatrixFixedNumeric.h>
00032 #include <mrpt/math/CMatrixTemplateNumeric.h>
00033 #include <mrpt/math/CArray.h>
00034 #include <mrpt/math/utils.h>
00035
00036 #include <mrpt/utils/CTimeLogger.h>
00037 #include <mrpt/utils/CLoadableOptions.h>
00038 #include <mrpt/utils/CDebugOutputCapable.h>
00039 #include <mrpt/utils/stl_extensions.h>
00040 #include <mrpt/system/os.h>
00041 #include <mrpt/utils/CTicTac.h>
00042 #include <mrpt/utils/CFileOutputStream.h>
00043 #include <mrpt/utils/TEnumType.h>
00044
00045 #include <mrpt/bayes/link_pragmas.h>
00046
00047
00048 namespace mrpt
00049 {
00050 namespace bayes
00051 {
00052 using namespace mrpt::utils;
00053 using namespace mrpt::math;
00054 using namespace mrpt;
00055 using namespace std;
00056
00057
00058
00059
00060
00061
00062 enum TKFMethod {
00063 kfEKFNaive = 0,
00064 kfEKFAlaDavison,
00065 kfIKFFull,
00066 kfIKF
00067 };
00068
00069
00070 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE> class CKalmanFilterCapable;
00071
00072 namespace detail {
00073 struct CRunOneKalmanIteration_addNewLandmarks;
00074 }
00075
00076
00077
00078
00079 struct BAYES_IMPEXP TKF_options : public utils::CLoadableOptions
00080 {
00081 TKF_options();
00082
00083 void loadFromConfigFile(
00084 const mrpt::utils::CConfigFileBase &source,
00085 const std::string §ion);
00086
00087
00088 void dumpToTextStream(CStream &out) const;
00089
00090 TKFMethod method;
00091 bool verbose;
00092 int IKF_iterations;
00093 bool enable_profiler;
00094 bool use_analytic_transition_jacobian;
00095 bool use_analytic_observation_jacobian;
00096 bool debug_verify_analytic_jacobians;
00097 double debug_verify_analytic_jacobians_threshold;
00098 };
00099
00100
00101 namespace detail
00102 {
00103
00104 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
00105 inline size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj);
00106
00107 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
00108 inline size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /*FEAT_SIZE*/,ACT_SIZE,KFTYPE> &obj);
00109
00110 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
00111 inline bool isMapEmpty(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj);
00112
00113 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
00114 inline bool isMapEmpty(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /*FEAT_SIZE*/,ACT_SIZE,KFTYPE> &obj);
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE = double>
00146 class CKalmanFilterCapable : public mrpt::utils::CDebugOutputCapable
00147 {
00148 public:
00149 static inline size_t get_vehicle_size() { return VEH_SIZE; }
00150 static inline size_t get_observation_size() { return OBS_SIZE; }
00151 static inline size_t get_feature_size() { return FEAT_SIZE; }
00152 static inline size_t get_action_size() { return ACT_SIZE; }
00153 inline size_t getNumberOfLandmarksInTheMap() const { return detail::getNumberOfLandmarksInMap(*this); }
00154 inline bool isMapEmpty() const { return detail::isMapEmpty(*this); }
00155
00156
00157 typedef KFTYPE kftype;
00158 typedef CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> KFCLASS;
00159
00160
00161 typedef mrpt::dynamicsize_vector<KFTYPE> KFVector;
00162 typedef CMatrixTemplateNumeric<KFTYPE> KFMatrix;
00163
00164 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,VEH_SIZE> KFMatrix_VxV;
00165 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,OBS_SIZE> KFMatrix_OxO;
00166 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,FEAT_SIZE> KFMatrix_FxF;
00167 typedef CMatrixFixedNumeric<KFTYPE,ACT_SIZE,ACT_SIZE> KFMatrix_AxA;
00168
00169 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,OBS_SIZE> KFMatrix_VxO;
00170 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,FEAT_SIZE> KFMatrix_VxF;
00171
00172 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,VEH_SIZE> KFMatrix_FxV;
00173 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,OBS_SIZE> KFMatrix_FxO;
00174
00175 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,FEAT_SIZE> KFMatrix_OxF;
00176 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,VEH_SIZE> KFMatrix_OxV;
00177
00178 typedef CArrayNumeric<KFTYPE,VEH_SIZE> KFArray_VEH;
00179 typedef CArrayNumeric<KFTYPE,ACT_SIZE> KFArray_ACT;
00180 typedef CArrayNumeric<KFTYPE,OBS_SIZE> KFArray_OBS;
00181 typedef typename mrpt::aligned_containers<KFArray_OBS>::vector_t vector_KFArray_OBS;
00182 typedef CArrayNumeric<KFTYPE,FEAT_SIZE> KFArray_FEAT;
00183
00184 inline size_t getStateVectorLength() const { return m_xkk.size(); }
00185
00186
00187
00188
00189 inline void getLandmarkMean(size_t idx, KFArray_FEAT &feat ) const {
00190 ASSERT_(idx<getNumberOfLandmarksInTheMap())
00191 ::memcpy(&feat[0], &m_xkk[VEH_SIZE+idx*FEAT_SIZE], FEAT_SIZE*sizeof(m_xkk[0]));
00192 }
00193
00194
00195
00196 inline void getLandmarkCov(size_t idx, KFMatrix_FxF &feat_cov ) const {
00197 m_pkk.extractMatrix(VEH_SIZE+idx*FEAT_SIZE,VEH_SIZE+idx*FEAT_SIZE,feat_cov);
00198 }
00199
00200 protected:
00201
00202
00203
00204 KFVector m_xkk;
00205 KFMatrix m_pkk;
00206
00207
00208
00209 mrpt::utils::CTimeLogger m_timLogger;
00210
00211
00212
00213
00214
00215
00216
00217
00218 virtual void OnGetAction( KFArray_ACT &out_u ) const = 0;
00219
00220
00221
00222
00223
00224
00225
00226 virtual void OnTransitionModel(
00227 const KFArray_ACT &in_u,
00228 KFArray_VEH &inout_x,
00229 bool &out_skipPrediction
00230 ) const = 0;
00231
00232
00233
00234
00235
00236 virtual void OnTransitionJacobian( KFMatrix_VxV &out_F ) const
00237 {
00238 m_user_didnt_implement_jacobian=true;
00239 }
00240
00241
00242
00243 virtual void OnTransitionJacobianNumericGetIncrements(KFArray_VEH &out_increments) const
00244 {
00245 for (size_t i=0;i<VEH_SIZE;i++) out_increments[i] = 1e-6;
00246 }
00247
00248
00249
00250
00251
00252 virtual void OnTransitionNoise( KFMatrix_VxV &out_Q ) const = 0;
00253
00254
00255
00256
00257
00258
00259
00260
00261 virtual void OnPreComputingPredictions(
00262 const vector_KFArray_OBS &in_all_prediction_means,
00263 mrpt::vector_size_t &out_LM_indices_to_predict ) const
00264 {
00265
00266 const size_t N = this->getNumberOfLandmarksInTheMap();
00267 out_LM_indices_to_predict.resize(N);
00268 for (size_t i=0;i<N;i++) out_LM_indices_to_predict[i]=i;
00269 }
00270
00271
00272
00273
00274
00275 virtual void OnGetObservationNoise(KFMatrix_OxO &out_R) const = 0;
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 virtual void OnGetObservationsAndDataAssociation(
00289 vector_KFArray_OBS &out_z,
00290 mrpt::vector_int &out_data_association,
00291 const vector_KFArray_OBS &in_all_predictions,
00292 const KFMatrix &in_S,
00293 const vector_size_t &in_lm_indices_in_S,
00294 const KFMatrix_OxO &in_R
00295 ) = 0;
00296
00297
00298
00299
00300
00301 virtual void OnObservationModel(
00302 const mrpt::vector_size_t &idx_landmarks_to_predict,
00303 vector_KFArray_OBS &out_predictions
00304 ) const = 0;
00305
00306
00307
00308
00309
00310
00311 virtual void OnObservationJacobians(
00312 const size_t &idx_landmark_to_predict,
00313 KFMatrix_OxV &Hx,
00314 KFMatrix_OxF &Hy
00315 ) const
00316 {
00317 m_user_didnt_implement_jacobian=true;
00318 }
00319
00320
00321
00322 virtual void OnObservationJacobiansNumericGetIncrements(
00323 KFArray_VEH &out_veh_increments,
00324 KFArray_FEAT &out_feat_increments ) const
00325 {
00326 for (size_t i=0;i<VEH_SIZE;i++) out_veh_increments[i] = 1e-6;
00327 for (size_t i=0;i<FEAT_SIZE;i++) out_feat_increments[i] = 1e-6;
00328 }
00329
00330
00331
00332 virtual void OnSubstractObservationVectors(KFArray_OBS &A, const KFArray_OBS &B) const
00333 {
00334 A -= B;
00335 }
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 virtual void OnInverseObservationModel(
00351 const KFArray_OBS & in_z,
00352 KFArray_FEAT & out_yn,
00353 KFMatrix_FxV & out_dyn_dxv,
00354 KFMatrix_FxO & out_dyn_dhn ) const
00355 {
00356 MRPT_START
00357 THROW_EXCEPTION("Inverse sensor model required but not implemented in derived class.")
00358 MRPT_END
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 virtual void OnInverseObservationModel(
00384 const KFArray_OBS & in_z,
00385 KFArray_FEAT & out_yn,
00386 KFMatrix_FxV & out_dyn_dxv,
00387 KFMatrix_FxO & out_dyn_dhn,
00388 KFMatrix_FxF & out_dyn_dhn_R_dyn_dhnT,
00389 bool & out_use_dyn_dhn_jacobian
00390 ) const
00391 {
00392 MRPT_START
00393 OnInverseObservationModel(in_z,out_yn,out_dyn_dxv,out_dyn_dhn);
00394 out_use_dyn_dhn_jacobian=true;
00395 MRPT_END
00396 }
00397
00398
00399
00400
00401
00402
00403 virtual void OnNewLandmarkAddedToMap(
00404 const size_t in_obsIdx,
00405 const size_t in_idxNewFeat )
00406 {
00407
00408 }
00409
00410
00411
00412 virtual void OnNormalizeStateVector()
00413 {
00414
00415 }
00416
00417
00418
00419 virtual void OnPostIteration()
00420 {
00421
00422 }
00423
00424
00425
00426
00427 public:
00428 CKalmanFilterCapable() {}
00429 virtual ~CKalmanFilterCapable() {}
00430
00431 mrpt::utils::CTimeLogger &getProfiler() { return m_timLogger; }
00432
00433 TKF_options KF_options;
00434
00435
00436 private:
00437
00438
00439
00440 vector_KFArray_OBS all_predictions;
00441 vector_size_t predictLMidxs;
00442 KFMatrix dh_dx;
00443 KFMatrix dh_dx_full;
00444 vector_size_t idxs;
00445 KFMatrix S;
00446 KFMatrix Pkk_subset;
00447 vector_KFArray_OBS Z;
00448 KFMatrix K;
00449 KFMatrix S_1;
00450 KFMatrix dh_dx_full_obs;
00451 KFMatrix aux_K_dh_dx;
00452
00453 protected:
00454
00455
00456
00457
00458
00459 void runOneKalmanIteration()
00460 {
00461 MRPT_START
00462
00463 m_timLogger.enable(KF_options.enable_profiler || KF_options.verbose);
00464 m_timLogger.enter("KF:complete_step");
00465
00466 ASSERT_(size_t(m_xkk.size())==m_pkk.getColCount())
00467 ASSERT_(size_t(m_xkk.size())>=VEH_SIZE)
00468
00469
00470
00471
00472 KFArray_ACT u;
00473
00474 m_timLogger.enter("KF:1.OnGetAction");
00475 OnGetAction(u);
00476 m_timLogger.leave("KF:1.OnGetAction");
00477
00478
00479 if (FEAT_SIZE) { ASSERTDEB_( (((m_xkk.size()-VEH_SIZE)/FEAT_SIZE)*FEAT_SIZE)== (m_xkk.size()-VEH_SIZE) ) }
00480
00481
00482
00483
00484 m_timLogger.enter("KF:2.prediction stage");
00485
00486 const size_t N_map = getNumberOfLandmarksInTheMap();
00487
00488 KFArray_VEH xv( &m_xkk[0] );
00489
00490 bool skipPrediction=false;
00491
00492
00493
00494 OnTransitionModel(u, xv, skipPrediction);
00495
00496 if ( !skipPrediction )
00497 {
00498
00499
00500
00501
00502 KFMatrix_VxV dfv_dxv;
00503
00504
00505 m_user_didnt_implement_jacobian=false;
00506 if (KF_options.use_analytic_transition_jacobian)
00507 OnTransitionJacobian(dfv_dxv);
00508
00509 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_transition_jacobian || KF_options.debug_verify_analytic_jacobians)
00510 {
00511 KFArray_VEH xkk_vehicle( &m_xkk[0] );
00512 KFArray_VEH xkk_veh_increments;
00513 OnTransitionJacobianNumericGetIncrements(xkk_veh_increments);
00514
00515 mrpt::math::estimateJacobian(
00516 xkk_vehicle,
00517 &KF_aux_estimate_trans_jacobian,
00518 xkk_veh_increments,
00519 std::make_pair<KFCLASS*,KFArray_ACT>(this,u),
00520 dfv_dxv);
00521
00522 if (KF_options.debug_verify_analytic_jacobians)
00523 {
00524 KFMatrix_VxV dfv_dxv_gt(UNINITIALIZED_MATRIX);
00525 OnTransitionJacobian(dfv_dxv_gt);
00526 if ((dfv_dxv-dfv_dxv_gt).Abs().sumAll()>KF_options.debug_verify_analytic_jacobians_threshold)
00527 {
00528 std::cerr << "[KalmanFilter] ERROR: User analytical transition Jacobians are wrong: \n"
00529 << " Real dfv_dxv: \n" << dfv_dxv << "\n Analytical dfv_dxv:\n" << dfv_dxv_gt << "Diff:\n" << (dfv_dxv-dfv_dxv_gt) << "\n";
00530 THROW_EXCEPTION("ERROR: User analytical transition Jacobians are wrong (More details dumped to cerr)")
00531 }
00532 }
00533
00534 }
00535
00536
00537 KFMatrix_VxV Q;
00538 OnTransitionNoise(Q);
00539
00540
00541
00542
00543
00544 m_pkk.block(0,0,VEH_SIZE,VEH_SIZE) =
00545 Q +
00546 dfv_dxv * m_pkk.block(0,0,VEH_SIZE,VEH_SIZE) * dfv_dxv.transpose();
00547
00548
00549
00550
00551
00552 KFMatrix_VxF aux;
00553 for (size_t i=0 ; i<N_map ; i++)
00554 {
00555
00556 dfv_dxv.multiply_subMatrix(
00557 m_pkk,
00558 aux,
00559 VEH_SIZE+i*FEAT_SIZE,
00560 0,
00561 FEAT_SIZE
00562 );
00563
00564 m_pkk.insertMatrix (0, VEH_SIZE+i*FEAT_SIZE, aux );
00565 m_pkk.insertMatrixTranspose(VEH_SIZE+i*FEAT_SIZE, 0 , aux );
00566 }
00567
00568
00569
00570
00571 for (size_t i=0;i<VEH_SIZE;i++)
00572 m_xkk[i]=xv[i];
00573
00574
00575 OnNormalizeStateVector();
00576
00577 }
00578
00579
00580 const double tim_pred = m_timLogger.leave("KF:2.prediction stage");
00581
00582
00583
00584
00585
00586 m_timLogger.enter("KF:3.predict all obs");
00587
00588 KFMatrix_OxO R;
00589 OnGetObservationNoise(R);
00590
00591
00592
00593 all_predictions.resize(N_map);
00594 OnObservationModel(
00595 mrpt::math::sequenceStdVec<size_t,1>(0,N_map),
00596 all_predictions);
00597
00598 const double tim_pred_obs = m_timLogger.leave("KF:3.predict all obs");
00599
00600 m_timLogger.enter("KF:4.decide pred obs");
00601
00602
00603 predictLMidxs.clear();
00604 if (FEAT_SIZE==0)
00605
00606 predictLMidxs.assign(1,0);
00607 else
00608
00609 OnPreComputingPredictions(all_predictions, predictLMidxs);
00610
00611
00612 m_timLogger.leave("KF:4.decide pred obs");
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 m_timLogger.enter("KF:5.build Jacobians");
00639
00640 size_t N_pred = FEAT_SIZE==0 ?
00641 1 :
00642 predictLMidxs.size();
00643
00644 vector_int data_association;
00645
00646
00647
00648 std::vector<size_t> missing_predictions_to_add;
00649
00650
00651 idxs.clear();
00652 idxs.reserve(VEH_SIZE+N_pred*FEAT_SIZE);
00653 for (size_t i=0;i<VEH_SIZE;i++) idxs.push_back(i);
00654
00655 dh_dx.zeros(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_pred );
00656 dh_dx_full.zeros(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
00657
00658 size_t first_new_pred = 0;
00659
00660 do
00661 {
00662 if (!missing_predictions_to_add.empty())
00663 {
00664 const size_t nNew = missing_predictions_to_add.size();
00665 printf_debug("[KF] *Performance Warning*: %u LMs were not correctly predicted by OnPreComputingPredictions()\n",static_cast<unsigned int>(nNew));
00666
00667 ASSERTDEB_(FEAT_SIZE!=0)
00668 for (size_t j=0;j<nNew;j++)
00669 predictLMidxs.push_back( missing_predictions_to_add[j] );
00670
00671 N_pred = predictLMidxs.size();
00672 missing_predictions_to_add.clear();
00673 }
00674
00675 dh_dx.setSize(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_pred );
00676 dh_dx_full.setSize(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
00677
00678 for (size_t i=first_new_pred;i<N_pred;++i)
00679 {
00680 const size_t lm_idx = FEAT_SIZE==0 ? 0 : predictLMidxs[i];
00681 KFMatrix_OxV Hx(UNINITIALIZED_MATRIX);
00682 KFMatrix_OxF Hy(UNINITIALIZED_MATRIX);
00683
00684
00685 m_user_didnt_implement_jacobian=false;
00686 if (KF_options.use_analytic_observation_jacobian)
00687 OnObservationJacobians(lm_idx,Hx,Hy);
00688
00689 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_observation_jacobian || KF_options.debug_verify_analytic_jacobians)
00690 {
00691 const size_t lm_idx_in_statevector = VEH_SIZE+lm_idx*FEAT_SIZE;
00692
00693 const KFArray_VEH x_vehicle( &m_xkk[0] );
00694 const KFArray_FEAT x_feat( &m_xkk[lm_idx_in_statevector] );
00695
00696 KFArray_VEH xkk_veh_increments;
00697 KFArray_FEAT feat_increments;
00698 OnObservationJacobiansNumericGetIncrements(xkk_veh_increments, feat_increments);
00699
00700 mrpt::math::estimateJacobian(
00701 x_vehicle,
00702 &KF_aux_estimate_obs_Hx_jacobian,
00703 xkk_veh_increments,
00704 std::make_pair<KFCLASS*,size_t>(this,lm_idx),
00705 Hx);
00706
00707 ::memcpy(&m_xkk[0],&x_vehicle[0],sizeof(m_xkk[0])*VEH_SIZE);
00708
00709 mrpt::math::estimateJacobian(
00710 x_feat,
00711 &KF_aux_estimate_obs_Hy_jacobian,
00712 feat_increments,
00713 std::make_pair<KFCLASS*,size_t>(this,lm_idx),
00714 Hy);
00715
00716 ::memcpy(&m_xkk[lm_idx_in_statevector],&x_feat[0],sizeof(m_xkk[0])*FEAT_SIZE);
00717
00718 if (KF_options.debug_verify_analytic_jacobians)
00719 {
00720 KFMatrix_OxV Hx_gt(UNINITIALIZED_MATRIX);
00721 KFMatrix_OxF Hy_gt(UNINITIALIZED_MATRIX);
00722 OnObservationJacobians(lm_idx,Hx_gt,Hy_gt);
00723 if ((Hx-Hx_gt).Abs().sumAll()>KF_options.debug_verify_analytic_jacobians_threshold) {
00724 std::cerr << "[KalmanFilter] ERROR: User analytical observation Hx Jacobians are wrong: \n"
00725 << " Real Hx: \n" << Hx << "\n Analytical Hx:\n" << Hx_gt << "Diff:\n" << Hx-Hx_gt << "\n";
00726 THROW_EXCEPTION("ERROR: User analytical observation Hx Jacobians are wrong (More details dumped to cerr)")
00727 }
00728 if ((Hy-Hy_gt).Abs().sumAll()>KF_options.debug_verify_analytic_jacobians_threshold) {
00729 std::cerr << "[KalmanFilter] ERROR: User analytical observation Hy Jacobians are wrong: \n"
00730 << " Real Hy: \n" << Hy << "\n Analytical Hx:\n" << Hy_gt << "Diff:\n" << Hy-Hy_gt << "\n";
00731 THROW_EXCEPTION("ERROR: User analytical observation Hy Jacobians are wrong (More details dumped to cerr)")
00732 }
00733 }
00734 }
00735
00736 dh_dx.insertMatrix(i*OBS_SIZE,0, Hx);
00737 if (FEAT_SIZE!=0)
00738 dh_dx.insertMatrix(i*OBS_SIZE,VEH_SIZE+i*FEAT_SIZE, Hy);
00739
00740 dh_dx_full.insertMatrix(i*OBS_SIZE,0, Hx);
00741 if (FEAT_SIZE!=0)
00742 {
00743 dh_dx_full.insertMatrix(i*OBS_SIZE,VEH_SIZE+lm_idx*FEAT_SIZE, Hy);
00744
00745 for (size_t k=0;k<FEAT_SIZE;k++)
00746 idxs.push_back(k+VEH_SIZE+FEAT_SIZE*lm_idx);
00747 }
00748 }
00749 m_timLogger.leave("KF:5.build Jacobians");
00750
00751
00752
00753
00754 m_timLogger.enter("KF:6.build S");
00755
00756 S.setSize(N_pred*OBS_SIZE,N_pred*OBS_SIZE);
00757
00758
00759
00760 m_pkk.extractSubmatrixSymmetrical(idxs,Pkk_subset);
00761
00762
00763 dh_dx.multiply_HCHt(Pkk_subset,S);
00764
00765
00766 if ( FEAT_SIZE>0 )
00767 {
00768 for (size_t i=0;i<N_pred;++i)
00769 {
00770 const size_t obs_idx_off = i*OBS_SIZE;
00771 for (size_t j=0;j<OBS_SIZE;j++)
00772 for (size_t k=0;k<OBS_SIZE;k++)
00773 S.get_unsafe(obs_idx_off+j,obs_idx_off+k) += R.get_unsafe(j,k);
00774 }
00775 }
00776 else
00777 {
00778 ASSERTDEB_(S.getColCount() == OBS_SIZE );
00779 S+=R;
00780 }
00781
00782 m_timLogger.leave("KF:6.build S");
00783
00784
00785 Z.clear();
00786
00787 m_timLogger.enter("KF:7.get obs & DA");
00788
00789
00790 OnGetObservationsAndDataAssociation(
00791 Z, data_association,
00792 all_predictions, S, predictLMidxs, R
00793 );
00794 ASSERTDEB_(data_association.size()==Z.size() || (data_association.empty() && FEAT_SIZE==0));
00795
00796
00797
00798
00799 missing_predictions_to_add.clear();
00800 if (FEAT_SIZE!=0)
00801 {
00802 for (size_t i=0;i<data_association.size();++i)
00803 {
00804 if (data_association[i]<0) continue;
00805 const size_t assoc_idx_in_map = static_cast<size_t>(data_association[i]);
00806 const size_t assoc_idx_in_pred = mrpt::utils::find_in_vector(assoc_idx_in_map, predictLMidxs);
00807 if (assoc_idx_in_pred==std::string::npos)
00808 missing_predictions_to_add.push_back(assoc_idx_in_map);
00809 }
00810 }
00811
00812 first_new_pred = N_pred;
00813
00814 } while (!missing_predictions_to_add.empty());
00815
00816
00817 const double tim_obs_DA = m_timLogger.leave("KF:7.get obs & DA");
00818
00819
00820
00821
00822
00823 if ( !Z.empty() )
00824 {
00825 m_timLogger.enter("KF:8.update stage");
00826
00827 switch (KF_options.method)
00828 {
00829
00830
00831
00832 case kfEKFNaive:
00833 case kfIKFFull:
00834 {
00835
00836
00837
00838 vector_int mapIndicesForKFUpdate(data_association.size());
00839 mapIndicesForKFUpdate.resize( std::distance(mapIndicesForKFUpdate.begin(),
00840 std::remove_copy_if(
00841 data_association.begin(),
00842 data_association.end(),
00843 mapIndicesForKFUpdate.begin(),
00844 binder1st<equal_to<int> >(equal_to<int>(),-1) ) ) );
00845
00846 const size_t N_upd = (FEAT_SIZE==0) ?
00847 1 :
00848 mapIndicesForKFUpdate.size();
00849
00850
00851 const size_t nKF_iterations = (KF_options.method==kfEKFNaive) ? 1 : KF_options.IKF_iterations;
00852
00853 const KFVector xkk_0 = m_xkk;
00854
00855
00856 if (N_upd>0)
00857 {
00858 for (size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
00859 {
00860
00861 KFVector ytilde(OBS_SIZE*N_upd);
00862 size_t ytilde_idx = 0;
00863
00864
00865 dh_dx_full_obs.zeros(N_upd*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
00866 KFMatrix S_observed;
00867
00868 if (FEAT_SIZE!=0)
00869 {
00870 vector_size_t S_idxs;
00871 S_idxs.reserve(OBS_SIZE*N_upd);
00872
00873 const size_t row_len = VEH_SIZE + FEAT_SIZE * N_map;
00874
00875 for (size_t i=0;i<data_association.size();++i)
00876 {
00877 if (data_association[i]<0) continue;
00878
00879 const size_t assoc_idx_in_map = static_cast<size_t>(data_association[i]);
00880 const size_t assoc_idx_in_pred = mrpt::utils::find_in_vector(assoc_idx_in_map, predictLMidxs);
00881 ASSERTMSG_(assoc_idx_in_pred!=string::npos, "OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
00882
00883
00884
00885 dh_dx_full_obs.block(S_idxs.size() ,0, OBS_SIZE, row_len)
00886 =
00887 dh_dx_full.block (assoc_idx_in_pred*OBS_SIZE,0, OBS_SIZE, row_len);
00888
00889 for (size_t k=0;k<OBS_SIZE;k++)
00890 S_idxs.push_back(assoc_idx_in_pred*OBS_SIZE+k);
00891
00892
00893 KFArray_OBS ytilde_i = Z[i];
00894 OnSubstractObservationVectors(ytilde_i,all_predictions[predictLMidxs[assoc_idx_in_pred]]);
00895 for (size_t k=0;k<OBS_SIZE;k++)
00896 ytilde[ytilde_idx++] = ytilde_i[k];
00897 }
00898
00899 S.extractSubmatrixSymmetrical(S_idxs,S_observed);
00900 }
00901 else
00902 {
00903 ASSERT_(Z.size()==1 && all_predictions.size()==1)
00904
00905 dh_dx_full_obs = dh_dx_full;
00906 KFArray_OBS ytilde_i = Z[0];
00907 OnSubstractObservationVectors(ytilde_i,all_predictions[0]);
00908 for (size_t k=0;k<OBS_SIZE;k++)
00909 ytilde[ytilde_idx++] = ytilde_i[k];
00910
00911 S_observed = S;
00912 }
00913
00914
00915
00916 m_timLogger.enter("KF:8.update stage:1.FULLKF:build K");
00917
00918 K.setSize(m_pkk.getRowCount(), S_observed.getColCount() );
00919
00920
00921 K.multiply_ABt(m_pkk, dh_dx_full_obs);
00922
00923
00924 S_observed.inv(S_1);
00925 K*=S_1;
00926
00927 m_timLogger.leave("KF:8.update stage:1.FULLKF:build K");
00928
00929
00930 if (nKF_iterations==1)
00931 {
00932 m_timLogger.enter("KF:8.update stage:2.FULLKF:update xkk");
00933 m_xkk += K * ytilde;
00934 m_timLogger.leave("KF:8.update stage:2.FULLKF:update xkk");
00935 }
00936 else
00937 {
00938 m_timLogger.enter("KF:8.update stage:2.FULLKF:iter.update xkk");
00939
00940 KFVector HAx_column;
00941 dh_dx_full_obs.multiply_Ab( m_xkk - xkk_0, HAx_column);
00942
00943 m_xkk = xkk_0;
00944 K.multiply_Ab(
00945 (ytilde-HAx_column),
00946 m_xkk,
00947 true
00948 );
00949
00950 m_timLogger.leave("KF:8.update stage:2.FULLKF:iter.update xkk");
00951 }
00952
00953
00954
00955 if (IKF_iteration == (nKF_iterations-1) )
00956 {
00957 m_timLogger.enter("KF:8.update stage:3.FULLKF:update Pkk");
00958
00959
00960
00961
00962
00963
00964 aux_K_dh_dx.multiply(K,dh_dx_full_obs);
00965
00966
00967 const size_t stat_len = aux_K_dh_dx.getColCount();
00968 for (size_t r=0;r<stat_len;r++)
00969 for (size_t c=0;c<stat_len;c++)
00970 if (r==c)
00971 aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c) + kftype(1);
00972 else aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c);
00973
00974 m_pkk.multiply_result_is_symmetric(aux_K_dh_dx, m_pkk );
00975
00976 m_timLogger.leave("KF:8.update stage:3.FULLKF:update Pkk");
00977 }
00978 }
00979 }
00980 }
00981 break;
00982
00983
00984
00985
00986 case kfEKFAlaDavison:
00987 {
00988
00989 for (size_t obsIdx=0;obsIdx<Z.size();obsIdx++)
00990 {
00991
00992 bool doit;
00993 size_t idxInTheFilter=0;
00994
00995 if (data_association.empty())
00996 {
00997 doit = true;
00998 }
00999 else
01000 {
01001 doit = data_association[obsIdx] >= 0;
01002 if (doit)
01003 idxInTheFilter = data_association[obsIdx];
01004 }
01005
01006 if ( doit )
01007 {
01008 m_timLogger.enter("KF:8.update stage:1.ScalarAtOnce.prepare");
01009
01010
01011 const size_t idx_off = VEH_SIZE + idxInTheFilter*FEAT_SIZE;
01012
01013
01014 vector_KFArray_OBS pred_obs;
01015 OnObservationModel( vector_size_t(1,idxInTheFilter),pred_obs);
01016 ASSERTDEB_(pred_obs.size()==1);
01017
01018
01019 KFArray_OBS ytilde = Z[obsIdx];
01020 OnSubstractObservationVectors(ytilde, pred_obs[0]);
01021
01022
01023
01024
01025
01026 KFMatrix_OxV Hx(UNINITIALIZED_MATRIX);
01027 KFMatrix_OxF Hy(UNINITIALIZED_MATRIX);
01028 const size_t i_idx_in_preds = mrpt::utils::find_in_vector(idxInTheFilter,predictLMidxs);
01029 ASSERTMSG_(i_idx_in_preds!=string::npos, "OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
01030 dh_dx.extractMatrix(i_idx_in_preds*OBS_SIZE,0, Hx);
01031 dh_dx.extractMatrix(i_idx_in_preds*OBS_SIZE,VEH_SIZE+i_idx_in_preds*OBS_SIZE, Hy);
01032
01033
01034 m_timLogger.leave("KF:8.update stage:1.ScalarAtOnce.prepare");
01035
01036
01037 for (size_t j=0;j<OBS_SIZE;j++)
01038 {
01039 m_timLogger.enter("KF:8.update stage:2.ScalarAtOnce.update");
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053 #if defined(_DEBUG)
01054 {
01055
01056 for (size_t a=0;a<OBS_SIZE;a++)
01057 for (size_t b=0;b<OBS_SIZE;b++)
01058 if ( a!=b )
01059 if (R(a,b)!=0)
01060 THROW_EXCEPTION("This KF algorithm assumes independent noise components in the observation (matrix R). Select another KF algorithm.")
01061 }
01062 #endif
01063
01064 KFTYPE Sij = R.get_unsafe(j,j);
01065
01066
01067 for (size_t k=0;k<VEH_SIZE;k++)
01068 {
01069 KFTYPE accum = 0;
01070 for (size_t q=0;q<VEH_SIZE;q++)
01071 accum += Hx.get_unsafe(j,q) * m_pkk.get_unsafe(q,k);
01072 Sij+= Hx.get_unsafe(j,k) * accum;
01073 }
01074
01075
01076 KFTYPE term2=0;
01077 for (size_t k=0;k<VEH_SIZE;k++)
01078 {
01079 KFTYPE accum = 0;
01080 for (size_t q=0;q<FEAT_SIZE;q++)
01081 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,k);
01082 term2+= Hx.get_unsafe(j,k) * accum;
01083 }
01084 Sij += 2 * term2;
01085
01086
01087 for (size_t k=0;k<FEAT_SIZE;k++)
01088 {
01089 KFTYPE accum = 0;
01090 for (size_t q=0;q<FEAT_SIZE;q++)
01091 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,idx_off+k);
01092 Sij+= Hy.get_unsafe(j,k) * accum;
01093 }
01094
01095
01096
01097 size_t N = m_pkk.getColCount();
01098 vector<KFTYPE> Kij( N );
01099
01100 for (size_t k=0;k<N;k++)
01101 {
01102 KFTYPE K_tmp = 0;
01103
01104
01105 size_t q;
01106 for (q=0;q<VEH_SIZE;q++)
01107 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(j,q);
01108
01109
01110 for (q=0;q<FEAT_SIZE;q++)
01111 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(j,q);
01112
01113 Kij[k] = K_tmp / Sij;
01114 }
01115
01116
01117
01118
01119 for (size_t k=0;k<N;k++)
01120 m_xkk[k] += Kij[k] * ytilde[j];
01121
01122
01123
01124 {
01125 for (size_t k=0;k<N;k++)
01126 {
01127 for (size_t q=k;q<N;q++)
01128 {
01129 m_pkk(k,q) -= Sij * Kij[k] * Kij[q];
01130
01131 m_pkk(q,k) = m_pkk(k,q);
01132 }
01133
01134 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
01135 if (m_pkk(k,k)<0)
01136 {
01137 m_pkk.saveToTextFile("Pkk_err.txt");
01138 mrpt::system::vectorToTextFile(Kij,"Kij.txt");
01139 ASSERT_(m_pkk(k,k)>0)
01140 }
01141 #endif
01142 }
01143 }
01144
01145
01146 m_timLogger.leave("KF:8.update stage:2.ScalarAtOnce.update");
01147 }
01148 }
01149 }
01150 }
01151 break;
01152
01153
01154
01155
01156 case kfIKF:
01157 {
01158 THROW_EXCEPTION("IKF scalar by scalar not implemented yet.");
01159 #if 0
01160 KFMatrix h,Hx,Hy;
01161
01162
01163 size_t nKF_iterations = KF_options.IKF_iterations;
01164
01165
01166 KFMatrix *saved_Pkk=NULL;
01167 if (nKF_iterations>1)
01168 {
01169
01170 saved_Pkk = new KFMatrix( m_pkk );
01171 }
01172
01173 KFVector xkk_0 = m_xkk;
01174 KFVector xkk_next_iter = m_xkk;
01175
01176
01177 for (size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
01178 {
01179
01180
01181
01182 if (IKF_iteration>0)
01183 {
01184 m_pkk = *saved_Pkk;
01185 xkk_next_iter = xkk_0;
01186 }
01187
01188
01189 for (size_t obsIdx=0;obsIdx<Z.getRowCount();obsIdx++)
01190 {
01191
01192 bool doit;
01193 size_t idxInTheFilter=0;
01194
01195 if (data_association.empty())
01196 {
01197 doit = true;
01198 }
01199 else
01200 {
01201 doit = data_association[obsIdx] >= 0;
01202 if (doit)
01203 idxInTheFilter = data_association[obsIdx];
01204 }
01205
01206 if ( doit )
01207 {
01208
01209 const size_t idx_off = VEH_SIZE + idxInTheFilter *FEAT_SIZE;
01210 const size_t R_row_offset = obsIdx*OBS_SIZE;
01211
01212
01213 KFVector ytilde;
01214 OnObservationModelAndJacobians(
01215 Z,
01216 data_association,
01217 false,
01218 (int)obsIdx,
01219 ytilde,
01220 Hx,
01221 Hy );
01222
01223 ASSERTDEB_(ytilde.size() == OBS_SIZE )
01224 ASSERTDEB_(Hx.getRowCount() == OBS_SIZE )
01225 ASSERTDEB_(Hx.getColCount() == VEH_SIZE )
01226
01227 if (FEAT_SIZE>0)
01228 {
01229 ASSERTDEB_(Hy.getRowCount() == OBS_SIZE )
01230 ASSERTDEB_(Hy.getColCount() == FEAT_SIZE )
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 KFMatrix Si(OBS_SIZE,OBS_SIZE);
01254 R.extractMatrix(R_row_offset,0, Si);
01255
01256 size_t k;
01257 KFMatrix term(OBS_SIZE,OBS_SIZE);
01258
01259
01260 Hx.multiply_HCHt(
01261 m_pkk,
01262 Si,
01263 true,
01264 0,
01265 true
01266 );
01267
01268
01269
01270 KFMatrix Pyix( FEAT_SIZE, VEH_SIZE );
01271 m_pkk.extractMatrix(idx_off,0, Pyix);
01272
01273 term.multiply_ABCt( Hy, Pyix, Hx );
01274 Si.add_AAt( term );
01275
01276
01277 Hy.multiply_HCHt(
01278 m_pkk,
01279 Si,
01280 true,
01281 idx_off,
01282 true
01283 );
01284
01285
01286 KFMatrix Si_1(OBS_SIZE,OBS_SIZE);
01287
01288
01289
01290 size_t N = m_pkk.getColCount();
01291
01292 KFMatrix Ki( N, OBS_SIZE );
01293
01294 for (k=0;k<N;k++)
01295 {
01296 size_t q;
01297
01298 for (size_t c=0;c<OBS_SIZE;c++)
01299 {
01300 KFTYPE K_tmp = 0;
01301
01302
01303 for (q=0;q<VEH_SIZE;q++)
01304 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(c,q);
01305
01306
01307 for (q=0;q<FEAT_SIZE;q++)
01308 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(c,q);
01309
01310 Ki.set_unsafe(k,c, K_tmp);
01311 }
01312 }
01313
01314 Ki.multiply(Ki, Si.inv() );
01315
01316
01317
01318 if (nKF_iterations==1)
01319 {
01320
01321
01322 for (k=0;k<N;k++)
01323 for (size_t q=0;q<OBS_SIZE;q++)
01324 m_xkk[k] += Ki.get_unsafe(k,q) * ytilde[q];
01325 }
01326 else
01327 {
01328
01329 mrpt::dynamicsize_vector<KFTYPE> HAx(OBS_SIZE);
01330 size_t o,q;
01331
01332 for (o=0;o<OBS_SIZE;o++)
01333 {
01334 KFTYPE tmp = 0;
01335 for (q=0;q<VEH_SIZE;q++)
01336 tmp += Hx.get_unsafe(o,q) * (xkk_0[q] - m_xkk[q]);
01337
01338 for (q=0;q<FEAT_SIZE;q++)
01339 tmp += Hy.get_unsafe(o,q) * (xkk_0[idx_off+q] - m_xkk[idx_off+q]);
01340
01341 HAx[o] = tmp;
01342 }
01343
01344
01345 for (o=0;o<OBS_SIZE;o++)
01346 HAx[o] = ytilde[o] - HAx[o];
01347
01348
01349
01350 for (k=0;k<N;k++)
01351 {
01352 KFTYPE tmp = xkk_next_iter[k];
01353
01354 for (o=0;o<OBS_SIZE;o++)
01355 tmp += Ki.get_unsafe(k,o) * HAx[o];
01356
01357 xkk_next_iter[k] = tmp;
01358 }
01359 }
01360
01361
01362
01363
01364 {
01365
01366 Ki.multiplyByMatrixAndByTransposeNonSymmetric(
01367 Si,
01368 m_pkk,
01369 true,
01370 true);
01371
01372 m_pkk.force_symmetry();
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 }
01394
01395 }
01396
01397 }
01398
01399
01400 if (nKF_iterations>1)
01401 {
01402 #if 0
01403 cout << "IKF iter: " << IKF_iteration << " -> " << xkk_next_iter << endl;
01404 #endif
01405 m_xkk = xkk_next_iter;
01406 }
01407
01408 }
01409
01410
01411 if (saved_Pkk) delete saved_Pkk;
01412
01413 #endif
01414 }
01415 break;
01416
01417 default:
01418 THROW_EXCEPTION("Invalid value of options.KF_method");
01419 }
01420
01421 }
01422
01423 const double tim_update = m_timLogger.leave("KF:8.update stage");
01424
01425 OnNormalizeStateVector();
01426
01427
01428
01429
01430 if (!data_association.empty())
01431 {
01432 detail::CRunOneKalmanIteration_addNewLandmarks()(*this, Z, data_association,R);
01433 }
01434
01435 if (KF_options.verbose)
01436 {
01437 printf_debug("[KF] %u LMs | Pr: %.2fms | Pr.Obs: %.2fms | Obs.DA: %.2fms | Upd: %.2fms\n",
01438 static_cast<unsigned int>(getNumberOfLandmarksInTheMap()),
01439 1e3*tim_pred,
01440 1e3*tim_pred_obs,
01441 1e3*tim_obs_DA,
01442 1e3*tim_update
01443 );
01444 }
01445
01446
01447 OnPostIteration();
01448
01449 m_timLogger.leave("KF:complete_step");
01450
01451 MRPT_END
01452
01453 }
01454
01455
01456
01457 private:
01458 mutable bool m_user_didnt_implement_jacobian;
01459
01460
01461 static void KF_aux_estimate_trans_jacobian(
01462 const KFArray_VEH &x,
01463 const std::pair<KFCLASS*,KFArray_ACT> &dat,
01464 KFArray_VEH &out_x)
01465 {
01466 bool dumm;
01467 out_x=x;
01468 dat.first->OnTransitionModel(dat.second,out_x, dumm);
01469 }
01470 static void KF_aux_estimate_obs_Hx_jacobian(
01471 const KFArray_VEH &x,
01472 const std::pair<KFCLASS*,size_t> &dat,
01473 KFArray_OBS &out_x)
01474 {
01475 vector_size_t idxs_to_predict(1,dat.second);
01476 vector_KFArray_OBS prediction;
01477
01478 ::memcpy(&dat.first->m_xkk[0],&x[0],sizeof(x[0])*VEH_SIZE);
01479 dat.first->OnObservationModel(idxs_to_predict,prediction);
01480 ASSERTDEB_(prediction.size()==1);
01481 out_x=prediction[0];
01482 }
01483 static void KF_aux_estimate_obs_Hy_jacobian(
01484 const KFArray_FEAT &x,
01485 const std::pair<KFCLASS*,size_t> &dat,
01486 KFArray_OBS &out_x)
01487 {
01488 vector_size_t idxs_to_predict(1,dat.second);
01489 vector_KFArray_OBS prediction;
01490 const size_t lm_idx_in_statevector = VEH_SIZE+FEAT_SIZE*dat.second;
01491
01492 ::memcpy(&dat.first->m_xkk[lm_idx_in_statevector],&x[0],sizeof(x[0])*FEAT_SIZE);
01493 dat.first->OnObservationModel(idxs_to_predict,prediction);
01494 ASSERTDEB_(prediction.size()==1);
01495 out_x=prediction[0];
01496 }
01497
01498
01499 friend struct detail::CRunOneKalmanIteration_addNewLandmarks;
01500
01501 };
01502
01503 namespace detail
01504 {
01505
01506 struct CRunOneKalmanIteration_addNewLandmarks {
01507 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
01508 void operator()(
01509 CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj,
01510 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::vector_KFArray_OBS & Z,
01511 const vector_int &data_association,
01512 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::KFMatrix_OxO &R
01513 )
01514 {
01515 typedef CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> KF;
01516
01517 for (size_t idxObs=0;idxObs<Z.size();idxObs++)
01518 {
01519
01520 if ( data_association[idxObs] < 0 )
01521 {
01522 obj.m_timLogger.enter("KF:9.create new LMs");
01523
01524
01525
01526 ASSERTDEB_(FEAT_SIZE>0)
01527 ASSERTDEB_( 0 == ((obj.m_xkk.size() - VEH_SIZE) % FEAT_SIZE) )
01528
01529 const size_t newIndexInMap = (obj.m_xkk.size() - VEH_SIZE) / FEAT_SIZE;
01530
01531
01532 typename KF::KFArray_FEAT yn;
01533 typename KF::KFMatrix_FxV dyn_dxv;
01534 typename KF::KFMatrix_FxO dyn_dhn;
01535 typename KF::KFMatrix_FxF dyn_dhn_R_dyn_dhnT;
01536 bool use_dyn_dhn_jacobian=true;
01537
01538
01539 obj.OnInverseObservationModel(
01540 Z[idxObs],
01541 yn,
01542 dyn_dxv,
01543 dyn_dhn,
01544 dyn_dhn_R_dyn_dhnT,
01545 use_dyn_dhn_jacobian );
01546
01547
01548 obj.OnNewLandmarkAddedToMap(
01549 idxObs,
01550 newIndexInMap
01551 );
01552
01553 ASSERTDEB_( yn.size() == FEAT_SIZE )
01554
01555
01556 size_t q;
01557 size_t idx = obj.m_xkk.size();
01558 obj.m_xkk.resize( obj.m_xkk.size() + FEAT_SIZE );
01559
01560 for (q=0;q<FEAT_SIZE;q++)
01561 obj.m_xkk[idx+q] = yn[q];
01562
01563
01564
01565
01566 ASSERTDEB_( obj.m_pkk.getColCount()==idx && obj.m_pkk.getRowCount()==idx );
01567
01568 obj.m_pkk.setSize( idx+FEAT_SIZE,idx+FEAT_SIZE );
01569
01570
01571
01572 typename KF::KFMatrix_VxV Pxx;
01573 obj.m_pkk.extractMatrix(0,0,Pxx);
01574 typename KF::KFMatrix_FxV Pxyn;
01575 Pxyn.multiply( dyn_dxv, Pxx );
01576
01577 obj.m_pkk.insertMatrix( idx,0, Pxyn );
01578 obj.m_pkk.insertMatrixTranspose( 0,idx, Pxyn );
01579
01580
01581
01582 const size_t nLMs = (idx-VEH_SIZE)/FEAT_SIZE;
01583 for (q=0;q<nLMs;q++)
01584 {
01585 typename KF::KFMatrix_VxF P_x_yq(UNINITIALIZED_MATRIX);
01586 obj.m_pkk.extractMatrix(0,VEH_SIZE+q*FEAT_SIZE,P_x_yq) ;
01587
01588 typename KF::KFMatrix_FxF P_cross(UNINITIALIZED_MATRIX);
01589 P_cross.multiply(dyn_dxv, P_x_yq );
01590
01591 obj.m_pkk.insertMatrix(idx,VEH_SIZE+q*FEAT_SIZE, P_cross );
01592 obj.m_pkk.insertMatrixTranspose(VEH_SIZE+q*FEAT_SIZE,idx, P_cross );
01593 }
01594
01595
01596
01597
01598 typename KF::KFMatrix_FxF P_yn_yn(UNINITIALIZED_MATRIX);
01599 dyn_dxv.multiply_HCHt(Pxx, P_yn_yn);
01600 if (use_dyn_dhn_jacobian)
01601 dyn_dhn.multiply_HCHt(R, P_yn_yn, true);
01602 else P_yn_yn+=dyn_dhn_R_dyn_dhnT;
01603
01604 obj.m_pkk.insertMatrix(idx,idx, P_yn_yn );
01605
01606 obj.m_timLogger.leave("KF:9.create new LMs");
01607 }
01608 }
01609 }
01610
01611 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
01612 void operator()(
01613 CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE> &obj,
01614 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE>::vector_KFArray_OBS & Z,
01615 const vector_int &data_association,
01616 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE>::KFMatrix_OxO &R
01617 )
01618 {
01619
01620 }
01621
01622 };
01623
01624 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
01625 inline size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj)
01626 {
01627 return (obj.getStateVectorLength()-VEH_SIZE)/FEAT_SIZE;
01628 }
01629
01630 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
01631 inline size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /*FEAT_SIZE*/,ACT_SIZE,KFTYPE> &obj)
01632 {
01633 return 0;
01634 }
01635
01636 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
01637 inline bool isMapEmpty(const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj)
01638 {
01639 return (obj.getStateVectorLength()==VEH_SIZE);
01640 }
01641
01642 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
01643 inline bool isMapEmpty (const CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /*FEAT_SIZE*/,ACT_SIZE,KFTYPE> &obj)
01644 {
01645 return true;
01646 }
01647
01648 }
01649
01650 }
01651
01652
01653 namespace utils
01654 {
01655 template <>
01656 struct TEnumTypeFiller<bayes::TKFMethod>
01657 {
01658 typedef bayes::TKFMethod enum_t;
01659 static void fill(bimap<enum_t,std::string> &m_map)
01660 {
01661 m_map.insert(bayes::kfEKFNaive, "kfEKFNaive");
01662 m_map.insert(bayes::kfEKFAlaDavison, "kfEKFAlaDavison");
01663 m_map.insert(bayes::kfIKFFull, "kfIKFFull");
01664 m_map.insert(bayes::kfIKF, "kfIKF");
01665 }
01666 };
01667 }
01668
01669 }
01670
01671 #endif