ROS2教程 05 服务Service

简介: 本文是关于ROS2(机器人操作系统2)中服务(Service)机制的教程,介绍了服务与话题(Topic)的区别、ROS2服务的相关命令,包括列出服务、查找服务、获取服务类型和调用服务,并通过示例代码展示了如何创建服务端(Server)和客户端(Client),以及如何测试服务调用过程。

一、ROS2 服务Service 运行示意图

在这里插入图片描述

服务Service是一种通信方式,与话题Topic不同,服务是call-and-response模型,不同于话题的publisher-subscriber模型。因此,话题Topic用于订阅数据流并获得持续更新,而服务Service仅在被客户端Client请求调用Request时,从服务端Server取得数据,并将客户端Client的反馈Response传回给服务端Server

话题Topic用于单向通信,而服务Service用于双向通信,在需要持续发布内容时,通常采用话题Topic方式

ROS2中的每个节点基本都包含这六项Service

/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

二、ros2 service

ROS2 service下的命令有四条

  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

可以看到和ros1的service没有什么区别

ROS1
Commands: rosservice args print service arguments rosservice call
提供所需参数并请求某服务 call the service with the provided args rosservice find
find services by service type rosservice info print information about
service rosservice list list active services rosservice type print
service type rosservice uri print service ROSRPC uri

① ros2 service list

输出当前存在的话题Service列表

ros2 service list
OUTPUT:
/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

同理,当添加 -t 后缀时将同时输出服务列表与各个服务Service的消息类型Message Type

② ros2 service type

输出服务Service的类型,type含有两部分,其中一个消息是用于请求,另一个用于反馈处理结果,他们之间用三个短横线分开

ros2 service type /spawn
OUTPUT:
turtlesim/srv/Spawn

查看消息类型MessageType具体的结构可以通过如下命令

ros2 service type /clear
OUTPUT:
float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name

③ ros2 service find

根据消息类型查找属于该消息类型的服务

ros2 service find std_srvs/srv/Empty
OUTPUT:
/clear
/reset

④ ros2 service call

直接在命令行中请求服务call service

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

以召唤海龟为例

ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: 'new_turtle'}"
OUTPUT:
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=2.0, theta=0.2, name='new_turtle')

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

三、服务端 Server

1.新建功能包

ros2 pkg create --build-type ament_python py_srv_cli --dependencies rclpy example_interfaces

此处在新建功能包时为其添加了依赖 rclpy和example_interfaces
example_interfaces是ros2的数据类型接口,里面有用于ROS2教学的一些样例数据类型,比如example_interfaces/srv/AddTwoInts就是本示例要使用的数据类型

2.新建服务端 Server

编写流程

1.编程接口初始化
2.创建节点并初始化
3.创建服务器端对象
4.通过回调函数处进行服务
5.向客户端反馈应答结果
6.销毁节点并关闭接口

源码示例

from example_interfaces.srv import AddTwoInts # 导入需要使用的srv数据类型

import rclpy
from rclpy.node import Node


class MinimalService(Node):

    def __init__(self):
        super().__init__('minimal_service')
        # 创建server 
        # 数据类型,服务名称,回调函数
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)

    #回调函数
    def add_two_ints_callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))

        return response #回调函数的返回值将被返回


def main(args=None):
    rclpy.init(args=args)

    minimal_service = MinimalService()

    rclpy.spin(minimal_service)

    rclpy.shutdown()


if __name__ == '__main__':
    main()

3.添加依赖

在功能包目录下打开package.xml,修改以下内容[可选,不影响使用]
例子:

<description>Examples of minimal publisher/subscriber using rclpy</description>
<maintainer email="hermanye233@icloud.com">Herman Ye</maintainer>
<license>Apache License 2.0</license>

继续添加内容[必须]
当功能包里的代码被执行时,这些语句声明了功能包的依赖
因为在创建功能包时已经添加了依赖,因此此处无需重复添加

  <depend>rclpy</depend>
  <depend>example_interfaces</depend>

4.添加入口点

打开setup.py,添加入口点

maintainer='Herman Ye',
maintainer_email='hermanye233@icloud.com',
description='Examples of minimal publisher/subscriber using rclpy',
license='Apache License 2.0',

在entry_points下的这个位置添加以下命令

'service = py_srv_cli.service_member_function:main',

最终效果:

    entry_points={
   
   
        'console_scripts': [
        'service = py_srv_cli.service_member_function:main',
        ],
    },

四、客户端 Client

1.新建客户端 Client

在和服务端相同的目录下新建client_member_function.py

编写流程

1.编程接口初始化
2.创建节点并初始化
3.创建客户端对象
4.创建并发送请求数据
5.等待服务器端应答数据
6.销毁节点并关闭接口

源码示例

import sys #客户端节点代码使用sys.argv来访问命令行输入的请求命令的参数,这是客户端的特别之处

from example_interfaces.srv import AddTwoInts # 数据类型导入
import rclpy
from rclpy.node import Node # 节点必备的类


class MinimalClientAsync(Node):

    def __init__(self):
        super().__init__('minimal_client_async') # async是异步通信的意思
        # 创建客户端
        # 数据类型 服务名称
        self.cli = self.create_client(AddTwoInts, 'add_two_ints')
        # 超时
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')
        self.req = AddTwoInts.Request() #request部分定义

    def send_request(self): # 发送函数
        self.req.a = int(sys.argv[1]) # 命令行输入的数1
        self.req.b = int(sys.argv[2]) # 命令行输入的数2 sys.argv[x]获取了命令行输入的参数
        self.future = self.cli.call_async(self.req) #future包含反馈的response


