时间:2026-03-24 09:35
人气:
作者:admin
接前文我们知道节点里面有多个功能,其中之一是服务,本章学习服务 services。


服务就是我们常用的C/S模型,Client 客户端请求,而Service 服务端提供相应的响应。相较于发布者-订阅者主题模型,调用与响应模型是点对点的通信。
前一章的内容,运行turtlesim的显示节点,打开终端,执行 ros2 run turtlesim turtlesim_node (ros2 run <包名> <执行名>)
运行turtlesim的控制节点,另开终端,执行 ros2 run turtlesim turtle_teleop_key
在新终端中执行命令ros2 service list将返回系统中当前所有活跃服务的列表:
root@bc2bf85b2e4a:/ros2_ws# 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
你会看到两个节点名称中包含相同的六个服务(describe_parameters、get_parameter_types、get_parameters、list_parameters、set_parameters、set_parameters_atomically)。 ROS 2 中几乎每个节点都有这些基础设施服务,参数就是基于这些服务构建的。 关于参数的更多内容将在下一个教程中介绍。 在本教程中,参数服务将被省略。
查看服务数据类型(请求参数和响应参数类型)
服务数据类型描述服务的请求和响应数据结构。 服务类型定义类似于主题类型,但服务类型分为请求参数和响应参数2部分。
要了解服务类型,使用命令: ros2 service type <service_name>
让我们来看看 turtlesim 的服务。 在新终端中,输入以下命令:ros2 service type /clear
root@bc2bf85b2e4a:/ros2_ws# ros2 service type /clear
std_srvs/srv/Empty
Empty类型意味着服务调用在发出请求时不发送数据,接收响应时也不接收数据。ros2 service list 加上参数-t ,可以查看服务名和数据类型
root@bc2bf85b2e4a:/ros2_ws# 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]
...
/turtle1/set_pen [turtlesim/srv/SetPen]
/turtle1/teleport_absolute [turtlesim/srv/TeleportAbsolute]
...
/turtlesim/set_parameters [rcl_interfaces/srv/SetParameters]
/turtlesim/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
接口参数(请求参数和响应参数类型)
跟上一节相似,我们需要知道具体的类型才能给对应服务发送请求。错误的数据类型调用会引发服务的失败响应,用接口参数查看ros2 interface show <数据类型>
root@bc2bf85b2e4a:/ros2_ws# ros2 interface show std_srvs/srv/Empty
---
该结构将请求结构(上图)与响应结构(下文)分开。 但正如你之前学到的,这种类型不会发送或接收任何数据。 所以,自然,它的结构是空白的。
再试试服务/spawn的消息 turtlesim/srv/Spawn (回想一下ros2 service list -t)
root@bc2bf85b2e4a:/ros2_ws# 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
---上方的信息是请求参数: x,y,theta,name。(x,y,theta确定生成龟的二维姿态,name是可选的)---下方的信息是响应参数: name。
调用服务
现在已经知道了服务类型,和请求参数的结构,可以用以下方式调用一个服务: ros2 service call <服务名> <请求参数类型> <实际参数> 其中<实际参数>可以为空, 下面调用ros2 service call /clear std_srvs/srv/Empty
root@bc2bf85b2e4a:/ros2_ws# ros2 service call /clear std_srvs/srv/Empty
requester: making request: std_srvs.srv.Empty_Request()
response:
std_srvs.srv.Empty_Response()
实际效果是会清空小乌龟绘制的线 
我们试试另一个命令ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}" 生成其他小乌龟
root@bc2bf85b2e4a:/ros2_ws# 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')
root@bc2bf85b2e4a:/ros2_ws# 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='turtle3')
root@bc2bf85b2e4a:/ros2_ws# ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 7, theta: 0.2, name: ''}"
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=7.0, theta=0.2, name='')
response:
turtlesim.srv.Spawn_Response(name='turtle4')
实际效果是生成很多小乌龟 
杂项
ros2 service find <type_name> 例如root@bc2bf85b2e4a:/ros2_ws# ros2 service find turtlesim/srv/Spawn
/spawn
服务就是我们常用的C/S模型,Client 客户端请求,而Service 服务端提供相应的响应。