在ROS2当中两种rmw比较(CycloneDDS和FastDDS)

文章目录

DDS

DDS(Data Distribution Service,数据分发服务)为实时分布式系统设计的数据通信标准。

是一个去中心化的、以数据为中心的发布/订阅中间件协议。

  1. 去中心化
    DDS 没有中心代理,所有节点是对等的,通过自动的动态发现机制找到彼此并直接通信。这避免了单点故障和中心节点的性能瓶颈。
  2. 以数据为中心
    发布-订阅导向
  3. 实时
    底层使用零拷贝和共享内存

ROS1架构和ROS2架构之间的关系

DDS架构

QoS(Quality of Service)

配置节点间通信行为的一组策略

发布方(Publisher)和订阅方(Subscriber)的配置必须兼容才能建立连接。

匹配的总原则是:订阅方的"要求"必须比发布方的"承诺"更宽松或相等。

cpp 复制代码
// 创建一个自定义的 QoS 对象
auto custom_qos = rclcpp::QoS(rclcpp::KeepLast(10))           // 历史记录:保留最近10条
                     .reliable()                               // 可靠性:可靠(类似TCP)
                     .transient_local()                        // 持久性:为晚加入的订阅者提供历史数据
                     .deadline(std::chrono::milliseconds(100));// 截止时间:每100ms必须收到一次数据

// 应用到发布者
auto publisher = this->create_publisher<std_msgs::msg::String>("my_topic", custom_qos);

// 应用到订阅者(必须兼容发布者的配置)
auto subscriber = this->create_subscription<std_msgs::msg::String>("my_topic", custom_qos, callback_function);

可靠性 (Reliability)

  • RELIABLE 可靠:确保数据送达,丢失会重传。
  • BEST_EFFORT 尽力:低延迟,丢失不重传。

历史记录 (History)

  • KEEP_LAST (保留最近N条):只为新的订阅者保留队列里最后的 N 条消息。
  • KEEP_ALL (保留所有条):为所有新订阅者保留发布过的所有消息。

持久性 (Durability)

  • VOLATILE (易变的):新订阅者只能收到连接建立之后发布的消息。
  • TRANSIENT_LOCAL (本地瞬态的):新订阅者能收到连接建立之前,发布者已发出的部分历史数据

深度 (Depth)

截止时间 (Deadline)

预期的最大数据发布/接收间隔。如果超时,ROS 2 会触发回调,这对安全关键系统监控数据流是否中断非常重要。

活跃性 (Liveliness)

用于确认发布者是"活着"的。可以配置为当发布者节点还存活、或主动发送心跳信号时,才算活跃。

RMW

什么是RMW?

RMW(ROS Middleware Interface,ROS 中间件接口) 是 ROS 2 架构中的通信抽象层,它让 ROS 2 的核心功能与底层的通信协议解耦

可以使用如下命令查看使用的是哪个中间件

bash 复制代码
ros2 doctor --report

cycloneDDS

接口:rmw_cyclonedds_cpp

优势:资源占用低

配置方式

使用方式1:

bash 复制代码
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file://从根目录开始的路径

使用方式2:

bash 复制代码
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI='xml格式扩展内容'

配置模板

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!--
    Eclipse Cyclone DDS 配置模板
    适用版本:ROS 2 Humble (rmw_cyclonedds_cpp)
    使用方式1:export CYCLONEDDS_URI=file://从根目录开始的路径
    或者
    使用方式2:export CYCLONEDDS_URI='xml格式扩展内容'
    说明:手动指定网卡和单播对等体,适合需要精细控制网络路径的场景。
