ROS2入门教程—理解服务(Service)
之前讲的话题通信是基于订阅/发布机制的,无论有没有订阅者,发布者都会周期发布数据,这种模式适合持续数据的收发,比如传感器数据。机器人系统中还有另外一些配置性质的数据,并不需要周期处理,此时就要用到另外一种ROS通信方式——服务(Service)。服务是基于客户端/服务器模型的通信机制,服务器端只在接收到客户端请求时才会提供反馈数据。
1 启动小海龟仿真器
打开新终端并运行:
ros2 run turtlesim turtlesim_node
打开另一个终端并运行:
ros2 run turtlesim turtle_teleop_key
2 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/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/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically
在列表中可以看到每个节点都有6个带有“parameters”
的服务,在ROS2中,几乎每一个节点都会有这几个服务,主要是用来设置一些参数的,算是节点的默认服务配置,这里我们暂时忽略这些默认的服务,主要看其他几个海龟仿真器提供的功能性质的服务。
3 ros2 service type
类似话题中的消息,服务中完成通信的数据也是有数据结构的,只不过是有请求和应答两部分的数据组成的。我们可以通过以下命令来查看某一个服务的数据结构:
ros2 service type <service_name>
我们先来看看/turtlesim
的/clear
服务。在新终端中,输入命令:
ros2 service type /clear
将返回如下结果:
std_srvs/srv/Empty
Empty
类型表示服务调用在发出请求时不发送数据,在接收响应时不接收数据。
4 ros2 service list -t
类似查看所有节点的话题消息类型,也可以用类似的方式查看所有服务的数据类型:
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/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/list_parameters [rcl_interfaces/srv/ListParameters]
/turtlesim/set_parameters [rcl_interfaces/srv/SetParameters]
/turtlesim/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
5 ros2 service find
如果要查找特定类型的所有服务,可以使用以下命令:
ros2 service find <type_name>
比如可以查找所有提供std_srvs/srv/Empty
数据类型的服务:
ros2 service find std_srvs/srv/Empty
在终端中将会输出:
/clear
/reset
6 ros2 interface show
现在我们已经可以看到某一个服务的数据类型了,那这种数据类型具体的数据结构是什么样的呢?可以使用这个命令来查看:
ros2 interface show <type_name>
比如,运行如下命令,
ros2 interface show std_srvs/srv/Empty
终端中会输出如下信息:
---
这里的“---”
在服务的数据结构中是用来分割请求和应答两个部分的数据,这里之所以只有“---”
,是因为std_srvs/srv/Empty
的请求和应答都不需要任何数据描述,类似一个触发信号。让我们查看一个具有发送和接收数据类型的服务,例如/spawn
。从ros2 service list -t
的结果,我们知道/spawn
的数据类型是turtlesim/srv/Spawn
。要查看/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
服务请求部分所需的参数。x
, y
和theta
确定生成的海龟的位置,name
显然是可选的。在这种情况下,您不需要了解该行下方的信息,但它可以帮助您了解从调用中获得的响应的数据类型。
7 ros2 service call
我们已经了解了如何查看服务的数据类型和结构,接下来通过终端尝试发送一个服务请求。
ros2 service call <service_name> <service_type> <arguments>
<arguments>
部分是可选的,比如std_srvs/srv/Empty
类型的服务就没有任何参数:
ros2 service call /clear std_srvs/srv/Empty
这个服务只是出发一个信号,让海龟仿真器清除海龟后边的运动轨迹,不需要传输什么数据:
现在让我们通过调用服务/spawn
并输入参数来生成一个新的海龟。<arguments>
部分就需要采用YAML语法输入上边看到的请求数据了:
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')
同时,海龟仿真器中立刻就可以看到一只新的海龟:
请求数据中的x
、y
、theta
表示海龟的横纵坐标和旋转角度,name
表示新生海龟的名字。 好啦,这就是ROS2中的服务概念啦,简而言之,客户端发送请求,服务端完成处理后反馈应答,通信只会交互一次数据,不像话题是周期发送数据的。