use crate::common::FilterError;
#[derive(Debug, Clone, Copy)]
pub struct HInfinityFilter1D {
x: f64,
p: f64,
q: f64,
r: f64,
gamma: f64,
}
impl HInfinityFilter1D {
pub fn new(
initial_state: f64,
initial_variance: f64,
process_bound_q: f64,
measurement_bound_r: f64,
gamma: f64,
) -> Result<Self, FilterError> {
if !initial_state.is_finite()
|| initial_variance <= 0.0
|| process_bound_q < 0.0
|| measurement_bound_r <= 0.0
|| gamma <= 0.0
{
return Err(FilterError::InvalidCovariance);
}
Ok(Self {
x: initial_state,
p: initial_variance,
q: process_bound_q,
r: measurement_bound_r,
gamma,
})
}
pub fn predict(&mut self, control_input: f64) -> Result<(), FilterError> {
if !control_input.is_finite() {
return Err(FilterError::NonFiniteInput);
}
self.x += control_input;
self.p += self.q;
Ok(())
}
pub fn update(&mut self, measurement: f64) -> Result<f64, FilterError> {
if !measurement.is_finite() {
return Err(FilterError::NonFiniteInput);
}
let gamma_sq = self.gamma * self.gamma;
let _h_term = 1.0;
let d = 1.0 - (self.p / gamma_sq) + (self.p / self.r);
if d <= 1e-12 || !d.is_finite() {
return Err(FilterError::NumericalInstability);
}
let k = self.p / (self.r * d);
let residual = measurement - self.x;
self.x += k * residual;
self.p /= d;
if self.p < 1e-15 {
self.p = 1e-15;
}
Ok(self.x)
}
#[inline(always)]
pub fn state(&self) -> f64 {
self.x
}
#[inline(always)]
pub fn bound(&self) -> f64 {
self.p
}
}
#[derive(Debug, Clone)]
pub struct AdaptiveFilter1D {
pub x: f64,
pub p: f64,
pub q: f64,
pub r: f64,
pub alpha: f64,
}
impl AdaptiveFilter1D {
pub fn new(
initial_x: f64,
initial_p: f64,
q: f64,
initial_r: f64,
adaptation_rate: f64,
) -> Result<Self, FilterError> {
if !initial_x.is_finite()
|| initial_p <= 0.0
|| q < 0.0
|| initial_r <= 0.0
|| adaptation_rate <= 0.0
|| adaptation_rate >= 1.0
{
return Err(FilterError::InvalidCovariance);
}
Ok(Self {
x: initial_x,
p: initial_p,
q,
r: initial_r,
alpha: adaptation_rate,
})
}
pub fn predict(&mut self, u: f64) {
self.x += u;
self.p += self.q;
}
pub fn update(&mut self, z: f64) -> Result<f64, FilterError> {
if !z.is_finite() {
return Err(FilterError::NonFiniteInput);
}
let y = z - self.x;
let s = self.p + self.r;
let k = self.p / s;
self.x += k * y;
let one_minus_k = 1.0 - k;
self.p = (one_minus_k * one_minus_k * self.p) + (k * k * self.r);
let r_sample = y * y - self.p;
if r_sample > 1e-6 {
self.r = (1.0 - self.alpha) * self.r + self.alpha * r_sample;
}
Ok(self.x)
}
#[inline(always)]
pub fn estimated_measurement_noise(&self) -> f64 {
self.r
}
}