use core::time::Duration;
use vexide::core::time::Instant;
#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Settler {
start_timestamp: Option<Instant>,
tolerance_timestamp: Option<Instant>,
tolerance_duration: Option<Duration>,
error_tolerance: Option<f64>,
velocity_tolerance: Option<f64>,
timeout: Option<Duration>,
}
impl Settler {
pub fn new() -> Self {
Self::default()
}
pub fn error_tolerance(&mut self, tolerance: f64) -> Self {
self.error_tolerance = Some(tolerance);
*self
}
pub fn velocity_tolerance(&mut self, tolerance: f64) -> Self {
self.velocity_tolerance = Some(tolerance);
*self
}
pub fn tolerance_duration(&mut self, duration: Duration) -> Self {
self.tolerance_duration = Some(duration);
*self
}
pub fn timeout(&mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
*self
}
pub fn is_settled(&mut self, error: f64, velocity: f64) -> bool {
if self.start_timestamp.is_none() {
self.start_timestamp = Some(Instant::now());
}
if let Some(timeout) = self.timeout {
if self.start_timestamp.unwrap().elapsed() > timeout {
return true;
}
}
let in_tolerances = self
.error_tolerance
.is_none_or(|tolerance| error < tolerance)
&& self
.velocity_tolerance
.is_none_or(|tolerance| velocity < tolerance);
if in_tolerances {
if self.tolerance_timestamp.is_none() {
self.tolerance_timestamp = Some(Instant::now());
}
if self
.tolerance_duration
.is_none_or(|time| self.tolerance_timestamp.unwrap().elapsed() > time)
{
return true;
}
} else if self.tolerance_timestamp.is_some() {
self.tolerance_timestamp = None;
}
false
}
}