news 2026/9/10 2:45:20

RuView WiFi 感知信号处理领域模型全解:从 CsiData 到 PresenceState 的 DDD 落地

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RuView WiFi 感知信号处理领域模型全解:从 CsiData 到 PresenceState 的 DDD 落地

RuView WiFi 感知信号处理领域模型全解:从 CsiData 到 PresenceState 的 DDD 落地

【免费下载链接】RuViewπ RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.项目地址: https://gitcode.com/GitHub_Trending/wi/RuView

导读

本文以 RuView 仓库中的 signal-processing-domain-model.md 为骨架,结合其在wifi-densepose-signalcrate 中的真实 Rust 实现(约 8000+ 行源码与全套确定性测试),系统拆解一套把"普通 WiFi 信号"转化为"人体运动与呼吸感知结果"的完整信号处理管线。读者将掌握:领域模型中的通用语言与三个有界上下文如何划分、CsiProcessor/FeatureExtractor/MotionDetector三个聚合根的职责边界、共轭相乘与 Hampel 滤波等六种 SOTA 算法及其数学原理、12 条关键不变量在源码中的强制方式,以及硬件/神经网络/MAT 三类防腐层如何保证领域纯净。这份 DDD 规格文档基于 ADR-014(SOTA 信号处理) 与wifi-densepose-signalcrate 编写,是理解 RuView「无摄像头、纯射频感知」能力的入口。


一、为什么需要用 DDD 建模 WiFi 感知

RuView 的核心是把商用 WiFi 的 CSI(Channel State Information)变成空间智能与生命体征监测信号。而这条链路上物理层、信号层、特征层、检测层之间数据形态差异极大,若不加约束极易演变成互相泄漏实现的"大泥球"。

领域驱动设计在此的价值体现在三个层面:

  1. 统一语言(Ubiquitous Language):团队与 Agent 用同一组精确术语(CsiFrameCSI RatioBVP……)讨论同一个物理过程,消除歧义;
  2. 边界划分(Bounded Context):将"清洗硬件伪影"、"抽取 ML 特征"、"检测人体/生命体征"三个关注点隔离成独立上下文,每个上下文有自己的聚合根与不变量;
  3. 防腐层(Anti-Corruption Layer):通过适配器吸收 ESP32/Intel5300 等硬件差异与下游神经网络张量格式差异,保护领域模型不被外部细节污染。

该模型文档声明其依据为 ADR-014 与wifi-densepose-signalcrate;而 v2/crates/wifi-densepose-signal/README.md 确认该 crate 实现了六篇同行评审文献中的算法(SpotFi、WiGest、FarSense、WiDance、Widar 3.0 等),每个算法都有确定性的单元测试且无 mock 数据。


二、通用语言(Ubiquitous Language)速查

文档定义的术语表是整个领域模型的锚点,理解它们后再读代码会顺畅得多:

术语定义要点
CsiFrame单个时刻、每个天线每个子载波的幅度 + 相位的一次 CSI 测量
Conjugate MultiplicationH_ref[k] * conj(H_target[k]),消除 CFO/SFO/PDD,只保留环境引起的相位
CSI Ratio两天线流共轭相乘得到的复结果
Hampel Filter运行中位数 ± 缩放 MAD 的离群检测器,可抵抗高达 50% 污染
Phase Sanitization对原始 CSI 相位执行去卷绕、去离群、平滑、去噪的流水线
SpectrogramSTFT 得到的 2D 时频矩阵,WiFi 活动识别的标准 CNN 输入
Subcarrier Sensitivity方差比(运动方差/静态方差),衡量子载波对运动的响应度
Body Velocity Profile (BVP)多普勒导出的"速度 × 时间"2D 矩阵,领域无关的运动表示
Fresnel ZoneTX 与 RX 之间发生反射/绕射的椭球区域
Breathing Estimate由 Fresnel 区边界穿越推导的 BPM + 幅度 + 置信度
Motion Score0.0–1.0 的复合分,融合方差、相关、相位与可选多普勒分量
Presence State二值检测结果:人存在/缺席,带平滑置信度
Calibration在已知为空时段记录基线方差,用于自适应检测

