2. Cyber RT基础概念
Apollo Cyber RT 是面向自动驾驶场景自研的运行时框架,它把实时操作系统能力、中间件通信、组件化调度与参数服务整合在同一套运行时里。理解 Cyber RT,不能只记住“它是一个通信库”,而要把它看成“以组件为执行单元、以通道为数据平面、以调度器为时间控制面”的完整系统。本章围绕核心术语与整体架构展开,为后续性能与可靠性分析建立统一语言。
一、核心术语的层次关系
Cyber RT 的术语可以按“执行—通信—配置”三条线索理解。执行线索是组件(Component)、节点(Node)与任务调度(Scheduler);通信线索是通道(Channel)、服务(Service)与通信模型;配置线索是参数(Parameter)与中间件。组件是业务逻辑的载体,节点是组件在运行时中的身份标识,通道是节点之间传递消息的命名数据管道,服务则用于请求—应答式交互。
需要特别区分“节点”与“组件”。在 Cyber RT 中,一个节点可以承载一个或多个组件;组件通过 Init() 与 Proc() 定义行为,节点负责注册、发现与生命周期管理。调度器不直接操作业务代码,而是根据组件声明的运行条件(如消息到达、定时触发)把任务放入协程或线程池执行。
二、通信模型:通道、服务与数据流
Cyber RT 的通信模型以“通道”为中心。发布者向某个通道写消息,订阅者从该通道读消息,通道名即话题名。底层中间件负责序列化、共享内存传输、发现与 QoS 策略。服务则采用请求—应答模式,适合配置查询、状态确认等低频交互。下图给出节点、组件、通道、服务与调度器之间的整体关系。
图中可以看到,调度器位于执行控制面,通道与服务位于数据与交互面,参数与中间件位于配置与传输面。节点是组件的容器,组件通过通道或服务与外部交互,最终由调度器决定何时执行。
三、组件、节点与任务调度的协作流程
一个典型组件的运行流程如下:组件在 Init() 中创建读取者与写入者,声明输入通道和输出通道;调度器根据触发条件把 Proc() 放入执行队列;Proc() 从通道读取消息、处理并写出结果。若组件需要定时执行,可使用定时器触发;若需要响应请求,则注册服务处理函数。
class PerceptionComponent : public cyber::Component<SensorFrame> {
public:
bool Init() override {
reader_ = node_->CreateReader<SensorFrame>(
"/sensor/camera", [this](const std::shared_ptr<SensorFrame>& msg) {
// 消息到达触发
});
writer_ = node_->CreateWriter<Obstacles>("/perception/obstacles");
return true;
}
bool Proc(const std::shared_ptr<SensorFrame>& msg) override {
auto obstacles = Detect(msg);
writer_->Write(obstacles);
return true;
}
};
这段代码体现了 Cyber RT 的核心约定:组件不直接管理线程,而是通过节点创建读写者,由框架负责调度与传输。理解这一点,才能在后端分析延迟、丢帧与 CPU 占用时定位到正确的层次。
四、核心术语速查清单
| 术语 | 作用 | 典型对象 | 性能关注点 |
|---|---|---|---|
| 实时操作系统 | 提供确定性时钟与优先级 | Linux + RT 补丁 | 抖动、中断延迟 |
| 中间件 | 消息传输与发现 | 共享内存、序列化 | 拷贝次数、吞吐 |
| 通信模型 | 定义交互方式 | 发布订阅、请求应答 | 端到端延迟 |
| 组件 | 业务逻辑执行单元 | 感知、规划、控制 | Proc 耗时 |
| 节点 | 组件运行时身份 | Node A / Node B | 发现开销 |
| 通道 | 命名数据管道 | /perception/obstacles | 队列深度、丢帧 |
| 服务 | 请求—应答交互 | 参数查询 | 超时与重试 |
| 参数 | 运行时配置 | 全局/私有参数 | 热更新一致性 |
| 任务调度 | 决定执行时机 | 协程、线程池 | 优先级反转 |
五、常见误区与复盘要点
误区一:把节点等同于进程。节点是逻辑身份,多个节点可运行在同一进程内,也可能跨进程通信。排查性能问题时,先确认节点与进程的映射关系。
误区二:认为通道写入即送达。通道有队列与 QoS 策略,队列满时可能丢弃或阻塞。分析丢帧时,应同时检查发布频率、队列深度与订阅者处理速度。
误区三:忽视调度器触发条件。组件未执行不一定是代码问题,可能是触发条件未满足、优先级被抢占或线程池饱和。
复盘建议:遇到延迟或丢帧,按“参数配置 → 通道队列 → 组件 Proc 耗时 → 调度器负载 → 中间件传输”的顺序逐层排查,避免直接修改业务代码。