百度阿波罗 和 ROS 2.0 采用的消息中间件
ROS 和前期的 Apollo 定义了一个 API,它向用户公开如
发布
/订阅
等通信概念。
这些通信概念的实现基于自定义协议,并使用共享内存去降低基于Socket通信的开销。
这些传统方法存在一些问题,如每个节点以单独进程的形式存在,由底层操作系统调度,而Linux是个通用系统,每个节点的运行顺序并无任何逻辑。ROS是专用系统,任务应按照一定的业务逻辑执行。
ROS 2
和 Apollo 3
的计算框架 Cyber RT
构建在现有中间件解决方案 DDS
之上 [1] [2]
Cyber RT
在此基础上构建了自己的调度器 [3],由一个多队列的任务编排策略
调度协程(Coroutine)在 Native Thread 上有序运行。其中,Cyber RT 会动态的根据不同调度顺序的执行时间来动态的选择一个时间最短的调度策略。
0x01 Data Distribution Servic, DDS
DDS解决了通信层面的问题,这使操作系统的开发者、应用的开发者得以集中精力专注于业务的研究。 DDS 已经广泛用于 战列舰、大坝等大型公用设施、金融系统、空间系统、飞行系统、火车总机系统 中。
DDS 通过 可靠传输策略 (Quality of Service, QoS)
,控制与底层通信机制的方方面面,主要从时限、可靠性、连续性、历史等方面来满足不同场景的用户数据需求。
DDS 是一个 DCPS (Data-Centric Publish Subscribe) 模型,其中包括Participant, Publisher, Subscriber, DataWriter, DataReader, Topic等概念。具体通信机制如下图:
使用DDS与传统通信的优势:
- 实时性:DDS通过优化的内核机制,实现微秒级的数据传输;纯分布式的系统结构,保证系统内不存在影响实时性的瓶颈节点。DDS 实体被建模为类或类型化接口,允许提前分配内存而不是动态分配内存,可以更有效的对资源处理。
- 可靠性:DDS提供点到点的信息交互服务,从而保证整个系统服务不存在单点故障的风险;同时提供可靠传输策略,通过重发机制确保数据可靠地传输。
- 持续性:DDS可以通过相应的QoS为ROS提供数据历史的服务,新加入的节点也可以获取发布的所有历史数据。
- 灵活性:应用系统可以根据应用场景需求,灵活选择多种DDS提供的应用级QoS策略(例如可靠性传输、数据过滤、优先级排序等等),以满足系统的灵活性需求。
- 扩展性:DDS使用“订阅/发布”机制进行数据交互,建立全局的虚拟数据空间,在通信层面将应用逻辑与节点的物理信息解耦合,使系统能够方便的实现节点增减或系统本身的分割/合并,满足系统的扩展性需求;运行时由DDS自动发现并连接设备和应用程序,即插即用,无需系统管理或目录服务。
- 异构网络支持:DDS通过适配底层多种异构架构网络,对上层提供无差别的通信服务,使通信软硬件层对应用层完全透明。
0x02 Fast DDS
2.1 简介
ROS 2 的大多数版本使用 Fast DDS
作为中间件。ROS 团队提供了一个很完善的报告[4] 详细对比了各个主流 DDS 中间件在压力测试中的 CPU/内存占用率
延时
丢包
,以及代码质量
社区评价
等指标,以及阐述了使用 FastDDS
作为默认中间件的理由。
a. 架构
Fast DDS 的架构如下图 ,包括 应用层
FastDDS层
RTPS层
和 传输层
。其中,传输层
可以选择UDP
TCP
或 共享内存(SHM)
。
具体每个实体和接口的介绍可参考[FASTDDS: Library Overview]。
b. 并发
Fast DDS 是多线程且线程安全的,包括由应用程序管理的主线程,Domain管理的多个事件线程,一个异步写入线程和多个接收线程
c. 消息结构
接口描述语言 (Interface Description Language, IDL)
1 | // HelloWorld.idl |
使用 $./fastddsgen HelloWorld.idl
编译成接口文件:
1 | HelloWorld.h/cxx: HelloWorld type 定义. |
d. 编写subscriber/publisher
参考 [Fast-DDS/examples] 编写代码,其中包含共享内存的使用方法。另外, [FASTDDS: Typical Use-Cases] 有包括高速率通信、实时场景、零拷贝等对符合我们应用场景的配置示例。
2.2 特性
a. 历史记录
Fast DDS 提供数据历史的服务,可以定义过去样本的存储策略。
- Keep Last:历史记录将保存并允许访问最后“k”个收到的样本。这个“k”数字称为历史深度,也可以由用户手动设置。
- Keep All:历史记录将保存并允许访问所有收到的样本,直到达到历史记录的最大样本大小。
b. 零拷贝
传统的共享内存方式避免了传输层中涉及的开销,节省内存的占用(左图)。
FastDDS不仅提供共享内存,还提供类似 NVIDIA Jetson 的零拷贝模式 [8](右图,后者基于GPU/CPU使用同一块内存)。应用程序获取接收到的数据作为引用,这可以防止将数据从共享内存复制到应用程序。
使用零拷贝可以显著加速进程间的通信速度 [9],吞吐量测试结果如下:
z. DDS Monitor
Fast DDS 提供一个GUI应用,可以实时监控 DDS 实体之间的发布/订阅状态,物理架构和统计数据。