The ROS Command Line Interface

ROS 命令行界面(简称 CLI)是一组用于启动、检查、控制和监控 ROS 机器人的程序。理解 CLI 的最佳方式是,它是一组小型和简单的程序,可让您在 ROS 中执行基本任务。从汽车类比来看,CLI 可以被认为是车辆的子系统:刹车、变速器、雨刷,所有这些较小的部件组合在一起构成了更大的车辆。我们将在本节中向您展示如何启动汽车、挂档、打开收音机,以及检查机油以执行日常维护。ROS 2 CLI 大量借鉴了 Unix/Linux 的理念,即可以组合在一起的小程序。如果您熟悉 Unix 和 Linux 中的命令行界面,或者在较小程度上熟悉 MacOS 或 Windows 中的命令行界面,那么您会感到非常熟悉。

ROS 命令行工具大量借鉴了上一节中提到的设计模式,并直接与我们将在下一节中介绍的 API 交互。CLI 接口本质上只是一组基于 ROS 2 API 构建的简单工具;此 API 只是我们在上一节中讨论的高级模式的实现。如果您的目标只是与使用 ROS 编写的特定软件交互,则 CLI 接口就是您启动、停止和控制底层 ROS 软件的方式。对于更高级的用户,这些工具将允许您通过探索系统中的底层软件流程来研究 ROS 系统。

本节中您只需记住两件事。 第一个命令只是告诉您的计算机您正在使用 ROS,以及您想要使用哪个版本的 ROS。让我们来看看 这个神奇的命令:

source /opt/ros/eloquent/setup.bash

如果一切正常,此命令应该会返回。您看不到任何内容 发生,但在幕后,您刚刚告诉这个特定的 shell,您正在使用 ROS 2 Eloquent Elusor,以及所有 ROS 程序和文件所在的位置。您应该计划在每次想要使用 ROS 时执行此操作。新用户最常犯的错误是没有运行此命令。如果您不确定是否在 shell 中运行了此命令,那没关系。该命令是幂等的;连续运行两次不会破坏任何东西。您可以连续运行一百万次, 也不会有任何区别。

您需要记住的另一个命令是ros2。ROS 2 CLI 中的几乎所有内容都以ros2开头。继续在刚刚获取安装文件的同一 shell 中尝试它。 如果一切正常,您应该会看到以下内容:

$ ros2
usage: ros2 [-h] Call `ros2 <command> -h` for more detailed usage. ...

ros2 is an extensible command-line tool for ROS 2.

optional arguments:
  -h, --help            show this help message and exit

Commands:
  action     Various action related sub-commands
  component  Various component related sub-commands
  daemon     Various daemon related sub-commands
  doctor     Check ROS setup and other potential issues
  interface  Show information about ROS interfaces
  launch     Run a launch file
  lifecycle  Various lifecycle related sub-commands
  msg        Various msg related sub-commands
  multicast  Various multicast related sub-commands
  node       Various node related sub-commands
  param      Various param related sub-commands
  pkg        Various package related sub-commands
  run        Run a package specific executable
  security   Various security related sub-commands
  service    Various service related sub-commands
  srv        Various srv related sub-commands
  topic      Various topic related sub-commands
  wtf        Use `wtf` as alias to `doctor`

  Call `ros2 <command> -h` for more detailed usage.

通过这一个命令,您可以了解每个 ROS 2 CLI 程序的作用以及 如何使用它。ROS 2 CLI 的语法与大多数语言一样。所有 ROS CLI 命令都以 ros2 开头,后跟一个命令。命令后可以有许多其他内容 ;您可以附加 --help-h 来查看文档并找出任何命令需要的参数。 本节的其余部分只是逐一介绍每个命令。

使用命令行编写命令很棘手,而且容易出错。您可以使用一些工具使这个过程更加顺畅。第一个是 TAB 键,它会尝试自动完成您输入的任何内容。它无法读懂您的想法,但对于常见的命令组合,您通常只需要输入前一个或两个字母。另一个工具是向上箭头键。当您使用命令行时,有时您会输错命令,或者需要重新运行命令。按向上键将循环显示以前的命令,您可以根据需要修改并重新运行这些命令。

运行你的第一个 ROS 程序

让我们开始使用第一个 ROS CLI 命令。我们将访问的第一个命令是run。让我们先查看run命令的文档:

$ ros2 run
usage: ros2 run [-h] [--prefix PREFIX] package_name executable_name ...
ros2 run: error: the following arguments are required: package_name, executable_name, argv

要获取有关 ROS 2 命令的更完整信息,只需在命令中添加 --help 即可向命令寻求帮助。让我们再试一次:

$ ros2 run --help
usage: ros2 run [-h] [--prefix PREFIX] package_name executable_name ...

Run a package specific executable

positional arguments:
  package_name     Name of the ROS package
  executable_name  Name of the executable
  argv             Pass arbitrary arguments to the executable

optional arguments:
  -h, --help       show this help message and exit
  --prefix PREFIX  Prefix command, which should go before the executable.
                   Command must be wrapped in quotes if it contains spaces
                   (e.g. --prefix 'gdb -ex run --args').

我们可以看到,ros2 run 是“运行包特定的可执行文件”的命令。在 ROS 2 中,ROS 软件集合被收集到称为“包”的逻辑单元中。每个包都包含包的所有源代码以及各种其他数据,这些数据告诉 ROS 如何构建和编译包以及可以在包中找到的所有程序(也称为“可执行文件”)的名称。描述下方的行给出了包的_位置参数_。位置参数是位于 ros2 和您运行的命令之后的单词和值。在这种情况下,我们要编写的命令句的语法如下:

ros2 run <package name> <program/executable name> <args>

这里缺少一条信息。该命令要求的 argv 是什么?argv 元素是程序员对可变参数的简写,它只是意味着“由可执行文件确定的一些附加参数”。值得注意的是,程序可以有零个参数,您可以将其留空。这实际上是许多程序的工作方式。例如,假设我们有一个名为 math 的包,以及一个名为 add 的可执行文件,它接受两个数字并返回结果。在这种情况下,argv 将是要添加的两个数字。最终命令如下所示:

ros2 run math add 1 2

最后,在位置参数下面我们有_可选参数_。 除非需要,否则您不需要包含它们。

现在我们已经查看了帮助文件,让我们运行我们的第一个 ROS 程序。对于 这些教程,我们将使用一个名为turtlesim的包,我们要运行的程序是turtlesim_node。让我们运行这个程序(记住您的制表符已完成!)。您的命令应如下所示:

ros2 run turtlesim turtlesim_node

如果一切顺利,您应该看到以下内容:

[INFO] [turtlesim]: Starting turtlesim with node name /turtlesim
[INFO] [turtlesim]: Spawning turtle [turtle1] at x=[5.544445], y=[5.544445], theta=[0.000000]

还会弹出一个窗口,上面有一只可爱的小乌龟,如下所示:

Turtlesim upon opening

ROS 的真正强大之处不在于它可以运行一个程序,而在于它可以同时运行 许多程序,这些程序共同控制一个机器人或 多个机器人,共同工作。为了说明这一点,让我们运行第二个 ROS 程序,让我们的小乌龟四处移动。

为此,我们首先打开一个新终端(使用CTRL-SHIFT-T)。接下来,我们将使用“source”命令告诉该终端我们想要使用 ROS Eloquent。最后,我们将运行turtlesim包中的另一个程序来绘制正方形。看看你是否能自己找到该程序(提示:使用TAB)。如果一切正常,你应该已经输入了以下内容,并且应该可以看到以下输出:

$ source /opt/ros/eloquent/setup.bash
$ ros2 run turtlesim draw_square
[INFO] [draw_square]: New goal [7.544445 5.544445, 0.000000]
[INFO] [draw_square]: Reached goal
[INFO] [draw_square]: New goal [7.448444 5.544445, 1.570796]
[INFO] [draw_square]: Reached goal

你的屏幕看起来大致如下:

image

