11 [=](arma::mat x, arma::mat u, \ 12 arma::mat w) // Lambda function f(x,u,w) ([capture] by copy) 13 using fcn_t = std::function<double(arma::mat, arma::mat, arma::mat)>;
14 using fcn_v = std::vector<fcn_t>;
15 using fcn_m = std::vector<fcn_v>;
26 const arma::mat &u,
const arma::mat &w)
28 arma::mat y((arma::uword)(f.size()), 1, arma::fill::zeros);
29 for (arma::uword n = 0; n < y.n_rows; n++)
30 y(n, 0) = f[n](x, u, w);
44 arma::mat w0(0, 0, arma::fill::zeros);
56 arma::mat w0(0, 0, arma::fill::zeros);
82 arma_inline
void lti2discr(
const arma::mat &F,
const arma::mat &W,
83 const arma::mat &Qc,
const double dT, arma::mat &A,
86 arma::uword M = F.n_rows;
89 A = arma::expmat(F * dT);
92 arma::mat AB = arma::zeros(2 * M, M);
93 arma::mat CD = arma::zeros(2 * M, 2 * M);
94 arma::mat EF = arma::zeros(2 * M, M);
95 EF.submat(M, 0, 2 * M - 1, M - 1) = arma::eye(M, M);
96 CD.submat(0, 0, M - 1, M - 1) = F;
97 CD.submat(M, M, 2 * M - 1, 2 * M - 1) = -F.t();
98 CD.submat(0, M, M - 1, 2 * M - 1) = W * Qc * W.t();
100 AB = arma::expmat(CD * dT) * EF;
102 Q = AB.rows(0, M - 1) * arma::inv(AB.rows(M, 2 * M - 1));
152 KF(arma::uword _N, arma::uword _M, arma::uword _L)
161 z_err.set_size(M, 1);
249 P = A * P * A.t() +
Q;
257 arma::mat u0(L, 1, arma::fill::zeros);
267 K = P * H.t() * inv(H * P * H.t() +
R);
274 arma::mat Jf = arma::eye<arma::mat>(
N,
N) - K * H;
275 P = Jf * P * Jf.t() + K * R * K.t();
283 void rts_smooth(
const arma::mat &Xf,
const arma::cube &Pf, arma::mat &Xs,
286 arma::uword Nf = Xf.n_cols;
287 arma::mat X_pred(N, 1);
288 arma::mat P_pred(N, N);
296 for (arma::uword n = Nf - 2; n > 0; n--)
299 X_pred = A * Xf.col(n);
300 P_pred = A * Pf.slice(n) * A.t() +
Q;
303 C = Pf.slice(n) * A.t() * inv(P_pred);
304 Xs.col(n) += C * (Xs.col(n + 1) - X_pred);
305 Ps.slice(n) += C * (Ps.slice(n + 1) - P_pred) * C.t();
339 EKF(arma::uword _N, arma::uword _M, arma::uword _L) :
KF(_N, _M, _L)
369 arma::uword nC = _F.n_cols;
370 arma::uword nR =
static_cast<arma::uword
>(_f.size());
372 nC, 1, arma::fill::zeros);
374 if (nR == 0 || nR != _F.n_rows)
375 err_handler(
"Function list is empty or wrong size");
377 for (arma::uword c = 0; c < nC; c++)
385 for (arma::uword r = 0; r < nR; r++)
386 _F(r, c) = (_f[r](xp, z0, z0) - _f[r](xm, z0, z0)) / (2 * dx);
397 jacobian_diff(_F, _f,
x);
408 arma::uword nC = _F.n_cols;
409 arma::uword nR =
static_cast<arma::uword
>(_f_m.size());
411 if (nR == 0 || nR != _F.n_rows)
412 err_handler(
"Function list is empty or wrong size");
415 nC, 1, arma::fill::zeros);
416 for (arma::uword c = 0; c < nC; c++)
418 for (arma::uword r = 0; r < nR; r++)
419 _F(r, c) = _f_m[r][c](_x, z0, z0);
429 jacobian_analytical(_F, _f_m,
x);
441 if (f_jac.size() > 0)
442 jacobian_analytical(
A, f_jac);
453 P =
A *
P *
A.t() +
Q;
461 arma::mat u0(
L, 1, arma::fill::zeros);
470 arma::mat z_hat(
M, 1);
475 if (h_jac.size() > 0)
476 jacobian_analytical(
H, h_jac);
490 K =
P *
H.t() * inv(
H *
P *
H.t() +
R);
496 arma::mat Jf = arma::eye<arma::mat>(
N,
N) -
K *
H;
497 P = Jf * P * Jf.t() +
K *
R *
K.t();
505 void rts_smooth(
const arma::mat &Xf,
const arma::cube &Pf, arma::mat &Xs,
508 arma::uword Nf = Xf.n_cols;
509 arma::mat X_pred(
N, 1);
510 arma::mat P_pred(
N,
N);
518 for (arma::uword n = Nf - 2; n > 0; n--)
523 if (f_jac.size() > 0)
524 jacobian_analytical(
A, f_jac, Xf.col(n));
526 jacobian_diff(
A,
f, Xf.col(n));
534 X_pred =
A * Xf.col(n);
538 P_pred =
A * Pf.slice(n) *
A.t() +
Q;
541 C = Pf.slice(n) *
A.t() * inv(P_pred);
542 Xs.col(n) += C * (Xs.col(n + 1) - X_pred);
543 Ps.slice(n) += C * (Ps.slice(n + 1) - P_pred) * C.t();
577 UKF(arma::uword _N, arma::uword _M, arma::uword _L) :
KF(_N, _M, _L)
582 lambda = alpha * alpha * (_N + kappa) - _N;
583 X.set_size(_N, 2 * _N + 1);
585 Wx.set_size(2 * _N + 1);
587 Wp.set_size(2 * _N + 1);
605 lambda = alpha * alpha * (
N + kappa) -
N;
608 Wx(0) = lambda / (
N + lambda);
609 Wp(0) = lambda / (
N + lambda) + (1 - alpha * alpha + beta);
611 for (arma::uword n = 1; n <= 2 *
N; n++)
613 Wx(n) = 1 / (2 * (
N + lambda));
626 arma::mat _A = sqrt(
N + lambda) * arma::chol(_P,
"lower");
628 X = arma::repmat(_x, 1, 2 *
N + 1);
630 X.cols(
N + 1, 2 *
N) -= _A;
636 arma::mat
ut(
const arma::mat &_x,
const arma::mat &_P,
const fcn_v _f)
638 arma::uword Ny =
static_cast<arma::uword
>(_f.size());
644 update_sigma(_x, _P);
647 arma::mat Xy(Ny, 2 *
N + 1);
648 for (arma::uword n = 0; n < 2 *
N + 1; n++)
655 S = (Xy - arma::repmat(y, 1, 2 * N + 1)) * arma::diagmat(Wp) *
656 (Xy - arma::repmat(y, 1, 2 * N + 1)).t();
659 C = (X - arma::repmat(_x, 1, 2 * N + 1)) * arma::diagmat(Wp) *
660 (Xy - arma::repmat(y, 1, 2 * N + 1)).t();
674 x = ut(
x,
P,
f) +
B * u;
685 P =
A *
P *
A.t() +
Q;
694 arma::mat u0(
L, 1, arma::fill::zeros);
703 arma::mat z_hat(
M, 1);
713 K = C * arma::inv(S);
720 P =
P -
K * S *
K.t();
728 K =
P *
H.t() * inv(
H *
P *
H.t() +
R);
734 arma::mat Jf = arma::eye<arma::mat>(
N,
N) -
K *
H;
735 P = Jf * P * Jf.t() +
K *
R *
K.t();
744 void rts_smooth(
const arma::mat &Xf,
const arma::cube &Pf, arma::mat &Xs,
747 arma::uword Nf = Xf.n_cols;
748 arma::mat X_pred(
N, 1, arma::fill::zeros);
749 arma::mat P_pred(
N,
N, arma::fill::zeros);
750 arma::mat D_pred(
N,
N, arma::fill::zeros);
757 for (arma::uword k = Nf - 2; k > 0; k--)
762 X_pred = ut(Xf.col(k), Pf.slice(k),
f);
766 D_pred = C * inv(P_pred);
767 Xs.col(k) += D_pred * (Xs.col(k + 1) - X_pred);
768 Ps.slice(k) += D_pred * (Ps.slice(k + 1) - P_pred) * D_pred.t();
773 X_pred =
A * Xf.col(k);
776 P_pred =
A * Pf.slice(k) *
A.t() +
Q;
779 D_pred = Pf.slice(k) *
A.t() * inv(P_pred);
780 Xs.col(k) += D_pred * (Xs.col(k + 1) - X_pred);
781 Ps.slice(k) += D_pred * (Ps.slice(k + 1) - P_pred) * D_pred.t();
KF(arma::uword _N, arma::uword _M, arma::uword _L)
Constructor.
void rts_smooth(const arma::mat &Xf, const arma::cube &Pf, arma::mat &Xs, arma::cube &Ps)
Rauch-Tung-Striebel smoother. See http://www.lce.hut.fi/~ssarkka/course_k2011/pdf/course_booklet_2011...
bool lin_meas
Linearity flag for measurement.
fcn_v h
Vector of Kalman measurement functions.
arma::mat get_state_vec(void)
arma::mat K
Kalman gain vector.
arma::mat H
Measurement matrix.
arma::uword N
Number of states.
double dx
Finite difference approximation step size.
void update_sigma(const arma::mat &_x, const arma::mat &_P)
Calculate sigma points around a reference point.
void predict(void)
Predict the internal states, no control.
arma::mat R
Measurement noise.
fcn_m h_jac
Matrix of Extended Kalman measurement transition jacobian.
arma::vec Wp
Weights covariance.
void jacobian_analytical(arma::mat &_F, fcn_m _f_m)
Evaluate Jacobian matrix using analytical jacobian.
void update(const arma::mat z)
Correct and update the internal states.
void set_meas_mat(const arma::mat &_H)
void set_diff_step(double _dx)
arma::mat A
State transition matrix.
std::function< double(arma::mat, arma::mat, arma::mat)> fcn_t
void set_trans_fcn(fcn_v _f)
arma::mat C
Cross covariance input-output.
arma::vec Wx
Weights states.
Unscented Kalman filter class.
double alpha
Spread factor of sigma points.
void set_lambda(double _l)
arma::mat S
Output covariance.
void predict(const arma::mat u)
Predict the internal states using a control input.
double beta
x distr. prior knowledge factor
std::vector< fcn_t > fcn_v
UKF(arma::uword _N, arma::uword _M, arma::uword _L)
void jacobian_analytical(arma::mat &_F, fcn_m _f_m, const arma::mat &_x)
Evaluate Jacobian matrix using analytical jacobian.
arma::uword L
Number of measurements/observations.
arma_inline arma::mat eval_fcn(const fcn_v f, const arma::mat &x, const arma::mat &u, const arma::mat &w)
Evaluate function f(x,u,w)
void predict(const arma::mat u)
Predict the internal states using a control input.
void set_control_mat(const arma::mat &_B)
void update_weights(void)
Calculate sigma point weights.
std::vector< fcn_v > fcn_m
void predict(void)
Predict the internal states, no control.
void set_state_vec(const arma::mat &_x)
void update(const arma::mat z)
Correct and update the internal states. EKF.
EKF(arma::uword _N, arma::uword _M, arma::uword _L)
void set_alpha(double _a)
arma::mat z_err
Prediction error.
void set_meas_fcn(fcn_v _h)
void set_proc_noise(const arma::mat &_Q)
arma::mat get_kalman_gain(void)
void set_kalman_gain(const arma::mat &_K)
void predict(void)
Predict the internal states, no control. Convenient function.
void predict(const arma::mat u)
Predict the internal states using a control input.
void clear(void)
Clear the internal states and pointer.
First order Extended Kalman filter class.
fcn_v f
Vector of Kalman state transition functions.
void jacobian_diff(arma::mat &_F, fcn_v _f)
Calculate and evaluate Jacobian matrix using finite difference approximation.
arma::uword M
Number of inputs.
void set_err_cov(const arma::mat &_P)
void set_meas_jac(fcn_m _h)
void set_trans_mat(const arma::mat &_A)
void rts_smooth(const arma::mat &Xf, const arma::cube &Pf, arma::mat &Xs, arma::cube &Ps)
Rauch-Tung-Striebel smoother. See http://www.lce.hut.fi/~ssarkka/course_k2011/pdf/course_booklet_2011...
fcn_m f_jac
Matrix of Extended Kalman state transition jacobian.
void update(const arma::mat z)
Correct and update the internal states. UKF.
void set_state_jac(fcn_m _f)
void rts_smooth(const arma::mat &Xf, const arma::cube &Pf, arma::mat &Xs, arma::cube &Ps)
Rauch-Tung-Striebel smoother. See http://www.lce.hut.fi/~ssarkka/course_k2011/pdf/course_booklet_2011...
void jacobian_diff(arma::mat &_F, fcn_v _f, const arma::mat &_x)
Calculate and evaluate Jacobian matrix using finite difference approximation.
bool lin_proc
Linearity flag for process.
void set_meas_noise(const arma::mat &_R)
arma_inline void lti2discr(const arma::mat &F, const arma::mat &W, const arma::mat &Qc, const double dT, arma::mat &A, arma::mat &Q)
Discretize to a state transition and state noise cov matrix from an LTI system.
arma::mat P
Error covariance matrix (estimated accuracy)
arma::mat Q
Process noise.
arma::mat ut(const arma::mat &_x, const arma::mat &_P, const fcn_v _f)
Calculate unscented transform.
void set_kappa(double _k)
arma::mat get_err_cov(void)