首页
/ RuView 为 RTL8720F FMCW 雷达定义版本化线协议:RtlRadarFrameV1 信封设计、传输与 Rust 解析器解析

RuView 为 RTL8720F FMCW 雷达定义版本化线协议:RtlRadarFrameV1 信封设计、传输与 Rust 解析器解析

2026-09-08 20:06:16作者:沈韬淼Beryl

导读

RuView 通过 ADR-263 引入 Realtek RTL8720F 2.4 GHz FMCW 雷达作为可选的感知平台,而 ADR-264-rtl8720f-radar-wire-protocol.md(本文的骨架文档)则决定在"反腐化边界"上为 CFR(Channel Frequency Report)与近/远 Range-FFT 上报定义一套 独立的、带版本、小端序、带 CRC 的 RtlRadarFrameV1 信封。读完本文你将掌握:RTL8720F 雷达报文从字节布局、载荷语义到 UDP / 串口 / 回放三种传输方式的完整契约;宿主解析器的安全校验与信任规则;以及在真实硬件与厂商 SDK 尚未到达时,如何用仓库内已落地的 Rust 编解码器、确定性模拟器、模糊测试与回放 CLI 先行打通整条数据链路。

背景:为什么不能直接复刻 Realtek 的二进制布局

ADR-263 所引用的 Realtek RTL8720F-2.4G-Radar-Advantages_EN.pptx 只描述了能力(CFR、近/远 Range-FFT、干扰上报、20/40/70 MHz 扫频、8/16/32/64 µs chirp 等),并未给出任何二进制 ABI:没有头文件名、函数签名、回调内存布局或报文结构。同时上游 Ameba RTOS 公开仓库(v1.2.1)只包含 CSI 修复,PR #1336 才暴露 wifi_radar_configAT+RAD 命令,而报表接收仍依赖 wifi_hal_radar_recv_data(...) 这类非公开/占位 HAL 符号。

因此 ADR-264 需要回答两个问题:

  1. RuView 需要一个稳定、可测试、可在厂商 SDK 到达前实现的契约;
  2. 该契约不能在网络上暴露厂商结构体、指针布局、内存填充或回调生命周期规则

另一个关键约束来自 ADR-018(ESP32 CSI 帧格式):虽然同属 2.4 GHz 频段,但 RTL8720F 是有源单站 FMCW 雷达,ESP32 路径观察的是 Wi-Fi 数据包 CSI。若直接复用 ADR-018 的 magic 或把 Realtek 雷达伪装成 ESP32 数据包,会导致"数据源识别歧义"并丢失雷达专属的标定元数据。ADR-264 明确拒绝了这条捷径。

决策总览:RuView 自有协议而非厂商内存视图

ADR-264 的核心决策是一句话:定义一个新的小端序 RtlRadarFrameV1 信封,使用独立 magic 与显式载荷类型。这是 RuView 自己的协议,不是对 Realtek 原生内存布局的断言。

实现上的铁律是:

  • 所有整数字段均为小端序(little-endian);
  • 浮点载荷使用 IEEE-754 binary32
  • 任何 C struct 都不允许通过 memcpy 直接发送;固件必须逐字段显式序列化。

该原则在仓库源码中落地为 v2/crates/wifi-densepose-hardware/src/rtl8720f.rs 模块的文件头注释:"This is a RuView-owned wire contract around the public Ameba API boundary, not a representation of Realtek's private structs"。该模块被 v2/crates/wifi-densepose-hardware/src/lib.rspub mod rtl8720f 导出,并在 lib.rs 中通过 pub use rtl8720f::{...} 公开 Rtl8720fRadarFrameRtl8720fReportTypeRtl8720fRadarFlags 等类型别名,可供同 crate 与下游直接使用。

V1 信封:56 字节定长头 + 载荷 + CRC32

ADR-264 文档给出了完整的字节布局表,这是整个协议最核心的契约,必须原样保留:

Offset Size Field Meaning
0 4 magic ASCII RTR1 (0x31525452)
4 1 version 1
5 1 report_type 1 CFR, 2 range-near, 3 range-far, 4 interference, 5 capabilities
6 2 header_len complete header size, initially 56
8 4 frame_len header + payload + CRC
12 4 sequence wraps modulo 2^32
16 8 timestamp_us monotonic device time at acquisition
24 8 device_id stable pseudonymous identifier, not a MAC address
32 4 center_freq_khz RF centre frequency
36 2 bandwidth_mhz 20, 40, or 70
38 2 flags calibration/interference/saturation/time-sync flags
40 2 element_count complex samples or range bins
42 1 element_format 0 bytes/TLV, 1 complex-i16, 2 complex-f32, 3 power-u16, 4 power-f32
43 1 antenna_count expected to be 1 for the deck's 1T1R configuration
44 4 scale quantized-to-physical multiplier; 1.0 for float payloads
48 4 bin_spacing Hz for CFR, metres for Range-FFT
52 4 calibration_id device calibration revision/hash prefix
56 variable payload determined by type, count, and format
final-4 4 crc32 IEEE CRC-32 over header and payload