这些术语在代码中均有对应类型,例如MotionScoreBreathingEstimate等结构体定义在 motion.rs 与 fresnel.rs,并非停留在纸面规格。


三、三个有界上下文(Bounded Contexts)

3.1 CSI 预处理上下文(CSI Preprocessing Context)

职责:把原始测量变成无硬件伪影的干净 CSI 数据。其内部组成为:

  • 三个并行子能力:Conjugate MultiplicationHampel FilterPhase Sanitizer
  • 分别产出三个值对象:CsiRatio(clean phase)、HampelResult(outlier-free)、Sanitized Phase
  • 最终由CsiProcessor(聚合根)汇聚为CleanedCsiData输出。

对应的类型关系清晰可见:csi_ratio.rs 实现共轭相乘,hampel.rs 实现 Hampel 滤波,phase_sanitizer.rs 实现相位清洗,csi_processor.rs 作为聚合根串起整条预处理管线。

聚合根CsiProcessor值对象CsiDataCsiRatioHampelResultHampelConfigPhaseSanitizerConfig领域服务CsiPreprocessorPhaseSanitizer

3.2 特征提取上下文(Feature Extraction Context)

职责:把干净 CSI 转换为可喂给 ML 的特征表示。同样由三条支线构成:

  • STFT Spectrogram产出 2D 时频矩阵Spectrogram
  • Subcarrier Selection按敏感度挑出对运动响应最强的子载波;
  • Doppler BVP Engine抽取多普勒域BodyVelocityProfile

三者汇入聚合根FeatureExtractor输出CsiFeatures。实现分布在 spectrogram.rs、subcarrier_selection.rs、bvp.rs 与 features.rs。

聚合根FeatureExtractor值对象SpectrogramSubcarrierSelectionBodyVelocityProfileCsiFeatures

3.3 运动分析上下文(Motion Analysis Context)

职责:从 CSI 特征检测与分类人体运动与生命体征:

  • Motion Detector产出MotionScore + Detection
  • Fresnel Breathing依据菲涅尔区几何产出Breathing Estimate
  • 二者汇入HumanDetectionResult,对外发布最终PresenceState

实现在 motion.rs(约 1000 行,含完整检测状态机)与 fresnel.rs。

聚合根MotionDetector值对象MotionScoreMotionAnalysisHumanDetectionResultBreathingEstimateFresnelGeometry领域服务FresnelBreathingEstimator


四、三大聚合根:源码级契约

4.1 CsiProcessor —— 预处理聚合根

文档给出的契约如下(源码见 csi_processor.rs):

pub struct CsiProcessor { config: CsiProcessorConfig, preprocessor: CsiPreprocessor, history: VecDeque<CsiData>, previous_detection_confidence: f64, statistics: ProcessingStatistics, } impl CsiProcessor { pub fn new(config: CsiProcessorConfig) -> Result<Self, CsiProcessorError>; pub fn preprocess(&self, csi_data: &CsiData) -> Result<CsiData, CsiProcessorError>; pub fn add_to_history(&mut self, csi_data: CsiData); pub fn apply_temporal_smoothing(&mut self, raw_confidence: f64) -> f64; }

有意思的是:聚合根不仅做"噪声去除 → 加窗 → 归一化"(preprocess的 doc 注释),还维护时间历史(history: VecDeque<CsiData>)为下游特征抽取供数,并用指数移动平均对检测置信度做时间平滑。这与 Crate 的CsiData类型直接集成——从 lib.rs 的 re-export 可以看到,CsiProcessorCsiPreprocessor与错误类型都在 crate 顶层对外可见。

配置项默认值来自源码 csi_processor.rs 的Default实现:

配置项默认值含义
sampling_rate1000.0 Hz采样率
window_size256处理窗口(样点数)
overlap0.5窗口重叠率(0.0–1.0)
noise_threshold-30.0 dB幅度低于此值视为噪声子载波
human_detection_threshold0.8人体检测阈值
smoothing_factor0.9时间平滑因子
max_history_size500历史缓冲上限
enable_preprocessing/enable_feature_extraction/enable_human_detection均 true各阶段开关