值得注意的是,您可以通过在终端中同时按下 CtrlC 键来停止任何 ROS 程序;我们称之为 CTRL-C(请注意,CTRL-SHIFT-CCTRL-SHIFT-V 负责在 Linux 终端中复制和粘贴)。 请随意尝试。启动和停止程序,然后 重新启动它们,然后再继续。

ROS Topics

我们现在有两个 ROS 2 程序从 turtlesim 包运行。

turtle_node 用于打开我们的海龟模拟,draw_square

用于使 turtle_node 中的海龟移动。这两个

程序如何通信?

ROS 程序(也称为_节点_)通过 ROS _消息总线_上的 _主题_进行通信。ROS _主题_使用命名空间来区分自己。 例如,在运行 ROS 的车辆中,每个车轮的位置可以 按以下方式组织:

/wheels/front/driver/velocity
/wheels/front/passenger/velocity
/wheels/rear/driver/velocity
/wheels/rear/passenger/velocity

关于主题,关键是要认识到它们包含的数据是动态的,这意味着它会不断变化。在我们的车辆示例中,每个车轮的速度可能每秒测量一千次或更多次。由于 ROS 主题中的数据不断变化,因此主题的一个重要区别是主题是“创建”还是像我们在 ROS 中所说的那样publishing,或者它是否正在读取数据,我们称之为subscribing主题。许多 ROS 节点订阅一组主题,处理输入数据,然后发布到另一组主题。

让我们回到我们的 turtlesim 示例,看看我们是否可以使用 ROS CLI 来 了解主题、发布者和订阅者。 要查看 topic 命令的子命令和语法,我们将运行:ros2 topic --help

此命令输出以下内容:

$ ros2 topic --help
usage: ros2 topic [-h] [--include-hidden-topics]
                  Call `ros2 topic <command> -h` for more detailed usage. ...

Various topic related sub-commands

optional arguments:
  -h, --help            show this help message and exit
  --include-hidden-topics
                        Consider hidden topics as well

Commands:
  bw     Display bandwidth used by topic
  delay  Display delay of topic from timestamp in header
  echo   Output messages from a topic
  find   Output a list of available topics of a given type
  hz     Print the average publishing rate to screen
  info   Print information about a topic
  list   Output a list of available topics
  pub    Publish a message to a topic
  type   Print a topic's type

  Call `ros2 topic <command> -h` for more detailed usage.

有相当多的子命令;我们不会讨论所有子命令,但让我们仔细看看其中几个。 子命令有自己的帮助命令。我们为什么不检查一下list命令呢?重复我们的命令模式,让我们尝试运行ros2 topic list --help

usage: ros2 topic list [-h] [--spin-time SPIN_TIME] [-t] [-c]
                       [--include-hidden-topics]

Output a list of available topics

optional arguments:
  -h, --help            show this help message and exit
  --spin-time SPIN_TIME
                        Spin time in seconds to wait for discovery (only
                        applies when not using an already running daemon)
  -t, --show-types      Additionally show the topic type
  -c, --count-topics    Only display the number of topics discovered
  --include-hidden-topics
                        Consider hidden topics as well

正如此命令帮助文件顶部所示,ros2 topic list 将 “输出可用主题列表”。似乎有各种 可选 参数,如果我们不想的话,我们不需要包含它们。但是, -t, --show-types 行看起来很有趣。值得注意的是,命令 参数(有时称为标志)可以有两种类型。短格式用单破折号(“-”)表示,长格式用双破折号 (“--”)表示。别担心,尽管两个版本的参数看起来不同,但它们的作用相同。让我们尝试运行此命令,子命令对与 -show-types 参数。

$ ros2 topic list --show-types
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
/turtle1/cmd_vel [geometry_msgs/msg/Twist]
/turtle1/color_sensor [turtlesim/msg/Color]
/turtle1/pose [turtlesim/msg/Pose]

在左侧,我们可以看到系统上运行的所有 ROS 主题,每个主题都以/开头。我们可以看到,它们中的大多数都聚集在/turtle1/组中。该组定义了我们屏幕上的小海龟的所有输入和输出。主题名称右侧括号([])中的单词定义了主题上使用的消息。我们的车轮示例很简单,我们只发布速度,但 ROS 允许您发布由_消息类型_定义的更复杂的数据结构。当我们添加--show-types标志时,我们告诉命令包含此信息。稍后我们将详细探讨消息。

最常用的主题子命令之一是 info。毫不奇怪,info 提供有关主题的信息。让我们使用 ros2 topic info --help 查看其 帮助文件

$ ros2 topic info --help
usage: ros2 topic info [-h] topic_name

Print information about a topic

positional arguments:
  topic_name  Name of the ROS topic to get info (e.g. '/chatter')

optional arguments:
  -h, --help  show this help message and exit

这看起来非常简单。让我们在 /turtle1/pose 上运行它来尝试一下

$ ros2 topic info /turtle1/pose
Type: turtlesim/msg/Pose
Publisher count: 1
Subscriber count: 1

这个命令告诉我们什么?首先,它告诉我们 /turtle1/pose 主题的 消息类型,即 /turtlesim/msg/Pose。由此我们可以确定消息类型来自 turtlesim 包,其类型为 Pose。ROS 消息具有预定义的消息类型,可以由不同的编程语言和不同的节点共享。我们还可以看到,这个主题有一个发布者,也就是说,一个节点在主题上生成数据。该主题还有一个订阅者,也称为侦听器,它正在处理传入的姿势数据。

如果我们只想知道某个主题的消息类型,那么有一个专门用于该主题的子命令,名为type。让我们看一下它的帮助文件及其结果:

$ ros2 topic type --help
usage: ros2 topic type [-h] topic_name

Print a topic's type

positional arguments:
  topic_name  Name of the ROS topic to get type (e.g. '/chatter')

optional arguments:
  -h, --help  show this help message and exit
kscottz@kscottz-ratnest:~/Code/ros2multirobotbook$ ros2 topic type /turtle1/pose
turtlesim/msg/Pose

虽然它不是 topic 命令的一部分,但我们值得简要地跳过并查看一个特定的命令,子命令对,即 interface 命令和 show 子命令。此子命令将打印与消息类型相关的所有信息,以便您更好地了解在主题上移动的数据。在前面的例子中,我们看到 topic type 子命令告诉我们 /turtle1/pose 主题的类型为 turtlesim/msg/Pose。但是 turtlesim/msg/Pose 数据是什么样的?我们可以通过运行 ros2 interface show 子命令并将消息类型名称作为输入来查看此主题传输的数据结构。让我们看看这个子命令的帮助及其输出:

$ ros2 interface show --help
usage: ros2 interface show [-h] type

Output the interface definition

positional arguments:
  type        Show an interface definition (e.g. "std_msgs/msg/String")

optional arguments:
  -h, --help  show this help message and exit

$ ros2 interface show turtlesim/msg/Pose
float32 x
float32 y
float32 theta

float32 linear_velocity
float32 angular_velocity

我们可以看到值 xy 是我们的海龟的位置坐标, 并且它们的类型为 float32theta 是头部指向的方向。 接下来的两个值 linear_velocityangular_velocity 分别表示海龟移动的速度和转动的速度。总而言之,这条消息告诉我们海龟在屏幕上的位置、它要去哪里以及它移动或旋转的速度。

现在我们知道了简单的 turtlesim 上的 ROS 主题及其消息类型,我们可以深入研究并了解更多有关一切工作原理的信息。如果我们回顾我们的主题子命令,我们可以看到一个名为“echo”的子命令。Echo 是计算机术语,意思是“重复”某事。如果您回显某个主题,则意味着您希望 CLI 重复该主题上的内容。让我们看看“echo”子命令的帮助文本:

$ ros2 topic echo --help
usage: ros2 topic echo [-h]
                       [--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}]
                       [--qos-reliability {system_default,reliable,best_effort}]
                       [--qos-durability {system_default,transient_local,volatile}]
                       [--csv] [--full-length]
                       [--truncate-length TRUNCATE_LENGTH] [--no-arr]
                       [--no-str]
                       topic_name [message_type]

