#![no_std] #![forbid(unsafe_code)]
#[cfg(feature = "f32")]
pub type Float = f32;
#[cfg(not(feature = "f32"))]
pub type Float = f64;
#[derive(Debug, Clone, Copy)]
pub struct LowPass1 {
y: Float,
pub tau: Float,
}
impl LowPass1 {
#[inline(always)]
pub fn new(initial: Float, tau: Float) -> Self {
Self { y: initial, tau }
}
#[inline(always)]
pub fn update(&mut self, input: Float, dt: Float) -> Float {
if !dt.is_finite() || dt <= 0.0 {
return self.y;
}
let safe_dt = if dt < 1e-6 { 1e-6 } else if dt > 0.1 { 0.1 } else { dt };
let alpha = safe_dt / (self.tau + safe_dt);
self.y = self.y + alpha * (input - self.y);
self.y
}
#[inline(always)]
pub fn reset(&mut self, value: Float) {
self.y = value;
}
}
#[cfg(test)]
mod tests {
extern crate std;
use super::*;
#[test]
fn test_lowpass_stability() {
let mut filter = LowPass1::new(0.0, 0.1);
let dt = 0.01;
let mut y = 0.0;
for _ in 0..200 { y = filter.update(1.0, dt); }
assert!((y - 1.0).abs() < 0.01);
}
#[test]
fn test_zero_dt_integrity() {
let mut filter = LowPass1::new(0.5, 0.1);
let y = filter.update(1.0, 0.0);
assert_eq!(y, 0.5);
}
}