-->
<CycloneDDS xmlns="https://cdds.io/config"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://cdds.io/config
    https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">

    <Domain Id="any">
        <!-- =============================================================================== -->
        <!-- 1. 通用网络设置 (General)                                                      -->
        <!-- =============================================================================== -->
        <General>
            <Interfaces>
                <!--
                    !!!关键:将 "wlp2s0" 替换成你实际使用的网卡名字 !!!
                    使用命令 `ip a` 或 `ifconfig` 来查看你本机用于通信的网卡名。
                    autodetermine="false" 表示禁用自动选择,强制使用指定的网卡。
                -->
                <NetworkInterface autodetermine="false" name="wlp2s0" />
            </Interfaces>
            <!--
                禁用组播。在 WiFi 或受限网络中,组播容易引起数据包丢失。
                Cyclone DDS 默认情况下 AllowMulticast 是开启的。
            -->
            <AllowMulticast>false</AllowMulticast>
            <!--
                最大消息大小,默认 65500B。如果传输超大的点云或图像,可以适当调大。
                例如:<MaxMessageSize>65500B</MaxMessageSize>
            -->
        </General>

        <!-- =============================================================================== -->
        <!-- 2. 发现配置 (Discovery)                                                       -->
        <!-- =============================================================================== -->
        <Discovery>
            <!--
                单播对等体列表。当组播被禁用后,完全依赖这个列表里的地址来寻找其他节点。
            -->
            <Peers>
                <!-- !!!关键:添加所有你需要通信的远程主机的 IP 地址 !!! -->
                <!-- 本地回环地址,保证本机节点间通信 -->
                <Peer Address="127.0.0.1"/>
                <!-- 远程主机1的IP -->
                <Peer Address="192.168.1.100"/>
                <!-- 可以继续添加更多远程主机 -->
            </Peers>
        </Discovery>

        <!-- =============================================================================== -->
        <!-- 3. 内部性能调优 (Internal) - 可选,高级场景才需要                              -->
        <!-- =============================================================================== -->
        <!--
        <Internal>
            <Watermarks>
                <WhcHigh>500kB</WhcHigh>
            </Watermarks>
        </Internal>
        -->
    </Domain>
</CycloneDDS>

当节点数量增加,需要更多内存运行节点时,直接在终端当中使用命令行

bash 复制代码
export CYCLONEDDS_URI='
<CycloneDDS>
	<Domain id="any">
		<Discovery>
			<ParticipantIndex>auto</ParticipantIndex>
			<MaxAutoParticipantIndex>220</MaxAutoParticipantIndex>
		</Discovery>
	</Domain>
</CycloneDDS>'

或者在launch文件当中添加

python 复制代码
            # 提高 CYCLONEDDS_URI 自动参与者索引上限,避免多节点同时启动时域创建失败
            SetEnvironmentVariable(
                name='CYCLONEDDS_URI',
                value='<CycloneDDS><Domain id="any"><Discovery><ParticipantIndex>auto</ParticipantIndex><MaxAutoParticipantIndex>120</MaxAutoParticipantIndex></Discovery></Domain></CycloneDDS>'
            ),

fastDDS

接口:rmw_fastrtps_cpp

优势:功能完整丰富

  1. 自带零拷贝功能实现(Cyclone DDS需要通过iceoryx实现)
  2. 多机、大规模、受限网络环境部署时的发现服务器(Discovery Server) 模式,可以大幅降低大规模系统中的网络发现流量
  3. 发布话题可以设置同步、异步模式;
  • 异步模式:不阻塞主线程,适合多数场景----publish() 立即返回,数据被放入内部队列,由独立的后台线程负责发送。
  • 同步模式:更高的吞吐量和更低的延迟,适合对实时性要求极高时使用----publish() 会阻塞当前线程,直到数据真正被写入网络后才返回。
xml 复制代码
<publisher profile_name="async_publisher">
    <qos>
        <publishMode>
            异步<kind>ASYNCHRONOUS_PUBLISH_MODE</kind>
            同步<kind>SYNCHRONOUS_PUBLISH_MODE</kind>
        </publishMode>
    </qos>
</publisher>
  1. Statistics 模块与fastdds monitor 可视化工具:实时报告网络延迟、吞吐量、丢包数等详细通信指标,快速定位通信瓶颈(Cyclone DDS不能做到)

配置方式

bash 复制代码
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export FASTRTPS_DEFAULT_PROFILES_FILE=file://从根目录开始的路径

(只能指定文件路径来实现)

配置模板

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!--
    Fast DDS 高级配置模板
    适用版本:ROS 2 Humble (rmw_fastrtps_cpp)
    使用方式:export FASTRTPS_DEFAULT_PROFILES_FILE=file://从根目录开始的路径
    (只能指定文件路径来实现)
    说明:此模板关闭了组播,使用单播进行发现,适用于 WiFi 等组播不稳定的网络环境。
