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