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:
@@ -0,0 +1,56 @@
|
||||
# ADR-001: Rust Workspace Structure
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
We need to port the WiFi-DensePose Python application to Rust for improved performance, memory safety, and cross-platform deployment including WASM. The architecture must be modular, maintainable, and support multiple deployment targets.
|
||||
|
||||
## Decision
|
||||
We will use a Cargo workspace with 9 modular crates:
|
||||
|
||||
```
|
||||
wifi-densepose-rs/
|
||||
├── Cargo.toml # Workspace root
|
||||
├── crates/
|
||||
│ ├── wifi-densepose-core/ # Core types, traits, errors
|
||||
│ ├── wifi-densepose-signal/ # Signal processing (CSI, phase, FFT)
|
||||
│ ├── wifi-densepose-nn/ # Neural networks (DensePose, translation)
|
||||
│ ├── wifi-densepose-api/ # REST/WebSocket API (Axum)
|
||||
│ ├── wifi-densepose-db/ # Database layer (SQLx)
|
||||
│ ├── wifi-densepose-config/ # Configuration management
|
||||
│ ├── wifi-densepose-hardware/ # Hardware abstraction
|
||||
│ ├── wifi-densepose-wasm/ # WASM bindings
|
||||
│ └── wifi-densepose-cli/ # CLI application
|
||||
```
|
||||
|
||||
### Crate Responsibilities
|
||||
|
||||
1. **wifi-densepose-core**: Foundation types, traits, and error handling shared across all crates
|
||||
2. **wifi-densepose-signal**: CSI data processing, phase sanitization, FFT, feature extraction
|
||||
3. **wifi-densepose-nn**: Neural network inference using ONNX Runtime, Candle, or tch-rs
|
||||
4. **wifi-densepose-api**: HTTP/WebSocket server using Axum
|
||||
5. **wifi-densepose-db**: Database operations with SQLx
|
||||
6. **wifi-densepose-config**: Configuration loading and validation
|
||||
7. **wifi-densepose-hardware**: Router and hardware interfaces
|
||||
8. **wifi-densepose-wasm**: WebAssembly bindings for browser deployment
|
||||
9. **wifi-densepose-cli**: Command-line interface
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Clear separation of concerns
|
||||
- Independent crate versioning
|
||||
- Parallel compilation
|
||||
- Selective feature inclusion
|
||||
- Easier testing and maintenance
|
||||
- WASM target isolation
|
||||
|
||||
### Negative
|
||||
- More complex dependency management
|
||||
- Initial setup overhead
|
||||
- Cross-crate refactoring complexity
|
||||
|
||||
## References
|
||||
- [Cargo Workspaces](https://doc.rust-lang.org/cargo/reference/workspaces.html)
|
||||
- [ruvector crate structure](https://github.com/ruvnet/ruvector)
|
||||
@@ -0,0 +1,40 @@
|
||||
# ADR-002: Signal Processing Library Selection
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
CSI signal processing requires FFT operations, complex number handling, and matrix operations. We need to select appropriate Rust libraries that provide Python/NumPy equivalent functionality.
|
||||
|
||||
## Decision
|
||||
We will use the following libraries:
|
||||
|
||||
| Library | Purpose | Python Equivalent |
|
||||
|---------|---------|-------------------|
|
||||
| `ndarray` | N-dimensional arrays | NumPy |
|
||||
| `rustfft` | FFT operations | numpy.fft |
|
||||
| `num-complex` | Complex numbers | complex |
|
||||
| `num-traits` | Numeric traits | - |
|
||||
|
||||
### Key Implementations
|
||||
|
||||
1. **Phase Sanitization**: Multiple unwrapping methods (Standard, Custom, Itoh, Quality-Guided)
|
||||
2. **CSI Processing**: Amplitude/phase extraction, temporal smoothing, Hamming windowing
|
||||
3. **Feature Extraction**: Doppler, PSD, amplitude, phase, correlation features
|
||||
4. **Motion Detection**: Variance-based with adaptive thresholds
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Pure Rust implementation (no FFI overhead)
|
||||
- WASM compatible (rustfft is pure Rust)
|
||||
- NumPy-like API with ndarray
|
||||
- High performance with SIMD optimizations
|
||||
|
||||
### Negative
|
||||
- ndarray-linalg requires BLAS backend for advanced operations
|
||||
- Learning curve for ndarray patterns
|
||||
|
||||
## References
|
||||
- [ndarray documentation](https://docs.rs/ndarray)
|
||||
- [rustfft documentation](https://docs.rs/rustfft)
|
||||
@@ -0,0 +1,57 @@
|
||||
# ADR-003: Neural Network Inference Strategy
|
||||
|
||||
## Status
|
||||
Accepted
|
||||
|
||||
## Context
|
||||
The WiFi-DensePose system requires neural network inference for:
|
||||
1. Modality translation (CSI → visual features)
|
||||
2. DensePose estimation (body part segmentation + UV mapping)
|
||||
|
||||
We need to select an inference strategy that supports pre-trained models and multiple backends.
|
||||
|
||||
## Decision
|
||||
We will implement a multi-backend inference engine:
|
||||
|
||||
### Primary Backend: ONNX Runtime (`ort` crate)
|
||||
- Load pre-trained PyTorch models exported to ONNX
|
||||
- GPU acceleration via CUDA/TensorRT
|
||||
- Cross-platform support
|
||||
|
||||
### Alternative Backends (Feature-gated)
|
||||
- `tch-rs`: PyTorch C++ bindings
|
||||
- `candle`: Pure Rust ML framework
|
||||
|
||||
### Architecture
|
||||
```rust
|
||||
pub trait Backend: Send + Sync {
|
||||
fn load_model(&mut self, path: &Path) -> NnResult<()>;
|
||||
fn run(&self, inputs: HashMap<String, Tensor>) -> NnResult<HashMap<String, Tensor>>;
|
||||
fn input_specs(&self) -> Vec<TensorSpec>;
|
||||
fn output_specs(&self) -> Vec<TensorSpec>;
|
||||
}
|
||||
```
|
||||
|
||||
### Feature Flags
|
||||
```toml
|
||||
[features]
|
||||
default = ["onnx"]
|
||||
onnx = ["ort"]
|
||||
tch-backend = ["tch"]
|
||||
candle-backend = ["candle-core", "candle-nn"]
|
||||
cuda = ["ort/cuda"]
|
||||
tensorrt = ["ort/tensorrt"]
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- Use existing trained models (no retraining)
|
||||
- Multiple backend options for different deployments
|
||||
- GPU acceleration when available
|
||||
- Feature flags minimize binary size
|
||||
|
||||
### Negative
|
||||
- ONNX model conversion required
|
||||
- ort crate pulls in C++ dependencies
|
||||
- tch requires libtorch installation
|
||||
263
rust-port/wifi-densepose-rs/docs/ddd/README.md
Normal file
263
rust-port/wifi-densepose-rs/docs/ddd/README.md
Normal 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
|
||||
1480
rust-port/wifi-densepose-rs/docs/ddd/aggregates.md
Normal file
1480
rust-port/wifi-densepose-rs/docs/ddd/aggregates.md
Normal file
File diff suppressed because it is too large
Load Diff
765
rust-port/wifi-densepose-rs/docs/ddd/bounded-contexts.md
Normal file
765
rust-port/wifi-densepose-rs/docs/ddd/bounded-contexts.md
Normal 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`
|
||||
1158
rust-port/wifi-densepose-rs/docs/ddd/domain-events.md
Normal file
1158
rust-port/wifi-densepose-rs/docs/ddd/domain-events.md
Normal file
File diff suppressed because it is too large
Load Diff
114
rust-port/wifi-densepose-rs/docs/ddd/domain-model.md
Normal file
114
rust-port/wifi-densepose-rs/docs/ddd/domain-model.md
Normal 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 |
|
||||
487
rust-port/wifi-densepose-rs/docs/ddd/ubiquitous-language.md
Normal file
487
rust-port/wifi-densepose-rs/docs/ddd/ubiquitous-language.md
Normal 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
|
||||
Reference in New Issue
Block a user