带着目的学:CyberRT
故事背景
最近处在上学与退学,上班与无业的叠加态,想学点CyberRT、Ros2、DDS这些大型项目为工作做准备。虽说之前实习时也算接触过大型项目了,但是毕竟现在时间更充裕,也没有一个明确的任务催着、针对性的去解决,所以看了好几天代码,给环境配得极其顺手,但是实际上对项目的了解始终停留在0。这也值得小小反思以下:
比较一下,实习的时候看代码,是带着一个明确的目标看的。先有业务场景,比如是一个表达式解析错误的bug,当输入表达式是什么的时候,出现什么样的bug。然后我就专找表达式解析部分的代码,专找相应的case处理逻辑,理解起来就很快。表达式解析的case见多了(业务场景见多了),自然也能理解解析部分的代码,为什么 要那样写。
现在看代码呢,我的目的就只是,学习cyberrt。但是至于具体学习什么,其实没有一点概念,只知道要学这个项目,要学那个库。甚至我还没想清楚没了解清楚CyberRT到底是一个什么东西,就深入到代码逻辑中去了。去看它的协程,看协程调度,然后跳了几次调用几个文件,就去打游戏了,什么也没记住。
如果不明白为什么要调度,不清楚究竟是什么场景,才需要专门写一套协程去调度,那就很难真正理解调度的逻辑。
因为不管什么代码,生产项目还是个人项目,哪怕是虚空打靶,它们都对应着一个或者多个目的,搞清楚这个目的,才能更清楚这段代码为什么要这样写。
真正重要的是业务场景对应的解决方案,而不是某一处代码的实现细节,某一个代码片, Know Why 要比 Know How 要重要,也更高效。
已经浪费了很久很久的时间了,没有一个明确的目标而学习,耗时是巨大的,收获是甚微的,看再久代码,最终也不过是盲人摸象管窥蠡测,难以有深入的理解。
因此,我决定,以后要尽力做到:
CyberRT学习目标
啰哩吧嗦了那么多,现在来分析一下所谓的学习CyberRT,到底是要学什么?现在我完全没有概念,那么先让AI替我深度思考一下切入点,带着AI的理解去学一阵子,再回过头来总结我认为的切入点
我认为学习开源代码库或者技术的时候,最重要的不是代码本身怎么实现,而是先搞明白现实中有哪些需求,然后再是,这个技术具体是怎么解决这些问题的,为什么要这么做。然后才是具体的实现。从这个思路,我想学习百度的Apollo项目中的CyberRT框架,你帮我十分详尽地分析下,这个框架对应的需求是什么?要解决什么问题?对应的设计又是什么?(你可以参考Ros2,听说它们很多功能类似,我也有学习ros2的兴趣)
百度 Apollo CyberRT 框架分析:需求、问题与设计
CyberRT 的核心需求与背景
自动驾驶系统对实时性、可靠性和计算效率的要求极高,传统机器人中间件(如ROS1)在以下方面难以满足需求:
- 确定性调度:ROS1 的节点以独立进程运行,调度顺序无法保证,导致任务执行周期不可控。
- 通信效率:ROS1 基于 TCP/UDP 的通信模型存在高延迟和带宽瓶颈,难以处理自动驾驶多传感器的高频数据流。
- 资源管理:传统线程模型(OS Thread)的上下文切换开销大,大量异步任务会导致 CPU 缓存失效(Cache Miss)。
- 模块化部署:自动驾驶需要动态加载算法模块,ROS1 的静态节点管理缺乏灵活性。
CyberRT 的定位:专为自动驾驶设计的高性能运行时框架,核心目标是提供高吞吐、低延迟、确定性调度的计算环境,支持商业化量产需求。
CyberRT 解决的核心问题
实时性与确定性调度
问题:自动驾驶算法需在固定周期内完成数据处理(如感知-规划-控制链路),传统线程调度无法保证任务优先级和周期。
解决方案:
-
用户空间协程(CRoutine):将任务从 OS 线程转为轻量级协程,由 CyberRT 调度器统一管理,减少内核态切换开销。
-
基于 DAG 的任务调度:通过有向无环图(DAG)定义任务依赖关系,结合优先级和周期配置,确保关键任务优先执行。
高效通信机制
问题:ROS1 的通信模型(Topic/Service)存在序列化开销和网络延迟。
解决方案:
- 共享内存与零拷贝:支持进程内、跨进程(共享内存)和网络(DDS)通信,减少数据复制。
- Protobuf 序列化:采用高效的二进制协议,压缩率比 XML/JSON 更高,提升传输效率。
资源隔离与优化
问题:多任务竞争 CPU 资源导致计算延迟不可控。
解决方案:
- CPU 亲和性绑定:将关键任务绑定到特定 CPU 核,减少缓存抖动(Cache Bouncing)。
- 进程级资源隔离:不同模块(如感知、规划)运行在独立进程,分配专属 CPU 核,避免资源抢占。
模块化与动态部署
问题:自动驾驶算法需灵活更新,传统二进制部署需重启系统。
解决方案:
- 组件(Component)模型:通过继承 Component 基类实现算法模块,动态加载共享库(.so),支持热更新。
- DAG 配置文件:定义模块拓扑结构和通信通道,修改配置无需重新编译。
CyberRT 的核心设计
分层架构
- 通信层:基于 DDS/共享内存的发布-订阅模型,支持多种 QoS 策略(如低延迟、高可靠性)。
- 数据层:提供数据缓存与融合机制,例如 Blocker 用于多传感器数据同步。
- 计算层:协程调度器(Scheduler)负责任务调度,支持两种策略:
- Choreography:强调周期性和实时性,适用于自动驾驶任务。
- Classic:传统优先级调度,适用于通用场景。
关键组件
-
Node:功能模块的载体,管理 Reader/Writer 和 Service/Client。
-
Component:继承自 Component 或 TimerComponent,通过 Init() 和 Proc() 定义初始化和处理逻辑。
-
DAG 文件:描述模块依赖关系和通信通道,例如:
module_config { components { class_name: "PerceptionComponent" readers { channel: "sensor_data" } } }
通过 mainboard 工具动态加载。
性能优化技术
- 无锁队列:减少线程竞争,提升并发效率。
- 协程池:预分配协程资源,避免频繁创建销毁开销。
- 时间同步:基于硬件时钟的精准时间戳,支持数据融合与控制协同。