4.2 FeatureExtractor —— 特征提取聚合根

pub struct FeatureExtractor { config: FeatureExtractorConfig } impl FeatureExtractor { pub fn extract(&self, csi_data: &CsiData) -> CsiFeatures; }

一个快照式的无状态抽取器。真实实现 features.rs(约 950 行)远比规格更丰富:从 crate 的lib.rs可看到它产出AmplitudeFeaturesCorrelationFeaturesPhaseFeaturesDopplerFeaturesPowerSpectralDensity五类特征子结构,最终合并为CsiFeatures

4.3 MotionDetector —— 运动分析聚合根

pub struct MotionDetector { config: MotionDetectorConfig, previous_confidence: f64, motion_history: VecDeque<MotionScore>, baseline_variance: Option<f64>, } impl MotionDetector { pub fn analyze_motion(&self, features: &CsiFeatures) -> MotionAnalysis; pub fn detect_human(&mut self, features: &CsiFeatures) -> HumanDetectionResult; pub fn calibrate(&mut self, features: &CsiFeatures); }

注意三个状态字段的精妙分工:

  • previous_confidence+apply_temporal_smoothing支撑帧间置信度平滑;
  • motion_historyVecDeque)支撑时间维分析,超过容量时旧条目被pop_front逐出(这正是第 12 条不变量的代码落地);
  • baseline_variance: Option<f64>支撑calibrate()自适应的空房间基线校准——静态值在未校准时为None,语义上天然表达了"尚未标定"这一状态。

MotionDetectorConfig的默认值在源码 motion.rs:

配置项默认值含义
human_detection_threshold0.8人体判定阈值(0–1)
motion_threshold0.3运动判定阈值(0–1)
smoothing_factor0.9平滑因子,越高越偏向历史检测
amplitude_threshold/phase_threshold0.1 / 0.05幅度与相位指标的阈值
history_size100时间分析历史长度
adaptive_thresholdfalse是否启用自适应阈值
amplitude_weight/phase_weight/motion_weight0.4 / 0.3 / 0.3三个指示子的加权比重

五、核心值对象(Value Objects)

值对象是不可变的数据描述,这里 7 个结构体完整定义了整个感知链路中的"中间产物"。

5.1 CsiData —— 一切开始的地方

