28 #ifndef CKalmanFilterCapable_H
29 #define CKalmanFilterCapable_H
52 using namespace mrpt::utils;
53 using namespace mrpt::math;
70 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
class CKalmanFilterCapable;
83 void loadFromConfigFile(
85 const std::string §ion);
88 void dumpToTextStream(
CStream &out)
const;
104 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
107 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
110 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
113 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
145 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE =
double>
190 ASSERT_(idx<getNumberOfLandmarksInTheMap())
191 ::
memcpy(&feat[0], &m_xkk[VEH_SIZE+idx*FEAT_SIZE], FEAT_SIZE*
sizeof(m_xkk[0]));
197 m_pkk.extractMatrix(VEH_SIZE+idx*FEAT_SIZE,VEH_SIZE+idx*FEAT_SIZE,feat_cov);
218 virtual void OnGetAction(
KFArray_ACT &out_u )
const = 0;
226 virtual void OnTransitionModel(
229 bool &out_skipPrediction
238 m_user_didnt_implement_jacobian=
true;
243 virtual void OnTransitionJacobianNumericGetIncrements(
KFArray_VEH &out_increments)
const
245 for (
size_t i=0;i<VEH_SIZE;i++) out_increments[i] = 1e-6;
252 virtual void OnTransitionNoise( KFMatrix_VxV &out_Q )
const = 0;
261 virtual void OnPreComputingPredictions(
266 const size_t N = this->getNumberOfLandmarksInTheMap();
267 out_LM_indices_to_predict.resize(N);
268 for (
size_t i=0;i<N;i++) out_LM_indices_to_predict[i]=i;
275 virtual void OnGetObservationNoise(KFMatrix_OxO &out_R)
const = 0;
288 virtual void OnGetObservationsAndDataAssociation(
289 vector_KFArray_OBS &out_z,
291 const vector_KFArray_OBS &in_all_predictions,
292 const KFMatrix &in_S,
294 const KFMatrix_OxO &in_R
301 virtual void OnObservationModel(
303 vector_KFArray_OBS &out_predictions
311 virtual void OnObservationJacobians(
312 const size_t &idx_landmark_to_predict,
317 m_user_didnt_implement_jacobian=
true;
322 virtual void OnObservationJacobiansNumericGetIncrements(
326 for (
size_t i=0;i<VEH_SIZE;i++) out_veh_increments[i] = 1e-6;
327 for (
size_t i=0;i<FEAT_SIZE;i++) out_feat_increments[i] = 1e-6;
350 virtual void OnInverseObservationModel(
357 THROW_EXCEPTION(
"Inverse sensor model required but not implemented in derived class.")
383 virtual void OnInverseObservationModel(
389 bool & out_use_dyn_dhn_jacobian
393 OnInverseObservationModel(in_z,out_yn,out_dyn_dxv,out_dyn_dhn);
394 out_use_dyn_dhn_jacobian=
true;
403 virtual void OnNewLandmarkAddedToMap(
404 const size_t in_obsIdx,
405 const size_t in_idxNewFeat )
412 virtual void OnNormalizeStateVector()
419 virtual void OnPostIteration()
463 m_timLogger.enable(KF_options.enable_profiler || KF_options.verbose);
464 m_timLogger.enter(
"KF:complete_step");
466 ASSERT_(
size_t(m_xkk.size())==m_pkk.getColCount())
467 ASSERT_(
size_t(m_xkk.size())>=VEH_SIZE)
474 m_timLogger.enter(
"KF:1.OnGetAction");
476 m_timLogger.leave(
"KF:1.OnGetAction");
479 if (FEAT_SIZE) {
ASSERTDEB_( (((m_xkk.size()-VEH_SIZE)/FEAT_SIZE)*FEAT_SIZE)== (m_xkk.size()-VEH_SIZE) ) }
484 m_timLogger.enter(
"KF:2.prediction stage");
486 const size_t N_map = getNumberOfLandmarksInTheMap();
490 bool skipPrediction=
false;
494 OnTransitionModel(u, xv, skipPrediction);
496 if ( !skipPrediction )
505 m_user_didnt_implement_jacobian=
false;
506 if (KF_options.use_analytic_transition_jacobian)
507 OnTransitionJacobian(dfv_dxv);
509 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_transition_jacobian || KF_options.debug_verify_analytic_jacobians)
513 OnTransitionJacobianNumericGetIncrements(xkk_veh_increments);
517 &KF_aux_estimate_trans_jacobian,
519 std::make_pair<KFCLASS*,KFArray_ACT>(
this,u),
522 if (KF_options.debug_verify_analytic_jacobians)
525 OnTransitionJacobian(dfv_dxv_gt);
526 if ((dfv_dxv-dfv_dxv_gt).
Abs().
sumAll()>KF_options.debug_verify_analytic_jacobians_threshold)
528 std::cerr <<
"[KalmanFilter] ERROR: User analytical transition Jacobians are wrong: \n"
529 <<
" Real dfv_dxv: \n" << dfv_dxv <<
"\n Analytical dfv_dxv:\n" << dfv_dxv_gt <<
"Diff:\n" << (dfv_dxv-dfv_dxv_gt) <<
"\n";
530 THROW_EXCEPTION(
"ERROR: User analytical transition Jacobians are wrong (More details dumped to cerr)")
538 OnTransitionNoise(Q);
544 m_pkk.block(0,0,VEH_SIZE,VEH_SIZE) =
546 dfv_dxv * m_pkk.block(0,0,VEH_SIZE,VEH_SIZE) * dfv_dxv.transpose();
553 for (
size_t i=0 ; i<N_map ; i++)
556 dfv_dxv.multiply_subMatrix(
559 VEH_SIZE+i*FEAT_SIZE,
564 m_pkk.insertMatrix (0, VEH_SIZE+i*FEAT_SIZE, aux );
565 m_pkk.insertMatrixTranspose(VEH_SIZE+i*FEAT_SIZE, 0 , aux );
571 for (
size_t i=0;i<VEH_SIZE;i++)
575 OnNormalizeStateVector();
580 const double tim_pred = m_timLogger.leave(
"KF:2.prediction stage");
586 m_timLogger.enter(
"KF:3.predict all obs");
589 OnGetObservationNoise(R);
593 all_predictions.resize(N_map);
595 mrpt::math::sequenceStdVec<size_t,1>(0,N_map),
598 const double tim_pred_obs = m_timLogger.leave(
"KF:3.predict all obs");
600 m_timLogger.enter(
"KF:4.decide pred obs");
603 predictLMidxs.clear();
606 predictLMidxs.assign(1,0);
609 OnPreComputingPredictions(all_predictions, predictLMidxs);
612 m_timLogger.leave(
"KF:4.decide pred obs");
638 m_timLogger.enter(
"KF:5.build Jacobians");
640 size_t N_pred = FEAT_SIZE==0 ?
642 predictLMidxs.size();
648 std::vector<size_t> missing_predictions_to_add;
652 idxs.reserve(VEH_SIZE+N_pred*FEAT_SIZE);
653 for (
size_t i=0;i<VEH_SIZE;i++) idxs.push_back(i);
655 dh_dx.zeros(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_pred );
656 dh_dx_full.zeros(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
658 size_t first_new_pred = 0;
662 if (!missing_predictions_to_add.empty())
664 const size_t nNew = missing_predictions_to_add.size();
665 printf_debug(
"[KF] *Performance Warning*: %u LMs were not correctly predicted by OnPreComputingPredictions()\n",static_cast<unsigned int>(nNew));
668 for (
size_t j=0;j<nNew;j++)
669 predictLMidxs.push_back( missing_predictions_to_add[j] );
671 N_pred = predictLMidxs.size();
672 missing_predictions_to_add.clear();
675 dh_dx.setSize(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_pred );
676 dh_dx_full.setSize(N_pred*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
678 for (
size_t i=first_new_pred;i<N_pred;++i)
680 const size_t lm_idx = FEAT_SIZE==0 ? 0 : predictLMidxs[i];
685 m_user_didnt_implement_jacobian=
false;
686 if (KF_options.use_analytic_observation_jacobian)
687 OnObservationJacobians(lm_idx,Hx,Hy);
689 if (m_user_didnt_implement_jacobian || !KF_options.use_analytic_observation_jacobian || KF_options.debug_verify_analytic_jacobians)
691 const size_t lm_idx_in_statevector = VEH_SIZE+lm_idx*FEAT_SIZE;
694 const KFArray_FEAT x_feat( &m_xkk[lm_idx_in_statevector] );
698 OnObservationJacobiansNumericGetIncrements(xkk_veh_increments, feat_increments);
702 &KF_aux_estimate_obs_Hx_jacobian,
704 std::make_pair<KFCLASS*,size_t>(
this,lm_idx),
707 ::memcpy(&m_xkk[0],&x_vehicle[0],
sizeof(m_xkk[0])*VEH_SIZE);
711 &KF_aux_estimate_obs_Hy_jacobian,
713 std::make_pair<KFCLASS*,size_t>(
this,lm_idx),
716 ::memcpy(&m_xkk[lm_idx_in_statevector],&x_feat[0],
sizeof(m_xkk[0])*FEAT_SIZE);
718 if (KF_options.debug_verify_analytic_jacobians)
722 OnObservationJacobians(lm_idx,Hx_gt,Hy_gt);
723 if ((Hx-Hx_gt).
Abs().
sumAll()>KF_options.debug_verify_analytic_jacobians_threshold) {
724 std::cerr <<
"[KalmanFilter] ERROR: User analytical observation Hx Jacobians are wrong: \n"
725 <<
" Real Hx: \n" << Hx <<
"\n Analytical Hx:\n" << Hx_gt <<
"Diff:\n" << Hx-Hx_gt <<
"\n";
726 THROW_EXCEPTION(
"ERROR: User analytical observation Hx Jacobians are wrong (More details dumped to cerr)")
728 if ((Hy-Hy_gt).
Abs().
sumAll()>KF_options.debug_verify_analytic_jacobians_threshold) {
729 std::cerr <<
"[KalmanFilter] ERROR: User analytical observation Hy Jacobians are wrong: \n"
730 <<
" Real Hy: \n" << Hy <<
"\n Analytical Hx:\n" << Hy_gt <<
"Diff:\n" << Hy-Hy_gt <<
"\n";
731 THROW_EXCEPTION(
"ERROR: User analytical observation Hy Jacobians are wrong (More details dumped to cerr)")
736 dh_dx.insertMatrix(i*OBS_SIZE,0, Hx);
738 dh_dx.insertMatrix(i*OBS_SIZE,VEH_SIZE+i*FEAT_SIZE, Hy);
740 dh_dx_full.insertMatrix(i*OBS_SIZE,0, Hx);
743 dh_dx_full.insertMatrix(i*OBS_SIZE,VEH_SIZE+lm_idx*FEAT_SIZE, Hy);
745 for (
size_t k=0;k<FEAT_SIZE;k++)
746 idxs.push_back(k+VEH_SIZE+FEAT_SIZE*lm_idx);
749 m_timLogger.leave(
"KF:5.build Jacobians");
754 m_timLogger.enter(
"KF:6.build S");
756 S.setSize(N_pred*OBS_SIZE,N_pred*OBS_SIZE);
760 m_pkk.extractSubmatrixSymmetrical(idxs,Pkk_subset);
763 dh_dx.multiply_HCHt(Pkk_subset,S);
768 for (
size_t i=0;i<N_pred;++i)
770 const size_t obs_idx_off = i*OBS_SIZE;
771 for (
size_t j=0;j<OBS_SIZE;j++)
772 for (
size_t k=0;k<OBS_SIZE;k++)
773 S.get_unsafe(obs_idx_off+j,obs_idx_off+k) += R.get_unsafe(j,k);
782 m_timLogger.leave(
"KF:6.build S");
787 m_timLogger.enter(
"KF:7.get obs & DA");
790 OnGetObservationsAndDataAssociation(
792 all_predictions, S, predictLMidxs, R
794 ASSERTDEB_(data_association.size()==Z.size() || (data_association.empty() && FEAT_SIZE==0));
799 missing_predictions_to_add.clear();
802 for (
size_t i=0;i<data_association.size();++i)
804 if (data_association[i]<0)
continue;
805 const size_t assoc_idx_in_map =
static_cast<size_t>(data_association[i]);
807 if (assoc_idx_in_pred==std::string::npos)
808 missing_predictions_to_add.push_back(assoc_idx_in_map);
812 first_new_pred = N_pred;
814 }
while (!missing_predictions_to_add.empty());
817 const double tim_obs_DA = m_timLogger.leave(
"KF:7.get obs & DA");
825 m_timLogger.enter(
"KF:8.update stage");
827 switch (KF_options.method)
838 vector_int mapIndicesForKFUpdate(data_association.size());
839 mapIndicesForKFUpdate.resize(
std::distance(mapIndicesForKFUpdate.begin(),
841 data_association.begin(),
842 data_association.end(),
843 mapIndicesForKFUpdate.begin(),
844 binder1st<equal_to<int> >(equal_to<int>(),-1) ) ) );
846 const size_t N_upd = (FEAT_SIZE==0) ?
848 mapIndicesForKFUpdate.size();
851 const size_t nKF_iterations = (KF_options.method==
kfEKFNaive) ? 1 : KF_options.IKF_iterations;
858 for (
size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
862 size_t ytilde_idx = 0;
865 dh_dx_full_obs.zeros(N_upd*OBS_SIZE, VEH_SIZE + FEAT_SIZE * N_map );
871 S_idxs.reserve(OBS_SIZE*N_upd);
873 const size_t row_len = VEH_SIZE + FEAT_SIZE * N_map;
875 for (
size_t i=0;i<data_association.size();++i)
877 if (data_association[i]<0)
continue;
879 const size_t assoc_idx_in_map =
static_cast<size_t>(data_association[i]);
881 ASSERTMSG_(assoc_idx_in_pred!=string::npos,
"OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
885 dh_dx_full_obs.block(S_idxs.size() ,0, OBS_SIZE, row_len)
887 dh_dx_full.block (assoc_idx_in_pred*OBS_SIZE,0, OBS_SIZE, row_len);
889 for (
size_t k=0;k<OBS_SIZE;k++)
890 S_idxs.push_back(assoc_idx_in_pred*OBS_SIZE+k);
894 OnSubstractObservationVectors(ytilde_i,all_predictions[predictLMidxs[assoc_idx_in_pred]]);
895 for (
size_t k=0;k<OBS_SIZE;k++)
896 ytilde[ytilde_idx++] = ytilde_i[k];
899 S.extractSubmatrixSymmetrical(S_idxs,S_observed);
903 ASSERT_(Z.size()==1 && all_predictions.size()==1)
905 dh_dx_full_obs = dh_dx_full;
907 OnSubstractObservationVectors(ytilde_i,all_predictions[0]);
908 for (
size_t k=0;k<OBS_SIZE;k++)
909 ytilde[ytilde_idx++] = ytilde_i[k];
916 m_timLogger.enter(
"KF:8.update stage:1.FULLKF:build K");
918 K.setSize(m_pkk.getRowCount(), S_observed.getColCount() );
921 K.multiply_ABt(m_pkk, dh_dx_full_obs);
927 m_timLogger.leave(
"KF:8.update stage:1.FULLKF:build K");
930 if (nKF_iterations==1)
932 m_timLogger.enter(
"KF:8.update stage:2.FULLKF:update xkk");
934 m_timLogger.leave(
"KF:8.update stage:2.FULLKF:update xkk");
938 m_timLogger.enter(
"KF:8.update stage:2.FULLKF:iter.update xkk");
941 dh_dx_full_obs.multiply_Ab( m_xkk - xkk_0, HAx_column);
950 m_timLogger.leave(
"KF:8.update stage:2.FULLKF:iter.update xkk");
955 if (IKF_iteration == (nKF_iterations-1) )
957 m_timLogger.enter(
"KF:8.update stage:3.FULLKF:update Pkk");
964 aux_K_dh_dx.multiply(K,dh_dx_full_obs);
967 const size_t stat_len = aux_K_dh_dx.getColCount();
968 for (
size_t r=0;r<stat_len;r++)
969 for (
size_t c=0;c<stat_len;c++)
971 aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c) +
kftype(1);
972 else aux_K_dh_dx.get_unsafe(r,c)=-aux_K_dh_dx.get_unsafe(r,c);
974 m_pkk.multiply_result_is_symmetric(aux_K_dh_dx, m_pkk );
976 m_timLogger.leave(
"KF:8.update stage:3.FULLKF:update Pkk");
989 for (
size_t obsIdx=0;obsIdx<Z.size();obsIdx++)
993 size_t idxInTheFilter=0;
995 if (data_association.empty())
1001 doit = data_association[obsIdx] >= 0;
1003 idxInTheFilter = data_association[obsIdx];
1008 m_timLogger.enter(
"KF:8.update stage:1.ScalarAtOnce.prepare");
1011 const size_t idx_off = VEH_SIZE + idxInTheFilter*FEAT_SIZE;
1015 OnObservationModel(
vector_size_t(1,idxInTheFilter),pred_obs);
1020 OnSubstractObservationVectors(ytilde, pred_obs[0]);
1029 ASSERTMSG_(i_idx_in_preds!=string::npos,
"OnPreComputingPredictions() didn't recommend the prediction of a landmark which has been actually observed!")
1030 dh_dx.extractMatrix(i_idx_in_preds*OBS_SIZE,0, Hx);
1031 dh_dx.extractMatrix(i_idx_in_preds*OBS_SIZE,VEH_SIZE+i_idx_in_preds*OBS_SIZE, Hy);
1034 m_timLogger.leave(
"KF:8.update stage:1.ScalarAtOnce.prepare");
1037 for (
size_t j=0;j<OBS_SIZE;j++)
1039 m_timLogger.enter(
"KF:8.update stage:2.ScalarAtOnce.update");
1056 for (
size_t a=0;a<OBS_SIZE;a++)
1057 for (
size_t b=0;b<OBS_SIZE;b++)
1060 THROW_EXCEPTION(
"This KF algorithm assumes independent noise components in the observation (matrix R). Select another KF algorithm.")
1064 KFTYPE Sij = R.get_unsafe(j,j);
1067 for (
size_t k=0;k<VEH_SIZE;k++)
1070 for (
size_t q=0;q<VEH_SIZE;q++)
1071 accum += Hx.get_unsafe(j,q) * m_pkk.get_unsafe(q,k);
1072 Sij+= Hx.get_unsafe(j,k) * accum;
1077 for (
size_t k=0;k<VEH_SIZE;k++)
1080 for (
size_t q=0;q<FEAT_SIZE;q++)
1081 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,k);
1082 term2+= Hx.get_unsafe(j,k) * accum;
1087 for (
size_t k=0;k<FEAT_SIZE;k++)
1090 for (
size_t q=0;q<FEAT_SIZE;q++)
1091 accum += Hy.get_unsafe(j,q) * m_pkk.get_unsafe(idx_off+q,idx_off+k);
1092 Sij+= Hy.get_unsafe(j,k) * accum;
1097 size_t N = m_pkk.getColCount();
1098 vector<KFTYPE> Kij( N );
1100 for (
size_t k=0;k<N;k++)
1106 for (q=0;q<VEH_SIZE;q++)
1107 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(j,q);
1110 for (q=0;q<FEAT_SIZE;q++)
1111 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(j,q);
1113 Kij[k] = K_tmp / Sij;
1119 for (
size_t k=0;k<N;k++)
1120 m_xkk[k] += Kij[k] * ytilde[j];
1125 for (
size_t k=0;k<N;k++)
1127 for (
size_t q=k;q<N;q++)
1129 m_pkk(k,q) -= Sij * Kij[k] * Kij[q];
1131 m_pkk(q,k) = m_pkk(k,q);
1134 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG)
1137 m_pkk.saveToTextFile(
"Pkk_err.txt");
1146 m_timLogger.leave(
"KF:8.update stage:2.ScalarAtOnce.update");
1163 size_t nKF_iterations = KF_options.IKF_iterations;
1167 if (nKF_iterations>1)
1177 for (
size_t IKF_iteration=0;IKF_iteration<nKF_iterations;IKF_iteration++)
1182 if (IKF_iteration>0)
1185 xkk_next_iter = xkk_0;
1189 for (
size_t obsIdx=0;obsIdx<Z.getRowCount();obsIdx++)
1193 size_t idxInTheFilter=0;
1195 if (data_association.empty())
1201 doit = data_association[obsIdx] >= 0;
1203 idxInTheFilter = data_association[obsIdx];
1209 const size_t idx_off = VEH_SIZE + idxInTheFilter *FEAT_SIZE;
1210 const size_t R_row_offset = obsIdx*OBS_SIZE;
1214 OnObservationModelAndJacobians(
1254 R.extractMatrix(R_row_offset,0, Si);
1270 KFMatrix Pyix( FEAT_SIZE, VEH_SIZE );
1271 m_pkk.extractMatrix(idx_off,0, Pyix);
1273 term.multiply_ABCt( Hy, Pyix, Hx );
1290 size_t N = m_pkk.getColCount();
1298 for (
size_t c=0;c<OBS_SIZE;c++)
1303 for (q=0;q<VEH_SIZE;q++)
1304 K_tmp+= m_pkk.get_unsafe(k,q) * Hx.get_unsafe(c,q);
1307 for (q=0;q<FEAT_SIZE;q++)
1308 K_tmp+= m_pkk.get_unsafe(k,idx_off+q) * Hy.get_unsafe(c,q);
1310 Ki.set_unsafe(k,c, K_tmp);
1314 Ki.multiply(Ki, Si.inv() );
1318 if (nKF_iterations==1)
1323 for (
size_t q=0;q<OBS_SIZE;q++)
1324 m_xkk[k] += Ki.get_unsafe(k,q) * ytilde[q];
1332 for (o=0;o<OBS_SIZE;o++)
1335 for (q=0;q<VEH_SIZE;q++)
1336 tmp += Hx.get_unsafe(o,q) * (xkk_0[q] - m_xkk[q]);
1338 for (q=0;q<FEAT_SIZE;q++)
1339 tmp += Hy.get_unsafe(o,q) * (xkk_0[idx_off+q] - m_xkk[idx_off+q]);
1345 for (o=0;o<OBS_SIZE;o++)
1346 HAx[o] = ytilde[o] - HAx[o];
1352 KFTYPE tmp = xkk_next_iter[k];
1354 for (o=0;o<OBS_SIZE;o++)
1355 tmp += Ki.get_unsafe(k,o) * HAx[o];
1357 xkk_next_iter[k] = tmp;
1366 Ki.multiplyByMatrixAndByTransposeNonSymmetric(
1372 m_pkk.force_symmetry();
1400 if (nKF_iterations>1)
1403 cout <<
"IKF iter: " << IKF_iteration <<
" -> " << xkk_next_iter << endl;
1405 m_xkk = xkk_next_iter;
1411 if (saved_Pkk)
delete saved_Pkk;
1423 const double tim_update = m_timLogger.leave(
"KF:8.update stage");
1425 m_timLogger.enter(
"KF:9.OnNormalizeStateVector");
1426 OnNormalizeStateVector();
1427 m_timLogger.leave(
"KF:9.OnNormalizeStateVector");
1432 if (!data_association.empty())
1434 m_timLogger.enter(
"KF:A.add new landmarks");
1436 m_timLogger.leave(
"KF:A.add new landmarks");
1440 m_timLogger.enter(
"KF:B.OnPostIteration");
1442 m_timLogger.leave(
"KF:B.OnPostIteration");
1444 m_timLogger.leave(
"KF:complete_step");
1446 if (KF_options.verbose)
1448 printf_debug(
"[KF] %u LMs | Pr: %.2fms | Pr.Obs: %.2fms | Obs.DA: %.2fms | Upd: %.2fms\n",
1449 static_cast<unsigned int>(getNumberOfLandmarksInTheMap()),
1463 mutable bool m_user_didnt_implement_jacobian;
1466 static void KF_aux_estimate_trans_jacobian(
1468 const std::pair<KFCLASS*,KFArray_ACT> &dat,
1473 dat.first->OnTransitionModel(dat.second,out_x, dumm);
1475 static void KF_aux_estimate_obs_Hx_jacobian(
1476 const KFArray_VEH &x,
1477 const std::pair<KFCLASS*,size_t> &dat,
1481 vector_KFArray_OBS prediction;
1483 ::memcpy(&dat.first->m_xkk[0],&x[0],
sizeof(x[0])*VEH_SIZE);
1484 dat.first->OnObservationModel(idxs_to_predict,prediction);
1486 out_x=prediction[0];
1488 static void KF_aux_estimate_obs_Hy_jacobian(
1489 const KFArray_FEAT &x,
1490 const std::pair<KFCLASS*,size_t> &dat,
1494 vector_KFArray_OBS prediction;
1495 const size_t lm_idx_in_statevector = VEH_SIZE+FEAT_SIZE*dat.second;
1497 ::memcpy(&dat.first->m_xkk[lm_idx_in_statevector],&x[0],
sizeof(x[0])*FEAT_SIZE);
1498 dat.first->OnObservationModel(idxs_to_predict,prediction);
1500 out_x=prediction[0];
1512 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1522 for (
size_t idxObs=0;idxObs<Z.size();idxObs++)
1525 if ( data_association[idxObs] < 0 )
1534 const size_t newIndexInMap = (obj.
m_xkk.size() - VEH_SIZE) / FEAT_SIZE;
1537 typename KF::KFArray_FEAT yn;
1538 typename KF::KFMatrix_FxV dyn_dxv;
1539 typename KF::KFMatrix_FxO dyn_dhn;
1540 typename KF::KFMatrix_FxF dyn_dhn_R_dyn_dhnT;
1541 bool use_dyn_dhn_jacobian=
true;
1550 use_dyn_dhn_jacobian );
1562 size_t idx = obj.
m_xkk.size();
1565 for (q=0;q<FEAT_SIZE;q++)
1566 obj.
m_xkk[idx+q] = yn[q];
1573 obj.
m_pkk.setSize( idx+FEAT_SIZE,idx+FEAT_SIZE );
1577 typename KF::KFMatrix_VxV Pxx;
1578 obj.
m_pkk.extractMatrix(0,0,Pxx);
1579 typename KF::KFMatrix_FxV Pxyn;
1580 Pxyn.multiply( dyn_dxv, Pxx );
1582 obj.
m_pkk.insertMatrix( idx,0, Pxyn );
1583 obj.
m_pkk.insertMatrixTranspose( 0,idx, Pxyn );
1587 const size_t nLMs = (idx-VEH_SIZE)/FEAT_SIZE;
1588 for (q=0;q<nLMs;q++)
1591 obj.
m_pkk.extractMatrix(0,VEH_SIZE+q*FEAT_SIZE,P_x_yq) ;
1594 P_cross.multiply(dyn_dxv, P_x_yq );
1596 obj.
m_pkk.insertMatrix(idx,VEH_SIZE+q*FEAT_SIZE, P_cross );
1597 obj.
m_pkk.insertMatrixTranspose(VEH_SIZE+q*FEAT_SIZE,idx, P_cross );
1604 dyn_dxv.multiply_HCHt(Pxx, P_yn_yn);
1605 if (use_dyn_dhn_jacobian)
1606 dyn_dhn.multiply_HCHt(R, P_yn_yn,
true);
1607 else P_yn_yn+=dyn_dhn_R_dyn_dhnT;
1609 obj.
m_pkk.insertMatrix(idx,idx, P_yn_yn );
1616 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1629 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1635 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1641 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1647 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>