1use crate::common::FilterError;
11
12#[derive(Debug, Clone, Copy)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct HInfinityFilter1D {
20 x: f64,
22 p: f64,
24 q: f64,
26 r: f64,
28 gamma: f64,
30}
31
32impl HInfinityFilter1D {
33 pub fn new(
36 initial_state: f64,
37 initial_variance: f64,
38 process_bound_q: f64,
39 measurement_bound_r: f64,
40 gamma: f64,
41 ) -> Result<Self, FilterError> {
42 if !initial_state.is_finite()
43 || initial_variance <= 0.0
44 || process_bound_q < 0.0
45 || measurement_bound_r <= 0.0
46 || gamma <= 0.0
47 {
48 return Err(FilterError::InvalidCovariance);
49 }
50
51 Ok(Self {
52 x: initial_state,
53 p: initial_variance,
54 q: process_bound_q,
55 r: measurement_bound_r,
56 gamma,
57 })
58 }
59
60 pub fn predict(&mut self, control_input: f64) -> Result<(), FilterError> {
64 if !control_input.is_finite() {
65 return Err(FilterError::NonFiniteInput);
66 }
67 self.x += control_input;
68 self.p += self.q;
69 Ok(())
70 }
71
72 pub fn update(&mut self, measurement: f64) -> Result<f64, FilterError> {
76 if !measurement.is_finite() {
77 return Err(FilterError::NonFiniteInput);
78 }
79
80 let gamma_sq = self.gamma * self.gamma;
81 let _h_term = 1.0; let d = 1.0 - (self.p / gamma_sq) + (self.p / self.r);
86
87 if d <= 1e-12 || !d.is_finite() {
89 return Err(FilterError::NumericalInstability);
90 }
91
92 let k = self.p / (self.r * d);
95
96 let residual = measurement - self.x;
98 self.x += k * residual;
99
100 self.p /= d;
102
103 if self.p < 1e-15 {
104 self.p = 1e-15;
105 }
106
107 Ok(self.x)
108 }
109
110 #[inline(always)]
111 pub fn state(&self) -> f64 {
112 self.x
113 }
114
115 #[inline(always)]
116 pub fn bound(&self) -> f64 {
117 self.p
118 }
119}
120
121#[derive(Debug, Clone)]
125#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
126pub struct AdaptiveFilter1D {
127 pub x: f64,
128 pub p: f64,
129 pub q: f64,
130 pub r: f64,
131 pub alpha: f64,
133}
134
135impl AdaptiveFilter1D {
136 pub fn new(
137 initial_x: f64,
138 initial_p: f64,
139 q: f64,
140 initial_r: f64,
141 adaptation_rate: f64,
142 ) -> Result<Self, FilterError> {
143 if !initial_x.is_finite()
144 || initial_p <= 0.0
145 || q < 0.0
146 || initial_r <= 0.0
147 || adaptation_rate <= 0.0
148 || adaptation_rate >= 1.0
149 {
150 return Err(FilterError::InvalidCovariance);
151 }
152
153 Ok(Self {
154 x: initial_x,
155 p: initial_p,
156 q,
157 r: initial_r,
158 alpha: adaptation_rate,
159 })
160 }
161
162 pub fn predict(&mut self, u: f64) {
163 self.x += u;
164 self.p += self.q;
165 }
166
167 pub fn update(&mut self, z: f64) -> Result<f64, FilterError> {
168 if !z.is_finite() {
169 return Err(FilterError::NonFiniteInput);
170 }
171
172 let y = z - self.x;
173 let s = self.p + self.r;
174
175 let k = self.p / s;
176 self.x += k * y;
177
178 let one_minus_k = 1.0 - k;
180 self.p = (one_minus_k * one_minus_k * self.p) + (k * k * self.r);
181
182 let r_sample = y * y - self.p;
185 if r_sample > 1e-6 {
186 self.r = (1.0 - self.alpha) * self.r + self.alpha * r_sample;
187 }
188
189 Ok(self.x)
190 }
191
192 #[inline(always)]
193 pub fn estimated_measurement_noise(&self) -> f64 {
194 self.r
195 }
196}