ROS2 Topics和Services

本文主要介绍ROS的Topics概念,如何创建Publisher和Subscriber,通过Topic在ROS程序间通信;介绍ROS的Services概念,如何创建Client和Server并建立通信。
更多内容,访问专栏目录获取实时更新。

ROS Topics

Topics可以被视为一种具名的总线,用于节点间交换数据,通过Topics可以发布和订阅消息,实现单向的流式通信。需要注意的重点包括:

  • 单向流式通信(发布/订阅模式)
  • 匿名通信
  • 每个Topic都有特定的消息格式
  • 可以在ROS节点中通过Python, C++等多种语言实现
  • 一个节点可以拥有多个Topic

Publisher in Python

在ROS2基础编程一文中,我们已经创建了工作空间和工作包,在此基础上,来通过Python实现一个Topic的发布者。
my_py_pkg工作包下创建一个新的文件robot_news_station.py
在这里插入图片描述
robot_news_station.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.msg import String  # do not forget to add package dependencyclass RobotNewsPublisherNode(Node):def __init__(self):super().__init__("robot_news_publisher")self.robot_name = "HiRobot"self.publisher = self.create_publisher(String, "robot_news", 10)self.timer = self.create_timer(1, self.publish_news)self.get_logger().info("Robot News Publisher has been started")def publish_news(self):msg = String()msg.data = "Hi, this is " + str(self.robot_name) + " from the robot news publisher"self.publisher.publish(msg)def main(args=None):rclpy.init(args=args)node = RobotNewsPublisherNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

还需要添加依赖包引用,修改package.xml文件:
在这里插入图片描述

然后装载我们的新节点,修改setup.py:
在这里插入图片描述

之后执行下面的指令就可以启动我们的publisher了:

colcon build --packages-select my_py_pkg --symlink-install
source ~/.bashrc
ros2 run my_py_pkg robot_news_station
ros2 topic echo /robot_news

Subscriber in Python

创建订阅者的方式与创建发布者类似,这里我们添加了一个名为robot_news_subscriber.py的文件:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.msg import String  # do not forget to add package dependencyclass RobotNewsSubscriberNode(Node):def __init__(self):super().__init__("robot_news_subscriber")self.subscriber = self.create_subscription(String, "robot_news", self.subscribe_news_callback, 10)self.get_logger().info("Robot News Subscriber has been started")def subscribe_news_callback(self, msg):self.get_logger().info(msg.data)def main(args=None):rclpy.init(args=args)node = RobotNewsSubscriberNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

不要忘记修改setup.pycolcon build编译。之后同时运行publisher和subscriber就可以看到右侧命令行里的subscriber每1s收到一条来自publisher的信息,并打印:
在这里插入图片描述

使用命令行工具调试Topics

ros2 topic list
ros2 topic info <topic_name>  # 查看所有激活的topic
ros2 topic echo <topic_name>   # 创建一个订阅者监听发布的消息
ros2 interface show <msg_type>  # 显示话题消息的类型
ros2 topic hz <topic_name>  # 获取发布频率
ros2 topic bw <topic_name>  # 获取消息的长度,byte width
ros2 topic pub <topic_name>  <msg_type> <msg_data>  # 发布一个topic
ros2 topic pub -r 10 /robot_news example_interfaces/msg/String "{data: 'hello from robot'}"
ros2 node list
ros2 info <node_name>
ros2 run <pkg_name> <node_name> --ros-args -r __node:=<new_node_name>
ros2 run <pkg_name> <node_name> --ros-args -r __node:=<new_node_name> -r <topic_name>:=<new_topic_name>

Ros Services

前文提到Topics实现的是单向的传输,通过发布/订阅模式建立连接,但用在一些需要请求/回复的分布式系统中就不太合适了。
Services可以帮助我们实现请求/回复的通信模式,一条消息用于请求,一条用于回复,ROS节点以字符串名称提供服务,客户端通过发送请求消息并等待回复来调用服务,从而建立持久性的连接。

Service Server in Python

ros2 interface show example_interfaces/srv

