5 #include <boost/circular_buffer.hpp>
6 #include <std_msgs/Time.h>
38 template <
class Model,
bool disable_reprediction=false>
44 using x_t =
typename Model::x_t;
45 using u_t =
typename Model::u_t;
46 using z_t =
typename Model::z_t;
47 using P_t =
typename Model::P_t;
48 using R_t =
typename Model::R_t;
49 using Q_t =
typename Model::Q_t;
51 using ModelPtr =
typename std::shared_ptr<Model>;
66 template<
bool check=disable_reprediction>
67 std::enable_if_t<!check, statecov_t>
predictTo(
const ros::Time& to_stamp)
69 assert(!m_history.empty());
70 auto hist_it = std::begin(m_history);
71 if (hist_it->is_measurement)
74 hist_it->is_measurement =
false;
77 auto cur_stamp = hist_it->stamp;
82 cur_sc.stamp = hist_it->stamp;
84 if ((hist_it->is_measurement))
85 cur_sc = correctFrom(cur_sc, *hist_it);
89 ros::Time next_stamp = to_stamp;
90 if ((hist_it + 1) != std::end(m_history) && (hist_it + 1)->stamp <= to_stamp)
91 next_stamp = (hist_it + 1)->stamp;
94 cur_sc = predictFrom(cur_sc, *hist_it, cur_stamp, next_stamp);
95 cur_stamp = next_stamp;
99 }
while (hist_it != std::end(m_history) && hist_it->stamp <= to_stamp);
100 cur_sc.stamp = to_stamp;
116 template<
bool check=disable_reprediction>
117 std::enable_if_t<check, statecov_t>
predictTo(
const ros::Time& to_stamp)
119 assert(!m_history.empty());
120 const auto& info = m_history.front();
121 auto sc = predictFrom(m_sc, info, info.stamp, to_stamp);
140 template<
bool check=disable_reprediction>
143 const info_t info(stamp, u, Q, model);
147 const auto added = addInfo(info, next_it);
149 if (added != std::end(m_history))
150 for (
auto it = added + 1; it != std::end(m_history) && it->is_measurement; it++)
151 it->updateUsing(info);
166 template<
bool check=disable_reprediction>
169 if (m_history.empty())
170 m_history.push_back({stamp});
171 m_history.front().u = u;
172 m_history.front().Q = Q;
173 m_history.front().stamp = stamp;
174 m_history.front().predict_model = model;
190 template<
bool check=disable_reprediction>
193 assert(!m_history.empty());
197 const auto prev_it = next_it == std::begin(m_history) ? next_it : next_it - 1;
199 const info_t info(stamp, u, prev_it->Q, model);
201 const auto added = addInfo(info, next_it);
203 if (added != std::end(m_history))
204 for (
auto it = added + 1; it != std::end(m_history) && it->is_measurement; it++)
205 it->updateUsing(info);
219 template<
bool check=disable_reprediction>
222 if (m_history.empty())
223 m_history.push_back({stamp});
224 m_history.front().u = u;
225 m_history.front().stamp = stamp;
226 m_history.front().predict_model = model;
242 template<
bool check=disable_reprediction>
245 assert(!m_history.empty());
249 const auto prev_it = next_it == std::begin(m_history) ? next_it : next_it - 1;
251 const info_t info(stamp, prev_it->u, Q, model);
253 const auto added = addInfo(info, next_it);
255 if (added != std::end(m_history))
256 for (
auto it = added + 1; it != std::end(m_history) && it->is_measurement; it++)
257 it->updateUsing(info);
271 template<
bool check=disable_reprediction>
274 if (m_history.empty())
275 m_history.push_back({stamp});
276 m_history.front().Q = Q;
277 m_history.front().stamp = stamp;
278 m_history.front().predict_model = model;
295 template<
bool check=disable_reprediction>
296 std::enable_if_t<!check>
addMeasurement(
const z_t& z,
const R_t& R,
const ros::Time& stamp,
const ModelPtr& model =
nullptr,
const double& meas_id = -1)
298 assert(!m_history.empty());
302 const auto prev_it = next_it == std::begin(m_history) ? next_it : next_it - 1;
304 const info_t info(stamp, z, R, model, *prev_it, meas_id);
306 addInfo(info, next_it);
321 template<
bool check=disable_reprediction>
322 std::enable_if_t<check>
addMeasurement(
const z_t& z,
const R_t& R,
const ros::Time& stamp,
const ModelPtr& model =
nullptr,
const double& meas_id = -1)
324 if (m_history.empty())
325 m_history.push_back({stamp});
326 auto& info = m_history.front();
327 const ros::Time to_stamp = stamp > info.stamp ? stamp : info.stamp;
331 info.stamp = to_stamp;
332 info.is_measurement =
true;
333 info.meas_id = meas_id;
334 info.correct_model = model;
335 m_sc = correctFrom(sc, info);
356 : m_sc{x0, P0}, m_default_model(model), m_history(history_t(hist_len))
358 assert(hist_len > 0);
382 : m_sc{x0, P0}, m_default_model(model), m_history(history_t(hist_len))
384 assert(hist_len > 0);
416 info_t(
const ros::Time& stamp) : stamp(stamp), is_measurement(false){};
419 info_t(
const ros::Time& stamp,
const u_t& u,
const Q_t& Q,
const ModelPtr& model)
420 : stamp(stamp), u(u), Q(Q), predict_model(model), is_measurement(false){};
423 info_t(
const ros::Time& stamp,
const z_t& z,
const R_t& R,
const ModelPtr& model,
const info_t& prev_info,
const int& meas_id)
424 : stamp(stamp), z(z), R(R), correct_model(model), is_measurement(true), meas_id(meas_id)
426 updateUsing(prev_info);
430 void updateUsing(
const info_t& info)
434 predict_model = info.predict_model;
442 using history_t = boost::circular_buffer<info_t>;
448 template <
typename T>
449 bool checkMonotonicity(
const T& buf)
453 for (
auto it = std::begin(buf) + 1; it != std::end(buf); it++)
454 if (earlier(*it, *(it - 1)))
461 template <
typename T>
462 void printBuffer(
const T& buf)
466 const auto first_stamp = buf.front().stamp;
467 std::cerr <<
"first stamp: " << first_stamp << std::endl;
468 for (
size_t it = 0; it < buf.size(); it++)
470 std::cerr << it <<
":\t" << buf.at(it).stamp - first_stamp << std::endl;
479 typename history_t::iterator addInfo(
const info_t& info,
const typename history_t::iterator& next_it)
482 if (next_it == std::begin(m_history) && !m_history.empty())
484 ROS_WARN_STREAM_THROTTLE(1.0,
"[Repredictor]: Added history point is older than the oldest by "
485 << (next_it->stamp - info.stamp).toSec()
486 <<
"s. Ignoring it! Consider increasing the history buffer size (currently: " << m_history.size() <<
")");
487 return std::end(m_history);
491 if (m_history.size() == m_history.capacity())
494 auto new_oldest = m_history.front();
495 if (m_history.size() == 1 || (m_history.size() > 1 && info.stamp > m_history.at(0).stamp && info.stamp < m_history.at(1).stamp))
498 }
else if (m_history.size() > 1)
500 new_oldest = m_history.at(1);
508 const auto ret = m_history.insert(next_it, info);
511 #ifdef REPREDICTOR_DEBUG
512 if (!checkMonotonicity(m_history))
514 std::cerr <<
"History buffer is not monotonous after modification!" << std::endl;
516 std::cerr <<
"Added info (" << m_history.size() <<
" total)" << std::endl;
525 static bool earlier(
const info_t& ob1,
const info_t& ob2)
527 return ob1.stamp < ob2.stamp;
532 statecov_t predictFrom(
const statecov_t& sc,
const info_t& inpt,
const ros::Time& from_stamp,
const ros::Time& to_stamp)
534 const auto model = inpt.predict_model ==
nullptr ? m_default_model : inpt.predict_model;
535 const auto dt = (to_stamp - from_stamp).toSec();
536 return model->predict(sc, inpt.u, inpt.Q, dt);
541 statecov_t correctFrom(
const statecov_t& sc,
const info_t& meas)
543 assert(meas.is_measurement);
544 const auto model = meas.correct_model ==
nullptr ? m_default_model : meas.correct_model;
546 return model->correct(sc_tmp, meas.z, meas.R);
553 #endif // REPREDICTOR_H