1use crate::matrix::{mat_inverse_f32, MatrixInstance, MatrixInstanceMut};
17use crate::types::Status;
18
19#[derive(Debug, Clone, Copy)]
21pub struct KalmanFilter1D {
22 pub x: f32,
24 pub p: f32,
26 pub q: f32,
28 pub r: f32,
30}
31
32impl KalmanFilter1D {
33 pub fn new(x0: f32, p0: f32, q: f32, r: f32) -> Self {
35 Self { x: x0, p: p0, q, r }
36 }
37
38 pub fn predict(&mut self, u: f32) {
40 self.x += u;
41 self.p += self.q;
42 }
43
44 pub fn update(&mut self, z: f32) -> f32 {
46 let k = self.p / (self.p + self.r);
47 self.x += k * (z - self.x);
48 self.p = (1.0 - k) * self.p;
49 self.x
50 }
51}
52
53#[derive(Debug, Clone, Copy)]
55pub struct KalmanFilter2D {
56 pub x: [f32; 2],
58 pub p: [f32; 4],
60 pub q_var: f32,
62 pub r_var: f32,
64}
65
66impl KalmanFilter2D {
67 pub fn new(initial_pos: f32, initial_vel: f32, q_var: f32, r_var: f32) -> Self {
69 Self {
70 x: [initial_pos, initial_vel],
71 p: [1.0, 0.0, 0.0, 1.0],
72 q_var,
73 r_var,
74 }
75 }
76
77 pub fn predict(&mut self, dt: f32) {
79 self.x[0] += dt * self.x[1];
81
82 let dt2 = dt * dt;
84 let dt3 = dt2 * dt;
85 let dt4 = dt3 * dt;
86
87 let p00 =
88 self.p[0] + dt * (self.p[2] + self.p[1]) + dt2 * self.p[3] + 0.25 * dt4 * self.q_var;
89 let p01 = self.p[1] + dt * self.p[3] + 0.5 * dt3 * self.q_var;
90 let p10 = self.p[2] + dt * self.p[3] + 0.5 * dt3 * self.q_var;
91 let p11 = self.p[3] + dt2 * self.q_var;
92
93 self.p = [p00, p01, p10, p11];
94 }
95
96 pub fn update(&mut self, z_pos: f32) -> [f32; 2] {
98 let y = z_pos - self.x[0];
100 let s = self.p[0] + self.r_var;
101
102 let k0 = self.p[0] / s;
104 let k1 = self.p[2] / s;
105
106 self.x[0] += k0 * y;
108 self.x[1] += k1 * y;
109
110 let p00 = (1.0 - k0) * self.p[0];
112 let p01 = (1.0 - k0) * self.p[1];
113 let p10 = self.p[2] - k1 * self.p[0];
114 let p11 = self.p[3] - k1 * self.p[1];
115
116 self.p = [p00, p01, p10, p11];
117 self.x
118 }
119}
120
121#[inline]
124fn mat_vec_mul<const R: usize, const C: usize>(
125 a: &[[f32; C]; R],
126 x: &[f32; C],
127 out: &mut [f32; R],
128) {
129 for r in 0..R {
130 let mut sum = 0.0f32;
131 for c in 0..C {
132 sum += a[r][c] * x[c];
133 }
134 out[r] = sum;
135 }
136}
137
138#[inline]
139fn mat_mul<const R: usize, const K: usize, const C: usize>(
140 a: &[[f32; K]; R],
141 b: &[[f32; C]; K],
142 out: &mut [[f32; C]; R],
143) {
144 for r in 0..R {
145 for c in 0..C {
146 let mut sum = 0.0f32;
147 for k in 0..K {
148 sum += a[r][k] * b[k][c];
149 }
150 out[r][c] = sum;
151 }
152 }
153}
154
155#[inline]
157fn mat_mul_bt<const R: usize, const K: usize, const C: usize>(
158 a: &[[f32; K]; R],
159 b: &[[f32; K]; C],
160 out: &mut [[f32; C]; R],
161) {
162 for r in 0..R {
163 for c in 0..C {
164 let mut sum = 0.0f32;
165 for k in 0..K {
166 sum += a[r][k] * b[c][k];
167 }
168 out[r][c] = sum;
169 }
170 }
171}
172
173#[inline]
174fn mat_add_inplace_nn<const N: usize>(a: &mut [[f32; N]; N], b: &[[f32; N]; N]) {
175 for r in 0..N {
176 for c in 0..N {
177 a[r][c] += b[r][c];
178 }
179 }
180}
181
182#[inline]
183fn mat_add_inplace_mm<const M: usize>(a: &mut [[f32; M]; M], b: &[[f32; M]; M]) {
184 for r in 0..M {
185 for c in 0..M {
186 a[r][c] += b[r][c];
187 }
188 }
189}
190
191#[inline]
192fn identity_n<const N: usize>() -> [[f32; N]; N] {
193 let mut i = [[0.0f32; N]; N];
194 for n in 0..N {
195 i[n][n] = 1.0;
196 }
197 i
198}
199
200fn invert_mxm<const M: usize>(s: &[[f32; M]; M], s_inv: &mut [[f32; M]; M]) -> Status {
202 if M == 0 {
203 return Status::SizeMismatch;
204 }
205 if M > 16 {
206 return Status::ArgumentError;
207 }
208
209 let mut flat_src = [0.0f32; 16 * 16];
210 let mut flat_dst = [0.0f32; 16 * 16];
211 for r in 0..M {
212 for c in 0..M {
213 flat_src[r * M + c] = s[r][c];
214 }
215 }
216
217 let src = MatrixInstance::new(M as u16, M as u16, &flat_src[..M * M]);
218 let mut dst = MatrixInstanceMut::new(M as u16, M as u16, &mut flat_dst[..M * M]);
219 let status = mat_inverse_f32(&src, &mut dst);
220 if status != Status::Success {
221 return status;
222 }
223
224 for r in 0..M {
225 for c in 0..M {
226 s_inv[r][c] = flat_dst[r * M + c];
227 }
228 }
229 Status::Success
230}
231
232fn kf_predict_core<const N: usize>(
234 x: &mut [f32; N],
235 p: &mut [[f32; N]; N],
236 q: &[[f32; N]; N],
237 f: &[[f32; N]; N],
238) {
239 let mut x_new = [0.0f32; N];
240 mat_vec_mul(f, x, &mut x_new);
241 *x = x_new;
242
243 let mut fp = [[0.0f32; N]; N];
244 mat_mul(f, p, &mut fp);
245 let mut p_new = [[0.0f32; N]; N];
246 mat_mul_bt(&fp, f, &mut p_new);
247 mat_add_inplace_nn(&mut p_new, q);
248 *p = p_new;
249}
250
251fn kf_predict_control_core<const N: usize, const U: usize>(
253 x: &mut [f32; N],
254 p: &mut [[f32; N]; N],
255 q: &[[f32; N]; N],
256 f: &[[f32; N]; N],
257 b: &[[f32; U]; N],
258 u: &[f32; U],
259) {
260 let mut x_new = [0.0f32; N];
261 mat_vec_mul(f, x, &mut x_new);
262 let mut bu = [0.0f32; N];
263 mat_vec_mul(b, u, &mut bu);
264 for i in 0..N {
265 x_new[i] += bu[i];
266 }
267 *x = x_new;
268
269 let mut fp = [[0.0f32; N]; N];
270 mat_mul(f, p, &mut fp);
271 let mut p_new = [[0.0f32; N]; N];
272 mat_mul_bt(&fp, f, &mut p_new);
273 mat_add_inplace_nn(&mut p_new, q);
274 *p = p_new;
275}
276
277fn kf_update_core<const N: usize, const M: usize>(
279 x: &mut [f32; N],
280 p: &mut [[f32; N]; N],
281 r: &[[f32; M]; M],
282 h: &[[f32; N]; M],
283 z: &[f32; M],
284) -> Status {
285 if M > 16 {
286 return Status::ArgumentError;
287 }
288 if M == 0 {
289 return Status::SizeMismatch;
290 }
291
292 let mut hx = [0.0f32; M];
294 mat_vec_mul(h, x, &mut hx);
295 let mut y = [0.0f32; M];
296 for i in 0..M {
297 y[i] = z[i] - hx[i];
298 }
299
300 let mut hp = [[0.0f32; N]; M];
302 mat_mul(h, p, &mut hp);
303 let mut s = [[0.0f32; M]; M];
304 mat_mul_bt(&hp, h, &mut s);
305 mat_add_inplace_mm(&mut s, r);
306
307 let mut s_inv = [[0.0f32; M]; M];
308 let inv_status = invert_mxm(&s, &mut s_inv);
309 if inv_status != Status::Success {
310 return inv_status;
311 }
312
313 let mut pht = [[0.0f32; M]; N];
315 for i in 0..N {
316 for j in 0..M {
317 let mut sum = 0.0f32;
318 for k in 0..N {
319 sum += p[i][k] * h[j][k];
320 }
321 pht[i][j] = sum;
322 }
323 }
324
325 let mut k = [[0.0f32; M]; N];
327 mat_mul(&pht, &s_inv, &mut k);
328
329 let mut ky = [0.0f32; N];
331 mat_vec_mul(&k, &y, &mut ky);
332 let mut x_new = *x;
333 for i in 0..N {
334 x_new[i] += ky[i];
335 }
336
337 let mut kh = [[0.0f32; N]; N];
339 mat_mul(&k, h, &mut kh);
340 let mut i_kh = identity_n::<N>();
341 for r in 0..N {
342 for c in 0..N {
343 i_kh[r][c] -= kh[r][c];
344 }
345 }
346 let mut p_new = [[0.0f32; N]; N];
347 mat_mul(&i_kh, p, &mut p_new);
348
349 *x = x_new;
350 *p = p_new;
351 Status::Success
352}
353
354#[derive(Debug, Clone, Copy, PartialEq)]
359pub struct KalmanFilter<const N: usize, const M: usize> {
360 pub x: [f32; N],
362 pub p: [[f32; N]; N],
364 pub q: [[f32; N]; N],
366 pub r: [[f32; M]; M],
368}
369
370impl<const N: usize, const M: usize> KalmanFilter<N, M> {
371 pub fn new(x0: [f32; N], p0: [[f32; N]; N], q: [[f32; N]; N], r: [[f32; M]; M]) -> Self {
373 Self { x: x0, p: p0, q, r }
374 }
375
376 pub fn from_variances(x0: [f32; N], p_var: f32, q_var: f32, r_var: f32) -> Self {
378 let mut p = [[0.0f32; N]; N];
379 let mut q = [[0.0f32; N]; N];
380 let mut r = [[0.0f32; M]; M];
381 for i in 0..N {
382 p[i][i] = p_var;
383 q[i][i] = q_var;
384 }
385 for i in 0..M {
386 r[i][i] = r_var;
387 }
388 Self::new(x0, p, q, r)
389 }
390
391 pub fn predict(&mut self, f: &[[f32; N]; N]) {
393 kf_predict_core(&mut self.x, &mut self.p, &self.q, f);
394 }
395
396 pub fn predict_with_control<const U: usize>(
398 &mut self,
399 f: &[[f32; N]; N],
400 b: &[[f32; U]; N],
401 u: &[f32; U],
402 ) {
403 kf_predict_control_core(&mut self.x, &mut self.p, &self.q, f, b, u);
404 }
405
406 pub fn update(&mut self, h: &[[f32; N]; M], z: &[f32; M]) -> Status {
411 kf_update_core(&mut self.x, &mut self.p, &self.r, h, z)
412 }
413}
414
415pub trait EkfModel<const N: usize, const M: usize> {
417 fn f(&self, x: &[f32; N], dt: f32, out: &mut [f32; N]);
419
420 fn h(&self, x: &[f32; N], out: &mut [f32; M]);
422
423 fn jacobian_f(&self, x: &[f32; N], dt: f32, out: &mut [[f32; N]; N]);
425
426 fn jacobian_h(&self, x: &[f32; N], out: &mut [[f32; N]; M]);
428
429 fn f_with_input<const U: usize>(
436 &self,
437 x: &[f32; N],
438 u: &[f32; U],
439 dt: f32,
440 out: &mut [f32; N],
441 ) {
442 let _ = u;
443 self.f(x, dt, out)
444 }
445
446 fn jacobian_f_with_input<const U: usize>(
451 &self,
452 x: &[f32; N],
453 u: &[f32; U],
454 dt: f32,
455 out: &mut [[f32; N]; N],
456 ) {
457 let _ = u;
458 self.jacobian_f(x, dt, out)
459 }
460
461 fn h_with_input<const U: usize>(&self, x: &[f32; N], u: &[f32; U], out: &mut [f32; M]) {
466 let _ = u;
467 self.h(x, out)
468 }
469
470 fn jacobian_h_with_input<const U: usize>(
475 &self,
476 x: &[f32; N],
477 u: &[f32; U],
478 out: &mut [[f32; N]; M],
479 ) {
480 let _ = u;
481 self.jacobian_h(x, out)
482 }
483}
484
485#[derive(Debug, Clone, Copy, PartialEq)]
489pub struct ExtendedKalmanFilter<const N: usize, const M: usize, Model> {
490 pub x: [f32; N],
492 pub p: [[f32; N]; N],
494 pub q: [[f32; N]; N],
496 pub r: [[f32; M]; M],
498 pub model: Model,
500}
501
502impl<const N: usize, const M: usize, Model: EkfModel<N, M>> ExtendedKalmanFilter<N, M, Model> {
503 pub fn new(
505 x0: [f32; N],
506 p0: [[f32; N]; N],
507 q: [[f32; N]; N],
508 r: [[f32; M]; M],
509 model: Model,
510 ) -> Self {
511 Self {
512 x: x0,
513 p: p0,
514 q,
515 r,
516 model,
517 }
518 }
519
520 pub fn from_variances(x0: [f32; N], p_var: f32, q_var: f32, r_var: f32, model: Model) -> Self {
522 let mut p = [[0.0f32; N]; N];
523 let mut q = [[0.0f32; N]; N];
524 let mut r = [[0.0f32; M]; M];
525 for i in 0..N {
526 p[i][i] = p_var;
527 q[i][i] = q_var;
528 }
529 for i in 0..M {
530 r[i][i] = r_var;
531 }
532 Self::new(x0, p, q, r, model)
533 }
534
535 pub fn predict(&mut self, dt: f32) {
537 let mut f_jac = [[0.0f32; N]; N];
538 self.model.jacobian_f(&self.x, dt, &mut f_jac);
539
540 let mut x_new = [0.0f32; N];
541 self.model.f(&self.x, dt, &mut x_new);
542
543 ekf_predict_apply(&mut self.x, &mut self.p, &self.q, &f_jac, x_new);
544 }
545
546 pub fn predict_with_input<const U: usize>(&mut self, dt: f32, u: &[f32; U]) {
550 let mut f_jac = [[0.0f32; N]; N];
551 self.model.jacobian_f_with_input(&self.x, u, dt, &mut f_jac);
552
553 let mut x_new = [0.0f32; N];
554 self.model.f_with_input(&self.x, u, dt, &mut x_new);
555
556 ekf_predict_apply(&mut self.x, &mut self.p, &self.q, &f_jac, x_new);
557 }
558
559 pub fn update(&mut self, z: &[f32; M]) -> Status {
563 let mut h_jac = [[0.0f32; N]; M];
564 self.model.jacobian_h(&self.x, &mut h_jac);
565
566 let mut hx = [0.0f32; M];
567 self.model.h(&self.x, &mut hx);
568
569 ekf_update_apply(&mut self.x, &mut self.p, &self.r, &h_jac, &hx, z)
570 }
571
572 pub fn update_with_input<const U: usize>(&mut self, z: &[f32; M], u: &[f32; U]) -> Status {
578 let mut h_jac = [[0.0f32; N]; M];
579 self.model.jacobian_h_with_input(&self.x, u, &mut h_jac);
580
581 let mut hx = [0.0f32; M];
582 self.model.h_with_input(&self.x, u, &mut hx);
583
584 ekf_update_apply(&mut self.x, &mut self.p, &self.r, &h_jac, &hx, z)
585 }
586}
587
588fn ekf_predict_apply<const N: usize>(
592 x: &mut [f32; N],
593 p: &mut [[f32; N]; N],
594 q: &[[f32; N]; N],
595 f_jac: &[[f32; N]; N],
596 x_new: [f32; N],
597) {
598 *x = x_new;
599
600 let mut fp = [[0.0f32; N]; N];
601 mat_mul(f_jac, p, &mut fp);
602 let mut p_new = [[0.0f32; N]; N];
603 mat_mul_bt(&fp, f_jac, &mut p_new);
604 mat_add_inplace_nn(&mut p_new, q);
605 *p = p_new;
606}
607
608fn ekf_update_apply<const N: usize, const M: usize>(
613 x: &mut [f32; N],
614 p: &mut [[f32; N]; N],
615 r: &[[f32; M]; M],
616 h_jac: &[[f32; N]; M],
617 hx: &[f32; M],
618 z: &[f32; M],
619) -> Status {
620 if M > 16 {
621 return Status::ArgumentError;
622 }
623 if M == 0 {
624 return Status::SizeMismatch;
625 }
626
627 let mut z_equiv = [0.0f32; M];
630 let mut hx_lin = [0.0f32; M];
631 mat_vec_mul(h_jac, x, &mut hx_lin);
632 for i in 0..M {
633 z_equiv[i] = z[i] - hx[i] + hx_lin[i];
634 }
635
636 kf_update_core(x, p, r, h_jac, &z_equiv)
637}