def main(args=None):
    rclpy.init(args=args) #初始化rclpy

    minimal_client = MinimalClientAsync() # 客户端
    minimal_client.send_request() # 客户端发送请求

    while rclpy.ok(): # 当ros准备就绪时
        rclpy.spin_once(minimal_client) # 循环客户端
        if minimal_client.future.done(): # 当future完成时,代表服务端已经完成了服务并且反馈response了result
            try: # 首先执行
                response = minimal_client.future.result()
            except Exception as e: # 程序异常时执行
                minimal_client.get_logger().info(
                    'Service call failed %r' % (e,))
            else: # 程序没有异常时会执行
                minimal_client.get_logger().info(
                    'Result of add_two_ints: for %d + %d = %d' %
                    (minimal_client.req.a, minimal_client.req.b, response.sum))
            break # 跳出循环

    minimal_client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

call_async()
也可以使用call_async()来执行异步呼叫服务,作用和上文中的send_request类似但更简单,上文的send_request有输入参数,因此独立成发送函数

call_async(request)
Make a service request and asyncronously get the result.

Parameters
request (~SrvTypeRequest) – The service request.

Return type
Future

Returns
A future that completes when the request does.

Raises
TypeError if the type of the passed request isn’t an instance of the Request type of the provided service when the client was constructed.

要获取更多信息请查阅rclpy文档

2.添加入口点

打开setup.py,添加入口点
在entry_points下的这个位置添加以下命令

'client = py_srv_cli.client_member_function:main',

最终效果:

    entry_points={
   
   
        'console_scripts': [
        'service = py_srv_cli.service_member_function:main',
        'client = py_srv_cli.client_member_function:main',
        ],
    },

五、测试 客户端-服务-服务端

1.编译

colcon build --packages-select py_srv_cli

2.运行

先运行服务端

ros2 run py_srvcli service

随后运行客户端并键入参数

ros2 run py_srvcli client 2 3
目录
相关文章
|
1月前
|
Ubuntu 机器人 Linux
|
2月前
|
弹性计算 持续交付 API
基于 ROS 的Terraform托管服务轻松部署ChatGLM-6B
文章介绍了如何利用ROS和Terraform模板轻松自动化部署基于GLM架构、优化中文对话的ChatGLM-6B模型至阿里云,提高了部署效率与便捷性,适用于多种应用场景,且模型部署过程详细,彰显了基础设施即代码(IaC)的优势。
48 3
基于 ROS 的Terraform托管服务轻松部署ChatGLM-6B
|
2月前
|
弹性计算 人工智能 持续交付
基于 ROS 的Terraform托管服务轻松部署Qwen-7B-Chat
文章介绍了如何利用ROS和Terraform模板轻松自动化部署阿里云的Qwen-7B-Chat大语言模型服务,提高了部署效率与便捷性,是实现云资源和服务快速上线的最佳实践。
68 2
基于 ROS 的Terraform托管服务轻松部署Qwen-7B-Chat
|
1月前
|
传感器 数据可视化 机器人
【ROS速成】半小时入门机器人ROS系统简明教程之可视化系统(三)
半小时入门机器人ROS系统简明教程之可视化系统
|
1月前
|
机器人
【ROS速成】半小时入门机器人ROS系统简明教程之安装测速(二)
半小时入门机器人ROS系统简明教程之安装测速
|
3月前
|
存储 自然语言处理 机器人
ROS2教程06 ROS2行动
这篇文章是关于ROS2(Robot Operating System 2)行动(Action)通信机制的教程,包括行动的概念、特点、命令行工具的使用,以及如何编写行动的客户端和服务器代码,并介绍了如何测试行动通信。
114 4
ROS2教程06 ROS2行动
|
3月前
|
机器人 Shell Python
ROS2教程05 ROS2服务
这篇文章是关于ROS2(Robot Operating System 2)服务的教程,涵盖了服务的概念、特性、命令行工具的使用,以及如何编写服务的服务器和客户端代码,并提供了测试服务通信机制的示例。
88 4
ROS2教程05 ROS2服务
|
3月前
|
传感器 算法 数据可视化
ROS2教程04 ROS2话题
这篇文章是关于ROS2(Robot Operating System 2)的教程,主要介绍了ROS2中话题的概念、特性、使用方式,以及如何编写发布者和订阅者的代码。
85 3
ROS2教程04 ROS2话题
|
3月前
|
传感器 自然语言处理 机器人
ROS2教程03 ROS2节点
本文是关于ROS2(机器人操作系统2)节点的教程,涵盖了节点的概念、特性、使用方法,以及如何编写、测试和使用ROS2节点相关的命令行工具。文章介绍了节点的独立性、任务执行、跨硬件分布和多语言编写能力。详细解释了如何启动节点、查看节点信息、编写节点代码(包括面向过程和面向对象的方法),以及如何为功能包添加依赖和入口点。此外,还探讨了重映射节点名称和使用节点命令行工具的方法,如 `ros2 node info` 和 `ros2 node list`。适合已安装ROS2 Humble和Ubuntu 22.04操作系统,并具有Shell基础知识的读者学习。
94 1
|
3月前
|
机器人 Shell 开发者
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
这篇文章是关于ROS2(Robot Operating System 2)中功能包、依赖管理、工作空间配置和编译的教程,涵盖了ROS2工作空间的概念、如何获取和安装功能包的依赖、构建工作空间的步骤,以及如何创建和管理ROS2功能包,包括使用命令行工具对功能包进行操作的方法。
382 0
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译

推荐镜像

更多