11 #ifndef CKalmanFilterCapable_H 12 #error Include this file only from 'CKalmanFilterCapable.h' 17 #include <Eigen/Dense> 25 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
27 void CKalmanFilterCapable<
28 VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE>::runOneKalmanIteration()
33 m_timLogger.enable(KF_options.enable_profiler);
34 m_timLogger.enter(
"KF:complete_step");
36 ASSERT_(
int(m_xkk.size()) == m_pkk.cols());
37 ASSERT_(
size_t(m_xkk.size()) >= VEH_SIZE);
43 m_timLogger.enter(
"KF:1.OnGetAction");
45 m_timLogger.leave(
"KF:1.OnGetAction");
51 (((m_xkk.size() - VEH_SIZE) / FEAT_SIZE) * FEAT_SIZE) ==
52 (m_xkk.size() - VEH_SIZE));
58 m_timLogger.enter(
"KF:2.prediction stage");
60 const size_t N_map = getNumberOfLandmarksInTheMap();
65 bool skipPrediction =
false;
73 OnTransitionModel(u, xv, skipPrediction);
85 m_user_didnt_implement_jacobian =
false;
88 if (KF_options.use_analytic_transition_jacobian)
89 OnTransitionJacobian(dfv_dxv);
91 if (m_user_didnt_implement_jacobian ||
92 !KF_options.use_analytic_transition_jacobian ||
93 KF_options.debug_verify_analytic_jacobians)
98 OnTransitionJacobianNumericGetIncrements(xkk_veh_increments);
104 const std::pair<KFCLASS*, KFArray_ACT>& dat,
105 KFArray_VEH& out_x)>(&KF_aux_estimate_trans_jacobian),
106 xkk_veh_increments, std::pair<KFCLASS*, KFArray_ACT>(
this, u),
109 if (KF_options.debug_verify_analytic_jacobians)
112 OnTransitionJacobian(dfv_dxv_gt);
113 if ((dfv_dxv - dfv_dxv_gt).sum_abs() >
114 KF_options.debug_verify_analytic_jacobians_threshold)
116 std::cerr <<
"[KalmanFilter] ERROR: User analytical " 117 "transition Jacobians are wrong: \n" 118 <<
" Real dfv_dxv: \n" 119 << dfv_dxv <<
"\n Analytical dfv_dxv:\n" 120 << dfv_dxv_gt <<
"Diff:\n" 121 << (dfv_dxv - dfv_dxv_gt) <<
"\n";
123 "ERROR: User analytical transition Jacobians are wrong " 124 "(More details dumped to cerr)");
132 OnTransitionNoise(Q);
138 m_pkk.asEigen().template block<VEH_SIZE, VEH_SIZE>(0, 0) =
140 m_pkk.template block<VEH_SIZE, VEH_SIZE>(0, 0) *
148 for (
size_t i = 0; i < N_map; i++)
150 aux = dfv_dxv.
asEigen() * m_pkk.template block<VEH_SIZE, FEAT_SIZE>(
151 0, VEH_SIZE + i * FEAT_SIZE);
153 m_pkk.asEigen().template block<VEH_SIZE, FEAT_SIZE>(
154 0, VEH_SIZE + i * FEAT_SIZE) = aux.
asEigen();
155 m_pkk.asEigen().template block<FEAT_SIZE, VEH_SIZE>(
156 VEH_SIZE + i * FEAT_SIZE, 0) = aux.
asEigen().transpose();
162 for (
size_t i = 0; i < VEH_SIZE; i++) m_xkk[i] = xv[i];
165 OnNormalizeStateVector();
169 const double tim_pred = m_timLogger.leave(
"KF:2.prediction stage");
174 m_timLogger.enter(
"KF:3.predict all obs");
177 OnGetObservationNoise(
R);
181 m_all_predictions.resize(N_map);
183 mrpt::math::sequenceStdVec<size_t, 1>(0, N_map), m_all_predictions);
185 const double tim_pred_obs = m_timLogger.leave(
"KF:3.predict all obs");
187 m_timLogger.enter(
"KF:4.decide pred obs");
190 m_predictLMidxs.clear();
194 m_predictLMidxs.assign(1, 0);
197 OnPreComputingPredictions(m_all_predictions, m_predictLMidxs);
199 m_timLogger.leave(
"KF:4.decide pred obs");
222 m_timLogger.enter(
"KF:5.build Jacobians");
227 : m_predictLMidxs.size();
237 std::vector<size_t> missing_predictions_to_add;
239 m_Hxs.resize(N_pred);
240 m_Hys.resize(N_pred);
242 size_t first_new_pred = 0;
248 if (!missing_predictions_to_add.empty())
250 const size_t nNew = missing_predictions_to_add.size();
252 "[KF] *Performance Warning*: " 254 <<
" LMs were not correctly predicted by " 255 "OnPreComputingPredictions().");
258 for (
size_t j = 0; j < nNew; j++)
259 m_predictLMidxs.push_back(missing_predictions_to_add[j]);
261 N_pred = m_predictLMidxs.size();
262 missing_predictions_to_add.clear();
265 m_Hxs.resize(N_pred);
266 m_Hys.resize(N_pred);
268 for (
size_t i = first_new_pred; i < N_pred; ++i)
270 const size_t lm_idx = FEAT_SIZE == 0 ? 0 : m_predictLMidxs[i];
275 m_user_didnt_implement_jacobian =
278 if (KF_options.use_analytic_observation_jacobian)
279 OnObservationJacobians(lm_idx, Hx, Hy);
281 if (m_user_didnt_implement_jacobian ||
282 !KF_options.use_analytic_observation_jacobian ||
283 KF_options.debug_verify_analytic_jacobians)
285 const size_t lm_idx_in_statevector =
286 VEH_SIZE + lm_idx * FEAT_SIZE;
289 const KFArray_FEAT x_feat(&m_xkk[lm_idx_in_statevector]);
293 OnObservationJacobiansNumericGetIncrements(
294 xkk_veh_increments, feat_increments);
300 const std::pair<KFCLASS*, size_t>& dat,
301 KFArray_OBS& out_x)>(&KF_aux_estimate_obs_Hx_jacobian),
303 std::pair<KFCLASS*, size_t>(
this, lm_idx), Hx);
306 ::memcpy(&m_xkk[0], &x_vehicle[0],
sizeof(m_xkk[0]) * VEH_SIZE);
312 const std::pair<KFCLASS*, size_t>& dat,
313 KFArray_OBS& out_x)>(&KF_aux_estimate_obs_Hy_jacobian),
314 feat_increments, std::pair<KFCLASS*, size_t>(
this, lm_idx),
319 &m_xkk[lm_idx_in_statevector], &x_feat[0],
320 sizeof(m_xkk[0]) * FEAT_SIZE);
322 if (KF_options.debug_verify_analytic_jacobians)
326 OnObservationJacobians(lm_idx, Hx_gt, Hy_gt);
327 if (
KFMatrix(Hx - Hx_gt).sum_abs() >
328 KF_options.debug_verify_analytic_jacobians_threshold)
330 std::cerr <<
"[KalmanFilter] ERROR: User analytical " 331 "observation Hx Jacobians are wrong: \n" 333 << Hx.
asEigen() <<
"\n Analytical Hx:\n" 334 << Hx_gt.
asEigen() <<
"Diff:\n" 337 "ERROR: User analytical observation Hx Jacobians " 338 "are wrong (More details dumped to cerr)");
340 if (
KFMatrix(Hy - Hy_gt).sum_abs() >
341 KF_options.debug_verify_analytic_jacobians_threshold)
343 std::cerr <<
"[KalmanFilter] ERROR: User analytical " 344 "observation Hy Jacobians are wrong: \n" 346 << Hy.
asEigen() <<
"\n Analytical Hx:\n" 347 << Hy_gt.
asEigen() <<
"Diff:\n" 350 "ERROR: User analytical observation Hy Jacobians " 351 "are wrong (More details dumped to cerr)");
356 m_timLogger.leave(
"KF:5.build Jacobians");
358 m_timLogger.enter(
"KF:6.build m_S");
365 m_S.setSize(N_pred * OBS_SIZE, N_pred * OBS_SIZE);
370 const auto Px = m_pkk.template block<VEH_SIZE, VEH_SIZE>(0, 0);
372 for (
size_t i = 0; i < N_pred; ++i)
374 const size_t lm_idx_i = m_predictLMidxs[i];
376 const auto Pxyi_t = m_pkk.template block<FEAT_SIZE, VEH_SIZE>(
377 VEH_SIZE + lm_idx_i * FEAT_SIZE, 0);
380 for (
size_t j = i; j < N_pred; ++j)
382 const size_t lm_idx_j = m_predictLMidxs[j];
386 const auto Pxyj = m_pkk.template block<VEH_SIZE, FEAT_SIZE>(
387 0, VEH_SIZE + lm_idx_j * FEAT_SIZE);
389 m_pkk.template block<FEAT_SIZE, FEAT_SIZE>(
390 VEH_SIZE + lm_idx_i * FEAT_SIZE,
391 VEH_SIZE + lm_idx_j * FEAT_SIZE);
394 Sij = m_Hxs[i].
asEigen() * Px * m_Hxs[j].asEigen().transpose() +
395 m_Hys[i].asEigen() * Pxyi_t * m_Hxs[j].asEigen().transpose() +
396 m_Hxs[i].asEigen() * Pxyj * m_Hys[j].asEigen().transpose() +
397 m_Hys[i].asEigen() * Pyiyj * m_Hys[j].asEigen().transpose();
400 m_S.insertMatrix(OBS_SIZE * i, OBS_SIZE * j, Sij);
404 m_S.insertMatrixTransposed(
405 OBS_SIZE * j, OBS_SIZE * i, Sij);
409 const size_t obs_idx_off = i * OBS_SIZE;
410 m_S.asEigen().template block<OBS_SIZE, OBS_SIZE>(
411 obs_idx_off, obs_idx_off) +=
R.asEigen();
419 m_S = m_Hxs[0].asEigen() * m_pkk.asEigen() *
420 m_Hxs[0].asEigen().transpose() +
424 m_timLogger.leave(
"KF:6.build m_S");
428 m_timLogger.enter(
"KF:7.get obs & DA");
431 OnGetObservationsAndDataAssociation(
432 m_Z, data_association,
433 m_all_predictions, m_S, m_predictLMidxs,
R 436 data_association.size() == m_Z.size() ||
437 (data_association.empty() && FEAT_SIZE == 0));
444 missing_predictions_to_add.clear();
447 for (
int i : data_association)
450 const auto assoc_idx_in_map =
static_cast<size_t>(i);
451 const size_t assoc_idx_in_pred =
453 assoc_idx_in_map, m_predictLMidxs);
454 if (assoc_idx_in_pred == std::string::npos)
455 missing_predictions_to_add.push_back(assoc_idx_in_map);
459 first_new_pred = N_pred;
462 }
while (!missing_predictions_to_add.empty());
464 const double tim_obs_DA = m_timLogger.leave(
"KF:7.get obs & DA");
472 m_timLogger.enter(
"KF:8.update stage");
474 switch (KF_options.method)
485 std::vector<int> mapIndicesForKFUpdate(data_association.size());
487 mapIndicesForKFUpdate.begin(),
489 data_association.begin(), data_association.end(),
490 mapIndicesForKFUpdate.begin(),
491 [](
int i) {
return i == -1; })));
494 (FEAT_SIZE == 0) ? 1 :
497 mapIndicesForKFUpdate
501 const size_t nKF_iterations = (KF_options.method ==
kfEKFNaive)
503 : KF_options.IKF_iterations;
510 for (
size_t IKF_iteration = 0;
511 IKF_iteration < nKF_iterations; IKF_iteration++)
515 size_t ytilde_idx = 0;
519 m_dh_dx_full_obs.setZero(
521 VEH_SIZE + FEAT_SIZE * N_map);
528 std::vector<size_t> S_idxs;
529 S_idxs.reserve(OBS_SIZE * N_upd);
534 for (
size_t i = 0; i < data_association.size(); ++i)
536 if (data_association[i] < 0)
continue;
538 const auto assoc_idx_in_map =
539 static_cast<size_t>(data_association[i]);
540 const size_t assoc_idx_in_pred =
542 assoc_idx_in_map, m_predictLMidxs);
544 assoc_idx_in_pred != string::npos,
545 "OnPreComputingPredictions() didn't " 546 "recommend the prediction of a landmark " 547 "which has been actually observed!");
561 .template block<OBS_SIZE, VEH_SIZE>(
563 m_Hxs[assoc_idx_in_pred].asEigen();
565 .template block<OBS_SIZE, FEAT_SIZE>(
568 assoc_idx_in_map * FEAT_SIZE) =
569 m_Hys[assoc_idx_in_pred].asEigen();
573 for (
size_t k = 0; k < OBS_SIZE; k++)
575 assoc_idx_in_pred * OBS_SIZE + k);
579 OnSubstractObservationVectors(
582 [m_predictLMidxs[assoc_idx_in_pred]]);
583 for (
size_t k = 0; k < OBS_SIZE; k++)
584 ytilde[ytilde_idx++] = ytilde_i[k];
589 m_S, S_idxs, S_observed);
595 m_all_predictions.size() == 1);
597 m_dh_dx_full_obs.rows() == OBS_SIZE &&
598 m_dh_dx_full_obs.cols() == VEH_SIZE);
600 m_dh_dx_full_obs = m_Hxs[0];
602 OnSubstractObservationVectors(
603 ytilde_i, m_all_predictions[0]);
604 for (
size_t k = 0; k < OBS_SIZE; k++)
605 ytilde[ytilde_idx++] = ytilde_i[k];
613 m_timLogger.enter(
"KF:8.update stage:1.FULLKF:build K");
618 m_K.asEigen() = m_pkk.asEigen() *
619 m_dh_dx_full_obs.asEigen().transpose();
623 m_K.asEigen() *= m_S_1.asEigen();
625 m_timLogger.leave(
"KF:8.update stage:1.FULLKF:build K");
628 if (nKF_iterations == 1)
631 "KF:8.update stage:2.FULLKF:update xkk");
632 m_xkk.asEigen() += (m_K * ytilde).eval();
634 "KF:8.update stage:2.FULLKF:update xkk");
639 "KF:8.update stage:2.FULLKF:iter.update xkk");
642 KFVector(m_dh_dx_full_obs * (m_xkk - xkk_0));
645 m_xkk.asEigen() += m_K * (ytilde - HAx_column);
648 "KF:8.update stage:2.FULLKF:iter.update xkk");
654 if (IKF_iteration == (nKF_iterations - 1))
657 "KF:8.update stage:3.FULLKF:update Pkk");
664 m_aux_K_dh_dx.matProductOf_AB(
665 m_K, m_dh_dx_full_obs);
668 const size_t stat_len = m_aux_K_dh_dx.cols();
669 for (
size_t r = 0;
r < stat_len;
r++)
671 for (
size_t c = 0;
c < stat_len;
c++)
674 m_aux_K_dh_dx(
r,
c) =
677 m_aux_K_dh_dx(
r,
c) =
678 -m_aux_K_dh_dx(
r,
c);
682 m_pkk = m_aux_K_dh_dx * m_pkk;
685 "KF:8.update stage:3.FULLKF:update Pkk");
698 for (
size_t obsIdx = 0; obsIdx < m_Z.size(); obsIdx++)
702 size_t idxInTheFilter = 0;
704 if (data_association.empty())
710 doit = data_association[obsIdx] >= 0;
711 if (doit) idxInTheFilter = data_association[obsIdx];
717 "KF:8.update stage:1.ScalarAtOnce.prepare");
720 const size_t idx_off =
729 std::vector<size_t>(1, idxInTheFilter), pred_obs);
734 OnSubstractObservationVectors(ytilde, pred_obs[0]);
741 const size_t i_idx_in_preds =
743 idxInTheFilter, m_predictLMidxs);
745 i_idx_in_preds != string::npos,
746 "OnPreComputingPredictions() didn't recommend the " 747 "prediction of a landmark which has been actually " 754 "KF:8.update stage:1.ScalarAtOnce.prepare");
757 for (
size_t j = 0; j < OBS_SIZE; j++)
760 "KF:8.update stage:2.ScalarAtOnce.update");
784 for (
size_t a = 0;
a < OBS_SIZE;
a++)
785 for (
size_t b = 0;
b < OBS_SIZE;
b++)
789 "This KF algorithm assumes " 792 "observation (matrix R). " 798 KFTYPE Sij =
R(j, j);
801 for (
size_t k = 0; k < VEH_SIZE; k++)
804 for (
size_t q = 0;
q < VEH_SIZE;
q++)
805 accum += Hx(j,
q) * m_pkk(
q, k);
806 Sij += Hx(j, k) * accum;
811 for (
size_t k = 0; k < VEH_SIZE; k++)
814 for (
size_t q = 0;
q < FEAT_SIZE;
q++)
815 accum += Hy(j,
q) * m_pkk(idx_off +
q, k);
816 term2 += Hx(j, k) * accum;
821 for (
size_t k = 0; k < FEAT_SIZE; k++)
824 for (
size_t q = 0;
q < FEAT_SIZE;
q++)
826 m_pkk(idx_off +
q, idx_off + k);
827 Sij += Hy(j, k) * accum;
833 size_t N = m_pkk.
cols();
834 vector<KFTYPE> Kij(N);
836 for (
size_t k = 0; k < N; k++)
842 for (
q = 0;
q < VEH_SIZE;
q++)
843 K_tmp += m_pkk(k,
q) * Hx(j,
q);
846 for (
q = 0;
q < FEAT_SIZE;
q++)
847 K_tmp += m_pkk(k, idx_off +
q) * Hy(j,
q);
849 Kij[k] = K_tmp / Sij;
854 for (
size_t k = 0; k < N; k++)
855 m_xkk[k] += Kij[k] * ytilde[j];
860 for (
size_t k = 0; k < N; k++)
862 for (
size_t q = k;
q < N;
865 m_pkk(k,
q) -= Sij * Kij[k] * Kij[
q];
867 m_pkk(
q, k) = m_pkk(k,
q);
870 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG) 873 m_pkk.saveToTextFile(
"Pkk_err.txt");
883 "KF:8.update stage:2.ScalarAtOnce.update");
904 const double tim_update = m_timLogger.leave(
"KF:8.update stage");
906 m_timLogger.enter(
"KF:9.OnNormalizeStateVector");
907 OnNormalizeStateVector();
908 m_timLogger.leave(
"KF:9.OnNormalizeStateVector");
913 if (!data_association.empty())
915 m_timLogger.enter(
"KF:A.add new landmarks");
917 m_timLogger.leave(
"KF:A.add new landmarks");
921 m_timLogger.enter(
"KF:B.OnPostIteration");
923 m_timLogger.leave(
"KF:B.OnPostIteration");
925 m_timLogger.leave(
"KF:complete_step");
928 "[KF] %u LMs | Pr: %.2fms | Pr.Obs: %.2fms | Obs.DA: %.2fms | Upd: " 930 static_cast<unsigned int>(getNumberOfLandmarksInTheMap()),
931 1e3 * tim_pred, 1e3 * tim_pred_obs, 1e3 * tim_obs_DA,
937 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
941 const KFArray_VEH&
x,
const std::pair<KFCLASS*, KFArray_ACT>& dat,
946 dat.first->OnTransitionModel(dat.second, out_x, dumm);
950 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
954 const KFArray_VEH&
x,
const std::pair<KFCLASS*, size_t>& dat,
957 std::vector<size_t> idxs_to_predict(1, dat.second);
960 ::memcpy(&dat.first->m_xkk[0], &
x[0],
sizeof(
x[0]) * VEH_SIZE);
961 dat.first->OnObservationModel(idxs_to_predict, prediction);
963 out_x = prediction[0];
967 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
971 const KFArray_FEAT&
x,
const std::pair<KFCLASS*, size_t>& dat,
974 std::vector<size_t> idxs_to_predict(1, dat.second);
976 const size_t lm_idx_in_statevector = VEH_SIZE + FEAT_SIZE * dat.second;
979 &dat.first->m_xkk[lm_idx_in_statevector], &
x[0],
980 sizeof(
x[0]) * FEAT_SIZE);
981 dat.first->OnObservationModel(idxs_to_predict, prediction);
983 out_x = prediction[0];
990 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
995 VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE>::vector_KFArray_OBS& Z,
996 const std::vector<int>& data_association,
998 VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE>::KFMatrix_OxO&
R)
1003 for (
size_t idxObs = 0; idxObs < Z.size(); idxObs++)
1006 if (data_association[idxObs] < 0)
1014 0 == ((
obj.internal_getXkk().size() - VEH_SIZE) %
1017 const size_t newIndexInMap =
1018 (
obj.internal_getXkk().size() - VEH_SIZE) / FEAT_SIZE;
1021 typename KF::KFArray_FEAT yn;
1022 typename KF::KFMatrix_FxV dyn_dxv;
1023 typename KF::KFMatrix_FxO dyn_dhn;
1024 typename KF::KFMatrix_FxF dyn_dhn_R_dyn_dhnT;
1025 bool use_dyn_dhn_jacobian =
true;
1028 obj.OnInverseObservationModel(
1029 Z[idxObs], yn, dyn_dxv, dyn_dhn, dyn_dhn_R_dyn_dhnT,
1030 use_dyn_dhn_jacobian);
1034 obj.OnNewLandmarkAddedToMap(idxObs, newIndexInMap);
1040 size_t idx =
obj.internal_getXkk().size();
1041 obj.internal_getXkk().resize(
1042 obj.internal_getXkk().size() + FEAT_SIZE);
1044 for (
q = 0;
q < FEAT_SIZE;
q++)
1045 obj.internal_getXkk()[idx +
q] = yn[
q];
1051 obj.internal_getPkk().cols() == (int)idx &&
1052 obj.internal_getPkk().rows() == (int)idx);
1054 obj.internal_getPkk().setSize(idx + FEAT_SIZE, idx + FEAT_SIZE);
1058 auto Pxx =
typename KF::KFMatrix_VxV(
1059 obj.internal_getPkk().template block<VEH_SIZE, VEH_SIZE>(0, 0));
1060 auto Pxyn =
typename KF::KFMatrix_FxV(dyn_dxv * Pxx);
1062 obj.internal_getPkk().insertMatrix(idx, 0, Pxyn);
1063 obj.internal_getPkk().insertMatrix(0, idx, Pxyn.transpose());
1068 (idx - VEH_SIZE) / FEAT_SIZE;
1069 for (
q = 0;
q < nLMs;
q++)
1071 auto P_x_yq =
typename KF::KFMatrix_VxF(
1072 obj.internal_getPkk().template block<VEH_SIZE, FEAT_SIZE>(
1073 0, VEH_SIZE +
q * FEAT_SIZE));
1075 auto P_cross =
typename KF::KFMatrix_FxF(dyn_dxv * P_x_yq);
1077 obj.internal_getPkk().insertMatrix(
1078 idx, VEH_SIZE +
q * FEAT_SIZE, P_cross);
1079 obj.internal_getPkk().insertMatrix(
1080 VEH_SIZE +
q * FEAT_SIZE, idx, P_cross.transpose());
1087 typename KF::KFMatrix_FxF P_yn_yn =
1089 if (use_dyn_dhn_jacobian)
1093 P_yn_yn += dyn_dhn_R_dyn_dhnT;
1095 obj.internal_getPkk().insertMatrix(idx, idx, P_yn_yn);
1097 obj.getProfiler().leave(
"KF:9.create new LMs");
1102 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1105 VEH_SIZE, OBS_SIZE, 0 , ACT_SIZE, KFTYPE>&
obj,
1107 VEH_SIZE, OBS_SIZE, 0 , ACT_SIZE,
1108 KFTYPE>::vector_KFArray_OBS& Z,
1109 const std::vector<int>& data_association,
1111 VEH_SIZE, OBS_SIZE, 0 , ACT_SIZE,
1112 KFTYPE>::KFMatrix_OxO&
R)
1118 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
1124 return (
obj.getStateVectorLength() - VEH_SIZE) / FEAT_SIZE;
1127 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1130 VEH_SIZE, OBS_SIZE, 0 , ACT_SIZE, KFTYPE>&
obj)
1136 size_t VEH_SIZE,
size_t OBS_SIZE,
size_t FEAT_SIZE,
size_t ACT_SIZE,
1142 return (
obj.getStateVectorLength() == VEH_SIZE);
1145 template <
size_t VEH_SIZE,
size_t OBS_SIZE,
size_t ACT_SIZE,
typename KFTYPE>
1148 VEH_SIZE, OBS_SIZE, 0 , ACT_SIZE, KFTYPE>&
obj)
A compile-time fixed-size numeric matrix container.
#define MRPT_LOG_DEBUG(_STRING)
Use: MRPT_LOG_DEBUG("message");
#define THROW_EXCEPTION(msg)
GLdouble GLdouble GLdouble GLdouble q
static void KF_aux_estimate_obs_Hx_jacobian(const KFArray_VEH &x, const std::pair< KFCLASS *, size_t > &dat, KFArray_OBS &out_x)
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
GLsizei GLsizei GLuint * obj
#define MRPT_LOG_WARN_STREAM(__CONTENTS)
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.
#define ASSERT_(f)
Defines an assertion mechanism.
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 std::vector< int > &data_association, const typename CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE >::KFMatrix_OxO &R)
Virtual base for Kalman Filter (EKF,IEKF,UKF) implementations.
size_t getNumberOfLandmarksInMap(const CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE > &obj)
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.
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Derived inverse_LLt() const
Returns the inverse of a symmetric matrix using LLt.
double kftype
The numeric type used in the Kalman Filter (default=double)
size_type cols() const
Number of columns in the matrix.
void estimateJacobian(const VECTORLIKE &x, const std::function< void(const VECTORLIKE &x, const USERPARAM &y, VECTORLIKE3 &out)> &functor, 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...
void extractSubmatrixSymmetrical(const MAT &m, const std::vector< size_t > &indices, MATRIX &out)
Get a submatrix from a square matrix, by collecting the elements M(idxs,idxs), where idxs is the sequ...
std::vector< KFArray_OBS > vector_KFArray_OBS
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
GLdouble GLdouble GLdouble r
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
bool isMapEmpty(const CKalmanFilterCapable< VEH_SIZE, OBS_SIZE, FEAT_SIZE, ACT_SIZE, KFTYPE > &obj)
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
EIGEN_MAP asEigen()
Get as an Eigen-compatible Eigen::Map object.
constexpr size_type cols() const
Number of columns in the matrix.
static void KF_aux_estimate_obs_Hy_jacobian(const KFArray_FEAT &x, const std::pair< KFCLASS *, size_t > &dat, KFArray_OBS &out_x)
bool 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.
GLubyte GLubyte GLubyte a
mrpt::system::CTimeLogger & getProfiler()
void enter(const std::string_view &func_name)
Start of a named section.
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".
void multiply_HCHt(const MAT_H &H, const MAT_C &C, MAT_R &R, bool accumResultInOutput=false)
R = H * C * H^t.