首页
/ RuView Sensor HAL(ADR-320):用一套 `SensorHal` trait 与统一 `Observation` 类型抽象全部感知硬件

RuView Sensor HAL(ADR-320):用一套 `SensorHal` trait 与统一 `Observation` 类型抽象全部感知硬件

2026-09-08 20:04:13作者:苗圣禹Peter

导读

本文围绕 ADR-320-sensor-hal.md(ADR-300 感知基座程序的第 20 号原语、phase-2 集成原语)展开,讲解 RuView 如何通过一个 SensorHal trait唯一的 Observation 类型,把 {CSI、802.11bf、BLE、UWB、mmWave、声学、相机、激光雷达、IMU、自定义} 等任意传感硬件收拢进同一条摄入通道,使下游世界模型永远只看到携带来源与证据标注的观测,而不再面对某一模态专有的帧格式。读完本文,你将理解该 HAL 的 trait 契约、Modality/SensorDescriptor/HalObservation 等核心类型的设计逻辑、边界校验与“诚实证据”纪律,以及它如何为 ADR-311 的真实传感器融合提供可实现的前提,并能对照 ruview-hal crate 的源码与测试亲自验证。

背景:为什么需要一层“传感器 HAL”

RuView 的战略天花板长期由它与 WiFi CSI 的耦合程度决定。每一个新模态进入系统,历史上都会变成一条定制摄入链路:自己的帧形状、自己的一套 provenance 处理、自己在管线中的专属位置。这样的路线使 RuView 停留在“一个 WiFi-DensePose 项目”的范畴;而让任意传感硬件——{CSI, 802.11bf, BLE, UWB, mmWave, acoustic, camera, lidar, IMU, custom}——经由同一个抽象进入、变成同一个 Observation 并喂给同一个世界模型,才会让它演化为“开放的空间智能操作系统层”。二者分野的判据就是:换一个传感品类是否意味着重写一条管线

必须强调的是,这是一次统一(unification),而不是绿地重写。现有的适配器必须复用而非重建:

  • ADR-279 的原生 RF 帧契约(RfFrameV2)已经统一了 ESP32、Intel、Atheros、PicoScenes、Realtek 雷达以及 320 MHz 802.11bk 生产者,全部收敛进一个共享隐空间——“轻量、按设备定制的适配器进共享隐空间,而不是进共享张量”。HAL 把这条经验推广到 RF 之外。
  • 既有 CSI 适配器(ESP32/Nexmon/FeitCSI 各路径)、ADR-063 的 mmWave 融合路径、ADR-029 的多站 WiFi 路径,都是要被纳入同一 trait 的具体生产者。
  • ADR-305 已经完成了 Sensor/DeviceId 的认证;ADR-306 已把 SensorObservationTrackEvent 定义为一等节点类型。HAL 正是那个把异构设备变成“已认证 Sensor、持续发出 Observation”的 trait。

缺口的答案是一个 SensorHal trait 与一个 Observation 类型:每种模态都实现该 trait,世界模型永远不接触模态专有的帧,只看到携带 provenance、带证据标签的 Observation

备选方案回顾(Options considered)

ADR-320 在做出决策前比较了三条路线,理解取舍有助于把握 trait 形态为何如此:

  1. 继续增加按模态定制的摄入路径——否决。代价是 O(模态数) 条专用管线,每条都在重复实现 provenance 与证据逻辑,每条都是一处可被攻破的“梯子”;且它让 RuView 在类别上始终是 WiFi 项目。
  2. 把所有模态强行塞进 ADR-274/279 的 RF 张量/帧——否决。ADR-279 的经验恰恰是:过早规范化会丢弃信息(带宽、天线结构、相位)。相机、激光雷达、IMU 根本没有有意义的 RfFrameV2 投影;强行投射只是把同一个错误放大到更大的尺度。
  3. 定义产出单一 Observation 类型的 SensorHal trait,以既有适配器为实现,喂给共享隐空间与 ADR-306 本体——采纳。

