当前位置: 首页 > news >正文

【ROS 通信】Services 服务通信

【ROS】Service 服务通信

  • 前言
  • 前置操作
    • 创建一个 tutorial 功能包
    • 定义服务接口
    • 修改 CMakeLists.txt 文件
      • 修改 find_package
      • 修改 add_service_files
      • 修改 generate_messages
      • 修改 catkin_package
      • find_package 和 catkin_package
    • 修改 package.xml 文件
    • 构建
  • 服务通信的 Python 实现
    • 服务端
      • 创建服务端节点 add_server.py
      • 编写服务端代码
      • 添加可执行权限
      • 添加 python 脚本安装规则
      • 构建并测试
    • 客户端
      • 创建客户端节点 add_client.py
      • 编写客户端代码
      • 添加可执行权限
      • 添加 python 脚本安装规则
      • 构建并测试

前言

ROS 的服务通信采用同步的请求-响应模式。

节点角色

  • 服务端 (Server):提供服务并处理请求。
  • 客户端 (Client):发送请求并等待服务端的响应。

工作流程:

  • 客户端向服务端发送请求,并在等待服务端处理后接收响应。

适用场景

  • 服务通信适用于需要明确交互和结果的场景,如查询状态、获取配置或执行特定操作等。

本文通过一个简单的例子来讲解服务通信:
客户端向服务端发送两个整数请求,服务端计算这两个数的和并将结果返回给客户端。


前置操作

创建一个 tutorial 功能包

使用以下指令创建 tutorial 包,并包含常见的依赖项:

catkin_create_pkg tutorial roscpp rospy std_srvs std_msgs

定义服务接口

tutorial 功能包中创建一个 srv 目录,用于存放自定义的服务消息类型。
例如,创建一个 AddTwoInts.srv 文件,用于定义两个整数相加的服务消息。

在该文件中添加以下内容:

int64 a
int64 b
---
int64 sum

这个服务消息文件定义了两个输入参数:ab,以及一个输出参数:sum,表示两个整数相加后的结果。


修改 CMakeLists.txt 文件

修改 find_package

find_package 中添加 message_generation,以便 CMake 在构建时找到这个工具包。

修改后的内容如下:

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  std_srvs
  message_generation
)

在这里插入图片描述

备注
message_generation 是一个工具包,主要用于自动化处理自定义消息类型(如 .msg.srv.action 文件)。
它可以在 CMake 构建时,根据这些消息文件自动生成对应的 C++ 头文件和 Python 模块。这样,你在编写 C++ 或 Python 代码时,就可以直接 #includeimport 这些自动生成的消息文件。
因此,它就像一个代码生成器,自动生成各种编程语言所需的头文件和模块,使得在项目中使用自定义消息和服务更加方便。


修改 add_service_files

  • CMakeLists.txt 文件中添加 add_service_files,告知消息生成器需要转换的服务消息文件。
    CMake 会根据这些文件自动生成对应的 C++ 头文件和 Python 模块。

  • add_service_files 中指定自定义的服务消息类型。
    例如,使用 AddTwoInts.srv 文件作为服务消息,CMake 会自动生成相关代码。

修改后的代码:

add_service_files(
  FILES
  AddTwoInts.srv
)

在这里插入图片描述

通过添加此配置,message_generation 将自动根据 AddTwoInts.srv 文件生成相应的 C++ 头文件和 Python 模块。


修改 generate_messages

  • CMakeLists.txt 文件中添加 generate_messages 函数,调用消息生成器。
    CMake 会自动编译 .srv.msg 文件,并生成 C++ 头文件和 Python 模块。

  • generate_messages 中指定依赖项,告诉生成器哪些消息文件需要依赖。
    例如,如果使用了 std_msgs 中的 bool 类型,就需要将 std_msgs 添加为依赖项。

修改后的代码:

generate_messages(
  DEPENDENCIES
  std_msgs
  std_srvs
)

在这里插入图片描述

通常需要添加 std_msgsstd_srvs 作为依赖项。如有其他依赖,根据实际情况修改。


修改 catkin_package

在 ROS 中进行服务、话题和动作通信时,需要一个消息翻译器,它能够将节点之间交互的数据转换为 ROS 可识别的格式,即字节流。为了确保在运行时能够使用这个翻译器,我们需要在 catkin_package 中添加对其的依赖。

修改后的代码:

catkin_package(
  CATKIN_DEPENDS roscpp rospy std_msgs std_srvs message_runtime
)

在这里插入图片描述

通过添加 message_runtime 依赖,我们确保在运行时能够正确处理消息翻译,保证节点之间的通信能够顺利进行。


find_package 和 catkin_package

