文章目录
在 ROS 开发中,我们常需要将不同功能的节点(如感知、规划、控制)部署在独立的 Docker 容器中,以实现环境隔离和资源管理。但 Docker 容器默认的网络隔离特性会导致 ROS 节点无法直接通讯,本文将详细讲解如何配置网络和环境变量,实现 ROS1 跨 Docker 容器的节点通讯。
一、核心原理:ROS1 通讯的 2 个关键要素
ROS1 采用 “主从式” 架构,节点间通讯依赖主节点(roscore)的调度和节点身份的正确声明,这也是跨容器通讯的核心配置点:
- ROS_MASTER_URI:所有节点必须知道 roscore 的网络位置(格式:http://IP:端口),否则无法注册和获取话题 / 服务信息。
- 节点身份标识:每个节点需通过 ROS_IP 或 ROS_HOSTNAME(推荐) 声明自己的网络地址,确保其他节点能反向连接(如订阅者连接发布者)。二者的区别如下:
a) ROS_IP:直接填写容器 IP(如 172.18.0.2)。适用于网络不支持容器名解析时
b) ROS_HOSTNAME:填写容器名(如 talker_container)。适用于自定义网络(推荐,无需查 IP)
二、实现步骤:配置跨容器通讯
0. 前提条件
-
已安装 Docker并拉取 ROS1 基础镜像
-
可参考之前的文章了解基本概念和操作:
1.创建 Docker 共享网络
Docker 默认的bridge网络不支持容器名解析,需创建自定义桥接网络实现容器间的 DNS 互通(可参考:同一宿主机内不同docker间通讯):
# 创建名为ros_net的共享网络(名称可自定义)
sudo docker network create --driver bridge ros_net
# 验证网络是否创建成功
sudo docker network ls | grep ros_net
2. 启动 roscore 容器(主节点)
首先启动 roscore 作为 ROS 网络的 “调度中心”,需加入共享网络并配置环境变量:
sudo docker run -it \
--name roscore_container \
--network ros_net \
-p 11311:11311 \
--env ROS_MASTER_URI=http://roscore_container:11311 \
--env ROS_HOSTNAME=roscore_container \
osrf/ros:noetic-desktop-full \
roscore
参数说明:
--name roscore_container:容器名,后续用于地址解析
--network ros_net:将容器加入共享网络,确保与其他节点容器互通。
-p 11311:11311:# 暴露主节点端口(可选,供宿主机访问)
--env ROS_MASTER_URI:指定 roscore 的地址为容器名(自定义网络支持容器名解析,无需记 IP),声明主节点地址(容器名)。
--env ROS_HOSTNAME:声明自身地址(容器名)
osrf/ros:noetic-desktop-full:使用ROS1 noetic基础镜像
roscore:启动主节点
3. 启动发布者容器(talker 示例)
打开新的终端,启动一个发布/chatter话题的节点容器,配置需与 roscore 保持一致:
sudo docker run -it \
--name talker_container \
--network ros_net \
--env ROS_MASTER_URI=http://roscore_container:11311 \
--env ROS_HOSTNAME=talker_container \
osrf/ros:noetic-desktop-full \
rostopic pub /chatter std_msgs/String "data: 'Hello from Docker Talker'" -r 1
参数说明:
--name talker_container:容器名,后续用于地址解析
--network ros_net:将容器加入共享网络
--env ROS_MASTER_URI:指向同一roscore
--env ROS_HOSTNAME:声明自身地址(容器名)
osrf/ros:noetic-desktop-full:使用ROS1 noetic基础镜像
-r 1:表示每秒发布 1 条消息到/chatter 话题。
4. 启动订阅者容器(listener 示例)
sudo docker run -it \
--name listener_container \
--network ros_net \
--env ROS_MASTER_URI=http://roscore_container:11311 \
--env ROS_HOSTNAME=listener_container \
osrf/ros:noetic-desktop-full \
rostopic echo /chatter
参数说明:
--name talker_container:容器名,后续用于地址解析
--network ros_net:将容器加入共享网络
--env ROS_MASTER_URI:指向同一roscore
--env ROS_HOSTNAME:声明自身地址(容器名)
osrf/ros:noetic-desktop-full:使用ROS1 noetic基础镜像
rostopic echo /chatter:打印 /chatter 话题
验证结果:此时 listener 容器会实时打印 talker 发布的消息,说明跨容器通讯成功!




664

被折叠的 条评论
为什么被折叠?