ADR 明确补充了设计取舍:若厂商证据表明 56 字节头代价过高,后续协议版本可引入紧凑头;V1 宁愿优先保证可审计的溯源,也不做过早的字节节省

源码层面对应着 rtl8720f.rs 的一组常量:

pub const RTL8720F_RADAR_MAGIC: u32 = 0x3152_5452; // "RTR1" in little endian
pub const RTL8720F_RADAR_VERSION: u8 = 1;
pub const RTL8720F_RADAR_HEADER_LEN: usize = 56;
pub const RTL8720F_RADAR_CRC_LEN: usize = 4;
/// Largest payload that can be carried in one IPv4 UDP datagram.
pub const RTL8720F_RADAR_MAX_FRAME_LEN: usize = 65_507;
pub const RTL8720F_RADAR_MAX_ELEMENTS: usize = 16_384;

注意两个安全边界常量:单帧上限 65 507 字节(一个 IPv4 UDP 数据报能容纳的最大载荷,即 65 535 - 20 IP 头 - 8 UDP 头)与最大元素数 16 384。这两者共同约束了长度算术的安全上界。CRC 实现位于 v2/crates/wifi-densepose-hardware/src/radio_ops.rs,文档注释说明它与 rv_feature_state.c 中的逐位实现一致:多项式 0xEDB88320、初值 0xFFFFFFFF、结果取反(即标准 IEEE CRC-32),且覆盖范围是 header + payload(不含 CRC 自身字段)

枚举与类型/格式组合是强校验对象

header 中 report_typeelement_format 两个枚举在源码中被建模为 Rust 枚举,非法值一律拒绝解析:

  • ReportTypeCfr = 1RangeNear = 2RangeFar = 3Interference = 4Capabilities = 5(见 rtl8720f.rs),其余值返回 UnknownReportType
  • ElementFormatBytes = 0(TLV/opaque)、ComplexI16 = 1ComplexF32 = 2PowerU16 = 3PowerF32 = 4,并据此推导每个元素的字节宽度:Bytes=1、ComplexI16/PowerF32=4、ComplexF32=8、PowerU16=2(见 rtl8720f.rs)。

更重要的是,ADR-264 要求做语义级类型/格式匹配,源码中的 validate_type_formatrtl8720f.rs)明确规定:

  • CFR 只允许 ComplexI16 | ComplexF32(复数信道频率样本);
  • RangeNear / RangeFar 只允许 PowerU16 | PowerF32(功率谱距离 bin);
  • Interference / Capabilities 只允许 Bytes(版本化 TLV)。

这样一来,任何一个把 CFR 声明为 power 类型、或把 range 声明为 complex 类型的畸形帧都会在解码前被 InvalidTypeFormat 拒绝——这是把"轴(axis)语义"直接写进协议层。

载荷语义:五类上报各自的物理含义

ADR-264 规定了每类 payload 的语义:

  • CFR 含有序的复数信道-频率样本。适配器必须知道频率起点/顺序,不得伪造缺失的相位;未标定帧会带 uncalibrated 标志,且不得进入任何相位敏感处理。源码中 RadarFlags::CALIBRATED 为 bit 0,未置位即视为不可信相位。
  • Range-near / range-far 含有序距离 bin。near 与 far 是独立的上报类型,因此滤波与泄漏行为永远不会对消费者隐藏。源码里模拟器对 RangeNear 在前 2 个 bin 叠加静态泄漏分量、对 RangeFar 则不叠加,正是这种区分的直观体现。
  • Interference 含一套版本化 TLV:channel-busy、detected-during-chirp、估计干扰功率、数据包抖动。未知 TLV 必须按长度跳过(长度字段前置于每个 TLV,保证向后兼容)。模拟器产出的干扰 TLV 为:type 1 = channel-busy 百分比、type 2 = 是否在 chirp 期间检测到干扰、type 3 = 有符号 dBm 干扰功率。
  • Capabilities启动时广播一次、也可按请求发出。它声明:支持的上报类型、带宽、chirp 长度、单帧最大元素数、最大帧率、固件版本与 SDK 标识。模拟器把能力集编码为紧凑 TLV:type 1 = 带宽位图(0b0000_0111 表示 20/40/70 MHz)、type 2 = CFR bin 数、type 3 = range bin 数、type 4 = 最小帧周期(µs)。启动能力帧让 SDK/API 漂移变成可观测事件:一旦真实 SDK 暴露的参数与启动帧声明不符,宿主可以立刻察觉。

