use crate::core::scalar::ControlScalar;
#[derive(Debug, Clone, Copy)]
pub struct TimeoutMonitor<S: ControlScalar> {
timeout: S,
elapsed: S,
in_violation: bool,
}
impl<S: ControlScalar> TimeoutMonitor<S> {
pub fn new(timeout: S) -> Self {
Self {
timeout,
elapsed: S::ZERO,
in_violation: false,
}
}
pub fn feed(&mut self) {
self.elapsed = S::ZERO;
self.in_violation = false;
}
pub fn check(&mut self, dt: S) -> bool {
self.elapsed += dt;
if self.elapsed >= self.timeout {
self.in_violation = true;
false
} else {
true
}
}
pub fn in_violation(&self) -> bool {
self.in_violation
}
pub fn reset(&mut self) {
self.elapsed = S::ZERO;
self.in_violation = false;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_timeout_when_fed() {
let mut m = TimeoutMonitor::<f64>::new(0.1);
assert!(m.check(0.05));
m.feed();
assert!(m.check(0.05));
m.feed();
assert!(m.check(0.05));
assert!(!m.in_violation());
}
#[test]
fn timeout_when_not_fed() {
let mut m = TimeoutMonitor::<f64>::new(0.1);
assert!(m.check(0.05));
assert!(!m.check(0.06));
assert!(m.in_violation());
}
#[test]
fn feed_clears_violation() {
let mut m = TimeoutMonitor::<f64>::new(0.1);
m.check(0.2);
assert!(m.in_violation());
m.feed();
assert!(!m.in_violation());
assert!(m.check(0.05));
}
#[test]
fn reset_clears() {
let mut m = TimeoutMonitor::<f64>::new(0.1);
m.check(0.2);
m.reset();
assert!(!m.in_violation());
}
}