9 #ifndef CKalmanFilterCapable_IMPL_H
10 #define CKalmanFilterCapable_IMPL_H
12 #ifndef CKalmanFilterCapable_H
13 #error Include this file only from 'CKalmanFilterCapable.h'
21 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
26 m_timLogger.enable(KF_options.enable_profiler || KF_options.verbose);
27 m_timLogger.enter(
"KF:complete_step");
29 ASSERT_(
size_t(m_xkk.size())==m_pkk.getColCount())
30 ASSERT_(
size_t(m_xkk.size())>=VEH_SIZE)
37 m_timLogger.enter(
"KF:1.OnGetAction");
39 m_timLogger.leave(
"KF:1.OnGetAction");
42 if (FEAT_SIZE) {
ASSERTDEB_( (((m_xkk.size()-VEH_SIZE)/FEAT_SIZE)*FEAT_SIZE)== (m_xkk.size()-VEH_SIZE) ) }
47 m_timLogger.enter(
"KF:2.prediction stage");
49 const size_t N_map = getNumberOfLandmarksInTheMap();
53 bool skipPrediction=
false;
57 OnTransitionModel(u, xv, skipPrediction);
59 if ( !skipPrediction )
68 m_user_didnt_implement_jacobian=
false;
69 if (KF_options.use_analytic_transition_jacobian)
70 OnTransitionJacobian(dfv_dxv);
72 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_transition_jacobian || KF_options.debug_verify_analytic_jacobians)
76 OnTransitionJacobianNumericGetIncrements(xkk_veh_increments);
80 &KF_aux_estimate_trans_jacobian,
82 std::pair<KFCLASS*,KFArray_ACT>(
this,u),
85 if (KF_options.debug_verify_analytic_jacobians)
88 OnTransitionJacobian(dfv_dxv_gt);
89 if ((dfv_dxv-dfv_dxv_gt).array().
abs().
sum()>KF_options.debug_verify_analytic_jacobians_threshold)
91 std::cerr <<
"[KalmanFilter] ERROR: User analytical transition Jacobians are wrong: \n"
92 <<
" Real dfv_dxv: \n" << dfv_dxv <<
"\n Analytical dfv_dxv:\n" << dfv_dxv_gt <<
"Diff:\n" << (dfv_dxv-dfv_dxv_gt) <<
"\n";
93 THROW_EXCEPTION(
"ERROR: User analytical transition Jacobians are wrong (More details dumped to cerr)")
101 OnTransitionNoise(Q);
107 Eigen::Block<typename KFMatrix::Base,VEH_SIZE,VEH_SIZE>(m_pkk,0,0) =
109 dfv_dxv * Eigen::Block<typename KFMatrix::Base,VEH_SIZE,VEH_SIZE>(m_pkk,0,0) * dfv_dxv.transpose();
116 for (
size_t i=0 ; i<N_map ; i++)
118 aux = dfv_dxv * Eigen::Block<typename KFMatrix::Base,VEH_SIZE,FEAT_SIZE>(m_pkk,0,VEH_SIZE+i*FEAT_SIZE);
120 Eigen::Block<typename KFMatrix::Base,VEH_SIZE,FEAT_SIZE>(m_pkk, 0 , VEH_SIZE+i*FEAT_SIZE) = aux;
121 Eigen::Block<typename KFMatrix::Base,FEAT_SIZE,VEH_SIZE>(m_pkk, VEH_SIZE+i*FEAT_SIZE , 0 ) = aux.transpose();
127 for (
size_t i=0;i<VEH_SIZE;i++)
131 OnNormalizeStateVector();
135 const double tim_pred = m_timLogger.leave(
"KF:2.prediction stage");
140 m_timLogger.enter(
"KF:3.predict all obs");
143 OnGetObservationNoise(R);
147 all_predictions.resize(N_map);
149 mrpt::math::sequenceStdVec<size_t,1>(0,N_map),
152 const double tim_pred_obs = m_timLogger.leave(
"KF:3.predict all obs");
154 m_timLogger.enter(
"KF:4.decide pred obs");
157 predictLMidxs.clear();
160 predictLMidxs.assign(1,0);
163 OnPreComputingPredictions(all_predictions, predictLMidxs);
166 m_timLogger.leave(
"KF:4.decide pred obs");
188 m_timLogger.enter(
"KF:5.build Jacobians");
190 size_t N_pred = FEAT_SIZE==0 ?
192 predictLMidxs.size();
198 std::vector<size_t> missing_predictions_to_add;
203 size_t first_new_pred = 0;
207 if (!missing_predictions_to_add.empty())
209 const size_t nNew = missing_predictions_to_add.size();
210 printf_debug(
"[KF] *Performance Warning*: %u LMs were not correctly predicted by OnPreComputingPredictions()\n",static_cast<unsigned int>(nNew));
213 for (
size_t j=0;j<nNew;j++)
214 predictLMidxs.push_back( missing_predictions_to_add[j] );
216 N_pred = predictLMidxs.size();
217 missing_predictions_to_add.clear();
223 for (
size_t i=first_new_pred;i<N_pred;++i)
225 const size_t lm_idx = FEAT_SIZE==0 ? 0 : predictLMidxs[i];
230 m_user_didnt_implement_jacobian=
false;
231 if (KF_options.use_analytic_observation_jacobian)
232 OnObservationJacobians(lm_idx,Hx,Hy);
234 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_observation_jacobian || KF_options.debug_verify_analytic_jacobians)
236 const size_t lm_idx_in_statevector = VEH_SIZE+lm_idx*FEAT_SIZE;
239 const KFArray_FEAT x_feat( &m_xkk[lm_idx_in_statevector] );
243 OnObservationJacobiansNumericGetIncrements(xkk_veh_increments, feat_increments);
247 &KF_aux_estimate_obs_Hx_jacobian,
249 std::pair<KFCLASS*,size_t>(
this,lm_idx),
252 ::memcpy(&m_xkk[0],&x_vehicle[0],
sizeof(m_xkk[0])*VEH_SIZE);
256 &KF_aux_estimate_obs_Hy_jacobian,
258 std::pair<KFCLASS*,size_t>(
this,lm_idx),
261 ::memcpy(&m_xkk[lm_idx_in_statevector],&x_feat[0],
sizeof(m_xkk[0])*FEAT_SIZE);
263 if (KF_options.debug_verify_analytic_jacobians)
267 OnObservationJacobians(lm_idx,Hx_gt,Hy_gt);
268 if ((Hx-Hx_gt).array().
abs().
sum()>KF_options.debug_verify_analytic_jacobians_threshold) {
269 std::cerr <<
"[KalmanFilter] ERROR: User analytical observation Hx Jacobians are wrong: \n"
270 <<
" Real Hx: \n" << Hx <<
"\n Analytical Hx:\n" << Hx_gt <<
"Diff:\n" << Hx-Hx_gt <<
"\n";
271 THROW_EXCEPTION(
"ERROR: User analytical observation Hx Jacobians are wrong (More details dumped to cerr)")
273 if ((Hy-Hy_gt).array().
abs().
sum()>KF_options.debug_verify_analytic_jacobians_threshold) {
274 std::cerr <<
"[KalmanFilter] ERROR: User analytical observation Hy Jacobians are wrong: \n"
275 <<
" Real Hy: \n" << Hy <<
"\n Analytical Hx:\n" << Hy_gt <<
"Diff:\n" << Hy-Hy_gt <<
"\n";
276 THROW_EXCEPTION(
"ERROR: User analytical observation Hy Jacobians are wrong (More details dumped to cerr)")
281 m_timLogger.leave(
"KF:5.build Jacobians");
283 m_timLogger.enter(
"KF:6.build S");
290 S.setSize(N_pred*OBS_SIZE,N_pred*OBS_SIZE);
294 const Eigen::Block<const typename KFMatrix::Base,VEH_SIZE,VEH_SIZE> Px(m_pkk,0,0);
296 for (
size_t i=0;i<N_pred;++i)
298 const size_t lm_idx_i = predictLMidxs[i];
299 const Eigen::Block<const typename KFMatrix::Base,FEAT_SIZE,VEH_SIZE> Pxyi_t(m_pkk,VEH_SIZE+lm_idx_i*FEAT_SIZE,0);
302 for (
size_t j=i;j<N_pred;++j)
304 const size_t lm_idx_j = predictLMidxs[j];
306 Eigen::Block<typename KFMatrix::Base, OBS_SIZE, OBS_SIZE> Sij(S,OBS_SIZE*i,OBS_SIZE*j);
308 const Eigen::Block<const typename KFMatrix::Base,VEH_SIZE,FEAT_SIZE> Pxyj(m_pkk,0, VEH_SIZE+lm_idx_j*FEAT_SIZE);
309 const Eigen::Block<const typename KFMatrix::Base,FEAT_SIZE,FEAT_SIZE> Pyiyj(m_pkk,VEH_SIZE+lm_idx_i*FEAT_SIZE,VEH_SIZE+lm_idx_j*FEAT_SIZE);
311 Sij = Hxs[i] * Px * Hxs[j].transpose()
312 + Hys[i] * Pxyi_t * Hxs[j].transpose()
313 + Hxs[i] * Pxyj * Hys[j].transpose()
314 + Hys[i] * Pyiyj * Hys[j].transpose();
318 Eigen::Block<typename KFMatrix::Base, OBS_SIZE, OBS_SIZE>(S,OBS_SIZE*j,OBS_SIZE*i) = Sij.transpose();
322 const size_t obs_idx_off = i*OBS_SIZE;
323 Eigen::Block<typename KFMatrix::Base, OBS_SIZE, OBS_SIZE>(S,obs_idx_off,obs_idx_off) += R;
331 S = Hxs[0] * m_pkk *Hxs[0].transpose() + R;
334 m_timLogger.leave(
"KF:6.build S");
338 m_timLogger.enter(
"KF:7.get obs & DA");
341 OnGetObservationsAndDataAssociation(
343 all_predictions, S, predictLMidxs, R
345 ASSERTDEB_(data_association.size()==Z.size() || (data_association.empty() && FEAT_SIZE==0));
350 missing_predictions_to_add.clear();
353 for (
size_t i=0;i<data_association.size();++i)
355 if (data_association[i]<0)
continue;
356 const size_t assoc_idx_in_map =
static_cast<size_t>(data_association[i]);
358 if (assoc_idx_in_pred==std::string::npos)
359 missing_predictions_to_add.push_back(assoc_idx_in_map);
363 first_new_pred = N_pred;
365 }
while (!missing_predictions_to_add.empty());
368 const double tim_obs_DA = m_timLogger.leave(
"KF:7.get obs & DA");
376 m_timLogger.enter(
"KF:8.update stage");
378 switch (KF_options.method)
389 vector_int mapIndicesForKFUpdate(data_association.size());
390 mapIndicesForKFUpdate.resize(
std::distance(mapIndicesForKFUpdate.begin(),
392 data_association.begin(),
393 data_association.end(),
394 mapIndicesForKFUpdate.begin(),
395 binder1st<equal_to<int> >(equal_to<int>(),-1) ) ) );
397 const size_t N_upd = (FEAT_SIZE==0) ?
399 mapIndicesForKFUpdate.size();
402 const size_t nKF_iterations = (KF_options.method==
kfEKFNaive) ? 1 : KF_options.IKF_iterations;
409 for (
size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
413 size_t ytilde_idx = 0;
416 dh_dx_full_obs.zeros(N_upd*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
422 S_idxs.reserve(OBS_SIZE*N_upd);
426 for (
size_t i=0;i<data_association.size();++i)
428 if (data_association[i]<0)
continue;
430 const size_t assoc_idx_in_map =
static_cast<size_t>(data_association[i]);
432 ASSERTMSG_(assoc_idx_in_pred!=string::npos,
"OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
440 Eigen::Block<typename KFMatrix::Base,OBS_SIZE,VEH_SIZE> (dh_dx_full_obs, S_idxs.size(),0) = Hxs[assoc_idx_in_pred];
441 Eigen::Block<typename KFMatrix::Base,OBS_SIZE,FEAT_SIZE>(dh_dx_full_obs, S_idxs.size(), VEH_SIZE+assoc_idx_in_map*FEAT_SIZE ) = Hys[assoc_idx_in_pred];
444 for (
size_t k=0;k<OBS_SIZE;k++)
445 S_idxs.push_back(assoc_idx_in_pred*OBS_SIZE+k);
449 OnSubstractObservationVectors(ytilde_i,all_predictions[predictLMidxs[assoc_idx_in_pred]]);
450 for (
size_t k=0;k<OBS_SIZE;k++)
451 ytilde[ytilde_idx++] = ytilde_i[k];
454 S.extractSubmatrixSymmetrical(S_idxs,S_observed);
458 ASSERT_(Z.size()==1 && all_predictions.size()==1)
459 ASSERT_(dh_dx_full_obs.getRowCount()==OBS_SIZE && dh_dx_full_obs.getColCount()==VEH_SIZE)
462 dh_dx_full_obs = Hxs[0];
464 OnSubstractObservationVectors(ytilde_i,all_predictions[0]);
465 for (
size_t k=0;k<OBS_SIZE;k++)
466 ytilde[ytilde_idx++] = ytilde_i[k];
473 m_timLogger.enter(
"KF:8.update stage:1.FULLKF:build K");
475 K.setSize(m_pkk.getRowCount(), S_observed.getColCount() );
478 K.multiply_ABt(m_pkk, dh_dx_full_obs);
484 m_timLogger.leave(
"KF:8.update stage:1.FULLKF:build K");
487 if (nKF_iterations==1)
489 m_timLogger.enter(
"KF:8.update stage:2.FULLKF:update xkk");
491 m_timLogger.leave(
"KF:8.update stage:2.FULLKF:update xkk");
495 m_timLogger.enter(
"KF:8.update stage:2.FULLKF:iter.update xkk");
498 dh_dx_full_obs.multiply_Ab( m_xkk - xkk_0, HAx_column);
507 m_timLogger.leave(
"KF:8.update stage:2.FULLKF:iter.update xkk");
512 if (IKF_iteration == (nKF_iterations-1) )
514 m_timLogger.enter(
"KF:8.update stage:3.FULLKF:update Pkk");
521 aux_K_dh_dx.multiply(K,dh_dx_full_obs);
524 const size_t stat_len = aux_K_dh_dx.getColCount();
525 for (
size_t r=0;r<stat_len;r++)
526 for (
size_t c=0;c<stat_len;c++)
528 aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c) +
kftype(1);
529 else aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c);
531 m_pkk.multiply_result_is_symmetric(aux_K_dh_dx, m_pkk );
533 m_timLogger.leave(
"KF:8.update stage:3.FULLKF:update Pkk");
546 for (
size_t obsIdx=0;obsIdx<Z.size();obsIdx++)
550 size_t idxInTheFilter=0;
552 if (data_association.empty())
558 doit = data_association[obsIdx] >= 0;
560 idxInTheFilter = data_association[obsIdx];
565 m_timLogger.enter(
"KF:8.update stage:1.ScalarAtOnce.prepare");
568 const size_t idx_off = VEH_SIZE + idxInTheFilter*FEAT_SIZE;
572 OnObservationModel(
vector_size_t(1,idxInTheFilter),pred_obs);
577 OnSubstractObservationVectors(ytilde, pred_obs[0]);
584 ASSERTMSG_(i_idx_in_preds!=string::npos,
"OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
589 m_timLogger.leave(
"KF:8.update stage:1.ScalarAtOnce.prepare");
592 for (
size_t j=0;j<OBS_SIZE;j++)
594 m_timLogger.enter(
"KF:8.update stage:2.ScalarAtOnce.update");
611 for (
size_t a=0;a<OBS_SIZE;a++)
612 for (
size_t b=0;b<OBS_SIZE;b++)
615 THROW_EXCEPTION(
"This KF algorithm assumes independent noise components in the observation (matrix R). Select another KF algorithm.")
619 KFTYPE Sij = R.get_unsafe(j,j);
622 for (
size_t k=0;k<VEH_SIZE;k++)
625 for (
size_t q=0;q<VEH_SIZE;q++)
626 accum += Hx.get_unsafe(j,q) * m_pkk.get_unsafe(q,k);
627 Sij+= Hx.get_unsafe(j,k) * accum;
632 for (
size_t k=0;k<VEH_SIZE;k++)
635 for (
size_t q=0;q<FEAT_SIZE;q++)
636 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,k);
637 term2+= Hx.get_unsafe(j,k) * accum;
642 for (
size_t k=0;k<FEAT_SIZE;k++)
645 for (
size_t q=0;q<FEAT_SIZE;q++)
646 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,idx_off+k);
647 Sij+= Hy.get_unsafe(j,k) * accum;
652 size_t N = m_pkk.getColCount();
653 vector<KFTYPE> Kij( N );
655 for (
size_t k=0;k<N;k++)
661 for (q=0;q<VEH_SIZE;q++)
662 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(j,q);
665 for (q=0;q<FEAT_SIZE;q++)
666 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(j,q);
668 Kij[k] = K_tmp / Sij;
674 for (
size_t k=0;k<N;k++)
675 m_xkk[k] += Kij[k] * ytilde[j];
680 for (
size_t k=0;k<N;k++)
682 for (
size_t q=k;q<N;q++)
684 m_pkk(k,q) -= Sij * Kij[k] * Kij[q];
686 m_pkk(q,k) = m_pkk(k,q);
689 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
692 m_pkk.saveToTextFile(
"Pkk_err.txt");
701 m_timLogger.leave(
"KF:8.update stage:2.ScalarAtOnce.update");
718 size_t nKF_iterations = KF_options.IKF_iterations;
722 if (nKF_iterations>1)
732 for (
size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
740 xkk_next_iter = xkk_0;
744 for (
size_t obsIdx=0;obsIdx<Z.getRowCount();obsIdx++)
748 size_t idxInTheFilter=0;
750 if (data_association.empty())
756 doit = data_association[obsIdx] >= 0;
758 idxInTheFilter = data_association[obsIdx];
764 const size_t idx_off = VEH_SIZE + idxInTheFilter *FEAT_SIZE;
765 const size_t R_row_offset = obsIdx*OBS_SIZE;
769 OnObservationModelAndJacobians(
809 R.extractMatrix(R_row_offset,0, Si);
825 KFMatrix Pyix( FEAT_SIZE, VEH_SIZE );
826 m_pkk.extractMatrix(idx_off,0, Pyix);
828 term.multiply_ABCt( Hy, Pyix, Hx );
845 size_t N = m_pkk.getColCount();
853 for (
size_t c=0;c<OBS_SIZE;c++)
858 for (q=0;q<VEH_SIZE;q++)
859 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(c,q);
862 for (q=0;q<FEAT_SIZE;q++)
863 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(c,q);
865 Ki.set_unsafe(k,c, K_tmp);
869 Ki.multiply(Ki, Si.inv() );
873 if (nKF_iterations==1)
878 for (
size_t q=0;q<OBS_SIZE;q++)
879 m_xkk[k] += Ki.get_unsafe(k,q) * ytilde[q];
884 Eigen::Matrix<KFTYPE,Eigen::Dynamic,1> HAx(OBS_SIZE);
887 for (o=0;o<OBS_SIZE;o++)
890 for (q=0;q<VEH_SIZE;q++)
891 tmp += Hx.get_unsafe(o,q) * (xkk_0[q] - m_xkk[q]);
893 for (q=0;q<FEAT_SIZE;q++)
894 tmp += Hy.get_unsafe(o,q) * (xkk_0[idx_off+q] - m_xkk[idx_off+q]);
900 for (o=0;o<OBS_SIZE;o++)
901 HAx[o] = ytilde[o] - HAx[o];
907 KFTYPE tmp = xkk_next_iter[k];
909 for (o=0;o<OBS_SIZE;o++)
910 tmp += Ki.get_unsafe(k,o) * HAx[o];
912 xkk_next_iter[k] = tmp;
921 Ki.multiplyByMatrixAndByTransposeNonSymmetric(
927 m_pkk.force_symmetry();
955 if (nKF_iterations>1)
958 cout <<
"IKF iter: " << IKF_iteration <<
" -> " << xkk_next_iter << endl;
960 m_xkk = xkk_next_iter;
966 if (saved_Pkk)
delete saved_Pkk;
978 const double tim_update = m_timLogger.leave(
"KF:8.update stage");
980 m_timLogger.enter(
"KF:9.OnNormalizeStateVector");
981 OnNormalizeStateVector();
982 m_timLogger.leave(
"KF:9.OnNormalizeStateVector");
987 if (!data_association.empty())
989 m_timLogger.enter(
"KF:A.add new landmarks");
991 m_timLogger.leave(
"KF:A.add new landmarks");
995 m_timLogger.enter(
"KF:B.OnPostIteration");
997 m_timLogger.leave(
"KF:B.OnPostIteration");
999 m_timLogger.leave(
"KF:complete_step");
1001 if (KF_options.verbose)
1003 printf_debug(
"[KF] %u LMs | Pr: %.2fms | Pr.Obs: %.2fms | Obs.DA: %.2fms | Upd: %.2fms\n",
1004 static_cast<unsigned int>(getNumberOfLandmarksInTheMap()),
1017 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1020 const std::pair<KFCLASS*,KFArray_ACT> &dat,
1025 dat.first->OnTransitionModel(dat.second,out_x, dumm);
1028 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1031 const std::pair<KFCLASS*,size_t> &dat,
1037 ::memcpy(&dat.first->m_xkk[0],&x[0],
sizeof(x[0])*VEH_SIZE);
1038 dat.first->OnObservationModel(idxs_to_predict,prediction);
1040 out_x=prediction[0];
1043 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1046 const std::pair<KFCLASS*,size_t> &dat,
1051 const size_t lm_idx_in_statevector = VEH_SIZE+FEAT_SIZE*dat.second;
1053 ::memcpy(&dat.first->m_xkk[lm_idx_in_statevector],&x[0],
sizeof(x[0])*FEAT_SIZE);
1054 dat.first->OnObservationModel(idxs_to_predict,prediction);
1056 out_x=prediction[0];
1063 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1073 for (
size_t idxObs=0;idxObs<Z.size();idxObs++)
1076 if ( data_association[idxObs] < 0 )
1085 const size_t newIndexInMap = (obj.
internal_getXkk().size() - VEH_SIZE) / FEAT_SIZE;
1088 typename KF::KFArray_FEAT yn;
1089 typename KF::KFMatrix_FxV dyn_dxv;
1090 typename KF::KFMatrix_FxO dyn_dhn;
1091 typename KF::KFMatrix_FxF dyn_dhn_R_dyn_dhnT;
1092 bool use_dyn_dhn_jacobian=
true;
1101 use_dyn_dhn_jacobian );
1116 for (q=0;q<FEAT_SIZE;q++)
1128 typename KF::KFMatrix_VxV Pxx;
1130 typename KF::KFMatrix_FxV Pxyn;
1131 Pxyn.multiply( dyn_dxv, Pxx );
1138 const size_t nLMs = (idx-VEH_SIZE)/FEAT_SIZE;
1139 for (q=0;q<nLMs;q++)
1145 P_cross.multiply(dyn_dxv, P_x_yq );
1147 obj.
internal_getPkk().insertMatrix(idx,VEH_SIZE+q*FEAT_SIZE, P_cross );
1148 obj.
internal_getPkk().insertMatrixTranspose(VEH_SIZE+q*FEAT_SIZE,idx, P_cross );
1155 dyn_dxv.multiply_HCHt(Pxx, P_yn_yn);
1156 if (use_dyn_dhn_jacobian)
1157 dyn_dhn.multiply_HCHt(R, P_yn_yn,
true);
1158 else P_yn_yn+=dyn_dhn_R_dyn_dhnT;
1167 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1178 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1184 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1190 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1196 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
mrpt::utils::CTimeLogger & getProfiler()
Virtual base for Kalman Filter (EKF,IEKF,UKF) implementations.
void BASE_IMPEXP memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) MRPT_NO_THROWS
An OS and compiler independent version of "memcpy".
CMatrixFixedNumeric< KFTYPE, VEH_SIZE, VEH_SIZE > KFMatrix_VxV
#define THROW_EXCEPTION(msg)
static void KF_aux_estimate_obs_Hx_jacobian(const KFArray_VEH &x, const std::pair< KFCLASS *, size_t > &dat, KFArray_OBS &out_x)
CMatrixFixedNumeric< KFTYPE, VEH_SIZE, FEAT_SIZE > KFMatrix_VxF
void runOneKalmanIteration()
The main entry point, executes one complete step: prediction + update.
static void KF_aux_estimate_trans_jacobian(const KFArray_VEH &x, const std::pair< KFCLASS *, KFArray_ACT > &dat, KFArray_VEH &out_x)
Auxiliary functions for Jacobian numeric estimation.
static void KF_aux_estimate_obs_Hy_jacobian(const KFArray_FEAT &x, const std::pair< KFCLASS *, size_t > &dat, KFArray_OBS &out_x)
mrpt::aligned_containers< KFArray_OBS >::vector_t vector_KFArray_OBS
virtual void OnNewLandmarkAddedToMap(const size_t in_obsIdx, const size_t in_idxNewFeat)
If applicable to the given problem, do here any special handling of adding a new landmark to the map...
std::vector< size_t > vector_size_t
A numeric matrix of compile-time fixed size.
CArrayNumeric< KFTYPE, ACT_SIZE > KFArray_ACT
std::vector< size_t > vector_size_t
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE > &obj)
CMatrixFixedNumeric< KFTYPE, OBS_SIZE, FEAT_SIZE > KFMatrix_OxF
void addNewLandmarks(CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE > &obj, const typename CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE >::vector_KFArray_OBS &Z, const vector_int &data_association, const typename CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE >::KFMatrix_OxO &R)
bool BASE_IMPEXP vectorToTextFile(const std::vector< float > &vec, const std::string &fileName, bool append=false, bool byRows=false)
A useful function for debugging, which saves a std::vector into a text file (compat.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
size_t getStateVectorLength() const
std::vector< int32_t > vector_int
bool isMapEmpty(const CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE > &obj)
CArrayNumeric< KFTYPE, VEH_SIZE > KFArray_VEH
virtual void OnInverseObservationModel(const KFArray_OBS &in_z, KFArray_FEAT &out_yn, KFMatrix_FxV &out_dyn_dxv, KFMatrix_FxO &out_dyn_dhn) const
If applicable to the given problem, this method implements the inverse observation model needed to ex...
KFTYPE kftype
The numeric type used in the Kalman Filter (default=double)
Eigen::Matrix< KFTYPE, Eigen::Dynamic, 1 > KFVector
double leave(const char *func_name)
End of a named section.
CMatrixTemplateNumeric< KFTYPE > KFMatrix
KFMatrix & internal_getPkk()
void estimateJacobian(const VECTORLIKE &x, void(*functor)(const VECTORLIKE &x, const USERPARAM &y, VECTORLIKE3 &out), const VECTORLIKE2 &increments, const USERPARAM &userParam, MATRIXLIKE &out_Jacobian)
Estimate the Jacobian of a multi-dimensional function around a point "x", using finite differences of...
size_t find_in_vector(const T &value, const CONTAINER &vect)
Returns the index of the value "T" in the container "vect" (std::vector,std::deque,etc), or string::npos if not found.
KFVector & internal_getXkk()
void enter(const char *func_name)
Start of a named section.
CArrayNumeric< KFTYPE, FEAT_SIZE > KFArray_FEAT
#define ASSERTMSG_(f, __ERROR_MSG)
CMatrixFixedNumeric< KFTYPE, OBS_SIZE, VEH_SIZE > KFMatrix_OxV
CArrayNumeric< KFTYPE, OBS_SIZE > KFArray_OBS
double BASE_IMPEXP distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.