ROS2教程05 ROS2服务

本文涉及的产品
资源编排,不限时长
简介: 这篇文章是关于ROS2(Robot Operating System 2)服务的教程,涵盖了服务的概念、特性、命令行工具的使用,以及如何编写服务的服务器和客户端代码,并提供了测试服务通信机制的示例。

ROS2服务

版权信息

Copyright 2023 Herman Ye@Auromix. All rights reserved.

This course and all of its associated content, including but not limited to text, 
images, videos, and any other materials, are protected by copyright law. 
The author holds all rights to this course and its contents.

Any unauthorized use, reproduction, distribution, or modification of this course 
or its contents is strictly prohibited and may result in legal action. 
This includes, but is not limited to:
Copying or distributing course materials without express written permission.
Reposting, sharing, or distributing course content on any platform without proper attribution and permission.
Creating derivative works based on this course without permission.
Permissions and Inquiries

If you wish to use or reproduce any part of this course for purposes other than personal learning, 
please contact the author to request permission.

The course content is provided for educational purposes, and the author makes no warranties or representations 
regarding the accuracy, completeness, or suitability of the course content for any specific purpose. 
The author shall not be held liable for any damages, losses, 
or other consequences resulting from the use or misuse of this course.

Please be aware that this course may contain materials or images obtained from third-party sources. 
The author and course creator diligently endeavor to ensure that these materials 
are used in full compliance with copyright and fair use regulations. 
If you have concerns about any specific content in this regard, 
please contact the author for clarification or resolution.

By enrolling in this course, you agree to abide by the terms and conditions outlined in this copyright notice.
AI 代码解读

学习目标

  • 熟悉ROS2的服务概念
  • 了解ROS2服务相关的命令行工具操作
  • 熟悉服务通信中的客户端和服务器代码编写
  • 熟悉服务通信的测试手段

难度级别

初级 中级 高级

预计耗时

35 mins

学习前提

对象 类型 状态
ROS2 Humble 软件 已安装
Ubuntu22.04操作系统 软件 已确认
Shell的基本使用 知识 已了解
ROS2 节点 知识 已了解
ROS2 话题 知识 已了解

什么是服务

服务(Service)是ROS(Robot Operating System)图中节点之间进行通信的另一种方式。它建立在调用和响应模型之上,与主题(Topic)的发布者-订阅者模型不同。虽然主题允许节点订阅数据流并获取持续的更新,但服务仅在客户端专门调用时才提供数据。

在这里插入图片描述

服务是一种通信方式,采用的是请求和响应模型,与主题的单向发布-订阅模型形成鲜明对比。话题用于节点之间的单向通信,而服务则支持双向通信,允许客户端向服务端发出请求,服务端处理请求并生成响应。

服务的特性

在这里插入图片描述

  • 服务是一对一或者一对多的
    服务可以是一对一或一对多的。这意味着可以有一个客户端向一个服务器请求服务,也可以有多个客户端向同一个服务器请求服务。举个例子,考虑一个早餐店,多个顾客可以来店里请求"购买早餐"的服务。每个顾客传递自己的请求,而服务器则生成相应的响应。

  • 服务不适合连续调用情境
    服务适合需要请求和响应的场景,其中客户端向节点发出请求以获得特定服务,而服务会处理请求并生成相应的响应。
    对于需要持续发布内容而不需要反馈的情况,通常采用话题方式,而服务更适合需要请求和响应的通信需求。这种区分有助于在机器人系统中选择适当的通信方式,以满足不同的应用需求。

  • 双向通信
    话题是用于单向通信,信息发布者将数据发送到话题,然后订阅者获取这些数据。
    这种方式适用于需要将信息广播给多个订阅者的场景,但通常不支持双向通信。
    然而,服务提供了一种双向通信的机制,其中客户端(Client)可以向服务端(Server)发送请求,然后服务端会处理请求并发送响应回客户端。
    这种请求-响应模型使得服务适用于需要交互式通信的场景,例如请求特定任务的执行并接收结果。

服务的命令行使用

