理解服务
目标:使用命令行工具了解 ROS 2 中的服务。
教程级别:初学者
时间:10 分钟
目录
-
背景
-
先决条件
-
任务
-
设置
-
2 ros2 服务列表
-
三种 ros2 服务类型
-
4 ros2 服务信息
-
5 ros2 服务查找
-
6 ros2 接口显示
-
7 ros2 服务调用
-
8 ros2 服务回声
-
-
摘要
-
下一步
-
相关内容
背景
服务是 ROS 图中节点间通信的另一种方法。服务基于呼叫-响应模型,与主题的发布-订阅模型不同。虽然主题允许节点订阅数据流并获取持续更新,但服务只在客户端明确调用时才提供数据。
先决条件
在本教程中提到的一些概念,如节点和主题,在系列的前几个教程中已经介绍过了。
您将需要 turtlesim 包。
始终不要忘记在您打开的每个新终端中获取 ROS 2 的源。
任务
1. 设置
启动两个 turtlesim 节点, /turtlesim
和 /teleop_turtle
。
打开一个新的终端并运行:
nginx
ros2 run turtlesim turtlesim_node
打开另一个终端并运行:
nginx
ros2 run turtlesim turtle_teleop_key
2 ros2 服务列表
在新终端运行 ros2 service list
命令将返回系统中当前所有活动服务的列表:
perl
cxy@ubuntu2404-cxy:~$ 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
您将看到两个节点都有六个带有 parameters
的服务在它们的名字中。ROS 2 中几乎每个节点都有这些基础设施服务,参数就是基于这些服务构建的。下一个教程中会有更多关于参数的内容。在本教程中,参数服务将不包括在讨论中。
目前,让我们专注于 turtlesim 特定的服务, /clear
, /kill
, /reset
, /spawn
, /turtle1/set_pen
, /turtle1/teleport_absolute
,以及 /turtle1/teleport_relative
。您可能还记得在使用 turtlesim、ros2 和 rqt 教程中通过 rqt 与这些服务中的一些进行交互。
3 ros2 服务类型
服务具有类型,这些类型描述了服务的请求和响应数据是如何结构化的。服务类型的定义与主题类型类似,不同之处在于服务类型有两部分:一个是请求的消息,另一个是响应的消息。
要查找服务的类型,请使用命令:
bash
ros2 service type <service_name>
让我们看一下 turtlesim 的 /clear
服务。在新终端中,输入命令:
bash
ros2 service type /clear
哪个应该返回:
typescript
cxy@ubuntu2404-cxy:~$ ros2 service type /clear
std_srvs/srv/Empty
Empty
类型意味着服务调用在发出请求时不发送数据,在接收响应时也不接收数据。
3.1 ros2 服务列表 -t
要同时查看所有活动服务的类型,您可以将 --show-types
选项(简写为 -t
)附加到 list
命令:
cpp
ros2 service list -t
将返回:
sql
cxy@ubuntu2404-cxy:~$ ros2 service list -t
/clear [std_srvs/srv/Empty]
/kill [turtlesim/srv/Kill]
/reset [std_srvs/srv/Empty]
/spawn [turtlesim/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/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/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 服务信息
要查看特定服务的信息,请使用以下命令:
nginx
ros2 service info <service_name>
这将返回服务类型以及服务客户端和服务器的数量。
例如,您可以找到 /clear
服务的客户端和服务器的数量:
nginx
ros2 service info /clear
将返回:
properties
cxy@ubuntu2404-cxy:~$ ros2 service info /clear
Type: std_srvs/srv/Empty
Clients count: 0
Services count: 1
5 ros2 服务查找
如果您想要查找特定类型的所有服务,您可以使用以下命令:
xml
ros2 service find <type_name>
例如,您可以像这样找到所有 Empty
类型的服务:
nginx
ros2 service find std_srvs/srv/Empty
将返回:
perl
cxy@ubuntu2404-cxy:~$ ros2 service find std_srvs/srv/Empty
/clear
/reset
6 ros2 接口显示
您可以从命令行调用服务,但首先您需要了解输入参数的结构。
kotlin
ros2 interface show <type_name>
尝试在 /clear
服务的类型 Empty
上使用这个:将返回:
sql
cxy@ubuntu2404-cxy:~$ ros2 interface show std_srvs/srv/Empty
---
---
将请求结构(上面)与响应结构(下面)分开。但是,如你之前所学, Empty
类型不发送或接收任何数据。因此,自然地,它的结构是空的。
让我们内省一个发送和接收数据的服务类型,就像 /spawn
。从 ros2 service list -t
的结果中,我们知道 /spawn
的类型是 turtlesim/srv/Spawn
。
要查看 /spawn
服务的请求和响应参数,请运行命令:
kotlin
ros2 interface show turtlesim/srv/Spawn
将返回:
sql
cxy@ubuntu2404-cxy:~$ 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
所需的参数。 x
、 y
和 theta
决定了生成的乌龟的 2D 姿态,而 name
显然是可选的。
线下的信息在这种情况下你不需要知道,但它可以帮助你理解你从调用中得到的响应的数据类型。
7 ros2 服务调用
现在您已经知道什么是服务类型,如何找到服务的类型,以及如何找到该类型参数的结构,您可以使用以下方式调用服务:
xml
ros2 service call <service_name> <service_type> <arguments>
可选部分是 <arguments>
。例如,您知道 Empty
类型的服务没有任何参数:
sql
ros2 service call /clear std_srvs/srv/Empty
此命令将清除 turtlesim 窗口中乌龟绘制的任何线条。
makefile
cxy@ubuntu2404-cxy:~$ ros2 service call /clear std_srvs/srv/Empty
requester: making request: std_srvs.srv.Empty_Request()
response:
std_srvs.srv.Empty_Response()
现在让我们通过调用 /spawn
并设置参数来生成一个新的乌龟。从命令行进行服务调用时,输入 <arguments>
需要采用 YAML 语法。
输入命令:
nginx
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
您将获得这种方法风格的视图,了解正在发生的事情,然后是服务响应:
sql
cxy@ubuntu2404-cxy:~$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=2.0, theta=0.2, name='')
response:
turtlesim.srv.Spawn_Response(name='turtle2')
您的 turtlesim 窗口将立即更新新生成的乌龟
8 ros2 服务回声
要查看服务客户端和服务服务器之间的数据通信 ,您可以使用以下方法 echo
服务:
xml
ros2 service echo <service_name | service_type> <arguments>
ros2 service echo
依赖于服务客户端和服务器的服务内省,该服务默认是禁用的。要启用它,用户必须在创建服务器客户端或服务器后调用 configure_introspection
。
启动 introspection_client
和 introspection_service
服务自检演示。
css
ros2 launch demo_nodes_cpp introspect_services_launch.py
打开另一个终端并运行以下命令以启用 introspection_client
和 introspection_service
的服务内省。
sql
ros2 param set /introspection_service service_configure_introspection contents
ros2 param set /introspection_client client_configure_introspection contents
现在我们可以通过 ros2 service echo
看到 introspection_client
和 introspection_service
之间的服务通信。
properties
cxy@ubuntu2404-cxy:~$ ros2 service echo --flow-style /add_two_ints
info:
event_type: REQUEST_SENT
stamp:
sec: 1720065556
nanosec: 372663510
client_gid: [1, 15, 189, 33, 116, 40, 126, 14, 0, 0, 0, 0, 0, 0, 21, 3]
sequence_number: 291
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1720065556
nanosec: 373104543
client_gid: [1, 15, 189, 33, 116, 40, 126, 14, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 291
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: RESPONSE_SENT
stamp:
sec: 1720065556
nanosec: 373481609
client_gid: [1, 15, 189, 33, 116, 40, 126, 14, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 291
request: []
response: [{sum: 5}]
---
info:
event_type: RESPONSE_RECEIVED
stamp:
sec: 1720065556
nanosec: 373846318
client_gid: [1, 15, 189, 33, 116, 40, 126, 14, 0, 0, 0, 0, 0, 0, 21, 3]
sequence_number: 291
request: []
response: [{sum: 5}]
---
摘要
节点可以使用 ROS 2 中的服务进行通信。与主题不同------主题是一种单向通信模式,节点发布的信息可以被一个或多个订阅者消费------服务是一种请求/响应模式,客户端向提供服务的节点发出请求,服务节点处理请求并生成响应。
通常,您不会希望使用服务来进行连续呼叫;主题或甚至行动会更合适。
在本教程中,您使用命令行工具来识别、内省和调用服务。
下一步
相关内容
查看这个教程;这是使用 Robotis 机器人臂的 ROS 服务的一个极好的现实应用。