ROS多机通信

在充分的单机学习测试之后,往往要进行真实机器人的测试,那么就要接触到多机通信的问题。ROS采用的分布式网络通信,只要正确的设置ROS_MASTER_URIROS_IP两个环境变量,就可以成功实现ROS的多机通信,有时我们也称之为主从机设置,但是在这里初学者往往因为没有深入理解ROS通信机制而产生问题,ROS Wiki的说明也比较笼统,但是需要先行阅读,后面我们详细说明在多机通信产生问题时如何处理。

  • http://wiki.ros.org/ROS/NetworkSetup
  • http://wiki.ros.org/ROS/Tutorials/MultipleMachines

ROS消息通信机制

我们简单梳理一下,在消息通信时,什么时候会用到ROS_MASTER_URIROS_IP这两个环境变量。

  • Talker启动,通过ROS_MASTER_URI连接到ROS Master,注册发布者的信息,包含所要发布的话题名称(bar)和消息类型;ROS Master会将该发布者的注册信息存储到发布者注册列表中,等待接收者。

  • Listener启动,通过ROS_MASTER_URI连接到ROS Master,将其订阅的话题名bar和消息类型在ROS Master上注册(实际上也包括自己的地址和端口信息)。

  • ROS Master根据Listener所需的订阅话题在发布者注册列表寻找与之匹配的话题,并返回Talker的XML-RPC地址信息,即foo:1234。Listener根据alker的XML-RPC地址向Talker请求TCP的连接地址,Talker的地址就是图中所示的foo:2345。其中foo就是在执行talker时的环境变量ROS_IP的。

因此,如果需要正确接收到Talker发布的消息,必须在Talker和Listener上都正确设置ROS_MASTER_URI,同时必须正确设置Talker的ROS_IP,一般情况下,都是双向互通,所以listener的ROS_IP也要正确设置。

最常见问题:可以看到消息列表,但是无法接收消息内容

  • https://answers.ros.org/question/349095/ros-on-multiple-machine-not-working-properly/#349098

如何进行多机通信

这是最困扰大家的一个问题,我们用robot和 ROS2GO 来代表机器人上的电脑和远程操控的电脑。那么首先大家能够在robot和ros2go上能够相互ping通(相互ping通,保证是在同网段),也可以使用ssh成功从ros2go端登录到robot。

多机通信大家一般都会知道在 ROS2GO 端将 ROS_MASTER_URI 设置为robot的ip,这样就可以成功的使用rostopic list看到话题列表。不过rostopic echo /foobar是看不到任何消息的(很大概率,也有例外,后面我们说明)。这个最主要的问题就是没有在robot上设置ROS_IP这个环境变量。

类似的,如果 ROS2GO 端的 ROS_IP 没有设置正确,可能发生在RViz中能够看到传感器的数据,但是发布2D Nav Goal而机器人完全没反应的状况。总结一下,如果能看到话题列表而没有话题内容,就是因为通讯是没问题的可以在ROS Master上注册,但是上报地址错了导致后面无法进行点对点通信。

安全可靠

全部用 IP 地址进行设置,ROS_MASTER_URIROS_IP都可以在.bashrc文件中设置。我们假设robot的IP地址为192.168.1.100,ros2go的ip地址为192.168.1.111,roscore在robot上启动(一般我们都是在robot上启动roscore)。

那么在robot上

export ROS_MASTER_URI=http://192.168.1.100:11311
export ROS_IP=192.168.1.100

在 ROS2GO 上

export ROS_MASTER_URI=http://192.168.1.100:11311
export ROS_IP=192.168.1.111

这样的设置是一定可以互通的。因为本地回环的存在,在robot上可以设置为

export ROS_MASTER_URI=http://localhost:11311
export ROS_IP=192.168.1.100

方便快捷

为了方便大家使用,我们不建议频繁在从机端的修改.bashrc文件,可以将ROS_MASTER_URI和ROS_IP的ip地址设置在外置脚本.ros_master.sh中。

touch .ros_master.sh && chmod +x .ros_master.sh

使用如下命令写入外置脚本.ros_master.sh中。

echo '## set $ROS_MASTER_URI and $ROS_IP for Multi Machine Communicate
export ROS_MASTER_URI=http://192.168.1.100:11311
IP=$(ip addr show wlan0 | grep -w inet | awk '{print $2}' | awk -F / '{print $1}')
export ROS\_IP=${IP}' >> ~/.ros_master.sh

使用方法

source ~/.ros_master.sh

如果需要修改ROS_MASTER_URI,只需要修改.ros_master.sh此脚本的export ROS_MASTER_URI=http://192.168.1.100:11311192.168.1.100为正确IP即可。

用正则截取相应设备IP

