RuView Signal Intelligence 模块深度解析:ESP32 边缘 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
本文系统讲解 RuView 项目中运行在 ESP32-S3 芯片上的 6 个 Signal Intelligence(信号智能)WASM 模块——Flash Attention、Coherence Gate、Temporal Compress、Sparse Recovery、Min-Cut Person Match 与 Optimal Transport。它们位于原始 CSI 数据与健康、安防等应用级模块之间,负责清洗、压缩与特征提取,为上层应用提供高质量输入。读完本文,你将掌握每个模块的算法原理、事件协议、配置常量与性能预算,并能结合源码理解其
no_std、无堆分配的边缘部署约束。
Signal Intelligence 模块隶属于 RuView 的 Edge Intelligence Modules 体系——60 余个运行在 ESP32 上的 WASM 模块,每个模块 5–30 KB,本地决策延迟低于 10 ms,无需联网与云服务。信号智能这一组 6 个模块(对应 54 个测试用例)是整个体系的数据质量地基:它们不直接产出业务结论,而是保证健康、安防、智能建筑等上层模块拿到的永远是"干净、完整、可解释"的 WiFi 信道数据。
Overview:六个模块一览
| 模块 | 文件 | 功能 | 事件 ID | 预算 |
|---|---|---|---|---|
| Flash Attention | sig_flash_attention.rs | 将计算聚焦于信息量最大的子载波分组 | 700-702 | S(<5ms) |
| Coherence Gate | sig_coherence_gate.rs | 利用相位相干性滤除噪声/损坏的 CSI 帧 | 710-712 | L(<2ms) |
| Temporal Compress | sig_temporal_compress.rs | 以 3 层压缩环形缓冲存储 CSI 历史 | 705-707 | S(<5ms) |
| Sparse Recovery | sig_sparse_recovery.rs | 用 ISTA 稀疏优化恢复丢失的子载波 | 715-717 | H(<10ms) |
| Min-Cut Person Match | sig_mincut_person_match.rs | 用二分图匹配维护跨帧稳定的人员 ID | 720-722 | H(<10ms) |
| Optimal Transport | sig_optimal_transport.rs | 用 sliced Wasserstein 距离检测细微运动 | 725-727 | S(<5ms) |
所有 6 个模块的源码均位于 v2/crates/wifi-densepose-wasm-edge/src/ 目录,事件 ID 注册于 700–729 的 Signal Intelligence 区间(见 Edge Intelligence Modules 文档 的 Event ID Registry)。
信号处理在整体架构中的位置
Signal Intelligence 模块构成了原始 CSI 数据与应用级模块之间的处理管线:
Raw CSI from WiFi chipset (Tier 0-2 firmware DSP) | v +---------------------+ +---------------------+ | Coherence Gate | --> | Sparse Recovery | | Reject noisy frames, | | Fill in dropped | | gate quality levels | | subcarriers via ISTA | +---------------------+ +---------------------+ | | v v +---------------------+ +---------------------+ | Flash Attention | | Temporal Compress | | Focus on informative | | Store CSI history | | subcarrier groups | | at 3 quality tiers | +---------------------+ +---------------------+ | | v v +---------------------+ +---------------------+ | Min-Cut Person Match | | Optimal Transport | | Track person IDs | | Detect subtle motion | | across frames | | via distribution | +---------------------+ +---------------------+ | | v v Application modules: Health, Security, Smart Building, etc.Coherence Gate位于管线最顶端充当质量过滤器,只有通过门控的帧才会进入Sparse Recovery(检测到子载波丢失时触发)并流向下游分析;Flash Attention识别信号最集中的空间区域,Temporal Compress维护高效的滚动历史;Min-Cut Person Match与Optimal Transport提取上层模块消费的高级特征(人员身份与运动)。
从源码结构看,这套管线可以直接嵌套在 vendor_common.rs 定义的VendorModuleStatetrait 生命周期中——每个厂商模块统一实现init()、process()(每 CSI 帧约 20 Hz 调用)、timer()(默认 1 秒间隔)三个回调,便于组合成统一的处理链。
共享工具库(vendor_common.rs)
所有信号智能模块共享 vendor_common.rs 中的以下工具。该文件头部注释明确声明:所有结构体均为no_std、const可构造、无堆分配,供信号智能、自适应学习、空间推理、时间分析、AI 安全、量子启发、自治等 24 个厂商集成模块复用:
| 工具 | 用途 |
|---|---|
CircularBuffer<N> | 定长环形缓冲,用于相位历史,栈上分配 |
Ema | 可配置 alpha 的指数移动平均 |
WelfordStats | O(1) 内存的在线均值/方差/标准差 |
dot_product、l2_norm、cosine_similarity | 定长向量数学 |
dtw_distance、dtw_distance_banded | 动态时间规整,用于手势/模式匹配 |
FixedPriorityQueue<CAP> | 无堆分配的 Top-K 选择 |
其中CircularBuffer<N>是 const 泛型实现(见 vendor_common.rs 的 CircularBuffer),支持push满时覆盖最旧元素、按年龄读取get(i)、copy_recent批量拷贝最近值,是相位历史与滚动统计的基础容器。
Flash Attention(sig_flash_attention.rs)
功能:将处理聚焦于携带最多有用信息的 WiFi 信道,忽略噪声。将 32 个子载波划分为 8 个分组(tile),计算注意力权重,显示信号活动集中在何处。
算法:对 8 个子载波分组执行 tiled attention(Q·K/√d),配合 softmax 归一化与 Shannon 熵跟踪。源码实现(sig_flash_attention.rs):
- 计算分组均值:Q = 当前各分组相位,K = 上一帧相位,V = 各分组幅度;
- 打分每个分组:
score[g] = Q[g] * K[g] / sqrt(8); - Softmax 归一化(数值稳定实现:先减去最大值再取 exp,且对
exp_sum施加LOG_EPSILON = 1e-7下限防除零); - 跟踪熵 H = -Σ(p·ln(p)),经
ENTROPY_ALPHA = 0.15的 EMA 平滑。
低熵意味着活动集中于某一空间区域(Fresnel 区);高熵意味着活动均匀分布。熵的初始值为MAX_ENTROPY = 2.079(即 ln(8)),第一帧仅用于初始化 K(上一帧相位)而不产生事件——这一点有单元测试test_first_frame_no_events专门验证。
公开 API
pub struct FlashAttention { /* ... */ } impl FlashAttention { pub const fn new() -> Self; pub fn process_frame(&mut self, phases: &[f32], amplitudes: &[f32]) -> &[(i32, f32)]; pub fn weights() -> &[f32; 8]; // Current attention weights per group pub fn entropy() -> f32; // EMA-smoothed entropy [0, ln(8)] pub fn peak_group() -> usize; // Group index with highest weight pub fn centroid() -> f32; // Weighted centroid position [0, 7] pub fn frame_count() -> u32; pub fn reset(&mut self); }注意:process_frame要求子载波数不少于分组数(n_sc < N_GROUPS时直接返回空事件,测试test_too_few_subcarriers以 4 个子载波验证了这一行为)。
事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 700 | ATTENTION_PEAK_SC | 分组索引(0-7) | 哪个子载波分组的注意力权重最强 |
| 701 | ATTENTION_SPREAD | 熵(0 ~ 约 2.08) | 注意力分布有多分散(低=聚焦,高=均匀) |
| 702 | SPATIAL_FOCUS_ZONE | 质心(0.0-7.0) | 跨分组的注意力加权中心 |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
N_GROUPS | 8 | 子载波分组(tile)数量 |
MAX_SC | 32 | 处理的最大子载波数 |
ENTROPY_ALPHA | 0.15 | 熵的 EMA 平滑因子 |
LOG_EPSILON | 1e-7 | 熵与 softmax 的数值稳定下限 |
MAX_ENTROPY | 2.079 | 熵上限(= ln(8)),作为初始值 |
教程:理解注意力权重
8 个注意力权重之和为 1.0。当一个人站在房间的某个区域时,WiFi 信号在与该区域相交的 Fresnel 区的子载波分组中变化最剧烈。
- 所有权重接近 0.125(= 1/8):均匀注意力。没有局部活动——要么房间为空,要么全身运动对所有制载波影响相同。源码测试
test_uniform_attention用全 1.0 相位/幅度输入验证了权重收敛于 0.125。 - 某个权重接近 1.0、其余接近 0.0:高度聚焦。活动集中于一个空间区域,
peak_group索引告诉你具体是哪个区域。测试test_focused_attention将子载波 12–16 置为 3.0,断言 peak 落在分组 3。 - 两个相邻分组同时升高:活动位于两个空间区域的边界,或有人在两者之间移动。
- 熵低于 1.0:强空间聚焦,适合做区域级定位。
- 熵高于 1.8:接近均匀,难以定位活动。
centroid(0.0 到 7.0)给出加权平均位置。随时间跟踪质心可以揭示横穿房间的运动方向。
Coherence Gate(sig_coherence_gate.rs)
功能:决定每帧入站 CSI 数据是否足够可信以用于感知,或应被丢弃。利用各子载波相位变化的统计一致性度量信号质量。
算法:每个子载波的相位增量构成单位相量(cos + i·sin),平均相量的模即相干性分数 [0,1]。Welford 在线统计跟踪均值/方差用于 Z-score 计算;迟滞状态机防止状态快速振荡。源码实现见 sig_coherence_gate.rs。
状态转换(与文档一致的实现细节):
- Accept → PredictOnly:连续 5 帧低于
LOW_THRESHOLD(0.40); - PredictOnly → Reject:单帧低于阈值;
- Reject/PredictOnly → Accept:连续 10 帧高于
HIGH_THRESHOLD(0.75); - 任意状态 → Recalibrate:运行方差超过初始快照的 4 倍。
实现中还有一个文档未强调的细节:方差漂移检测并非一上来就生效,而是需要先积累MIN_FRAMES_FOR_DRIFT = 50帧数据并捕获初始方差快照(variance_captured),这保证了基线统计的可靠性。每帧相位增量按子载波逐个计算cosf/sinf,这是其预算标记为 L(<2ms)却仍属"轻量"的原因。
公开 API
pub struct CoherenceGate { /* ... */ } impl CoherenceGate { pub const fn new() -> Self; pub fn process_frame(&mut self, phases: &[f32]) -> &[(i32, f32)]; pub fn gate() -> GateDecision; // Accept/PredictOnly/Reject/Recalibrate pub fn coherence() -> f32; // Last coherence score [0, 1] pub fn zscore() -> f32; // Z-score of last coherence pub fn variance() -> f32; // Running variance of coherence pub fn frame_count() -> u32; pub fn reset(&mut self); } pub enum GateDecision { Accept, PredictOnly, Reject, Recalibrate }GateDecision枚举提供了as_f32()方法(Accept=2.0 / PredictOnly=1.0 / Reject=0.0 / Recalibrate=-1.0),用于映射为事件数值。
事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 710 | GATE_DECISION | 2/1/0/-1 | Accept(2)、PredictOnly(1)、Reject(0)、Recalibrate(-1) |
| 711 | COHERENCE_SCORE | [0.0, 1.0] | 相位相量相干幅度 |
| 712 | RECALIBRATE_NEEDED | 方差 | 环境发生重大变化——需重训基线 |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
HIGH_THRESHOLD | 0.75 | 相干性高于此值 = 质量良好 |
LOW_THRESHOLD | 0.40 | 相干性低于此值 = 质量差 |
DEGRADE_COUNT | 5 | 降级前连续坏帧数 |
RECOVER_COUNT | 10 | 恢复前连续好帧数 |
VARIANCE_DRIFT_MULT | 4.0 | 触发重校准的方差倍数 |
MIN_FRAMES_FOR_DRIFT | 50 | 捕获初始方差快照所需的最小帧数 |
教程:使用 Coherence Gate
相干性门控保护下游模块不处理垃圾数据。实践中:
- Accept(值=2):帧干净。可用于所有感知任务(生命体征、存在检测、手势)。
- PredictOnly(值=1):帧质量边缘。使用此前帧的缓存预测,不更新模型。
- Reject(值=0):帧噪声过大。完全跳过,不馈入任何学习模块。
- Recalibrate(值=-1):环境发生根本性变化(家具移动、新 AP、门打开)。重置基线并重新学习。
源码测试覆盖了主要路径:test_coherent_stays_accept验证稳定相位下门控保持 Accept;test_recovery用RECOVER_COUNT + 5帧稳定数据验证从劣化状态恢复为 Accept;test_incoherent_degrades则用每帧大幅跳变的相位流验证门控降级逻辑。
低相干性的常见原因:
- 微波炉运行(2.4 GHz 干扰);
- 多人朝不同方向行走(相位抵消);
- 硬件故障(天线接触不良)。
Temporal Compress(sig_temporal_compress.rs)
功能:以压缩形式维护最多 512 个 CSI 快照的滚动历史。近期数据以高精度存储;越旧的数据逐步压缩以节省内存,同时保留长期趋势。
算法:三级量化,按年龄边界自动降级。源码实现(sig_temporal_compress.rs)中,push_frame以 Hot 精度写入后,在HOT_END、WARM_END边界处将对应槽位先反量化再以低精度重量化(dequantize→quantize),并发出TIER_TRANSITION事件:
| 层级 | 年龄范围 | 位宽 | 量化级别 | 最大误差 |
|---|---|---|---|---|
| Hot | 0-63(最新) | 8-bit | 256 | <0.5% |
| Warm | 64-255 | 5-bit | 32 | <3% |
| Cold | 256-511 | 3-bit | 8 | <15% |
以 20 Hz 帧率估算,缓冲区覆盖约:
- Hot:3.2 秒高保真数据;
- Warm:9.6 秒中保真数据;
- Cold:12.8 秒低保真数据;
- 总计约 25.6 秒,更低帧率下覆盖时间更长。
每个快照存储 8 个相位 + 8 个幅度值(分组均值),外加一个缩放因子与层级标签。Snap结构体为data: [u8; 16] + scale: f32 + tier + valid,共 24 字节(与性能预算表中的 512 × 24 字节对应)。量化采用对称有符号映射(v/scale归一化到 [-1,1]),缩放因子取本帧 16 个值的最大绝对值。
公开 API
pub struct TemporalCompressor { /* ... */ } impl TemporalCompressor { pub const fn new() -> Self; pub fn push_frame(&mut self, phases: &[f32], amps: &[f32], ts_ms: u32) -> &[(i32, f32)]; pub fn on_timer() -> &[(i32, f32)]; pub fn get_snapshot(age: usize) -> Option<[f32; 16]>; // Decompressed 8 phase + 8 amp pub fn compression_ratio() -> f32; pub fn frame_rate() -> f32; pub fn total_written() -> u32; pub fn occupied() -> usize; }帧率通过时间戳差 EMA 估计(RATE_ALPHA = 0.05,且只接受 0–5000 ms 的有效间隔),测试test_frame_rate以 50 ms 间隔(20 Hz)推入 100 帧,断言估计帧率落在 15–25 Hz。get_snapshot(0)返回最新快照,get_snapshot(CAP)返回None(环形缓冲区回绕后容量恒定 512,测试test_wrap验证)。
事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 705 | COMPRESSION_RATIO | 比值(>1.0) | 原始字节 / 压缩字节 |
| 706 | TIER_TRANSITION | 层级(1 或 2) | 快照降级为 Warm(1) 或 Cold(2) |
| 707 | HISTORY_DEPTH_HOURS | 小时 | 缓冲区覆盖的墙钟时间 |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
CAP | 512 | 快照总容量 |
HOT_END | 64 | 前 N 个快照使用 8-bit 精度 |
WARM_END | 256 | 快照 64-255 使用 5-bit 精度 |
RATE_ALPHA | 0.05 | 帧率估计的 EMA alpha |
HOT_Q/WARM_Q/COLD_Q | 255 / 31 / 7 | 各层量化级别 |
Sparse Recovery(sig_sparse_recovery.rs)
功能:当 WiFi 硬件丢弃部分子载波测量值(深衰落导致的 null/零值、固件故障或多径零点)时,该模块用数学优化重建缺失值。
算法:迭代收缩阈值算法(ISTA)——一种最小化 L1 的稀疏恢复方法。源码实现(sig_sparse_recovery.rs):
x_{k+1} = soft_threshold(x_k + step * A^T * (b - A*x_k), lambda)其中:
A是三对角相关模型(对角 + 直接邻居,96 个 f32,而非完整 32×32=1024);b是观测到的(非 null)子载波值;soft_threshold(x, t) = sign(x) * max(|x| - t, 0)促进稀疏性(源码 soft_threshold 函数,测试test_soft_threshold覆盖了正/负/阈值内三种情形);- 每帧最多 10 次迭代。
相关模型在完全有效的帧上在线学习:update_correlation对每个子载波 i 维护三个 EMA 混合乘积——自相关corr(i,i)、左邻居corr(i,i-1)、右邻居corr(i,i+1),对应NEIGHBORS = 3的紧凑存储。ISTA 迭代中,null 子载波先用recent_valid(最近一次有效帧的值)初始化,再在观测位置计算残差、以三对角结构完成 A 与 Aᵀ 的矩阵向量乘。
公开 API
pub struct SparseRecovery { /* ... */ } impl SparseRecovery { pub const fn new() -> Self; pub fn process_frame(&mut self, amplitudes: &mut [f32]) -> &[(i32, f32)]; pub fn dropout_rate() -> f32; // Fraction of null subcarriers pub fn last_residual_norm() -> f32; // L2 residual from last recovery pub fn last_recovered_count() -> u32; // How many subcarriers were recovered pub fn is_initialized() -> bool; // Whether correlation model is ready }注意:process_frame就地修改amplitudes—— null 子载波会被恢复值覆盖。测试test_recovered_values_nonzero验证了这一点。
事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 715 | RECOVERY_COMPLETE | 数量 | 恢复的子载波数量 |
| 716 | RECOVERY_ERROR | L2 范数 | 恢复的残差误差 |
| 717 | DROPOUT_RATE | 分数 [0,1] | null 子载波占比(每 20 帧发出一次) |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
NULL_THRESHOLD | 0.001 | 幅度低于此值视为丢失 |
MIN_DROPOUT_RATE | 0.10 | 触发恢复的最低丢失比例 |
MAX_ITERATIONS | 10 | 每帧 ISTA 迭代上限 |
STEP_SIZE | 0.05 | 梯度下降学习率 |
LAMBDA | 0.01 | L1 稀疏惩罚权重 |
CORR_ALPHA | 0.05 | 相关模型更新的 EMA alpha |
NEIGHBORS | 3 | 每个子载波存储的邻居相关项数 |
教程:恢复何时介入
- 模块需要至少 10 个完全有效的帧来初始化相关模型(
is_initialized() == true,源码中valid_frame_count >= 10置位,测试test_correlation_model_builds验证); - 仅当丢失超过 10% 时恢复才触发(如 32 个子载波中 ≥4 个为 null)。测试
test_no_recovery_below_threshold以 16 个子载波中 1 个 null(6.25%)验证不触发; - 低于 10% 时,null 过于稀疏,不值得承担恢复开销;
- 三对角相关模型利用了相邻 WiFi 子载波高度相关的特性——子载波 15 的 null 可从子载波 14 和 16 估计;
- 监控
RECOVERY_ERROR——残差上升提示相关模型已陈旧、环境已变化。
Min-Cut Person Match(sig_mincut_person_match.rs)
功能:为感知区域内最多 4 人维护稳定的身份标签。人员移动时其 WiFi 签名位置随之变化——该模块跟踪每个签名属于哪个人,跨连续帧保持身份一致。
算法:灵感来自ruvector-mincut(DynamicPersonMatcher)的移植,源码见 sig_mincut_person_match.rs。每帧执行:
- 特征提取:对每个检测到的人,从其空间区域提取前 8 大子载波方差(降序排列),得到 8 维签名向量。
extract_features使用选择排序风格逐位挑选最大值(测试test_extract_features_sorted验证输出降序且最大值正确); - 代价矩阵:计算所有当前特征与所有已存签名之间的 L2 距离;
- 贪心分配:选取最小代价的(检测, 槽位)对,标记两者已用,重复。类似简化版匈牙利算法,对最多 4 人最优。
greedy_assign中代价超过MAX_MATCH_DISTANCE即中断,未匹配的检测优先分配给未激活槽位; - 签名更新:通过 EMA(alpha=0.15)将新特征混合进已存签名;
- 超时:缺席 100 帧后释放槽位。
公开 API
pub struct PersonMatcher { /* ... */ } impl PersonMatcher { pub const fn new() -> Self; pub fn process_frame(&mut self, amplitudes: &[f32], variances: &[f32], n_persons: usize) -> &[(i32, f32)]; pub fn active_persons() -> u8; pub fn total_swaps() -> u32; pub fn is_person_stable(slot: usize) -> bool; pub fn person_signature(slot: usize) -> Option<&[f32; 8]>; }测试覆盖:test_two_persons_distinct_signatures用两个方差分布差异极大的人验证 20 帧内维持 2 个激活槽位且零交换;test_person_timeout验证缺席ABSENT_TIMEOUT + 1帧后槽位被释放;test_too_few_subcarriers验证子载波数少于特征维度 8 时返回空。
事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 720 | PERSON_ID_ASSIGNED | person_id + confidence*0.01 | 分配的槽位(整数部分)与匹配置信度(小数部分) |
| 721 | PERSON_ID_SWAP | prev*16 + curr | 检测到身份交换(前后槽位索引编码) |
| 722 | MATCH_CONFIDENCE | [0.0, 1.0] | 所有检测人员的平均匹配置信度(每 10 帧发出) |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
MAX_PERSONS | 4 | 最大并发人员跟踪数 |
FEAT_DIM | 8 | 签名向量维度 |
SIG_ALPHA | 0.15 | 签名更新的 EMA 混合因子 |
MAX_MATCH_DISTANCE | 5.0 | 有效匹配的 L2 距离阈值 |
STABLE_FRAMES | 10 | 跟踪被视为稳定的所需帧数 |
ABSENT_TIMEOUT | 100 | 释放槽位前的缺席帧数(20 Hz 下约 5 秒) |
Optimal Transport(sig_optimal_transport.rs)
功能:检测传统基于方差的检测器会错过的细微运动。计算帧间 WiFi 信号分布整体形状的变化量——即使总功率保持不变也能捕捉。
算法:Sliced Wasserstein 距离——完整 Wasserstein(推土机)距离的计算高效近似。源码实现(sig_optimal_transport.rs):
- 生成 4 个固定随机投影方向(LCG 伪随机数发生器,种子
[42, 137, 2718, 31415],编译期const fn gen_proj()计算并 L2 归一化,归一化用 6 次牛顿-拉弗森迭代求平方根倒数); - 将当前与上一帧幅度向量投影到每个方向;
- 排序投影值(Ciura 间隔序列的 Shell 排序,O(n^1.3),
GAPS = [10, 4, 1]——对 n=32 将最坏比较次数从约 1024 降到约 128); - 计算排序后投影间的 1D Wasserstein-1 距离(即平均绝对差);
- 对 4 个投影取平均;
- EMA 平滑后与阈值比较。
细微运动检测:当 Wasserstein 距离升高(分布形状改变)而方差保持稳定(总功率不变)时,说明有物体移动却未造成明显扰动——例如缓慢的手部动作、呼吸、或门慢慢关闭。
公开 API
pub struct OptimalTransportDetector { /* ... */ } impl OptimalTransportDetector { pub const fn new() -> Self; pub fn process_frame(&mut self, amplitudes: &[f32]) -> &[(i32, f32)]; pub fn distance() -> f32; // EMA-smoothed Wasserstein distance pub fn variance_smoothed() -> f32; // EMA-smoothed variance pub fn frame_count() -> u32; }事件
| ID | 名称 | 值 | 含义 |
|---|---|---|---|
| 725 | WASSERSTEIN_DISTANCE | 距离 | 平滑后的 sliced Wasserstein 距离(每 5 帧发出) |
| 726 | DISTRIBUTION_SHIFT | 距离 | 检测到大幅分布变化(去抖:连续 3 帧 > 0.25) |
| 727 | SUBTLE_MOTION | 距离 | 方差稳定时仍检测到运动(连续 5 帧距离 > 0.10 且方差变化 < 15%) |
配置常量
| 常量 | 值 | 用途 |
|---|---|---|
N_PROJ | 4 | 随机投影方向数量 |
ALPHA | 0.15 | 距离平滑的 EMA alpha |
VAR_ALPHA | 0.1 | 方差平滑的 EMA alpha |
WASS_SHIFT | 0.25 | 分布移事件的水深距离阈值 |
WASS_SUBTLE | 0.10 | 细微运动的水深距离阈值 |
VAR_STABLE | 0.15 | "稳定"分类的最大相对方差变化 |
SHIFT_DEB | 3 | 分布移去抖计数 |
SUBTLE_DEB | 5 | 细微运动去抖计数 |
教程:解读 Wasserstein 距离
Wasserstein 距离度量将一个分布转换为另一个分布的"代价"。与只度量离散程度的方差类指标不同,它捕捉形状、位置与模态结构的变化。
典型取值:
- 0.00-0.05:无运动。静态环境。
- 0.05-0.15:呼吸、轻微身体摇摆、环境漂移。
- 0.15-0.30:行走、手臂运动、正常活动。
- 0.30+:大幅运动、多人移动、或突发环境变化。
"细微运动"为何重要:一个人静坐并缓慢抬手几乎不改变总信号方差,但 Wasserstein 距离会上升,因为信号强度的空间分布发生了位移。这对以下场景至关重要:
- 跌倒检测(跌倒前的摇摆);
- 手势识别(微动作);
- 入侵者检测(有人试图潜行移动)。
性能预算
| 模块 | 预算级别 | 典型延迟 | 栈内存 | 关键瓶颈 |
|---|---|---|---|---|
| Flash Attention | S(<5ms) | ~0.5ms | ~512 字节 | 8 个分组上的 Softmax exp() |
| Coherence Gate | L(<2ms) | ~0.3ms | ~320 字节 | 每子载波 sin/cos |
| Temporal Compress | S(<5ms) | ~0.8ms | ~12 KB | 512 快照 × 24 字节 |
| Sparse Recovery | H(<10ms) | ~3ms | ~768 字节 | 10 次 ISTA 迭代 × 32 子载波 |
| Min-Cut Person Match | H(<10ms) | ~1.5ms | ~640 字节 | 4×4 代价矩阵 + 特征提取 |
| Optimal Transport | S(<5ms) | ~1.5ms | ~1 KB | 8 次 Shell 排序(4 投影 × 2 分布) |
以上延迟为 ESP32-S3 运行 WASM3 解释器、240 MHz 主频下的估算值。实际性能随子载波数量与帧复杂度变化。
内存布局与部署约束
所有模块使用定长栈/静态分配。无堆、无alloc、无Vec。这是no_stdWASM 部署到 ESP32-S3 的硬性要求——文档的模块开发约束(见 Edge Intelligence Modules 文档)明确规定:使用定长数组而非Vec/String,数学函数使用libm,预算级别 L(<2ms)/S(<5ms)/H(<10ms)每帧,每个模块 WASM 二进制 5–30 KB。
6 个信号模块的总静态内存约 15 KB,远在 ESP32-S3 可用 WASM 线性内存范围内。
构建与测试(来自 Edge Intelligence Modules 快速开始):
# 为 ESP32 构建全部模块 cd v2/crates/wifi-densepose-wasm-edge cargo build --target wasm32-unknown-unknown --release # 运行全部 632 个测试(信号智能组 54 个) cargo test --features std总结
Signal Intelligence 六模块构成了 RuView 边缘 WiFi 感知的数据质量闭环:Coherence Gate 在最前端拒绝脏帧并管理环境漂移,Sparse Recovery 填补硬件丢点,Flash Attention 定位空间焦点,Temporal Compress 以三档精度保存 25 秒级滚动历史,Min-Cut Person Match 与 Optimal Transport 则分别输出跨帧稳定的人员身份与方差不可见却空间可感的细微运动。所有实现均遵循no_std、const fn、定长数组的约束,可在 ESP32-S3 的 WASM3 运行时中以亚毫秒到 3 毫秒的延迟完成每帧处理——这正是"零像素视频、纯 WiFi 信号"空间智能愿景在边缘侧得以落地的工程基石。相关设计决策可进一步查阅 ADR-039(边缘智能层级)、ADR-040(WASM 运行时设计) 与 ADR-041(模块规格全集)。
【免费下载链接】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),仅供参考