feat: Complete Rust port of WiFi-DensePose with modular crates

Major changes:
- Organized Python v1 implementation into v1/ subdirectory
- Created Rust workspace with 9 modular crates:
  - wifi-densepose-core: Core types, traits, errors
  - wifi-densepose-signal: CSI processing, phase sanitization, FFT
  - wifi-densepose-nn: Neural network inference (ONNX/Candle/tch)
  - wifi-densepose-api: Axum-based REST/WebSocket API
  - wifi-densepose-db: SQLx database layer
  - wifi-densepose-config: Configuration management
  - wifi-densepose-hardware: Hardware abstraction
  - wifi-densepose-wasm: WebAssembly bindings
  - wifi-densepose-cli: Command-line interface

Documentation:
- ADR-001: Workspace structure
- ADR-002: Signal processing library selection
- ADR-003: Neural network inference strategy
- DDD domain model with bounded contexts

Testing:
- 69 tests passing across all crates
- Signal processing: 45 tests
- Neural networks: 21 tests
- Core: 3 doc tests

Performance targets:
- 10x faster CSI processing (~0.5ms vs ~5ms)
- 5x lower memory usage (~100MB vs ~500MB)
- WASM support for browser deployment
This commit is contained in:
Claude
2026-01-13 03:11:16 +00:00
parent 5101504b72
commit 6ed69a3d48
427 changed files with 90993 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
# WiFi-DensePose Domain-Driven Design Documentation
## Overview
This documentation describes the Domain-Driven Design (DDD) architecture for the WiFi-DensePose Rust port. The system uses WiFi Channel State Information (CSI) to perform non-invasive human pose estimation, translating radio frequency signals into body positioning data.
## Strategic Design
### Core Domain
The **Pose Estimation Domain** represents the core business logic that provides unique value. This domain translates WiFi CSI signals into DensePose-compatible human body representations. The algorithms for modality translation (RF to visual features) and pose inference constitute the competitive advantage of the system.
### Supporting Domains
1. **Signal Domain** - CSI acquisition and preprocessing
2. **Streaming Domain** - Real-time data delivery infrastructure
3. **Storage Domain** - Persistence and retrieval mechanisms
4. **Hardware Domain** - Device abstraction and management
### Generic Domains
- Authentication and authorization
- Logging and monitoring
- Configuration management
## Tactical Design Patterns
### Aggregates
Each bounded context contains aggregates that enforce invariants and maintain consistency:
- **CsiFrame** - Raw signal data with validation rules
- **ProcessedSignal** - Feature-extracted signal ready for inference
- **PoseEstimate** - Inference results with confidence scoring
- **Session** - Client connection lifecycle management
- **Device** - Hardware abstraction with state machine
### Domain Events
Events flow between bounded contexts through an event-driven architecture:
```
CsiFrameReceived -> SignalProcessed -> PoseEstimated -> (MotionDetected | FallDetected)
```
### Repositories
Each aggregate root has a corresponding repository for persistence:
- `CsiFrameRepository`
- `SessionRepository`
- `DeviceRepository`
- `PoseEstimateRepository`
### Domain Services
Cross-aggregate operations are handled by domain services:
- `PoseEstimationService` - Orchestrates CSI-to-pose pipeline
- `CalibrationService` - Hardware calibration workflows
- `AlertService` - Motion and fall detection alerts
## Context Map
```
+------------------+
| Pose Domain |
| (Core Domain) |
+--------+---------+
|
+--------------+---------------+
| | |
+---------v----+ +------v------+ +-----v-------+
| Signal Domain| | Streaming | | Storage |
| (Upstream) | | Domain | | Domain |
+---------+----+ +------+------+ +------+------+
| | |
+--------------+----------------+
|
+--------v--------+
| Hardware Domain |
| (Foundation) |
+-----------------+
```
### Relationships
| Upstream | Downstream | Relationship |
|----------|------------|--------------|
| Hardware | Signal | Conformist |
| Signal | Pose | Customer-Supplier |
| Pose | Streaming | Published Language |
| Pose | Storage | Shared Kernel |
## Architecture Principles
### 1. Hexagonal Architecture
Each bounded context follows hexagonal (ports and adapters) architecture:
```
+--------------------+
| Application |
| Services |
+---------+----------+
|
+---------------+---------------+
| |
+---------v---------+ +---------v---------+
| Domain Layer | | Domain Layer |
| (Entities, VOs, | | (Aggregates, |
| Domain Events) | | Repositories) |
+---------+---------+ +---------+---------+
| |
+---------v---------+ +---------v---------+
| Infrastructure | | Infrastructure |
| (Adapters: DB, | | (Adapters: API, |
| Hardware, MQ) | | WebSocket) |
+-------------------+ +-------------------+
```
### 2. CQRS (Command Query Responsibility Segregation)
The system separates read and write operations:
- **Commands**: `ProcessCsiFrame`, `CreateSession`, `UpdateDeviceConfig`
- **Queries**: `GetCurrentPose`, `GetSessionHistory`, `GetDeviceStatus`
### 3. Event Sourcing (Optional)
For audit and replay capabilities, CSI processing events can be stored as an event log:
```rust
pub enum DomainEvent {
CsiFrameReceived(CsiFrameReceivedEvent),
SignalProcessed(SignalProcessedEvent),
PoseEstimated(PoseEstimatedEvent),
MotionDetected(MotionDetectedEvent),
FallDetected(FallDetectedEvent),
}
```
## Rust Implementation Guidelines
### Module Structure
```
wifi-densepose-rs/
crates/
wifi-densepose-core/ # Shared kernel
src/
domain/
entities/
value_objects/
events/
wifi-densepose-signal/ # Signal bounded context
src/
domain/
application/
infrastructure/
wifi-densepose-nn/ # Pose bounded context
src/
domain/
application/
infrastructure/
wifi-densepose-api/ # Streaming bounded context
src/
domain/
application/
infrastructure/
wifi-densepose-db/ # Storage bounded context
src/
domain/
application/
infrastructure/
wifi-densepose-hardware/ # Hardware bounded context
src/
domain/
application/
infrastructure/
```
### Type-Driven Design
Leverage Rust's type system to encode domain invariants:
```rust
// Newtype pattern for domain identifiers
pub struct DeviceId(Uuid);
pub struct SessionId(Uuid);
pub struct FrameId(u64);
// State machines via enums
pub enum DeviceState {
Disconnected,
Connecting(ConnectionAttempt),
Connected(ActiveConnection),
Streaming(StreamingSession),
Error(DeviceError),
}
// Validated value objects
pub struct Frequency {
hz: f64, // Invariant: always > 0
}
impl Frequency {
pub fn new(hz: f64) -> Result<Self, DomainError> {
if hz <= 0.0 {
return Err(DomainError::InvalidFrequency);
}
Ok(Self { hz })
}
}
```
### Error Handling
Domain errors are distinct from infrastructure errors:
```rust
#[derive(Debug, thiserror::Error)]
pub enum SignalDomainError {
#[error("Invalid CSI frame: {0}")]
InvalidFrame(String),
#[error("Signal quality below threshold: {snr} dB")]
LowSignalQuality { snr: f64 },
#[error("Calibration required for device {device_id}")]
CalibrationRequired { device_id: DeviceId },
}
```
## Testing Strategy
### Unit Tests
- Value object invariants
- Aggregate business rules
- Domain service logic
### Integration Tests
- Repository implementations
- Inter-context communication
- Event publishing/subscription
### Property-Based Tests
- Signal processing algorithms
- Pose estimation accuracy
- Event ordering guarantees
## References
- Evans, Eric. *Domain-Driven Design: Tackling Complexity in the Heart of Software*. Addison-Wesley, 2003.
- Vernon, Vaughn. *Implementing Domain-Driven Design*. Addison-Wesley, 2013.
- Millett, Scott and Tune, Nick. *Patterns, Principles, and Practices of Domain-Driven Design*. Wrox, 2015.
## Document Index
1. [Bounded Contexts](./bounded-contexts.md) - Detailed context definitions
2. [Aggregates](./aggregates.md) - Aggregate root specifications
3. [Domain Events](./domain-events.md) - Event catalog and schemas
4. [Ubiquitous Language](./ubiquitous-language.md) - Domain terminology glossary

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,765 @@
# Bounded Contexts
This document defines the five bounded contexts that compose the WiFi-DensePose system. Each context represents a distinct subdomain with its own ubiquitous language, models, and boundaries.
---
## 1. Signal Domain (CSI Processing)
### Purpose
The Signal Domain is responsible for acquiring, validating, preprocessing, and extracting features from Channel State Information (CSI) data. It transforms raw RF measurements into structured signal features suitable for pose inference.
### Ubiquitous Language (Context-Specific)
| Term | Definition |
|------|------------|
| CSI Frame | A single capture of channel state information across all subcarriers and antennas |
| Subcarrier | Individual frequency bin in OFDM modulation carrying amplitude and phase data |
| Amplitude | Signal strength component of CSI measurement |
| Phase | Signal timing component of CSI measurement |
| Doppler Shift | Frequency change caused by moving objects |
| Noise Floor | Background electromagnetic interference level |
| SNR | Signal-to-Noise Ratio, quality metric for CSI data |
### Core Responsibilities
1. **CSI Acquisition** - Interface with hardware to receive raw CSI bytes
2. **Frame Parsing** - Decode vendor-specific CSI formats (ESP32, Atheros, Intel)
3. **Validation** - Verify frame integrity, antenna counts, subcarrier dimensions
4. **Preprocessing** - Noise removal, windowing, normalization
5. **Feature Extraction** - Compute amplitude statistics, phase differences, correlations, PSD
### Aggregate: CsiFrame
```rust
pub struct CsiFrame {
id: FrameId,
device_id: DeviceId,
session_id: Option<SessionId>,
timestamp: Timestamp,
sequence_number: u64,
// Raw measurements
amplitude: Matrix<f32>, // [antennas x subcarriers]
phase: Matrix<f32>, // [antennas x subcarriers]
// Signal characteristics
frequency: Frequency, // Center frequency (Hz)
bandwidth: Bandwidth, // Channel bandwidth (Hz)
num_subcarriers: u16,
num_antennas: u8,
// Quality metrics
snr: SignalToNoise,
rssi: Option<Rssi>,
noise_floor: Option<NoiseFloor>,
// Processing state
status: ProcessingStatus,
metadata: FrameMetadata,
}
```
### Value Objects
```rust
// Validated frequency with invariants
pub struct Frequency(f64); // Hz, must be > 0
// Bandwidth with common WiFi values
pub enum Bandwidth {
Bw20MHz,
Bw40MHz,
Bw80MHz,
Bw160MHz,
}
// SNR with reasonable bounds
pub struct SignalToNoise(f64); // dB, typically -50 to +50
// Processing pipeline status
pub enum ProcessingStatus {
Pending,
Preprocessing,
FeatureExtraction,
Completed,
Failed(ProcessingError),
}
```
### Domain Services
```rust
pub trait CsiPreprocessor {
fn remove_noise(&self, frame: &CsiFrame, threshold: NoiseThreshold) -> Result<CsiFrame>;
fn apply_window(&self, frame: &CsiFrame, window: WindowFunction) -> Result<CsiFrame>;
fn normalize_amplitude(&self, frame: &CsiFrame) -> Result<CsiFrame>;
fn sanitize_phase(&self, frame: &CsiFrame) -> Result<CsiFrame>;
}
pub trait FeatureExtractor {
fn extract_amplitude_features(&self, frame: &CsiFrame) -> AmplitudeFeatures;
fn extract_phase_features(&self, frame: &CsiFrame) -> PhaseFeatures;
fn extract_correlation_features(&self, frame: &CsiFrame) -> CorrelationFeatures;
fn extract_doppler_features(&self, frames: &[CsiFrame]) -> DopplerFeatures;
fn compute_power_spectral_density(&self, frame: &CsiFrame) -> PowerSpectralDensity;
}
```
### Outbound Events
- `CsiFrameReceived` - Raw frame acquired from hardware
- `CsiFrameValidated` - Frame passed integrity checks
- `SignalProcessed` - Features extracted and ready for inference
### Integration Points
| Context | Direction | Mechanism |
|---------|-----------|-----------|
| Hardware Domain | Inbound | Raw bytes via async channel |
| Pose Domain | Outbound | ProcessedSignal via event bus |
| Storage Domain | Outbound | Persistence via repository |
---
## 2. Pose Domain (DensePose Inference)
### Purpose
The Pose Domain is the core of the system. It translates processed CSI features into human body pose estimates using neural network inference. This domain encapsulates the modality translation algorithms and DensePose model integration.
### Ubiquitous Language (Context-Specific)
| Term | Definition |
|------|------------|
| Modality Translation | Converting RF signal features to visual-like representations |
| DensePose | Dense human pose estimation mapping pixels to body surface |
| Body Part | Anatomical region (head, torso, limbs) identified in segmentation |
| UV Coordinates | 2D surface coordinates on body mesh |
| Keypoint | Named anatomical landmark (nose, shoulder, knee, etc.) |
| Confidence Score | Probability that a detection is correct |
| Bounding Box | Rectangular region containing a detected person |
### Core Responsibilities
1. **Modality Translation** - Transform CSI features to visual feature space
2. **Person Detection** - Identify presence and count of humans
3. **Body Segmentation** - Classify pixels/regions into body parts
4. **UV Regression** - Predict continuous surface coordinates
5. **Keypoint Localization** - Detect anatomical landmarks
6. **Activity Classification** - Infer high-level activities (standing, sitting, walking)
### Aggregate: PoseEstimate
```rust
pub struct PoseEstimate {
id: EstimateId,
session_id: SessionId,
frame_id: FrameId,
timestamp: Timestamp,
// Detection results
persons: Vec<PersonDetection>,
person_count: u8,
// Processing metadata
processing_time: Duration,
model_version: ModelVersion,
algorithm: InferenceAlgorithm,
// Quality assessment
overall_confidence: Confidence,
is_valid: bool,
}
pub struct PersonDetection {
person_id: PersonId,
bounding_box: BoundingBox,
keypoints: Vec<Keypoint>,
body_parts: BodyPartSegmentation,
uv_coordinates: UvMap,
confidence: Confidence,
activity: Option<Activity>,
}
pub struct Keypoint {
name: KeypointName,
position: Position2D,
confidence: Confidence,
}
pub enum KeypointName {
Nose,
LeftEye,
RightEye,
LeftEar,
RightEar,
LeftShoulder,
RightShoulder,
LeftElbow,
RightElbow,
LeftWrist,
RightWrist,
LeftHip,
RightHip,
LeftKnee,
RightKnee,
LeftAnkle,
RightAnkle,
}
```
### Value Objects
```rust
// Confidence score bounded [0, 1]
pub struct Confidence(f32);
impl Confidence {
pub fn new(value: f32) -> Result<Self, DomainError> {
if value < 0.0 || value > 1.0 {
return Err(DomainError::InvalidConfidence);
}
Ok(Self(value))
}
pub fn is_high(&self) -> bool {
self.0 >= 0.8
}
}
// 2D position in normalized coordinates [0, 1]
pub struct Position2D {
x: NormalizedCoordinate,
y: NormalizedCoordinate,
}
// Activity classification
pub enum Activity {
Standing,
Sitting,
Walking,
Lying,
Falling,
Unknown,
}
```
### Domain Services
```rust
pub trait ModalityTranslator {
fn translate(&self, signal: &ProcessedSignal) -> Result<VisualFeatures>;
}
pub trait PoseInferenceEngine {
fn detect_persons(&self, features: &VisualFeatures) -> Vec<PersonDetection>;
fn segment_body_parts(&self, detection: &PersonDetection) -> BodyPartSegmentation;
fn regress_uv_coordinates(&self, detection: &PersonDetection) -> UvMap;
fn classify_activity(&self, detection: &PersonDetection) -> Activity;
}
pub trait HumanPresenceDetector {
fn detect_presence(&self, signal: &ProcessedSignal) -> HumanPresenceResult;
fn estimate_count(&self, signal: &ProcessedSignal) -> PersonCount;
}
```
### Outbound Events
- `PoseEstimated` - Pose inference completed successfully
- `PersonDetected` - New person entered detection zone
- `PersonLost` - Person left detection zone
- `ActivityChanged` - Person's activity classification changed
- `MotionDetected` - Significant motion observed
- `FallDetected` - Potential fall event identified
### Integration Points
| Context | Direction | Mechanism |
|---------|-----------|-----------|
| Signal Domain | Inbound | ProcessedSignal events |
| Streaming Domain | Outbound | PoseEstimate broadcasts |
| Storage Domain | Outbound | Persistence via repository |
---
## 3. Streaming Domain (WebSocket, Real-time)
### Purpose
The Streaming Domain manages real-time data delivery to clients via WebSocket connections. It handles connection lifecycle, message routing, filtering by zones/topics, and maintains streaming quality of service.
### Ubiquitous Language (Context-Specific)
| Term | Definition |
|------|------------|
| Connection | Active WebSocket session with a client |
| Stream Type | Category of data stream (pose, csi, alerts, status) |
| Zone | Logical or physical area for filtering pose data |
| Subscription | Client's expressed interest in specific stream/zone |
| Broadcast | Message sent to all matching subscribers |
| Heartbeat | Periodic ping to verify connection liveness |
| Backpressure | Flow control when client cannot keep up |
### Core Responsibilities
1. **Connection Management** - Accept, track, and close WebSocket connections
2. **Subscription Handling** - Manage client subscriptions to streams and zones
3. **Message Routing** - Deliver events to matching subscribers
4. **Quality of Service** - Handle backpressure, buffering, reconnection
5. **Metrics Collection** - Track latency, throughput, error rates
### Aggregate: Session
```rust
pub struct Session {
id: SessionId,
client_id: ClientId,
// Connection details
connected_at: Timestamp,
last_activity: Timestamp,
remote_addr: Option<IpAddr>,
user_agent: Option<String>,
// Subscription state
stream_type: StreamType,
zone_subscriptions: Vec<ZoneId>,
filters: SubscriptionFilters,
// Session state
status: SessionStatus,
message_count: u64,
// Quality metrics
latency_stats: LatencyStats,
error_count: u32,
}
pub enum StreamType {
Pose,
Csi,
Alerts,
SystemStatus,
All,
}
pub enum SessionStatus {
Active,
Paused,
Reconnecting,
Completed,
Failed(SessionError),
Cancelled,
}
pub struct SubscriptionFilters {
min_confidence: Option<Confidence>,
max_persons: Option<u8>,
include_keypoints: bool,
include_segmentation: bool,
throttle_ms: Option<u32>,
}
```
### Value Objects
```rust
// Zone identifier with validation
pub struct ZoneId(String);
impl ZoneId {
pub fn new(id: impl Into<String>) -> Result<Self, DomainError> {
let id = id.into();
if id.is_empty() || id.len() > 64 {
return Err(DomainError::InvalidZoneId);
}
Ok(Self(id))
}
}
// Latency tracking
pub struct LatencyStats {
min_ms: f64,
max_ms: f64,
avg_ms: f64,
p99_ms: f64,
samples: u64,
}
```
### Domain Services
```rust
pub trait ConnectionManager {
async fn connect(&self, socket: WebSocket, config: ConnectionConfig) -> Result<SessionId>;
async fn disconnect(&self, session_id: &SessionId) -> Result<()>;
async fn update_subscription(&self, session_id: &SessionId, filters: SubscriptionFilters) -> Result<()>;
fn get_active_sessions(&self) -> Vec<&Session>;
}
pub trait MessageRouter {
async fn broadcast(&self, message: StreamMessage, filter: BroadcastFilter) -> BroadcastResult;
async fn send_to_session(&self, session_id: &SessionId, message: StreamMessage) -> Result<()>;
async fn send_to_zone(&self, zone_id: &ZoneId, message: StreamMessage) -> BroadcastResult;
}
pub trait StreamBuffer {
fn buffer_message(&mut self, message: StreamMessage);
fn get_recent(&self, count: usize) -> Vec<&StreamMessage>;
fn clear(&mut self);
}
```
### Outbound Events
- `SessionStarted` - Client connected and subscribed
- `SessionEnded` - Client disconnected
- `SubscriptionUpdated` - Client changed filter preferences
- `MessageDelivered` - Confirmation of successful delivery
- `DeliveryFailed` - Message could not be delivered
### Integration Points
| Context | Direction | Mechanism |
|---------|-----------|-----------|
| Pose Domain | Inbound | PoseEstimate events |
| Signal Domain | Inbound | ProcessedSignal events (if CSI streaming enabled) |
| API Layer | Bidirectional | WebSocket upgrade, REST for management |
---
## 4. Storage Domain (Persistence)
### Purpose
The Storage Domain handles all persistence operations including saving CSI frames, pose estimates, session records, and device configurations. It provides repositories for aggregate roots and supports both real-time writes and historical queries.
### Ubiquitous Language (Context-Specific)
| Term | Definition |
|------|------------|
| Repository | Interface for aggregate persistence operations |
| Entity | Persistent domain object with identity |
| Query | Read operation against stored data |
| Migration | Schema evolution script |
| Transaction | Atomic unit of work |
| Aggregate Store | Persistence layer for aggregate roots |
### Core Responsibilities
1. **CRUD Operations** - Create, read, update, delete for all aggregates
2. **Query Support** - Time-range queries, filtering, aggregation
3. **Transaction Management** - Ensure consistency across operations
4. **Schema Evolution** - Handle database migrations
5. **Performance Optimization** - Indexing, partitioning, caching
### Repository Interfaces
```rust
#[async_trait]
pub trait CsiFrameRepository {
async fn save(&self, frame: &CsiFrame) -> Result<FrameId>;
async fn save_batch(&self, frames: &[CsiFrame]) -> Result<Vec<FrameId>>;
async fn find_by_id(&self, id: &FrameId) -> Result<Option<CsiFrame>>;
async fn find_by_session(&self, session_id: &SessionId, limit: usize) -> Result<Vec<CsiFrame>>;
async fn find_by_time_range(&self, start: Timestamp, end: Timestamp) -> Result<Vec<CsiFrame>>;
async fn delete_older_than(&self, cutoff: Timestamp) -> Result<u64>;
}
#[async_trait]
pub trait PoseEstimateRepository {
async fn save(&self, estimate: &PoseEstimate) -> Result<EstimateId>;
async fn find_by_id(&self, id: &EstimateId) -> Result<Option<PoseEstimate>>;
async fn find_by_session(&self, session_id: &SessionId) -> Result<Vec<PoseEstimate>>;
async fn find_by_zone_and_time(&self, zone_id: &ZoneId, start: Timestamp, end: Timestamp) -> Result<Vec<PoseEstimate>>;
async fn get_statistics(&self, start: Timestamp, end: Timestamp) -> Result<PoseStatistics>;
}
#[async_trait]
pub trait SessionRepository {
async fn save(&self, session: &Session) -> Result<SessionId>;
async fn update(&self, session: &Session) -> Result<()>;
async fn find_by_id(&self, id: &SessionId) -> Result<Option<Session>>;
async fn find_active(&self) -> Result<Vec<Session>>;
async fn find_by_device(&self, device_id: &DeviceId) -> Result<Vec<Session>>;
async fn mark_completed(&self, id: &SessionId, end_time: Timestamp) -> Result<()>;
}
#[async_trait]
pub trait DeviceRepository {
async fn save(&self, device: &Device) -> Result<DeviceId>;
async fn update(&self, device: &Device) -> Result<()>;
async fn find_by_id(&self, id: &DeviceId) -> Result<Option<Device>>;
async fn find_by_mac(&self, mac: &MacAddress) -> Result<Option<Device>>;
async fn find_all(&self) -> Result<Vec<Device>>;
async fn find_by_status(&self, status: DeviceStatus) -> Result<Vec<Device>>;
}
```
### Query Objects
```rust
pub struct TimeRangeQuery {
start: Timestamp,
end: Timestamp,
zone_ids: Option<Vec<ZoneId>>,
device_ids: Option<Vec<DeviceId>>,
limit: Option<usize>,
offset: Option<usize>,
}
pub struct PoseStatistics {
total_detections: u64,
successful_detections: u64,
failed_detections: u64,
average_confidence: f32,
average_processing_time_ms: f32,
unique_persons: u32,
activity_distribution: HashMap<Activity, f32>,
}
pub struct AggregatedPoseData {
timestamp: Timestamp,
interval_seconds: u32,
total_persons: u32,
zones: HashMap<ZoneId, ZoneOccupancy>,
}
```
### Integration Points
| Context | Direction | Mechanism |
|---------|-----------|-----------|
| All Domains | Inbound | Repository trait implementations |
| Infrastructure | Outbound | SQLx, Redis adapters |
---
## 5. Hardware Domain (Device Management)
### Purpose
The Hardware Domain abstracts physical WiFi devices (routers, ESP32, Intel NICs) and manages their lifecycle. It handles device discovery, connection establishment, configuration, and health monitoring.
### Ubiquitous Language (Context-Specific)
| Term | Definition |
|------|------------|
| Device | Physical WiFi hardware capable of CSI extraction |
| Firmware | Software running on the device |
| MAC Address | Unique hardware identifier |
| Calibration | Process of tuning device for accurate CSI |
| Health Check | Periodic verification of device status |
| Driver | Software interface to hardware |
### Core Responsibilities
1. **Device Discovery** - Scan network for compatible devices
2. **Connection Management** - Establish and maintain hardware connections
3. **Configuration** - Apply and persist device settings
4. **Health Monitoring** - Track device status and performance
5. **Firmware Management** - Version tracking, update coordination
### Aggregate: Device
```rust
pub struct Device {
id: DeviceId,
// Identification
name: DeviceName,
device_type: DeviceType,
mac_address: MacAddress,
ip_address: Option<IpAddress>,
// Hardware details
firmware_version: Option<FirmwareVersion>,
hardware_version: Option<HardwareVersion>,
capabilities: DeviceCapabilities,
// Location
location: Option<Location>,
zone_id: Option<ZoneId>,
// State
status: DeviceStatus,
last_seen: Option<Timestamp>,
error_count: u32,
// Configuration
config: DeviceConfig,
calibration: Option<CalibrationData>,
}
pub enum DeviceType {
Esp32,
AtheriosRouter,
IntelNic,
Nexmon,
Custom(String),
}
pub enum DeviceStatus {
Disconnected,
Connecting,
Connected,
Streaming,
Calibrating,
Maintenance,
Error(DeviceError),
}
pub struct DeviceCapabilities {
max_subcarriers: u16,
max_antennas: u8,
supported_bandwidths: Vec<Bandwidth>,
supported_frequencies: Vec<Frequency>,
csi_rate_hz: u32,
}
pub struct DeviceConfig {
sampling_rate: u32,
subcarriers: u16,
antennas: u8,
bandwidth: Bandwidth,
channel: WifiChannel,
gain: Option<f32>,
custom_params: HashMap<String, serde_json::Value>,
}
```
### Value Objects
```rust
// MAC address with validation
pub struct MacAddress([u8; 6]);
impl MacAddress {
pub fn parse(s: &str) -> Result<Self, DomainError> {
// Parse "AA:BB:CC:DD:EE:FF" format
let parts: Vec<&str> = s.split(':').collect();
if parts.len() != 6 {
return Err(DomainError::InvalidMacAddress);
}
let mut bytes = [0u8; 6];
for (i, part) in parts.iter().enumerate() {
bytes[i] = u8::from_str_radix(part, 16)
.map_err(|_| DomainError::InvalidMacAddress)?;
}
Ok(Self(bytes))
}
}
// Physical location
pub struct Location {
name: String,
room_id: Option<String>,
coordinates: Option<Coordinates3D>,
}
pub struct Coordinates3D {
x: f64,
y: f64,
z: f64,
}
```
### Domain Services
```rust
pub trait DeviceDiscovery {
async fn scan(&self, timeout: Duration) -> Vec<DiscoveredDevice>;
async fn identify(&self, address: &IpAddress) -> Option<DeviceType>;
}
pub trait DeviceConnector {
async fn connect(&self, device: &Device) -> Result<DeviceConnection>;
async fn disconnect(&self, device_id: &DeviceId) -> Result<()>;
async fn reconnect(&self, device_id: &DeviceId) -> Result<DeviceConnection>;
}
pub trait DeviceConfigurator {
async fn apply_config(&self, device_id: &DeviceId, config: &DeviceConfig) -> Result<()>;
async fn read_config(&self, device_id: &DeviceId) -> Result<DeviceConfig>;
async fn reset_to_defaults(&self, device_id: &DeviceId) -> Result<()>;
}
pub trait CalibrationService {
async fn start_calibration(&self, device_id: &DeviceId) -> Result<CalibrationSession>;
async fn get_calibration_status(&self, session_id: &CalibrationSessionId) -> CalibrationStatus;
async fn apply_calibration(&self, device_id: &DeviceId, data: &CalibrationData) -> Result<()>;
}
pub trait HealthMonitor {
async fn check_health(&self, device_id: &DeviceId) -> HealthStatus;
async fn get_metrics(&self, device_id: &DeviceId) -> DeviceMetrics;
}
```
### Outbound Events
- `DeviceDiscovered` - New device found on network
- `DeviceConnected` - Connection established
- `DeviceDisconnected` - Connection lost
- `DeviceConfigured` - Configuration applied
- `DeviceCalibrated` - Calibration completed
- `DeviceHealthChanged` - Status change (healthy/unhealthy)
- `DeviceError` - Error condition detected
### Integration Points
| Context | Direction | Mechanism |
|---------|-----------|-----------|
| Signal Domain | Outbound | Raw CSI bytes via channel |
| Storage Domain | Outbound | Device persistence |
| API Layer | Bidirectional | REST endpoints for management |
---
## Context Integration Patterns
### Anti-Corruption Layer
When integrating with vendor-specific CSI formats, the Signal Domain uses an Anti-Corruption Layer to translate external formats:
```rust
pub trait CsiParser: Send + Sync {
fn parse(&self, raw: &[u8]) -> Result<CsiFrame>;
fn device_type(&self) -> DeviceType;
}
pub struct Esp32Parser;
pub struct AtheriosParser;
pub struct IntelParser;
pub struct ParserRegistry {
parsers: HashMap<DeviceType, Box<dyn CsiParser>>,
}
```
### Published Language
The Pose Domain publishes events in a standardized format that other contexts consume:
```rust
#[derive(Serialize, Deserialize)]
pub struct PoseEventPayload {
pub event_type: String,
pub version: String,
pub timestamp: DateTime<Utc>,
pub correlation_id: Uuid,
pub payload: PoseEstimate,
}
```
### Shared Kernel
The `wifi-densepose-core` crate contains shared types used across all contexts:
- Identifiers: `DeviceId`, `SessionId`, `FrameId`, `EstimateId`
- Timestamps: `Timestamp`, `Duration`
- Common errors: `DomainError`
- Configuration: `ConfigurationLoader`

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,114 @@
# Domain-Driven Design: WiFi-DensePose Domain Model
## Bounded Contexts
### 1. Signal Domain
**Purpose**: Raw CSI data acquisition and preprocessing
**Aggregates**:
- `CsiFrame`: Raw CSI measurement from WiFi hardware
- `ProcessedSignal`: Cleaned and feature-extracted signal
**Value Objects**:
- `Amplitude`: Signal strength measurements
- `Phase`: Phase angle measurements
- `SubcarrierData`: Per-subcarrier information
- `Timestamp`: Measurement timing
**Domain Services**:
- `CsiProcessor`: Preprocesses raw CSI data
- `PhaseSanitizer`: Unwraps and cleans phase data
- `FeatureExtractor`: Extracts signal features
### 2. Pose Domain
**Purpose**: Human pose estimation from processed signals
**Aggregates**:
- `PoseEstimate`: Complete DensePose output
- `InferenceSession`: Neural network session state
**Value Objects**:
- `BodyPart`: Labeled body segment (torso, arms, legs, etc.)
- `UVCoordinate`: Surface mapping coordinate
- `Keypoint`: Body joint position
- `Confidence`: Prediction confidence score
**Domain Services**:
- `ModalityTranslator`: CSI → visual feature translation
- `DensePoseHead`: Body part segmentation and UV regression
### 3. Streaming Domain
**Purpose**: Real-time data delivery to clients
**Aggregates**:
- `Session`: Client connection with history
- `StreamConfig`: Client streaming preferences
**Value Objects**:
- `WebSocketMessage`: Typed message payload
- `ConnectionState`: Active/idle/disconnected
**Domain Services**:
- `StreamManager`: Manages client connections
- `BroadcastService`: Pushes updates to subscribers
### 4. Storage Domain
**Purpose**: Persistence and retrieval
**Aggregates**:
- `Recording`: Captured CSI session
- `ModelArtifact`: Neural network weights
**Repositories**:
- `SessionRepository`: Session CRUD operations
- `RecordingRepository`: Recording storage
- `ModelRepository`: Model management
### 5. Hardware Domain
**Purpose**: Physical device management
**Aggregates**:
- `Device`: WiFi router/receiver
- `Antenna`: Individual antenna configuration
**Domain Services**:
- `DeviceManager`: Device discovery and control
- `CsiExtractor`: Raw CSI extraction
## Context Map
```
┌─────────────────────────────────────────────────────────────┐
│ WiFi-DensePose │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Hardware │────▶│ Signal │────▶│ Pose │ │
│ │ Domain │ │ Domain │ │ Domain │ │
│ └──────────────┘ └──────────────┘ └─────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Storage Domain │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Streaming Domain │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
```
## Ubiquitous Language
| Term | Definition |
|------|------------|
| CSI | Channel State Information - WiFi signal properties |
| Subcarrier | Individual frequency component in OFDM |
| Phase Unwrapping | Correcting 2π phase discontinuities |
| DensePose | Dense human pose estimation with UV mapping |
| Modality Translation | Converting CSI features to visual features |
| Body Part | One of 15 labeled human body segments |
| UV Mapping | 2D surface parameterization of 3D body |

