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