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/CVectorTemplate.h>
00034 #include <mrpt/math/CArray.h>
00035 #include <mrpt/math/utils.h>
00036
00037 #include <mrpt/utils/CTimeLogger.h>
00038 #include <mrpt/utils/CLoadableOptions.h>
00039 #include <mrpt/utils/CDebugOutputCapable.h>
00040 #include <mrpt/utils/stl_extensions.h>
00041 #include <mrpt/system/os.h>
00042 #include <mrpt/utils/CTicTac.h>
00043 #include <mrpt/utils/CFileOutputStream.h>
00044
00045 #if defined(_MSC_VER)
00046 #pragma warning (push)
00047 #pragma warning (disable: 4723) // Potential div/mod by 0, which actually will never happen.
00048 #pragma warning (disable: 4724)
00049 #endif
00050
00051 namespace mrpt
00052 {
00053 namespace bayes
00054 {
00055 using namespace mrpt::utils;
00056 using namespace mrpt::math;
00057 using namespace std;
00058
00059
00060
00061
00062
00063 enum TKFMethod {
00064 kfEKFNaive = 0,
00065 kfEKFAlaDavison,
00066 kfIKFFull,
00067 kfIKF
00068 };
00069
00070
00071
00072
00073 enum TKFFusionMethod {
00074 kfFusAll = 0,
00075 kfFusSeqMaha,
00076 kfFusSeqML
00077 };
00078
00079
00080
00081 struct MRPTDLLIMPEXP TKF_options : public utils::CLoadableOptions
00082 {
00083 TKF_options();
00084
00085 void loadFromConfigFile(
00086 const mrpt::utils::CConfigFileBase &source,
00087 const std::string §ion);
00088
00089
00090 void dumpToTextStream(CStream &out) const;
00091
00092 TKFMethod method;
00093 TKFFusionMethod fusion_strategy;
00094 bool verbose;
00095 int IKF_iterations;
00096 bool enable_profiler;
00097 };
00098
00099
00100 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE> class CKalmanFilterCapable;
00101
00102 namespace detail
00103 {
00104
00105 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
00106 void runOneKalmanIteration_addNewLandmarks(
00107 CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj,
00108 std::vector<typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::KFArray_OBS> Z,
00109 const vector_int &data_association,
00110 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::KFMatrix_OxO &R
00111 );
00112 }
00113
00114
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 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE = double>
00142 class CKalmanFilterCapable : public mrpt::utils::CDebugOutputCapable
00143 {
00144 public:
00145 static inline size_t get_vehicle_size() { return VEH_SIZE; }
00146 static inline size_t get_observation_size() { return OBS_SIZE; }
00147 static inline size_t get_feature_size() { return FEAT_SIZE; }
00148 static inline size_t get_action_size() { return ACT_SIZE; }
00149 inline size_t getNumberOfLandmarksInTheMap() const { return FEAT_SIZE ? (m_xkk.size()-VEH_SIZE)/FEAT_SIZE : 0; }
00150
00151
00152 typedef KFTYPE kftype;
00153
00154
00155 typedef CVectorTemplate<KFTYPE> KFVector;
00156 typedef CMatrixTemplateNumeric<KFTYPE> KFMatrix;
00157
00158 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,VEH_SIZE> KFMatrix_VxV;
00159 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,OBS_SIZE> KFMatrix_OxO;
00160 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,FEAT_SIZE> KFMatrix_FxF;
00161 typedef CMatrixFixedNumeric<KFTYPE,ACT_SIZE,ACT_SIZE> KFMatrix_AxA;
00162
00163 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,OBS_SIZE> KFMatrix_VxO;
00164 typedef CMatrixFixedNumeric<KFTYPE,VEH_SIZE,FEAT_SIZE> KFMatrix_VxF;
00165
00166 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,VEH_SIZE> KFMatrix_FxV;
00167 typedef CMatrixFixedNumeric<KFTYPE,FEAT_SIZE,OBS_SIZE> KFMatrix_FxO;
00168
00169 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,FEAT_SIZE> KFMatrix_OxF;
00170 typedef CMatrixFixedNumeric<KFTYPE,OBS_SIZE,VEH_SIZE> KFMatrix_OxV;
00171
00172 typedef CArrayNumeric<KFTYPE,VEH_SIZE> KFArray_VEH;
00173 typedef CArrayNumeric<KFTYPE,ACT_SIZE> KFArray_ACT;
00174 typedef CArrayNumeric<KFTYPE,OBS_SIZE> KFArray_OBS;
00175 typedef CArrayNumeric<KFTYPE,FEAT_SIZE> KFArray_FEAT;
00176
00177 protected:
00178
00179
00180
00181 KFVector m_xkk;
00182 KFMatrix m_pkk;
00183
00184
00185
00186 mrpt::utils::CTimeLogger m_timLogger;
00187
00188
00189
00190
00191
00192
00193
00194
00195 virtual void OnGetAction( KFArray_ACT &out_u ) = 0;
00196
00197
00198
00199
00200
00201
00202 virtual void OnTransitionModel(
00203 const KFArray_ACT &in_u,
00204 KFArray_VEH &inout_x,
00205 bool &out_skipPrediction
00206 ) = 0;
00207
00208
00209
00210
00211
00212 virtual void OnTransitionJacobian( KFMatrix_VxV &out_F ) = 0;
00213
00214
00215
00216
00217
00218 virtual void OnTransitionNoise( KFMatrix_VxV &out_Q ) = 0;
00219
00220
00221
00222
00223
00224
00225
00226
00227 virtual void OnPreComputingPredictions(
00228 const vector<KFArray_OBS> &in_all_prediction_means,
00229 vector_size_t &out_LM_indices_to_predict )
00230 {
00231
00232 const size_t N = this->getNumberOfLandmarksInTheMap();
00233 out_LM_indices_to_predict.resize(N);
00234 for (size_t i=0;i<N;i++) out_LM_indices_to_predict[i]=i;
00235 }
00236
00237
00238
00239
00240
00241 virtual void OnGetObservationNoise(KFMatrix_OxO &out_R) = 0;
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 virtual void OnGetObservationsAndDataAssociation(
00255 std::vector<KFArray_OBS> &out_z,
00256 vector_int &out_data_association,
00257 const vector<KFArray_OBS> &in_all_predictions,
00258 const KFMatrix &in_S,
00259 const vector_size_t &in_lm_indices_in_S,
00260 const KFMatrix_OxO &in_R
00261 ) = 0;
00262
00263
00264
00265
00266
00267 virtual void OnObservationModel(
00268 const vector_size_t &idx_landmarks_to_predict,
00269 std::vector<KFArray_OBS> &out_predictions
00270 ) = 0;
00271
00272
00273
00274
00275
00276
00277 virtual void OnObservationJacobians(
00278 const size_t &idx_landmark_to_predict,
00279 KFMatrix_OxV &Hx,
00280 KFMatrix_OxF &Hy
00281 ) = 0;
00282
00283
00284
00285 virtual void OnSubstractObservationVectors(KFArray_OBS &A, const KFArray_OBS &B)
00286 {
00287 A -= B;
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 virtual void OnInverseObservationModel(
00303 const KFArray_OBS & in_z,
00304 KFArray_FEAT & out_yn,
00305 KFMatrix_FxV & out_dyn_dxv,
00306 KFMatrix_FxO & out_dyn_dhn )
00307 {
00308 MRPT_START
00309 THROW_EXCEPTION("Inverse sensor model required but not implemented in derived class.")
00310 MRPT_END
00311 }
00312
00313
00314
00315
00316
00317
00318 virtual void OnNewLandmarkAddedToMap(
00319 const size_t in_obsIdx,
00320 const size_t in_idxNewFeat )
00321 {
00322
00323 }
00324
00325
00326
00327 virtual void OnNormalizeStateVector()
00328 {
00329
00330 }
00331
00332
00333
00334 virtual void OnPostIteration()
00335 {
00336
00337 }
00338
00339
00340
00341
00342 public:
00343 CKalmanFilterCapable() {}
00344 virtual ~CKalmanFilterCapable() {}
00345
00346 mrpt::utils::CTimeLogger &getProfiler() { return m_timLogger; }
00347
00348 TKF_options KF_options;
00349
00350 protected:
00351
00352
00353
00354
00355
00356 void runOneKalmanIteration()
00357 {
00358 MRPT_START
00359
00360 m_timLogger.enable(KF_options.enable_profiler || KF_options.verbose);
00361
00362
00363
00364
00365 KFArray_ACT u;
00366
00367 m_timLogger.enter("KF:1.OnGetAction");
00368 OnGetAction(u);
00369 m_timLogger.leave("KF:1.OnGetAction");
00370
00371
00372 if (FEAT_SIZE) ASSERTDEB_( (m_xkk.size() - VEH_SIZE) % FEAT_SIZE == 0 );
00373
00374
00375
00376
00377 m_timLogger.enter("KF:2.prediction stage");
00378
00379 const size_t N_map = getNumberOfLandmarksInTheMap();
00380
00381 KFArray_VEH xv( &m_xkk[0] );
00382
00383 bool skipPrediction=false;
00384
00385
00386
00387 OnTransitionModel(u, xv, skipPrediction);
00388
00389 if ( !skipPrediction )
00390 {
00391
00392
00393
00394
00395 KFMatrix_VxV dfv_dxv;
00396 OnTransitionJacobian(dfv_dxv);
00397
00398
00399 KFMatrix_VxV Q;
00400 OnTransitionNoise(Q);
00401
00402
00403
00404
00405 KFMatrix_VxV Pkk_new = Q;
00406
00407
00408
00409 multiply_HCHt(
00410 dfv_dxv,
00411 m_pkk,
00412 Pkk_new,
00413 true,
00414 true
00415 );
00416
00417
00418 m_pkk.insertMatrix(0,0, Pkk_new );
00419
00420
00421
00422
00423
00424 KFMatrix aux;
00425 for (size_t i=0 ; i<N_map ; i++)
00426 {
00427
00428 multiplySubMatrix(
00429 dfv_dxv,
00430 m_pkk,
00431 aux,
00432 VEH_SIZE+i*FEAT_SIZE,
00433 0,
00434 FEAT_SIZE
00435 );
00436
00437 m_pkk.insertMatrix (0, VEH_SIZE+i*FEAT_SIZE, aux );
00438 m_pkk.insertMatrixTranspose(VEH_SIZE+i*FEAT_SIZE, 0 , aux );
00439 }
00440
00441
00442
00443
00444 for (size_t i=0;i<VEH_SIZE;i++)
00445 m_xkk[i]=xv[i];
00446
00447
00448 OnNormalizeStateVector();
00449
00450 }
00451
00452
00453 const double tim_pred = m_timLogger.leave("KF:2.prediction stage");
00454
00455
00456
00457
00458
00459 m_timLogger.enter("KF:3.predict all obs");
00460
00461 KFMatrix_OxO R;
00462 OnGetObservationNoise(R);
00463
00464
00465
00466 vector<KFArray_OBS> all_predictions(N_map);
00467 OnObservationModel(
00468 mrpt::math::sequence<size_t,1>(0,N_map),
00469 all_predictions);
00470
00471 const double tim_pred_obs = m_timLogger.leave("KF:3.predict all obs");
00472
00473 m_timLogger.enter("KF:4.decide pred obs");
00474
00475
00476 vector_size_t predictLMidxs;
00477 OnPreComputingPredictions(all_predictions, predictLMidxs);
00478
00479 m_timLogger.leave("KF:4.decide pred obs");
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 m_timLogger.enter("KF:5.build Jacobians");
00506
00507 const size_t N_pred = FEAT_SIZE==0 ?
00508 1 :
00509 predictLMidxs.size();
00510
00511 KFMatrix dh_dx (N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_pred );
00512 KFMatrix dh_dx_full(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
00513
00514
00515 vector_size_t idxs;
00516 idxs.reserve(VEH_SIZE+N_pred*FEAT_SIZE);
00517
00518 for (size_t i=0;i<VEH_SIZE;i++) idxs.push_back(i);
00519
00520 for (size_t i=0;i<N_pred;++i)
00521 {
00522 const size_t lm_idx = FEAT_SIZE==0 ? 0 : predictLMidxs[i];
00523 KFMatrix_OxV Hx(UNITIALIZED_MATRIX);
00524 KFMatrix_OxF Hy(UNITIALIZED_MATRIX);
00525
00526 OnObservationJacobians(lm_idx,Hx,Hy);
00527
00528 dh_dx.insertMatrix(i*OBS_SIZE,0, Hx);
00529 if (FEAT_SIZE!=0)
00530 dh_dx.insertMatrix(i*OBS_SIZE,VEH_SIZE+i*OBS_SIZE, Hy);
00531
00532 dh_dx_full.insertMatrix(i*OBS_SIZE,0, Hx);
00533 if (FEAT_SIZE!=0)
00534 {
00535 dh_dx_full.insertMatrix(i*OBS_SIZE,VEH_SIZE+lm_idx*OBS_SIZE, Hy);
00536
00537 for (size_t k=0;k<FEAT_SIZE;k++)
00538 idxs.push_back(k+VEH_SIZE+FEAT_SIZE*lm_idx);
00539 }
00540 }
00541 m_timLogger.leave("KF:5.build Jacobians");
00542
00543
00544
00545
00546 m_timLogger.enter("KF:6.build S");
00547
00548 KFMatrix S(N_pred*OBS_SIZE,N_pred*OBS_SIZE);
00549
00550
00551
00552 KFMatrix Pkk_subset;
00553 m_pkk.extractSubmatrixSymmetrical(idxs,Pkk_subset);
00554
00555
00556 dh_dx.multiply_HCHt(Pkk_subset,S);
00557
00558
00559 if ( FEAT_SIZE>0 )
00560 {
00561 for (size_t i=0;i<N_pred;++i)
00562 {
00563 const size_t obs_idx_off = i*OBS_SIZE;
00564 for (size_t j=0;j<OBS_SIZE;j++)
00565 for (size_t k=0;k<OBS_SIZE;k++)
00566 S.get_unsafe(obs_idx_off+j,obs_idx_off+k) += R.get_unsafe(j,k);
00567 }
00568 }
00569 else
00570 {
00571 ASSERTDEB_(S.getColCount() == OBS_SIZE );
00572 S+=R;
00573 }
00574
00575 m_timLogger.leave("KF:6.build S");
00576
00577
00578 vector<KFArray_OBS> Z;
00579 vector_int data_association;
00580
00581 m_timLogger.enter("KF:7.get obs & DA");
00582
00583
00584 OnGetObservationsAndDataAssociation(
00585 Z, data_association,
00586 all_predictions, S, predictLMidxs, R
00587 );
00588
00589 ASSERTDEB_(data_association.size()==Z.size() || (data_association.empty() && FEAT_SIZE==0));
00590
00591 const double tim_obs_DA = m_timLogger.leave("KF:7.get obs & DA");
00592
00593
00594
00595
00596
00597 if ( !Z.empty() )
00598 {
00599 m_timLogger.enter("KF:8.update stage");
00600
00601 switch (KF_options.method)
00602 {
00603
00604
00605
00606 case kfEKFNaive:
00607 case kfIKFFull:
00608 {
00609
00610
00611
00612 vector_int mapIndicesForKFUpdate(data_association.size());
00613 mapIndicesForKFUpdate.resize( std::distance(mapIndicesForKFUpdate.begin(),
00614 std::remove_copy_if(
00615 data_association.begin(),
00616 data_association.end(),
00617 mapIndicesForKFUpdate.begin(),
00618 binder1st<equal_to<int> >(equal_to<int>(),-1) ) ) );
00619
00620 const size_t N_upd = mapIndicesForKFUpdate.size();
00621
00622
00623 const size_t nKF_iterations = KF_options.method==kfEKFNaive ? 1 : KF_options.IKF_iterations;
00624
00625 const KFVector xkk_0 = m_xkk;
00626
00627
00628 if (N_upd>0)
00629 {
00630 for (size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
00631 {
00632
00633 if (IKF_iteration>0)
00634 {
00635 }
00636
00637
00638 vector_size_t S_idxs;
00639 KFVector ytilde;
00640
00641 S_idxs.reserve(OBS_SIZE*N_upd);
00642 ytilde.reserve(OBS_SIZE*N_upd);
00643
00644 KFMatrix dh_dx_full_obs(N_upd*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
00645
00646 for (size_t i=0;i<data_association.size();++i)
00647 {
00648 if (data_association[i]<0) continue;
00649
00650 const size_t assoc_idx_in_map = static_cast<size_t>(data_association[i]);
00651 const size_t assoc_idx_in_pred = mrpt::utils::find_in_vector(assoc_idx_in_map, predictLMidxs);
00652 ASSERT_(assoc_idx_in_pred!=string::npos);
00653
00654
00655
00656 for (size_t k=0;k<OBS_SIZE;k++)
00657 {
00658 ::memcpy(
00659 dh_dx_full_obs.get_unsafe_row(S_idxs.size()),
00660 dh_dx_full.get_unsafe_row(assoc_idx_in_pred*OBS_SIZE + k ),
00661 sizeof(dh_dx_full(0,0))*(VEH_SIZE + FEAT_SIZE * N_map) );
00662 S_idxs.push_back(assoc_idx_in_pred*OBS_SIZE+k);
00663 }
00664
00665
00666 KFArray_OBS ytilde_i = Z[i];
00667 OnSubstractObservationVectors(ytilde_i,all_predictions[predictLMidxs[assoc_idx_in_pred]]);
00668 for (size_t k=0;k<OBS_SIZE;k++)
00669 ytilde.push_back( ytilde_i[k] );
00670 }
00671
00672
00673 KFMatrix S_observed;
00674 S.extractSubmatrixSymmetrical(S_idxs,S_observed);
00675
00676
00677
00678 m_timLogger.enter("KF:8.update stage:1.FULLKF:build K");
00679
00680 KFMatrix K(m_pkk.getRowCount(), S_observed.getColCount() );
00681
00682
00683 K.multiply_ABt(m_pkk, dh_dx_full_obs);
00684
00685 KFMatrix S_1( S_observed.getRowCount(), S_observed.getColCount() );
00686 S_observed.inv(S_1);
00687 K.multiply( K, S_1 );
00688
00689 m_timLogger.leave("KF:8.update stage:1.FULLKF:build K");
00690
00691
00692 if (nKF_iterations==1)
00693 {
00694 m_timLogger.enter("KF:8.update stage:2.FULLKF:update xkk");
00695
00696 K.multiply_Ab(
00697 ytilde,
00698 m_xkk,
00699 true
00700 );
00701
00702 m_timLogger.leave("KF:8.update stage:2.FULLKF:update xkk");
00703 }
00704 else
00705 {
00706 m_timLogger.enter("KF:8.update stage:2.FULLKF:iter.update xkk");
00707
00708 KFVector HAx_column;
00709 dh_dx_full_obs.multiply_Ab( m_xkk - xkk_0, HAx_column);
00710
00711 m_xkk = xkk_0;
00712 K.multiply_Ab(
00713 (ytilde-HAx_column),
00714 m_xkk,
00715 true
00716 );
00717
00718 m_timLogger.leave("KF:8.update stage:2.FULLKF:iter.update xkk");
00719 }
00720
00721
00722
00723 if (IKF_iteration == (nKF_iterations-1) )
00724 {
00725 m_timLogger.enter("KF:8.update stage:3.FULLKF:update Pkk");
00726
00727
00728
00729
00730
00731 KFMatrix aux_K_dh_dx;
00732 aux_K_dh_dx.multiply(K,dh_dx_full_obs);
00733
00734
00735 const size_t stat_len = aux_K_dh_dx.getColCount();
00736 for (size_t r=0;r<stat_len;r++)
00737 for (size_t c=0;c<stat_len;c++)
00738 if (r==c)
00739 aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c) + kftype(1);
00740 else aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c);
00741
00742 m_pkk.multiply_result_is_symmetric(aux_K_dh_dx, m_pkk );
00743
00744 m_timLogger.leave("KF:8.update stage:3.FULLKF:update Pkk");
00745 }
00746 }
00747 }
00748 }
00749 break;
00750
00751
00752
00753
00754 case kfEKFAlaDavison:
00755 {
00756
00757 for (size_t obsIdx=0;obsIdx<Z.size();obsIdx++)
00758 {
00759
00760 bool doit;
00761 size_t idxInTheFilter=0;
00762
00763 if (data_association.empty())
00764 {
00765 doit = true;
00766 }
00767 else
00768 {
00769 doit = data_association[obsIdx] >= 0;
00770 if (doit)
00771 idxInTheFilter = data_association[obsIdx];
00772 }
00773
00774 if ( doit )
00775 {
00776 m_timLogger.enter("KF:8.update stage:1.ScalarAtOnce.prepare");
00777
00778
00779 const size_t idx_off = VEH_SIZE + idxInTheFilter*FEAT_SIZE;
00780
00781
00782 vector<KFArray_OBS> pred_obs;
00783 OnObservationModel( vector_size_t(1,idxInTheFilter),pred_obs);
00784 ASSERTDEB_(pred_obs.size()==1);
00785
00786
00787 KFArray_OBS ytilde = Z[obsIdx];
00788 OnSubstractObservationVectors(ytilde, pred_obs[0]);
00789
00790
00791 KFMatrix_OxV Hx(UNITIALIZED_MATRIX);
00792 KFMatrix_OxF Hy(UNITIALIZED_MATRIX);
00793 OnObservationJacobians(idxInTheFilter,Hx,Hy);
00794
00795 m_timLogger.leave("KF:8.update stage:1.ScalarAtOnce.prepare");
00796
00797
00798 for (size_t j=0;j<OBS_SIZE;j++)
00799 {
00800 m_timLogger.enter("KF:8.update stage:2.ScalarAtOnce.update");
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814 #if defined(_DEBUG)
00815 {
00816
00817 for (size_t a=0;a<OBS_SIZE;a++)
00818 for (size_t b=0;b<OBS_SIZE;b++)
00819 if ( a!=b )
00820 if (R(a,b)!=0)
00821 THROW_EXCEPTION("This KF algorithm assumes independent noise components in the observation (matrix R). Select another KF algorithm.")
00822 }
00823 #endif
00824
00825 KFTYPE Sij = R.get_unsafe(j,j);
00826
00827
00828 for (size_t k=0;k<VEH_SIZE;k++)
00829 {
00830 KFTYPE accum = 0;
00831 for (size_t q=0;q<VEH_SIZE;q++)
00832 accum += Hx.get_unsafe(j,q) * m_pkk.get_unsafe(q,k);
00833 Sij+= Hx.get_unsafe(j,k) * accum;
00834 }
00835
00836
00837 KFTYPE term2=0;
00838 for (size_t k=0;k<VEH_SIZE;k++)
00839 {
00840 KFTYPE accum = 0;
00841 for (size_t q=0;q<FEAT_SIZE;q++)
00842 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,k);
00843 term2+= Hx.get_unsafe(j,k) * accum;
00844 }
00845 Sij += 2 * term2;
00846
00847
00848 for (size_t k=0;k<FEAT_SIZE;k++)
00849 {
00850 KFTYPE accum = 0;
00851 for (size_t q=0;q<FEAT_SIZE;q++)
00852 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,idx_off+k);
00853 Sij+= Hy.get_unsafe(j,k) * accum;
00854 }
00855
00856
00857
00858 size_t N = m_pkk.getColCount();
00859 vector<KFTYPE> Kij( N );
00860
00861 for (size_t k=0;k<N;k++)
00862 {
00863 KFTYPE K_tmp = 0;
00864
00865
00866 size_t q;
00867 for (q=0;q<VEH_SIZE;q++)
00868 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(j,q);
00869
00870
00871 for (q=0;q<FEAT_SIZE;q++)
00872 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(j,q);
00873
00874 Kij[k] = K_tmp / Sij;
00875 }
00876
00877
00878
00879
00880 for (size_t k=0;k<N;k++)
00881 m_xkk[k] += Kij[k] * ytilde[j];
00882
00883
00884
00885
00886 {
00887 for (size_t k=0;k<N;k++)
00888 {
00889 for (size_t q=k;q<N;q++)
00890 {
00891 m_pkk(k,q) -= Sij * Kij[k] * Kij[q];
00892
00893 m_pkk(q,k) = m_pkk(k,q);
00894 }
00895
00896 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
00897 if (m_pkk(k,k)<0)
00898 {
00899 m_pkk.saveToTextFile("Pkk_err.txt");
00900 mrpt::system::vectorToTextFile(Kij,"Kij.txt");
00901 ASSERT_(m_pkk(k,k)>0)
00902 }
00903 #endif
00904 }
00905 }
00906
00907
00908 m_timLogger.leave("KF:8.update stage:2.ScalarAtOnce.update");
00909 }
00910 }
00911 }
00912 }
00913 break;
00914
00915
00916
00917
00918 case kfIKF:
00919 {
00920 #if 0
00921 KFMatrix h,Hx,Hy;
00922
00923
00924 size_t nKF_iterations = KF_options.IKF_iterations;
00925
00926
00927 KFMatrix *saved_Pkk=NULL;
00928 if (nKF_iterations>1)
00929 {
00930
00931 saved_Pkk = new KFMatrix( m_pkk );
00932 }
00933
00934 KFVector xkk_0 = m_xkk;
00935 KFVector xkk_next_iter = m_xkk;
00936
00937
00938 for (size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
00939 {
00940
00941
00942
00943 if (IKF_iteration>0)
00944 {
00945 m_pkk = *saved_Pkk;
00946
00947 xkk_next_iter = xkk_0;
00948 }
00949
00950
00951 for (size_t obsIdx=0;obsIdx<Z.getRowCount();obsIdx++)
00952 {
00953
00954 bool doit;
00955 size_t idxInTheFilter=0;
00956
00957 if (data_association.empty())
00958 {
00959 doit = true;
00960 }
00961 else
00962 {
00963 doit = data_association[obsIdx] >= 0;
00964 if (doit)
00965 idxInTheFilter = data_association[obsIdx];
00966 }
00967
00968 if ( doit )
00969 {
00970
00971 const size_t idx_off = VEH_SIZE + idxInTheFilter *FEAT_SIZE;
00972 const size_t R_row_offset = obsIdx*OBS_SIZE;
00973
00974
00975 KFVector ytilde;
00976 OnObservationModelAndJacobians(
00977 Z,
00978 data_association,
00979 false,
00980 (int)obsIdx,
00981 ytilde,
00982 Hx,
00983 Hy );
00984
00985 ASSERTDEB_(ytilde.size() == OBS_SIZE )
00986 ASSERTDEB_(Hx.getRowCount() == OBS_SIZE )
00987 ASSERTDEB_(Hx.getColCount() == VEH_SIZE )
00988
00989 if (FEAT_SIZE>0)
00990 {
00991 ASSERTDEB_(Hy.getRowCount() == OBS_SIZE )
00992 ASSERTDEB_(Hy.getColCount() == FEAT_SIZE )
00993 }
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015 KFMatrix Si(OBS_SIZE,OBS_SIZE);
01016 R.extractMatrix(R_row_offset,0, Si);
01017
01018 size_t k;
01019 KFMatrix term(OBS_SIZE,OBS_SIZE);
01020
01021
01022 Hx.multiply_HCHt(
01023 m_pkk,
01024 Si,
01025 true,
01026 0,
01027 true
01028 );
01029
01030
01031
01032 KFMatrix Pyix( FEAT_SIZE, VEH_SIZE );
01033 m_pkk.extractMatrix(idx_off,0, Pyix);
01034
01035 term.multiply_ABCt( Hy, Pyix, Hx );
01036 Si.add_AAt( term );
01037
01038
01039 Hy.multiply_HCHt(
01040 m_pkk,
01041 Si,
01042 true,
01043 idx_off,
01044 true
01045 );
01046
01047
01048 KFMatrix Si_1(OBS_SIZE,OBS_SIZE);
01049
01050
01051
01052 size_t N = m_pkk.getColCount();
01053
01054 KFMatrix Ki( N, OBS_SIZE );
01055
01056 for (k=0;k<N;k++)
01057 {
01058 size_t q;
01059
01060 for (size_t c=0;c<OBS_SIZE;c++)
01061 {
01062 KFTYPE K_tmp = 0;
01063
01064
01065 for (q=0;q<VEH_SIZE;q++)
01066 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(c,q);
01067
01068
01069 for (q=0;q<FEAT_SIZE;q++)
01070 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(c,q);
01071
01072 Ki.set_unsafe(k,c, K_tmp);
01073 }
01074 }
01075
01076 Ki.multiply(Ki, Si.inv() );
01077
01078
01079
01080 if (nKF_iterations==1)
01081 {
01082
01083
01084 for (k=0;k<N;k++)
01085 for (size_t q=0;q<OBS_SIZE;q++)
01086 m_xkk[k] += Ki.get_unsafe(k,q) * ytilde[q];
01087 }
01088 else
01089 {
01090
01091 std::vector<KFTYPE> HAx(OBS_SIZE);
01092 size_t o,q;
01093
01094 for (o=0;o<OBS_SIZE;o++)
01095 {
01096 KFTYPE tmp = 0;
01097 for (q=0;q<VEH_SIZE;q++)
01098 tmp += Hx.get_unsafe(o,q) * (xkk_0[q] - m_xkk[q]);
01099
01100 for (q=0;q<FEAT_SIZE;q++)
01101 tmp += Hy.get_unsafe(o,q) * (xkk_0[idx_off+q] - m_xkk[idx_off+q]);
01102
01103 HAx[o] = tmp;
01104 }
01105
01106
01107 for (o=0;o<OBS_SIZE;o++)
01108 HAx[o] = ytilde[o] - HAx[o];
01109
01110
01111
01112 for (k=0;k<N;k++)
01113 {
01114 KFTYPE tmp = xkk_next_iter[k];
01115
01116 for (o=0;o<OBS_SIZE;o++)
01117 tmp += Ki.get_unsafe(k,o) * HAx[o];
01118
01119 xkk_next_iter[k] = tmp;
01120 }
01121 }
01122
01123
01124
01125
01126 {
01127
01128 Ki.multiplyByMatrixAndByTransposeNonSymmetric(
01129 Si,
01130 m_pkk,
01131 true,
01132 true);
01133
01134 m_pkk.force_symmetry();
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155 }
01156
01157 }
01158
01159 }
01160
01161
01162 if (nKF_iterations>1)
01163 {
01164 #if 0
01165 cout << "IKF iter: " << IKF_iteration << " -> " << xkk_next_iter << endl;
01166 #endif
01167 m_xkk = xkk_next_iter;
01168 }
01169
01170 }
01171
01172
01173 if (saved_Pkk) delete saved_Pkk;
01174
01175 #endif
01176 }
01177 break;
01178
01179 default:
01180 THROW_EXCEPTION("Invalid value of options.KF_method");
01181 }
01182
01183 }
01184
01185 const double tim_update = m_timLogger.leave("KF:8.update stage");
01186
01187 OnNormalizeStateVector();
01188
01189
01190
01191
01192 if (!data_association.empty())
01193 {
01194 detail::runOneKalmanIteration_addNewLandmarks(*this, Z, data_association,R);
01195 }
01196
01197 if (KF_options.verbose)
01198 {
01199 printf_debug("[KF] %u LMs | Pr: %.2fms | Pr.Obs: %.2fms | Obs.DA: %.2fms | Upd: %.2fms\n",
01200 static_cast<unsigned int>(getNumberOfLandmarksInTheMap()),
01201 1e3*tim_pred,
01202 1e3*tim_pred_obs,
01203 1e3*tim_obs_DA,
01204 1e3*tim_update
01205 );
01206 }
01207
01208
01209 OnPostIteration();
01210
01211 MRPT_END
01212
01213 }
01214
01215
01216 template <size_t _VEH_SIZE, size_t _OBS_SIZE, size_t _FEAT_SIZE, size_t _ACT_SIZE, typename _KFTYPE>
01217 friend void detail::runOneKalmanIteration_addNewLandmarks(
01218 CKalmanFilterCapable<_VEH_SIZE,_OBS_SIZE,_FEAT_SIZE,_ACT_SIZE,_KFTYPE> &obj,
01219 std::vector<typename CKalmanFilterCapable<_VEH_SIZE,_OBS_SIZE,_FEAT_SIZE,_ACT_SIZE,_KFTYPE>::KFArray_OBS> Z,
01220 const vector_int &data_association,
01221 const typename CKalmanFilterCapable<_VEH_SIZE,_OBS_SIZE,_FEAT_SIZE,_ACT_SIZE,_KFTYPE>::KFMatrix_OxO &R
01222 );
01223
01224 };
01225
01226 namespace detail
01227 {
01228
01229 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t FEAT_SIZE, size_t ACT_SIZE, typename KFTYPE>
01230 void runOneKalmanIteration_addNewLandmarks(
01231 CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> &obj,
01232 std::vector<typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::KFArray_OBS> Z,
01233 const vector_int &data_association,
01234 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE>::KFMatrix_OxO &R
01235 )
01236 {
01237 typedef CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,FEAT_SIZE,ACT_SIZE,KFTYPE> KF;
01238
01239 for (size_t idxObs=0;idxObs<Z.size();idxObs++)
01240 {
01241
01242 if ( data_association[idxObs] < 0 )
01243 {
01244 obj.m_timLogger.enter("KF:9.create new LMs");
01245
01246
01247
01248 ASSERTDEB_(FEAT_SIZE>0)
01249 ASSERTDEB_( 0 == ((obj.m_xkk.size() - VEH_SIZE) % FEAT_SIZE) )
01250
01251 const size_t newIndexInMap = (obj.m_xkk.size() - VEH_SIZE) / FEAT_SIZE;
01252
01253
01254 typename KF::KFArray_FEAT yn;
01255 typename KF::KFMatrix_FxV dyn_dxv;
01256 typename KF::KFMatrix_FxO dyn_dhn;
01257
01258
01259 obj.OnInverseObservationModel(
01260 Z[idxObs],
01261 yn,
01262 dyn_dxv,
01263 dyn_dhn );
01264
01265
01266 obj.OnNewLandmarkAddedToMap(
01267 idxObs,
01268 newIndexInMap
01269 );
01270
01271 ASSERTDEB_( yn.size() == FEAT_SIZE )
01272
01273
01274 size_t q;
01275 size_t idx = obj.m_xkk.size();
01276 obj.m_xkk.resize( obj.m_xkk.size() + FEAT_SIZE );
01277
01278 for (q=0;q<FEAT_SIZE;q++)
01279 obj.m_xkk[idx+q] = yn[q];
01280
01281
01282
01283
01284 ASSERTDEB_( obj.m_pkk.getColCount()==idx && obj.m_pkk.getRowCount()==idx );
01285
01286 obj.m_pkk.setSize( idx+FEAT_SIZE,idx+FEAT_SIZE );
01287
01288
01289
01290 typename KF::KFMatrix_VxV Pxx;
01291 obj.m_pkk.extractMatrix(0,0,Pxx);
01292 typename KF::KFMatrix_FxV Pxyn;
01293 Pxyn.multiply( dyn_dxv, Pxx );
01294
01295 obj.m_pkk.insertMatrix( idx,0, Pxyn );
01296 obj.m_pkk.insertMatrixTranspose( 0,idx, Pxyn );
01297
01298
01299
01300 const size_t nLMs = (idx-VEH_SIZE)/FEAT_SIZE;
01301 for (q=0;q<nLMs;q++)
01302 {
01303 typename KF::KFMatrix_VxF P_x_yq(UNITIALIZED_MATRIX);
01304 obj.m_pkk.extractMatrix(0,VEH_SIZE+q*FEAT_SIZE,P_x_yq) ;
01305
01306 typename KF::KFMatrix_FxF P_cross(UNITIALIZED_MATRIX);
01307 P_cross.multiply(dyn_dxv, P_x_yq );
01308
01309 obj.m_pkk.insertMatrix(idx,VEH_SIZE+q*FEAT_SIZE, P_cross );
01310 obj.m_pkk.insertMatrixTranspose(VEH_SIZE+q*FEAT_SIZE,idx, P_cross );
01311 }
01312
01313
01314
01315 typename KF::KFMatrix_FxF P_yn_yn(UNITIALIZED_MATRIX);
01316 multiply_HCHt(dyn_dxv, Pxx, P_yn_yn);
01317 multiply_HCHt(dyn_dhn, R, P_yn_yn, true);
01318
01319
01320 obj.m_pkk.insertMatrix(idx,idx, P_yn_yn );
01321
01322 obj.m_timLogger.leave("KF:9.create new LMs");
01323 }
01324 }
01325 }
01326
01327 template <size_t VEH_SIZE, size_t OBS_SIZE, size_t ACT_SIZE, typename KFTYPE>
01328 void runOneKalmanIteration_addNewLandmarks(
01329 CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE> &obj,
01330 std::vector<typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE>::KFArray_OBS> Z,
01331 const vector_int &data_association,
01332 const typename CKalmanFilterCapable<VEH_SIZE,OBS_SIZE,0 /* FEAT_SIZE=0 */,ACT_SIZE,KFTYPE>::KFMatrix_OxO &R
01333 )
01334 {
01335
01336 }
01337
01338
01339 }
01340
01341 }
01342 }
01343
01344 #if defined(_MSC_VER)
01345 #pragma warning (pop)
01346 #endif
01347
01348 #endif