命令 作用
call 调用一个服务
find 查看给定服务类型的可用服务列表
list 查看可用服务的列表
type 查看服务的类型

让我们以调用 turtlesim 示例中的 /clear 服务为例来讲解服务的命令行使用:

首先,让小乌龟先绘制出一些轨迹,随后使用/clear来清理轨迹

ros2 service call /clear std_srvs/srv/Empty
AI 代码解读

在这里插入图片描述
在这里插入图片描述

查看可用服务的列表

使用此命令可以输出当前存在的服务列表:

ros2 service list
AI 代码解读

在ROS2中,每个节点基本上都包含以下六个服务,这些服务用于节点参数的基本设置,关于节点参数的概念将在后续的教程中解释,此处不涉及。

hello_world_demo是一个不包含自定义服务的demo,但仍然可以发现它有一些基本的服务可以调用。
在这里插入图片描述

对于turtlesim这样的包,则是有相关的服务可以调用:

在这里插入图片描述

查看服务的消息类型

同样,当添加-t后缀时,会同时输出服务列表和各个服务的消息类型:

ros2 service list -t
AI 代码解读

在这里插入图片描述
若需要查看特定服务类型的具体结构,可以通过使用 ros2 service typeros2 interface show 命令来完成。首先,使用 ros2 service type 获取服务的类型信息,接着使用 ros2 interface show 获取该类型的具体消息结构。

服务消息类型的结构通常包括两部分:一个用于请求服务的消息结构,另一个用于描述响应服务结果的消息结构。它们之间通过一行三个短横线进行分隔。