-->
<profiles>
    <!-- =============================================================================== -->
    <!-- 1. 传输层配置 (Transport Descriptors)                                          -->
    <!--    让 Fast DDS 知道有哪些通道可以用来发送数据。                                -->
    <!-- =============================================================================== -->
    <transport_descriptors>
        <!-- 定义一个名为 "UDP_Transport" 的传输方式 -->
        <transport_descriptor>
            <transport_id>UDP_Transport</transport_id> <!-- 这个ID会在后面被引用 -->
            <type>UDPv4</type>
            <!-- 为了多机通信的稳定,通常关闭组播 -->
            <interfaceWhiteList>
                <!-- !!!关键:将 "wlp2s0" 替换成你实际使用的网卡名字 !!! -->
                <!-- 使用命令 `ip a` 或 `ifconfig` 来查看你本机用于通信的网卡名 -->
                <address>192.168.1.101</address>
            </interfaceWhiteList>
        </transport_descriptor>
    </transport_descriptors>

    <!-- =============================================================================== -->
    <!-- 2. 参与者配置 (Participant Profiles)                                           -->
    <!--    配置 ROS 2 节点(DDS 参与者)的通用行为。                                     -->
    <!-- =============================================================================== -->
    <participant profile_name="fastdds_custom_profile" is_default_profile="true">
        <!-- 引用上面定义的传输方式 -->
        <rtps>
            <userTransports>
                <transport_id>UDP_Transport</transport_id> <!-- 引用上面定义的传输ID -->
            </userTransports>
            <!-- 关闭默认的内置组播发现 -->
            <builtin>
                <!--
                    简单发现协议 (Simple Discovery Protocol) 配置。
                    默认使用 Multicast (组播),这里改为不使用。
                -->
                <initialPeersList>
                    <!-- !!!关键:添加所有你需要通信的远程主机的 IP 地址 !!! -->
                    <!-- 本地回环地址,保证本机节点间通信 -->
                    <locator>
                        <udpv4>
                            <address>127.0.0.1</address>
                        </udpv4>
                    </locator>
                    <!-- 远程主机1的IP -->
                    <locator>
                        <udpv4>
                            <address>192.168.1.100</address>
                        </udpv4>
                    </locator>
                    <!-- 可以继续添加更多远程主机 -->
                </initialPeersList>
            </builtin>
        </rtps>
    </participant>
</profiles>

比较

DDS Cyclone DDS Fast DDS
中间件名称 rmw_cyclonedds_cpp rmw_fastrtps_cpp
设计理念 简洁、稳定和高性能 功能丰富和高可配置性
网络通信性能 跨主机通信延迟抖动更小,CPU 占用通常更低 在高吞吐场景下 CPU 占用相对更高
进程内通信性能 主要优势在网络通信,进程内也具备良好表现 在单机共享内存场景下延迟更低,零拷贝优化更成熟
环境变量(指定文件) CYCLONEDDS_URI 环境变量 FASTRTPS_DEFAULT_PROFILES_FILE 环境变量
配置风格 配置项精简 配置项丰富
资源占用 内存和 CPU 占用通常更低,适合资源受限平台 功能全面,基准资源占用相对略高
适用场景 多机通信、嵌入式平台、对稳定性要求高的系统 单机大数据量通信、需要完整 DDS 功能覆盖或商业工具链支持的场景
相关推荐
kyle~1 天前
CDR--- 数据序列化格式(DDS的底层数据支持)
机器人·信息与通信·ros2·dds
kyle~1 天前
RTPS(Real-Time Publish-Subscribe)---DDS的传输协议
c++·机器人·ros2
MIXLLRED1 天前
Ubuntu 22.04 + ROS2 Humble 环境下对 RealSense D435 进行深度校准
ros2·校准·d435·深度图校准
勤自省2 天前
ROS2分布式通信与Launch文件实战:从踩坑到打通(第12-20讲总结)
分布式·ubuntu·ros2·gazebo·launch·rqt·rviz2
济6173 天前
ROS开发专栏---ROS2humble安装详细教程---适配Ubuntu 22.04
ubuntu·ros2·ros2 humble·机器人开发
kobesdu5 天前
【ROS2实战笔记-19】ROS2 生命周期节点的启动顺序、状态转换陷阱与热备方案
java·前端·笔记·机器人·ros·ros2
波特率1152005 天前
ROS2当中的几个关键的环境变量
机器人·ros·ros2
辰尘_星启5 天前
【ROS2】 Python 节点的开发流程
开发语言·python·机器人·系统·控制·ros2
勤自省5 天前
ROS2从入门到“重启解决”:21讲8~12章踩坑血泪史与核心总结
linux·开发语言·ubuntu·ssh·ros