Skip to main content

entrenar/monitor/inference/safety_andon/
emergency.rs

1//! Emergency conditions that trigger immediate action
2
3use crate::monitor::andon::AlertLevel;
4use serde::{Deserialize, Serialize};
5
6/// Emergency condition that triggers immediate action
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub enum EmergencyCondition {
9    /// Collision imminent (AV)
10    CollisionImminent {
11        /// Time to collision in milliseconds
12        time_to_collision_ms: f32,
13    },
14
15    /// Sensor degraded
16    SensorDegraded {
17        /// Sensor identifier
18        sensor: String,
19        /// Quality score (0.0 - 1.0)
20        quality: f32,
21    },
22
23    /// Audit chain integrity failure
24    AuditChainBroken,
25
26    /// Decision system timeout
27    DecisionTimeout {
28        /// Maximum allowed latency in milliseconds
29        max_ms: f32,
30    },
31
32    /// Repeated low-confidence decisions
33    ConsecutiveLowConfidence {
34        /// Number of consecutive low-confidence decisions
35        count: usize,
36        /// Threshold for low confidence
37        threshold: f32,
38    },
39
40    /// NaN or Inf detected in output
41    InvalidOutput,
42}
43
44impl EmergencyCondition {
45    /// Get alert level for this condition
46    pub fn alert_level(&self) -> AlertLevel {
47        match self {
48            EmergencyCondition::CollisionImminent { .. } => AlertLevel::Critical,
49            EmergencyCondition::SensorDegraded { quality, .. } if *quality < 0.3 => {
50                AlertLevel::Critical
51            }
52            EmergencyCondition::SensorDegraded { .. } => AlertLevel::Error,
53            EmergencyCondition::AuditChainBroken => AlertLevel::Critical,
54            EmergencyCondition::DecisionTimeout { .. } => AlertLevel::Error,
55            EmergencyCondition::ConsecutiveLowConfidence { .. } => AlertLevel::Warning,
56            EmergencyCondition::InvalidOutput => AlertLevel::Critical,
57        }
58    }
59
60    /// Generate alert message
61    pub fn message(&self) -> String {
62        match self {
63            EmergencyCondition::CollisionImminent { time_to_collision_ms } => {
64                format!("Collision imminent in {time_to_collision_ms:.1}ms")
65            }
66            EmergencyCondition::SensorDegraded { sensor, quality } => {
67                let quality_pct = quality * 100.0;
68                format!("Sensor {sensor} degraded: quality={quality_pct:.1}%")
69            }
70            EmergencyCondition::AuditChainBroken => "Audit chain integrity failure".to_string(),
71            EmergencyCondition::DecisionTimeout { max_ms } => {
72                format!("Decision timeout: exceeded {max_ms:.1}ms limit")
73            }
74            EmergencyCondition::ConsecutiveLowConfidence { count, threshold } => {
75                let threshold_pct = threshold * 100.0;
76                format!("{count} consecutive decisions below {threshold_pct:.1}% confidence")
77            }
78            EmergencyCondition::InvalidOutput => "NaN or Inf detected in model output".to_string(),
79        }
80    }
81}