Output messages from a topic

positional arguments:
  topic_name            Name of the ROS topic to listen to (e.g. '/chatter')
  message_type          Type of the ROS message (e.g. 'std_msgs/String')

optional arguments:
  -h, --help            show this help message and exit
  --qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}
                        Quality of service preset profile to subscribe with
                        (default: sensor_data)
  --qos-reliability {system_default,reliable,best_effort}
                        Quality of service reliability setting to subscribe
                        with (overrides reliability value of --qos-profile
                        option, default: best_effort)
  --qos-durability {system_default,transient_local,volatile}
                        Quality of service durability setting to subscribe
                        with (overrides durability value of --qos-profile
                        option, default: volatile)
  --csv                 Output all recursive fields separated by commas (e.g.
                        for plotting)
  --full-length, -f     Output all elements for arrays, bytes, and string with
                        a length > '--truncate-length', by default they are
                        truncated after '--truncate-length' elements with
                        '...''
  --truncate-length TRUNCATE_LENGTH, -l TRUNCATE_LENGTH
                        The length to truncate arrays, bytes, and string to
                        (default: 128)
  --no-arr              Don't print array fields of messages
  --no-str              Don't print string fields of messages

哇,功能真多。帮助文件的顶部说这个 CLI 程序“输出来自主题的消息”。当我们扫描位置参数时,我们会看到一个必需参数、一个主题名称和一个可选消息类型。我们知道消息类型是可选的,因为它周围有方括号([])。在处理一些可选元素之前,让我们先试一下这个简单案例。要记住两件事:第一,主题很长,很容易弄乱,所以请使用TAB键。第二,这将快速打印大量数据。您可以使用CTRL-C停止命令并停止所有输出。让我们看看/turtle1/pose主题。

$ ros2 topic echo /turtle1/pose
x: 5.4078755378723145
y: 7.081490516662598
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
x: 5.4155988693237305
y: 7.067478179931641
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
x: 5.423322677612305
y: 7.053465843200684
theta: -1.0670461654663086
linear_velocity: 1.0
angular_velocity: 0.0
---
<<GOING ON FOREVER>>

让我们来看看到底发生了什么。在破折号(---)之间是一条关于我们主题的 ROS 消息。如果仔细检查这些数字,您会发现它们正在变化,并且与乌龟的运动有关。回到我们的汽车示例,您可以看到这对于理解每个车轮的瞬时速度非常有用。

现在我们已经掌握了基础知识,让我们深入研究一些可选参数。我们看到各种以--qos开头的命令。这里的“QOS”表示“服务质量”,这是一个非常酷的功能,仅在 ROS 2 中才有。不用太技术性,QOS 是一种要求一定程度的网络稳健性的方式。ROS 系统可以通过网络运行,就像流媒体视频或视频游戏一样,数据包可能会被丢弃或无法到达目的地。操作系统设置可帮助您控制哪些数据包最重要,应该获得最高优先级。

大多数其他命令都用于更改此 CLI 程序的输出格式,但有一个命令特别方便,它也是 ROS 2 中的新功能。--csv 标志代表“逗号分隔值”,它是一种定义电子表格的非常简单的方法。此参数的作用是使主题 echo 命令以逗号分隔值格式输出数据。许多命令行允许您将数据从屏幕发送到文件,保存数据以供以后查看或分析。要在 Linux 中执行此文件保存,我们使用 > 字符后跟文件名。以下是使用 --csv 参数的两个示例:

$ ros2 topic echo /turtle1/pose --csv
7.097168922424316,8.498645782470703,2.442624092102051,0.0,0.4000000059604645
7.097168922424316,8.498645782470703,2.449024200439453,0.0,0.4000000059604645
...
<<CTRL-C>>
$ ros2 topic echo /turtle1/pose --csv > mydata.csv
<<nothing happens>>
<<CTRL-C>>

上面的第二个命令创建了一个名为mydata.csv的文件。您可以使用名为less的 CLI 实用程序查看它(按 q 退出),或者使用您最喜欢的电子表格工具打开它。

现在我们已经看过了ros2 topic echo,让我们来看看其他几个主题子命令。您可能已经注意到的一件事是主题可以输出大量数据!更复杂的机器人,比如自动驾驶汽车,可以以其产生的数据量使高速互联网连接饱和。有两个主题子命令可用于诊断性能问题。第一个子命令是topic hz,它是赫兹的缩写,赫兹是频率的单位。Hz子命令将告诉您特定主题生成消息的频率。同样,还有topic bw子命令,其中bw代表带宽,这是一个与生成的数据量相关的工程术语。高带宽连接可以传输更多数据(例如高清视频),而低带宽连接则可能传输广播节目。让我们来看看这两个命令的帮助:

$ ros2 topic hz --help
usage: ros2 topic hz [-h] [--window WINDOW] [--filter EXPR] [--wall-time]
                     topic_name

Print the average publishing rate to screen

positional arguments:
  topic_name            Name of the ROS topic to listen to (e.g. '/chatter')

optional arguments:
  -h, --help            show this help message and exit
  --window WINDOW, -w WINDOW
                        window size, in # of messages, for calculating rate
                        (default: 10000)
  --filter EXPR         only measure messages matching the specified Python
                        expression
  --wall-time           calculates rate using wall time which can be helpful
                        when clock is not published during simulation
$ ros2 topic bw --help
usage: ros2 topic bw [-h] [--window WINDOW] topic

Display bandwidth used by topic

positional arguments:
  topic                 Topic name to monitor for bandwidth utilization

optional arguments:
  -h, --help            show this help message and exit
  --window WINDOW, -w WINDOW
                        window size, in # of messages, for calculating rate
                        (default: 100)

bwhz 都遵循相同的模式,它们只是接受一个主题名称,后面跟着几个可选参数。唯一值得注意的参数是 window 参数。这两个命令都计算一系列消息的统计数据;计算这些统计数据时要使用多少条消息就是窗口大小。window 的默认值为 100,因此当您调用 ros2 topic bw 时,它将首先收集 100 条消息,然后使用该数据计算平均消息大小。让我们试一试(使用 TAB 完成,使用 CTRL-C 退出)。

$ ros2 topic hz /turtle1/pose
average rate: 60.021
	min: 0.001s max: 0.073s std dev: 0.00731s window: 65
average rate: 61.235
	min: 0.001s max: 0.073s std dev: 0.00523s window: 128
$ ros2 topic bw /turtle1/pose
Subscribed to [/turtle1/pose]
average: 1.44KB/s
	mean: 0.02KB/s min: 0.02KB/s max: 0.02KB/s window: 46
average: 1.52KB/s
	mean: 0.02KB/s min: 0.02KB/s max: 0.02KB/s window: 100

如上所示,hz 命令表示主题以 60.021 的频率发布消息,其中单位为 hz,即每秒 60.021 次。请注意,该命令以平均值的形式给出发布频率,后跟最小值、最大值和标准偏差(以秒为单位)。带宽子命令非常相似;我们可以看到该主题每秒产生 1.44 千字节的数据。此命令在最小值、最大值和平均值方面具有类似的输出。

探索主题时,一个方便的工具是了解它们的类型。虽然我们已经查看了 interface 命令以查看组成主题的整数类型,但 topic 命令既有查询主题类型的工具,也有搜索所有主题以查找特定类型的方法。如果您只想知道主题的类型,则可以使用 type 命令,它将返回一个类型,然后可以使用 interface 命令进一步探索该类型。如果您想知道哪些主题使用特定消息类型,则可以使用 topic find 命令、子命令对。topic typetopic interface 命令、子命令对的可选参数集非常有限,因此我们只需为它们提供所需的主题或消息类型即可。让我们一起看看这两个命令:

$ ros2 topic type --help
usage: ros2 topic type [-h] topic_name
Print a topic's type

positional arguments:
  topic_name  Name of the ROS topic to get type (e.g. '/chatter')

