Autoware.Auto
history.hpp
Go to the documentation of this file.
1 // Copyright 2021 Apex.AI, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Co-developed by Tier IV, Inc. and Apex.AI, Inc.
16 
19 
20 #ifndef STATE_ESTIMATION_NODES__HISTORY_HPP_
21 #define STATE_ESTIMATION_NODES__HISTORY_HPP_
22 
23 #include <common/types.hpp>
25 #include <mpark_variant_vendor/variant.hpp>
27 
28 #include <Eigen/Cholesky>
29 #include <Eigen/Core>
30 
31 #include <chrono>
32 #include <map>
33 #include <memory>
34 #include <utility>
35 
36 namespace autoware
37 {
38 namespace common
39 {
40 namespace state_estimation
41 {
42 
43 namespace detail
44 {
45 
58 template<std::int32_t kNumOfStates>
60  const Eigen::Matrix<common::types::float32_t, kNumOfStates, 1> & sample,
61  const Eigen::Matrix<common::types::float32_t, kNumOfStates, 1> & mean,
62  const Eigen::Matrix<common::types::float32_t, kNumOfStates, kNumOfStates> & covariance,
63  const common::types::float32_t mahalanobis_threshold)
64 {
65  using Matrix = Eigen::Matrix<common::types::float32_t, kNumOfStates, kNumOfStates>;
66  const Matrix L = covariance.llt().matrixL();
67  const auto squared_mahalanobis_distance =
69  const auto squared_threshold = mahalanobis_threshold * mahalanobis_threshold;
70  return squared_mahalanobis_distance < squared_threshold;
71 }
72 
73 } // namespace detail
74 
76 struct PredictionEvent {};
77 
83 template<typename FilterT>
84 struct ResetEvent
85 {
86  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
88  typename FilterT::State::Matrix covariance;
89 };
90 
104 template<typename FilterT, typename ... EventT>
105 class History
106 {
110  class HistoryEntry;
115  class EkfStateUpdater;
116 
118  using Timestamp = std::chrono::system_clock::time_point;
120  using HistoryMap = std::multimap<Timestamp, HistoryEntry>;
121 
122 public:
130  explicit History(
131  FilterT & filter,
132  const std::size_t max_history_size,
133  const common::types::float32_t mahalanobis_threshold)
134  : m_filter{filter},
135  m_max_history_size{max_history_size},
136  m_mahalanobis_threshold{mahalanobis_threshold} {}
137 
145  void emplace_event(const Timestamp & timestamp, const HistoryEntry & entry);
147  inline bool empty() const noexcept {return m_history.empty();}
149  inline std::size_t size() const noexcept {return m_history.size();}
151  inline const Timestamp & get_last_timestamp() const noexcept {return m_history.rbegin()->first;}
153  inline const HistoryEntry & get_last_event() const noexcept {return m_history.rbegin()->second;}
155  const FilterT & get_filter() const noexcept {return m_filter;}
157  FilterT & get_filter() noexcept {return m_filter;}
158 
159 private:
163  inline void drop_oldest_event_if_needed()
164  {
165  if ((m_history.size() >= m_max_history_size) && (m_max_history_size > 0U)) {
166  (void) m_history.erase(m_history.begin());
167  }
168  }
169 
175  void update_impacted_events(const typename HistoryMap::iterator & start_iter);
176 
177  HistoryMap m_history{};
178  FilterT & m_filter{};
179  std::size_t m_max_history_size{};
180  common::types::float32_t m_mahalanobis_threshold{};
181 };
182 
183 template<typename FilterT, typename ... EventT>
184 class History<FilterT, EventT...>::HistoryEntry
185 {
186 public:
187  // cppcheck-suppress unknownMacro // cppcheck seems to be confused due to lots of templates.
188  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
189 
190  template<typename SingleEventT>
191  // cppcheck-suppress noExplicitConstructor; Conversion to the variant type takes place.
192  HistoryEntry(const SingleEventT & event) : m_event {event} {}
193 
195  void update_stored_state(const typename FilterT::State & state) noexcept
196  {
197  m_stored_state = state;
198  }
200  const typename FilterT::State & stored_state() const noexcept {return m_stored_state;}
202  void update_stored_covariance(const typename FilterT::State::Matrix & covariance) noexcept
203  {
204  m_stored_covariance = covariance;
205  }
207  const typename FilterT::State::Matrix & stored_covariance() const noexcept
208  {
209  return m_stored_covariance;
210  }
212  const mpark::variant<EventT...> & event() const {return m_event;}
213 
214 private:
216  typename FilterT::State m_stored_state{};
218  typename FilterT::State::Matrix m_stored_covariance{FilterT::State::Matrix::Zero()};
220  mpark::variant<EventT...> m_event;
221 };
222 
223 template<typename FilterT, typename ... EventT>
224 class History<FilterT, EventT...>::EkfStateUpdater
225 {
226 public:
227  explicit EkfStateUpdater(
228  FilterT & filter,
229  const common::types::float32_t mahalanobis_threshold,
230  const std::chrono::system_clock::duration & dt = std::chrono::milliseconds{0})
231  : m_filter {filter}, m_mahalanobis_threshold{mahalanobis_threshold}, m_dt{dt}
232  {}
233 
241  template<typename MeasurementT>
242  void operator()(const MeasurementT & event)
243  {
244  m_filter.predict(m_dt);
245  // TODO(#887): I see a couple of ways to check mahalanobis distance in case the measurement does
246  // not cover the full state. Here I upscale it to the full state, copying the values of the
247  // current state for ones missing in the observation. We can alternatively apply the H matrix
248  // and only compute the distance in the measurement world. Don't really know which one is best
249  // here.
250  const auto measurement_as_state = event.map_into(m_filter.state());
252  measurement_as_state.vector(),
253  m_filter.state().vector(),
254  m_filter.covariance(),
255  m_mahalanobis_threshold)) {return;}
256  m_filter.correct(event);
257  }
258 
260  void operator()(const ResetEvent<FilterT> & event)
261  {
262  m_filter.reset(event.state, event.covariance);
263  }
264 
267  {
268  m_filter.predict(m_dt);
269  }
270 
271 private:
272  FilterT & m_filter{};
273  common::types::float32_t m_mahalanobis_threshold{};
274  std::chrono::system_clock::duration m_dt{};
275 };
276 
277 template<typename FilterT, typename ... EventT>
279  const Timestamp & timestamp, const HistoryEntry & entry)
280 {
281  drop_oldest_event_if_needed();
282  const auto iterator_to_inserted_position = m_history.emplace(timestamp, entry);
283  update_impacted_events(iterator_to_inserted_position);
284 }
285 
286 template<typename FilterT, typename ... EventT>
288  const typename HistoryMap::iterator & start_iter)
289 {
290  Timestamp previous_timestamp{};
291  if (start_iter == m_history.begin()) {
292  if (!mpark::holds_alternative<ResetEvent<FilterT>>(start_iter->second.event())) {
293  (void) m_history.erase(start_iter);
294  throw std::runtime_error(
295  "Non-reset event inserted to the beginning of history. This might "
296  "happen if a very old event is inserted into the queue. Consider "
297  "increasing the queue size or debug program latencies.");
298  }
299  } else {
300  const auto prev_iter = std::prev(start_iter);
301  previous_timestamp = prev_iter->first;
302  const auto & prev_entry = prev_iter->second;
303  m_filter.reset(
304  typename FilterT::State{prev_entry.stored_state()},
305  prev_entry.stored_covariance());
306  }
307  for (auto iter = start_iter; iter != m_history.end(); ++iter) {
308  const auto current_timestamp = iter->first;
309  auto & entry = iter->second;
310  mpark::visit(
311  EkfStateUpdater{m_filter, m_mahalanobis_threshold, current_timestamp - previous_timestamp},
312  entry.event());
313  entry.update_stored_state(m_filter.state());
314  entry.update_stored_covariance(m_filter.covariance());
315  previous_timestamp = iter->first;
316  }
317 }
318 
319 
320 } // namespace state_estimation
321 } // namespace common
322 } // namespace autoware
323 
324 
325 #endif // STATE_ESTIMATION_NODES__HISTORY_HPP_
autoware::common::state_estimation::detail::passes_mahalanobis_gate
bool passes_mahalanobis_gate(const Eigen::Matrix< common::types::float32_t, kNumOfStates, 1 > &sample, const Eigen::Matrix< common::types::float32_t, kNumOfStates, 1 > &mean, const Eigen::Matrix< common::types::float32_t, kNumOfStates, kNumOfStates > &covariance, const common::types::float32_t mahalanobis_threshold)
Definition: history.hpp:59
steady_time_grid.hpp
autoware::common::state_estimation::History::HistoryEntry::HistoryEntry
EIGEN_MAKE_ALIGNED_OPERATOR_NEW HistoryEntry(const SingleEventT &event)
Definition: history.hpp:192
types.hpp
This file includes common type definition.
autoware::common::state_estimation::History::HistoryEntry::stored_covariance
const FilterT::State::Matrix & stored_covariance() const noexcept
Get the stored covariance.
Definition: history.hpp:207
autoware::common::state_estimation::History::EkfStateUpdater::operator()
void operator()(const MeasurementT &event)
An operator that passes a measurement event to the filter implementation.
Definition: history.hpp:242
autoware::common::state_estimation::History::EkfStateUpdater
Definition: history.hpp:224
autoware::common::state_estimation::History::HistoryEntry::event
const mpark::variant< EventT... > & event() const
Get the event stored in this history entry.
Definition: history.hpp:212
autoware::common::state_estimation::History::get_filter
const FilterT & get_filter() const noexcept
Get the filter as a const ref.
Definition: history.hpp:155
autoware::common::state_estimation::ResetEvent
An event to reset the state of the filter.
Definition: history.hpp:84
motion::motion_common::State
autoware_auto_vehicle_msgs::msg::VehicleKinematicState State
Definition: motion_common.hpp:40
autoware::common::state_estimation::ResetEvent::state
EIGEN_MAKE_ALIGNED_OPERATOR_NEW FilterT::State state
Definition: history.hpp:87
motion::motion_common::sample
void sample(const Trajectory &in, Trajectory &out, std::chrono::nanoseconds period, SlerpF slerp_fn)
Sample a trajectory using interpolation; does not extrapolate.
Definition: motion_common.hpp:181
autoware::common::state_estimation::History::emplace_event
void emplace_event(const Timestamp &timestamp, const HistoryEntry &entry)
Add an event to history. If it is added to the middle the following ones are automatically replayed o...
Definition: history.hpp:278
autoware::common::state_estimation::PredictionEvent
An event to indicate a prediction step.
Definition: history.hpp:76
autoware
This file defines the lanelet2_map_provider_node class.
Definition: quick_sort.hpp:24
autoware::common::state_estimation::History::EkfStateUpdater::operator()
void operator()(const PredictionEvent &)
An operator that applies the prediction event to the filter implementation.
Definition: history.hpp:266
autoware::common::state_estimation::ResetEvent::covariance
FilterT::State::Matrix covariance
Definition: history.hpp:88
autoware::common::state_estimation::History
This class encapsulates a history of events used with EKF.
Definition: history.hpp:105
mahalanobis_distance.hpp
autoware::common::state_estimation::History::size
std::size_t size() const noexcept
Get size of history.
Definition: history.hpp:149
autoware::common::state_estimation::History::HistoryEntry
Definition: history.hpp:184
autoware::common::types::float32_t
float float32_t
Definition: types.hpp:45
autoware::common::state_estimation::History::History
History(FilterT &filter, const std::size_t max_history_size, const common::types::float32_t mahalanobis_threshold)
Construct history from a filter pointer with a specific size.
Definition: history.hpp:130
autoware::common::state_estimation::History::HistoryEntry::stored_state
const FilterT::State & stored_state() const noexcept
Get the stored state.
Definition: history.hpp:200
autoware::common::state_estimation::History::get_last_timestamp
const Timestamp & get_last_timestamp() const noexcept
Get last timestamp in history.
Definition: history.hpp:151
autoware::common::state_estimation::History::HistoryEntry::update_stored_state
void update_stored_state(const typename FilterT::State &state) noexcept
Update the stored state.
Definition: history.hpp:195
autoware::common::state_estimation::History::get_last_event
const HistoryEntry & get_last_event() const noexcept
Get last event in history.
Definition: history.hpp:153
autoware::common::state_estimation::History::EkfStateUpdater::EkfStateUpdater
EkfStateUpdater(FilterT &filter, const common::types::float32_t mahalanobis_threshold, const std::chrono::system_clock::duration &dt=std::chrono::milliseconds{0})
Definition: history.hpp:227
autoware::common::state_estimation::History::get_filter
FilterT & get_filter() noexcept
Get the filter.
Definition: history.hpp:157
autoware::common::state_estimation::History::empty
bool empty() const noexcept
Check if the history is empty.
Definition: history.hpp:147
autoware::common::helper_functions::calculate_squared_mahalanobis_distance
types::float32_t calculate_squared_mahalanobis_distance(const Eigen::Matrix< T, kNumOfStates, 1 > &sample, const Eigen::Matrix< T, kNumOfStates, 1 > &mean, const Eigen::Matrix< T, kNumOfStates, kNumOfStates > &covariance_factor)
Calculate square of mahalanobis distance.
Definition: mahalanobis_distance.hpp:36
autoware::common::state_estimation::History::HistoryEntry::update_stored_covariance
void update_stored_covariance(const typename FilterT::State::Matrix &covariance) noexcept
Set the stored covariance.
Definition: history.hpp:202
autoware::common::type_traits::visit
constexpr COMMON_PUBLIC std::enable_if_t< I==sizeof...(TypesT)> visit(std::tuple< TypesT... > &, Callable) noexcept
Visit every element in a tuple.
Definition: type_traits.hpp:80
autoware::common::state_estimation::History::EkfStateUpdater::operator()
void operator()(const ResetEvent< FilterT > &event)
An operator that resets the state of the filter implementation.
Definition: history.hpp:260