首页
/ RuView 传感器布局优化器解析:从 ADR-308 到 ruview-placement 的实现与实践

RuView 传感器布局优化器解析:从 ADR-308 到 ruview-placement 的实现与实践

2026-09-08 12:41:14作者:胡唯隽

RuView 通过普通 WiFi 信号实现空间感知、生命体征监测与存在检测,而真实部署中"传感器放哪"往往依赖经验猜测。本文围绕设计决策记录 ADR-308(sensor placement optimizer),讲解其在 RuView 感知子系统中承担的角色:以楼层平面图与硬件清单为输入,输出可落地的推荐布点,并在安装后用实测可观测性闭环校验。读者读完将掌握布局优化的输入/输出契约、预测与后安装比对的数据流、证据等级纪律,以及当前仓库中对应 Rust crate(ruview-placement)的源码级实现与测试验证方式。

背景:布局问题是 RuView 部署失败的常见根因

ADR-308 是 ADR-300(Perception Substrate Program) 规划蓝图下的子决策,归属于其 primitive #8「sensor placement optimizer」,处于 phase-3(研究前沿阶段),构建在融合世界状态之上。在 ADR-300 的 DAG 中,它与 ADR-315(digital RF twin) 紧密耦合:RF 孪生负责提供优化器规划所依赖的传播仿真;优化器本身读取 ADR-306(canonical spatial ontology) 描述的物理场景,并在安装后用自己的预测与 ADR-302 观测性与 ADR-318 能力证书做比对。

该问题被定义为 RuView 部署失败的单一最常见原因:传感器靠猜测摆放。房间能否被可靠感知,取决于 AP/传感器相对于墙体的几何位置、菲涅尔区净空(Fresnel-zone clearance)、多径结构以及人的真实活动区域。传统安装流程缺少原则性方法来回答"我手上只有两个节点,放在哪才能让厨房可观测",也无法在安装后判断现实是否与规划一致。优化器把 RuView 从"感知给定布点恰好能覆盖的范围"转变成"推荐能让目标感知需求可行的布点"。

方案选型:为什么不做静态指南或全电磁求解器

ADR-308 对比了三类候选方案,最终结论直接决定后续实现形态:

候选方案 结论 理由
文档静态布局指南(如"每房间一个节点、正对门") 拒绝 忽略具体平面图、墙体材质与真实硬件清单,无不确定性量化,无安装后反馈
每站点全电磁求解器 默认路径拒绝 对安装者工作流过重,相对 RuView 现有的粗粒度 rf_attenuation_db 场景是过度设计;保留为 ADR-315 内部可选高保真后端
基于 ADR-306 场景 + ADR-315 RF 孪生做覆盖优化,并在安装后校验预测 vs 实测可观测性 采纳 消耗 RF 孪生而非重复实现第二个仿真器;可复用运行时同款观测性口径

可直接复用的既有资产

ADR-308 强调"构建而非重复造轮子",明确列出要复用的体系构件:

  • worldgraph 场景模型:用 Room/Space + bounds_enuWall { rf_attenuation_db }(石膏墙约 3 dB、砖墙约 12 dB)、DoorwayZone 描述物理场景,足以播种一个粗粒度覆盖模型;同时包含作为候选位置的 Sensor 节点(ADR-306)。
  • ADR-315(RF 孪生,phase-3):传播/多径仿真器。本优化器是孪生的消费者,而非第二个仿真器。
  • ADR-302(OOD/可观测性)与 ADR-318(能力证书):定义"可靠感知目标现象"的度量口径,使优化器能针对运行时最终门控的同一种观测性度量做优化。
  • ADR-029(多站感知)与 ADR-063(mmWave 融合):指示哪些链路几何对哪些现象有效。

决策内容与输入输出契约

决策定义明确:一个布局优化器,输入楼层平面图(ADR-306 场景)与硬件清单,输出推荐的传感器位置,并在安装后闭环。共分为三类输入、一步预测、一个安装后闭环和一套证据纪律。

三类输入

  1. ADR-306 规范场景Space/Zone 边界、带 rf_attenuation_dbWall 线段、Doorway 拓扑,以及任何已部署的 Sensor 节点。
  2. 硬件清单:可用无线电的数量与类型(ESP32-S3/C6 节点、mmWave、网卡等),携带各自的能力包络——即每种硬件能感知什么,按 ADR-318 / ADR-320(sensor HAL)描述符定义。
  3. 感知目标(objective):哪种现象必须在哪个 Space/Zone 可观测(存在检测 presence、生命体征 vitals、姿态 pose),用 ADR-302 观测性度量表述。

