TinyRobotics
Loading...
Searching...
No Matches
KalmanFilter.h
1#pragma once
2
3#include <array>
4#include <cstddef>
5
6namespace tinyrobotics {
7
8/**
9 * @struct Matrix
10 * @ingroup control
11 * @brief Simple static matrix for linear algebra operations.
12 *
13 * This templated struct represents a fixed-size matrix of floats, supporting basic
14 * operations such as element access, identity matrix creation, and arithmetic. Used
15 * throughout the Kalman filter and control modules for efficient matrix computations
16 * in embedded robotics applications.
17 *
18 * @tparam R Number of rows
19 * @tparam C Number of columns
20 */
21template <size_t R, size_t C>
22struct Matrix {
23 std::array<float, R * C> data{};
24
25 float& operator()(size_t r, size_t c) { return data[r * C + c]; }
26
27 const float& operator()(size_t r, size_t c) const { return data[r * C + c]; }
28
29 static Matrix<R, C> identity() {
30 static_assert(R == C, "Identity only for square matrices");
31 Matrix<R, C> m;
32 for (size_t i = 0; i < R; ++i) m(i, i) = 1.0f;
33 return m;
34 }
35};
36
37// Matrix multiplication
38template <size_t R, size_t C, size_t K>
39Matrix<R, K> operator*(const Matrix<R, C>& a, const Matrix<C, K>& b) {
40 Matrix<R, K> result;
41 for (size_t i = 0; i < R; ++i)
42 for (size_t j = 0; j < K; ++j)
43 for (size_t k = 0; k < C; ++k) result(i, j) += a(i, k) * b(k, j);
44 return result;
45}
46
47// Matrix addition
48template <size_t R, size_t C>
49Matrix<R, C> operator+(const Matrix<R, C>& a, const Matrix<R, C>& b) {
50 Matrix<R, C> result;
51 for (size_t i = 0; i < R * C; ++i) result.data[i] = a.data[i] + b.data[i];
52 return result;
53}
54
55// Matrix subtraction
56template <size_t R, size_t C>
57Matrix<R, C> operator-(const Matrix<R, C>& a, const Matrix<R, C>& b) {
58 Matrix<R, C> result;
59 for (size_t i = 0; i < R * C; ++i) result.data[i] = a.data[i] - b.data[i];
60 return result;
61}
62
63// Transpose
64template <size_t R, size_t C>
65Matrix<C, R> transpose(const Matrix<R, C>& m) {
66 Matrix<C, R> result;
67 for (size_t i = 0; i < R; ++i)
68 for (size_t j = 0; j < C; ++j) result(j, i) = m(i, j);
69 return result;
70}
71
72// Inverse for 1x1 and 2x2 only (embedded-friendly)
73template <size_t N>
74Matrix<N, N> inverse(const Matrix<N, N>& m);
75
76// 1x1 inverse
77template <>
78inline Matrix<1, 1> inverse(const Matrix<1, 1>& m) {
79 Matrix<1, 1> r;
80 r(0, 0) = 1.0f / m(0, 0);
81 return r;
82}
83
84// 2x2 inverse
85template <>
86inline Matrix<2, 2> inverse(const Matrix<2, 2>& m) {
87 Matrix<2, 2> r;
88 float det = m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0);
89
90 r(0, 0) = m(1, 1) / det;
91 r(0, 1) = -m(0, 1) / det;
92 r(1, 0) = -m(1, 0) / det;
93 r(1, 1) = m(0, 0) / det;
94
95 return r;
96}
97
98/**
99 * @class KalmanFilter
100 * @ingroup control
101 * @brief A lightweight, fixed-size Kalman Filter for embedded state estimation.
102 *
103 * This template class implements a discrete-time, linear Kalman Filter for
104 * real-time state estimation in embedded and robotics applications. It is
105 * designed for efficiency and simplicity, using static, fixed-size matrices and
106 * minimal dynamic memory. The filter estimates the internal state of a process
107 * given noisy measurements and a mathematical model of the system dynamics.
108 *
109 * ## Features
110 * - Fixed-size, stack-allocated matrices for predictable memory usage
111 * - Suitable for microcontrollers and real-time systems
112 * - Supports arbitrary state and measurement dimensions via template parameters
113 * - Simple API: `predict()` for time update, `update(z)` for measurement update
114 *
115 * ## Mathematical Model
116 * The Kalman Filter models the system as:
117 *
118 * x_k = F * x_{k-1} + w (state transition)
119 * z_k = H * x_k + v (measurement)
120 *
121 * where:
122 * - x: state vector (NX x 1)
123 * - z: measurement vector (NZ x 1)
124 * - F: state transition matrix (NX x NX)
125 * - H: measurement matrix (NZ x NX)
126 * - Q: process noise covariance (NX x NX)
127 * - R: measurement noise covariance (NZ x NZ)
128 * - w, v: process and measurement noise (zero-mean, Gaussian)
129 *
130 * ## Usage Example
131 * @code
132 * KalmanFilter<2, 1> kf;
133 * kf.Fmat = ...; // set state transition
134 * kf.H = ...; // set measurement model
135 * kf.Q = ...; // set process noise
136 * kf.R = ...; // set measurement noise
137 * kf.x = ...; // set initial state
138 * kf.P = ...; // set initial covariance
139 * kf.predict();
140 * kf.update(z);
141 * @endcode
142 *
143 * ## Template Parameters
144 * @tparam NX Number of state variables (state vector dimension)
145 * @tparam NZ Number of measurement variables (measurement vector dimension)
146 *
147 * ## Members
148 * - x: State estimate vector (NX x 1)
149 * - P: State covariance matrix (NX x NX)
150 * - Fmat: State transition matrix (NX x NX)
151 * - Q: Process noise covariance (NX x NX)
152 * - H: Measurement matrix (NZ x NX)
153 * - R: Measurement noise covariance (NZ x NZ)
154 * - I: Identity matrix (NX x NX)
155 *
156 * ## Methods
157 * - predict(): Performs the time update (prediction) step
158 * - update(z): Performs the measurement update (correction) step
159 *
160 * ## Applications
161 * - Sensor fusion (IMU, GPS, encoders)
162 * - Robot localization
163 * - Signal filtering and smoothing
164 * - Any scenario requiring optimal state estimation from noisy data
165 */
166template <size_t NX, size_t NZ>
167class KalmanFilter {
168 public:
169 Matrix<NX, 1> x; // state
170 Matrix<NX, NX> P; // covariance
171 Matrix<NX, NX> Fmat; // state transition
172 Matrix<NX, NX> Q; // process noise
173
174 Matrix<NZ, NX> H; // measurement matrix
175 Matrix<NZ, NZ> R; // measurement noise
176
177 Matrix<NX, NX> I = Matrix<NX, NX>::identity();
178
179 // Prediction step
180 void predict() {
181 x = Fmat * x;
182 P = Fmat * P * transpose(Fmat) + Q;
183 }
184
185 // Update step
186 void update(const Matrix<NZ, 1>& z) {
187 auto y = z - (H * x); // innovation
188 auto S = H * P * transpose(H) + R; // innovation covariance
189 auto K = P * transpose(H) * inverse(S); // Kalman gain
190
191 x = x + (K * y);
192 P = (I - (K * H)) * P;
193 }
194};
195
196} // namespace tinyrobotics
A lightweight, fixed-size Kalman Filter for embedded state estimation.
Definition: KalmanFilter.h:167
Simple static matrix for linear algebra operations.
Definition: KalmanFilter.h:22