pub struct CsiData { pub timestamp: DateTime<Utc>, pub amplitude: Array2<f64>, // (num_antennas x num_subcarriers) pub phase: Array2<f64>, // (num_antennas x num_subcarriers), radians pub frequency: f64, // center frequency in Hz pub bandwidth: f64, // bandwidth in Hz pub num_subcarriers: usize, pub num_antennas: usize, pub snr: f64, // dB pub metadata: CsiMetadata, }

它同时携带元数据(时间戳、载频、带宽、SNR)与数据(天线×子载波的幅度/相位矩阵),Array2为 ndarray 的 2D 数组。源代码中的CsiDataBuilder(见 csi_processor.rs 的类型签名区)可从复数 CSI 快照构造出该结构。

5.2 Spectrogram 与 SubcarrierSelection

pub struct Spectrogram { pub data: Array2<f64>, // (n_freq x n_time) power/magnitude pub n_freq: usize, // 频率 bin 数 = window_size/2 + 1 pub n_time: usize, pub freq_resolution: f64, // Hz per bin pub time_resolution: f64, // 每帧秒数 } pub struct SubcarrierSelection { pub selected_indices: Vec<usize>, // 按敏感度降序 pub sensitivity_scores: Vec<f64>, // 所有子载波的方差比 pub selected_data: Option<Array2<f64>>,// 可选过滤矩阵 }

其中SpectrogramConfig默认窗口 256、hop 64、Hann 窗、计算功率谱(见 spectrogram.rs)。WindowFunction支持 Rectangular/Hann/Hamming/Blackman 四种窗函数。n_freq = window_size/2 + 1反映了实数信号的 FFT 对称性——只保留一半频谱。

5.3 BVP、BreathingEstimate、MotionScore、HampelResult

pub struct BodyVelocityProfile { pub data: Array2<f64>, // (n_velocity_bins x n_time_frames) pub velocity_bins: Vec<f64>, // 每行对应速度 (m/s) pub n_time: usize, pub time_resolution: f64, // 每帧秒数 pub velocity_resolution: f64, // 每个 bin 的 m/s } pub struct BreathingEstimate { pub rate_bpm: f64, // 每分钟呼吸次数 pub confidence: f64, // 组合置信度 0-1 pub period_seconds: f64, pub autocorrelation_peak: f64, // 周期性质量 pub fresnel_confidence: f64, // Fresnel 模型匹配度 pub amplitude_variation: f64, // 观测幅度变化 } pub struct MotionScore { pub total: f64, // 加权复合分 0-1 pub variance_component: f64, pub correlation_component: f64, pub phase_component: f64, pub doppler_component: Option<f64>, // 可选多普勒分量 }

MotionScore.doppler_componentOption表达"是否有可用多普勒信息"——静态场景下该分量不存在而非为 0,这一设计在 DDD 上非常优雅:类型系统本身编码了领域语义。BreathingEstimateautocorrelation_peakfresnel_confidence分别对应"周期性强不强"与"是否符合菲涅尔物理模型"两重验证,这源自 ADR-014 中 Fresnel 模型的"位置预测"思想(见下文第六节)。

pub struct HampelResult { pub filtered: Vec<f64>, // 离群点被局部中位数替换 pub outlier_indices: Vec<usize>, pub medians: Vec<f64>, // 每个样本的局部中位数 pub sigma_estimates: Vec<f64>, // 每个样本的局部 σ 估计 }

5.4 FresnelGeometry —— 内嵌物理公式的值对象

pub struct FresnelGeometry { pub d_tx_body: f64, // TX 到人体距离 (m) pub d_body_rx: f64, // 人体到 RX 距离 (m) pub frequency: f64, // 载频 (Hz) } impl FresnelGeometry { pub fn wavelength(&self) -> f64; pub fn fresnel_radius(&self, n: u32) -> f64; pub fn phase_change(&self, displacement_m: f64) -> f64; pub fn expected_amplitude_variation(&self, displacement_m: f64) -> f64; }

它把物理公式封装成可测试的方法。源码 fresnel.rs 给出精确实现:

  • wavelength()= 光速 / 频率(SPEED_OF_LIGHT = 2.998e8 m/s);
  • fresnel_radius(n)=sqrt(n·λ·d1·d2/(d1+d2))
  • phase_change(Δd)=2π·2Δd/λ(往返路径差);
  • expected_amplitude_variation(Δd)=|sin(ΔΦ/2)|

FresnelGeometry::new构造器直接校验d_tx_body > 0d_body_rx > 0frequency > 0,非法值返回FresnelError::InvalidDistance/InvalidFrequency——把第 9、10 条不变量做进了构造入口,从根上杜绝了非法几何对象的存在。


六、六大 SOTA 算法:数学原理与源码对应

ADR-014 明确说明了为什么要替换旧管线:旧实现(Z-score 离群剔除、零交叉呼吸计数、全子载波等权)相比 2020–2025 学术界 SOTA 存在六项差距。逐一对应到 crate 模块如下:

能力旧实现SOTA 方案crate 模块文献来源
相位清洗Z-score 离群 + 去卷绕共轭相乘csi_ratio.rsSpotFi 2015, IndoTrack 2017
离群检测Z-scoreHampel 滤波(鲁棒中位数)hampel.rsWiGest 2015
呼吸检测零交叉计数Fresnel 区模型fresnel.rsFarSense 2019, Wi-Sleep 2021
信号表示原始幅度/相位CSI 谱图(2D 时频)spectrogram.rs2018 年以来 CNN 方案通用
子载波使用全部等权敏感度选择(方差比)subcarrier_selection.rsWiDance 2017
运动刻画单一运动分数Body Velocity Profilebvp.rsWidar 3.0 2019

6.1 共轭相乘(CSI Ratio 模型)

原理:原始 CSI 相位中混入逐包变化的 CFO(载波频率偏移)、SFO(采样频率偏移)与 PDD(包检测延迟)。对天线对(i, j)CSI_ratio[k] = H_1[k] · conj(H_2[k])后,两天线共有的硬件相位偏移被抵消,只剩下由环境(人体运动)路径差引起的相位。

实现细节:真实实现采用共轭乘积而非除法H_i/H_j——这是刻意的选择。源码 csi_ratio.rs 用一个专门的测试钉死了该性质:当参考信号幅值低至1e-12边界(甚至精确为零)时,除法会爆出 ±inf/NaN,而共轭乘积保持有限且与理论值逐位一致。单元测试还验证了:

