ROS2从入门到精通1-2:详解ROS2服务通信机制与自定义服务
目录
- 0 专栏介绍
- 1 服务通信模型
- 2 服务模型实现(C++)
- 3 服务模型实现(Python)
- 4 自定义服务
- 5 话题、服务通信的异同
0 专栏介绍
本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。
🚀详情:《ROS2从入门到精通》
1 服务通信模型
服务是 ROS 图中节点之间的另一种通信方法。服务基于服务器-客户端模型,不同于话题的发布者-订阅者模型。话题允许节点订阅数据流并获取持续更新,而服务只在客户端特别调用时才提供数据。二者更详细的对比请参考第5节


2 服务模型实现(C++)
实验目标:客户端提交请求给
turtlesim功能包的/spawn服务,在界面上生成新的乌龟。
-
服务器
本实验中无需编程,为
turtlesim::Spawn定义的/spwan服务 -
客户端
void OnResultCallBack(rclcpp::Client<turtlesim::srv::Spawn>::SharedFuture result) {auto response = result.get();RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Request service successfully! [turtle id: %s]", response->name.c_str()); }void request() {auto spawn = std::make_shared<turtlesim::srv::Spawn::Request>(); spawn->name = "winter_turtle";spawn->x = 1.0;spawn->y = 1.0;spawn->theta = 1.57;while (!client_->wait_for_service(std::chrono::seconds(1))) { if (!rclcpp::ok()) {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");return;}RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");}auto result = client_->async_send_request(spawn, std::bind(&ClientNode::OnResultCallBack, this, std::placeholders::_1)); }
服务通信的效果如下所示:

3 服务模型实现(Python)
实验目标:客户端提交请求给
turtlesim功能包的/spawn服务,在界面上生成新的乌龟。
-
服务器
本实验中无需编程,为
turtlesim::Spawn定义的/spwan服务 -
客户端
class ClientNode(Node):def __init__(self, name):super().__init__(name)self.client = self.create_client(Spawn, '/spawn') while not self.client.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...') self.request = Spawn.Request()def sendRequest(self):self.request.name = "winter_turtle"self.request.x = 1.0self.request.y = 1.0self.request.theta = 1.57self.future = self.client.call_async(self.request)
服务通信的效果如下所示:

4 自定义服务
自定义服务的通用流程如下:
- 功能包下新建
srv文件夹,在其中添加自定义服务xxx.srv,注意请求和响应数据结构使用---分割- 功能包
package.xml中添加编译依赖与执行依赖<buildtool_depend>rosidl_default_generators</buildtool_depend> <exec_depend>rosidl_default_runtime</exec_depend> <member_of_group>rosidl_interface_packages</member_of_group>- 功能包
CMakeLists.txt中添加编译消息相关依赖find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME}"xxx.srv"DEPENDENCIES xxx_srvs )ament_export_dependencies(rosidl_default_runtime)- 编译自定义消息,在
install/<pkg_name>/include中生成由xxx.srv编译的C++可识别的xxx.hpp头文件- 引入
xxx.hpp即可调用自定义服务
下面给出一个实例
添加如下自定义服务实现一个加法服务,并按上面步骤配置依赖
# client
int32 a
int32 b
---
# server
int32 sum
定义一个服务器、一个客户端,限于篇幅只贴出部分代码,完整代码见文末。
- 服务器
class ServerNode : public rclcpp::Node {public:ServerNode() : Node("lab_srv_server_own") {server_ = create_service<own_srv_lab::srv::Add>("/add_service",std::bind(&ServerNode::OnAddSrvCallBack, this, std::placeholders::_1, std::placeholders::_2)); }private:rclcpp::Service<own_srv_lab::srv::Add>::SharedPtr server_;void OnAddSrvCallBack(const std::shared_ptr<own_srv_lab::srv::Add::Request> request, std::shared_ptr<own_srv_lab::srv::Add::Response> response) {response->sum = request->a + request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %d" " b: %d", request->a, request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%d]", response->sum);} }; - 客户端
ClientNode() : Node("lab_srv_client_own") {client_ = create_client<own_srv_lab::srv::Add>("/add_service"); }void request(int a, int b) {auto add_srv = std::make_shared<own_srv_lab::srv::Add::Request>();add_srv->a = a; add_srv->b = b;while (!client_->wait_for_service(std::chrono::seconds(1))) { if (!rclcpp::ok()) {RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");return;}RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");}auto result = client_->async_send_request(add_srv, std::bind(&ClientNode::OnResultCallBack, this, std::placeholders::_1)); }
服务通信效果如下所示:

