RuView 原生 RF 帧契约 RfFrameV2:以保留原生采样的权威帧结构取代统一规范张量
导读
在 RuView(π RuView,将商用 WiFi 信号转化为空间智能、生命体征与存在感知的射频感知项目)的 ruview-unified Rust 工作区中,ADR-279 定义了一个架构级修正:权威数据格式不再是把每种设备都重采样成 56-bin × 8-snapshot 的规范张量(RfTensor),而是保留设备原生采样的 RfFrameV2 原生帧。本篇文章以 ADR-279-native-rf-frame-contract.md 为骨架,结合 frame.rs、tensor.rs、adapters.rs 与 eval.rs 的源码实现,系统讲解 RfFrameV2 的字段契约、七条强制不变量、规范张量如何被降级为只读派生视图,以及配套的反泄漏数据划分清单。读完本文,你将掌握如何理解、构造并验证一个符合 RuView 证据纪律的原生 RF 帧,以及为什么"先保留原生数据、再按需派生规范视图"是射频感知系统避免信息丢失的正确架构选择。
1. 背景:一次对规范张量的架构修正
1.1 旧的假设(ADR-274)与其代价
ADR-279 之前,ADR-274 把 56 × 8 的规范 RfTensor 当作适配器输出:所有设备(CSI、SRS、FMCW、UWB、BLE-CS)都被归一化进同一个 (links × bins × snapshots) 复张量。这在兼容性上是正确的——下游 tokenizer、encoder、Gaussian memory 永远只看到一个厂商无关的格式(见 tensor.rs 头部注释),但从信息保真角度它是错误的权威格式,因为:
- 重采样会丢失带宽信息:一段 320 MHz 的 802.11bk 采集与一段 20 MHz 的 802.11n 采集被压进同一张量后变得不可区分;
- 会丢弃天线结构、相位状态、硬件特有信息——而这些恰恰是基础编码器(foundation encoder)应当学习的先验;
- 其教训被称为"WiLLM 教训":正确的做法是让每种设备只经过一个轻量级 per-device 适配器(adapter)进入共享的 latent 空间,而不是进入一个共享的物理张量。
文档还以 RuView 自身历史佐证过早规范化(premature canonicalization)的代价:MERIDIAN 的 normalizer 之所以仍然有用,正是因为原生数据当时还在。一旦原生数据被抹掉,事后任何规范化工具都无法找回丢失的信息。
1.2 ADR-279 的定位:在数据债务累积前修正
这是一份修正型(correction)ADR:修正 ADR-274 §2 的结论,并且是在"可测量的数据债务累积之前"采纳(采用 ADR-273 的证据分级纪律)。它与 ADR-136(CanonicalFrame——是扩展而非取代)、ADR-262(溯源纪律)、ADR-282(证据阶梯策略)关联。
2. RfFrameV2:权威记录保留原生采集
2.1 数据结构总览
RfFrameV2 的权威地位在源码中被明确注释(frame.rs):schema 版本、帧 ID、时间戳、模态、声明式原生轴、中心频率/带宽/采样率、任意秩的原生张量与显式有效性掩码、TX/RX 位姿、天线单元几何、样本年龄、校准状态(含相位状态声明)、信号质量与帧溯源。字段如下:
| 字段 | 类型 / 取值 | 语义 |
|---|---|---|
schema_version |
u16(当前 SCHEMA_VERSION = 2) |
帧契约版本,见 frame.rs |
frame_id |
u128 |
唯一帧标识 |
timestamp_ns |
u64 |
自 epoch 起的采集时间戳(ns) |
modality |
RfModality |
感知模态(见下) |
axes |
Vec<FieldAxis> |
原生轴语义,每个维度对应 native_shape 的一个维度 |
centre_frequency_hz |
f64 |
载波中心频率(Hz) |
bandwidth_hz |
f64 |
占用带宽(Hz) |
sample_rate_hz |
f64 |
类时间轴原生采样率(Hz) |
native_shape |
Vec<usize> |
原生张量形状(任意秩) |
native_iq |
Vec<Complex64> |
原生复采样——永不被覆盖(不变量 1) |
valid_mask |
Vec<bool> |
逐样本有效性掩码,长度与 native_iq 一致(不变量 2) |
transmitter_pose / receiver_pose |
Option<Pose3> |
同一建筑坐标系中的 TX/RX 位姿(不变量 4) |
antenna_geometry |
Vec<AntennaElement> |
接收阵列的天线单元几何 |
sample_age_ns |
u64 |
采集在交棒时的年龄(ns)(不变量 7) |
calibration |
CalibrationState |
校准状态,含 PhaseState 声明(不变量 3) |
quality |
SignalQuality |
前端信号质量 |
provenance |
FrameProvenance |
溯源:类/证据级别/设备/固件/收据 ID(不变量 5–6) |
2.2 模态集合:RfModality
与 ADR-274 时代相比,模态枚举在 tensor.rs 中扩展了 WifiCir、WifiBfReport、FmcwRangeAzimuth、FmcwDopplerAzimuth,完整列表为:
| 模态 | 含义 |
|---|---|
WifiCsi |
802.11 每子载波信道状态信息(频域响应) |
WifiCir |
802.11 信道冲激响应(时延域 tap) |
WifiBfReport |
802.11 波束成形反馈报告(BFI/BFLD 链路) |
CellularSrs |
5G NR 上行探测参考信号频响(O-RAN ISAC 路径) |
FmcwRadar |
FMCW 雷达距离剖面(range-FFT 后复 bin) |
FmcwRangeAzimuth |
FMCW 雷达距离–方位角图 |
FmcwDopplerAzimuth |
FMCW 雷达多普勒–方位角图 |
UwbCir |
超宽带信道冲激响应 tap |
BleCs |
蓝牙信道探测 tone(基于相位的测距 + RTT) |
Synthetic |
ADR-276 合成世界生成器输出(诚实标注:此类张量绝不报告为实测) |
2.3 声明的原生轴:FieldAxis
任意秩的原生张量需要一个"每个维度代表什么"的显式声明,FieldAxis 在 frame.rs 中提供九种轴语义:Time(采样时间)、Frequency(子载波/频率)、Delay(时延,多径到达)、Doppler(多普勒频移)、Range(雷达距离 bin)、Azimuth(方位角)、Elevation(俯仰角)、Antenna(天线单元)、Polarization(极化)。注释特别说明:像 OTFS ISAC 这类时延-多普勒原生模态不能被折叠成标量运动能量后再存储(关联 ADR-281 §3)——这就是需要任意秩 native_shape 的原因。
2.4 几何与天线:Pose3 与 AntennaElement
Pose3(frame.rs):建筑坐标系中的位姿,position_m: [f64; 3](米)+orientation: [f64; 4](单位四元数[w,x,y,z])。AntennaElement(frame.rs):每个天线单元相对设备位姿的位置(米)与增益(dBi)。
"同一个建筑坐标系"这一要求直接来自不变量 4——TX 与 RX 的位姿必须处于同一坐标系中,否则多链路几何计算(例如 LinkGeometry::distance_m(),见 tensor.rs)将失去意义。
2.5 校准状态与信号质量
CalibrationState(frame.rs)携带:phase_state(相位状态,见第 4 节)、gain_calibrated(幅度增益是否已校准)、clock_ppm(振荡器漂移)、baseline_id(若应用了空房间基线则记录其 ID,关联 ADR-135)、confidence(校准置信度,必须在 [0,1],构造器强制校验)。
SignalQuality(frame.rs)记录:rssi_dbm、noise_floor_dbm、packet_loss(捕获窗口内预期丢包比例,[0,1])、interference(干扰评分,[0,1],0 = 干净)。这些量不但在采集侧可用于质量门控,还参与派生视图时的不确定性估计(见第 6.3 节)。
3. 七条强制不变量:从文档到构造器与测试
ADR-279 §2 给出七条不变量,其中一部分由校验过的构造器 RfFrameV2::new 在运行时强制执行,另一部分由测试证明。构造器内实际执行的全部边界规则位于 frame.rs:
| # | 不变量 | 执行方式(源码依据) |
|---|---|---|
| 1 | 原生采样永不覆盖 | to_canonical(&self) 只读、不写回(frame.rs);测试 canonical_view_is_derived_and_native_is_untouched 在派生后断言 native_iq 与 valid_mask 逐字节相同(frame.rs) |
| 2 | 子载波/天线掩码显式且长度匹配 | 构造器校验 native_shape 非空、元素积非零、native_iq.len() 与 valid_mask.len() 均等于形状元素积、axes.len() == native_shape.len()(秩匹配)(frame.rs);测试 constructor_enforces_shape_mask_and_axes_arity |
| 3 | 相位声明其状态 | PhaseState 枚举(第 4 节),消费方不再猜测是否做过去趋势 |
| 4 | TX/RX 几何用同一建筑坐标系 | 统一 Pose3 类型 + 派生视图要求 rank-3 与 links.len() == n_links 几何匹配 |
| 5 | 结果保留源身份 receipt_id |
FrameProvenance.receipt_id: u128,供 Gaussian memory 的 source_receipts 谱系消费(关联 ADR-275) |
| 6 | 合成帧与实测帧永不共享溯源类 | 证据规则 Synthetic ⇒ 恰好 L0Simulation、Measured ⇒ ≥ L1CapturedReplay,双向均在构造期拒绝(见第 5 节) |
| 7 | 采样年龄贯穿全链路 | sample_age_ns → 张量 → 年龄门 → BoundedEvent |
除掩码/形状外,构造器还会拒绝:频率与采样率非有限/非正(frame.rs)、被标记为有效的非有限复采样(frame.rs)、越界校准置信度(frame.rs)。也就是说,RfFrameV2::new 是唯一构建合法原生帧的入口,非法状态在源头即被类型化错误(UnifiedError::ShapeMismatch / InvalidInput)拒绝。
4. 相位状态声明:消费方停止"猜相位"
CSI 等模态的相位历史处理链非常复杂(CFO/STO 伪影 → 去线性斜坡 + 去常量偏移 → 硬件/基线校准),如果帧不声明自己处于哪个阶段,下游消费者只能靠猜。
PhaseState(frame.rs)用四个变体消除歧义:
| 变体 | 含义 |
|---|---|
Raw |
按采集原样;存在 CFO/STO 伪影 |
Sanitized |
已移除线性斜坡 + 常量偏移(ADR-274 阶段 3 的去趋势) |
Calibrated |
上游已做硬件/基线校准 |
Unavailable |
仅幅度捕获(例如某些厂商的 RSSI/BF 报告) |
该枚举配合 CalibrationState 的其它字段形成帧级"校准契约"。消费端根据它决定行为——例如在 to_canonical 派生视图时,只有当相位状态是 Sanitized 或 Calibrated 时才跳过相位去趋势步骤(frame.rs 中 matches!(...) 决定传入 normalize_grid 的 phase_calibrated 标志)。
5. 证据阶梯与溯源:合成与实测永不混淆
5.1 FrameProvenance 与证据级别
每帧携带 FrameProvenance(frame.rs):
class: ProvenanceClass——只有两态Measured(真实硬件捕获)与Synthetic(模拟器/生成器产出,ADR-276),没有第三个变体,也没有默认值(frame.rs);evidence: EvidenceLevel——公开证据阶梯(ADR-282 §4):L0Simulation→L1CapturedReplay→L2Lab→L3HeldOutValidation→L4MultisiteField→L5Production(frame.rs),任何能力、任何数据集只能取恰好一级;device_id、firmware(设备/固件标识)、receipt_id(把推理结果关联回源帧)。
5.2 构造期的双向证据规则(不变量 6)
构造器中的 match 逻辑(frame.rs)把文档规则变成代码:
Synthetic+ 任何高于L0Simulation的证据级别 → 拒绝("synthetic frames are L0Simulation by definition");Measured+L0Simulation→ 拒绝("measured frames cannot claim L0Simulation")。
测试 synthetic_and_measured_provenance_can_never_alias(frame.rs)覆盖了这四个组合:两类非法配对返回 Err,两个合法配对(Synthetic+L0Simulation、Measured+L1CapturedReplay)返回 Ok。由此,合成证据永远无法伪装成现场证据,反之亦然——这是诚实标注(honest labeling)与证据阶梯策略的核心机制。
6. 规范张量降级为"兼容派生视图"
6.1 to_canonical:同一段归一化代码,许多入口
RfFrameV2::to_canonical(&self)(frame.rs)只接受 rank-3(links, bins, snapshots) 的原生帧,并把它送入与每个硬件适配器完全相同的归一化代码路径——adapters::normalize_grid(crate 内可见,见 adapters.rs,注释明确说明这是"one normalization, many entry points",即 ADR-279 §3 的实现)。非 rank-3 帧(例如延迟-多普勒原生模态、秩 1 的纯频率帧)没有规范投影,并会返回类型化错误:"canonical view needs a rank-3 (links, bins, snapshots) frame, got rank N"。
6.2 掩码感知的缺口填补(mask-aware gap-filling)
派生前必须先处理无效 bin:对每个 (link, snapshot) 列,收集有效 bin 索引,若某列完全没有有效 bin 则报错;对每个无效 bin,在复平面(complex plane)上取最近的前后有效邻域做线性插值填补(frame.rs)。测试 canonical_view_is_derived_and_native_is_untouched 用 114 子载波、挖掉两个 bin 的帧验证:派生后张量为 (1, 56, 8) 且所有采样有限,同时原生采样与掩码保持逐字节不变。
6.3 与 normalize_grid 的三阶段流水线对齐
normalize_grid 的标准流水线(adapters.rs 的模块注释 + adapters.rs)为:
- 布局(Layout):把厂商捕获整形为
(links, bins, snapshots)(FMCW 雷达含 fast-time DFT 到距离 bin),然后把 bin 轴与 snapshot 轴重采样到CANONICAL_BINS(56) × CANONICAL_SNAPSHOTS(8)(常量定义见 tensor.rs,56 对应 20 MHz 802.11n CSI 去保护间隔后的可用子载波数,故最常见来源甚至无需重采样); - 幅度(Amplitude):每个 link 除以其幅度中位数,消除芯片间前端增益差,偏移量记录进
CalibrationMeta::gain_offset_db供溯源; - 相位(Phase):对每个
(link, snapshot)用最小二乘去掉跨 bin 的常量相位偏移(CFO 残差)与线性斜坡(采样时刻偏移)——除非捕获声明自身已相位校准。
当 to_canonical 调用它时,还会从帧字段推导两个 [0,1] 输入:clock_quality(由 clock_ppm 映射)与 uncertainty(由 rssi - noise_floor 信噪比映射,见 frame.rs)。因此派生视图不是另一个不透明重采样器,而是与所有适配器共享同一套经过验证的归一化语义,只是把"存储格式"变成了"按需计算、只读、永不写回"。
6.4 既有 114→56 投影不变
文档明确说明:已有的 ESP32/Intel/Atheros 114→56 子载波投影保持不变,它们只是不再是存储格式——仍然作为归一化阶段的既有适配路径存在于 wifi_densepose 生态(wifi_densepose_core::types::CsiFrame 是 RawCapture::WifiCsi 的载体,见 adapters.rs)。
7. 强制划分清单:让"无泄漏结果"成为可证属性
7.1 PartitionKey 新增 session 维度
RF 感知结果最常见的失败模式是领域泄漏伪装成精度(eval.rs)。ADR-279 §4 把"泄漏规则"变成了代码:PartitionKey(eval.rs)覆盖全部七个维度——room(房间)、day(天)、person(人)、chipset(芯片组)、firmware(固件)、layout(天线布局),并新增 session(捕获会话)。注释点明了动机:"包级会话泄漏与房间泄漏同样真实"(packet-session leakage is as real as room leakage)。
7.2 SplitManifest:逐维度不相交证书
SplitManifest::build(eval.rs)对 PartitionDim::ALL(七维,eval.rs)逐一计算训练集与测试集取值集合的 BTreeSet 交集,得到 (dimension, disjoint) 证书向量。核心判据为:
train_rooms ∩ test_rooms = ∅ … train_sessions ∩ test_sessions = ∅
fully_disjoint()(eval.rs)要求七个维度全部不相交,才允许把结果报告为"抗泄漏(leakage-resistant)"。反过来,一个只按房间留出、但跨集共享了人的划分,其 manifest 会如实说明 Person 维度不相交为 false,而不是假装完全无泄漏——这正是测试 split_manifest_certifies_per_dimension_disjointness(eval.rs)所断言的:rooms/sessions 不相交,但 people/chipsets 共享,因此 fully_disjoint() 返回 false。
配套机制还有 StrictSplit::holdout(按完整维度值留出、构造即保证不相交)与 StrictSplit::verify(独立复核任何被改动过的划分,eval.rs),后者由测试 verify_catches_a_manufactured_leak 验证——人为把一条测试样本塞进训练集即被检出。
另注意 ADR-279 强调:隐藏的真实世界测试集(synthetic 生成/校准永远无法访问的那部分)是流程性要求,记录于 ADR-282 §4,而非本 ADR 的数据结构范畴。
8. 落地后果与后续路径
ADR-279 §5 从三个方向说明采纳后的工程后果:
- 新硬件以"producer + latent adapter"落地:PicoScenes、Intel、Atheros、Realtek 雷达、320 MHz 802.11bk 等新硬件,一律先作为
RfFrameV2producer 入帧,再接入 latent adapter——接入时什么都不丢。厂商一致性收据(vendor conformance receipt)就是构造器的七条不变量:原生形状被保留、相位状态已声明、时间戳单调、几何存在、损耗已测量、合成标志正确。 - 编码器输入契约今天不变:ADR-274 的编码器输入契约当前仍消费派生视图(规范张量);把 tokenizer 迁移到原生分辨率 token 被标记为后续工作项(P2),要等真实多带宽数据出现后才实施——即"现在不冻结尚不存在的输入形态"。
- 存储代价上升是可接受的:因为原生 + 派生双份存储中,派生视图随时可以重算,原生数据永远无法重得。
配合该契约的还有同文件中的 IEEE P3162-profile 合成孔径信道探测数据集导入结构 SyntheticApertureSoundingDataset(frame.rs),它是"实测环境、模拟器与学习型 RF 场景模型之间的校准桥"(ADR-281 §5),同样带校验构造器(频率区间有序且为正、孔径几何非空、方向性 PDP 形状匹配且能量非负、可处理清单哈希)。
9. 验证方式:把不变量锁进测试
ADR-279 的状态行标注了"5 invariant tests"并以 MEASURED-CODE(实测代码)为证据等级。运行命令:
cargo test -p ruview-unified frame::
覆盖 5 项测试(均在 frame.rs 的 mod tests 中):
| 测试 | 验证内容 |
|---|---|
synthetic_and_measured_provenance_can_never_alias |
不变量 6:Synthetic+L3、Measured+L0 均被拒绝,两类合法配对通过 |
constructor_enforces_shape_mask_and_axes_arity |
不变量 2/秩匹配:掩码长度错误、轴数量与秩不符均返回 ShapeMismatch |
canonical_view_is_derived_and_native_is_untouched |
不变量 1:114 子载波 + 掩码挖洞 → 派生 (1,56,8) 视图后原生采样/掩码逐字节不变,valid_fraction 精确吻合 |
canonical_view_rejects_wrong_rank_or_geometry |
几何长度不匹配、秩 1 帧(合法原生帧但无规范投影)都被 to_canonical 拒绝 |
synthetic_aperture_profile_validates |
P3162 合成孔径导入配置:合法区间通过、乱序频率区间被拒 |
这些测试与 e2e_acceptance.rs 一起构成"契约即代码"的回归防线:任何未来改动如果破坏了原生采样完整性、掩码/形状一致性或合成/实测边界,都会在测试层直接暴露。
10. 结语:把"规范化"放回它应在的位置
RfFrameV2 的架构主张可以浓缩为一句话:规范化(normalization)是派生行为,不是存储行为。 RuView 用一份修正型 ADR + 一份 frame.rs 实现,把"权威数据 = 保留原生带宽/天线/相位/硬件信息的原生帧"落成代码:显式的轴声明与有效性掩码保护原生形状,相位状态声明与证据级别规则让消费方不再猜测、让合成/实测永不混淆,只读的 to_canonical 与共享的 normalize_grid 保证兼容视图与全部硬件适配器语义一致,而七维划分清单把"报告抗泄漏结果"从口号变成可机械验证的 fully_disjoint()。对于任何多硬件射频感知系统,这套"原生为权威、规范为视图"的契约设计,都是一份值得直接借鉴的工程模板。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00