这两行代码虽然看起来相似,但有所不同:

  • find_package 用于指定编译时需要的依赖项。它告诉 CMake 在构建过程中需要哪些外部库或工具包。

  • catkin_package 用于声明当前功能包在导出时所需的依赖项。当其他功能包依赖于当前功能包时,它会自动根据 catkin_package 中的声明包含这些依赖项,确保依赖当前功能包的功能包能够正确地使用所需资源。

简而言之,find_package 是编译构建时的依赖声明,而 catkin_package 是用于导出时的依赖声明(声明其他功能包包含当前功能包的时候需要包含的依赖),它确保当其他功能包依赖于当前功能包时,能够自动获取所需的依赖项。


1. find_package 包含 message_generation,但不直接包含 message_runtime,是因为:

  • message_generation 在编译时处理消息文件并生成 C++ 头文件和 Python 模块,同时隐式包含了 message_runtime,负责消息翻译。

  • 因此,当包含 message_generation 时,message_runtime 会自动得到支持,无需额外声明。


  1. catkin_package 中不包含 message_generation,是因为:
  • 其他功能包会自动依赖已生成的 C++ 头文件和 Python 模块,无需重新使用 message_generation

  • 但它们仍需依赖 message_runtime,因为需要在运行时处理消息翻译。因此,必须在 catkin_package 中声明 message_runtime


修改 package.xml 文件

package.xml 中,需要添加以下依赖项:

  • 构建依赖message_generation(用于构建期间生成消息相关代码)

    <build_depend>message_generation</build_depend>
    
  • 运行依赖message_runtime(用于运行期间处理消息通信)

    <exec_depend>message_runtime</exec_depend>
    

在这里插入图片描述

package.xml 相当于功能包的“说明书”,用于声明构建和运行时所需的依赖。它本身不参与构建过程,但构建系统会读取其中的依赖信息,确保功能包可以正常编译和运行。


构建

使用 catkin_make 构建整个工作空间,服务消息生成成功时将输出类似如下信息:
在这里插入图片描述


构建成功后,工作空间根目录下的 devel/includedevel/lib/pythonX/site-packages 目录中会生成由 message_generation 自动生成的 C++ 头文件和 Python 模块,效果如下图所示:
在这里插入图片描述
在这里插入图片描述

服务通信的 Python 实现

服务端

创建服务端节点 add_server.py

在这里插入图片描述

编写服务端代码

#! /usr/bin/env python2
# -*- coding: utf-8 -*-

import rospy # 导入ROS Python库

# 从 tutorial 功能包的 srv 服务通信的子模块中,导入AddTwoInts、AddTwoIntsResponse、AddTwoIntsRequest 这三个类
# 该 srv 子模块位于 lby_ws/devel/lib/python2.7/dist-packages/tutorial/srv/_AddTwoInts.py中,是catkin_make构建时,message_generation自动生成的 python 模块
from tutorial.srv import AddTwoInts, AddTwoIntsResponse, AddTwoIntsRequest

# 从 tutorial 功能包的 srv 服务通信的子模块中,导入所有类
# from tutorial.srv import *

# 服务请求的回调函数
def add_server_callback(req):
    sum = req.a + req.b
    rospy.loginfo("收到请求: %d + %d = %d" % (req.a, req.b, sum))
    # 将结果传入类 AddTwoIntsResponse() 中,创造一个服务通信的响应的实例并返回
    # 返回服务消息的响应的实例,返还给客户端
    return AddTwoIntsResponse(sum)

def add_server():
    # 初始化ROS节点
    rospy.init_node('add_server')
    
    # 创建服务端
    # 给 rospy.Service 这个类传入三个参数创建一个 服务端实例server
    # 参数1:服务端实例s的名称
    # 参数2:服务消息的类型(.srv文件)
    # 参数3:服务端接受到请求后调用的回调函数
    server = rospy.Service('add_server', AddTwoInts, add_server_callback)
    
    rospy.loginfo("准备好进行加法运算。")
    
    # 保持节点运行
    rospy.spin()

if __name__ == "__main__":
    try:
        add_server()
    except rospy.ROSInterruptException:
        pass

添加可执行权限

chmod +x ~/lby_ws/src/tutorial/scripts/add_server.py

添加 python 脚本安装规则

