大家好,我是爱吃灰的小鱼,经过昨天的折腾,家里的网络问题总算解决了,买了个二手路由器,一看里面的日志居然是2006年出产的,这岁数比ROS都大。
看着路由器想起来小鱼吃灰的树莓派3B,挂在闲鱼上至今没有卖出去,算了再折腾折腾。
所以就有了今天的ROS2多机通信,顺便也讲讲ROS2是如何通过组播发现其他主机的节点的。
可以使用下面指令查看网络配置,返回可能有多个,根据你电脑网卡数量有关系,不过记得要标有ip地址的,比如下面的编号为2的网卡,ip地址为:inet 10.55.23.148,应该还会看到一个叫做127.0.0.1的ip,这个ip是用于本地回环的,可以暂且忽略。
ip a
然后换到电脑终端看一下电脑的网络,操作相同,可以看到ip为,10.55.23.40。
大家可以看到ip地址后面都标有/24,大家将24/8=3,3就代表ip地址前三位相同,比如电脑和树莓派的前三位都是10.55.23
ip a
ros2提供了网络检查CLI(命令行接口)工具,multicast ,我们可以使用multicast执行对两个ros2终端进行测试。
来尝试以下
首先在电脑端我们启动接收组播指令
ros2 multicast receive
在树莓派上,我们发送一个组播,
ros2 multicast send
然后你如果在接收终端看到如下打印,说明你的ROS2已经可以多机通信啦~
可以清楚看到电脑终端中的打印了来自树莓派的亲切问候。
以小鱼的尿性这样子肯定不算结束,至少要对原理说一说,其实就是UDP的组播。
所谓组播,可以理解为在小组里广播,需要指明小组成员,广播就是喊话,我们用树莓派发送send,就是让树莓派喊话,电脑端启动一个接收,如果树莓派这边喊话了,电脑端就能听到来自树莓派的话,并且接收到来自树莓派的函数内容以及树莓派的信息。
这里还有个小知识点,如果我们不启动接收端,只让发送端发,发送端其实只会发一次就结束了,并且发送端是没有任何提示的。那如果我们先启动发送端,再启动接收端,接收端还没开始接收呢,发送端就发送结束了,这样就收不到了,遇到这种情况不要慌,在喊一次就行了。
除了组播还是有广播、单播,单播就是只对一个人喊话,广播是对所有人所有的组喊话。以后有机会小鱼再讲。
这个其实很简单,我们先在树莓派上启动一个示例程序发话题,然后在电脑端直接接收,话题数据,看看能不能收到。
ros2 run examples_rclcpp_minimal_publisher publisher_member_function
如果报错没有examples_rclcpp_minimal_publisher 功能包,可以用下面的指令安装下
sudo apt install ros-foxy-examples-rclpy-minimal-publisher
先用ROS2的CLI看一下是否有话题
ros2 topic list
再看一下话题信息,并打印一下话题内容
ros2@ubuntu:~$ ros2 topic info /topic
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 0
打印一下数据,完美显示~
ros2 topic echo /topic
通过上面的实验,我们知道ROS2如何实现多机通信的了。那还有一些问题,是不是只要是同一个局域网,只要树莓派发布数据其他电脑就能收到,怎么分离呢?
这里就可以引入ROS_DOMAIN_ID的概念了,只有ROS_DOMAIN_ID相同的主机才能通信,那为什么刚刚树莓派没有设置主机ID,电脑也没设置但是他们能通信呢?
原因在于他们有ROS_DOMAIN_ID有默认值0.
继续动手,我们把树莓派的ROS_DOMAIN_ID改成1,看看和电脑还能不能通信了?
如何设置ROS_DOMAIN_ID呢?
export指令可以帮助我们完成,export Name=Value 可以为我们在当前终端中临时添加一个名字叫Name值为Value的环境变量,添加完成后,使用echo指令就可以查看环境变量的值
export ROS_DOMAIN_ID=1
echo $ROS_DOMAIN_ID
继续做实验,先试试组播能不能检测到
电脑端
ros2 multicast send
树莓派
ros2 multicast receive
结果你猜,居然还可以
ros2@ubuntu:~$ ros2 multicast receive
Waiting for UDP multicast datagram...
Received from 10.55.23.148:47451: 'Hello World!'
组播还可以收到,看看话题通信行不行
启动树莓派端开始发布话题
ros2 run examples_rclcpp_minimal_publisher publisher_member_function
电脑端检查话题列表
ros2 topic list
为什么设置了ROS_DOMAIN_ID之后,multicast依然可以检测到对方呢?
因为组播只是发送出去一个广播,并不会对接收方进行过滤,接收方也只是接收,不会对发送者进行过滤。
简单的理解就是,multicast只是测试物理上通不通,不对ROS_DOMAIN_ID进行检查。
小鱼觉得ROS2的这种局域网互相发现机制的确比ROS1的好用太多,还要设置主机地址之类的,其实挺麻烦的。小鱼昨天还有一个大胆的想法,怎么把ROS2分成两部分,一部分放在云服务器上,一部分放在我们的小车上,云服务器来直接进行数据的处理,感觉很有意思,以后有机会再折腾。
既然是多机通信其实还涉及到另外一个问题,那就是安全,其实ROS2也有安全通信的设计,这个等小鱼研究研究之后再写篇文章总结一下。
本篇文章只是从使用的角度讲了一下ROS_DOMAIN_ID,对其原理之类没有深入挖掘,有兴趣的同学可以看看下面的参考链接哦~
我是小鱼,目前在做公众号,名字叫做《鱼香ROS》,想和小鱼和鱼粉们一起交流学习机器人吗?关注公众号鱼香ROS,点击下方鱼群加入~