optional arguments:
  -h, --help  show this help message and exit
$ ros2 topic type /turtle1/pose
turtlesim/msg/Pose
$ ros2 topic find --help
usage: ros2 topic find [-h] [-c] [--include-hidden-topics] topic_type

Output a list of available topics of a given type

positional arguments:
  topic_type            Name of the ROS topic type to filter for (e.g.
                        'std_msg/msg/String')

optional arguments:
  -h, --help            show this help message and exit
  -c, --count-topics    Only display the number of topics discovered
  --include-hidden-topics
                        Consider hidden topics as wel
$ ros2 topic find  turtlesim/msg/Pose
/turtle1/pose

它允许您从命令行向任何 ROS 主题发布命令。虽然您不需要经常使用此命令,但在构建机器人系统时,它对于测试和调试特别方便。pub 命令有许多可选参数,允许您发送一条或多条消息,并具有不同的服务质量 (QoS) 预设。该命令的格式为 ros2 topic pub TOPIC_NAME MESSAGE_TYPE VALUES,这意味着要使其成功运行,您必须包含目标主题、主题的消息类型以及消息的值。消息的值以 YAML 格式指定,我们可以使用 interface show 命令来了解格式。为了说明此命令的实用性,我们将通过发布到 /turtle1/cmd_vel/ 主题来发出一条消息来旋转和停止我们的海龟。在构建命令之前,我们先来看一下 topic pub 文档:

$ ros2 topic pub --help
usage: ros2 topic pub [-h] [-r N] [-p N] [-1] [-n NODE_NAME]
                      [--qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}]
                      [--qos-reliability {system_default,reliable,best_effort}]
                      [--qos-durability {system_default,transient_local,volatile}]
                      topic_name message_type [values]

Publish a message to a topic

positional arguments:
  topic_name            Name of the ROS topic to publish to (e.g. '/chatter')
  message_type          Type of the ROS message (e.g. 'std_msgs/String')
  values                Values to fill the message with in YAML format (e.g.
                        "data: Hello World"), otherwise the message will be
                        published with default values

optional arguments:
  -h, --help            show this help message and exit
  -r N, --rate N        Publishing rate in Hz (default: 1)
  -p N, --print N       Only print every N-th published message (default: 1)
  -1, --once            Publish one message and exit
  -n NODE_NAME, --node-name NODE_NAME
                        Name of the created publishing node
  --qos-profile {system_default,sensor_data,services_default,parameters,parameter_events,action_status_default}
                        Quality of service preset profile to publish with
                        (default: system_default)
  --qos-reliability {system_default,reliable,best_effort}
                        Quality of service reliability setting to publish with
                        (overrides reliability value of --qos-profile option,
                        default: system_default)
  --qos-durability {system_default,transient_local,volatile}
                        Quality of service durability setting to publish with
                        (overrides durability value of --qos-profile option,
                        default: system_default)

由于我们想要手动移动我们的乌龟,我们将使用 --once 标志发出一次命令。值得注意的是,用于控制乌龟速度的消息类型很复杂,因为它由其他消息类型组成,所以我们必须查询基本消息类型。以下是我们将要做的事情的粗略总结:

  • 使用 ros2 topic type 打印 cmd_vel 主题类型,即 geometry_msgs/msg/Twist
  • 使用 interface show 确定 Twist 消息类型的结构。
  • 再次使用 inteface show 命令确定 Vector3 的结构,它是 Twist 消息类型的一部分。
  • 为我们的命令创建 YAML 语法。请注意下面的 YAML 语法,因为它相当棘手!YAML 用单引号和一组顶级花括号括起来,而后续级别遵循 name:value 模式,对于嵌套类型(如 Twist 命令),则遵循 name:{name1:val1,name2:val2}
  • 使用 ros2 pub 发出命令。
$ ros2 topic type /turtle1/cmd_vel
geometry_msgs/msg/Twist
$ ros2 interface show geometry_msgs/msg/Twist
# This expresses velocity in free space broken into its linear and angular parts.

Vector3  linear
Vector3  angular
$ ros2 interface show geometry_msgs/msg/Vector3
# This represents a vector in free space.

float64 x
float64 y
float64 z

$ ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist '{linear: {x: 4.0,y: 4.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}'

如果你做对了所有事情,你应该已经移动了屏幕上的乌龟。尝试更改命令以绘制一个小图片。

ROS 2 服务和操作

如前所述,服务是指可以快速完成的简短、同步的机器人行为,例如打开灯和打开或关闭组件。动作是长期、异步的任务,可能有中间步骤。动作的一个典型例子是导航:为机器人提供一个目标位置并要求其导航到该目标。尽管机器人可以尝试,但由于它不能无限快速地移动,因此需要时间才能移动到目标,有时其路径可能会被阻塞。

这两个原语是大多数使用 ROS 的机器人系统的骨干,学习如何通过命令行使用它们将使您能够快速轻松地命令机器人为您完成任务。为了帮助清晰地理解本节,我们还将介绍 ros2 node 命令,以确定哪个节点或软件进程正在执行特定操作或服务。

让我们快速解决节点问题。ROS 节点是小程序,在自己的进程中运行。ROS 系统可以同时运行十个、数百个甚至数千个节点。此外,ROS 系统可以在同一系统上同时运行同一节点的多个副本。在我们的海龟模拟中,我们实际上可以创建多个海龟,每个海龟都有自己的节点,所有海龟都运行完全相同的程序。ROS 节点与 ROS 主题一样,具有命名空间,因此您可以在运行同一节点(程序)的多个副本的情况下处理特定节点。让我们通过在终端中使用ros2 run turtlesim turtlesim_node重新启动我们的海龟模拟来深入了解一下。现在,在新的终端中,让我们首先通过寻求帮助来检查ros2 nod可以提供什么。

$ ros2 node --help
usage: ros2 node [-h]
                 Call `ros2 node <command> -h` for more detailed usage. ...

Various node related sub-commands

optional arguments:
  -h, --help            show this help message and exit

Commands:
  info  Output information about a node
  list  Output a list of available nodes

  Call `ros2 node <command> -h` for more detailed usage.

与主题非常相似,我们看到两个子命令,infolistnode list 的工作原理与 topic list 非常相似,只是打印所有正在运行的节点的列表。让我们看看我们的系统上运行了什么:

$ ros2 node list
/turtlesim

我们有一个名为“turtlesim”的单节点正在运行。node info 的工作方式与 topic info 非常相似,只不过它列出了我们提供给它的节点的信息。让我们用我们的单个 ROS 节点 /turtlesim 作为其参数来调用它:

$ ros2 node info /turtlesim
/turtlesim
  Subscribers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /turtle1/cmd_vel: geometry_msgs/msg/Twist
  Publishers:
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /turtle1/color_sensor: turtlesim/msg/Color
    /turtle1/pose: turtlesim/msg/Pose
  Service Servers:
    /clear: std_srvs/srv/Empty
    /kill: turtlesim/srv/Kill
    /reset: std_srvs/srv/Empty
    /spawn: turtlesim/srv/Spawn
    /turtle1/set_pen: turtlesim/srv/SetPen
    /turtle1/teleport_absolute: turtlesim/srv/TeleportAbsolute
    /turtle1/teleport_relative: turtlesim/srv/TeleportRelative
    /turtlesim/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /turtlesim/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /turtlesim/get_parameters: rcl_interfaces/srv/GetParameters
    /turtlesim/list_parameters: rcl_interfaces/srv/ListParameters
    /turtlesim/set_parameters: rcl_interfaces/srv/SetParameters
    /turtlesim/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:
    /turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
  Action Clients:

哇,信息量很大,其中一些看起来很熟悉。我们可以看到节点订阅的所有主题,以及它发布到的所有节点。我们还可以看到许多“操作服务器”和“服务服务器”。值得注意的是这里的客户端和服务器关系。由于 ROS 可能有多个节点在运行,因此一些节点可能提供服务(这些是服务器),而其他 ROS 节点可能会调用这些服务器(这些是客户端)。客户端可以是其他 ROS 节点,或者对于这些示例,可以是使用 CLI 的人。

