feat: Add wifi-Mat disaster detection enhancements
Implement 6 optional enhancements for the wifi-Mat module: 1. Hardware Integration (csi_receiver.rs + hardware_adapter.rs) - ESP32 CSI support via serial/UDP - Intel 5300 BFEE file parsing - Atheros CSI Tool integration - Live UDP packet streaming - PCAP replay capability 2. CLI Commands (wifi-densepose-cli/src/mat.rs) - `wifi-mat scan` - Run disaster detection scan - `wifi-mat status` - Check event status - `wifi-mat zones` - Manage scan zones - `wifi-mat survivors` - List detected survivors - `wifi-mat alerts` - View and acknowledge alerts - `wifi-mat export` - Export data in various formats 3. REST API (wifi-densepose-mat/src/api/) - Full CRUD for disaster events - Zone management endpoints - Survivor and alert queries - WebSocket streaming for real-time updates - Comprehensive DTOs and error handling 4. WASM Build (wifi-densepose-wasm/src/mat.rs) - Browser-based disaster dashboard - Real-time survivor tracking - Zone visualization - Alert management - JavaScript API bindings 5. Detection Benchmarks (benches/detection_bench.rs) - Single survivor detection - Multi-survivor detection - Full pipeline benchmarks - Signal processing benchmarks - Hardware adapter benchmarks 6. ML Models for Debris Penetration (ml/) - DebrisModel for material analysis - VitalSignsClassifier for triage - FFT-based feature extraction - Bandpass filtering - Monte Carlo dropout for uncertainty All 134 unit tests pass. Compilation verified for: - wifi-densepose-mat - wifi-densepose-cli - wifi-densepose-wasm (with mat feature)
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
//! Detection pipeline combining all vital signs detectors.
|
||||
//!
|
||||
//! This module provides both traditional signal-processing-based detection
|
||||
//! and optional ML-enhanced detection for improved accuracy.
|
||||
|
||||
use crate::domain::{ScanZone, VitalSignsReading, ConfidenceScore};
|
||||
use crate::ml::{MlDetectionConfig, MlDetectionPipeline, MlDetectionResult};
|
||||
use crate::{DisasterConfig, MatError};
|
||||
use super::{
|
||||
BreathingDetector, BreathingDetectorConfig,
|
||||
@@ -23,6 +27,10 @@ pub struct DetectionConfig {
|
||||
pub enable_heartbeat: bool,
|
||||
/// Minimum overall confidence to report detection
|
||||
pub min_confidence: f64,
|
||||
/// Enable ML-enhanced detection
|
||||
pub enable_ml: bool,
|
||||
/// ML detection configuration (if enabled)
|
||||
pub ml_config: Option<MlDetectionConfig>,
|
||||
}
|
||||
|
||||
impl Default for DetectionConfig {
|
||||
@@ -34,6 +42,8 @@ impl Default for DetectionConfig {
|
||||
sample_rate: 1000.0,
|
||||
enable_heartbeat: false,
|
||||
min_confidence: 0.3,
|
||||
enable_ml: false,
|
||||
ml_config: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +63,20 @@ impl DetectionConfig {
|
||||
|
||||
detection_config
|
||||
}
|
||||
|
||||
/// Enable ML-enhanced detection with the given configuration
|
||||
pub fn with_ml(mut self, ml_config: MlDetectionConfig) -> Self {
|
||||
self.enable_ml = true;
|
||||
self.ml_config = Some(ml_config);
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable ML-enhanced detection with default configuration
|
||||
pub fn with_default_ml(mut self) -> Self {
|
||||
self.enable_ml = true;
|
||||
self.ml_config = Some(MlDetectionConfig::default());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for vital signs detection
|
||||
@@ -123,20 +147,42 @@ pub struct DetectionPipeline {
|
||||
heartbeat_detector: HeartbeatDetector,
|
||||
movement_classifier: MovementClassifier,
|
||||
data_buffer: parking_lot::RwLock<CsiDataBuffer>,
|
||||
/// Optional ML detection pipeline
|
||||
ml_pipeline: Option<MlDetectionPipeline>,
|
||||
}
|
||||
|
||||
impl DetectionPipeline {
|
||||
/// Create a new detection pipeline
|
||||
pub fn new(config: DetectionConfig) -> Self {
|
||||
let ml_pipeline = if config.enable_ml {
|
||||
config.ml_config.clone().map(MlDetectionPipeline::new)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Self {
|
||||
breathing_detector: BreathingDetector::new(config.breathing.clone()),
|
||||
heartbeat_detector: HeartbeatDetector::new(config.heartbeat.clone()),
|
||||
movement_classifier: MovementClassifier::new(config.movement.clone()),
|
||||
data_buffer: parking_lot::RwLock::new(CsiDataBuffer::new(config.sample_rate)),
|
||||
ml_pipeline,
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize ML models asynchronously (if enabled)
|
||||
pub async fn initialize_ml(&mut self) -> Result<(), MatError> {
|
||||
if let Some(ref mut ml) = self.ml_pipeline {
|
||||
ml.initialize().await.map_err(MatError::from)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if ML pipeline is ready
|
||||
pub fn ml_ready(&self) -> bool {
|
||||
self.ml_pipeline.as_ref().map_or(true, |ml| ml.is_ready())
|
||||
}
|
||||
|
||||
/// Process a scan zone and return detected vital signs
|
||||
pub async fn process_zone(&self, zone: &ScanZone) -> Result<Option<VitalSignsReading>, MatError> {
|
||||
// In a real implementation, this would:
|
||||
@@ -152,17 +198,66 @@ impl DetectionPipeline {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// Detect vital signs
|
||||
// Detect vital signs using traditional pipeline
|
||||
let reading = self.detect_from_buffer(&buffer, zone)?;
|
||||
|
||||
// If ML is enabled and ready, enhance with ML predictions
|
||||
let enhanced_reading = if self.config.enable_ml && self.ml_ready() {
|
||||
self.enhance_with_ml(reading, &buffer).await?
|
||||
} else {
|
||||
reading
|
||||
};
|
||||
|
||||
// Check minimum confidence
|
||||
if let Some(ref r) = reading {
|
||||
if let Some(ref r) = enhanced_reading {
|
||||
if r.confidence.value() < self.config.min_confidence {
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(reading)
|
||||
Ok(enhanced_reading)
|
||||
}
|
||||
|
||||
/// Enhance detection results with ML predictions
|
||||
async fn enhance_with_ml(
|
||||
&self,
|
||||
traditional_reading: Option<VitalSignsReading>,
|
||||
buffer: &CsiDataBuffer,
|
||||
) -> Result<Option<VitalSignsReading>, MatError> {
|
||||
let ml_pipeline = match &self.ml_pipeline {
|
||||
Some(ml) => ml,
|
||||
None => return Ok(traditional_reading),
|
||||
};
|
||||
|
||||
// Get ML predictions
|
||||
let ml_result = ml_pipeline.process(buffer).await.map_err(MatError::from)?;
|
||||
|
||||
// If we have ML vital classification, use it to enhance or replace traditional
|
||||
if let Some(ref ml_vital) = ml_result.vital_classification {
|
||||
if let Some(vital_reading) = ml_vital.to_vital_signs_reading() {
|
||||
// If ML result has higher confidence, prefer it
|
||||
if let Some(ref traditional) = traditional_reading {
|
||||
if ml_result.overall_confidence() > traditional.confidence.value() as f32 {
|
||||
return Ok(Some(vital_reading));
|
||||
}
|
||||
} else {
|
||||
// No traditional reading, use ML result
|
||||
return Ok(Some(vital_reading));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(traditional_reading)
|
||||
}
|
||||
|
||||
/// Get the latest ML detection results (if ML is enabled)
|
||||
pub async fn get_ml_results(&self) -> Option<MlDetectionResult> {
|
||||
let buffer = self.data_buffer.read();
|
||||
if let Some(ref ml) = self.ml_pipeline {
|
||||
ml.process(&buffer).await.ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Add CSI data to the processing buffer
|
||||
@@ -236,8 +331,23 @@ impl DetectionPipeline {
|
||||
self.breathing_detector = BreathingDetector::new(config.breathing.clone());
|
||||
self.heartbeat_detector = HeartbeatDetector::new(config.heartbeat.clone());
|
||||
self.movement_classifier = MovementClassifier::new(config.movement.clone());
|
||||
|
||||
// Update ML pipeline if configuration changed
|
||||
if config.enable_ml != self.config.enable_ml || config.ml_config != self.config.ml_config {
|
||||
self.ml_pipeline = if config.enable_ml {
|
||||
config.ml_config.clone().map(MlDetectionPipeline::new)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
/// Get the ML pipeline (if enabled)
|
||||
pub fn ml_pipeline(&self) -> Option<&MlDetectionPipeline> {
|
||||
self.ml_pipeline.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl VitalSignsDetector for DetectionPipeline {
|
||||
|
||||
Reference in New Issue
Block a user