Skip to main content

服务通信

目标

  • 学习如何使用命令行工具了解 ROS 2 中的服务(Services)。

理解 ROS 2 服务 (Services)

服务是 ROS 图中的节点之间进行通信的另一种方法。服务基于调用 - 响应模型,与主题的发布 - 订阅模型相对。当主题允许节点订阅数据流并持续更新时,服务仅在被客户端特别调用时提供数据。

单个服务客户端 多个服务客户端

本教程中提到的一些概念,如节点 (Node)主题 (Topic),已在系列教程的前几部分中介绍过。

你需要turtlesim 包

一如既往,不要忘记在你打开的每个新终端中源入 ROS 2 环境 (配置 ROS 2 环境)。

1. 设置

启动两个 turtlesim 节点,/turtlesim/teleop_turtle

打开一个新终端并运行:

ros2 run turtlesim turtlesim_node

再打开另一个终端并运行:

ros2 run turtlesim turtle_teleop_key

2. ros2 service list

在一个新终端中运行 ros2 service list 命令:

ros2 service list

它将返回系统中当前所有活动的服务列表:

/clear
/kill
/reset
/spawn
/teleop_turtle/describe_parameters
/teleop_turtle/get_parameter_types
/teleop_turtle/get_parameters
/teleop_turtle/get_type_description
/teleop_turtle/list_parameters
/teleop_turtle/set_parameters
/teleop_turtle/set_parameters_atomically
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/get_type_description
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically

3. ros2 service type

要找出服务的类型,可以使用以下命令:

命令格式

ros2 service type <service_name>

让我们来看看 turtlesim 的 /clear 服务。在新终端中输入命令:

ros2 service type /clear

终端输出为:

std_srvs/srv/Empty

Empty 类型意味着服务调用在发送请求时不发送任何数据,在接收响应时也不接收任何数据。

3.1 ros2 service list -t

要同时查看所有活动服务的类型,可以在 list 命令后附加 --show-types 选项(简写为 -t):

ros2 service list -t

终端输出为:

/clear [std_srvs/srv/Empty]
/kill [turtlesim_msgs/srv/Kill]
/reset [std_srvs/srv/Empty]
/spawn [turtlesim_msgs/srv/Spawn]
/teleop_turtle/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/teleop_turtle/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
/teleop_turtle/get_parameters [rcl_interfaces/srv/GetParameters]
/teleop_turtle/get_type_description [type_description_interfaces/srv/GetTypeDescription]
/teleop_turtle/list_parameters [rcl_interfaces/srv/ListParameters]
/teleop_turtle/set_parameters [rcl_interfaces/srv/SetParameters]
/teleop_turtle/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
/turtle1/set_pen [turtlesim_msgs/srv/SetPen]
/turtle1/teleport_absolute [turtlesim_msgs/srv/TeleportAbsolute]
/turtle1/teleport_relative [turtlesim_msgs/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/get_type_description [type_description_interfaces/srv/GetTypeDescription]
/turtlesim/list_parameters [rcl_interfaces/srv/ListParameters]
/turtlesim/set_parameters [rcl_interfaces/srv/SetParameters]
/turtlesim/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]

4. ros2 service info

要查看特定服务的信息,可以使用以下命令:

命令格式

ros2 service info <service_name>

例如,你可以找到 /clear 服务的客户端和服务端数量:

ros2 service info /clear

它的输出如下:

Type: std_srvs/srv/Empty
Clients count: 0
Services count: 1

5. ros2 service find

如果你想查找特定类型的所有服务,可以使用以下命令:

命令格式

ros2 service find <type_name>

例如,你可以这样查找所有 Empty 类型的服务:

ros2 service find std_srvs/srv/Empty

它的输出如下:

/clear
/reset

6. ros2 interface show

你可以从命令行调用服务,但首先需要知道输入参数的结构。

命令格式

ros2 interface show <type_name>

尝试对 /clear 服务的类型 Empty 执行此操作:

ros2 interface show std_srvs/srv/Empty

