ROS可以说是目前机器人相关开源社区最流行的项目之一,它是一个易用且完备的机器人开发框架、生态乃至社区,海量的机器人开源项目(涵盖感知、规划、控制、定位、SLAM和建图、可视化等几乎所有机器人领域)均使用ROS作为基础。以自动驾驶汽车为代表的新的机器人应用场景对于中间层和开发框架在实时性、可靠性、伸缩性、跨平台可移植等方面提出了大量新的需求,ROS显然不能满足这些需求,ROS2因此产生,在经历了若干年的迭代后,ROS2项目目前已经相对完备和稳定,对于我们开发者而言,是时候拥抱ROS2了。
为什么转向ROS2
ROS自2007年发布以来,为机器人社区提供了一套相对完善的中间层、工具、软件乃至通用的接口和标准,可以说,凭借ROS,机器人工业领域的开发者能够快速开发系统原型并做测试和验证。自动驾驶本质上是机器人研究的一个应用领域,在产品原型快速开发的过程中也通常会采用ROS。
如果说ROS1为科研和原型开发提供了很好的生态的话,那么ROS2就是用于实际产品的部署环境的开发架构和相应工具链。
ROS1的天然缺陷
ROS1项目的初衷是为了给科研机器人Willow Garage PR2提供一个开发环境和相应的工具,为了让这套软件在更多的机器人上运行,ROS为机器人开发构建了应用层的抽象和通用的消息接口,最终在机器人社区中广为使用并发展为目前最流行的机器人软件生态体系之一。然而,ROS1研发的初衷就注定了该架构存在以下缺陷:
- 无实时性(real-time)
- 嵌入式设备不友好
- 对于网络通信的重依赖(需要大带宽且稳定的网络连接)
- 多用于学术应用
- 超高的灵活性带来的不规范的编程模式
- 原生的ROS仅支持单机器人
然而如今ROS已在大量工业领域的应用,包括科研机器人、工业机器人、轮式机器人、自动驾驶汽车乃至航天无人驾驶设备,其原来的功能设计已经不能满足海量应用对于某些性能(如实时性、安全性、嵌入式移植等)的需求,ROS2即在这样的背景下被设计和开发。
ROS2相较于ROS1的提升和改进
相较于ROS1,ROS2在设计之初就考虑了在产品环境下面临的一些挑战,具体来说,ROS2采用(或者计划采用)以下策略以提升其在产品环境的适用度:
- 支持多机器人
- 对小型嵌入式设备和微控制器的支持
- 实时系统:支持实时控制,包括进程间和机器间通信的实时性
- 支持非理想网络环境:在低质量高延迟等网络环境下系统仍然能够工作
- 对产品环境的支持的能力
- 规范的编程模型以支持基于ROS的大规模目的构建、开发和部署
ROS2中的DDS中间层
ROS1的核心是一个基于master中心节点的匿名发布-订阅通信中间层,相比之下,ROS2采用基于RTPS(Real-Time Publish-Subscribe)协议的DDS作为中间层,DDS(Data-Distribution Service)是一种用于实时和嵌入式系统发布-订阅式通信的工业标准,这种点到点的通信模式类似于ROS1的中间层,但是DDS不需要像ROS1那样借由master节点来完成两个节点间通信,这使得系统更加容错和灵活,DDS被广泛应用于关键系统中,包括战舰、大型基础设施(如水电站)、金融系统、空间系统、航空系统等场景,这些用例也证实了DDS的可靠性。
多个厂商提供多种DDS实现,一般来说DDS的底层通信机制基于UDP协议或者共享内存机制(当然也有厂商提供基于TCP的DDS实现),而ROS2支持多种DDS实现,用户可以根据实际情况选择DDS中间层,目前来说ROS2 Foxy完整支持以下DDS中间层:
- eProsima的Fast RTPS(当前ROS2版本默认的DDS实现)
- RTI的Connext DDS
- Eclipse Cyclone DDS
了解更多DDS相关背景,可以参考这篇文章:https://design.ros2.org/articles/ros_on_dds.html
ROS2的内部架构:
ROS2的内部接口主要包括两个层:
- rmw (ros middleware interface): 相对底层的接口层,直接和DDS交互,C语言实现
- rcl (ros cliend libraries): 对rmw相对高层的抽象,c/c++实现
此外上图中还有一个ros_to_dds
组件,该组件主要为用户直接访问DDS层提供接口。
更多关于rmw和rcl等中间层的实现机制以及ROS msg,DSS idl文件和python、c++和C上的类(或者结构体)的转换可以参考ROS2官方文档:https://docs.ros.org/en/foxy/Concepts/About-Internal-Interfaces.html
ROS2中的QoS策略
ROS2中引入了Quality of Service, QoS(服务质量)的策略用于配置节点间通信,进而提升了ROS2适应于不同应用场景的灵活性。ROS1只支持基于TCP的通信,通过配置QoS,ROS2可以表现出TCP的可靠性,也可以表现出UDP那样的高实时性。用户可以通过选择不同的QoS配置文件以实现不同的通信表现,QoS配置文件为策略的集合,ROS2提供了预设的QoS配置文件,如下所示:
- 发布-订阅机制的QoS设定
- 服务(Service)的QoS设定
- 传感器数据的QoS设定
- 参数的QoS设定
- DDS中间层默认的QoS设定
ROS2的安装和开发环境准备
ROS2目前几乎每半年会release一个版本,不同的版本会有对应的代号(类似与ROS1中的Kinetic, Melodic和Noetic等版本代号),以下是ROS2的一些历史版本:
- Crystal: 2018年12月
- Dashing: 2019年5月底
- Eloquent: 2019年11月
- Foxy: 2020年6月
- Galactic: 2021年5月
我们以最新的Galactic为例,ROS2是跨平台的架构,同时支持Linux, MacOS 和Windows,但是依据我们在ROS1上开发的经验,我依然推荐大家在Linux的Ubuntu发行版上从事相应的ROS2 Application开发工作。在Ubuntu上,安装ROS2可以通过binary安装或者源代码编译安装,在Ubuntu上,最简单的安装方式是通过Debian packages安装(也就是apt安装),我们以此为例,在Ubuntu 20.04上使用apt安装ROS2的Galactic版本。
ROS2在Ubuntu下的安装
在你的Ubuntu 20.04系统中,配置ROS2的apt源:
sudo apt update && sudo apt install curl gnupg lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
更新apt索引:
sudo apt update
使用apt安装完整的ROS2:
sudo apt install ros-galactic-desktop
安装完成后,在~/.bashrc
文件中添加ros2的环境变量:
echo "source /opt/ros/galactic/setup.bash" >> ~/.bashrc
简单地验证一下安装情况,新建一个terminal,运行demo的talker:
ros2 run demo_nodes_cpp talker
在另一个terminal中,运行listener:
ros2 run demo_nodes_py listener
可以看到,一个类似于ROS1的Publisher-Subscriber通信demo就运行起来了:
不难发现,ROS2并不需要像ROS1那样启动roscore(即master节点),ROS2这种去中心化的策略能让其适应更多工业应用和产品级应用场景的需求。
Note: ROS1和ROS2可以并存于同一台电脑,你只需要source不同的setup.bash即可完成环境的选择。
ROS2的基本工具和命令
和ROS1一样,ROS2也提供了大量的开发调试工具,如Rviz, Rqt等工具均已经可以在ROS2中使用,运行rqt
,可以看到我们刚刚运行的两个demo节点:
运行 rviz2
可以启动ROS2环境下的rviz软件。
同时,ROS2也提供类似于ROS1的命令行指令,指令和ROS1略有区别:
ros2 node
: 输出node相关信息ros2 topic
: topic相关指令,包括list,hz,echo等ros2 service
: service相关指令,如list,call,type等ros2 bag
: rosbag相关指令, 录包,播包,打印数据包信息等ros2 bag
: package相关指令ros2 param
: 参数相关ros2 launch
: 运行launch文件ros2 run
: 运行单个节点
完整的ros2命令如下所示:
绝大多数指令基本是将ros1中的rosxxxx拆分成了ros2 xxxx