服务和操作的命令行界面非常相似,实际上它们都只有四个子命令。让我们运行 actionservice 命令并进行比较:

$ ros2 action --help
usage: ros2 action [-h]
                   Call `ros2 action <command> -h` for more detailed usage.
                   ...

Various action related sub-commands

optional arguments:
-h, --help            show this help message and exit

Commands:
  info       Print information about an action
  list       Output a list of action names
  send_goal  Send an action goal
  show       Output the action definition

  Call `ros2 action <command> -h` for more detailed usage.
$ ros2 service --help
usage: ros2 service [-h] [--include-hidden-services]
                    Call `ros2 service <command> -h` for more detailed usage.
                    ...

Various service related sub-commands

optional arguments:
  -h, --help            show this help message and exit
  --include-hidden-services
                        Consider hidden services as well

Commands:
  call  Call a service
  find  Output a list of available services of a given type
  list  Output a list of available services
  type  Output a service's type

  Call `ros2 service <command> -h` for more detailed usage.

我们可以看到,这两个命令都有一个 list 命令,它提供了可用服务或操作的列表。如果我们有多个节点在运行,并且想要查看提供的每项服务,那么在每个节点上调用 ros2 node info 会非常低效,特别是如果我们有数十个甚至数百个节点在运行。在这种情况下,使用 list 命令执行操作和服务命令会更有效率。我们可以在下面运行这些命令,并看到我们在单个节点中列出的操作和服务列表大致相同:

$ ros2 service list
/clear
/kill
/reset
/spawn
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically
kscottz@kscottz-ratnest:~$ ros2 action list
/turtle1/rotate_absolute

让我们开始深入研究服务。似乎列出了相当多的服务。让我们看一下 /spawn 服务,它将创建更多 turtle。ROS 服务和操作使用与主题中使用的消息类似的消息进行通信。事实上,操作和服务是建立在消息之上的。 我们可以使用 service type 子命令来确定特定服务使用的消息类型。我们可以使用 interface show 命令找到消息的具体信息。让我们在 spawn 服务中实际看看这一点:

$ ros2 service type /spawn
turtlesim/srv/Spawn
$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name

从上面的输出中我们可以看到,spawn 消息采用三个 float32 值作为其位置和方向,以及一个 string 作为其名称。--- 表示服务的返回值。与主题不同,服务具有返回值,这使它们能够执行诸如执行计算和计算之类的操作。

让我们通过运行 ros2 service call --help 来检查调用服务的帮助:

$ ros2 service call --help
usage: ros2 service call [-h] [-r N] service_name service_type [values]

Call a service

positional arguments:
  service_name    Name of the ROS service to call to (e.g. '/add_two_ints')
  service_type    Type of the ROS service (e.g. 'std_srvs/srv/Empty')
  values          Values to fill the service request with in YAML format (e.g.
                  "{a: 1, b: 2}"), otherwise the service request will be
                  published with default values

optional arguments:
  -h, --help      show this help message and exit
  -r N, --rate N  Repeat the call at a specific rate in Hz

这里的语法与发布到主题非常相似,但我们使用的是服务名称,而不是主题名称。服务类型就像我们过去使用的主题类型一样,但我们使用的不是消息类型,而是服务类型。最后,我们以 YAML 格式为其赋值。YAML 字符串必须用单引号括起来。让我们尝试通过在所有值都为零的位置创建一个名为Larry的海龟来调用服务(使用TAB完成)。

$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 0, y: 0, theta: 0.0, name: 'Larry'}"
requester: making request: turtlesim.srv.Spawn_Request(x=0.0, y=0.0, theta=0.0, name='Larry')

response:
turtlesim.srv.Spawn_Response(name='Larry')

如果一切正常,你现在应该在屏幕左下角看到一只名为“Larry”的乌龟:

Spawning a second turtle

尝试探索提供的其他服务,或 在不同位置创建更多海龟并移动它们。

让我们继续讨论操作。如前所述,操作在某些方面与服务不同,并且具有许多 优势。操作具有以下优势:

  • 操作有一个目标。也就是说,你向他们发送一个目标,他们就会尝试完成它。
  • 操作可以拒绝目标请求。这可以防止他们变得太忙。
  • 操作是异步的,可以在“你等待时”执行任务。
  • 操作将在你等待时为你提供有关其进度的“更新”。
  • 操作是可抢占的,这意味着如果你改变主意,你可以取消它们。

就像服务一样,我们首先要弄清楚如何使用 action listaction showaction info 命令来调用 ROS 系统中的单一操作。回想一下,当我们调用 ros2 action list 时,我们得到了一个单一服务。现在有了 Larry,事情就变了。让我们来看看:

$ ros2 action list
/Larry/rotate_absolute
/turtle1/rotate_absolute

现在有两个可用的操作,一个用于 Larry,一个用于turtle1。 让我们将 turtle1 旋转到面向 Larry。首先,我们将使用/turtle1/rotate_absolute作为输入调用action info,然后查看我们得到的结果:

$ ros2 action info /turtle1/rotate_absolute
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
    /turtlesim

好吧,这告诉了我们有关客户端和服务器的信息,但这对我们移动 Larry 的目标真的没有帮助。我们为什么不看看 action send_goal 帮助,看看我们能否弄清楚如何使用它:

$ ros2 action send_goal --help
usage: ros2 action send_goal [-h] [-f] action_name action_type goal

Send an action goal

positional arguments:
  action_name     Name of the ROS action (e.g. '/fibonacci')
  action_type     Type of the ROS action (e.g.
                  'example_interfaces/action/Fibonacci')
  goal            Goal request values in YAML format (e.g. '{order: 10}')

optional arguments:
  -h, --help      show this help message and exit
  -f, --feedback  Echo feedback messages for the goal

此命令需要 YAML 中的操作名称、操作类型和目标。我们知道 操作名称,也知道如何编写 YAML,所以我们需要做的就是确定 操作类型。获取操作类型的最佳方式与我们发布消息的方式相同。

我们看到我们的每个海龟都有一个名为rotate_absolute的服务。 让我们使用info子命令深入研究此操作。此命令有一个-t标志来列出消息的类型。

$ ros2 action info /turtle1/rotate_absolute -t
Action: /turtle1/rotate_absolute
Action clients: 0
Action servers: 1
  /turtlesim [turtlesim/action/RotateAbsolute]

第一行列出了操作名称。第二行给出了该操作的当前客户端数量。Action servers 行给出了此操作的操作服务器总数。最后一行给出了该操作的包和消息类型。

我们在这里可以看到,我们需要知道操作名称、类型和值。现在唯一的问题是弄清楚操作类型的格式。

让我们了解 RotateAbsolute 操作消息

可以使用 ros2 interface show 命令来查找操作消息的类型。让我们来看看:

$ ros2 interface show turtlesim/action/RotateAbsolute
# The desired heading in radians
float32 theta #< --- This section is the GOAL
---
# The angular displacement in radians to the starting position
float32 delta #< --- This section is the final result, different from the goal.
---
# The remaining rotation in radians
float32 remaining # < --- This is the current state.

这说明了绝对旋转的什么?

  • 有一个浮点输入 theta,即所需航向。第一部分是实际目标。
  • delta 是与初始航向的角度。这是操作完成时返回的值。
  • remaining 是要移动的剩余弧度。这是操作执行过程中由操作发布的值。

有了这些信息,我们可以创建对操作服务器的调用。我们将使用 -f 标志使其更清晰一些。留意你的乌龟!它应该慢慢移动。

$ ros2 action send_goal -f /turtle1/rotate_absolute turtlesim/action/RotateAbsolute {'theta: 1.70'}
Waiting for an action server to become available...
Sending goal:
  theta: 1.7

Feedback:
  remaining: 0.11599969863891602

Goal accepted with ID: 35c40e91590047099ae5bcc3c5151121