执行上面的指令,你能看到example_interface包里提供了哪些服务,这里我们使用AddTwoInts来演示如何创建一个service server
add_two_ints_server.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoIntsclass AddTwoIntsServerNode(Node):def __init__(self):super().__init__("add_two_ints_server")self.server = self.create_service(AddTwoInts, "add_two_ints", self.callback_add_two_ints)self.get_logger().info("Add Two Ints Server has started")def callback_add_two_ints(self, request, response):response.sum = request.a + request.bself.get_logger().info(str(request.a) + " + " + str(request.b) + " = " + str(response.sum))return responsedef main(args=None):rclpy.init(args=args)node = AddTwoIntsServerNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

编译并运行,通过ros2 service list就能在服务列表里看到我们启动的服务了。
在这里插入图片描述

ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 3, b: 4}"

执行上面的指令就可以在命令行里调用我们创建的service。

Service Client in Python

add_two_ints_client.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoIntsdef main(args=None):rclpy.init(args=args)node = Node("add_two_ints_no_oop")client = node.create_client(AddTwoInts, "add_two_ints")while not client.wait_for_service(1):node.get_logger().warn("Waiting for server Add Two Ints...")request = AddTwoInts.Request()request.a = 3request.b = 8future = client.call_async(request)rclpy.spin_until_future_complete(node, future)try:response = future.result()node.get_logger().info(str(request.a) + " + " + str(request.b) + " = " + str(response.sum))except Exception as e:node.get_logger().error("Service call failed %r" % (e,))rclpy.shutdown()if __name__ == "__main__":main()

使用命令行工具调试Services

ros2 service list
ros2 service type <service_name>
ros2 interface show <service type>
ros2 service call <service_name> <service_type> <value>
ros2 run <pkg_name> <node_name> --ros-args -r <service_name>:=<new_service_name>

ROS Interface

ROS应用之间有三种通信接口:messages, services和actions,ROS2使用IDL(interface definition language)来描述这些接口,使得在不同应用,不同编程语言间进行交互更加简单。例如前文提到的Topic和Service:

Topic:

  • Name:话题名
  • 消息定义:Msg,如example_interfaces/msg/Int64

Service:

  • Name: 服务名
  • 服务定义:Srv,如example_interfaces/srv/AddTwoInts (包含request和response)

创建自定义的Msg

创建一个新的工作包my_robot_interfaces,移除目录下的includesrc文件夹,并新建msg文件夹:
在这里插入图片描述
msg文件夹下新建msg定义文件: HardwareStatus.msg

int64 temperature
string debug_message

更新package.xml,添加:

<build_depend>rosidl_default_generators</build_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}"msg/HardwareStatus.msg"
)ament_export_dependencies(rosidl_default_runtime)
ament_package()

然后编译工作包,就可以在其他工程中使用该Msg定义了。

使用自定义的Msg

my_py_pkg工作包下创建一个新的publisher:hw_status_publisher.py

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from my_robot_interfaces.msg import HardwareStatusclass HardwareStatusPublisherNode(Node):def __init__(self):super().__init__("hardware_status_publisher")self.hw_status_publisher = self.create_publisher(HardwareStatus, "hardware_status", 10)self.timer = self.create_timer(1, self.publish_hw_status)self.get_logger().info("Hardware Status Publisher has been started")def publish_hw_status(self):msg = HardwareStatus()msg.temperature = 45msg.debug_message = "No error"self.hw_status_publisher.publish(msg)def main(args=None):rclpy.init(args=args)node = HardwareStatusPublisherNode()rclpy.spin(node)rclpy.shutdown()if __name__ == "__main__":main()

不要忘记在package.xml中添加对my_robot_interface的依赖,并把新的节点加载到setup.py并编译。运行haredware_status_publisher并监听,可以看到如下的效果:
在这里插入图片描述

创建自定义的Srv

my_robot_interfaces工作包目录下创建srv文件夹,并新建文件ComputerRectangleArea.srv

float64 length
float64 width
---
float64 area

更新CMakeLists.txt
在这里插入图片描述
成功编译了工作包后我们就能够获得自定义的Srv了
在这里插入图片描述

如有错误,欢迎留言或来信指正:hbin6358@163.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/18714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做电商,错过了2020年的抖音!那2024一定要选择视频号小店!