以下是示例命令,用于查看名为 `/spawn 的服务类型的具体结构

ros2 service type /spawn
AI 代码解读
ros2 interface show turtlesim/srv/Spawn
AI 代码解读

在这里插入图片描述

根据服务消息类型反查该类型的服务

根据服务消息类型来检索相应的服务是ROS 2 中的一项常见任务,这个命令会返回与指定消息类型相关联的可用服务的列表。
此处以查找与std_srvs/srv/Empty消息类型相关联的服务为例,我们可以执行以下命令:

ros2 service find std_srvs/srv/Empty
AI 代码解读

可以看到/clear/reset都是消息类型为std_srvs/srv/Empty的服务
在这里插入图片描述

请求服务

在ROS 2中,要通过命令行直接请求服务,你可以使用以下指令:

ros2 service call <service_name> <service_type> <arguments>
AI 代码解读

让我们以召唤一个海龟(也就是刚才的/spawn服务)为例来说明这个过程:

ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: 'new_turtle'}"
AI 代码解读

这个命令中指定了需要调用的服务、服务的消息类型、具体的参数(比如乌龟名为’new_turtle’,位置为(2,2),角度为0.2)
在这里插入图片描述
此时再次查看ROS中的节点和话题:
在这里插入图片描述

思考:
为什么没有新的节点诞生?
此时如果用键盘节点控制乌龟,会发生什么?为什么?
如何控制新诞生的那只乌龟?

ros2 run turtlesim turtle_teleop_key --ros-args --remap /turtle1/cmd_vel:=/new_turtle/cmd_vel --remap __node:=new_turtle_teleop
AI 代码解读

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

服务的编程使用

服务器

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

1.创建源码文件

# Go to your src
cd ~/ros2_workspace/src
# Go to your package
cd ros2_learning/ros2_learning
# Create file
touch service_demo_server.py
AI 代码解读

2.编写源码文件

from example_interfaces.srv import AddTwoInts  # 导入需要使用的srv数据类型,AddTwoInts是示例消息接口的类型
import rclpy
from rclpy.node import Node


class ServiceDemoServer(Node):
    def __init__(self):
        super().__init__("service_demo_server")
        # 创建server
        # 数据类型,服务名称,回调函数
        self.srv = self.create_service(
            AddTwoInts, "add_two_ints", self.add_two_ints_callback
        )
        self.get_logger().info("service_demo_server start")
    # 回调函数
    # 通过ros2 interface show example_interfaces/srv/AddTwoInts 查看这个消息类型的结构
    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)  # 初始化rclpy

    service_demo_server = ServiceDemoServer()  # 实例化

    rclpy.spin(service_demo_server)  # 循环

    rclpy.shutdown()  # 关闭


if __name__ == "__main__":
    main()
AI 代码解读

3.添加依赖

在创建功能包时,添加依赖项是一个关键步骤,因为这些依赖项是功能包所需的其他软件包或库。要实现这一目标,你需要编辑功能包的 package.xml 文件。下面是如何在其中添加依赖的详细步骤:

首先,打开功能包目录下的 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>
AI 代码解读

随后在 package.xml 中,你需要声明功能包的依赖项。在这个示例中,我们需要依赖两个库:rclpyexample_interfaces

rclpy 是 ROS 2 的 Python客户端库,用于编写 ROS 2 节点。而 example_interfaces 包含了 ROS 2 的官方教程数据类型接口,其中包括了一些用于教学和示例的数据类型,比如 example_interfaces/srv/AddTwoInts,这是本示例中要使用的数据类型。

  <depend>rclpy</depend>
  <depend>example_interfaces</depend>
AI 代码解读

4.添加入口点

接下来,你需要编辑 setup.py 文件,以定义功能包的入口点(entry point)。入口点是功能包中的可执行程序,它们可以在 ROS 2 中运行。在 setup.py 文件中,你需要添加入口点的定义。
首先,更新功能包的元信息,例如:

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

然后,在 entry_points 部分添加以下命令:

"server = ros2_learning.service_demo_server:main",
AI 代码解读

在这里插入图片描述

客户端

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

1.创建源码文件

在和服务端相同的目录下新建源码文件:

# Go to your src
cd ~/ros2_workspace/src
# Go to your package
cd ros2_learning/ros2_learning
# Create file
touch service_demo_client.py
AI 代码解读

2.编写源码文件

import sys  # 客户端节点代码使用sys.argv来访问命令行输入的请求命令的参数
from example_interfaces.srv import AddTwoInts  # 要使用的数据类型导入
import rclpy  # 引入ROS接口
from rclpy.node import Node  # 引入节点类


class ServiceDemoClient(Node):
    def __init__(self):
        super().__init__("service_demo_client")  # 以异步通信模式为例
        # 创建客户端
        # 数据类型 服务名称
        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, a, b):  # 发送函数
        self.req.a = a
        self.req.b = b
        self.future = self.cli.call_async(self.req)  # 异步调用服务
        rclpy.spin_until_future_complete(self, self.future)  # 循环等待直到返回
        return self.future.result()  # 返回结果


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

    if len(sys.argv) != 3:  # 确保参数个数正确
        print("Usage: python script_name.py <int_a> <int_b>")
        return
    num_a = int(sys.argv[1])
    num_b = int(sys.argv[2])

    service_demo_client = ServiceDemoClient()  # 客户端实例化
    response = service_demo_client.send_request(num_a, num_b)  # 客户端发送请求
    # 通过ros2 interface show example_interfaces/srv/AddTwoInts 查看这个消息类型的结构
    service_demo_client.get_logger().info(
        "Result of add_two_ints: for %d + %d = %d" % (num_a, num_b, response.sum)
    )

    service_demo_client.destroy_node()  # 销毁节点
    rclpy.shutdown()  # 关闭ROS


if __name__ == "__main__":
    main()
AI 代码解读

此处只简单介绍了service的一种发送请求的办法,要获取更多信息请查阅rclpy文档的serviceAPI

3.添加入口点

接下来,你需要编辑 setup.py 文件,以定义功能包的入口点(entry point)。入口点是功能包中的可执行程序,它们可以在 ROS 2 中运行。在 setup.py 文件中,你需要添加入口点的定义。
在 entry_points 部分添加以下命令:

"client = ros2_learning.service_demo_client:main",
AI 代码解读

在这里插入图片描述

4.编译工作空间

在最后,编译工作空间,相关命令在之后的课程里会讲解,此处不涉及。

# Go to your workspace
cd ~/ros2_workspace
# Build workspace
colcon build --symlink-install
AI 代码解读

测试服务通信机制

先运行服务器节点:

ros2 run ros2_learning server
AI 代码解读

在这里插入图片描述

随后运行客户端节点并键入测试参数:

ros2 run ros2_learning client 2 3
AI 代码解读

在这里插入图片描述

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
目录
打赏
0
3
4
0
31
分享
相关文章
具身智能干货|ROS2理论与实践系列(二):ROS2通信机制核心
机器人是一种高度复杂的系统性实现,一个完整的机器人应用程序可能由若干功能模块组成,每个功能模块可能又包含若干功能点,在不同功能模块、不同功能点之间需要频繁的进行数据交互。比如以导航中的路径规划模块为例: 路径规划时就需要其他功能模块输入数据,并输出数据以被其他模块调用。 输入的数据有地图服务提供的地图数据、定位模块提供的机器人位姿数据、人机交互模块提供的目标点数据......。 输出的路径信息则被运动控制订阅或是回显在人机交互界面上。 那么这些相对独立的功能模块或功能点之间是如何实现数据交互的呢?在此,我们就需要介绍一下ROS2中的通信机制了。
149 62
具身智能干货|ROS2理论与实践系列(一):ROS2概述与环境搭建
《ROS2理论与实践》系列课程主要由基础篇、核心篇、应用篇、进阶篇以及项目库五部分组成。本阶段为《ROS2理论与实践——核心篇》课程,核心篇课程设计以官方内容为标准,主要介绍ROS2中的通信机制与开发者工具,其中前者是整个ROS2框架中的核心构成,而后者则为开发者能够高效的构建应用程序提供有力支持。本阶段课程目的是帮助大家快速上手ROS2,为后续进阶奠定基础。
102 12
具身智能干货|ROS2理论与实践系列(一):ROS2概述与环境搭建
基于 ROS 的Terraform托管服务轻松部署ChatGLM-6B
文章介绍了如何利用ROS和Terraform模板轻松自动化部署基于GLM架构、优化中文对话的ChatGLM-6B模型至阿里云,提高了部署效率与便捷性,适用于多种应用场景,且模型部署过程详细,彰显了基础设施即代码(IaC)的优势。
基于 ROS 的Terraform托管服务轻松部署ChatGLM-6B
基于 ROS 的Terraform托管服务轻松部署Qwen-7B-Chat
文章介绍了如何利用ROS和Terraform模板轻松自动化部署阿里云的Qwen-7B-Chat大语言模型服务,提高了部署效率与便捷性,是实现云资源和服务快速上线的最佳实践。
基于 ROS 的Terraform托管服务轻松部署Qwen-7B-Chat
【ROS速成】半小时入门机器人ROS系统简明教程之安装测速(二)
半小时入门机器人ROS系统简明教程之安装测速
239 0
|
7月前
|
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
338 1
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
这篇文章是关于ROS2(Robot Operating System 2)中功能包、依赖管理、工作空间配置和编译的教程,涵盖了ROS2工作空间的概念、如何获取和安装功能包的依赖、构建工作空间的步骤,以及如何创建和管理ROS2功能包,包括使用命令行工具对功能包进行操作的方法。
900 0
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
ROS2:从初识到深入,探索机器人操作系统的进化之路
前言 最近开始接触到基于DDS的这个系统,是在稚晖君的机器人项目中了解和认识到。于是便开始自己买书学习起来,感觉挺有意思的,但是只是单纯的看书籍,总会显得枯燥无味,于是自己又开始在网上找了一些视频教程结合书籍一起来看,便让我对ROS系统有了更深的认识和理解。 ROS的发展历程 ROS诞生于2007年的斯坦福大学,这是早期PR2机器人的原型,这个项目很快被一家商业公司Willow Garage看中,类似现在的风险投资一样,他们投了一大笔钱给这群年轻人,PR2机器人在资本的助推下成功诞生。 2010年,随着PR2机器人的发布,其中的软件正式确定了名称,就叫做机器人操作系统,Robot Op
143 14

推荐镜像

更多