  • 公共相位(模拟 CFO)被精确消除:test_conjugate_multiply_cancels_common_phase
  • 3 天线产生 C(3,2)=3 对、4 天线产生 C(4,2)=6 对:test_ratio_matrix_pair_count
  • 全部子载波应显示相同的路径差相位:test_ratio_preserves_path_difference

6.2 Hampel 滤波

原理:WiFi CSI 存在突发干扰、多径尖峰与硬件毛刺。Z-score 依赖的均值/标准差会被离群值自身污染(掩蔽效应);Hampel 用运行中位数与 MAD 估计局部 σ,能抵抗高达 50% 的数据污染。

数学:窗口内median = med(x[i-w..i+w])MAD = med(|x[j]−median|)σ_est = 1.4826·MAD;当|x[i]−median| > t·σ_est时用中位数替换x[i]1.4826是高斯分布下 MAD 到 σ 的比例因子(源码 hampel.rs 中的MAD_SCALE常量)。

实现细节:默认配置half_window = 3threshold = 3.0(即滑动窗宽 7、3σ 判异)。当窗口全等导致 σ 退化时,实现用ZERO_MAD_EPSILON = 1e-15兜底(hampel.rs),任何超过该 ε 的偏离都视为离群。

6.3 Fresnel 区呼吸模型

原理:呼吸时胸腔位移约 5–10mm,在 5 GHz(λ=60mm)下是 Fresnel 区宽度的可观比例。Fresnel 模型根据 TX–RX–人体几何预测信号周期中呼吸运动应出现的位置,因此即便信号较弱也能检测——这正是零交叉法在富多径环境下失效的补救。

物理量F_n = sqrt(n·λ·d1·d2/(d1+d2))ΔΦ = 2π·2Δd/λ;呼吸期望幅度A = |sin(ΔΦ/2)|

实现细节FresnelBreathingEstimator以典型成人胸腔位移 4–12mm 为参照(fresnel.rs),构造时设置min_displacement = 3mmmax_displacement = 15mm的默认探测区间。breathing_confidence()把观测幅度变化映射到 0–1 置信度:落在期望区间内给 1.0,低于区间按比例线性缩放,高于区间(如走动这类大幅运动)则按high/observed反比衰减——物理上把"更大的运动不是呼吸"这一先验直接编码进打分函数。estimate_breathing_rate()先用自相关找周期性,再用 Fresnel 幅度区间做验证,少于 10 个幅度样本直接抛FresnelError::InsufficientData

6.4 CSI 谱图(Spectrogram)

原理:对每个子载波的时序幅度做滑动窗口 FFT(STFT),得到 2D 时频矩阵。呼吸约呈现 0.2–0.4 Hz 频带、行走约 1–2 Hz、静止环境只有噪声——2D 结构让 CNN 能学到 1D 特征看不到的空间模式。

数学S[t,f] = |Σ_n x[n]·w[n−t]·exp(−j2πfn)|²

实现细节:默认使用 Hann 窗、window_size = 256hop_size = 64(75% 重叠),默认输出功率谱(power = true),见 spectrogram.rs。

6.5 子载波敏感度选择

原理:并非所有子载波对人体运动同样敏感——有些落在多径零点、有些主要携带噪声。等权使用全部子载波会稀释信号;只选最敏感的 10–20 个可将 SNR 提升 6–10 dB。

数学sensitivity[k] = var_motion(amp[k]) / (var_static(amp[k]) + ε),然后取 top-K。

实现细节SubcarrierSelectionConfig(见 subcarrier_selection.rs)控制运动/静态窗口与 top-K 选择逻辑,产出按敏感度降序排列的selected_indices与全子载波sensitivity_scores

6.6 Body Velocity Profile(BVP)

原理:BVP 是"速度 × 时间"2D 表示,刻画身体不同部位以不同速度运动的方式。因为它是领域无关的——同样的速度分布不随房间布局、家具或 AP 位置改变——成为跨环境手势与活动识别的基石。

数学:对每个子载波沿时间做 DFT 后跨子载波聚合:BVP[v,t] = Σ_k |STFT_k[v,t]|,其中速度映射为v = f_doppler·λ/2

实现细节:源码 bvp.rs(405 行)要求至少window_size个时间样本才能计算 STFT(第 7 条不变量),BvpConfig默认参数定义了速度 bin 与时间帧的分辨率。


七、领域事件(Domain Events):上下文之间的"留痕"

文档定义了三个上下文的领域事件枚举,事件在 lib.rs 的 crate 架构中扮演"可观测性 + 可审计性"双角色。它们不仅是领域知识,也是测试与监控的抓手。

预处理事件

enum PreprocessingEvent { FrameCleaned { timestamp, num_antennas, num_subcarriers, noise_filtered, windowed, normalized }, OutliersDetected { subcarrier_indices, replacement_values, contamination_ratio }, PhaseSanitized { method: UnwrappingMethod, outliers_removed, smoothing_applied }, }

contamination_ratio这样的字段直接暴露了"这一帧有多少比例的子载波被判为离群",可据此诊断信道质量。

特征提取事件

enum FeatureExtractionEvent { SpectrogramGenerated { n_time, n_freq, window_size, window_fn }, SubcarriersSelected { top_k_indices, sensitivity_scores, min_sensitivity_threshold }, BvpExtracted { n_velocity_bins, n_time_frames, max_velocity, carrier_frequency }, }

运动分析事件

enum MotionAnalysisEvent { MotionDetected { score, confidence, threshold, timestamp }, BreathingDetected { rate_bpm, amplitude_variation, fresnel_confidence, autocorrelation_peak }, PresenceChanged { previous, current, smoothed_confidence, timestamp }, BaselineCalibrated { baseline_variance, timestamp }, }

PresenceChanged携带previous/current状态对与平滑置信度,是上层(如 Home Assistant、MAT、UI)做状态机转换的标准输入——RuView 的感知服务器正是这些事件的下游消费者。


八、12 条不变量(Invariants):物理与逻辑的双重约束

文档列出了 12 条必须始终成立的不变量,每一条都在源码/测试中找到了落点,其背后是"物理上不可能"或"算法上无意义"两类判断:

预处理(1–4)

