17 #ifndef CARTOGRAPHER_KALMAN_FILTER_UNSCENTED_KALMAN_FILTER_H_ 18 #define CARTOGRAPHER_KALMAN_FILTER_UNSCENTED_KALMAN_FILTER_H_ 25 #include "Eigen/Cholesky" 27 #include "Eigen/Eigenvalues" 29 #include "glog/logging.h" 32 namespace kalman_filter {
34 template <
typename FloatType>
35 constexpr FloatType
sqr(FloatType a) {
39 template <
typename FloatType,
int N>
41 const Eigen::Matrix<FloatType, N, 1>& v) {
42 return v * v.transpose();
46 template <
typename FloatType,
int N>
50 const FloatType norm = (A - A.transpose()).norm();
51 CHECK(!std::isnan(norm) && std::abs(norm) < 1e-5)
52 <<
"Symmetry check failed with norm: '" << norm <<
"' from matrix:\n" 57 template <
typename FloatType,
int N>
59 const Eigen::Matrix<FloatType, N, N>& A) {
62 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<FloatType, N, N>>
63 adjoint_eigen_solver((A + A.transpose()) / 2.);
64 const auto& eigenvalues = adjoint_eigen_solver.eigenvalues();
65 CHECK_GT(eigenvalues.minCoeff(), -1e-5)
66 <<
"MatrixSqrt failed with negative eigenvalues: " 67 << eigenvalues.transpose();
69 return adjoint_eigen_solver.eigenvectors() *
70 adjoint_eigen_solver.eigenvalues()
71 .cwiseMax(Eigen::Matrix<FloatType, N, 1>::Zero())
74 adjoint_eigen_solver.eigenvectors().transpose();
82 template <
typename FloatType,
int N>
92 const StateType& delta) {
return state + delta; },
93 std::function<StateType(const StateType& origin, const StateType& target)>
96 return target - origin;
113 std::vector<StateType> Y;
114 Y.reserve(2 * N + 1);
115 Y.emplace_back(g(mu));
117 const FloatType kSqrtNPlusLambda = std::sqrt(N +
kLambda);
118 for (
int i = 0; i < N; ++i) {
121 Y.emplace_back(g(
add_delta_(mu, kSqrtNPlusLambda * sqrt_sigma.col(i))));
122 Y.emplace_back(g(
add_delta_(mu, -kSqrtNPlusLambda * sqrt_sigma.col(i))));
128 for (
int i = 0; i < N; ++i) {
129 new_sigma +=
kCovWeightI * OuterProduct<FloatType, N>(
131 new_sigma +=
kCovWeightI * OuterProduct<FloatType, N>(
145 std::function<Eigen::Matrix<FloatType, K, 1>(
const StateType&)> h,
149 CHECK_NEAR(delta.
GetMean().norm(), 0., 1e-9);
157 std::vector<StateType> W;
158 W.reserve(2 * N + 1);
159 W.emplace_back(StateType::Zero());
161 std::vector<Eigen::Matrix<FloatType, K, 1>> Z;
162 Z.reserve(2 * N + 1);
163 Z.emplace_back(h(mu));
165 Eigen::Matrix<FloatType, K, 1> z_hat =
kMeanWeight0 * Z[0];
166 const FloatType kSqrtNPlusLambda = std::sqrt(N +
kLambda);
167 for (
int i = 0; i < N; ++i) {
170 W.emplace_back(kSqrtNPlusLambda * sqrt_sigma.col(i));
173 W.emplace_back(-kSqrtNPlusLambda * sqrt_sigma.col(i));
180 Eigen::Matrix<FloatType, K, K> S =
181 kCovWeight0 * OuterProduct<FloatType, K>(Z[0] - z_hat);
182 for (
int i = 0; i < N; ++i) {
183 S +=
kCovWeightI * OuterProduct<FloatType, K>(Z[2 * i + 1] - z_hat);
184 S +=
kCovWeightI * OuterProduct<FloatType, K>(Z[2 * i + 2] - z_hat);
189 Eigen::Matrix<FloatType, N, K> sigma_bar_xz =
191 for (
int i = 0; i < N; ++i) {
193 kCovWeightI * W[2 * i + 1] * (Z[2 * i + 1] - z_hat).transpose();
195 kCovWeightI * W[2 * i + 2] * (Z[2 * i + 2] - z_hat).transpose();
198 const Eigen::Matrix<FloatType, N, K> kalman_gain =
199 sigma_bar_xz * S.inverse();
205 add_delta_(mu, kalman_gain * -z_hat), new_sigma);
214 const std::vector<StateType>& states) {
217 for (
int i = 1; i != 2 * N + 1; ++i) {
220 return weighted_error;
226 CHECK_EQ(states.size(), 2 * N + 1);
230 while (weighted_error.norm() > 1e-9) {
231 double step_size = 1.;
234 add_delta_(current_estimate, step_size * weighted_error);
237 if (next_error.norm() < weighted_error.norm()) {
238 current_estimate = next_estimate;
239 weighted_error = next_error;
243 CHECK_GT(step_size, 1e-3) <<
"Step size too small, line search failed.";
246 CHECK_LT(iterations, 20) <<
"Too many iterations.";
248 return current_estimate;
253 constexpr
static FloatType
kAlpha = 1e-3;
255 constexpr
static FloatType
kBeta = 2.;
264 const std::function<StateType(const StateType& state, const StateType& delta)>
271 template <
typename FloatType,
int N>
273 template <
typename FloatType,
int N>
275 template <
typename FloatType,
int N>
277 template <
typename FloatType,
int N>
279 template <
typename FloatType,
int N>
281 template <
typename FloatType,
int N>
283 template <
typename FloatType,
int N>
285 template <
typename FloatType,
int N>
291 #endif // CARTOGRAPHER_KALMAN_FILTER_UNSCENTED_KALMAN_FILTER_H_ Eigen::Matrix< double, N, 1 > StateType
StateType ComputeWeightedError(const StateType &mean_estimate, const std::vector< StateType > &states)
void Observe(std::function< Eigen::Matrix< FloatType, K, 1 >(const StateType &)> h, const GaussianDistribution< FloatType, K > &delta)
Eigen::Matrix< double, N, N > StateCovarianceType
StateType ComputeMean(const std::vector< StateType > &states)
GaussianDistribution< FloatType, N > belief_
const std::function< StateType(const StateType &origin, const StateType &target)> compute_delta_
static constexpr FloatType kMeanWeightI
void CheckSymmetric(const Eigen::Matrix< FloatType, N, N > &A)
const Eigen::Matrix< T, N, 1 > & GetMean() const
static constexpr FloatType kLambda
Eigen::Matrix< FloatType, N, N > MatrixSqrt(const Eigen::Matrix< FloatType, N, N > &A)
const std::function< StateType(const StateType &state, const StateType &delta)> add_delta_
void Predict(std::function< StateType(const StateType &)> g, const GaussianDistribution< FloatType, N > &epsilon)
static constexpr FloatType kCovWeightI
Eigen::Matrix< FloatType, N, N > OuterProduct(const Eigen::Matrix< FloatType, N, 1 > &v)
static constexpr FloatType kMeanWeight0
static constexpr FloatType kCovWeight0
static constexpr FloatType kBeta
const GaussianDistribution< FloatType, N > & GetBelief() const
UnscentedKalmanFilter(const GaussianDistribution< FloatType, N > &initial_belief, std::function< StateType(const StateType &state, const StateType &delta)> add_delta=[](const StateType &state, const StateType &delta){return state+delta;}, std::function< StateType(const StateType &origin, const StateType &target)> compute_delta=[](const StateType &origin, const StateType &target){return target-origin;})
static constexpr FloatType kAlpha
const Eigen::Matrix< T, N, N > & GetCovariance() const
constexpr FloatType sqr(FloatType a)
static constexpr FloatType kKappa