Feedback:
 remaining: 0.09999966621398926

Feedback:
 remaining: 0.06799960136413574

Feedback:
 remaining: 0.03599953651428223

Result:
 delta: -0.09600019454956055

Goal finished with status: SUCCEEDED

如果一切正常,我们应该看到我们的乌龟已经旋转了。

ROS Parameters

在 ROS 中,参数是系统中节点之间共享的值(如果您熟悉软件工程中的 黑板设计模式)。参数是任何节点都可以查询或写入的值。另一个很好的类比是普通软件程序中的全局常量。参数最适合用于配置您的机器人。例如,如果您正在建造一辆自动驾驶汽车,并希望将汽车的最大速度限制在 100 公里/小时,您可以创建一个名为“MAX_SPEED”的参数,该参数对所有节点都可见。

让我们通过运行 ros2 param --help 来查看 param 命令。

$ ros2 param --help
Various param related sub-commands

Commands:
  delete  Delete parameter
  get     Get parameter
  list    Output a list of available parameters
  set     Set parameter
  Call `ros2 param <command> -h` for more detailed usage.

从高层次来看,ROS 2 的 param 命令具有用于获取和设置变量的子命令,以及 list 功能和 delete 命令。与我们已经研究过的大多数其他命令一样,首先查看 list 是有益的。让我们看看文档中关于 list 命令的说明,然后看看调用子命令时会发生什么:

$ ros2 param list --help
usage: ros2 param list [-h] [--spin-time SPIN_TIME] [--include-hidden-nodes]
                       [--param-prefixes PARAM_PREFIXES [PARAM_PREFIXES ...]]
                       [node_name]

Output a list of available parameters

positional arguments:
  node_name             Name of the ROS node

optional arguments:
  -h, --help            show this help message and exit
  --spin-time SPIN_TIME
                        Spin time in seconds to wait for discovery (only
                        applies when not using an already running daemon)
  --include-hidden-nodes
                        Consider hidden nodes as well
  --param-prefixes PARAM_PREFIXES [PARAM_PREFIXES ...]
                        Only list parameters with the provided prefixes
$ ros2 param list
/turtlesim:
  background_b
  background_g
  background_r
  use_sim_time

此子命令中唯一值得注意的参数是 node_name,它允许您将 param list 的范围缩小到特定节点使用的参数。就 turtlesim 节点中的参数而言,我们看到对 paramlist 的调用为我们提供了:三个名为 background_x 的背景颜色控制参数和一个 use_sim_time 参数。要了解有关 param 命令的所有信息,我们为什么不尝试使用 CLI 更改这些背景颜色参数呢?

更改背景颜色的第一步是查看当前颜色是什么。param get 子命令需要节点名称和参数名称。在上面的列表中,我们可以看到节点名称是顶级元素,前面带有正斜杠,即 /turtlesimparam get 的语法是 ros2 param get <node_name> <param>。让我们试一试,看看我们当前的背景颜色值。

$ ros2 param get /turtlesim background_b
Integer value is: 255
$ ros2 param get /turtlesim background_g
Integer value is: 86
$ ros2 param get /turtlesim background_r
Integer value is: 69

在大多数计算机上,颜色表示为 <R,G,B> 值的三元组。颜色值 <69,86,255> 对应于长春花蓝色。要更改 turtlesim 的颜色,我们需要先设置参数值,然后重置 turtlesim 以使其应用颜色更改。我们之前介绍了调用服务的基础知识,因此我们不会介绍构建服务调用的步骤。让我们尝试将背景颜色的蓝色分量设置为 128。

$ ros2 param set turtlesim background_b 128
Set parameter successful
$ ros2 service call /reset std_srvs/srv/Empty
requester: making request: std_srvs.srv.Empty_Request()

response:
std_srvs.srv.Empty_Response()

如果一切正常,你的乌龟应该看起来像下面的屏幕。

image

ROS Bags

ROS 包是 ROS 用于记录和重放数据的工具。ROS 包就像日志文件一样,可让您将数据与消息一起存储。ROS 系统可以生成大量数据,因此在打包数据时,您必须选择所需的主题。包是测试和调试应用程序的绝佳工具,也是构建强大单元测试的绝佳工具。

让我们通过在终端中输入ros2 bag --help来查看 root ROS Bag 命令。如果出现错误,您可能需要安装 ROS Bag,因为它通常位于单独的包中。在 Linux 上,您可以运行“sudo apt install ros-eloquent-ros2bag”,它会自动为您安装包。

$ ros2 bag -h
usage: ros2 bag [-h] Call `ros2 bag <command> -h` for more detailed usage. ...

Various rosbag related sub-commands

Commands:
  info    ros2 bag info
  play    ros2 bag play
  record  ros2 bag record

如您所见,有三个子命令,recordplayinfo。使用这些

命令,您可以录制一个 bag 文件,播放/重放您录制的文件,并查找有关 bag 文件的信息。

让我们尝试录制我们的第一个 bag 文件。为此,我们需要三个终端,它们都运行 ROS。第一个终端应该已经运行了我们的 turtlesim。如果它没有运行,您可以使用 ros2 run turtlesim turtlesim_node 重新启动它。接下来

您需要再次启动 draw_square 演示以使默认的 turtle

移动。为此,运行 ros2 run turtlesim draw_square。现在,在第三个

终端中,我们可以通过运行 bag 命令来打包一些数据。让我们首先通过运行 ros2 bag record -h 来查看 record 子命令

$ ros2 bag record -h
usage: ros2 bag record [-h] [-a] [-o OUTPUT] [-s STORAGE]
                       [-f SERIALIZATION_FORMAT] [--no-discovery]
                       [-p POLLING_INTERVAL] [-b MAX_BAG_SIZE]
                       [topics [topics ...]]

ros2 bag record

positional arguments:
  topics                topics to be recorded

optional arguments:
  -h, --help            show this help message and exit
  -a, --all             recording all topics, required if no topics are listed
                        explicitly.
  -o OUTPUT, --output OUTPUT
                        destination of the bagfile to create, defaults to a
                        timestamped folder in the current directory
  -s STORAGE, --storage STORAGE
                        storage identifier to be used, defaults to "sqlite3"
  -f SERIALIZATION_FORMAT, --serialization-format SERIALIZATION_FORMAT
                        rmw serialization format in which the messages are
                        saved, defaults to the rmw currently in use
  --no-discovery        disables topic auto discovery during recording: only
                        topics present at startup will be recorded
  -p POLLING_INTERVAL, --polling-interval POLLING_INTERVAL
                        time in ms to wait between querying available topics
                        for recording. It has no effect if --no-discovery is
                        enabled.
  -b MAX_BAG_SIZE, --max-bag-size MAX_BAG_SIZE
                        maximum size in bytes before the bagfile will be
                        split. Default it is zero, recording written in single
                        bagfile and splitting is disabled.

我们从帮助文件中可以看到,记录包的语法只是为子命令提供要记录的主题列表。大多数其他参数都是为更高级的用户提供的,用于帮助配置如何以及何时存储数据。值得注意的是,有一个 -a, --all 命令可以记录所有数据。您还可以使用 -o, --output command 指定输出包文件。

让我们继续运行 bag 命令,并使用 -o 标志将 /turtle1/pose 主题上的姿势数据打包并保存到文件 turtle1.bag 中。请注意,程序将继续打包数据,直到您按下 CTRL-C,因此在终止它之前,请给命令 30 秒的时间来收集数据。

