【ROS2】ROS 2 中 Unique Network Flow Endpoints唯一网络流端点的简介与使用1、官方示例代码2、代码解析2.1、整体功能总结2.2、核心前置概念2.3、逐模块代码解析2.4、核心细节与关键考点2.5、运行逻辑梳理完整流程2.6、应用场景与价值2.7、小结3、技术背景与应用场景3.1、推出时间与版本3.2、核心概念与作用3.3、适用场景核心价值3.4、不适用场景3.5、小结1、官方示例代码#includechrono#includefunctional#includememory#includesstream#includestring#includevector#includerclcpp/rclcpp.hpp#includerclcpp/publisher_options.hpp#includestd_msgs/msg/string.hppusingnamespacestd::chrono_literals;classMinimalPublisherWithUniqueNetworkFlowEndpoints:publicrclcpp::Node{public:MinimalPublisherWithUniqueNetworkFlowEndpoints():Node(minimal_publisher_with_unique_network_flow_endpoints),count_1_(0),count_2_(0){// Create publisher with unique network flow endpoints// Enable unique network flow endpoints via optionsautooptions_1rclcpp::PublisherOptions();options_1.require_unique_network_flow_endpointsRMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_OPTIONALLY_REQUIRED;publisher_1_this-create_publisherstd_msgs::msg::String(topic_1,10,options_1);timer_1_this-create_wall_timer(500ms,std::bind(MinimalPublisherWithUniqueNetworkFlowEndpoints::timer_1_callback,this));// Create publisher without unique network flow endpoints// Unique network flow endpoints are disabled in default optionspublisher_2_this-create_publisherstd_msgs::msg::String(topic_2,10);timer_2_this-create_wall_timer(1000ms,std::bind(MinimalPublisherWithUniqueNetworkFlowEndpoints::timer_2_callback,this));// Catch an exception if implementation does not support get_network_flow_endpoints.try{// Get network flow endpointsautonetwork_flow_endpoints_1publisher_1_-get_network_flow_endpoints();autonetwork_flow_endpoints_2publisher_2_-get_network_flow_endpoints();// Print network flow endpointsprint_network_flow_endpoints(network_flow_endpoints_1);print_network_flow_endpoints(network_flow_endpoints_2);}catch(constrclcpp::exceptions::RCLErrore){RCLCPP_INFO(this-get_logger(),%s,e.what());}}private:voidtimer_1_callback(){automessagestd_msgs::msg::String();message.dataHello, world! std::to_string(count_1_);RCLCPP_INFO(this-get_logger(),Publishing: %s,message.data.c_str());publisher_1_-publish(message);}voidtimer_2_callback(){automessagestd_msgs::msg::String();message.dataHej, världen! std::to_string(count_2_);RCLCPP_INFO(this-get_logger(),Publishing: %s,message.data.c_str());publisher_2_-publish(message);}/// Print network flow endpoints in JSON-like formatvoidprint_network_flow_endpoints(conststd::vectorrclcpp::NetworkFlowEndpointnetwork_flow_endpoints)const{std::ostringstream stream;stream{\networkFlowEndpoints\: [;boolcomma_skiptrue;for(autonetwork_flow_endpoint:network_flow_endpoints){if(comma_skip){comma_skipfalse;}else{stream,;}streamnetwork_flow_endpoint;}stream]};RCLCPP_INFO(this-get_logger(),%s,stream.str().c_str());}rclcpp::TimerBase::SharedPtr timer_1_;rclcpp::TimerBase::SharedPtr timer_2_;rclcpp::Publisherstd_msgs::msg::String::SharedPtr publisher_1_;rclcpp::Publisherstd_msgs::msg::String::SharedPtr publisher_2_;size_t count_1_;size_t count_2_;};intmain(intargc,char*argv[]){rclcpp::init(argc,argv);rclcpp::spin(std::make_sharedMinimalPublisherWithUniqueNetworkFlowEndpoints());rclcpp::shutdown();return0;}2、代码解析以上代码是 ROS 2 中带 “唯一网络流端点Unique Network Flow Endpoints” 配置的双发布者示例核心目的是演示如何为 ROS 2 发布者配置不同的网络流端点策略并获取 / 打印发布者的网络流信息。文本将从整体功能、核心概念、逐模块解析、运行逻辑四个维度对每个细节和背后的原理进行讲解。2.1、整体功能总结这个程序实现了一个 ROS 2 节点minimal_publisher_with_unique_network_flow_endpoints核心功能创建两个发布者publisher_1发布到 topic_1启用 “可选的唯一网络流端点”500ms 发布一次英文消息publisher_2发布到 topic_2使用默认配置禁用唯一网络流端点1000ms 发布一次瑞典语消息获取并打印两个发布者的网络流端点信息JSON 格式异常处理如果底层 RMWROS 中间件不支持 get_network_flow_endpoints 接口捕获并打印异常。2.2、核心前置概念在解析代码前先理解两个关键概念ROS 2 网络层核心RMWROS MiddlewareROS 2 的中间件抽象层底层对接 DDS如 FastDDS、CycloneDDS负责网络通信Unique Network Flow Endpoints唯一网络流端点作用为发布者 / 订阅者分配唯一的网络端口 / 流标识避免不同发布者 / 订阅者共享网络端点导致的流混淆策略RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_OPTIONALLY_REQUIRED 表示 “可选启用”—— 如果中间件支持则启用不支持则降级为默认策略场景多发布者 / 订阅者、高并发通信、网络隔离需求的场景如工业机器人、多机通信。2.3、逐模块代码解析头文件引入基础依赖#includechrono// 时间字面量500ms/1000ms#includefunctional// 函数绑定std::bind#includememory// 智能指针SharedPtr#includesstream// 字符串流拼接 JSON 格式#includestring// 字符串处理#includevector// 存储网络流端点列表#includerclcpp/rclcpp.hpp// ROS 2 核心 API#includerclcpp/publisher_options.hpp// 发布者配置选项核心网络流端点配置#includestd_msgs/msg/string.hpp// ROS 2 标准字符串消息重点rclcpp/publisher_options.hpp 是本次示例的核心必须引入才能配置发布者的网络流端点策略。时间字面量命名空间usingnamespacestd::chrono_literals;启用 C14 时间字面量简化定时器周期写法如 500ms 替代 std::chrono::milliseconds(500)。3. 发布者类定义核心逻辑classMinimalPublisherWithUniqueNetworkFlowEndpoints:publicrclcpp::Node{public:// 构造函数初始化节点、发布者、定时器、计数器MinimalPublisherWithUniqueNetworkFlowEndpoints():Node(minimal_publisher_with_unique_network_flow_endpoints),// 节点名count_1_(0),count_2_(0)// 两个发布者的计数器初始化{// 第一部分创建带“唯一网络流端点”的发布者publisher_1 // 1. 创建发布者配置选项autooptions_1rclcpp::PublisherOptions();// 2. 配置“可选的唯一网络流端点”策略options_1.require_unique_network_flow_endpointsRMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_OPTIONALLY_REQUIRED;// 3. 创建发布者topic_1队列大小10使用自定义配置 options_1publisher_1_this-create_publisherstd_msgs::msg::String(topic_1,10,options_1);// 4. 创建定时器500ms 触发一次 timer_1_callbacktimer_1_this-create_wall_timer(500ms,std::bind(MinimalPublisherWithUniqueNetworkFlowEndpoints::timer_1_callback,this));// 第二部分创建默认配置的发布者publisher_2 // 1. 创建发布者topic_2队列大小10使用默认配置禁用唯一网络流端点publisher_2_this-create_publisherstd_msgs::msg::String(topic_2,10);// 2. 创建定时器1000ms 触发一次 timer_2_callbacktimer_2_this-create_wall_timer(1000ms,std::bind(MinimalPublisherWithUniqueNetworkFlowEndpoints::timer_2_callback,this));// 第三部分获取并打印网络流端点信息异常处理 try{// 1. 获取两个发布者的网络流端点列表autonetwork_flow_endpoints_1publisher_1_-get_network_flow_endpoints();autonetwork_flow_endpoints_2publisher_2_-get_network_flow_endpoints();// 2. 打印网络流端点JSON 格式print_network_flow_endpoints(network_flow_endpoints_1);print_network_flow_endpoints(network_flow_endpoints_2);}catch(constrclcpp::exceptions::RCLErrore){// 捕获异常如果底层 RMW 不支持 get_network_flow_endpoints 接口RCLCPP_INFO(this-get_logger(),%s,e.what());}}private:// 定时器 1 回调函数publisher_1 发布逻辑 voidtimer_1_callback(){// 1. 创建 ROS 字符串消息automessagestd_msgs::msg::String();// 2. 拼接消息内容英文 计数器message.dataHello, world! std::to_string(count_1_);// 3. 打印日志RCLCPP_INFO(this-get_logger(),Publishing: %s,message.data.c_str());// 4. 发布消息到 topic_1publisher_1_-publish(message);}// 定时器 2 回调函数publisher_2 发布逻辑 voidtimer_2_callback(){// 1. 创建 ROS 字符串消息automessagestd_msgs::msg::String();// 2. 拼接消息内容瑞典语Hej, världen! 你好世界 计数器message.dataHej, världen! std::to_string(count_2_);// 3. 打印日志RCLCPP_INFO(this-get_logger(),Publishing: %s,message.data.c_str());// 4. 发布消息到 topic_2publisher_2_-publish(message);}// 辅助函数打印网络流端点JSON 格式 voidprint_network_flow_endpoints(conststd::vectorrclcpp::NetworkFlowEndpointnetwork_flow_endpoints)const{std::ostringstream stream;// 字符串流用于拼接 JSONstream{\networkFlowEndpoints\: [;// JSON 开头boolcomma_skiptrue;// 控制逗号避免第一个元素前加逗号// 遍历所有网络流端点for(autonetwork_flow_endpoint:network_flow_endpoints){if(comma_skip){comma_skipfalse;// 第一个元素跳过逗号}else{stream,;// 非第一个元素加逗号分隔}streamnetwork_flow_endpoint;// 输出单个端点信息NetworkFlowEndpoint 重载了 }stream]};// JSON 结尾// 打印 JSON 格式的网络流端点信息RCLCPP_INFO(this-get_logger(),%s,stream.str().c_str());}// 成员变量 rclcpp::TimerBase::SharedPtr timer_1_;// 定时器 1500msrclcpp::TimerBase::SharedPtr timer_2_;// 定时器 21000msrclcpp::Publisherstd_msgs::msg::String::SharedPtr publisher_1_;// 发布者 1带唯一网络流端点rclcpp::Publisherstd_msgs::msg::String::SharedPtr publisher_2_;// 发布者 2默认配置size_t count_1_;// 发布者 1 计数器size_t count_2_;// 发布者 2 计数器};主函数程序入口intmain(intargc,char*argv[]){rclcpp::init(argc,argv);// 初始化 ROS 2 上下文// 创建节点智能指针并进入自旋阻塞等待回调/消息rclcpp::spin(std::make_sharedMinimalPublisherWithUniqueNetworkFlowEndpoints());rclcpp::shutdown();// 关闭 ROS 2 上下文return0;}ROS 2 程序的标准入口逻辑和普通发布者示例一致无特殊逻辑。2.4、核心细节与关键考点唯一网络流端点的配置逻辑options_1.require_unique_network_flow_endpointsRMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_OPTIONALLY_REQUIRED;枚举值含义OPTIONALLY_REQUIRED → “可选启用”—— 如果底层 RMW如 FastDDS支持则启用唯一网络流端点不支持则忽略不报错。对比默认配置的 publisher_2 未设置该参数等价于 RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_DISABLED禁用。网络流端点的获取与打印publisher_-get_network_flow_endpoints()返回 std::vectorrclcpp::NetworkFlowEndpoint包含发布者的网络信息如 IP 地址、端口、传输协议、流标识等NetworkFlowEndpoint 重载了 运算符可直接输出为字符串格式由底层 RMW 决定打印为 JSON 格式是为了可读性方便解析 / 调试。异常处理的必要性get_network_flow_endpoints() 是 ROS 2 Humble 及以上版本新增的接口部分老旧 RMW 或自定义中间件可能不支持必须捕获 RCLError 异常否则程序会崩溃。双发布者的差异化配置维度publisher_1topic_1publisher_2topic_2网络流端点策略可选启用唯一端点默认禁用发布周期500ms1000ms消息内容英文Hello, world!瑞典语Hej, världen!配置选项自定义 PublisherOptions默认选项2.5、运行逻辑梳理完整流程程序启动 → main 函数初始化 ROS 2创建节点节点构造函数执行创建 publisher_1带唯一网络流端点 500ms 定时器创建 publisher_2默认配置 1000ms 定时器尝试获取两个发布者的网络流端点打印为 JSON 格式不支持则捕获异常并打印节点进入自旋定时器开始工作每 500mspublisher_1 发布英文消息到 topic_1计数器 count_1_ 自增每 1000mspublisher_2 发布瑞典语消息到 topic_2计数器 count_2_ 自增按下 CtrlC → 节点退出自旋ROS 2 上下文关闭程序结束。2.6、应用场景与价值这个示例的核心价值不是 “双发布者”而是ROS 2 网络层的精细化配置工业级通信在多机器人、高并发通信场景下唯一网络流端点可避免不同发布者的网络流混淆提升通信稳定性网络隔离 / 监控通过 get_network_flow_endpoints() 可获取发布者的网络端口、IP 等信息用于网络监控、防火墙配置中间件适配演示如何通过 PublisherOptions 配置中间件特性适配不同 RMW 的差异化功能。2.7、小结核心功能实现两个差异化配置的 ROS 2 发布者演示 “唯一网络流端点” 的配置、网络流信息的获取与打印关键技术PublisherOptions 的 require_unique_network_flow_endpoints 参数、get_network_flow_endpoints() 接口、异常处理核心价值ROS 2 网络层精细化配置的典型示例适用于工业级、高可靠性的通信场景。3、技术背景与应用场景3.1、推出时间与版本Unique Network Flow Endpoints唯一网络流端点 是 ROS 2 为解决网络流标识与 QoS 差异化而设计的特性。设计提案2021 年 5 月在 ROS 2 Design 文档中正式提出。正式发布随 ROS 2 Humble Hawksbill2022 年 5 月 稳定版发布成为 LTS 版本的标准特性ROS。核心 APIrclcpp::PublisherOptions::require_unique_network_flow_endpointsrclcpp::Publisher::get_network_flow_endpoints()rclcpp::NetworkFlowEndpoint 结构体RMW 支持FastDDS、CycloneDDS 等主流中间件在 Humble 及后续版本中逐步实现支持ROS。3.2、核心概念与作用默认问题ROS 2 默认下同节点、同话题的多个发布者 / 订阅者可能共享相同的网络流标识如端口、GID导致网络设备无法区分不同流无法对不同流做差异化 QoS带宽、优先级、延迟、丢包率。特性作用为每个发布者 / 订阅者分配唯一的网络流标识端口、流 ID、GID 等。让网络设备交换机、路由器、5G 核心网能识别不同流实现流级别的 QoS 控制、流量监控、防火墙策略、带宽隔离。配置枚举// 禁用默认RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_DISABLED// 可选启用RMW 支持则启用不支持则降级RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_OPTIONALLY_REQUIRED// 强制启用RMW 不支持则报错RMW_UNIQUE_NETWORK_FLOW_ENDPOINTS_STRICTLY_REQUIRED3.3、适用场景核心价值工业机器人 / 多机协作高实时、高可靠场景产线 AGV、机械臂集群、多机器人协同作业。痛点控制指令、传感器数据、状态反馈共用网络易被大流量数据如点云、图像抢占带宽导致控制延迟、抖动。价值为控制指令流分配高优先级、低延迟 QoS。为传感器数据流分配高带宽、可容忍丢包的 QoS。网络设备可按流标识做流量整形、优先级调度保障控制实时性。自动驾驶 / 车联网5G / 车规级网络场景自动驾驶车辆、V2X 通信、车路协同。痛点车辆内部CAN / 以太网、车 - 云、车 - 车通信需严格区分安全关键流制动、转向与非关键流娱乐、地图下载。价值结合 5G 5QIQoS 标识符为安全关键流分配高优先级、极低延迟如 10ms 内、零丢包的网络资源。网络可对不同流做独立计费、监控、故障隔离。高并发 / 大规模分布式系统场景多节点、多进程、多机器人组成的分布式集群如仓储物流、智慧城市。痛点大量发布者 / 订阅者共存网络流混杂难以定位通信瓶颈、排查丢包 / 延迟问题。价值通过 get_network_flow_endpoints() 获取每个发布者的端口、IP、协议、GID实现流级别的网络监控与故障定位。防火墙可基于流标识做精细化访问控制提升系统安全性。网络隔离与安全企业 / 军工场景场景涉密机器人、军工无人系统、企业内网隔离部署。痛点不同安全级别的数据流需物理 / 逻辑隔离防止越权访问、数据泄露。价值唯一流标识可作为安全隔离的最小单元实现不同功能模块的网络隔离。结合 SROS2实现流级别的加密、认证、访问控制。性能调优与网络规划场景机器人系统性能优化、网络架构设计。痛点无法量化不同流的带宽占用、延迟、丢包率难以针对性优化。价值基于流标识做流量统计、带宽分析识别瓶颈流。为网络规划交换机选型、带宽分配、QoS 配置提供精准数据支撑。3.4、不适用场景单节点、单发布者 / 订阅者无流区分需求开启会增加端口占用与配置复杂度。本地进程内通信localhost不经过物理网络QoS 配置无效无需开启。资源极度受限的嵌入式设备额外的端口 / 流管理会占用 CPU、内存资源。3.5、小结推出2022 年 5 月随 ROS 2 Humble 正式发布ROS。核心为发布者 / 订阅者分配唯一网络流标识实现流级 QoS、监控、隔离、安全。最佳场景工业机器人、自动驾驶、多机协作、车联网、大规模分布式系统等对实时性、可靠性、网络可控性要求极高的场景。