机器人操作系统(The Robot Operating System,简称 ROS)是用于构建机器人应用程序的一组软件库和工具。从驱动程序到最新算法(state-of-the-art algorithms),再到强大的开发人员工具,ROS 可以满足您下一个机器人项目的需求。而且都是开源的。
自 ROS 于 2007 年启动以来,机器人技术和 ROS 社区已发生了许多变化。ROS2 项目的目标是适应这些变化,充分利用 ROS1 的优点,并改善不受欢迎的事物。在这里,您可以找到有关 ROS 2(ROS的最新版本)的官方文档。如果您要查找有关 ROS1 的文档(即 ROS,因为它已经存在了几年,以及您现在可能使用的是什么),请查看 ROS wiki。
1 如何开始
新手和经验丰富的 ROS 用户应查阅以用户为中心的内容的概述,以查找所需内容。
Installation 页面将帮助您首次设置 ROS 2。您可以选择平台以及适合您需要的安装类型和发行版。
Tutorials 会带您逐步学习 ROS 2,无论您是从头开始学习还是在寻求实现更具体目标的指导。
Concepts 是有关 ROS 2 核心概念的高级解释和背景信息,应该为教程中涵盖的主题提供一些上下文。
Troubleshooting 指南涵盖了可能会出现问题的一些特定的常见情况。
Contributing 是使 ROS 2 出色的原因!它提供了有关最佳实践和方法的指南,以贡献新的 ROS 2 内容以及将现有内容从 ROS 1 迁移到 ROS 2。
始终鼓励使用 Getting help。在这里,您将找到几种获取问题答案或进行讨论的方法。
在线上有大量资源可用于了解有关 ROS 2 的更多信息。以下是一些资源:
-
design.ros2.org 包含有关 ROS 2 背后的设计决策的各种文章,例如:
ROS 2 的代码是开源的,分为多个存储库。您可以在 ros2 GitHub organization 中找到大多数存储库的代码。
awesome-ros2 是 ROS 2 软件包和资源的“备忘单”样式快速参考,可帮助 GitHub 用户了解 ROS 2。
这组 ROSCon talks 为各种 ROS 2 概念提供了一些上下文。
2 关于 ROS2
如果您对 ROS 2 项目的业务和发展方面感兴趣,则这些页面提供了各个相关领域的高级详细信息。
- Releases:过去,现在和将来的 ROS 2 发行版本,包括发行日期和发行之间的更改。
- Features:当前 ROS 2 版本中包含的功能,以及每个新功能的详细内容。
- Roadmap 是尚未实现但即将推出的 ROS 2 功能思想的集合。
- Project governance 由技术指导委员会负责,您可以在此处了解更多信息。
- 可以从此页面下载宣传 ROS 2 的 Marketing。
3 安装 ROS2
接下来将介绍如何在 Windows10 安装 ROS2。
首先,安装 Anaconda3,接着按照如下教程安装即可。
3.1 Windows10 安装 ROS2
- 打开 PowerShell,创建并激活 ros2 环境:
$ conda create -n ros2 python=3.8
$ cmd
$ conda activate ros2
- 安装 Git:
$ choco install -y git
需要添加环境变量 C:\Program Files\Git\cmd
到 Path
- 安装开发工具:
$ pip install -U vcstool # 运行 vcs 测试是否安装成功
$ pip install -U colcon-common-extensions # # 运行 colcon 测试是否安装成功
$ choco install -y curl
- 安装依赖包
$ pip install setuptools pip --upgrade
$ pip install catkin_pkg cryptography EmPy ifcfg importlib-metadata lark-parser lxml numpy pyparsing pyyaml
安装单元测试包:
$ pip install pytest pytest-mock coverage mock
安装自动补全工具包:
$ pip install flake8 flake8-blind-except flake8-builtins flake8-class-newline flake8-comprehensions flake8-deprecated flake8-docstrings flake8-import-order flake8-quotes mypy pep8 pydocstyle
安装 cppcheck
:
$ choco install -y cppcheck
安装 xmllint
:
- 从 https://www.zlatkovic.com/projects/libxml/ 下载 64 bit binary archives 的
libxml2
(依赖于iconv
andzlib
) - 解压到
C:\xmllint
- 添加
C:\xmllint\bin
to thePATH
安装 GUI 包:
$ pip install -U pydot PyQt5
- 安装 ROS2:
首先设置一个开发文件夹,例如 D:\dev\ros2_rolling
:
$ md \dev\ros2_rolling\src
$ cd \dev\ros2_rolling
获取 ros2.repos
文件,该文件定义了要克隆的存储库:
# CMD
$ curl -sk https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos -o ros2.repos
# PowerShell
$ curl https://raw.githubusercontent.com/ros2/ros2/master/ros2.repos -o ros2.repos
接下来,您可以使用 vcs
导入 ros2.repos
文件中列出的存储库:
# CMD
$ vcs import src < ros2.repos
# PowerShell
$ vcs import --input ros2.repos src
3.2 Ubuntu 安装 ROS2
Ubuntu 安装请见 Building ROS 2 on Linux。
ROS2 的 RWM 默认使用的 DDS 是 Fast RTPS,Cyclone DDS 默认也安装好了,还可以这样安装 RTI Connext:
$ sudo apt update
$ sudo apt install ros-foxy-rmw-connext-cpp # for RTI Connext (requires license agreement)
安装之后通过环境变量即可切换DDS:
$ RMW_IMPLEMENTATION=rmw_connext_cpp
如果哪一天不喜欢了,还可以这样删除 ROS2:
$ sudo apt remove ros-foxy-* && sudo apt autoremove
3.3 识别 ROS2
ROS 2 依赖于使用 Shell 环境组合工作空间的概念。“Workspace”(工作空间)是 ROS 术语,表示您正在使用 ROS 2 开发的系统上的位置,也是我们开发机器人代码的位置。核心 ROS 2 工作空间称为 underlay。后续的本地工作空间称为 overlay。使用 ROS 2 进行开发时,通常将同时激活多个工作区。我们可以通过 source
不同空间的环境变量脚本来更换所使用的 workspace,包括 ROS2 的版本。
组合工作区使针对不同版本的 ROS 2 或针对不同组的软件包的开发变得更加容易。它还允许在同一台计算机上安装多个 ROS 2 发行版(或“distros”,例如 Dashing 和 Eloquent),并在它们之间进行切换。
这可以通过在每次打开新的 Shell 时获取 setup 文件来完成,或者一次将 source 命令添加到 Shell 启动脚本中来实现。如果不提供 setup 文件,则将无法访问 ROS 2 命令,也无法找到或使用 ROS 2 软件包。换句话说,您将无法使用 ROS 2。
您将需要在打开的每个新 Shell 上运行如下命令,以访问 ROS 2 命令:
# Ubuntu
$ source /opt/ros/<distro>/setup.bash
# Windows
# 确切的命令取决于ROS 2的安装位置。如果遇到问题,请确保文件路径引导您进行安装。
$ call D:\dev\ros2\local_setup.bat
如果您不想每次打开新的外壳程序时都需要获取安装文件的源代码(即跳过任务1),则可以将命令添加到外壳程序启动脚本中:
# Ubuntu
$ echo "source /opt/ros/<distro>/setup.bash" >> ~/.bashrc
要在 Linux 和 macOS 中撤消此操作(更改为其他发行版),请找到系统的 Shell 启动脚本并删除附加的 source 命令。
命令 colcon_cd
允许您快速将 Shell 的当前工作目录更改为软件包的目录。例如,colcon_cd some_ros_package
会将您快速带到目录~/ros2_install/src/some_ros_package
。
$ echo "source /usr/share/colcon_cd/function/colcon_cd.sh" >> ~/.bashrc
$ echo "export _colcon_cd_root=~/ros2_install" >> ~/.bashrc
根据安装 colcon_cd
的方式和工作空间的位置,上述说明可能有所不同,请参阅 the documentation 以获取更多详细信息。要在 Linux 和 macOS 中撤消此操作,请找到系统的 Shell 启动脚本并删除附加的 source
和 export
命令。
定位 ROS 2安装文件将设置操作 ROS 2 所需的几个环境变量。如果在查找或使用 ROS 2 软件包时遇到问题,请使用以下命令确保正确设置了环境:
$ printenv | grep -i ROS
如果在局域网的多台电脑中使用 ROS2,默认的通信机制会自动建立各机器分布式通信框架,也就是不同电脑之间已经可以通信了,如果你不希望多台电脑之间产生连接,可以设置不同的组网 ID,相同 ID 的电脑之间可以通信,不同 ID 的电脑之间无法通信。
如果您的实验室或办公室有多个不同的运行 ROS 2 的计算机组,并且希望避免这些组之间发生串扰,请选择一个整数并将其设置为组中所有计算机上的环境变量ROS_DOMAIN_ID。为每个子组选择一个不同的唯一整数。(对于 eProsima Fast RTPS 上的默认 RMW,从 ROS 2 Eloquent 开始,此整数必须介于 0-232 之间,才能成功启动 ROS 2 守护程序)。
domain ID 用于对网络进行分段,以避免在同一局域网上运行 ROS 2 的不同计算机组之间的干扰。具有不同 domain ID 的机器不会互相通话,也不会互相干扰。
如果遇到多台计算机相互交谈的问题,请检查 Troubleshooting。此外,在 Discourse 和 Answers
网站上有多个过去的对话,其中包含更深入的信息。为 ROS 2 代理组确定唯一的整数后,可以使用以下命令设置环境变量:
Linux:
$ export ROS_DOMAIN_ID=<your_domain_id>
# 要在Shell会话之间保持此设置,可以将命令添加到Shell启动脚本中:
$ echo "export ROS_DOMAIN_ID=<your_domain_id>" >> ~/.bashrc
Windows:
$ set ROS_DOMAIN_ID=<your_domain_id>
# 如果要在两次shell会话之间保持此永久性,请运行:
$ setx ROS_DOMAIN_ID <your_domain_id>
接下来,我们将了解 ROS2 的核心概念。
4 理解节点
ROS grph 是由 ROS 2 元素同时处理数据的网络。如果要将它们全部映射并可视化,则它包含所有可执行文件及它们之间的连接。
ROS 中的每个节点都应负责单个模块目的(例如,一个节点用于控制轮式电机,一个节点用于控制激光测距仪,等等)。每个节点都可以通过主题,服务,操作或参数(topics, services, actions, or parameters)向其他节点发送和接收数据。
完整的机器人系统由许多协同工作的节点组成。在 ROS 2 中,单个可执行文件(C++ 程序,Python 程序等)可以包含一个或多个节点。
下面以 turtlesim
为例来说明节点。
4.0 安装 turtlesim
Turtlesim 是用于学习 ROS 2 的轻量级模拟器。它说明了 ROS 2 在最基本的水平上所做的工作,以使您对以后使用真实的机器人或机器人仿真将要做什么有所了解。rqt
是 ROS 2 的GUI工具。rqt
中完成的所有操作都可以在命令行上完成,但是它提供了一种更简单,更用户友好的方式来处理 ROS 2 元素。本小节教程涉及 ROS 2 的核心概念,例如节点,主题和服务的分离。 所有这些概念将在以后的教程中进行详细介绍。 现在,您只需设置工具并对其进行体验。
为您的 ROS 2 发行版安装 turtlesim
软件包:
$ sudo apt update
$ sudo apt install ros-<distro>-turtlesim
检查软件包是否已安装:
$ ros2 pkg executables turtlesim
上面的命令应返回 turtlesim
可执行文件的列表:
4.1 ros2 run¶
ros2 run
命令从软件包启动可执行文件。
ros2 run <package_name> <executable_name>
比如,要运行 turtlesim
,请打开一个新终端,然后输入以下命令:
ros2 run turtlesim turtlesim_node
弹出模拟器窗口,中间有一只随机使用一个 ROS2 的 logo 的乌龟:
终端中可以看到海龟的名字和在仿真器坐标系下的位置:
在这里,您可以看到乌龟的默认名称是 turtle1
,以及产生它的默认坐标。
4.2 ros2 node list¶
ros2 node list
将显示所有正在运行的节点的名称。当您要与节点进行交互时,或者当您的系统运行着许多节点并需要对其进行跟踪时,这特别有用。
当 turtlesim
仍在另一个终端中运行时,打开一个新终端,然后输入以下命令:
ros2 node list
显示如下:
接下来让海龟动起来,打开一个新的终端,输入如下命令:
ros2 run turtlesim turtle_teleop_key
此时,您应该打开三个窗口:一个运行 turtlesim_node
的终端,一个运行 turtle_teleop_key
的终端和 turtlesim
窗口。排列这些窗口,以便您可以看到 turtlesim
窗口,还可以使运行 turtle_teleop_key
的终端处于活动状态,以便您可以在 turtlesim
中控制海龟。
此时节点列表为:
/turtlesim
/teleop_turtle
然后根据终端中的提示点击键盘按键,即可控制小海龟运动啦,注意一定要让键盘控制节点在激活状态:
您可以使用 list
命令查看节点及其关联的服务,主题和操作:
$ ros2 node list
$ ros2 topic list
$ ros2 service list
$ ros2 action list
4.3 remapping
Remapping 允许您将默认节点属性(例如节点名称,主题名称,服务名称等)重新分配给自定义值。
现在,让我们重新分配 /turtlesim
节点的名称。在新的终端中,运行以下命令:
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
由于您再次调用 ros2 run
在 turtlesim
上,因此将打开另一个 turtlesim
窗口。但是,现在,如果您返回运行 ros2
节点列表的终端,然后再次运行它,您将看到三个节点名称:
/turtlesim
/teleop_turtle
/my_turtle
此时,虽然你又打开了一个小海龟的仿真界面,但是和之前的仿真窗口并没有任何冲突。
4.4 ros2 node info¶
现在您知道节点的名称,您可以通过以下方式访问有关它们的更多信息:
ros2 node info <node_name>
要检查您的最新节点 my_turtle
,请运行以下命令:
ros2 node info /my_turtle
ros2 node info
返回与该节点交互的订户(subscribers),发布者(publishers),服务(services)和操作(actions,即 ROS graph connections)的列表。输出应如下所示:
现在,尝试在 /teleop_turtle
节点上运行相同的命令,并查看其连接与 my_turtle
有何不同。
4.5 总结
节点是基本的 ROS 2 元素,在机器人系统中用于单个模块化目的。在本教程中,您通过运行可执行文件 turtlesim_node
和 turtle_teleop_key
来利用从 turtlesim
包创建的节点。您学习了如何使用 ros2 node list
来发现活动节点名称和 ros2 节点信息以在单个节点上进行内省。这些工具对于了解复杂的真实机器人系统中的数据流至关重要。
5 理解主题
ROS 2 将复杂的系统分解为许多模块化节点。主题是 ROS graph 的重要元素,它充当节点交换消息的总线(a bus)。
节点可以将数据发布到任意数量的主题,并同时订阅任意数量的主题。
主题是节点之间实现数据传输的重要途径,也是机器人各个子系统之间交换数据的重要方式。
5.0 ROS 2 的图形用户界面 rqt
安装 rqt
:
$ sudo apt update
$ sudo apt install ~nros-<distro>-rqt*
运行 rqt
:
$ rqt
第一次运行 rqt
之后,该窗口将为空白。别担心; 只需从顶部菜单栏中选择 Plugins > Services > Service Caller
即可。
这个插件是用来发布服务请求的,点击刷新按键之后,可以看到系统当前的所有服务。
单击 Service
下拉列表以查看 turtlesim
的服务,然后选择 /spawn
服务。
您可以从其名称猜测 /spawn
将在 turtlesim
窗口中创建另一只乌龟。
通过在 Expression 列中的空单引号之间双击,为新的乌龟赋予唯一的名称,例如 turtle2
。 您可以看到该表达式对应于 name
值,并且为 string
类型。
输入要生成的海龟的新坐标,例如 x = 1.0
和 y = 1.0
。
要生成 turtle2
,必须通过单击 rqt
窗口右上角的 Call 按钮来调用该服务。您将在坐标 处看到一只新的乌龟(同样具有随机设计)。
注意:如果您尝试生成与现有乌龟同名的新乌龟(例如默认的 turtle1
),则会在运行 turtlesim_node
的终端中显示错误消息:
[ERROR] [turtlesim]: A turtle named [turtle1] already exists
还可以尝试另外一个服务 /set_pen
,通过设置画笔,调整海龟轨迹的颜色。如下图所示,设置画笔的 rgb 值和宽度,点击 “Call” 之后,再运动海龟就可以看到全新的轨迹效果啦。
您可能已经注意到,无法移动 turtle2
。您可以通过将 turtle1
的 cmd_vel
主题重新映射到 turtle2
上来完成此操作。
在一个新的终端中输入如下指令:
$ ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_vel
这里就把 turtle1/cmd_vel
这个话题名更改为了 turtle2/cmd_vel
,现在该节点就可以控制 turtle2
啦,不信在该终端中点击键盘试一下。
5.1 rqt_graph¶
可以从上帝视角看到整个系统的状态,我们使用这个工具来可视化显示节点和话题的连接关系。在整个教程中,我们将使用 rqt_graph
可视化不断变化的节点和主题以及它们之间的连接。
在更加复杂的机器人系统中,rqt_graph
工具可以帮助我们快速理清节点之间通过话题的牵连。
5.2 ros2 topic list¶
在新终端中运行 ros2 topic list
命令将返回系统中当前活动的所有主题的列表:
ros2 topic list -t
将返回相同的主题列表,这次主题主题类型附加在每个主题之后:
主题具有名称和类型。这些属性(尤其是类型)是节点如何知道他们正在谈论与主题相关的相同信息。
5.3 ros2 topic echo¶
如果想看到节点之间的话题到底发了什么数据内容,可以这样:
$ ros2 topic echo <topic_name>
我们现在好奇键盘节点到底给小海龟发了什么,小海龟这么听话的动起来呢?由于我们知道 /teleop_turtle
通过 /turtle1/cmd_vel
主题将数据发布到 /turtlesim
,因此让我们使用 echo
对该主题进行内省:
$ ros2 topic echo /turtle1/cmd_vel
首先,该命令不会返回任何数据。那是因为它正在等待 /teleop_turtle
发布内容。在运行键盘控制节点的终端中点击键盘,您将看到发布的每个动作的位置数据:
原来键盘控制节点将点击的键盘按键变成了线速度和角速度,通过话题发送给海龟仿真器,海龟才动起来的。
5.4 ros2 topic info¶
主题不必只是点对点交流;它可以是一对多,多对一或多对多。
另一种查看方式是运行:
ros2 topic info /turtle1/cmd_vel
将返回:
5.5 ros2 interface show¶
节点使用消息通过主题发送数据。发布者和订阅者必须发送和接收相同类型的消息才能进行通信。
在运行 ros2 topic list -t
之后,我们在前面看到的主题类型让我们知道每个主题可以发送什么类型的消息。回想一下 cmd_vel
主题的类型:
geometry_msgs/msg/Twist
这意味着在软件包 geometry_msgs
中有一个名为 Twist
的 msg
。
现在我们可以在此类型上运行 ros2 interface show <type>.msg
来了解其详细信息,特别是消息期望的数据结构。
ros2 interface show geometry_msgs/msg/Twist
显示:
原来 Twist
中包含了两个三维向量,分别表示线速度和角速度。
5.6 ros2 topic pub¶
现在我们了解了消息的结构,有没有可能直接通过命令行来发布一个话题消息呢?当然是可以的。
ros2 topic pub <topic_name> <msg_type> '<args>'
这里的 '<args>'
就是具体的消息内容啦,我们需要使用 YAML 的语法来描述,比如要发布速度指令 Twist:
$ ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
–once
表示这个消息只发布一次就退出。
终端中会出现如下提示:
如果希望小海龟一直运动,那就得以某个频率持续发布:
$ ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
–rate
参数就表示频率啦,单位是 hz。
5.7 ros2 topic hz¶
如果我们想查看某一个话题的发布频率,依然可以通过命令行来实现:
$ ros2 topic hz /turtle1/pose
很快就可以看到 turtlesim
节点发布 pose
话题的频率啦:
好啦,Ctrl+C
即可关闭运行的终端内容。
6 理解服务
服务(Service)是 ROS graph 上节点通信的另一种方法。服务基于呼叫响应模型(call-and-response model),而不是主题的发布者-订阅者模型(publisher-subscriber model)。尽管主题允许节点订阅数据流并获得持续更新,但是服务仅在客户端专门调用它们时才提供数据。
接下来还是以海龟仿真为例,看看里边有哪些服务的应用呢?
还是用这两个终端来启动海龟仿真器:
$ ros2 run turtlesim turtlesim_node
$ ros2 run turtlesim turtle_teleop_key
6.1 ros2 service list¶
在小海龟背后,有哪些服务呢?可以使用 ros2 service list
命令来查看一下:
在列表中可以看到每个节点都有6个以“parameters”结尾的服务,在ROS2中,几乎每一个节点都会有这几个服务,主要是用来设置一些参数的,算是节点的默认服务配置,这里我们暂时忽略这些默认的服务,主要看其他几个海龟仿真器提供的功能性质的服务。
6.2 ros2 service type¶
服务具有描述服务的请求和响应数据的结构的类型。服务类型的定义与主题类型类似,不同的是,服务类型包括两部分:一个消息用于请求,另一个消息用于响应。
要找出服务的类型,请使用以下命令:
$ ros2 service type <service_name>
以 /clear
服务为例,可以这样来试试:
$ ros2 service type /clear
看到的服务数据结构是这样的:
Empty
类型表示服务请求部分的数据是没有的,发送请求的时候不需要任何数据。
6.2.1 ros2 service list -t
类似查看所有节点的主题消息类型,也可以用类似的方式查看所有服务的数据类型,需要在 list
命令后边加上“–show-types”配置,或者简写为“-t”。
ros2 service list -t
6.2.2 ros2 service find¶
ROS2 还允许查看所有提供同样数据类型的的服务,可以使用如下命令:
$ ros2 service find <type_name>
比如可以查找所有提供 Empty
数据类型的服务:
$ ros2 service find std_srvs/srv/Empty
可以看到:
6.3 ros2 interface show¶
现在我们已经可以看到某一个服务的数据类型了,那这种数据类型具体的数据结构是什么样的呢?可以用这个命令:
$ ros2 interface show <type_name>.srv
比如:
$ ros2 interface show std_srvs/srv/Empty.srv
终端中会显示:
这里的“---”在服务的数据结构中是用来分割请求和应答两个部分的数据,这里只所以只有“---”,是应为 Empty
的请求和应答都不需要任何数据描述,类似一个出发信号。
我们来看另外一个服务的数据类型 Spawn
,之前已经根据 list
命令看到该服务的数据类型是 turtlesim/srv/Spawn
:
$ ros2 interface show turtlesim/srv/Spawn.srv
显示:
这里可以看到,在 Spawn
服务的请求部分,由必须的 x、y、theta 和可选的 name 组成,应答数据则是 name 这个字符串。
6.4 ros2 service call¶
现在您已经知道什么是服务类型,如何找到服务类型以及如何找到该类型参数的结构,您可以使用以下命令调用服务:
$ ros2 service call <service_name> <service_type> <arguments>
<arguments>
部分是可选的,比如 Empty
类型的服务就没有任何参数:
$ ros2 service call /clear std_srvs/srv/Empty
这个服务只是出发一个信号,让海龟仿真器清除海龟后边的运动轨迹,不需要传输什么数据:
我们再来试试 /spawn
服务,这个服务可以产生一只新的海龟,<arguments>
部分就需要输入上边看到的请求数据了(从命令行在服务调用中输入 <arguments>
时必须使用 YAML 语法):
$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
您将获得此方法样式的事件视图,然后获得服务响应:
您的 turtlesim 窗口将立即更新为新生成的海龟:
6.5 总结¶
节点可以使用 ROS 2 中的服务进行通信。服务仅在该节点明确请求信息的情况下才将信息传递给该节点,并且每个请求仅将信息传递一次(不以连续流的形式)。您通常不希望使用服务进行连续通话;topic 甚至 action 将更适合。在本教程中,您使用了命令行工具来识别,详细说明和调用服务。
7 理解参数
参数是节点的配置值。您可以将参数视为节点设置。节点可以将参数存储为整数,浮点数,布尔值,字符串和列表。在 ROS 2 中,每个节点都维护自己的参数。所有参数都是可动态重新配置的,并且是基于 ROS 2 services 构建的。
要查看属于您节点的参数,请打开一个新终端并输入以下命令:
$ ros2 param list
您将看到节点子命名空间,/teleop_turtle
和 /turtlesim
,以及每个节点的参数:
每个节点都有参数 use_sim_time
; 它不是 turtlesim
特有的。
根据它们的名称,/turtlesim
的参数看起来像是使用 RGB 颜色值来确定 turtlesim
窗口的背景色。要确定参数类型,可以使用 ros2 param get
。
7.1 ros2 param get¶
要获取参数的当前值,请使用以下命令:
$ ros2 param get <node_name> <parameter_name>
让我们找出 /turtlesim
参数 background_g
的当前值:
$ ros2 param get /turtlesim background_g
可以看到如下反馈,是一个整型数:
7.2 ros2 param set¶
要在运行时更改参数的值,请使用以下命令:
$ ros2 param set <node_name> <parameter_name> <value>
让我们更改 /turtlesim
的背景颜色:
$ ros2 param set /turtlesim background_r 150
终端中会看到设置成功的日志,仿真器的背景也很快变色了:
这种方式只能修改一次参数值,下次重新启动就失效了,如果要下次继续生效,就得保存参数了。
7.3 ros2 param dump¶
您可以使用以下命令将节点的所有当前参数值 “dump” 到文件中以供以后保存:
$ ros2 param dump <node_name>
比如保存 /turtlesim
节点的参数:
$ ros2 param dump /turtlesim
终端中可以看到保存成功的提示:
很快就可以在你运行终端的路径下看到保存好的文件啦,打开之后的内容如下:
turtlesim:
ros__parameters:
background_b: 255
background_g: 86
background_r: 150
use_sim_time: false
如果您希望将来使用相同的参数重新加载节点,则转储参数会很方便。
7.4 Load parameter file¶
要使用保存的参数值启动同一节点,请使用:
$ ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
这是您始终用来启动 turtlesim
的同一命令,添加了标志 --ros-args
和 --params-file
,后跟要加载的文件。
停止运行的 turtlesim
节点,以便尝试使用保存的参数重新加载它,方法是:
$ ros2 run turtlesim turtlesim_node --ros-args --params-file ./turtlesim.yaml
turtlesim
窗口应照常显示,但带有您先前设置的紫色背景。
这就是 ROS2 中的参数,我们可以通过命令行 get
或 set
参数值,还可以利用文件保存和加载参数。
8 理解动作
动作(Action)是 ROS 2 中用于长时间运行任务的通信类型之一。它们由三部分组成:目标,结果和反馈(a goal, a result, and feedback)。
动作基于主题和服务。它们的功能与服务相似,但动作是可抢占的(您可以在执行时将其取消)。与返回单个响应的服务相反,它们还提供稳定的反馈。
动作使用客户端-服务器模型(client-server model),类似于发布者-订阅者模型(publisher-subscriber model)。“action client” 节点将目标发送到 “action server” 节点,该节点确认该目标并返回反馈和结果流。
8.1 Use actions¶
启动 /teleop_turtle
节点时,您将在终端中看到以下消息:
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.
之前我们都是使用键盘的上下左右按键发布话题指令来控制小海龟移动的,以上第二行信息提示的指令,则是通过 action 来控制海龟转动到指定方向的。
按键 G|B|V|C|D|E|R|T 都是围绕“F”的,以“F”为中心,对应方向的按键就表示控制小海龟的转动到的方向,比如按下“E”,小海龟就会转动到朝向左上方。
仔细观察小海龟仿真器,每当按下以上一个按键,相当于从客户端发送了一个action的任务目标,海龟仿真器后台运行的服务器端接收到之后就会开始执行,执行完成后反馈给客户端类似下边的结果:
“F”按键就是用来发送action终止指令的。假设你先按下了“C”,小海龟开始执行action,此时按下“F”,两个终端中都会看到:
再来试试先按下“D”,在完成action前按下“G”,这时终端中会提示:
没错,action 是抢占式的,后一个 action 的执行直接中断了前一个 action 的执行。
8.2 ros2 node info¶
我们来看下海龟仿真器节点有哪些 action:
$ ros2 node info /turtlesim
从反馈的信息列表中,我们可以看到所有仿真器中的订阅者、发布者、服务、动作服务器和客户端。
Action Servers 中可以看到有一个动作服务器 /turtle1/rotate_absolute
。
再来看看键盘控制节点的信息:
$ ros2 node info /teleop_turtle
在Action Clients中有同名的动作客户端 /turtle1/rotate_absolute
。
可见,键盘控制节点发送 action 目标,海龟仿真器执行 action 并反馈,action 名为 /turtle1/rotate_absolute
。
8.3 ros2 action list¶
action也可以类似话题服务一样查看:
$ ros2 action list
在海龟仿真器系统中,可以看到
如果想要看到更详细的action数据类型,需要加入 -t
参数:
$ ros2 action list -t
看到的信息就是这样啦:
这里的 turtlesim/action/RotateAbsolute
就是 action 的数据类型,当我们通过终端发送 action 指令时,这个数据类型就可以知道我们如何发送具体的数据了。
8.4 ros2 action info¶
从 list
列表中看到的 action 可以用如下命令查看详情:
$ ros2 action info /turtle1/rotate_absolute
看到的结果如下:
这里可以看到提供该 action 的服务器和客户端的数量。
8.5 ros2 interface show¶
如果我们想发送一个action的目标goal,就需要知道action的具体数据类型和数据结构,刚才我们已经看到 /turtle1/rotate_absolute
的数据类型是 turtlesim/action/RotateAbsolute
,那这个数据类型的具体数据结构是什么样的呢?
可以这样看到:
$ ros2 interface show turtlesim/action/RotateAbsolute.action
有点像 service 的数据结构,只不过有两个“---”将数据分成了三段,第一段描述客户端发送的请求目标,第二段描述的是action执行完成后的反馈结果,第三段描述的是action执行过程中的周期反馈。
8.6 ros2 action send_goal¶
终于可以发布action目标了,了解下命令行下发送goal的格式:
ros2 action send_goal <action_name> <action_type> <values>
<values>
同样是 YAML 格式描述的数据。发送一个试试:
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
小海龟开始转动啦,终端中会显示:
从以上信息我们可以看到,每一个action目标都有一个唯一的ID。
如果先要看到action中的周期反馈,以上命令还需要加一个 --feedback
参数:
$ ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
这时的终端信息是这样的:
在action执行完成前,终端中会不断周期刷新类似反馈信息。
好啦,这就是ROS2中的action概念,用于长时间运行某一任务,提供过程中的周期反馈,而且是可以取消或者抢占的。想象一下机械臂抓取、移动机器人导航,是不是都可以用到类似的通信机制呢?
更详细的内容见:CLI 工具 (xinetzone.github.io)。