  1. 共轭相乘需 ≥2 根天线,否则compute_ratio_matrix返回CsiRatioError::InsufficientAntennas(源码实现于 csi_ratio.rs);
  2. Hampel 窗宽 ≥1(half_window > 0),否则无法计算局部中位数,抛HampelError::InvalidWindow
  3. 相位数据须在配置范围内(默认[-π, π]),由PhaseSanitizer::validate_phase_data强制;
  4. 两天线流长度必须相等,否则conjugate_multiply返回CsiRatioError::LengthMismatch

特征提取(5–8)5. 谱图窗宽 > 0 且信号 ≥ 窗长,分别抛SpectrogramError::InvalidWindowSizeSignalTooShort; 6. 子载波选择输入的子载波数必须一致,抛SelectionError::SubcarrierCountMismatch; 7. BVP 需 ≥ 窗长时间样本,否则无法 STFT,抛BvpError::InsufficientSamples; 8. BVP 载频必须 > 0,否则多普勒→速度映射会出现除零。

运动分析(9–12)9. Fresnel 几何要求d_tx_body > 0d_body_rx > 0,由FresnelError::InvalidDistance强制——如前所述,fresnel.rs 在FresnelGeometry::new构造期即校验; 10. Fresnel 频率必须为正(FresnelError::InvalidFrequency); 11. 呼吸估计需 ≥10 个幅度样本(FresnelError::InsufficientData),否则自相关分析不可靠——实现在 fresnel.rs; 12. 运动检测器历史不超过配置上限,超过时VecDeque::pop_front逐出最旧条目。

从架构视角看,这些不变量被分两层防御:构造期防御(如 Fresnel 几何校验)把非法对象挡在门外;运行期防御(如长度/样本数校验)把非法运算挡在函数内。配套的确定性测试(tests/validation_test.rs 等)与 ADR-014 要求的"无 mock、确定性输入输出"原则一致。


九、领域服务(Domain Services):无状态的算法编排

CsiPreprocessor—— 单帧清洗管线,含三个原子操作:

pub struct CsiPreprocessor { noise_threshold: f64 } impl CsiPreprocessor { pub fn remove_noise(&self, csi_data: &CsiData) -> Result<CsiData, CsiProcessorError>; // 剔除 dB 幅度低于底噪的子载波 pub fn apply_windowing(&self, csi_data: &CsiData) -> Result<CsiData, CsiProcessorError>; // Hamming 窗降频谱泄漏 pub fn normalize_amplitude(&self, csi_data: &CsiData) -> Result<CsiData, CsiProcessorError>; // 幅度归一化到单位方差 }

PhaseSanitizer—— 完整相位清洗管线,四个阶段:去卷绕 → 离群剔除 → 平滑 → 去噪。默认配置见 phase_sanitizer.rs:Standard卷绕方法、离群阈值 3.0、平滑窗 5、默认关闭噪声滤波(noise_threshold 0.05)、相位范围(-π, π)

FresnelBreathingEstimator—— 基于菲涅尔几何的物理呼吸检测器,提供breathing_confidence()(幅度匹配度打分)与estimate_breathing_rate()(自相关 + Fresnel 双重验证)两个能力,代码见 fresnel.rs。


十、上下文映射(Context Map)与防腐层(ACL)

10.1 整体关系

模型文档用一张 Context Map 标明系统内外的协作模式:

