设计哲学
本文阐述 Roplat 的核心设计理念,帮助你理解它为什么要这样做,而不仅仅是它能做什么。
核心信条:运行期危险左移
传统机器人操作系统(以 ROS 2 为代表)的根本问题是:太多错误被推迟到运行时才暴露。
- 话题类型不匹配 → 运行时消息丢弃
- 节点依赖缺失 → 运行时超时等待
- 调度顺序不确定 → 间歇性死锁
- 内存越界 → 运行时 segfault
这些问题在实验室调试时已经很痛苦,在真实机器人上更是灾难性的——你无法让一台搬运重物的机械臂"再试一次"。
Roplat 的解决方案:尽可能将这些检查前移到编译期。
ROS 2 Roplat
┌─────────────┐ ┌─────────────┐
编译期 │ 语法检查 │ │ 语法检查 │
│ │ │ 类型匹配 │
│ │ │ 拓扑分析 │
│ │ │ 死锁检测 │
│ │ │ 调度确定 │
└──────┬──────┘ └──────┬──────┘
│ │
┌──────▼──────┐ ┌──────▼──────┐
运行期 │ 类型匹配 │ │ 纯执行 │
│ 拓扑发现 │ │ (确定性) │
│ 调度决策 │ │ │
│ 竞争检测 │ │ │
│ 崩溃/死锁 │ │ │
└─────────────┘ └─────────────┘
进程内静态,进程级动态
Roplat 在单个进程内追求完全静态:
- 所有节点连接在编译期确定
- 调度顺序在编译期确定
- 类型在编译期匹配
但在进程之间保留动态灵活性:
- 不同进程可以独立部署
- 进程间通过旁路通讯连接
- YAML 配置参数可运行时加载
这种"进程内静态 + 进程级动态"的策略,在安全性和灵活性之间取得了平衡。
图即调度,规约即编译
Roplat 的 system! 宏将数据流描述转化为有向图,然后通过图规约将其化简为最优执行序列:
原始拓扑:
A → B → D
A → C → D
R2 规约(并行融合):
A → (B ∥ C) → D
最终代码:
let a_out = a.process(input).await;
let (b_out, c_out) = tokio::join!(
b.process(a_out.clone()),
c.process(a_out),
);
d.process((b_out, c_out)).await;
五条规约规则:
| 规则 | 含义 | 效果 |
|---|---|---|
| R0 | 单节点直接执行 | 基础情况 |
| R1 | 串行链融合 | A → B → 顺序 await |
| R2 | 并行扇出融合 | A → (B ∥ C) → tokio::join! |
| R3 | 拓扑排序 | 保证依赖顺序 |
| R4 | 通道切割 | 跨域边界自动插入 channel |
零开销原则
Roplat 在运行时追求零额外开销:
-
Rhythm 零堆分配:
drive()方法使用值传递模式,每 tick 不产生任何堆分配。节点元组通过值移入/移出闭包,编译器优化为寄存器传递。 -
无动态分发:所有 trait 方法通过泛型单态化,没有 vtable 查表。
-
无运行时调度器:不需要执行器在运行时决定"下一个执行谁"——这个决定已经在编译期做完了。
-
Lock-free 通讯:旁路通讯使用原子操作而非互斥锁,保证实时线程不会被阻塞。
关注点分离
Roplat 严格分离三个正交关注点:
| 关注点 | 抽象 | 用户关心的问题 |
|---|---|---|
| 计算 | Node | "这个节点做什么计算?" |
| 时间 | Rhythm | "多快执行一次?什么事件触发?" |
| 连接 | System | "谁的输出接谁的输入?" |
这意味着:
- 修改控制算法 → 只改 Node,不动 Rhythm 和 System
- 修改执行频率 → 只改 Rhythm,不动 Node 和 System
- 修改数据流拓扑 → 只改 System,不动 Node 和 Rhythm
每次变更只影响一个维度。
与 ROS 2 的根本分歧
| 设计决策 | ROS 2 | Roplat | 理由 |
|---|---|---|---|
| 拓扑构建 | 运行时发现 | 编译期声明 | 消除启动阶段的不确定性 |
| 类型检查 | 运行时哈希比对 | 编译期泛型约束 | 类型错误不应在实验中才发现 |
| 调度器 | 运行时 Executor | 编译期图规约 | 确定性是安全的前提 |
| 通讯 | DDS 中间件 | 进程内 lock-free | 实时系统不能容忍中间件延迟 |
| 多语言 | 各语言独立实现 | 编译期绑定生成 | 消除手写绑定的类型不一致 |
Roplat 并非要替代 ROS 2 的所有场景。它更适合对安全性、确定性和实时性有高要求的场景——如工业机械臂控制、自动驾驶感知管线、多机器人协同编队。