在源码中,这三类输入分别映射到 coverage.rsObjectivePlacementinventory.rsInventory/RadioSpec,以及 lib.rs 中声明并重新导出的 SpaceId/ZoneId/SensorId/Container 等规范本体词表(ADR-300 rule 3 的体现——复用统一语义而不是发明新词)。

现象与感知需求强度

不同现象对菲涅尔净空的要求不同,coverage.rsPhenomenon::demand() 给出一个乘数:

现象 demand 乘数 含义
Presence(存在检测) 1.0 基础覆盖阈值
Vitals(生命体征) 1.6 需要更严格净空才计为可观测
Pose(姿态估计) 2.2 最严格净空要求

预测:把 RF 孪生仿真折算成带不确定性的可观测性

对每个候选布局,优化器向 ADR-315 RF 孪生查询仿真 RF 覆盖:墙体 rf_attenuation_db 带来的路径损耗、链路端点间的菲涅尔区净空、粗粒度多径结构,由此推导出每个空间内每个目标的期望可观测性不确定性——复用 ADR-302 定义,确保规划与运行时说同一种语言。

实现层面,ruview-placement crate 在 crate 文档字符串中把自身定位为 research-forward primitive / planning scaffold:给定粗粒度 FloorPlan(ADR-306 场景抽象)与硬件 Inventory,通过把候选布局对 ADR-315 RF 孪生的 SYNTHETIC(L0) 传播模型打分来推荐节点位置。

菲涅尔区几何:两个确定性纯函数

fresnel.rs 实现了两个无分配、确定性的解析函数:

  • fresnel_radius(wavelength_m, d1, d2):一阶菲涅尔半径,公式为 F1 = sqrt(λ · d1 · d2 / (d1 + d2))。路径中点(d1 == d2 == L/2)退化为 0.5·sqrt(λ·L),即测试中用于对照的已知解析极值。非有限或非物理输入一律返回 0.0(绝不返回 NaN/inf),调用方把零半径理解为"无净空信息",而不是除零。
  • link_clearance(a, b, p, wavelength_m):返回 [0, 1] 的净空因子——点在链路上为 1.0,线性衰减到一阶菲涅尔边界处的 0.0,超出边界恒为 0.0;投影不在两个端点之间的目标(处于链路感应走廊之外)以及退化链路(端点重合)也返回 0.0

其单元测试验证了关键解析情形:约 2.4 GHz(λ=0.125 m)、4 m 链路的中点半径直取解析式;链路中点净空为 1、端点之外与垂距远超菲涅尔半径处净空为 0;退化链路净空为 0。

覆盖打分与未知的一等公民语义

coverage.rs 说明了打分方式:候选布局用 RfTwin 前向模型在目标区域采样网格上打分——当采样点位于某条"预测良好链路"的一阶菲涅尔区内时即视为可观测。

每个目标输出一个 Observability 枚举,同时携带分数与不确定性,绝不给出模拟结果的单一自信数值

pub enum Observability {
    /// Modelled observability score in [0, 1] and its uncertainty in [0, 1].
    Known {
        score: f64,          // 该区域模型感知值的均值
        uncertainty: f64,    // 分数的不确定性(越大越不确定)
    },
    Unknown { reason: ObservabilityUnknown }, // 模型无法评估:一等公民值,而非错误
}

Unknown 携带明确的类型化原因(ObservabilityUnknown):TargetNotInPlan(目标不在平面图中)、EmptyRegion(退化几何导致无采样点)、NoLinks(少于两个无线电,孪生没有可评估的链路)、NonFinite(出现非有限计算值)。这正是 ADR-300 rule 1 的落地——信息不足是返回值而非异常或自信默认值

PlacementParams 提供模型参数与有界分配的硬上限,其 default_synthetic() 默认值如下(crate 明确声明这些默认值是教学性的,不对任何真实环境作断言):