决策:一条 trait + 一个 Observation

决策本身很克制:引入 SensorHal trait 与唯一的 Observation 类型;每种传感模态都是该 trait 的一个实现;世界模型只消费 Observation

SensorHal trait:描述能力、保留原生帧、提升为观测

一个 SensorHal 承担三件事:

  • 能力描述:说明设备能感知哪些现象,复用 ADR-305/ADR-141 的能力证明(CapabilityAttestation)思路;
  • 保留原生帧:设备原生的帧保持原生形态,不做规范化(遵循 ADR-279 的共享隐空间教训——过早规范化会丢弃带宽、天线结构、相位等信息);
  • 提供“提升”方法:把一个原生帧提升(lift)成一个 Observation

ruview-hal crate 中,该契约被编码为一个小而精确的 trait(adapter.rs):

pub trait SensorHal {
    /// 该适配器消费的、模态专有的原生采样类型。
    /// 保持原生(不规范化),遵循 ADR-279 共享隐空间经验。
    type Raw;

    /// 用规范术语描述这台设备。
    fn describe(&self) -> SensorDescriptor;

    /// 将一个原生原始采样规范化为一个 HalObservation。
    ///
    /// 不可失败(infallible):畸形/越界输入产生 UNKNOWN 标记的、
    /// degraded 观测,而不是 panic 或返回 Err。
    fn normalize(&self, raw: Self::Raw, ctx: &NormalizeCtx) -> HalObservation;
}

两个方法名值得注意:

  • describe() 产出的是规范设备描述 SensorDescriptor(见下文),把设备“是什么、能感知什么、原生采样长什么样”沉淀成可序列化、可往返的元数据;
  • normalize() 是硬件/FFI 边界校验点:它必须不可失败——畸形或越界的原始输入一律产出带 UNKNOWN 标记的 degraded 观测,绝不 panic、绝不返回 Err(这是 ADR-300 四条“不可谈判规则”中的第 1 条,源码以 //! 文档写死在 lib.rs)。

normalize 需要调用方注入一个 NormalizeCtx,它携带 observation_id、观测所在的 Container(空间/区域,来自 ADR-306 本体图)以及 at_unix_ms 捕获时间戳。HAL 从不自己铸造 id、也从不读墙钟——时间由调用方注入,从而保证适配器确定性与可复现测试(adapter.rs)。

SensorDescriptordescriptor.rs)把设备绑定到其本体 SensorId,并给出 modality(现象类别)、capabilities(能力标签)与 sampling(原生采样/单位元数据)。它以 serde 无损往返,供 ADR-316 的集群控制器统一枚举异构硬件:

pub struct SensorDescriptor {
    /// 该设备被认证为本体中的传感器身份(ADR-305)。
    pub sensor_id: SensorId,
    /// 设备感知的现象类别。
    pub modality: Modality,
    /// 能力标签——设备宣称能观测的现象。
    pub capabilities: Vec<CapabilityTag>,
    /// 原生帧的采样 / 单位元数据。
    pub sampling: SamplingSpec,
}

SamplingSpecdescriptor.rs)记录 sample_rate_hzNone 是一等的 UNKNOWN——事件驱动或未指定采样率的源不是错误)、原生单位标签(如 "csi-complex""m/s^2")与维度。注意它是描述性而非规定性:只记录设备原生如何产出采样,管线无需理解原始帧本身。

Modality:现象类别,管线区分“如何被感知”的唯一位置