flags 字段在源码 rtl8720f.rs 中有精确位义:bit 0 = CALIBRATED、bit 1 = INTERFERENCE_DETECTED、bit 2 = SATURATED、bit 3 = TIME_SYNCHRONIZED,且 bit 15 被 RuView 保留为 SYNTHETIC:Rust 模拟器生成的每一帧都必须置位它,真实固件则永远不得置位——这是"模拟数据绝不冒充硬件测量"的协议级兜底。

载荷元素的内存表示

源码用 RadarPayload 枚举表达五种载荷载体(rtl8720f.rs):Bytes(Vec<u8>)ComplexI16(Vec<[i16;2]>)ComplexF32(Vec<[f32;2]>)PowerU16(Vec<u16>)PowerF32(Vec<f32>)。序列化阶段全部走 to_le_bytes() 显式小端写出,没有任何一次按结构体 memcpy;解析阶段则对复数样本按 [I, Q] 交错的字节流切块重建。对 ComplexF32PowerF32,编码/解码都会执行 validate_finite,任何 NaN/Infinity 直接报 NonFiniteValue

传输层:同一信封走三种通道

ADR-264 规定同一份信封支持三种传输:

  1. UDP 数据报:用于常规 RuView 摄取。一条信封必须恰好装进一个 UDP 数据报,V1 不提供分片;固件会拒绝"最大上报超过配置 MTU"的 profile,并通过 capabilities 上报所需大小。
  2. USB CDC 或 UART:使用 COBS 成帧 + 零字节分隔符,解决串口通道的字节边界问题。
  3. 文件回放:长度前缀的连续信封序列(每条信封前跟一个长度字段)。

仓库中 v2/crates/wifi-densepose-hardware/src/bin/rtl8720f-sim.rs 是这三条传输路径的现成实现:它同时支持 --udp 127.0.0.1:PORT(一帧一个数据报)与 --output file(先写 LE u32 长度、再写帧字节,即"长度前缀序列")。每个测试会先发一条 capabilities_frame(),随后循环发出 CFR / RangeNear / RangeFar / Interference(每 16 帧中第 16 帧为干扰帧),并可加 --realtime 让每帧间隔 interval_ms 毫秒以模拟真实流速。--frames--seed 控制帧数与确定性随机种子。

其 CLI 参数全貌:

--frames N              # 发送的帧数(默认 100;另有 1 条启动 capabilities 帧)
--seed 0x...            # 确定性种子(默认 0x8720f123456789ab)
--bandwidth N           # 20 / 40 / 70 MHz(默认 40)
--interval_ms N         # 帧间隔毫秒(默认 15,转成 frame_period_us)
--udp IP:PORT           # UDP 目的地,每帧一个数据报(与 --output 至少选一)
--output PATH           # 回放文件,LE u32 长度 + ADR-264 帧字节
--realtime              # 按 interval_ms 实际睡眠节奏发送

硬件 crate 的 README 给出了 PowerShell 下的启动示例:

cargo run -p wifi-densepose-hardware --bin rtl8720f-sim -- `
  --frames 100 --seed 0x8720f123456789ab `
  --output rtl8720f-synthetic.rtr

--udp 127.0.0.1:5005 --realtime 即可按每 UDP 数据报一条 ADR-264 帧的方式实时推流。由于解析器是纯字节缓冲处理、无 C FFI 亦无硬件依赖,因此编译期可移植、运行结果确定——同样的字节进、同样的解析出。

v2/crates/wifi-densepose-sensing-server/src/main.rs 中,传感服务器用 RTL8720F_RADAR_MAX_FRAME_LEN 大小的缓冲区接收 UDP,先比对前 4 字节 RTL8720F_RADAR_MAGIC 完成协议分拣(与 Qualcomm QUALCOMM_CSI_MAGIC、MediaTek MEDIATEK_CSI_MAGIC 在同一接收循环并列,且服从 ADR-296 的源 IP 白名单过滤),随后调用 RadarFrame::from_bytes 解析,把结果转成有界摘要 RealtekRadarSnapshot 后:既在 /ws/sensing WebSocket 上推送 JSON,又通过 /api/v1/radar/latest 暴露最近一条上报(route 注册见 main.rs)。