CMakeLists.txt 中添加以下内容(确保放在 catkin_install_python(PROGRAMS 上):

catkin_install_python(PROGRAMS
  scripts/add_server.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

在这里插入图片描述

构建并测试

# 编译工作空间
cd ~/lby_ws
catkin_make

# 启动服务端
rosrun tutorial add_server.py

# 测试服务
# rosservice 是 ROS 提供的命令行工具,用于与 ROS 的服务通信进行交互
# call 是 rosservice 的子命令,用于 ”发送请求“ 给某个服务
# /add_two_ints 是服务端的名称
# "a: 10 b: 20" 是给服务端发送的请求的参数
rosservice call /add_server "a: 10 b: 20"

测试结果如下图:

在这里插入图片描述


客户端

创建客户端节点 add_client.py

在这里插入图片描述

编写客户端代码

#! /usr/bin/env python2
# -*- coding: utf-8 -*-

import rospy

# 从 tutorial 功能包的 srv 服务通信的子模块中,导入AddTwoInts、AddTwoIntsResponse、AddTwoIntsRequest 这三个类
# 该 srv 子模块位于 lby_ws/devel/lib/python2.7/dist-packages/tutorial/srv/_AddTwoInts.py中,是catkin_make构建时,message_generation自动生成的 python 模块
from tutorial.srv import AddTwoInts, AddTwoIntsResponse, AddTwoIntsRequest

# 从 tutorial 功能包的 srv 服务通信的子模块中,导入所有类
# from tutorial.srv import *


def add_client():
    # 初始化ROS节点
    rospy.init_node('add_client')
    
    # 等待服务可用
    # 参数:等待的服务端的名称(需要与服务端创建服务时使用的名称一致)
    # 防止服务端还没有创建好,客户端就开始调用服务,导致报错
    rospy.wait_for_service('add_server')
    
    try:
        # 创建客户端
        # 给 rospy.ServiceProxy 这个类传入二个参数创建一个 客户端实例client
        # 参数1:客户端实例client的名称
        # 参数2:服务消息的类型(.srv文件)
        client = rospy.ServiceProxy('add_server', AddTwoInts)
        
        # 给AddTwoIntsRequest()类 传入a和b的参数,创建请求消息数据的实例
        req = AddTwoIntsRequest(10, 20)

        # 发送请求并等待响应
        # 方式一:直接传递参数
        # 调用创建的客户端实例client,传入两个参数作为服务消息的请求的参数
        # 返回值是服务端返回的响应消息的实例 AddTwoIntsResponse
        # resp1 = client(10, 20)
        # rospy.loginfo("方式一 - 请求: 10 + 20 = %d" % resp1.sum)
        
        # 方式二:使用请求对象
        # 调用创建的客户端实例client,直接传入req(服务消息的AddTwoIntsRequest请求消息的实例)作为服务消息的请求的参数
        # 返回值是服务端的中断回调函数最后 return返回的响应消息的实例 AddTwoIntsResponse
        # 就是return AddTwoIntsResponse(sum)
        resp2 = client(req)
        rospy.loginfo("方式二 - 请求: %d + %d = %d" % (req.a, req.b, resp2.sum))
        
    except rospy.ServiceException as e:
        rospy.logerr("服务调用失败: %s" % e)

if __name__ == "__main__":
    try:
        add_client()
    except rospy.ROSInterruptException:
        pass

添加可执行权限

chmod +x ~/lby_ws/src/tutorial/scripts/add_client.py

添加 python 脚本安装规则

CMakeLists.txt 中添加以下内容(确保放在 catkin_install_python(PROGRAMS 上):

catkin_install_python(PROGRAMS
  scripts/add_server.py
  scripts/add_client.py
  DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)

在这里插入图片描述

构建并测试

# 编译工作空间
cd ~/lby_ws
catkin_make

# 启动服务端
rosrun tutorial add_server.py

# 启动客户端
rosrun tutorial add_client.py

测试结果如下图:

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

相关文章:

  • pinia中不定义state和action也能正常使用属性和方法
  • [Effective C++]条款28:避免返回handles指向对象内部成分
  • AI 智能外呼系统的智能体现
  • Python语言的网络编程
  • 大模型FAQ
  • C++-Mongoose(2)-https-server-openssl
  • Java核心技术面试题
  • micro ubuntu 安装教程
  • 【亲测】Linux 使用 Matplotlib 显示中文
  • Solidity入门实战—web3
  • 【Ansible自动化运维】一、初步了解,开启自动化运维之旅
  • STM32定时器完全指南:从基础原理到高级应用 | 零基础入门STM32第九十六步
  • 海外高防服务器延迟优化——跨国业务安全加速的底层逻辑
  • DIY AI ML:K-Means 算法
  • HTML静态网页成品作业(HTML+CSS)——阜阳剪纸介绍设计制作(1个页面)
  • R语言 | 2d概率密度分布图
  • 牛客 226303 【模板】差分
  • SPI通信
  • 重头学java cpu内存硬盘的关系
  • 深度集成学习不均衡样本图像分类
  • 有几家做网站的公司/精准防恶意点击软件
  • 如何为公司建立网站/武汉seo优化服务
  • 前端后端都是网站开发吧/全网络品牌推广
  • 陇西学做网站/湖南网站建站系统哪家好
  • 海南省建设网站/网站建设制作过程
  • 响应式网站建设企业/百度推广app