它的输出如下:

---

--- 将请求结构(上方)与响应结构(下方)分开。正如你之前所学的, Empty 类型不发送或接收任何数据。因此,其结构自然是空的。

让我们分析一个发送和接收数据的服务的类型,比如 /spawn 。从 ros2 service list -t 的结果中,我们知道 /spawn 的类型是 turtlesim_msgs/srv/Spawn

要查看 /spawn 服务的请求和响应参数,请运行命令:

ros2 interface show turtlesim_msgs/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 所需的参数。 xytheta 确定了生成的乌龟的 2D 姿态,而 name 显然是可选的。

线下方的信息在这种情况下不是你需要了解的内容,但它可以帮助你理解从调用中获取的响应的数据类型。

7. ros2 service call

现在你知道了服务类型是什么,如何找到服务的类型,以及如何找到该类型参数的结构,你可以使用以下命令调用服务:

命令格式

ros2 service call <service_name> <service_type> <arguments>

例如,你知道 Empty 类型的服务没有任何参数:

ros2 service call /clear std_srvs/srv/Empty

这将清除 turtlesim 窗口中乌龟绘制的任何线条。

清除

现在让我们通过调用 /spawn 并设置参数来生成一个新的乌龟。命令行中的 <arguments> 需要用 YAML 语法编写。

输入命令:

ros2 service call /spawn turtlesim_msgs/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"

你的 turtlesim 窗口将立即更新,显示新生成的乌龟:

生成

8. ros2 service echo

要查看服务客户端和服务服务器之间的数据通信,可以使用 echo 来回显服务:

命令格式

ros2 service echo <service_name | service_type> <arguments>

ros2 service echo 依赖于服务客户端和服务器的服务内省,默认情况下是禁用的。要启用它,用户必须在创建服务客户端或服务器后调用 configure_introspection

启动 introspection_clientintrospection_service 服务内省演示。

ros2 launch demo_nodes_cpp introspect_services_launch.py

打开另一个终端并运行以下命令以启用 introspection_clientintrospection_service 的服务内省功能。

ros2 param set /introspection_service service_configure_introspection contents
ros2 param set /introspection_client client_configure_introspection contents

现在我们可以通过 ros2 service echo 看到 introspection_clientintrospection_service 之间的服务通信。

ros2 service echo --flow-style /add_two_ints

它的输出如下:

info:
event_type: REQUEST_SENT
stamp:
sec: 1767078307
nanosec: 328133096
client_gid: [1, 15, 165, 41, 232, 99, 26, 240, 0, 0, 0, 0, 0, 0, 19, 4]
sequence_number: 441
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1767078307
nanosec: 328438722
client_gid: [1, 15, 165, 41, 232, 99, 26, 240, 0, 0, 0, 0, 0, 0, 19, 4]
sequence_number: 441
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: RESPONSE_SENT
stamp:
sec: 1767078307
nanosec: 328799033
client_gid: [1, 15, 165, 41, 232, 99, 26, 240, 0, 0, 0, 0, 0, 0, 19, 4]
sequence_number: 441
request: []
response: [{sum: 5}]
---
info:
event_type: RESPONSE_RECEIVED
stamp:
sec: 1767078307
nanosec: 328986207
client_gid: [1, 15, 165, 41, 232, 99, 26, 240, 0, 0, 0, 0, 0, 0, 19, 4]
sequence_number: 441
request: []
response: [{sum: 5}]
---

小结

节点可以通过服务在 ROS 2 中进行通信。不同于主题——一种单向通信模式,其中节点发布的消息可以被一个或多个订阅者消费——服务是一种请求/响应模式,其中客户端向提供服务的节点发出请求,服务处理请求并生成响应。

通常不希望对连续调用使用服务;主题甚至动作会更适合。

在本教程中,你使用命令行工具识别、内省和调用了服务。

在下一个章节理解 ROS 2 参数 (Understanding-ROS2-Parameters)中,你将学习如何配置节点设置。