Modality 枚举(modality.rs)是“世界是如何被感知的”在管线中的唯一区分点——所有模态流过同一个 SensorHal trait、进同一个规范 Observation,因此世界模型从不在模态专有的帧形状上分支:

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Modality {
    Csi,          // WiFi CSI(ESP32/Nexmon/FeitCSI,经 ADR-279)
    Ieee80211bf,  // IEEE 802.11bf 原生感知(ADR-310,phase 2)
    Ble,          // BLE 测距 / RSSI
    Uwb,          // 超宽带测距
    Mmwave,       // 毫米波雷达(ADR-063)
    Acoustic,     // 声学 / 超声感知
    Camera,       // 光学相机
    Lidar,        // 激光雷达点云
    Imu,          // 惯性测量单元(加速度计 + 陀螺仪)
    Custom(String), // 开放扩展点:携带校验后自由标签的模态
}
  • 封闭变体覆盖 ADR-320 点名的模态;Custom(String) 是未枚举模态的开放扩展点,须经 Modality::custom()/validate() 在边界做标签校验(非空、长度受限、不含控制字符,上限 MAX_LABEL_LEN = 128)。
  • is_rf()modality.rs)标出 RF 模态(Csi/Ieee80211bf/Ble/Uwb/Mmwave),它们整体复用 ADR-279 的逐设备隐空间适配器;HAL 只在其上补充非 RF 与测距模态。

HalObservationObservation:承载 provenance 与证据等级的统一事实

HAL 边界上流动的统一事实类型是 HalObservationobservation.rs):

pub struct HalObservation {
    /// 本次测量经由的模态。
    pub modality: Modality,
    /// 逐观测的不确定性(可能为 UNKNOWN)。
    pub uncertainty: Uncertainty,
    /// 该 HAL 采样映射到的规范本体观测。
    pub observation: Observation,
}

关键设计是:内层的 observation 直接复用 ADR-306 本体的 Observation,而不是再造一个每 crate 一形的结构(ADR-300 规则 3)。本体 Observationentity.rs)已经强制携带:id、产生它的 sensor: SensorId(ADR-305 认证身份)、located_in: Container、注入的 at_unix_ms恰好一个 EvidenceLevel 以及强制的 SemanticProvenance。HAL 的 HalObservation 只是在其上叠加了 modality 与逐观测 uncertainty 两块边界上下文,并通过委托访问器暴露 evidence_level()provenance()sensor()绝不复制或允许它们分叉observation.rs)。

一张由相机导出的观测与一张由 CSI 导出的观测是同一类型、不同 provenance——而相机观测永远不会把 WiFi 输出抬升到相机等级;每张观测各自携带自己的诚实证据等级(CLAUDE.md 纪律:绝不把 WiFi 感知包装成相机级)。

EvidenceLevel:ADR-282 证据阶梯 L0–L5

每个事实都携带恰好一个证据等级。EvidenceLevelprovenance.rs)在 ADR-306 中即定义,并沿用 ADR-282 的 L0–L5 阶梯,排序有意义(L0 < L1 < … < L5):

等级 含义
L0 声明/假定,无信号证据
L1 启发式/合成
L2 单一表面的信号证据
L3 跨表面相互印证
L4 已校准且经留出集验证
L5 见证/认证(ADR-319)

每个叶实体还携带强制的 SemanticProvenanceprovenance.rs):evidence(内容寻址句柄)、model_version(ADR-136)、calibration_version(ADR-135/ADR-301)、privacy_decision(ADR-141),且每项都是受限字符串句柄而非内嵌数据。观测跨任何表面边界都不能丢失其谱系——没有投影能静默升级或丢弃证据等级。

Uncertainty 与 Confidence:UNKNOWN 是值,不是错误

HAL 边界贡献的逐观测不确定性采用一等 UNKNOWN 建模(observation.rs):

  • ConfidenceUnknown 或闭区间 [0.0, 1.0] 内的 Known(f64)Known 构造时自动 clamp,NaN/inf 折叠为 Unknown,绝不传播“中毒”数值;
  • Uncertainty:携带 confidencedegraded 布尔。degraded 区分两类 UNKNOWN:degraded = false合法不可量化源(如不量化置信度的事件驱动传感器)vs degraded = true畸形/越界原始输入产生的尽力而为占位。两者都不是错误,但下游融合可以据此加权或丢弃。

