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树 理论 我们知道二叉搜索树拥有极高的搜索效率,但当二叉搜索树退化成单支时,其查找效率会大幅下降,因此我们需要避免其出现单支的情况,并且尽可能让其接近满二叉树。解…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...