-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExtendedKalmanFilter.h
100 lines (81 loc) · 2.57 KB
/
ExtendedKalmanFilter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#ifndef EXTENDED_KALMAN_FILTER_H
#define EXTENDED_KALMAN_FILTER_H
#include <Eigen/Dense>
#include "NumericalIntegration.h"
namespace kalmanfilter {
enum DiffMode {
ANALYTIC,
AUTOMATIC, // not supported
NUMERIC // not supported
};
template <typename Dynamics,
typename Observation,
IntegrationMode int_mode = EULER,
DiffMode diff_mode = ANALYTIC>
class ExtendedKalmanFilter {
public:
using Scalar = typename Dynamics::State::Scalar;
using State = typename Dynamics::State;
using Control = typename Dynamics::Control;
using Measurement = typename Observation::Measurement;
using StateCov = Eigen::Matrix<Scalar, State::RowsAtCompileTime, State::RowsAtCompileTime>;
enum {
nx = State::RowsAtCompileTime,
nz = Measurement::RowsAtCompileTime,
};
private:
static_assert(diff_mode == ANALYTIC, "Unsupported DiffMode");
NumericalIntegration<Dynamics, int_mode> f;
Observation h;
State x; // state vector
StateCov P; // state covariance
Eigen::Matrix<Scalar, nz, nz> S; // innovation covariance
Eigen::Matrix<Scalar, nx, nz> K; // Kalman gain
Eigen::Matrix<Scalar, nx, nx> I; // identity
public:
ExtendedKalmanFilter(State x0, StateCov P0) : x(x0), P(P0)
{
I.setIdentity();
}
State get_state()
{
return x;
}
StateCov get_covariance()
{
return P;
}
void predict(const Control &u, Scalar delta_t, unsigned integration_steps = 1)
{
Eigen::Matrix<Scalar, nx, nx> A;
A = I + delta_t * f.jacobian(x, u);
x = f.integrate(delta_t, x, u, integration_steps);
P = A * P * A.transpose() + f.Q;
}
void correct(const Measurement &z)
{
Measurement y; // innovation
Eigen::Matrix<Scalar, nz, nx> H; // jacobian of h
Eigen::Matrix<Scalar, nx, nx> IKH; // temporary matrix
H = h.jacobian(x);
S = H * P * H.transpose() + h.R;
// efficiently compute: K = P * H.transpose() * S.inverse();
K = S.llt().solve(H * P).transpose();
y = z - h(x);
IKH = (I - K * H);
// measurement update
x = x + K * y;
P = IKH * P * IKH.transpose() + K * h.R * K.transpose();
}
State update(const Control &u,
const Measurement &z,
Scalar delta_t,
unsigned integration_steps = 1)
{
predict(u, delta_t, integration_steps);
correct(z);
return x;
}
};
} // end namespace kalmanfilter
#endif /* EXTENDED_KALMAN_FILTER_H */