这正是 ADR-300 规则 1 的落地:UNKNOWN 是一等值、绝不是错误或 panic

实现如何落地:合成参考适配器(CSI + IMU)

ADR-320 的验证要求至少两个模态的 fixture SensorHal。crate 里随附两个确定性合成参考适配器adapter.rs):

  • SyntheticCsiAdapter(RF 代表,Raw = CsiSample:逐子载波幅值+相位)——形如上,它“演示”一个 CSI 生产者如何被提升为规范观测,但不声称任何真实设备
  • SyntheticImuAdapter(非 RF 第二模态,Raw = ImuSample:3 轴加速度 m/s² + 3 轴角速度 rad/s)——证明一个完全不同的现象类别也能以同一规范观测进入系统。

两者一律标注 SYNTHETIC / L0:证明的是抽象本身,而不是一台已部署设备(CLAUDE.md 纪律)。关键实现点:

  • 边界校验adapter.rs):空帧、幅相长度不匹配、超 MAX_CSI_TAPS = 4096 的越界输入、NaN 等非有限值 → 一律降级为 UNKNOWN,不 panic、不捏造置信值;
  • 确定性置信度:CSI 取幅值均值经饱和映射 mean/(mean+1) 生成 Known 置信;IMU 以加速度幅值与 1g 的接近度生成置信。无随机数、无时钟;
  • 诚实证据锁定adapter.rs):合成观测的 provenance calibration_version 被钉为常量 SYNTHETIC_CALIBRATION = "synthetic"is_synthetic() 恒真,证据等级恒为 L0,永远无法别名成实测/已校准观测(ADR-279 不变量 6)——它到不了 >= L2 的印证/校准等级。

下面给出 SyntheticCsiAdapter::normalize 的完整实现,读者可据此理解“原生帧 → 规范观测”的典型样板:

fn normalize(&self, raw: Self::Raw, ctx: &NormalizeCtx) -> HalObservation {
    let observation =
        synthetic_observation(self.sensor_id.clone(), ctx, "synthetic-csi-adapter@0");

    // 边界校验:空、不匹配、越界或非有限输入降级为 UNKNOWN,
    // 而不是 panic 或捏造一个高置信值。
    let malformed = raw.amplitudes.is_empty()
        || raw.amplitudes.len() != raw.phases.len()
        || raw.amplitudes.len() > MAX_CSI_TAPS
        || raw.amplitudes.iter().any(|v| !v.is_finite())
        || raw.phases.iter().any(|v| !v.is_finite());

    let uncertainty = if malformed {
        Uncertainty::degraded()
    } else {
        let sum: f64 = raw.amplitudes.iter().map(|&v| f64::from(v).abs()).sum();
        let mean = sum / raw.amplitudes.len() as f64;
        Uncertainty::known(mean / (mean + 1.0))
    };

    HalObservation { modality: Modality::Csi, uncertainty, observation }
}

两个合成适配器的 describe()adapter.rs)则各自产出能力标签(CSI:"amplitude"/"phase";IMU:"accel"/"gyro")与采样规格(CSI 100 Hz csi-complex 52 维;IMU 200 Hz m/s^2|rad/s 6 维)。

边界安全:把“不受信任的硬件输入”关在 trait 边界外

ADR-320 把 trait 明确为“不受信任的硬件输入被校验”的边界(CLAUDE.md:在每个硬件/FFI 边界校验;默认最小权限)。从源码可以看到这条纪律如何落到类型上:

  • CapabilityTagModality::Custom 载荷都来自可能不受信任的硬件描述符,它们在构造时用同一套标签规则校验(label.rs):非空、字节长度 ≤ MAX_LABEL_LEN(128)、不含 ASCII 控制字符;错误被建模为 LabelError::{Empty, TooLong, ControlChar}
  • 设备被认证为 ADR-305 的 Sensor(描述符中的 sensor_id)之后,它的观测才被信任;未经认证设备的观测在 trait 边界被拒。

