智能机器人的功能繁多,全都放在一个计算机里,经常会遇到计算能力不够、处理出现卡顿等情况,如果可以将这些任务拆解,分配到多个计算机中运行岂不是可以减轻压力?
这就是分布式系统,可以实现多计算平台上的任务分配。
一、分布式通信
之前我们也讲过,在ROS系统中,机器人功能是由各种节点组成的,这些节点可能位于不同的计算机中,这种结构可以将原本资源消耗较多的任务,分配到不同的平台上,减轻计算压力,这就是分布式通信框架的典型应用之一。
比如这款机器人系统中,有两个计算平台;
- 机器人体积比较小,不适合放一个笔记本电脑在上边,于是采用
NanoPC-T6开发板作为控制器,主要实现传感器驱动和电机控制等功能; - 不过视觉处理和应用功能就不适合在
NanoPC-T6开发板里运行了,我们放在另外一个性能更强的笔记本电脑中,此外我们还需要在电脑上监控机器人的传感器信息,并且远程控制机器人运动。
两个电脑之间的通信,看上去还有点复杂,毕竟相互传输的数据还挺多的,不过ROS系统都已经为我们设计好了,我们只需要在每一个电脑上配置好ROS环境,功能开发上完全不需要做任何变化,实现非常方便。
接下来,我们就一起来体验下ROS分布式系统的魅力。
1.1 ubuntu虚拟机环境搭建
在《ROS2概述和基于RK3588的环境搭建》我们使用了NanoPC-T6开发板搭建了ROS2环境,这里我们使用ubuntu虚拟机搭建另外一套ROS2环境,关于ubuntu 虚拟机的安装具体参考《Ubuntu虚拟机安装》。
1.1.1 ROS2系统安装
接下来,我们就可以把ROS2安装到ubuntu虚拟机中了,首先添加源:
zhengyang@ubuntu:~$ sudo apt install curl gnupg lsb-release
zhengyang@ubuntu:~$ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg zhengyang@ubuntu:~$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/nullzhengyang@ubuntu:~$ cat /etc/apt/sources.list.d/ros2.list
deb [arch=amd64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.tuna.tsinghua.edu.cn/ros2/ubuntu jammy mainzhengyang@ubuntu:~$ sudo apt update
安装ROS2:
zhengyang@ubuntu:~$ sudo apt upgrade
zhengyang@ubuntu:~$ sudo apt install ros-humble-desktop
默认安装到/opt/ros/humble目录;
zhengyang@ubuntu:~$ ll /opt/ros/humble
drwxr-xr-x 2 root root 4096 12月 16 23:15 bin/
drwxr-xr-x 2 root root 4096 12月 16 23:15 cmake/
drwxr-xr-x 108 root root 4096 12月 16 23:15 include/
drwxr-xr-x 77 root root 28672 12月 16 23:15 lib/
drwxr-xr-x 3 root root 4096 12月 16 23:15 local/
-rw-r--r-- 1 root root 373 5月 21 2025 local_setup.bash
-rw-r--r-- 1 root root 3902 7月 1 08:58 local_setup.sh
-rw-r--r-- 1 root root 15664 5月 21 2025 _local_setup_util.py
-rw-r--r-- 1 root root 379 5月 21 2025 local_setup.zsh
drwxr-xr-x 3 root root 4096 12月 16 23:15 opt/
-rw-r--r-- 1 root root 349 5月 21 2025 setup.bash
-rw-r--r-- 1 root root 4275 7月 1 08:58 setup.sh
-rw-r--r-- 1 root root 622 5月 21 2025 setup.zsh
drwxr-xr-x 283 root root 16384 12月 16 23:15 share/
drwxr-xr-x 4 root root 4096 12月 16 23:15 src/
drwxr-xr-x 3 root root 4096 12月 16 23:15 tools/
1.1.2 设置环境变量
在当前终端加入ROS2环境配置,可以立即使用ROS命令;
zhengyang@ubuntu:~$ source /opt/ros/humble/setup.bash
如果要永久生效,我们需要执行:
zhengyang@ubuntu:~$ echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
即将ROS配置添加到.bashrc文件,每次打开新终端都会自动加载。
注意:这里不要使用sudo,我们后面开发使用的就是普通用户zhengyang。
1.1.3 代码下载&&编译
拷贝NanoPC-T6开发板源码到ubuntu虚拟机中;
zhengyang@ubuntu:~$ mkdir -p ~/dev_ws/src
zhengyang@ubuntu:~$ cd dev_ws/src/
zhengyang@ubuntu:~/dev_ws/src$ scp -r pi@192.168.2.107:/home/pi/dev_ws/src/* ./
zhengyang@ubuntu:~/dev_ws/src$ ll
drwxrwxr-x 4 zhengyang zhengyang 4096 12月 16 23:06 jacket_detection_pkg_c/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 jacket_detection_pkg_python/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_action/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_interface/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_node/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_parameter/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_service/
drwxrwxr-x 5 zhengyang zhengyang 4096 12月 16 23:06 my_learning_topic/
drwxrwxr-x 26 zhengyang zhengyang 4096 12月 16 23:06 ros2_21_tutorials/
注意:ubuntu虚拟机IP地址为192.168.2.105,NanoPC-T6开发板IP地址为192.168.2.107。
安装依赖:
zhengyang@ubuntu:~/dev_ws/src$ sudo apt install -y python3-pip
zhengyang@ubuntu:~/dev_ws/src$ sudo pip3 install rosdepc
zhengyang@ubuntu:~/dev_ws/src$ sudo rosdepc init
zhengyang@ubuntu:~/dev_ws/src$ rosdepc update
zhengyang@ubuntu:~/dev_ws/src$ cd ..
zhengyang@ubuntu:~/dev_ws$ rosdepc install -i --from-path src --rosdistro humble -y
zhengyang@ubuntu:~/dev_ws$ sudo apt install python3-colcon-ros
# # 确保使用系统的Python包
zhengyang@ubuntu:~/dev_ws$ sudo pip uninstall numpy -y
zhengyang@ubuntu:~/dev_ws$ sudo apt install --reinstall python3-numpy python3-opencv
编译代码:
zhengyang@ubuntu:~/dev_ws$ colcon build
设置环境变量:
zhengyang@ubuntu:~/dev_ws$ source install/local_setup.sh
zhengyang@ubuntu:~/dev_ws$ echo "source ~/dev_ws/install/local_setup.sh" >> ~/.bashrc
1.2 分布式数据传输
ubuntu虚拟机配置完成后,确保已经和NanoPC-T6开发板连接到了同一个局域网络中,接下来我们打通两个计算平台的通信能力,具体需要做什么呢?
简而言之,什么都不需要做。我们直接用命令行测试一下话题通信的效果。
1.2.1 NanoPC-T6开发板
在开发板,使用如下命令启动一个发布者节点,节点会以固定频率(默认每秒一次)向 /chatter 话题发布 std_msgs/msg/String 类型的消息;
pi@NanoPC-T6:~/dev_ws$ ros2 run demo_nodes_cpp talker
[INFO] [1765898443.290089491] [talker]: Publishing: 'Hello World: 1'
[INFO] [1765898444.289929364] [talker]: Publishing: 'Hello World: 2'
[INFO] [1765898445.289903891] [talker]: Publishing: 'Hello World: 3'
......
[INFO] [1765898463.289720870] [talker]: Publishing: 'Hello World: 21'
[INFO] [1765898464.289650088] [talker]: Publishing: 'Hello World: 22'
[INFO] [1765898465.289564499] [talker]: Publishing: 'Hello World: 23'
[INFO] [1765898466.289475766] [talker]: Publishing: 'Hello World: 24'
[INFO] [1765898467.289370765] [talker]: Publishing: 'Hello World: 25'
[INFO] [1765898468.289326196] [talker]: Publishing: 'Hello World: 26'
[INFO] [1765898469.289211693] [talker]: Publishing: 'Hello World: 27'
[INFO] [1765898470.289176577] [talker]: Publishing: 'Hello World: 28'
[INFO] [1765898471.289235720] [talker]: Publishing: 'Hello World: 29'
[INFO] [1765898472.289015232] [talker]: Publishing: 'Hello World: 30'
[INFO] [1765898473.288960454] [talker]: Publishing: 'Hello World: 31'
1.2.2 ubuntu虚拟机
接下来在虚拟机,使用如下命令启动一个订阅者节点,节点会订阅 /chatter 话题;
zhengyang@ubuntu:~/dev_ws$ ros2 run demo_nodes_py listener
[INFO] [1765898463.241815861] [listener]: I heard: [Hello World: 21]
[INFO] [1765898464.232680067] [listener]: I heard: [Hello World: 22]
[INFO] [1765898465.232419733] [listener]: I heard: [Hello World: 23]
[INFO] [1765898466.232682488] [listener]: I heard: [Hello World: 24]
[INFO] [1765898467.232489282] [listener]: I heard: [Hello World: 25]
[INFO] [1765898468.232192649] [listener]: I heard: [Hello World: 26]
[INFO] [1765898469.232323659] [listener]: I heard: [Hello World: 27]
[INFO] [1765898470.232299185] [listener]: I heard: [Hello World: 28]
[INFO] [1765898471.232586267] [listener]: I heard: [Hello World: 29]
[INFO] [1765898472.232056527] [listener]: I heard: [Hello World: 30]
[INFO] [1765898473.232013101] [listener]: I heard: [Hello World: 31]
神奇的事情就这样发生了,只要两个计算机安装好ROS2,并且处于同一网络中,他们就可以实现之前讲过的话题、服务、动作等通信了,感觉就像在一个电脑里一样。
不过这也会带来一个问题,如果一个网络中有很多个计算机,我们并不希望他们都可以互通互联,而是可以分组通信,小组之间是无法实现通信的。
1.3 分布式网络分组
没问题,ROS2提供了一个DOMAIN的机制,就类似分组一样,处于同一个DOMAIN中的计算机才能通信。
我们可以在 ubuntu虚拟机和NanoPC-T6开发板的.bashrc中加入这样一句配置,即可将两者分配到一个小组中:
$ export ROS_DOMAIN_ID=<your_domain_id>
其中your_domain_id设置成一个具体数字。
二、分布式通信案例
2.1 小海龟分布式控制
分布式通信网络似乎已经建立成功了,是否真有我们想的这么神奇,我们继续测试之前学习过的一些案例,先来试试ROS中的经典案例——小海龟。
2.1.1 ubuntu虚拟机
进入ubuntu虚拟机桌面系统,启动第一个终端,运行小海龟仿真器;
hengyang@ubuntu:~/dev_ws$ ros2 run turtlesim turtlesim_node
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
[INFO] [1765898776.153979025] [turtlesim]: Starting turtlesim with node name /turtlesim
[INFO] [1765898776.164892701] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]
该指令将启动一个蓝色背景的海龟仿真器。
2.1.2 NanoPC-T6开发板
进入NanoPC-T6开发板桌面系统,运行如下指令:
pi@NanoPC-T6:~/dev_ws$ ros2 run turtlesim turtle_teleop_key
Reading from keyboard
---------------------------
Use arrow keys to move the turtle.
Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.
'Q' to quit.
该指令将启动一个键盘控制节点,在该终端中点击键盘上的“上下左右”按键,就可以控制小海龟运动啦。
2.2 话题分布式通信
我们之前编写的话题通信案例是否可以在不修改任何代码的情况下,直接使用呢?
2.2.1 ubuntu虚拟机
ubuntu虚拟机作为订阅者,订阅Hello World字符串:
zhengyang@ubuntu:~/dev_ws$ ros2 run my_learning_topic topic_helloworld_sub
[INFO] [1765899847.552366054] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899848.047724012] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899848.547411962] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899849.046847566] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899849.543365217] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899850.042852073] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899850.543550331] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899851.047129937] [topic_helloworld_sub]: I heard: "Hello World"
[INFO] [1765899851.543338505] [topic_helloworld_sub]: I heard: "Hello World"
2.2.2 NanoPC-T6开发板
NanoPC-T6作为发布者,发布Hello World字符串;
pi@NanoPC-T6:~/dev_wsros2 run my_learning_topic topic_helloworld_pub
[INFO] [1765899847.621922793] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899848.091729063] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899848.591811550] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899849.091519509] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899849.590804942] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899850.090894329] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899850.591572562] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899851.091764651] [topic_helloworld_pub]: Publishing: "Hello World"
[INFO] [1765899851.590533257] [topic_helloworld_pub]: Publishing: "Hello World"
2.3 服务分布式通信
我们之前编写的服务通信案例是否可以在不修改任何代码的情况下,直接使用呢?
2.3.1 ubuntu虚拟机
ubuntu虚拟机运行服务端程序,实现加法求和功能;
zhengyang@ubuntu:~/dev_ws$ ros2 run my_learning_service service_adder_server
[INFO] [1765899989.484504559] [service_adder_server]: Incoming request
a: 2 b: 3
2.3.2 NanoPC-T6开发板
NanoPC-T6作为客户端,发送求和请求;
pi@NanoPC-T6:~/dev_ws$ ros2 run my_learning_service service_adder_client 2 3
[INFO] [1765899989.560761457] [service_adder_client]: Result of add_two_ints: for 2 + 3 = 5
2.4 机器视觉分布式应用
以上这些功能还不够复杂?没问题,视觉识别的案例安排上。
接下来,我们将使用连接NanoPC-T6摄像头,模拟一个小型机器人,可以采集实时图像,然后再通过分布式网络,将图像发给ubuntu虚拟机处理节点,识别图像中的橙色物体。
2.4.1 ubuntu虚拟机
ubuntu虚拟机作为订阅者,订阅图像话题并实现视觉识别;
zhengyang@ubuntu:~/dev_ws$ ros2 run my_learning_topic topic_webcam_sub
[INFO] [1765900559.180033381] [topic_webcam_sub]: Receiving video frame
[INFO] [1765900559.231356659] [topic_webcam_sub]: Receiving video frame
[INFO] [1765900559.282422598] [topic_webcam_sub]: Receiving video frame
[INFO] [1765900559.333422282] [topic_webcam_sub]: Receiving video frame
......
2.4.2 NanoPC-T6开发板
NanoPC-T6作为发布者,发布图像话题:
pi@NanoPC-T6:~/dev_ws$ ros2 run usb_cam usb_cam_node_exe --ros-args -p video_device:="/dev/video21"
视觉识别的效果如下:
好啦,我们在分布式网络中测试了ROS一系列例程,都没有任何问题.
在实际的机器人开发中,类似的方法会频繁用到,ROS为分布式网络的搭建提供了非常友好的支持,我们几乎不需要任何配置,代码也不需要做任何修改,只要使用ROS系统,一切都会变得如此轻松。
参考文章
[1] 古月居ROS2入门教程学习笔记