5 话题、服务通信的异同
| 对比 | 话题 | 服务 |
|---|---|---|
| 通信模式 | 发布-订阅 | 请求-响应 |
| 同步性 | 异步 | 同步 |
| 缓冲区 | 有 | 无 |
| 实时性 | 弱 | 强 |
| 节点关系 | 多对多 | 一对多(1个server对应一个服务) |
| 通信格式 | .msg | .srv |
| 使用场景 | 连续高频的数据传输,例如激光雷达、里程计传输数据 | 偶尔调用的功能,例如图像识别 |
完整代码通过下方博主名片联系获取
🔥 更多精彩专栏:
- 《ROS从入门到精通》
- 《Pytorch深度学习实战》
- 《机器学习强基计划》
- 《运动规划实战精讲》
- …
相关文章:
ROS2从入门到精通1-2:详解ROS2服务通信机制与自定义服务
目录 0 专栏介绍1 服务通信模型2 服务模型实现(C)3 服务模型实现(Python)4 自定义服务5 话题、服务通信的异同 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。…...
vue两个特性和什么是MVVM
一、什么是vue 1.构建用户界面 用vue往html页面中填充数据,非常的方便 2.框架 框架是一套线成的解决方案 vue的指令、组件(是对ui结构的复用)、路由、vuex 二、vue的特性 1.数据驱动视图 2.双向数据绑定 1.数据驱动视图 数据的变化会驱动…...
CAD Plant3D 2023 下载地址及安装教程
CAD Plant3D是一款专业的三维工厂设计软件,用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一,专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能,帮助…...
集成电路企业tapeout,如何保证机台数据准确、完整、高效地采集?
Tapeout即流片,集成电路行业中将CDS最终版电路图提交给半导体制造厂商进行物理生产的过程。在芯片设计与制造的流程中,Tapeout是非常重要的阶段,包括了布局(Layout)、连线(Routing)、分析&#…...
Nginx三大常用功能“反向代理,负载均衡,动静分离”
注意:以下案例在Windows系统计算机作为宿主机,Linux CentOS 作为虚拟机的环境中实现 一,Nginx配置实例-反向代理 1.反向代理 案例一 实现效果:使用nginx反向代理,访问 www.123.com 直接跳转到127.0.0.1:8080 准备工…...
类方法介绍、使用细节
...
Java SpringBoot中优雅地判断一个对象是否为空
在Java中,可以使用以下方法优雅地判断一个对象是否为空: 使用Objects.isNull()方法判断对象是否为空: import java.util.Objects;if (Objects.isNull(obj)) {// obj为空的处理逻辑 }使用Optional类优雅地处理可能为空的对象: impo…...
算法——矩阵:对于边界元素的处理
. - 力扣(LeetCode) 题目简述:扫雷,点击一个格子,返回整个地图的下一个状态。 对于边界元素,可以设置两个数组,index_row,index_col,遍历到一个格子需要搜索其周围格子…...
Git分支提交时自动大写 fatal: the remote end hung up unexpectedly
先说结论: 进入 .git/refs/heads目录,会看到Feature文件夹,重命名为feature即可。 表现: 通过终端命令创建的分支 git checkout -b feature/name 使用git push后自动变成了Feature/name 并且有时候在本地创建feature/1234567…...
隐私计算实训营第七讲-隐语SCQL的架构详细拆解
隐私计算实训营第七讲-隐语SCQL的架构详细拆解 文章目录 隐私计算实训营第七讲-隐语SCQL的架构详细拆解1.SCQL Overview1.1 多方数据分析场景1.2 多方数据分析技术路线1.2.1 TEE SQL方案1.2.2 MPC SQL方案 1.3 Secure Collaborative Query Language(SCQL)1.3.1 SCQL 系统组件1.…...
Android JNI开发定义全局变量
要在 C 文件中设置一个 string 类型的全局变量,让其他 C 文件都可以访问,并且可以通过 JNI 方法修改这个变量,可以按照以下步骤进行操作 定义全局变量: 在一个头文件(比如 common.h)中定义一个全局的 strin…...
docker容器部署gitlab的runner的shell模式注册下job中无法使用docker指令
引言 现需通过gitlab-runner来构建jar部署的镜像,发现在job中无法使用docker指令,解决的过程中出现一系列异常,在此做个问题解决的记录。 内容 通过docker-compose部署 name: java-env services:env-gitlab-runner:restart: alwaysimage: env/gitlab-runner-java:latest…...
【SpringCloud】Zuul网关中心 代码详细介绍
Zuul是Spring Cloud中的一个API网关组件,它负责处理服务路由、监控、弹性、安全等API网关的核心功能。Zuul在Spring Cloud Netflix套件中是一个重要的组件,但需要注意的是,随着Spring Cloud的不断发展,Zuul已经被Spring Cloud Gat…...
Delphi D12中实现安卓中文语音合成(中文朗读)不用第三方控件
Delphi开发一个可以朗读中文的APP就非常的简单。 本文给大家介绍使用Delphi开发基于安卓原生的TTS(中文语音合成),将文字转语音实现中文的朗读。APP运行后,需要手机上已安装语音引擎。如果您手机上已安装并设置了语音引擎…...
设计模式 - Provider 模式
在某些情况下,我们希望为应用程序中的许多(如果不是全部)组件提供数据。尽管我们可以使用 props 将数据传递给组件,但如果应用程序中的几乎所有组件都需要访问 prop 的值,这可能很难做到。 我们经常遇到所谓的属性钻探…...
R语言颜色细分
1.如何对R语言中两种颜色之间进行细分 2.代码: x <- colorRampPalette(c("#FC8D62","#FDEAE6"))(12) #打印向量值 # 按字典顺序排序颜色值 x_sorted <- sort(x,decreasing TRUE)# 打印排序后的颜色值 print(x_sorted)#展示颜色 scales:…...
面向返回编程ROP问题及挑战
像我们描述的执行权限等功能已经使执行任意代码变得越来越困难。这意味着攻击者使用其他方法,比如面向返回编程(ROP)。ROP利用了许多现代系统中软件堆栈的规模。攻击者分析系统中的软件,寻找小工具(gadgets)…...
vscode shadertoy插件,非常方便的glsl着色器编写工具
很著名的shadertoy网站,集合了非常多大神利用数学写出美妙的shader效果。像shadertoy创始人之一的IQ大神它在这方面有很多的建树。他的利用光线步进和躁声可以创建很多不可思议的3D场景。 vscode有一件shadertoy的插件,安装后可以新建一个*.glsl文件&am…...
网络请求避坑,私有网络请求(Private Network Access)
前言 网络请求,大家肯定熟悉的不能再熟悉,网络请求失败,大家也肯定很熟悉。排查网络请求,也是我们必备的技能,对不,兄弟。 我坦言,最怕两种网络请求失败。 第一种:PC端模拟没有异常…...
AVL树和红黑树
AVL树和红黑树 AVL树理论代码实现 红黑树理论代码实现 AVL树 理论 我们知道二叉搜索树拥有极高的搜索效率,但当二叉搜索树退化成单支时,其查找效率会大幅下降,因此我们需要避免其出现单支的情况,并且尽可能让其接近满二叉树。解…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