View File

@@ -0,0 +1,487 @@
# Ubiquitous Language
This glossary defines the domain terminology used throughout the WiFi-DensePose system. All team members (developers, domain experts, stakeholders) should use these terms consistently in code, documentation, and conversation.
---
## Core Concepts
### WiFi-DensePose
The system that uses WiFi signals to perform non-invasive human pose estimation. Unlike camera-based systems, it operates through walls and in darkness, providing privacy-preserving body tracking.
### Channel State Information (CSI)
The detailed information about how a WiFi signal propagates between transmitter and receiver. CSI captures amplitude and phase changes across multiple subcarriers and antennas, encoding environmental information including human presence and movement.
### DensePose
A computer vision technique that maps all pixels of a detected human body to a 3D surface representation. In our context, we translate WiFi signals into DensePose-compatible outputs.
### Pose Estimation
The process of determining the position and orientation of a human body, typically by identifying anatomical landmarks (keypoints) and body segments.
---
## Signal Domain Terms
### Amplitude
The magnitude (strength) of the CSI measurement for a specific subcarrier and antenna pair. Amplitude variations indicate physical changes in the environment, particularly human movement.
**Units:** Linear scale or decibels (dB)
**Example Usage:**
```rust
let amplitude = csi_frame.amplitude(); // Matrix of amplitude values
```
### Phase
The timing offset of the WiFi signal, measured in radians. Phase is highly sensitive to distance changes and is crucial for detecting subtle movements like breathing.
**Units:** Radians (-pi to pi)
**Note:** Raw phase requires sanitization (unwrapping, noise removal) before use.
### Subcarrier
An individual frequency component within an OFDM (Orthogonal Frequency-Division Multiplexing) WiFi signal. Each subcarrier provides an independent measurement of the channel state.
**Typical Values:**
- 20 MHz bandwidth: 56 subcarriers
- 40 MHz bandwidth: 114 subcarriers
- 80 MHz bandwidth: 242 subcarriers
### Antenna
A physical receiver element on the WiFi device. Multiple antennas enable MIMO (Multiple-Input Multiple-Output) and provide spatial diversity in CSI measurements.
**Typical Configurations:** 1x1, 2x2, 3x3, 4x4
### Signal-to-Noise Ratio (SNR)
A quality metric measuring the strength of the desired signal relative to background noise. Higher SNR indicates cleaner, more reliable CSI data.
**Units:** Decibels (dB)
**Quality Thresholds:**
- SNR < 10 dB: Poor quality, may be unusable
- SNR 10-20 dB: Acceptable quality
- SNR > 20 dB: Good quality
### Noise Floor
The ambient electromagnetic interference level in the environment. The noise floor limits the minimum detectable signal.
**Units:** dBm (decibels relative to milliwatt)
### Doppler Shift
A frequency change caused by moving objects. The Doppler effect in CSI reveals motion velocity and direction.
**Formula:** fd = (2 * v * f) / c
Where v is velocity, f is carrier frequency, c is speed of light.
### Power Spectral Density (PSD)
The distribution of signal power across frequencies. PSD analysis reveals periodic motions like walking or breathing.
**Units:** dB/Hz
### Feature Extraction
The process of computing meaningful statistics and transformations from raw CSI data. Features include amplitude mean/variance, phase differences, correlations, and frequency-domain characteristics.
### Preprocessing
Initial signal conditioning including:
- **Noise removal** - Filtering out low-quality measurements
- **Windowing** - Applying window functions (Hamming, Hann) to reduce spectral leakage
- **Normalization** - Scaling values to standard ranges
- **Phase sanitization** - Unwrapping and smoothing phase data
---
## Pose Domain Terms
### Modality Translation
The core innovation of WiFi-DensePose: converting radio frequency (RF) features into visual-like feature representations that can be processed by pose estimation models.
**Also Known As:** Cross-modal learning, RF-to-vision translation
### Human Presence Detection
Binary classification determining whether one or more humans are present in the sensing area. This is typically the first stage of the pose estimation pipeline.
### Person Count
The estimated number of individuals in the detection zone. Accurate counting is challenging with WiFi sensing due to signal superposition.
### Keypoint
A named anatomical landmark on the human body. WiFi-DensePose uses the COCO keypoint format with 17 points:
| Index | Name | Description |
|-------|------|-------------|
| 0 | Nose | Tip of nose |
| 1 | Left Eye | Center of left eye |
| 2 | Right Eye | Center of right eye |
| 3 | Left Ear | Left ear |
| 4 | Right Ear | Right ear |
| 5 | Left Shoulder | Left shoulder joint |
| 6 | Right Shoulder | Right shoulder joint |
| 7 | Left Elbow | Left elbow joint |
| 8 | Right Elbow | Right elbow joint |
| 9 | Left Wrist | Left wrist |
| 10 | Right Wrist | Right wrist |
| 11 | Left Hip | Left hip joint |
| 12 | Right Hip | Right hip joint |
| 13 | Left Knee | Left knee joint |
| 14 | Right Knee | Right knee joint |
| 15 | Left Ankle | Left ankle |
| 16 | Right Ankle | Right ankle |
### Body Part
A segmented region of the human body. DensePose defines 24 body parts:
| ID | Part | ID | Part |
|----|------|----|------|
| 1 | Torso | 13 | Left Lower Leg |
| 2 | Right Hand | 14 | Right Lower Leg |
| 3 | Left Hand | 15 | Left Foot |
| 4 | Right Foot | 16 | Right Foot |
| 5 | Left Foot | 17 | Right Upper Arm Back |
| 6 | Right Upper Arm Front | 18 | Left Upper Arm Back |
| 7 | Left Upper Arm Front | 19 | Right Lower Arm Back |
| 8 | Right Lower Arm Front | 20 | Left Lower Arm Back |
| 9 | Left Lower Arm Front | 21 | Right Upper Leg Back |
| 10 | Right Upper Leg Front | 22 | Left Upper Leg Back |
| 11 | Left Upper Leg Front | 23 | Right Lower Leg Back |
| 12 | Right Lower Leg Front | 24 | Left Lower Leg Back |
### UV Coordinates
A 2D parameterization of the body surface. U and V are continuous coordinates (0-1) that map any point on the body to a canonical 3D mesh.
**Purpose:** Enable consistent body surface representation regardless of pose.
### Bounding Box
A rectangular region in the detection space that encloses a detected person.
**Format:** (x, y, width, height) in normalized coordinates [0, 1]
### Confidence Score
A probability value [0, 1] indicating the model's certainty in a detection or classification. Higher values indicate greater confidence.
**Thresholds:**
- Low: < 0.5
- Medium: 0.5 - 0.8
- High: > 0.8
### Activity
A high-level classification of what a person is doing:
| Activity | Description |
|----------|-------------|
| Standing | Upright, stationary |
| Sitting | Seated position |
| Walking | Ambulatory movement |
| Running | Fast ambulatory movement |
| Lying | Horizontal position |
| Falling | Rapid transition to ground |
| Unknown | Unclassified activity |
### Fall Detection
Identification of a fall event, typically characterized by:
1. Rapid vertical velocity
2. Horizontal final position
3. Sudden deceleration (impact)
4. Subsequent immobility
**Critical Use Case:** Elderly care, healthcare facilities
### Motion Detection
Recognition of significant movement in the sensing area. Motion is detected through:
- CSI amplitude/phase variance
- Doppler shift analysis
- Temporal feature changes
---
## Streaming Domain Terms
### Session
A client connection for real-time data streaming. A session has a lifecycle: connecting, active, paused, reconnecting, completed, failed.
### Stream Type
The category of data being streamed:
| Type | Data Content |
|------|--------------|
| Pose | Pose estimation results |
| CSI | Raw or processed CSI data |
| Alerts | Critical events (falls, motion) |
| Status | System health and metrics |
### Zone
A logical or physical area for filtering and organizing detections. Zones enable:
- Multi-room coverage with single system
- Per-area subscriptions
- Location-aware alerting
### Subscription
A client's expressed interest in receiving specific data. Subscriptions include:
- Stream types
- Zone filters
- Confidence thresholds
- Throttling preferences
### Broadcast
Sending data to all clients matching subscription criteria.
### Heartbeat
A periodic ping message to verify connection liveness. Clients that fail to respond to heartbeats are disconnected.
### Backpressure
Flow control mechanism when a client cannot process messages fast enough. Options include:
- Buffering (limited)
- Dropping frames
- Throttling source
### Latency
The time delay between event occurrence and client receipt. Measured in milliseconds.
**Target:** < 100ms for real-time applications
---
## Hardware Domain Terms
### Device
A physical WiFi hardware unit capable of CSI extraction. Supported types:
| Type | Description |
|------|-------------|
| ESP32 | Low-cost microcontroller with WiFi |
| Atheros Router | Router with modified firmware |
| Intel NIC | Intel 5300/5500 network cards |
| Nexmon | Broadcom chips with Nexmon firmware |
| PicoScenes | Research-grade CSI platform |
### MAC Address
Media Access Control address - a unique hardware identifier for network interfaces.
**Format:** XX:XX:XX:XX:XX:XX (hexadecimal)
### Firmware
Software running on the WiFi device that enables CSI extraction.
### Calibration
The process of tuning a device for optimal CSI quality:
1. Measure noise floor
2. Compute antenna phase offsets
3. Establish baseline signal characteristics
### Health Check
Periodic verification that a device is functioning correctly. Checks include:
- Connectivity
- Data rate
- Error rate
- Temperature (if available)
---
## Storage Domain Terms
### Repository
An interface for persisting and retrieving aggregate roots. Each aggregate type has its own repository.
**Pattern:** Repository pattern from Domain-Driven Design
### Entity
An object with a distinct identity that persists over time. Entities are equal if their identifiers match.
**Examples:** Device, Session, CsiFrame
### Value Object
An object defined by its attributes rather than identity. Value objects are immutable and equal if all attributes match.
**Examples:** Frequency, Confidence, MacAddress
### Aggregate
A cluster of entities and value objects treated as a single unit. One entity is the aggregate root; all access goes through it.
### Event Store
A persistence mechanism that stores domain events as the source of truth. Supports event sourcing and audit trails.
---
## Cross-Cutting Terms
### Bounded Context
A logical boundary within which a particular domain model is defined and applicable. Each bounded context has its own ubiquitous language.
**WiFi-DensePose Contexts:**
1. Signal (CSI processing)
2. Pose (inference)
3. Streaming (real-time delivery)
4. Storage (persistence)
5. Hardware (device management)
### Domain Event
A record of something significant that happened in the domain. Events are immutable and named in past tense.
**Examples:** CsiFrameReceived, PoseEstimated, FallDetected
### Command
A request to perform an action that may change system state.
**Examples:** ProcessCsiFrame, EstimatePose, ConnectDevice
### Query
A request for information that does not change state.
**Examples:** GetCurrentPose, GetDeviceStatus, GetSessionHistory
### Correlation ID
A unique identifier that links related events across the system, enabling end-to-end tracing.
---
## Metrics and Quality Terms
### Throughput
The rate of data processing, typically measured in:
- Frames per second (FPS) for CSI
- Poses per second for inference
- Messages per second for streaming
### Processing Time
The duration to complete a processing step. Measured in milliseconds.
### Accuracy
How closely estimates match ground truth. For pose estimation:
- OKS (Object Keypoint Similarity) for keypoints
- IoU (Intersection over Union) for bounding boxes
### Precision
The proportion of positive detections that are correct.
**Formula:** TP / (TP + FP)
### Recall
The proportion of actual positives that are detected.
**Formula:** TP / (TP + FN)
### F1 Score
Harmonic mean of precision and recall.
**Formula:** 2 * (Precision * Recall) / (Precision + Recall)
---
## Acronyms
| Acronym | Expansion |
|---------|-----------|
| API | Application Programming Interface |
| CQRS | Command Query Responsibility Segregation |
| CSI | Channel State Information |
| dB | Decibel |
| dBm | Decibel-milliwatt |
| DDD | Domain-Driven Design |
| FPS | Frames Per Second |
| Hz | Hertz (cycles per second) |
| IoU | Intersection over Union |
| MAC | Media Access Control |
| MIMO | Multiple-Input Multiple-Output |
| OFDM | Orthogonal Frequency-Division Multiplexing |
| OKS | Object Keypoint Similarity |
| PSD | Power Spectral Density |
| RF | Radio Frequency |
| RSSI | Received Signal Strength Indicator |
| SNR | Signal-to-Noise Ratio |
| UUID | Universally Unique Identifier |
| UV | Texture mapping coordinates |
| VO | Value Object |
| WiFi | Wireless Fidelity (IEEE 802.11) |
| WS | WebSocket |
---
## Usage Guidelines
### In Code
Use exact terms from this glossary:
```rust
// Good: Uses ubiquitous language
pub struct CsiFrame { ... }
pub fn detect_human_presence(&self) -> HumanPresenceResult { ... }
pub fn estimate_pose(&self) -> PoseEstimate { ... }
// Bad: Non-standard terminology
pub struct WifiData { ... } // Should be CsiFrame
pub fn find_people(&self) { ... } // Should be detect_human_presence
pub fn get_body_position(&self) { ... } // Should be estimate_pose
```
### In Documentation
Always use defined terms; avoid synonyms that could cause confusion.
### In Conversation
When discussing the system, use these terms consistently to ensure clear communication between technical and domain experts.
---
## Term Evolution
This glossary is a living document. To propose changes:
1. Discuss with domain experts and team
2. Update this document
3. Update code to reflect new terminology
4. Update all related documentation