用IP进行设置确实不会出问题,但是只要更换网络或者设备的IP发生变化等,多机通信就失效了需要重新设置。在Linux系统中我们有多种方式可以获得当前的IP地址。以下都是设置ROS_IP的方式。

最简单的情况下,仅有ipv4地址时,可以如下设置

export ROS_IP=`hostname -I`

但是有ipv6的地址时,需要截取

export ROS_IP=`hostname -I | cut -d " " -f 1`

不过有多个ipv4地址的情况下,比如使用NVidia Jetson系列板卡,会虚拟出一个usb网络,那么不能够保证截取到正确的ipv4地址。
非常确定的要截取某个网络下的ipv4地址时,可以使用如下命令

IP=$(ip addr show wlan0 | grep -w inet | awk '{print $2}' | awk -F / '{print $1}')
export ROS\_IP=${IP}

这样可以截取wlan0网络下的ipv4地址,已经非常灵活通用。但是在网络未准备好的情况下,截取的内容是空,这时候启动roscore或者其他节点时会报如下错误:

invalid ROS_IP (an empty string)

这样虽然在启动roscore时会用hostname信息替代,但是节点启动时上报的ROS_IP信息为空,会导致节点间无法通信。需要将ROS_IP的设置注释掉,或者保证ROS_IP能拿到正确的地址。

设置hostname

当我们不设置ROS_IP的时候,实际上节点上传到ROS Master的地址是本机的hostname。使用rosnode info查看可以看到节点的地址类似于 http://ros2go:33333/

  • 为什么我们没有设置ROS_IP时,节点之间还是可以成功通信呢?

  • 原因是系统启动时会上报自己的hostname给路由器,路由器的dns可以在局域网内成功解析hostname,对应到正确的IP地址从而使得ROS实现多机通信。但是因为多种因素,路由器dns解析的成功率非常不靠谱。

最简单的hostname设置

路由器可以正确解析hostname,那么可以按照官方教程,仅设置/etc/hostname文件(实际上这个文件一般也都设置好了),写入hostname即可。如果可以起作用,那么我们不用设置ROS_IP,就可以实现多机通信。这种情况最大的问题就是不可靠,也是产生问题的根源。

强制解析

设置/etc/hosts文件,在文件中加入强制hostname和IP地址的对应关系。这样设置的问题和纯IP设置类似,在网络条件发生变化的时候还是要修改。好处是hostname可以有意义,比IP地址好记的多。

使用ROS2GO和Tianbot官方的设备时,我们已经将比较优化的设置写入了.bashrc,大家可以根据需要去掉注释。

### ROS 多机通信配置与实现方法 #### 主从机网络设置 为了确保多台计算机能够相互通信,必须确认所有设备处于同一网段内。通过 `ifconfig` 命令可以查询各节点的 IP 地址[^1]。 #### 配置环境变量 针对每一台参与通信的机器(无论是作为主机还是从机),都需要修改其 `.bashrc` 文件来指定主节点的位置以及本机在网络中的身份标识。具体操作如下: - 设置ROS Master URI指向运行roscore服务的那一方; - 设定ROS HOSTNAME为当前电脑的实际IP地址; 例如,在一台充当主机的角色中,可能有如下配置: ```bash export ROS_MASTER_URI=http://192.168.1.66:11311 export ROS_HOSTNAME=192.168.1.66 ``` 而在另一些扮演从属地位的工作站,则应相应调整上述参数以匹配实际情况[^5]。 #### 启动核心组件和服务 在选定为主控端的一侧启动ROS的核心进程——`roscore`,这一步骤对于整个系统的正常运作至关重要。之后可以根据需求加载特定的应用程序或模拟器,比如`turtlesim_node`用于展示基本功能[^4]。 #### 测试连接状态 一旦完成了以上准备工作,便可以在任意客户端尝试执行`rostopic list`指令,以此验证是否成功接入到了由Master管理的消息总线体系之中[^3]。 #### 实现复杂交互逻辑 当基础架构搭建完毕后,可以通过编程方式进一步扩展应用范围。例如创建自定义类如`Robot`和`MultiRobot`来进行更高级别的抽象处理,其中涉及到了多个实体间的信息交换机制的设计与实施[^2]。 ```python class Robot: def __init__(self, name): self.name = name def publish_message(self, topic_name, message_content): pass # 发布消息到指定主题 class MultiRobot: robots = [] @staticmethod def initialize_robots(): robot_names = ['robot1', 'robot2', 'robot3'] for name in robot_names: new_robot = Robot(name) MultiRobot.robots.append(new_robot) # 初始化并控制三台机器人实例 MultiRobot.initialize_robots() for r in MultiRobot.robots: print(f'Starting {r.name}') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值