$ ros2 bag record /turtle1/pose -o turtle1
[INFO] [rosbag2_storage]: Opened database 'turtle1'.
[INFO] [rosbag2_transport]: Listening for topics...
[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/pose'
[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...
^C[INFO] [rclcpp]: signal_handler(signal_value=2)

现在我们收集了数据,让我们检查一下我们的 bag 文件。您可以使用 ros2 bag info 命令检查任何 bag 文件。此命令将列出 bag 中的消息、文件的持续时间以及消息数量。

$ ros2 bag info turtle1
Files:             turtle1.db3
Bag size:          268.4 KiB
Storage id:        sqlite3
Duration:          68.705s
Start:             May  4 2020 16:10:26.556 (1588633826.556)
End                May  4 2020 16:11:35.262 (1588633895.262)
Messages:          4249
Topic information: Topic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 4249 | Serialization Format: cdr

收集到 bag 文件后,您可以像正在运行的系统一样重播该文件。bag 是调试和测试的绝佳工具。您可以将 ROS bag 视为正在运行的 ROS 系统的记录。播放 bag 文件时,您可以使用大多数 ros2 CLI 工具来检查录制的主题。

要重播 bag,首先使用 CTRL-C 关闭 turtlesim_nodedraw_square 节点。现在在新的终端中使用以下命令重播 bag 文件:

$ ros2 bag play turtle1
[INFO] [rosbag2_storage]: Opened database 'turtle1'.

看起来应该没有什么事情发生,但实际上却发生了很多事情。 要查看发生了什么,请转到第二个终端。就像一个正在运行的机器人一样, 您应该能够listecho主题:

$ ros2 topic list
/parameter_events
/rosout
/turtle1/pose

$ ros2 bag info turtle1
x: 3.8595714569091797
y: 3.6481313705444336
theta: -1.2895503044128418
linear_velocity: 1.0
angular_velocity: 0.0
---

ROS2 Component Command

ROS2 Daemon Command

ROS2 Doctor Command

任何复杂的系统有时都会出现问题,知道如何描述您的系统以及正在发生的事情可以极大地帮助其他人帮助您解决问题。ROS 2 有一个 doctor 命令,您可以使用它来打印各种报告,这些报告可用于帮助向试图提供帮助的其他人传达系统状态。无论是您的同事、供应商还是在线论坛,提供有关您的 ROS 系统的详细和完整信息都可以大大帮助您解决问题。让我们在 ROS 2 的 --help 命令上调用:

$ ros2 doctor --help
usage: ros2 doctor [-h] [--report | --report-failed] [--include-warnings]

Check ROS setup and other potential issues

optional arguments:
  -h, --help            show this help message and exit
  --report, -r          Print all reports.
  --report-failed, -rf  Print reports of failed checks only.
  --include-warnings, -iw
                        Include warnings as failed checks. Warnings are
                        ignored by default.

从帮助文件中我们可以看到,我们有几个报告选项。一个选项是使用 -r 打印完整报告,或者使用 -rf 打印失败的内容。如果您正在运行 ros2 doctor -r,您应该会看到一份相当长的报告,其中包含有关您的计算机操作系统、网络配置和正在运行的 ROS 系统的信息。如果您遇到问题,您应该始终包含这份完整报告。

ROS 2 Interface

正如您已经看到的,ROS 使用标准消息,以便不同的包和程序(可能用不同的编程语言编写)都可以相互通信。为了使这一切正常进行,ROS 使用标准消息和基于这些标准消息构建的通信协议。这可能会使查找有关特定消息、服务或操作的类型信息变得困难。为了帮助开发人员编写 CLI 命令调用和开发客户端代码,ROS CLI 具有接口命令。我们在其他部分简要介绍了此命令,因为它是获取消息类型信息的首选工具。

为了更好地理解 interface 命令,我们首先查看其高级帮助命令,看看有哪些子命令可用:

$ ros2 interface --help
usage: ros2 interface [-h]
                      Call `ros2 interface <command> -h` for more detailed
                      usage. ...

Show information about ROS interfaces

optional arguments:
  -h, --help            show this help message and exit

Commands:
  list      List all interface types available
  package   Output a list of available interface types within one package
  packages  Output a list of packages that provide interfaces
  proto     Output an interface prototype
  show      Output the interface definition

  Call `ros2 interface <command> -h` for more detailed usage.

接口命令都旨在帮助您了解可用的消息类型。让我们深入研究一下 list 子命令。list 将列出系统上所有可用的消息、服务和操作。此命令具有可帮助您缩小搜索范围的标志。即使是基本的 ROS 安装也有很多消息,因此您应该熟悉的工具是 grepgrep 可让您搜索一些文本以快速轻松地找到您要查找的内容。您可以使用 -i 标志后跟要搜索的文本以不区分大小写的方式进行 grep。我们可以使用 UNIX 管道运算符 | 将此 CLI 工具绑定到我们的接口工具。下面的示例向您展示了如何使用列表操作以及如何使用它进行搜索:

$ ros2 interface list --only-msgs
Messages:
    action_msgs/msg/GoalInfo
    action_msgs/msg/GoalStatus
	... <DOZENS OF DIFFERENT TYPES> ...
	visualization_msgs/msg/MarkerArray
    visualization_msgs/msg/MenuEntry
$ ros2 interface list --only-msgs | grep -i point
    geometry_msgs/msg/Point
    geometry_msgs/msg/Point32
    geometry_msgs/msg/PointStamped
    map_msgs/msg/PointCloud2Update
    pcl_msgs/msg/PointIndices
    rcl_interfaces/msg/FloatingPointRange
    sensor_msgs/msg/PointCloud
    sensor_msgs/msg/PointCloud2
    sensor_msgs/msg/PointField
    trajectory_msgs/msg/JointTrajectoryPoint

使用 grep 搜索 CLI 输出是开发人员用来查找所需特定信息的常用策略。接下来的两个子命令 packagepackages 可用于首先确定系统上有哪些 ROS 包,然后深入研究单个包以确定该包中有哪些消息。请注意,您可以像以前一样使用 grep 搜索您感兴趣的特定内容。下面的示例向您展示了如何首先确定 std_msgs 是否已安装,然后找出它包含哪种数组类型:

$ ros2 interface packages
action_msgs
action_tutorials_interfaces
actionlib_msgs
builtin_interfaces
composition_interfaces
diagnostic_msgs
example_interfaces
geometry_msgs
lifecycle_msgs
logging_demo
map_msgs
nav_msgs
pcl_msgs
pendulum_msgs
rcl_interfaces
rosgraph_msgs
rqt_py_common
sensor_msgs
shape_msgs
std_msgs
std_srvs
stereo_msgs
tf2_msgs
trajectory_msgs
turtlesim
unique_identifier_msgs
visualization_msgs
kscottz@kscottz-ratnest:~/Code/ros2multirobotbook/src$ ros2 interface package std_msgs | grep -i array
std_msgs/msg/Int8MultiArray
std_msgs/msg/Int32MultiArray
std_msgs/msg/MultiArrayLayout
std_msgs/msg/UInt64MultiArray
std_msgs/msg/Float32MultiArray
std_msgs/msg/UInt16MultiArray
std_msgs/msg/UInt32MultiArray
std_msgs/msg/Int16MultiArray
std_msgs/msg/ByteMultiArray
std_msgs/msg/Int64MultiArray
std_msgs/msg/Float64MultiArray
std_msgs/msg/UInt8MultiArray
std_msgs/msg/MultiArrayDimension

接下来的两个命令特别有用,你应该记住它们,因为它们会让你的生活变得轻松很多。正如我们之前讨论过的那样,CLI 中的所有消息发布、服务调用和操作调用都以 YAML 格式接收你想要传输的消息类型和数据。但是如果你不知道消息格式,并且对 YAML 了解不多,该怎么办?interface showinterface proto 命令分别通过首先告诉你消息类型,然后告诉你消息格式,使这个过程更容易。回想一下本章前面我们在 turtle 模拟中调用 spawn 服务时的情况。我们可以使用 interface show 来大致告诉我们有关服务的信息以及每个值的含义。然后我们可以使用 interface proto(prototype 的缩写)来生成一条我们可以填写的空消息。请参见下面的示例:

$ ros2 interface show turtlesim/srv/Spawn
float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name
$ ros2 interface proto turtlesim/srv/Spawn
"x: 0.0
y: 0.0
theta: 0.0
name: ''
"
$ ros2 service call /spawn turtlesim/srv/Spawn "{<copy and paste proto here>}"

从上面的例子中,您可以看到这些工具是多么方便。值得注意的是,您需要将原型粘贴到一组引号和花括号中,才能使调用"{<prototype>}"起作用。

ROS 2 Launch

launch 命令用于运行 ROS 启动文件。到目前为止,我们一直使用 run 命令手动运行单个 ROS 程序,但这不是大型 ROS 系统通常的操作方式,许多机器人会控制数十甚至数百个小程序。ROS 启动命令与大多数其他 ROS 命令不同,它没有子命令,并且只有一个功能,即启动执行多个程序的 ROS 启动文件。为了说明此命令,让我们看一下它的帮助文件。

$ ros2 launch -h
usage: ros2 launch [-h] [-d] [-p | -s] [-a]
                   package_name [launch_file_name]
                   [launch_arguments [launch_arguments ...]]

Run a launch file

positional arguments:
  package_name          Name of the ROS package which contains the launch file
  launch_file_name      Name of the launch file
  launch_arguments      Arguments to the launch file; '<name>:=<value>' (for
                        duplicates, last one wins)

optional arguments:
  -h, --help            show this help message and exit
  -d, --debug           Put the launch system in debug mode, provides more
                        verbose output.
  -p, --print, --print-description
                        Print the launch description to the console without
                        launching it.
  -s, --show-args, --show-arguments
                        Show arguments that may be given to the launch file.
  -a, --show-all-subprocesses-output
                        Show all launched subprocesses' output by overriding
                        their output configuration using the
                        OVERRIDE_LAUNCH_PROCESS_OUTPUT envvar.

启动文件通常包含在 ROS 包中,通常存储在launch子目录中。现代启动文件通常用 Python 编写,并以*.launch.py​​文件扩展名结尾。launch命令有两个参数,第一个是包名称,然后是启动文件名。如果您不知道包中的启动文件,可以使用制表符补全列出所有可用的启动文件。最后,一些启动文件具有可以附加到命令的参数。如果您不确定启动文件的作用或它需要什么参数,--print--show-args命令将告诉您这些信息。让我们阅读multisym.launch.py​​启动文件,然后按照以下示例运行它(使用CTRL-C结束模拟):

$ ros2 launch turtlesim multisim.launch.py --show-args
Arguments (pass arguments as '<name>:=<value>'):

  No arguments.

$ ros2 launch turtlesim multisim.launch.py --print
<launch.launch_description.LaunchDescription object at 0x7f75aab63828>
├── ExecuteProcess(cmd=[ExecInPkg(pkg='turtlesim', exec='turtlesim_node'), '--ros-args'], cwd=None, env=None, shell=False)
└── ExecuteProcess(cmd=[ExecInPkg(pkg='turtlesim', exec='turtlesim_node'), '--ros-args'], cwd=None, env=None, shell=False)

$ ros2 launch turtlesim multisim.launch.py
[INFO] [launch]: All log files can be found below /home/kscottz/.ros/log/2020-06-24-14-39-03-312667-kscottz-ratnest-20933
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [turtlesim_node-1]: process started with pid [20944]
[INFO] [turtlesim_node-2]: process started with pid [20945]
^C[WARNING] [launch]: user interrupted with ctrl-c (SIGINT)

ROS 2 Lifecycle

ROS 2 有一项名为“生命周期”的新功能,可以更好地控制 ROS 节点的状态。大致来说,此功能允许节点拥有正确处理的复杂启动和关闭程序。这种节点的一个例子是控制传感器或执行器的节点,该节点需要在运行前执行开机自检或校准程序。ROS 设计文档 提供了有关生命周期节点中的状态和转换的很好的入门知识。让我们看看生命周期命令以确定可用的子命令:

$ ros2 lifecycle -h
usage: ros2 lifecycle [-h]
                      Call `ros2 lifecycle <command> -h` for more detailed
                      usage. ...

Various lifecycle related sub-commands

optional arguments:
  -h, --help            show this help message and exit

Commands:
  get    Get lifecycle state for one or more nodes
  list   Output a list of available transitions
  nodes  Output a list of nodes with lifecycle
  set    Trigger lifecycle state transition

  Call `ros2 lifecycle <command> -h` for more detailed usage.

nodes 子命令将列出给定系统上的所有生命周期节点。 列出节点后,您可以使用 ros2 lifecycle list <nodename> 列出每个节点的可用转换。这些转换由节点的当前状态决定,某些状态比其他状态具有更多可用的转换。如果您希望查询当前状态而不是可用转换,则可以使用 lifecycle get 返回目标节点的当前状态。一旦您满意地确定了节点的状态和可用的转换,就可以使用 lifecycle set 命令来触发节点转换到新状态。通常,这些 CLI 命令用于诊断系统的故障模式,或手动转换特定组件。

ROS 2 msg (Message)

ROS 2 Eloquent 是使用 msg 命令的最后一个 ROS 版本。msg 中的所有命令都反映在 interface 命令中。这些功能目前已弃用,并将在 Foxy 中删除。

ROS 2 pkg (Package)

ROS 2 package 命令是一个非常有用的命令,可以了解系统上安装了哪些 ROS 包、安装在哪里以及每个包中包含的可执行文件。这些工具对于了解现有的机器人配置和查找仅偶尔使用的工具特别有用。让我们首先看一下 pkg 命令的帮助文件:

$ ros2 pkg -h
usage: ros2 pkg [-h] Call `ros2 pkg <command> -h` for more detailed usage. ...

Various package related sub-commands

optional arguments:
  -h, --help            show this help message and exit

Commands:
  create       Create a new ROS2 package
  executables  Output a list of package specific executables
  list         Output a list of available packages
  prefix       Output the prefix path of a package
  xml          Output the XML of the package manifest or a specific tag

  Call `ros2 pkg <command> -h` for more detailed usage.

此命令有多种子命令,其中许多命令现在看起来应该相当熟悉。list 子命令的作用方式与我们之前讨论过的 list 子命令非常相似,但这个命令仅列出已安装的系统包。此子命令通常与 grep 一起使用,以帮助您找出是否安装了特定包。

找到已安装的包后,您可以使用 executables 命令列出包中包含的可执行文件。这比手动查找可执行文件更实用。子命令接受一个参数,即包名称。executables 命令有一个可选参数 --full-path,它将输出所有可执行程序的完整路径。下面的示例显示了如何使用这些命令检查所有 turtlesim 可执行文件的路径:

$ ros2 pkg list | grep turtle
turtlesim
$ ros2 pkg executables turtlesim --full-path
/opt/ros/eloquent/lib/turtlesim/draw_square
/opt/ros/eloquent/lib/turtlesim/mimic
/opt/ros/eloquent/lib/turtlesim/turtle_teleop_key
/opt/ros/eloquent/lib/turtlesim/turtlesim_node

如果您只是想知道 turtlesim 可执行文件的路径,则可以使用 prefix 子命令,该命令返回给定包的可执行文件的路径。

每个 ROS 包都包含一个 XML 文件,其中包含包的元数据,包括许可证、维护者及其依赖项等信息。ROS pkg 有一个方便的 xml 子命令来将这些文件打印到屏幕上,为您省去了查找和打开文件的麻烦。您可以在此命令的输出中使用 grep 来获取所需的信息。以下是使用 xmlprefix 查找 turtlesim 目录、其维护者及其许可证的示例:

$ ros2 pkg prefix turtlesim
/opt/ros/eloquent
$ ros2 pkg xml turtlesim | grep maintainer
  <maintainer email="dthomas@osrfoundation.org">Dirk Thomas</maintainer>
$ ros2 pkg xml turtlesim | grep license
  <license>BSD</license>
kscottz@kscottz-ratnest:~$

pkg 命令中的最后一个子命令是 createcreate 是一个帮助您创建 ROS 包的工具。我们将在本章后面使用此子命令来创建一个新的 ROS 包。简而言之,您将您的包名称和包的所有相关信息作为可选参数提供给命令。

ROS 2 Security