1use crate::common::{FilterError, FloatOps};
4
5#[derive(Debug, Clone, Copy)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct ScalarKalmanFilter {
9 x: f64,
10 p: f64,
11 q: f64,
12 r: f64,
13}
14
15impl ScalarKalmanFilter {
16 pub fn new(
17 initial_state: f64,
18 initial_variance: f64,
19 process_noise: f64,
20 measurement_noise: f64,
21 ) -> Result<Self, FilterError> {
22 if !initial_state.is_finite()
23 || !initial_variance.is_finite()
24 || !process_noise.is_finite()
25 || !measurement_noise.is_finite()
26 {
27 return Err(FilterError::NonFiniteInput);
28 }
29
30 if initial_variance <= 0.0 || process_noise < 0.0 || measurement_noise <= 0.0 {
31 return Err(FilterError::InvalidCovariance);
32 }
33
34 Ok(Self {
35 x: initial_state,
36 p: initial_variance,
37 q: process_noise,
38 r: measurement_noise,
39 })
40 }
41
42 pub fn predict(&mut self, control_input: f64) -> Result<(), FilterError> {
43 if !control_input.is_finite() {
44 return Err(FilterError::NonFiniteInput);
45 }
46
47 self.x += control_input;
48 self.p += self.q;
49
50 if !self.x.is_finite() || !self.p.is_finite() {
51 return Err(FilterError::NonFiniteInput);
52 }
53
54 Ok(())
55 }
56
57 pub fn update(
58 &mut self,
59 measurement: f64,
60 gate_threshold_sigma: Option<f64>,
61 ) -> Result<f64, FilterError> {
62 if !measurement.is_finite() {
63 return Err(FilterError::NonFiniteInput);
64 }
65
66 let y = measurement - self.x;
67 let s = self.p + self.r;
68 if s <= 1e-15 || !s.is_finite() {
69 return Err(FilterError::SingularInnovation);
70 }
71
72 if let Some(gate_sigma) = gate_threshold_sigma {
73 if gate_sigma > 0.0 {
74 let normalized_residual = y.abs_val() / s.sqrt_val();
75 if normalized_residual > gate_sigma {
76 return Err(FilterError::MeasurementGated);
77 }
78 }
79 }
80
81 let k = self.p / s;
82 self.x += k * y;
83
84 let one_minus_k = 1.0 - k;
86 self.p = (one_minus_k * one_minus_k * self.p) + (k * k * self.r);
87
88 if self.p < 1e-15 {
89 self.p = 1e-15;
90 }
91
92 Ok(self.x)
93 }
94
95 #[inline(always)]
96 pub fn state(&self) -> f64 {
97 self.x
98 }
99
100 #[inline(always)]
101 pub fn variance(&self) -> f64 {
102 self.p
103 }
104}
105
106#[derive(Debug, Clone)]
108pub struct LinearKalmanFilter<const S: usize, const M: usize> {
109 pub x: [f64; S],
110 pub p: [[f64; S]; S],
111 pub f: [[f64; S]; S],
112 pub q: [[f64; S]; S],
113 pub h: [[f64; S]; M],
114 pub r: [[f64; M]; M],
115}
116
117impl<const S: usize, const M: usize> LinearKalmanFilter<S, M> {
118 pub fn new(
119 initial_x: [f64; S],
120 initial_p: [[f64; S]; S],
121 f: [[f64; S]; S],
122 q: [[f64; S]; S],
123 h: [[f64; S]; M],
124 r: [[f64; M]; M],
125 ) -> Result<Self, FilterError> {
126 for val in initial_x.iter() {
127 if !val.is_finite() {
128 return Err(FilterError::NonFiniteInput);
129 }
130 }
131 Self::validate_matrix(&initial_p)?;
132 Self::validate_matrix(&f)?;
133 Self::validate_matrix(&q)?;
134 Self::validate_matrix(&h)?;
135 Self::validate_matrix(&r)?;
136
137 Ok(Self {
138 x: initial_x,
139 p: initial_p,
140 f,
141 q,
142 h,
143 r,
144 })
145 }
146
147 fn validate_matrix<const R: usize, const C: usize>(
148 matrix: &[[f64; C]; R],
149 ) -> Result<(), FilterError> {
150 for row in matrix.iter() {
151 for val in row.iter() {
152 if !val.is_finite() {
153 return Err(FilterError::NonFiniteInput);
154 }
155 }
156 }
157 Ok(())
158 }
159
160 #[allow(clippy::needless_range_loop)]
161 pub fn predict(&mut self) -> Result<(), FilterError> {
162 let mut x_pred = [0.0; S];
163 for i in 0..S {
164 let mut sum = 0.0;
165 for j in 0..S {
166 sum += self.f[i][j] * self.x[j];
167 }
168 x_pred[i] = sum;
169 }
170
171 let mut f_p = [[0.0; S]; S];
172 for i in 0..S {
173 for j in 0..S {
174 let mut sum = 0.0;
175 for k in 0..S {
176 sum += self.f[i][k] * self.p[k][j];
177 }
178 f_p[i][j] = sum;
179 }
180 }
181
182 let mut p_pred = [[0.0; S]; S];
183 for i in 0..S {
184 for j in 0..S {
185 let mut sum = 0.0;
186 for k in 0..S {
187 sum += f_p[i][k] * self.f[j][k];
188 }
189 p_pred[i][j] = sum + self.q[i][j];
190 }
191 }
192
193 for i in 0..S {
194 for j in (i + 1)..S {
195 let avg = (p_pred[i][j] + p_pred[j][i]) * 0.5;
196 p_pred[i][j] = avg;
197 p_pred[j][i] = avg;
198 }
199 }
200
201 self.x = x_pred;
202 self.p = p_pred;
203 Ok(())
204 }
205}