v2/crates/wifi-densepose-sensing-server/src/realtek_radar.rs 实现了这份"有界、隐私友好的雷达摘要":RealtekRadarSnapshot 只暴露聚合量(峰值距离 peak_range_m、峰值功率、CFR 平均幅度),而不是把整帧复数谱上抛;source 字段在模拟帧上固定为 realtek:simulated,保证溯源标签端到端保留。其单元测试断言:Range 摘要必带峰且 source == "realtek:simulated"、CFR 摘要只暴露聚合幅度而峰值为 None

宿主解析器与信任规则:解码前的每一道闸门

ADR-264 为宿主解析器列了 7 条硬性信任规则,逐条都能在源码中对应:

  1. 在任何分配/解码载荷之前校验 magic、version、长度、枚举值、element_count × format 的乘法与 CRC。源码 from_bytesrtl8720f.rs)严格按序:先 InsufficientData 检查最小头长 → magic → version → report_type 枚举 → header_len(不得小于 56)→ frame_len(不得超 65 507,且必须 ≥ header+CRC)→ 缓冲区是否含完整 frame_len 字节 → element_count ≤ 16 384 → format 枚举 → 类型/格式语义匹配 → 用 checked_mul/checked_add 的溢出保护算术推导 payload_len 与 expected_len → 核对 expected_len == frame_len → CRC 比对。任何一步失败都返回带结构化上下文的 RadarParseError,绝不 panic。
  2. 帧上限 64 KiB、元素数上限为配置的硬件最大值:对应常量 RTL8720F_RADAR_MAX_FRAME_LEN = 65_507RTL8720F_RADAR_MAX_ELEMENTS = 16_384
  3. 拒绝非有限浮点scalebin_spacing 以及浮点载荷都过 is_finite() 检查。
  4. 按设备追踪 sequence 缺口与时间戳回退:V1 设计上 sequence 按 2^32 环绕、timestamp_us 为单调设备时钟,供上层检测丢帧与时钟异常(对应验收标准中的 gap / regression 检测)。
  5. 保留未知 flags 但永不当作可信解释RadarFlags 是对 u16 的位容器,解析器不抹除未知位,但只有已定义的位(标定、干扰、饱和、时间同步、synthetic)会进入下游语义。
  6. 把传输源、固件/SDK 版本、calibration ID、干扰状态附到溯源上RealtekRadarSnapshot 保留 device_id、center_freq、bandwidth、calibrated/synthetic/interference/saturated/time_synchronized、calibration_id、bin_spacing 等完整溯源字段。
  7. 把 fixture/生成帧标记为 synthetic:模拟器每帧强制 CALIBRATED | SYNTHETIC,服务器侧 source 恒为 realtek:simulated

ADR 收尾还写了一条不可让步的原则:任何厂商提供的存在性概率都不能绕过 RuView 的隐私、溯源与质量门禁——厂商 AI 输出最多只能作为带 model/version 溯源、明确标注来源的派生观测,绝不充当 ground truth。这与 ADR-263 中"vendor AI presence probability → derived observation, advisory input, never ground truth"的用法表一致。

决策后果与取舍

正向收益(ADR-264 Consequences 原文):

  • 固件、传输、解析器、回放与融合可以各自独立演进;
  • 模糊测试与 golden fixture 的建立不依赖 Realtek SDK 或开发板
  • CFR 与 Range-FFT 能保住正确的轴(axis)与标定溯源;
  • 启动时能力帧让 SDK/API 漂移可观测。

负面代价

  • 相比直接倾倒厂商缓冲区,序列化增加 CPU 与带宽开销;
  • V1 字段可能在真实 API 与上报上限披露后需要修订;
  • UDP 只提供完整性/检错,不提供真实性或机密性

中性项

  • 认证可以后续叠加 ADR-032 设备身份或带签名的 RuField receipt,且不改变上报语义;
  • 已有的 ESP32 ADR-018 帧格式保持不变(两条链路并存互不干扰)。

实现计划的当前状态:代码先行,硬件待闸

