17 #ifndef STATE_ESTIMATION__KALMAN_FILTER__KALMAN_FILTER_HPP_
18 #define STATE_ESTIMATION__KALMAN_FILTER__KALMAN_FILTER_HPP_
36 namespace state_estimation
44 template<
typename MotionModelT,
typename NoiseModelT>
50 "\n\nMotion model must inherit from MotionModelInterface\n\n");
53 "\n\nNoise model must inherit from NoiseInterface\n\n");
55 std::is_same<typename MotionModelT::State, typename NoiseModelT::State>::value,
56 "\n\nMotion model and noise model must have the same underlying state\n\n");
59 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
74 MotionModelT motion_model,
75 NoiseModelT noise_model,
76 const State & initial_state,
78 : m_motion_model{motion_model},
79 m_noise_model{noise_model},
80 m_state{initial_state},
81 m_covariance{initial_covariance} {}
92 m_state = m_motion_model.predict(m_state, dt);
93 const auto & motion_jacobian = m_motion_model.jacobian(m_state, dt);
95 motion_jacobian * m_covariance * motion_jacobian.transpose() + m_noise_model.covariance(dt);
110 template<
typename MeasurementT>
113 const auto expected_measurement = measurement.create_new_instance_from(m_state);
114 const auto innovation = wrap_all_angles(measurement.state() - expected_measurement);
115 const auto mapping_matrix = measurement.mapping_matrix_from(m_state);
116 const auto innovation_covariance =
117 mapping_matrix * m_covariance * mapping_matrix.transpose() + measurement.covariance();
118 const auto kalman_gain =
119 m_covariance * mapping_matrix.transpose() * innovation_covariance.inverse();
120 m_state += kalman_gain * innovation.vector();
121 m_state.wrap_all_angles();
122 m_covariance = (State::Matrix::Identity() - kalman_gain * mapping_matrix) * m_covariance;
140 m_covariance = covariance;
155 MotionModelT m_motion_model{};
157 NoiseModelT m_noise_model{};
161 StateMatrix m_covariance{StateMatrix::Zero()};
180 template<
typename MotionModelT,
typename NoiseModelT>
182 const MotionModelT & motion_model,
183 const NoiseModelT & noise_model,
185 const typename MotionModelT::State::Matrix & initial_covariance)
188 motion_model, noise_model, initial_state, initial_covariance};
207 template<
typename StateT>
209 const StateT & initial_state,
210 const typename StateT::Matrix & initial_covariance)
214 using State = StateT;
215 typename State::Matrix crtp_covariance(
const std::chrono::nanoseconds &)
const
217 throw std::runtime_error(
218 "Trying to use a correction-only Kalman filter to predict the state.");
225 MotionModel{}, DummyNoise{}, initial_state, initial_covariance);
244 template<
typename MotionModelT,
typename NoiseModelT>
246 const MotionModelT & motion_model,
247 const NoiseModelT & noise_model,
249 const std::vector<typename MotionModelT::State::Scalar> & initial_variances)
252 if (initial_variances.size() !=
static_cast<std::size_t
>(State::size())) {
254 "Cannot create Kalman filter - dimensions mismatch. Provided " +
255 std::to_string(initial_variances.size()) +
" variances, but " +
256 std::to_string(State::size()) +
" required.");
258 typename State::Vector variances{State::Vector::Zero()};
260 const auto epsilon = 5.0F * std::numeric_limits<common::types::float32_t>::epsilon();
261 for (std::uint32_t i = 0; i < initial_variances.size(); ++i) {
263 throw std::domain_error(
"Variances must be positive");
265 variances[
static_cast<std::int32_t
>(i)] = initial_variances[i] * initial_variances[i];
268 motion_model, noise_model, initial_state, variances.asDiagonal()};
275 #endif // STATE_ESTIMATION__KALMAN_FILTER__KALMAN_FILTER_HPP_