哈喽~我是电商月月 电商老板们集合了&#xff0c;问大家一个问题: 如果能让你回到三四年前&#xff0c;抖音才步入大众视野&#xff0c;这时候让你去做抖音小店&#xff0c;你愿意吗&#xff1f; 我敢相信&#xff01;很多&#xff0c;错过当年抖音红利的商家&#xff0c;一…

Docker HTTPS api V2 Manifest V 2, Schema 2 下的免装docker下载镜像的方法

目录 前言 下载镜像代码 使用方法 原代码中无法适配 Schema 2 的原因浅析 如何解决 相对原代码改动的东西 前言 本文提供代码主要是基于 https://github.com/NotGlop/docker-drag 提供的代码修改的。链接中提供的代码应该是是基于HTTPS api V2 Manifest V 2, Schema 1实…

面试必备:应对 “为什么离职” 的万能回答

使用PC端的朋友&#xff0c;请将页面缩小到最小比例&#xff0c;阅读最佳&#xff01; 面试官问到你为什么从上一家公司离职时&#xff0c;你会怎么回答&#xff1f;这个问题我觉得很有意思&#xff0c;也很有必要去探讨一下。 很多专业人士都会建议你&#xff0c;最好不要直接…

C++---迭代器介绍

迭代器的介绍 使用迭代器需要引用头文件,但一般的容器都引用了这个头文件。 这五种迭代器的声明如下: struct output_iterator_tag { };//输出迭代器 struct input_iterator_tag{ };//输入迭代器 struct forward_iterator_tag : public input_iterator_tag {};//向前迭代器 …

基于序列深度学习模型的向量海岸线形状分类方法 2024.05

本文中提出了一个数据驱动的方法来分类的形状矢量海岸线&#xff0c;该方法利用基于序列的深度学习算法对海岸线矢量分段进行建模和分类。具体而言&#xff0c;首先将复杂的海岸线划分为一系列弯曲&#xff0c;并进一步提出了一组不同的特征来描述每个弯曲的形态特征。然后&…

强化学习——学习笔记2

在上一篇文章中对强化学习进行了基本的概述&#xff0c;在此篇文章中将继续深入强化学习的相关知识。 一、什么是DP、MC、TD&#xff1f; 动态规划法&#xff08;DP&#xff09;&#xff1a;动态规划法离不开一个关键词&#xff0c;拆分 &#xff0c;就是把求解的问题分解成若…

gif帧数修改怎么操作?一键掌握GIF帧数修改技巧!

gif帧数修改怎么操作&#xff1f;在数字化信息爆炸的时代&#xff0c;GIF动图因其生动有趣的特性而备受广大网友喜爱。然而&#xff0c;很多时候我们可能会遇到GIF动图帧数过多或过少&#xff0c;导致动画效果不尽如人意的情况。那么&#xff0c;如何对GIF动图的帧数进行修改呢…

探索微软Edge开发者工具:优化前端开发的艺术与科学

探索微软Edge开发者工具&#xff1a;优化前端开发的艺术与科学 引言&#xff1a;Edge开发者工具概览一、基础操作&#xff1a;步入DevTools的大门1.1 启动与界面布局1.2 快速导航与定制 二、元素审查与样式调整2.1 精准元素选取2.2 实时CSS编辑2.3 自动完成与内联文档 三、Java…

YOLOv10最详细全面讲解1- 目标检测-准备自己的数据集(YOLOv5,YOLOv8均适用)

YOLOv10没想到出来的如此之快&#xff0c;作为一名YOLO的爱好者&#xff0c;以YOLOv5和YOLOv8的经验&#xff0c;打算出一套从数据集装备->环境配置->训练->验证->目标追踪全系列教程。请大家多多点赞和收藏&#xff01;&#xff01;&#xff01;YOLOv5和YOLOv8亲测…

Redis中的数据结构与内部编码

本篇文章主要是对 Redis 常见的数据结构进行讲解&#xff0c;同时还对其所对应的不同的内部编码进行讲解。希望本篇文章会对你有所帮助。 文章目录 一、五大数据结构 二、数据结构对应的编码方式 String hash list set zset &#x1f64b;‍♂️ 作者&#xff1a;Ggggggtm &…