ADR-264 的实现计划共 6 步,其中宿主侧 1–3 步已在仓库落地,其余步骤被厂商 SDK 访问权限阻塞。逐条对照:

  1. wifi-densepose-hardware 中新增无厂商依赖的 rtl8720f 类型/解析模块——已完成,即 v2/crates/wifi-densepose-hardware/src/rtl8720f.rs,由 lib.rs 导出,注释明确"no dependency on the vendor SDK"。
  2. 新增 golden CFR、near/far Range-FFT、interference、capabilities fixtures——对应 ADR-264 收尾段所称"typed report and element enums, semantic type/format validation, bounded length arithmetic, CRC verification, finite-float checks, encode/decode round trips, corruption/truncation tests, deterministic arbitrary-input panic checks"。跨语言 golden vector 仍受厂商 SDK 回调 ABI 阻塞。
  3. 属性/模糊测试(长度算术、枚举处理、CRC、浮点校验)——同文件 #[cfg(test)] mod tests 内有:cfr_round_trip_and_stream_consumption(校验"已消费字节数",可正确处理数据报后跟随的下一条数据)、every_report_family_round_tripssingle_bit_corruption_is_detected(翻转载荷 1 bit 触发 CrcMismatch)、truncation_is_reported_without_panicking(从 0 到整帧逐字节截断全部 is_err() 且不 panic)、count_length_mismatch_fails_before_payload_decode(伪造 element_count 后即使重算 CRC 也报 PayloadLengthMismatch)、invalid_semantic_combinations_are_rejectednon_finite_values_are_rejectedarbitrary_short_inputs_never_panic(0–255 字节伪随机输入全部 catch_unwind 验证)、simulator_is_deterministic_and_uses_real_wire_boundary(同种子输出逐字节相等且走真实编码器)、simulator_range_peak_tracks_ground_truth(Range-FFT 峰值 bin × bin_spacing 与模拟目标距离误差 ≤ 一个 bin)、simulator_capabilities_are_explicitly_synthetic
  4. 回放 CLI——即 v2/crates/wifi-densepose-hardware/src/bin/rtl8720f-sim.rs,"打印归一化元数据而不跑推理"的宿主侧消费样例见服务器摘要。
  5. SDK 就绪后实现嵌入式序列化器——待厂商闸门(ADR-263 P0 的 VENDOR_BLOCKED 状态)。
  6. 以实测元素数、帧率与 API 名修订本 ADR——待验收。

ADR-264 收尾还强调:模拟器按种子确定性走生产级编码/解析器而非平行的 mock 表示——即模拟数据与真实硬件共享同一套 to_bytes/from_bytes 代码路径,因此测试的正是将来硬件会用的协议实现。v0.9.0-realtek-beta.1.md 亦记录:该预发布版已覆盖 Rust codec 往返、损坏拒绝、尺寸边界、确定性模拟器测试,并通过 loopback UDP 端到端验证了服务器摄取、REST 上报与来源溯源;但尚未有物理 RTL8720F 板卡被烧录或测量,雷达到姿态/生命体征推断、RF 标定与精度声明均未启用。

验收标准(何时才算完成)

ADR-264 给出了五项明确验收标准,可作为任何实现此协议的工作的自检清单:

  1. 每种上报类型的 Rust encode/decode 往返均通过;
  2. RTL8720F 固件产出跨语言 golden vector(即真实固件字节必须通过宿主 golden 解码器验证);
  3. 在模糊语料库与任意字节输入上零解析器 panic
  4. 能检测:单 bit 翻转损坏、截断、count 溢出、时间戳回退、sequence 缺口;
  5. 捕获 CFR 的频率顺序与 Range-FFT 的 bin 间距须对照厂商文档 + 实测目标双重验证。

协议调试与接入速查

把本文串成可执行的最小闭环,共三个环节:

① 造数据(无硬件):运行模拟器把确定性帧写入回放文件或直接 UDP 推流:

# 生成回放文件(LE u32 长度前缀 + ADR-264 帧)
cargo run -p wifi-densepose-hardware --bin rtl8720f-sim -- \
  --frames 200 --bandwidth 40 --output radar.rtr

# 或实时推到本机传感服务器(注意默认 15ms 间隔配合 --realtime)
cargo run -p wifi-densepose-hardware --bin rtl8720f-sim -- \
  --frames 200 --udp 127.0.0.1:5005 --realtime

② 看解析:让传感服务器在其 UDP 摄取循环里按 magic 分拣并解析(main.rs),然后查询最近一条上报摘要:

curl http://127.0.0.1:PORT/api/v1/radar/latest

③ 验正确性:跑 crate 内建测试,观察每类错误路径(损坏、截断、溢出、非有限浮点、类型/格式错配、非法带宽/天线数)都返回结构化 RadarParseError

cargo test -p wifi-densepose-hardware rtl8720f

三个环节全部验证通过,即代表你已具备不依赖任何 Realtek 私密 ABI 就能开发、测试与回放 RTL8720F 雷达数据的能力;而当厂商 SDK 闸门打开后,唯一剩余的工作是把同一套 RtlRadarFrameV1 信封塞进固件的真实回调。

关联文档与源码导航

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391