-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathkalmanfilter.hpp
190 lines (152 loc) · 5.39 KB
/
kalmanfilter.hpp
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#ifndef KALMANFILTER_H
#define KALMANFILTER_H
#include <cassert>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/lu.hpp>
#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/vector.hpp>
namespace ublas = boost::numeric::ublas;
template <typename NumericType>
class KalmanFilter
{
public:
typedef ublas::vector<NumericType> vector;
typedef ublas::matrix<NumericType> matrix;
KalmanFilter(size_t transitionDimension,
size_t measurementDimension)
: transitionModel(transitionDimension,transitionDimension),
controlModel(transitionDimension),
measurementModel(measurementDimension,transitionDimension)
{}
explicit KalmanFilter(vector X, matrix P, matrix A,
vector B, matrix R, matrix Q, matrix H)
: correctedState(X),
correctedCovarianceError(P),
transitionModel(A),
controlModel(B),
measurementNoise(R),
processNoise(Q),
measurementModel(H)
{}
~KalmanFilter()
{}
void initializeState(vector state, matrix covarianceError)
{
correctedState = state;
correctedCovarianceError = covarianceError;
}
/**
* @brief time update phase; predicts predictedState from correctedState (postState from previous iteration)
* @return predicted vector of state - X'(k)
*/
std::pair<vector,matrix> predict()
{
// predictedState (x') = transitionModel (A) * correctedState (x) + controlModel (B) * u
predictedState = ublas::prod(transitionModel,correctedState);
// predictedCovarianceError (P') = transitionModel (A) * correctedCovarianceError (P) * transposed (transitionModel (A)) + processNoise (Q)
matrix transposedTrModel = ublas::trans(transitionModel);
matrix mult = ublas::prod(correctedCovarianceError,transposedTrModel);
predictedCovarianceError = ublas::prod(transitionModel,mult) + processNoise;
return std::pair<KalmanFilter::vector,KalmanFilter::matrix>(predictedState,predictedCovarianceError);
}
/**
* @brief time update phase; predicts predictedState from correctedState (postState from previous iteration)
* @param u control vector
* @return predicted vector of state - X'(k)
*/
std::pair<vector,matrix> predict(const vector& u)
{
auto p = predict();
predictedState = p.first + controlModel * u;
return std::pair<KalmanFilter::vector,KalmanFilter::matrix>(predictedState,p.second);
}
/**
* @brief measurement update phase; corrects value of predictedState basis on measurement (observation) vector.
* @param z measurement vector
* @return corrected vector of state - X(k)
*/
std::pair<vector,matrix> correct(const vector& z)
{
// Kalman gain = P' * transposed(H) / (H * P' * transposed(H) + R)
matrix transposedMeasurement = ublas::trans(measurementModel);
matrix top = ublas::prod(predictedCovarianceError,transposedMeasurement);
// bottom = H * P' * transposed(H) + R
matrix bottom1 = ublas::prod(measurementModel, predictedCovarianceError);
matrix bottom_all = ublas::prod(bottom1,transposedMeasurement) + measurementNoise;
matrix bottom(bottom_all.size1(),bottom_all.size2());
bool inverted = invertMatrix(bottom_all,bottom);
assert(inverted);
matrix K = ublas::prod(top,bottom); // Kalman gain
vector residual = z - ublas::prod(measurementModel,predictedState);
// correctedState = predictedState + kalmanGain*(z - H*x')
correctedState = predictedState + ublas::prod(K,residual);
// P = (I - K*H)*P'
matrix KH = ublas::prod(K,measurementModel);
matrix Iminus = ublas::identity_matrix<NumericType>(KH.size1(),KH.size2()) - KH;
correctedCovarianceError = ublas::prod(Iminus,predictedCovarianceError);
return std::pair<vector,matrix>(correctedState,correctedCovarianceError);
}
void setTransitionModel(matrix m)
{
transitionModel = m;
}
void setControlModel(vector v)
{
controlModel = v;
}
void setMeasurementModel(matrix m)
{
measurementModel = m;
}
void setMeasurementNoise(matrix m)
{
measurementNoise = m;
}
void setProcessNoise(matrix m)
{
processNoise = m;
}
vector getPredictedState() const
{
return predictedState;
}
vector getCorrectedState() const
{
return correctedState;
}
private:
/*
* Matrix inversion routine.
* Uses lu_factorize and lu_substitute in uBLAS to invert a matrix
*
* found at: http://savingyoutime.wordpress.com/2009/09/21/c-matrix-inversion-boostublas/
*/
template<class T>
bool invertMatrix(const ublas::matrix<T>& input, ublas::matrix<T>& inverse)
{
typedef ublas::permutation_matrix<std::size_t> pmatrix;
// create a working copy of the input
ublas::matrix<T> A(input);
// create a permutation matrix for the LU-factorization
pmatrix pm(A.size1());
// perform LU-factorization
int res = ublas::lu_factorize(A, pm);
if (res != 0)
return false;
// create identity matrix of "inverse"
inverse.assign(ublas::identity_matrix<T> (A.size1()));
// backsubstitute to get the inverse
ublas::lu_substitute(A, pm, inverse);
return true;
}
vector predictedState; // X'(k) (a priori)
vector correctedState; // X(k) (a posteriori)
matrix predictedCovarianceError; // P'(k) (a priori)
matrix correctedCovarianceError; // P(k) (a posteriori)
matrix transitionModel; // A
vector controlModel; // B
matrix measurementNoise; // R
matrix processNoise; // Q
matrix measurementModel; // H
};
#endif // KALMANFILTER_H