这一点同样写进了 crate 文档的“四条不可谈判规则”(lib.rs):UNKNOWN 一等值永不 panic;证书做密码学绑定(虽在 HAL 范围之外,但设备须先认证);下游只有一种规范语义;诚实证据不互相抬级。

从 HAL 到世界模型:喂给 ADR-311 融合

SensorHal 产出的 HalObservation 是 ADR-306 本体 Observation 的包装,因而直接落入本体图(挂在对应 Sensor 节点下)——本体是唯一表示,HAL 是它的摄入漏斗。任意模态集合的观测流入 ADR-311 融合,后者把它们解析成一个概率世界状态。

ruview-fusion crate(lib.rs)把 ADR-311 的不变量说得很清楚:“许多观测解析为一个世界状态,而不是多条 feed 进一个可视化”——一个并排展示 WiFi 层、mmWave 层、BLE 层的仪表盘不是融合。它摄入一组 PresenceObservation(规范 HalObservation + 逐源占用 Claim),可能跨模态、可能冲突,最终产出单一的 WorldState

而 HAL 保证了融合永远看不到模态专有的帧——只有 provenance 与证据统一、且证据等级取所有贡献观测的最小值(绝不抬到最弱必要输入之上)的 Observation。这使 ADR-311 “many observations → one world state” 不变量在异构硬件上可落地:见 fusion 的测试Csi + MmwaveCsi + BleCsi + Mmwave(L3) 等跨模态集合都以统一 HalObservation 参与融合并保留逐源 provenance。

类别与诚实纪律:是统一摄入边界,不是“检测器”

  • 本 ADR 把 RuView 的类别从 WiFi-DensePose 管线切换为开放的空间智能操作系统层,但不做任何精度声明:HAL 交付的是统一摄入边界,不是检测器。新接入传感器的任何能力仍须由 ADR-302 门控、经 ADR-318 针对其具体环境认证——接上一台相机本身并不能授予一条已验证的能力。
  • 某一模态的硬件支持在真实芯片上以捕获证据被演示之前,只能记为 CLAIMED;一次通过的 trait 测试证明的是抽象,而非一台已部署的设备。成功构建或模拟器运行不算硬件证据(CLAUDE.md)。这正是 crate 内合成参考适配器坚持 SYNTHETIC/L0 的原因。

将既有生产者映射到 trait

crate 文档(lib.rs)用一张表记录“现有生产者收编到 trait 时实现哪个 SensorHal”(本 crate 只定义 trait 与合成参考实现,不重写既有生产者;RF 模态整体复用 ADR-279 逐设备隐空间适配器):

既有生产者 来源 ADR Modality 原生帧 说明
ESP32-S3/C6 CSI 节点 ADR-279 / firmware Csi RfFrameV2(子载波复数) 复用 ADR-279 原生帧→共享隐空间适配器;HAL 只把隐空间提升为观测
Nexmon CSI ADR-279 Csi RfFrameV2 逐设备适配器进共享隐空间;同 trait,不同原生布局
FeitCSI / Intel / Atheros / Realtek ADR-279 Csi RfFrameV2 同一共享隐空间路径;带宽/天线结构保持原生,不规范化
802.11bf 感知 ADR-310(phase 2) Ieee80211bf 原生 11bf 测量帧 随其落地纳入同一 trait
mmWave 雷达 ADR-063 Mmwave 距离-多普勒 / 点云帧 ADR-063 融合生产者成为 SensorHal 实现
多站 WiFi ADR-029 Csi 多链路 RfFrameV2 集合 多链路、一个认证 Sensor、一个观测

非 RF 模态(相机、激光雷达、声学)以与 RF 相同的 provenance 与隐私纪律进入受治理平面:相机不是无隐私捷径——它继承 ADR-277 治理并携带自己的诚实证据等级。