参数 默认值 语义
wavelength_m 0.1249 波长(米),约对应 2.4 GHz
good_rssi_dbm -50.0 RSSI ≥ 此值视为链路具备完整感知质量
floor_rssi_dbm -85.0 RSSI ≤ 此值视为链路感知质量为零
coverage_threshold 0.10 采样点被计为"已覆盖"的感知值下限(在现象 demand 乘数作用之前)
blind_spot_fraction 0.15 覆盖比例低于该值则把目标标记为盲区
grid_step_m / candidate_step_m 0.5 / 1.0 采样网格 / 候选网格步长(米)
uncertainty_variance_ref_db2 64.0 把模型化链路方差折算到 [0,1] 不确定性的参考方差
max_sample_points / max_candidates 4096 / 512 每个目标采样点 / 生成的候选位置数量上限(有界分配)
seed 0 候选生成的显式种子(全 crate 无 RNG)
propagation PropagationParams::default_indoor() RF 孪生传播模型参数(路径损耗指数、参考距离/损耗、阴影衰落 σ)

边界校验在 validate() 中完成:非法矩形、非有限坐标、发射功率为无穷、wavelength_m = 0 等畸形输入返回类型化 PlacementError,从不 panic(见 lib.rsboundary_validation_rejects_malformed_input_without_panic 测试)。几何边界常量在 geometry.rsMAX_PLAN_WALLS = 4096MAX_ZONES = 1024;清单上限 MAX_INVENTORY = 64inventory.rs

搜索:种子化候选网格上的贪心前向选择

optimize(见 plan.rs)在候选位置上做贪心前向选择:清单界定了无线电数量,场景界定了几何。每加入一个无线电只能让模型分数持平或上升,因此输出 PlacementPlan.score_trace 单调不减并最终在饱和处趋平。

配套的 rank_placements 用于对给定的候选布局集合排序(模型可观测性最高者优先),candidate_positions 生成种子化、确定性的候选网格——同一 seed 产生相同候选集,seed 变化则网格平移。crate 全链路确定性由 splitmix64 种子流驱动(lib.rssynthetic_floorplan(seed)),不读时钟、无 I/O、无未种子随机性。

安装后闭环:预测 vs 实测对比与孪生残差

安装完成后,ADR-308 要求用来自新注册(ADR-305)且已校准(ADR-301) 传感器的 ADR-302 运行时观测性信号,比较预测 vs 实测可观测性。当实测与预测不一致时,给出调整建议(移动、重新对准、增加节点),并把残差回馈给 ADR-315 孪生以改进其场景参数(例如某面墙的有效衰减)。

源码中对应 compare.rscompare_post_install / compare_post_install_with_tolerance(后者带默认容差 DEFAULT_COMPARE_TOLERANCE)。关键设计点是本 crate 从不测量:实测可观测性由调用方以 MeasuredObservability 提供,预测侧是 L0/SYNTHETIC。比对产出:

  • CompareVerdictMatch / Underperforming / Unknown(缺失实测即一等公民 Unknown,而非错误);
  • AdjustmentActionMoveNode / ReAim / AddNode 等建议动作;
  • TwinResidual:含 ResidualKind(如 EffectiveAttenuationHigher)与 magnitude_db,指示孪生应向哪个方向修正场景参数(例如墙体有效衰减更高)。

相关测试覆盖"实测显著低于预测 ⇒ 产出调整建议与正 dB 残差、判定 Underperforming"(lib.rs)以及"实测与预测一致 ⇒ 判定 Match、无需调整"(lib.rs)。

证据纪律:预测永不是感知声明

ADR-308 的证据纪律是该方案可信度的核心,与 ADR-282 的证据分级对齐:

  • 预测覆盖属于仿真(ADR-282 中的证据等级 L0),必须标记为 SYNTHETIC,是建议而非感知声明。crate 用 EvidenceLevel::L0 显式标注在 PlacementPlan 上,且 serde 序列化会保留 "evidence_level": "L0" 到线上(见 serde_round_trip_is_lossless_and_labels_evidence 测试)。
  • 预测 vs 实测的比对是唯一允许出现 MEASURED 声明的位置,且必须附带复现步骤与真实芯片可观测性数据(遵循 CLAUDE.md 的硬件规则)。
  • 优化器绝不把模拟覆盖图当作"该房间正在被感知"的证据;也不断言任何覆盖或精度数值。

源码 crate 文档同样在文件头强调:"Nothing here is a hardware, MEASURED, or accuracy claim, and the crate asserts no coverage or accuracy number — a twin/optimizer predicts, it does not measure."

结果与质量边界

