5#include "core/math/eigen_interface.h"
6#include "core/math/numerical/numerical_integration.h"
13template <
int COV_DIM,
int STATES,
int NUM_SIGMAS>
14std::tuple<EVec<COV_DIM>, EMat<COV_DIM, COV_DIM>> square_root_ut(
15 const EMat<COV_DIM, NUM_SIGMAS>& sigmas,
const EVec<NUM_SIGMAS>&
Wm,
const EVec<NUM_SIGMAS>&
Wc,
16 const std::function<EVec<COV_DIM>(
const EMat<COV_DIM, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>&
18 const std::function<EVec<COV_DIM>(
const EVec<COV_DIM>&,
const EVec<COV_DIM>&)>& residual_func,
19 const EMat<COV_DIM, COV_DIM>& square_root_R
63template <
int STATES,
int INPUTS,
int OUTPUTS>
66 static constexpr int NUM_SIGMAS = STATES + 2;
68 using StateVector = EVec<STATES>;
69 using InputVector = EVec<INPUTS>;
70 using OutputVector = EVec<OUTPUTS>;
72 using StateMatrix = EMat<STATES, STATES>;
74 using WithInputIntegrator = std::function<EVec<STATES>(
75 const WithInputDerivative<STATES, INPUTS>& f,
const EVec<STATES>& x,
const EVec<INPUTS>& u,
92 const std::function<StateVector(
const StateVector&,
const InputVector&)>& f,
93 const std::function<OutputVector(
const StateVector&,
const InputVector&)>& h,
94 const WithInputIntegrator& integrator,
const StateVector& state_stddevs,
95 const OutputVector& measurement_stddevs
97 : f_(f), h_(h), integrator_(integrator) {
98 sqrt_Q_ = state_stddevs.asDiagonal();
99 measurement_stddevs_ = measurement_stddevs;
100 mean_func_X_ = [](
const EMat<STATES, NUM_SIGMAS>& sigmas,
101 const EVec<NUM_SIGMAS>& Wm) -> StateVector {
return sigmas * Wm; };
103 mean_func_Y_ = [](
const EMat<OUTPUTS, NUM_SIGMAS>& sigmas,
104 const EVec<NUM_SIGMAS>& Wc) -> OutputVector {
return sigmas * Wc; };
105 residual_func_X_ = [](
const StateVector& a,
const StateVector& b) -> StateVector {
108 residual_func_Y_ = [](
const OutputVector& a,
const OutputVector& b) -> OutputVector {
111 add_func_X_ = [](
const StateVector& a,
const StateVector& b) -> StateVector {
return a + b; };
140 const std::function<StateVector(
const StateVector&,
const InputVector&)>& f,
141 const std::function<OutputVector(
const StateVector&,
const InputVector&)>& h,
142 const WithInputIntegrator& integrator,
const StateVector& state_stddevs,
143 const OutputVector& measurement_stddevs,
144 const std::function<StateVector(
const EMat<STATES, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>&
146 const std::function<OutputVector(
const EMat<OUTPUTS, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>&
148 const std::function<StateVector(
const StateVector&,
const StateVector&)>& residual_func_X,
149 const std::function<OutputVector(
const OutputVector&,
const OutputVector&)>& residual_func_Y,
150 const std::function<StateVector(
const StateVector&,
const StateVector&)>& add_func_X
154 integrator_(integrator),
155 mean_func_X_(mean_func_X),
156 mean_func_Y_(mean_func_Y),
157 residual_func_X_(residual_func_X),
158 residual_func_Y_(residual_func_Y),
159 add_func_X_(add_func_X) {
160 sqrt_Q_ = state_stddevs.asDiagonal();
161 measurement_stddevs_ = measurement_stddevs;
167 StateMatrix
S()
const {
return S_; }
175 double S(
int i,
int j)
const {
return S_(i, j); }
185 StateMatrix
P()
const {
return S_ * S_.transpose(); }
192 void set_P(
const StateMatrix&
P) { S_ =
P.llt().matrixL(); }
195 StateVector
xhat()
const {
return xhat_; }
202 double xhat(
int i)
const {
return xhat_(i); }
212 void set_xhat(
int i,
double value) { xhat_(i) = value; }
227 void predict(
const InputVector& u,
double dt) {
229 const EMat<STATES, STATES> Q = sqrt_Q_ * sqrt(dt);
235 EMat<STATES, NUM_SIGMAS> sigmas = pts_.square_root_sigma_points(xhat_, S_);
247 for (
int i = 0; i < NUM_SIGMAS; ++i) {
248 StateVector x = sigmas.template block<STATES, 1>(0, i);
249 sigmas_F_.template block<STATES, 1>(0, i) = integrator_(f_, x, u, dt);
257 auto [
xhat,
S] = square_root_ut<STATES, STATES>(
258 sigmas_F_, pts_.Wm(), pts_.Wc(), mean_func_X_, residual_func_X_,
259 Q.template triangularView<Eigen::Lower>()
272 void correct(
const InputVector& u,
const OutputVector& y) {
274 u, y, h_, measurement_stddevs_, mean_func_Y_, residual_func_Y_, residual_func_X_,
289 const InputVector& u,
const OutputVector& y,
const EVec<OUTPUTS>& measurement_stddevs
292 u, y, h_, measurement_stddevs, mean_func_Y_, residual_func_Y_, residual_func_X_, add_func_X_
310 const InputVector& u,
const EVec<ROWS>& y,
311 const std::function<EVec<ROWS>(
const StateVector&,
const InputVector&)>& h,
312 const EVec<ROWS>& measurement_stddevs
314 auto mean_func_Y = [](
const EMat<OUTPUTS, NUM_SIGMAS>& sigmas,
315 const EVec<NUM_SIGMAS>& Wc) -> EVec<ROWS> {
return sigmas * Wc; };
316 auto residual_func_X = [](
const StateVector& a,
const StateVector& b) -> StateVector {
319 auto residual_func_Y = [](
const EVec<ROWS>& a,
const EVec<ROWS>& b) -> EVec<ROWS> {
322 auto add_func_X = [](
const StateVector& a,
const StateVector& b) -> StateVector {
327 u, y, h, measurement_stddevs, mean_func_Y, residual_func_Y, residual_func_X, add_func_X
353 const InputVector& u,
const EVec<ROWS>& y,
354 const std::function<EVec<ROWS>(
const StateVector&,
const InputVector&)>& h,
355 const EVec<ROWS> measurement_stddevs,
356 const std::function<EVec<ROWS>(
const EMat<ROWS, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>&
358 const std::function<EVec<ROWS>(
const EVec<ROWS>&,
const EVec<ROWS>&)>& residual_func_Y,
359 const std::function<StateVector(
const StateVector&,
const StateVector&)>& residual_func_X,
360 const std::function<StateVector(
const StateVector&,
const StateVector&)>& add_func_X
362 EMat<ROWS, ROWS> sqrt_R = measurement_stddevs.asDiagonal();
374 EMat<ROWS, NUM_SIGMAS> sigmas_H;
375 EMat<STATES, NUM_SIGMAS> sigmas = pts_.square_root_sigma_points(xhat_, S_);
376 for (
int i = 0; i < NUM_SIGMAS; ++i) {
377 sigmas_H.template block<ROWS, 1>(0, i) = h(sigmas.template block<STATES, 1>(0, i), u);
386 auto [yhat, Sy] = square_root_ut<ROWS, STATES, NUM_SIGMAS>(
387 sigmas_H, pts_.Wm(), pts_.Wc(), mean_func_Y, residual_func_Y,
388 sqrt_R.template triangularView<Eigen::Lower>()
400 EMat<STATES, ROWS> Pxy;
402 for (
int i = 0; i < NUM_SIGMAS; ++i) {
403 Pxy += pts_.Wc(i) * (residual_func_X(sigmas_F_.template block<STATES, 1>(0, i), xhat_)) *
404 (residual_func_Y(sigmas_H.template block<ROWS, 1>(0, i), yhat)).transpose();
418 EMat<STATES, ROWS> K = (Sy.transpose().
template triangularView<Eigen::Upper>().solve(
419 Sy.template triangularView<Eigen::Lower>().solve(Pxy.transpose())
430 xhat_ = add_func_X(xhat_, K * residual_func_Y(y, yhat));
437 EMat<STATES, ROWS> U = K * Sy;
443 for (
int i = 0; i < ROWS; i++) {
444 Eigen::internal::llt_inplace<double, Eigen::Lower>::rankUpdate(
445 S_, U.template block<STATES, 1>(0, i), -1
451 std::function<StateVector(
const StateVector&,
const InputVector&)> f_;
452 std::function<OutputVector(
const StateVector&,
const InputVector&)> h_;
453 std::function<StateVector(
const EMat<STATES, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)> mean_func_X_;
454 std::function<OutputVector(
const EMat<OUTPUTS, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>
456 std::function<StateVector(
const StateVector&,
const StateVector&)> residual_func_X_;
457 std::function<OutputVector(
const OutputVector&,
const OutputVector&)> residual_func_Y_;
458 std::function<StateVector(
const StateVector&,
const StateVector&)> add_func_X_;
462 EVec<OUTPUTS> measurement_stddevs_;
463 EMat<STATES, NUM_SIGMAS> sigmas_F_;
467 WithInputIntegrator integrator_;
489template <
int COV_DIM,
int STATES,
int NUM_SIGMAS>
490std::tuple<EVec<COV_DIM>, EMat<COV_DIM, COV_DIM>> square_root_ut(
491 const EMat<COV_DIM, NUM_SIGMAS>& sigmas,
const EVec<NUM_SIGMAS>& Wm,
const EVec<NUM_SIGMAS>& Wc,
492 const std::function<EVec<COV_DIM>(
const EMat<COV_DIM, NUM_SIGMAS>&,
const EVec<NUM_SIGMAS>&)>&
494 const std::function<EVec<COV_DIM>(
const EVec<COV_DIM>&,
const EVec<COV_DIM>&)>& residual_func,
495 const EMat<COV_DIM, COV_DIM>& sqrt_R
507 EVec<COV_DIM> x = mean_func(sigmas, Wm);
516 EMat<COV_DIM, NUM_SIGMAS - 1 + COV_DIM> S_bar;
517 for (
int i = 0; i < NUM_SIGMAS - 1; i++) {
518 S_bar.template block<COV_DIM, 1>(0, i) =
519 std::sqrt(Wc[1]) * residual_func(sigmas.template block<COV_DIM, 1>(0, i + 1), x);
521 S_bar.template block<COV_DIM, COV_DIM>(0, NUM_SIGMAS - 1) = sqrt_R;
536 EMat<COV_DIM, COV_DIM> S = S_bar.transpose()
539 .template block<COV_DIM, COV_DIM>(0, 0)
540 .template triangularView<Eigen::Upper>()
548 Eigen::internal::llt_inplace<double, Eigen::Lower>::rankUpdate(
549 S, residual_func(sigmas.template block<COV_DIM, 1>(0, 0), x), Wc[0]
552 return std::make_tuple(x, S);
576 static constexpr int NUM_SIGMAS = STATES + 2;
587 compute_weights(alpha, beta);
604 const EVec<STATES>& x,
const EMat<STATES, STATES>& S
606 EMat<STATES, NUM_SIGMAS> sigmas = S * C_;
607 sigmas.colwise() += x;
613 const EVec<NUM_SIGMAS>&
Wm()
const {
return Wm_; }
616 const EVec<NUM_SIGMAS>&
Wc()
const {
return Wc_; }
623 double Wm(
int i)
const {
return Wm_(i); }
630 double Wc(
int i)
const {
return Wc_(i); }
633 EVec<NUM_SIGMAS> Wm_;
634 EVec<NUM_SIGMAS> Wc_;
637 EMat<STATES, NUM_SIGMAS> C_;
647 void compute_weights(
double alpha,
double beta) {
648 double c = 1 / (alpha * alpha * (STATES + 1));
649 Wm_ = EVec<NUM_SIGMAS>::Constant(c);
650 Wc_ = EVec<NUM_SIGMAS>::Constant(c);
652 Wm_(0) = 1 - (1 / (alpha * alpha));
653 Wc_(0) = 1 - (1 / (alpha * alpha)) + (1 - alpha * alpha + beta);
656 for (
int i = 0; i < STATES; i++) {
661 alpha * ((t * (STATES + 1)).cwiseQuotient(t + EVec<STATES>::Ones())).cwiseSqrt();
663 C_ = EMat<STATES, NUM_SIGMAS>::Zero();
664 for (
int row = 0; row < STATES; row++) {
665 C_.row(row).segment(1, row + 1).setConstant(-q(row) / (row + 1));
672template <
int STATES,
int INPUTS,
int OUTPUTS>
674template <
int STATES,
int INPUTS,
int OUTPUTS>
676template <
int STATES,
int INPUTS,
int OUTPUTS>
Definition unscented_kalman_filter.h:574
const EVec< NUM_SIGMAS > & Wm() const
Returns a vector containing the weights of each sigma point for the mean.
Definition unscented_kalman_filter.h:613
double Wc(int i) const
Definition unscented_kalman_filter.h:630
int num_sigmas()
Returns the number of sigma points, for simplex sigma points this is N+2.
Definition unscented_kalman_filter.h:591
const EVec< NUM_SIGMAS > & Wc() const
Returns a vector containing the weights of each sigma point for the covariance.
Definition unscented_kalman_filter.h:616
ScaledSphericalSimplexSigmaPoints(double alpha=0.001, double beta=2)
Definition unscented_kalman_filter.h:586
EMat< STATES, NUM_SIGMAS > square_root_sigma_points(const EVec< STATES > &x, const EMat< STATES, STATES > &S)
Definition unscented_kalman_filter.h:603
double Wm(int i) const
Definition unscented_kalman_filter.h:623
Definition unscented_kalman_filter.h:64
StateMatrix P() const
Returns the reconstructed covariance matrix P.
Definition unscented_kalman_filter.h:185
UnscentedKalmanFilter(const std::function< StateVector(const StateVector &, const InputVector &)> &f, const std::function< OutputVector(const StateVector &, const InputVector &)> &h, const WithInputIntegrator &integrator, const StateVector &state_stddevs, const OutputVector &measurement_stddevs, const std::function< StateVector(const EMat< STATES, NUM_SIGMAS > &, const EVec< NUM_SIGMAS > &)> &mean_func_X, const std::function< OutputVector(const EMat< OUTPUTS, NUM_SIGMAS > &, const EVec< NUM_SIGMAS > &)> &mean_func_Y, const std::function< StateVector(const StateVector &, const StateVector &)> &residual_func_X, const std::function< OutputVector(const OutputVector &, const OutputVector &)> &residual_func_Y, const std::function< StateVector(const StateVector &, const StateVector &)> &add_func_X)
Definition unscented_kalman_filter.h:139
void set_S(const StateMatrix &S)
Definition unscented_kalman_filter.h:182
void set_xhat(int i, double value)
Definition unscented_kalman_filter.h:212
void set_P(const StateMatrix &P)
Definition unscented_kalman_filter.h:192
StateVector xhat() const
Returns the current state estimate x-hat.
Definition unscented_kalman_filter.h:195
void correct(const InputVector &u, const EVec< ROWS > &y, const std::function< EVec< ROWS >(const StateVector &, const InputVector &)> &h, const EVec< ROWS > &measurement_stddevs)
Definition unscented_kalman_filter.h:309
UnscentedKalmanFilter(const std::function< StateVector(const StateVector &, const InputVector &)> &f, const std::function< OutputVector(const StateVector &, const InputVector &)> &h, const WithInputIntegrator &integrator, const StateVector &state_stddevs, const OutputVector &measurement_stddevs)
Definition unscented_kalman_filter.h:91
StateMatrix S() const
Returns the square-root covariance matrix S.
Definition unscented_kalman_filter.h:167
double xhat(int i) const
Definition unscented_kalman_filter.h:202
void predict(const InputVector &u, double dt)
Definition unscented_kalman_filter.h:227
void reset()
Resets the filter.
Definition unscented_kalman_filter.h:215
void set_xhat(const StateVector &xhat)
Set the current state estimate x-hat.
Definition unscented_kalman_filter.h:205
void correct(const InputVector &u, const EVec< ROWS > &y, const std::function< EVec< ROWS >(const StateVector &, const InputVector &)> &h, const EVec< ROWS > measurement_stddevs, const std::function< EVec< ROWS >(const EMat< ROWS, NUM_SIGMAS > &, const EVec< NUM_SIGMAS > &)> &mean_func_Y, const std::function< EVec< ROWS >(const EVec< ROWS > &, const EVec< ROWS > &)> &residual_func_Y, const std::function< StateVector(const StateVector &, const StateVector &)> &residual_func_X, const std::function< StateVector(const StateVector &, const StateVector &)> &add_func_X)
Definition unscented_kalman_filter.h:352
double S(int i, int j) const
Definition unscented_kalman_filter.h:175
void correct(const InputVector &u, const OutputVector &y, const EVec< OUTPUTS > &measurement_stddevs)
Definition unscented_kalman_filter.h:288
void correct(const InputVector &u, const OutputVector &y)
Definition unscented_kalman_filter.h:272