  • 上游(Conformist)wifi-densepose-core(提供CsiFrame原语)、wifi-densepose-hardware(ESP32 原始 CSI 摄取)——信号 crate 适配它们的类型;
  • 内部协作:预处理上下文 → 特征提取上下文通过CsiData作为Published Language契约;预处理/特征提取 → 运动分析是Customer/Supplier
  • 事件总线:三个上下文通过领域事件解耦;
  • 下游(Customer/Supplier)wifi-densepose-nn消费CsiFeatures/Spectrogramwifi-densepose-mat消费BreathingEstimate/MotionScorewifi-densepose-train消费CsiFeatures

这些下游 crate 在 v2/crates/ 下确实存在,例如 wifi-densepose-mat/src/integration/signal_adapter.rs 正是 MAT 侧对信号领域输出做转换的适配实现。

10.2 硬件防腐层(Hardware ACL,上游)

负责把 ESP32 原始 CSI 包翻译成 crate 内部的CsiData值对象,统一硬件特有怪癖(LLTF/HT-LTF 格式差异、天线映射、空子载波处理):

pub struct HardwareNormalizer { hardware_type: HardwareType } impl HardwareNormalizer { pub fn normalize(&self, raw_csi: &[u8], hardware_type: HardwareType) -> Result<CanonicalCsiFrame, HardwareNormError>; } pub enum HardwareType { Esp32S3, Intel5300, AtherosAr9580, Simulation }

真实实现在 hardware_norm.rs(511 行),它同时导出CanonicalCsiFrameAmplitudeStats等类型——这正是文档中"把厂商差异吸收在边界之内"的体现。可支持Simulation硬件类型也解释了仓库为何能用确定性合成数据做验证。

10.3 神经网络防腐层(Neural Network ACL,下游)

将信号处理输出(Spectrogram、BVP、CsiFeatures)适配为wifi-densepose-nncrate 期望的张量格式,防止神经网络实现细节反向泄漏进信号处理领域:

pub struct SignalToTensorAdapter; impl SignalToTensorAdapter { pub fn spectrogram_to_tensor(spec: &Spectrogram) -> Array2<f32>; // CNN 就绪 2D 张量 pub fn bvp_to_tensor(bvp: &BodyVelocityProfile) -> Array2<f32>; // 领域无关速度张量 pub fn selected_csi_to_tensor(selection: &SubcarrierSelection, data: &Array2<f64>) -> Result<Array2<f32>, SelectionError>; // 降维输入 }

10.4 MAT 防腐层(MAT ACL,下游)

MAT(Mass Casualty Assessment Tool,大规模伤亡评估工具)把领域通用的运动分与呼吸估计翻译为灾难场景下的生命体征上下文:

pub struct SignalToMatAdapter; impl SignalToMatAdapter { pub fn to_breathing_pattern(est: &BreathingEstimate) -> BreathingPattern; // BPM→rate、幅度变化→amplitude、自相关峰→regularity pub fn to_presence_indicator(score: &MotionScore) -> PresenceIndicator; // total>0.3 判存在 }

注意to_presence_indicatorscore.total > 0.3作为存在性阈值——该阈值在 MAT 适配边界上定义,而不是侵入信号处理领域内部,这正是防腐层"翻译"而非"耦合"的设计精神。


十一、领域模型如何驱动实现与验证

这份领域规格并非纸上谈兵,它与 crate 的工程质量直接挂钩:

  • 模块即上下文:crate 的 src/ 目录结构(csi_processor.rsfeatures.rsmotion.rsfresnel.rs等)与领域模型的上下文/聚合一一对应,开发者可凭文件名直达某个 DDD 概念;
  • 测试钉住不变量:tests/ 下 6 个集成测试文件覆盖校准漂移、校准往返、合成校准、CIR 合成/管道/幽灵径等场景,与单元测试一起构成"确定性、无 mock"的验证网;
  • 性能基准配套:benches/ 下的signal_benchdsp_perf_benchfeatures_bench等为感知管线的实时性提供量化依据;
  • 向下游延伸:信号领域模型与 docs/ddd/ 下其余 DDD 文档(如 wifi-mat-domain-model.md)通过防腐层衔接,构成更大的领域全景。

对想深入 RuView 感知链路的读者,建议的阅读顺序是:本文规格文档 → ADR-014 算法决策记录(含六个算法的完整数学推导与文献出处)→ crate 对应模块源码 → 各模块测试。这条路径能让你完整看到"物理假设 → DDD 规格 → Rust 实现 → 确定性验证"的全过程。


总结

RuView 的信号处理领域模型展示了一个高质量的 DDD 工程范例:用统一语言消除多学科歧义,用有界上下文隔离物理层、特征层与语义层,用聚合根管理生命周期,用领域事件支撑解耦与可观测,用 12 条不变量固化物理边界与算法前提,用三道防腐层保持领域纯净。而支撑它的,是一套把 SpotFi、FarSense、Widar 3.0 等发表于 2015–2021 年的学界 SOTA 算法逐一定稿、逐行实现、逐项测试的 Rust crate——这正是 RuView「无需任何视频像素,仅凭商品化 WiFi 信号即可感知空间、姿态与生命体征」的技术底座。

【免费下载链接】RuViewπ RuView turns commodity WiFi signals into real-time spatial intelligence, vital sign monitoring, and presence detection — all without a single pixel of video.项目地址: https://gitcode.com/GitHub_Trending/wi/RuView

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 2:44:41

开源AI Agent平台选型指南:从分类对比到企业落地实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 2:44:03

CANN/ge aclgrphBuildModel基础功能配置

基础功能 【免费下载链接】ge GE&#xff08;Graph Engine&#xff09;是面向昇腾的图编译器和执行器&#xff0c;提供了计算图优化、多流并行、内存复用和模型下沉等技术手段&#xff0c;加速模型执行效率&#xff0c;减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的…

作者头像 李华
网站建设 2026/9/10 2:40:37

从欧拉常数到-1/12:发散级数背后的数学统一

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 2:35:37

带注释的PinyinIME源码包:Android输入法开发的核心指南

简介&#xff1a;面向 Android 开发者的谷歌输入法 PinyinIME 注释源码包&#xff0c;覆盖拼音识别、词组预测、自动纠错、手势输入等核心模块&#xff0c;可帮助理解输入法内部工作原理与 Android 输入事件处理机制&#xff0c;适合希望自研或优化输入法的中高级 Android 开发…

作者头像 李华