1use crate::matrix::{mat_inverse_f32, MatrixInstance, MatrixInstanceMut};
9use crate::types::Status;
10
11#[derive(Debug, Clone, Copy)]
13pub struct KalmanFilter1D {
14 pub x: f32,
16 pub p: f32,
18 pub q: f32,
20 pub r: f32,
22}
23
24impl KalmanFilter1D {
25 pub fn new(x0: f32, p0: f32, q: f32, r: f32) -> Self {
27 Self { x: x0, p: p0, q, r }
28 }
29
30 pub fn predict(&mut self, u: f32) {
32 self.x += u;
33 self.p += self.q;
34 }
35
36 pub fn update(&mut self, z: f32) -> f32 {
38 let k = self.p / (self.p + self.r);
39 self.x += k * (z - self.x);
40 self.p = (1.0 - k) * self.p;
41 self.x
42 }
43}
44
45#[derive(Debug, Clone, Copy)]
47pub struct KalmanFilter2D {
48 pub x: [f32; 2],
50 pub p: [f32; 4],
52 pub q_var: f32,
54 pub r_var: f32,
56}
57
58impl KalmanFilter2D {
59 pub fn new(initial_pos: f32, initial_vel: f32, q_var: f32, r_var: f32) -> Self {
61 Self {
62 x: [initial_pos, initial_vel],
63 p: [1.0, 0.0, 0.0, 1.0],
64 q_var,
65 r_var,
66 }
67 }
68
69 pub fn predict(&mut self, dt: f32) {
71 self.x[0] += dt * self.x[1];
73
74 let dt2 = dt * dt;
76 let dt3 = dt2 * dt;
77 let dt4 = dt3 * dt;
78
79 let p00 =
80 self.p[0] + dt * (self.p[2] + self.p[1]) + dt2 * self.p[3] + 0.25 * dt4 * self.q_var;
81 let p01 = self.p[1] + dt * self.p[3] + 0.5 * dt3 * self.q_var;
82 let p10 = self.p[2] + dt * self.p[3] + 0.5 * dt3 * self.q_var;
83 let p11 = self.p[3] + dt2 * self.q_var;
84
85 self.p = [p00, p01, p10, p11];
86 }
87
88 pub fn update(&mut self, z_pos: f32) -> [f32; 2] {
90 let y = z_pos - self.x[0];
92 let s = self.p[0] + self.r_var;
93
94 let k0 = self.p[0] / s;
96 let k1 = self.p[2] / s;
97
98 self.x[0] += k0 * y;
100 self.x[1] += k1 * y;
101
102 let p00 = (1.0 - k0) * self.p[0];
104 let p01 = (1.0 - k0) * self.p[1];
105 let p10 = self.p[2] - k1 * self.p[0];
106 let p11 = self.p[3] - k1 * self.p[1];
107
108 self.p = [p00, p01, p10, p11];
109 self.x
110 }
111}
112
113#[inline]
116fn mat_vec_mul<const R: usize, const C: usize>(
117 a: &[[f32; C]; R],
118 x: &[f32; C],
119 out: &mut [f32; R],
120) {
121 for r in 0..R {
122 let mut sum = 0.0f32;
123 for c in 0..C {
124 sum += a[r][c] * x[c];
125 }
126 out[r] = sum;
127 }
128}
129
130#[inline]
131fn mat_mul<const R: usize, const K: usize, const C: usize>(
132 a: &[[f32; K]; R],
133 b: &[[f32; C]; K],
134 out: &mut [[f32; C]; R],
135) {
136 for r in 0..R {
137 for c in 0..C {
138 let mut sum = 0.0f32;
139 for k in 0..K {
140 sum += a[r][k] * b[k][c];
141 }
142 out[r][c] = sum;
143 }
144 }
145}
146
147#[inline]
149fn mat_mul_bt<const R: usize, const K: usize, const C: usize>(
150 a: &[[f32; K]; R],
151 b: &[[f32; K]; C],
152 out: &mut [[f32; C]; R],
153) {
154 for r in 0..R {
155 for c in 0..C {
156 let mut sum = 0.0f32;
157 for k in 0..K {
158 sum += a[r][k] * b[c][k];
159 }
160 out[r][c] = sum;
161 }
162 }
163}
164
165#[inline]
166fn mat_add_inplace_nn<const N: usize>(a: &mut [[f32; N]; N], b: &[[f32; N]; N]) {
167 for r in 0..N {
168 for c in 0..N {
169 a[r][c] += b[r][c];
170 }
171 }
172}
173
174#[inline]
175fn mat_add_inplace_mm<const M: usize>(a: &mut [[f32; M]; M], b: &[[f32; M]; M]) {
176 for r in 0..M {
177 for c in 0..M {
178 a[r][c] += b[r][c];
179 }
180 }
181}
182
183#[inline]
184fn identity_n<const N: usize>() -> [[f32; N]; N] {
185 let mut i = [[0.0f32; N]; N];
186 for n in 0..N {
187 i[n][n] = 1.0;
188 }
189 i
190}
191
192fn invert_mxm<const M: usize>(s: &[[f32; M]; M], s_inv: &mut [[f32; M]; M]) -> Status {
194 if M == 0 {
195 return Status::SizeMismatch;
196 }
197 if M > 16 {
198 return Status::ArgumentError;
199 }
200
201 let mut flat_src = [0.0f32; 16 * 16];
202 let mut flat_dst = [0.0f32; 16 * 16];
203 for r in 0..M {
204 for c in 0..M {
205 flat_src[r * M + c] = s[r][c];
206 }
207 }
208
209 let src = MatrixInstance::new(M as u16, M as u16, &flat_src[..M * M]);
210 let mut dst = MatrixInstanceMut::new(M as u16, M as u16, &mut flat_dst[..M * M]);
211 let status = mat_inverse_f32(&src, &mut dst);
212 if status != Status::Success {
213 return status;
214 }
215
216 for r in 0..M {
217 for c in 0..M {
218 s_inv[r][c] = flat_dst[r * M + c];
219 }
220 }
221 Status::Success
222}
223
224fn kf_predict_core<const N: usize>(
226 x: &mut [f32; N],
227 p: &mut [[f32; N]; N],
228 q: &[[f32; N]; N],
229 f: &[[f32; N]; N],
230) {
231 let mut x_new = [0.0f32; N];
232 mat_vec_mul(f, x, &mut x_new);
233 *x = x_new;
234
235 let mut fp = [[0.0f32; N]; N];
236 mat_mul(f, p, &mut fp);
237 let mut p_new = [[0.0f32; N]; N];
238 mat_mul_bt(&fp, f, &mut p_new);
239 mat_add_inplace_nn(&mut p_new, q);
240 *p = p_new;
241}
242
243fn kf_predict_control_core<const N: usize, const U: usize>(
245 x: &mut [f32; N],
246 p: &mut [[f32; N]; N],
247 q: &[[f32; N]; N],
248 f: &[[f32; N]; N],
249 b: &[[f32; U]; N],
250 u: &[f32; U],
251) {
252 let mut x_new = [0.0f32; N];
253 mat_vec_mul(f, x, &mut x_new);
254 let mut bu = [0.0f32; N];
255 mat_vec_mul(b, u, &mut bu);
256 for i in 0..N {
257 x_new[i] += bu[i];
258 }
259 *x = x_new;
260
261 let mut fp = [[0.0f32; N]; N];
262 mat_mul(f, p, &mut fp);
263 let mut p_new = [[0.0f32; N]; N];
264 mat_mul_bt(&fp, f, &mut p_new);
265 mat_add_inplace_nn(&mut p_new, q);
266 *p = p_new;
267}
268
269fn kf_update_core<const N: usize, const M: usize>(
271 x: &mut [f32; N],
272 p: &mut [[f32; N]; N],
273 r: &[[f32; M]; M],
274 h: &[[f32; N]; M],
275 z: &[f32; M],
276) -> Status {
277 if M > 16 {
278 return Status::ArgumentError;
279 }
280 if M == 0 {
281 return Status::SizeMismatch;
282 }
283
284 let mut hx = [0.0f32; M];
286 mat_vec_mul(h, x, &mut hx);
287 let mut y = [0.0f32; M];
288 for i in 0..M {
289 y[i] = z[i] - hx[i];
290 }
291
292 let mut hp = [[0.0f32; N]; M];
294 mat_mul(h, p, &mut hp);
295 let mut s = [[0.0f32; M]; M];
296 mat_mul_bt(&hp, h, &mut s);
297 mat_add_inplace_mm(&mut s, r);
298
299 let mut s_inv = [[0.0f32; M]; M];
300 let inv_status = invert_mxm(&s, &mut s_inv);
301 if inv_status != Status::Success {
302 return inv_status;
303 }
304
305 let mut pht = [[0.0f32; M]; N];
307 for i in 0..N {
308 for j in 0..M {
309 let mut sum = 0.0f32;
310 for k in 0..N {
311 sum += p[i][k] * h[j][k];
312 }
313 pht[i][j] = sum;
314 }
315 }
316
317 let mut k = [[0.0f32; M]; N];
319 mat_mul(&pht, &s_inv, &mut k);
320
321 let mut ky = [0.0f32; N];
323 mat_vec_mul(&k, &y, &mut ky);
324 let mut x_new = *x;
325 for i in 0..N {
326 x_new[i] += ky[i];
327 }
328
329 let mut kh = [[0.0f32; N]; N];
331 mat_mul(&k, h, &mut kh);
332 let mut i_kh = identity_n::<N>();
333 for r in 0..N {
334 for c in 0..N {
335 i_kh[r][c] -= kh[r][c];
336 }
337 }
338 let mut p_new = [[0.0f32; N]; N];
339 mat_mul(&i_kh, p, &mut p_new);
340
341 *x = x_new;
342 *p = p_new;
343 Status::Success
344}
345
346#[derive(Debug, Clone, Copy, PartialEq)]
351pub struct KalmanFilter<const N: usize, const M: usize> {
352 pub x: [f32; N],
354 pub p: [[f32; N]; N],
356 pub q: [[f32; N]; N],
358 pub r: [[f32; M]; M],
360}
361
362impl<const N: usize, const M: usize> KalmanFilter<N, M> {
363 pub fn new(x0: [f32; N], p0: [[f32; N]; N], q: [[f32; N]; N], r: [[f32; M]; M]) -> Self {
365 Self {
366 x: x0,
367 p: p0,
368 q,
369 r,
370 }
371 }
372
373 pub fn from_variances(x0: [f32; N], p_var: f32, q_var: f32, r_var: f32) -> Self {
375 let mut p = [[0.0f32; N]; N];
376 let mut q = [[0.0f32; N]; N];
377 let mut r = [[0.0f32; M]; M];
378 for i in 0..N {
379 p[i][i] = p_var;
380 q[i][i] = q_var;
381 }
382 for i in 0..M {
383 r[i][i] = r_var;
384 }
385 Self::new(x0, p, q, r)
386 }
387
388 pub fn predict(&mut self, f: &[[f32; N]; N]) {
390 kf_predict_core(&mut self.x, &mut self.p, &self.q, f);
391 }
392
393 pub fn predict_with_control<const U: usize>(
395 &mut self,
396 f: &[[f32; N]; N],
397 b: &[[f32; U]; N],
398 u: &[f32; U],
399 ) {
400 kf_predict_control_core(&mut self.x, &mut self.p, &self.q, f, b, u);
401 }
402
403 pub fn update(&mut self, h: &[[f32; N]; M], z: &[f32; M]) -> Status {
408 kf_update_core(&mut self.x, &mut self.p, &self.r, h, z)
409 }
410}
411
412pub trait EkfModel<const N: usize, const M: usize> {
414 fn f(&self, x: &[f32; N], dt: f32, out: &mut [f32; N]);
416
417 fn h(&self, x: &[f32; N], out: &mut [f32; M]);
419
420 fn jacobian_f(&self, x: &[f32; N], dt: f32, out: &mut [[f32; N]; N]);
422
423 fn jacobian_h(&self, x: &[f32; N], out: &mut [[f32; N]; M]);
425}
426
427#[derive(Debug, Clone, Copy, PartialEq)]
431pub struct ExtendedKalmanFilter<const N: usize, const M: usize, Model> {
432 pub x: [f32; N],
434 pub p: [[f32; N]; N],
436 pub q: [[f32; N]; N],
438 pub r: [[f32; M]; M],
440 pub model: Model,
442}
443
444impl<const N: usize, const M: usize, Model: EkfModel<N, M>> ExtendedKalmanFilter<N, M, Model> {
445 pub fn new(
447 x0: [f32; N],
448 p0: [[f32; N]; N],
449 q: [[f32; N]; N],
450 r: [[f32; M]; M],
451 model: Model,
452 ) -> Self {
453 Self {
454 x: x0,
455 p: p0,
456 q,
457 r,
458 model,
459 }
460 }
461
462 pub fn from_variances(x0: [f32; N], p_var: f32, q_var: f32, r_var: f32, model: Model) -> Self {
464 let mut p = [[0.0f32; N]; N];
465 let mut q = [[0.0f32; N]; N];
466 let mut r = [[0.0f32; M]; M];
467 for i in 0..N {
468 p[i][i] = p_var;
469 q[i][i] = q_var;
470 }
471 for i in 0..M {
472 r[i][i] = r_var;
473 }
474 Self::new(x0, p, q, r, model)
475 }
476
477 pub fn predict(&mut self, dt: f32) {
479 let mut f_jac = [[0.0f32; N]; N];
480 self.model.jacobian_f(&self.x, dt, &mut f_jac);
481
482 let mut x_new = [0.0f32; N];
483 self.model.f(&self.x, dt, &mut x_new);
484 self.x = x_new;
485
486 let mut fp = [[0.0f32; N]; N];
487 mat_mul(&f_jac, &self.p, &mut fp);
488 let mut p_new = [[0.0f32; N]; N];
489 mat_mul_bt(&fp, &f_jac, &mut p_new);
490 mat_add_inplace_nn(&mut p_new, &self.q);
491 self.p = p_new;
492 }
493
494 pub fn update(&mut self, z: &[f32; M]) -> Status {
498 if M > 16 {
499 return Status::ArgumentError;
500 }
501 if M == 0 {
502 return Status::SizeMismatch;
503 }
504
505 let mut h_jac = [[0.0f32; N]; M];
506 self.model.jacobian_h(&self.x, &mut h_jac);
507
508 let mut hx = [0.0f32; M];
509 self.model.h(&self.x, &mut hx);
510
511 let mut z_equiv = [0.0f32; M];
514 let mut hx_lin = [0.0f32; M];
515 mat_vec_mul(&h_jac, &self.x, &mut hx_lin);
516 for i in 0..M {
517 z_equiv[i] = z[i] - hx[i] + hx_lin[i];
518 }
519
520 kf_update_core(&mut self.x, &mut self.p, &self.r, &h_jac, &z_equiv)
521 }
522}