js 面试题学习笔记一

1、什么是防抖和节流&#xff1f;有什么区别&#xff1f;如何实现&#xff1f; 防抖&#xff1a;触发高频事件后N秒内函数只会执行一次&#xff0c;如果N秒高频事件再次被触发&#xff0c;则重新计算时间。&#xff08;a时间触发&#xff0c;5秒内执行一次&#xff0c;但是第4…

10G UDP协议栈 (9)UDP模块

目录 一、UDP协议简单介绍 二、UDP功能实现 三、仿真 一、UDP协议简单介绍 UDP协议和TCP协议同位于传输层&#xff0c;介于网络层&#xff08;IP&#xff09;和应用层之间&#xff1a;UDP数据部分为应用层报文&#xff0c;而UDP报文在IP中承载。 UDP 报文格式相对于简单&am…

电脑出现:excel词典(xllex.dll)文件丢失或损坏的错误提示怎么办?有效的将丢失的xllex.dll修复

当遇到 Excel 提示“词典 (xllex.dll) 文件丢失或损坏”的问题时&#xff0c;通常意味着该动态链接库文件&#xff08;Dynamic Link Library&#xff0c;DLL&#xff09;&#xff0c;它与拼写检查功能相关联的&#xff0c;无法被正确找到或者合适地使用。那么有什么办法可以解决…

LLVM技术在GaussDB等数据库中的应用

目录 LLVM和数据库 LLVM适用场景 LLVM对所有类型的SQL都会有收益吗&#xff1f; LLVM在OLTP中就一定没有收益吗&#xff1f; GaussDB中的LLVM 1. LLVM在华为应用于数据库的时间线 2. GaussDB LLVM实现简析 3. GaussDB LLVM支持加速的场景 支持LLVM的表达式&#xff1a…

vue项目出现多次ElMessage

问题&#xff1a; 解决方法&#xff1a; let message null if (message null) { message ElMessage.error(“登录过期,请重新登录”); } 最终效果&#xff1a;只出现一个弹框

Orange AIpro Color triangle帧率测试

OpenGL概述 OpenGL ES是KHRNOS Group推出的嵌入式加速3D图像标准&#xff0c;它是嵌入式平台上的专业图形程序接口&#xff0c;它是OpenGL的一个子集&#xff0c;旨在提供高效、轻量级的图形渲染功能。现推出的最新版本是OpenGL ES 3.2。OpenGL和OpenCV OpenCL不同&#xff0c;…

实操专区-第15周-课堂练习专区-漏斗图与金字塔图

实操专区-第15周-课堂练习专区-漏斗图 下载安装ECharts&#xff0c;完成如下样式图形。 代码和截图上传 基本要求&#xff1a;下图3选1&#xff0c;完成代码和截图 完成 3.1.3.16 漏斗图中的任务点 基本要求&#xff1a;2个选一个完成&#xff0c;多做1个加2分。 请用班级学号姓…

【Java EE】网络原理——HTTP请求

目录 1.认识URL 2.认识“方法&#xff08;method&#xff09;” 2.1GET方法 2.1.1使用Fiddler观察GET请求 2.1.2 GET请求的特点 2.2 POST方法 2.2.1 使用FIddler观察POST方法 2.2.2 POST请求的特点 3.认识请求“报头”&#xff08;header&#xff09; 3.1 Host 3.2 C…

Spring MVC 工作流程源码分析

前言&#xff1a; 我们知道 Spring MVC 的核心是前端控制器 DispatcherServlet&#xff0c;客户端所有的请求都会交给 DispatcherServlet 来处理&#xff0c;本篇我我们来分析 Spring MVC 处理客户端请求的流程&#xff0c;也就是工作流程。 Sping MVC 只是储备传送门&#x…

Java整合EasyExcel实战——3(上下列相同合并单元格策略)

参考&#xff1a;https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06https://juejin.cn/post/7322156759443095561?searchId202405262043517631094B7CCB463FDA06 准备条件 依赖 <dependency><groupId>com.alibaba</gr…