2. Cyber RT 基础概念

学习 Cyber RT,第一步不是急着写代码,而是把它的“词汇表”建立起来。Cyber RT 是一套面向自动驾驶的高性能运行时框架,它的设计目标可以概括为:让数据在正确的时刻,以正确的形式,到达正确的计算单元。围绕这个目标,框架把系统拆解成若干职责清晰的概念对象——节点负责组织计算,通道负责传输数据,消息负责承载内容,服务负责请求应答,参数负责运行期配置,组件负责封装可复用模块,调度器负责决定谁先执行,通信中间件负责把这一切连起来。理解它们之间的分工与协作,是后续开发组件、调优性能的基础。

一、核心对象的分工与关系

可以把 Cyber RT 想象成一座城市的物流系统:节点(Node)是分布在城市各处的收发站,它本身不生产货物,而是注册和管理自己关心的收发线路;通道(Channel)是连接收发站的专用运输线路,每条线路有唯一名称和明确的数据类型;消息(Message)是线路上运输的货物,通常由 Protobuf 定义结构;服务(Service)则像“呼叫—应答”专线,客户端发出请求,服务端处理后返回结果,适合配置查询、状态确认等交互;参数(Parameter)是挂在节点上的可调旋钮,运行期可读可改,用于避免硬编码;组件(Component)是封装好的业务模块,内部通常包含若干节点、通道和处理逻辑,是工程复用的基本单位;调度器(Scheduler)是交通指挥中心,决定哪些任务在哪个线程、以什么优先级执行;通信中间件则是底层的道路与信号系统,负责发现、序列化、传输和唤醒。

关键理解:节点是“逻辑归属”,通道是“数据管道”,消息是“数据本身”,组件是“业务封装”,调度器是“执行策略”,中间件是“传输底座”。它们不是并列的孤立概念,而是从业务到传输的层层依赖关系。
Cyber RT 基础概念关系总览 从业务封装到传输底座的分层协作 组件 Component(业务封装层) 感知组件 定位组件 规划组件 控制组件 节点 Node(逻辑归属层) Node: camera Node: lidar Node: fusion Node: planner Node: control 通道 Channel + 消息 Message(数据层) /camera/image (Image) /lidar/points (PointCloud) 服务 Service + 参数 Parameter /get_status (Request/Response) 调度器 Scheduler + 通信中间件 Middleware(执行与传输底座) 调度策略:优先级 / 协程 发现 / 序列化 / 传输 共享内存 / 零拷贝 包含 读写 承载 调用

二、一次数据流转的完整过程

以“摄像头图像进入感知组件”为例,可以清楚看到这些概念如何协同工作。首先,感知组件被加载,内部创建了一个名为 camera 的节点;该节点通过 CreateReader 订阅通道 /camera/image,并声明消息类型为 Image。当摄像头驱动节点通过 CreateWriter 向同一通道写入一帧图像时,通信中间件完成序列化与传输,调度器根据通道的优先级和回调策略唤醒感知节点的处理函数。处理函数拿到 Image 消息后执行推理,再把结果写入 /perception/obstacles 通道,供下游规划节点消费。如果规划节点需要查询感知模块的健康状态,则通过服务 /get_perception_status 发起请求,而不是再开一条数据通道。

// 节点创建与通道读写示意
auto node = cyber::CreateNode("camera");
auto reader = node->CreateReader<Image>(
    "/camera/image",
    [](const std::shared_ptr<Image>& msg) {
        // 消息回调:处理一帧图像
    });
auto writer = node->CreateWriter<Image>("/camera/image");
writer->Write(image_msg);

三、概念对照与常见误区

概念 核心职责 典型使用场景 常见误区
节点 Node 注册与管理通道、服务、参数 按传感器或算法划分逻辑单元 把节点当成线程,认为一个节点就是一个执行体
通道 Channel 命名化的数据传输管道 传感器数据、算法结果发布订阅 通道名随意起,导致上下游对不上
消息 Message 承载结构化数据 Protobuf 定义的图像、点云、轨迹 消息体过大,频繁拷贝拖慢性能
服务 Service 请求—应答式交互 状态查询、配置下发、一次性计算 用服务传高频数据,造成阻塞和延迟
参数 Parameter 运行期可读写的配置项 阈值、开关、标定参数动态调整 把参数当全局变量滥用,破坏模块边界
组件 Component 业务模块的封装与复用 感知、定位、规划、控制等模块 组件内塞入过多职责,难以独立测试
调度器 Scheduler 决定任务执行顺序与资源分配 高优先级控制任务优先执行 忽视调度策略,导致关键任务被饿死
通信中间件 发现、序列化、传输与唤醒 共享内存、零拷贝、跨进程通信 认为中间件“透明”,不关注传输开销
记忆口诀:组件装节点,节点挂通道,通道传消息,服务做问答,参数调行为,调度定先后,中间件管传输。把这七句话对应到架构图上,概念关系就不会乱。

四、案例复盘:通道命名不一致导致的“无数据”故障

某团队在联调时发现感知组件始终收不到图像。排查日志显示节点创建成功、回调已注册,但没有任何消息触发。最终定位到:摄像头驱动写入的通道是 /camera/image,而感知组件订阅的是 /camera/Image,大小写不一致。Cyber RT 的通道名是严格区分大小写的,且不会自动做模糊匹配。这个问题看似低级,却暴露了对“通道是显式契约”这一概念理解不深。复盘结论有三点:第一,通道名应纳入接口文档统一管理;第二,组件启动时应打印实际订阅的通道列表;第三,对关键通道增加心跳或超时告警,而不是等到“无数据”才被动发现。

另一个高频误区是把“服务”当成“通道”使用。服务适合低频、有明确请求和响应的交互;如果用它传输高频传感器数据,会因请求排队和应答等待造成严重延迟。高频数据流应使用通道,交互式查询才使用服务。

掌握这些基础概念后,后续无论是编写一个最小组件,还是排查通信故障,都可以沿着“组件—节点—通道—消息—中间件—调度器”这条链路逐层定位。概念清晰,工程才不会迷路。