正面结果:

  • 安装者获得有原则、基于具体平面图的布局方案,关键是安装后还有一次"现实是否匹配规划"的校验——相对猜了再装的部署方式是差异化能力。
  • 优化结果从不给出"推荐布点保证感知"的过度承诺:它只是在清单与几何约束下最大化模型化可观测性,且带显式不确定性。

质量边界:

  • 质量受限于 ADR-315 RF 孪生的保真度与 worldgraph 场景的粗糙度(2D 墙、粗粒度衰减)。优化器选择"报告不确定性"而不是夸大粗模型,更高保真度属于 ADR-315 的范畴。
  • 存在对 ADR-315(孪生)、ADR-302(观测性度量)、ADR-306(场景)的硬依赖;本 ADR 不自建仿真器也不自建观测性度量。
  • 作为 phase-3 研究前沿 primitive,这是坐落在融合世界状态之上的设计意图,随 ADR-315 与 phase-1 主干落地后预期会被修订。

验证与测试矩阵

ADR-308 规划了四级验证,且均能在 ruview-placement crate#[cfg(test)] 中找到对应实现:

ADR 验证项 源码测试
覆盖/可观测性预测是 场景+布局+孪生参数 的确定性函数 optimize_is_deterministic_and_seed_varies_the_scene(同 seed 逐位一致、不同 seed 场景不同、serde round-trip 无损)
菲涅尔区与墙衰减数学对照已知解析情形 fresnel_radius_matches_analytic_midpointclearance_is_one_on_the_line_and_zero_off_the_ends 等(fresnel.rs
搜索在小合成场景返回模型最优布局 better_covering_placement_ranks_higher(链路横跨区域 vs 双节点扎堆角落,前者正确排第一)
合成平面图上已知好/坏布局被正确排序,边缘情形不确定性更高 blind_spot_zone_is_flagged(远端角区被标记盲区、覆盖比例更低)、marginal_case_reports_higher_uncertainty(菲涅尔边缘区域的不确定性高于链路正中区域)
后安装闭环:注入预测-实测不一致产生合理调整建议与孪生参数残差 predicted_vs_observed_delta_yields_adjustment_suggestionmatching_observation_needs_no_adjustment
单调性与饱和度 adding_a_node_improves_score_monotonically_until_saturation(分数单调不减、早期有实质提升、后期趋于饱和)

尚未完成的是实硅片现场验证(ADR 中明确 deferred):在真实仪器化站点上报告 MEASURED 的预测 vs 实测可观测性并附复现步骤。在此之前,所有覆盖输出均为 SYNTHETIC/L0。

上手:一份可复现的最小示例

crate 文档字符串(lib.rs)提供了直接可运行的 API 示例——构建一个确定性的合成场景、一组清单与一个目标,调用 optimize 并断言证据等级与贪心轨迹单调性:

use ruview_placement::*;

// A reproducible SYNTHETIC scene, an inventory, and one objective.
let plan = synthetic_floorplan(7);
let inventory = Inventory::homogeneous("esp32-s3", 20.0, 4);
let objectives = vec![synthetic_objective(&plan)];
let params = PlacementParams::default_synthetic();

plan.validate().unwrap();
inventory.validate().unwrap();

let recommended = optimize(&plan, &inventory, &objectives, &params);
assert_eq!(recommended.evidence_level, EvidenceLevel::L0); // SYNTHETIC
// The greedy score trace never decreases.
for w in recommended.score_trace.windows(2) {
    assert!(w[1] + 1e-9 >= w[0]);
}

其中 Inventory::homogeneous("esp32-s3", 20.0, 4) 表示 4 台 ESP32-S3 类型无线电、每台 20 dBm 模型化发射功率;synthetic_floorplan(seed) 生成 5 m × 4 m 空间 + 一面衰减 6 dB 的内墙 + 中央 core 区与右上角 corner 区的确定性夹具场景。

小结

ADR-308 把"传感器放哪"从一个凭经验的问题转成一个可计算、可校验的问题:读取规范场景与硬件清单、消费 RF 孪生仿真、输出带不确定性的推荐布点,并在安装后以预测-实测比对闭环。RuView 当前仓库中的 ruview-placement crate 已落地这一设计的可运行骨架,严格贯彻 SYNTHETIC/L0 证据纪律与"信息不足是一等公民"的原则。若读者希望继续追溯,可依次深入 ADR-306(canonical spatial ontology)ADR-315(digital RF twin) 与其对应 crate ruview-twin,以及 ADR-318(capability certificates)

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 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++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
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
395