影响(Consequences)

  • 新传感硬件落地 = 一个 SensorHal 实现,而非一条定制管线;翻译矩阵保持 O(模态数),呼应 ADR-306 如何收缩表面矩阵;
  • ADR-300 验收条款“识别硬件(identify the hardware)”变得可实现:新传感器类型以 HAL 描述 → 认证为 ADR-305 Sensor → ADR-301 校准 → ADR-302 门控 → ADR-318 认证,走完同一条 phase-1 主干,闭合最后一个未决条款;
  • 新增的是一条 trait 边界与一个 Observation 类型;既有 RF 适配器被重新表达为实现而非重写,保留 ADR-279 原生帧/共享隐空间设计;
  • 非 RF 模态(相机、激光雷达、声学)以与 RF 相同的 provenance 与隐私纪律进入受治理平面,相机继承 ADR-277 治理并携带自身证据等级;
  • 作为 phase-2 Proposed ADR,trait 形态在 ADR-311 融合与 ADR-310 802.11bf 落地时可能修订——这是分阶段程序的预期。

验证方式(Validation)

设计期验证落在 ruview-hal crate 的 cargo test 上,源码测试与 ADR-320 验证条款一一对应(lib.rs):

  • 描述符无损往返descriptor_round_trip —— CSI/IMU 及自定义模态(thermal-array)的 SensorDescriptor serde 往返相等且 validate() 通过;
  • 合成采样归一化reference_adapter_normalizes_synthetic_sample —— CSI 与 IMU 各自产出统一 HalObservation,携带 sensor id、container、时间戳、恰好一个证据等级(L0)、is_synthetic() 为真、degraded 为假;IMU 观测证据等级严格小于 L2;
  • 畸形输入 → UNKNOWN 而非 panicdegraded_input_yields_unknown_not_panic —— 空帧、长度不匹配、NaN、超过 MAX_CSI_TAPS 的越界帧、含 f32::INFINITY 的 IMU 样本,全部产出 is_unknown() && degraded 的良构观测且不可别名到实测;
  • 标签边界校验label_validation_at_boundary —— 空标签、含换行控制字符、超长标签各自得到精确的 LabelError 变体;Modality::Csi.is_rf() 为真、Modality::Imu.is_rf() 为假;
  • serde 往返与确定性hal_observation_serde_round_trip(含 UNKNOWN 观测,序列化稳定输出 "csi"/"unknown"/"L0")、normalization_is_deterministic(同输入+ctx 恒等输出)、synthetic_cannot_alias_to_measured(合成校准句柄 + L0 把它钉在印证之下)、confidence_is_bounded(clamp 与 NaN 折叠)。

跨 ADR 验证(设计期描述):Observation 与 ADR-306 本体 Observation 节点往返无 provenance 丢失;来自不同模态的一组观测可被 ADR-311 融合 fixture 接受。任何模态的硬件支持在真实芯片上捕获启动/运行日志并发出 Observation 之前只能停留在 CLAIMED——成功构建或模拟器运行不是硬件证据。

如何继续深入与验证

实际运行验证按仓库根目录 README.md、v2 workspace Cargo.toml 的说明构建并执行 cargo test(HAL 为纯抽象 crate:无 I/O、无 async、无推理,其测试均为确定性、同步、可离线运行)。需要留意的前提与限制:ADR-320 定位为 phase-2 Proposed 设计,代码中的实现是其“initial implementation(ADR-300 phase 2)”形态,trait 形状在 ADR-311 融合与 ADR-310 802.11bf 实际落地后可能继续修订;实现中观测事实以认证后的 SensorId(ADR-305 本体身份)承载,而非直接携带裸 DeviceId 字符串——这是原 ADR 文本与当前实现演化之间的一个差异点,阅读时宜以 crate 源码为准。

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

项目优选

收起
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
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
924
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
599
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
394