ROS2从入门到精通1-1:详解ROS2话题通信机制与自定义消息

目录

  • 0 专栏介绍
  • 1 话题通信模型
  • 2 话题模型实现(C++)
  • 3 话题模型实现(Python)
  • 4 自定义消息

0 专栏介绍

本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。

🚀详情:《ROS2从入门到精通》


1 话题通信模型

话题是一种单向通信通道,数据或信息以定义的格式传递其中。机器人组件可以订阅主题以接收信息,或者发布信息到主题以与其他组件分享。其中发布信息的节点称为发布者,接受信息的节点称为订阅者

在这里插入图片描述

举个例子,想象一个移动机器人,其中有一个负责读取传感器数据的组件,另一个负责控制电机。传感器组件可以在名为sensor_readings的话题中发布传感器读数信息。同时,控制组件可以订阅此话题以接收该信息并用于控制电机。

在 ROS 2 中,话题由中间件管理以确保消息可靠高效地传输。话题中的消息可以是任何可序列化的数据类型,例如整数、浮点数、字符串、矩阵等。

ROS 2 中的话题具有多对多通信的灵活性和可扩展性。例如,可以有多个组件订阅同一话题,或者多个组件发布数据到同一主题。此外,可以使用线程来连接单个机器人内部的组件,或者在网络中连接不同机器人之间的组件。

在这里插入图片描述

2 话题模型实现(C++)

实验目标:发布者发布控制消息到/turtle1/cmd_vel,控制乌龟其做圆周运动;订阅者订阅/turtle1/cmd_vel,在终端显示乌龟实时的位置坐标。

  • 发布者

    class PublisherNode : public rclcpp::Node
    {public:PublisherNode() : Node("lab_topic_pub") {publisher_ = create_publisher<geometry_msgs::msg::Twist>("/turtle1/cmd_vel", 10); }void publish(geometry_msgs::msg::Twist msg) {publisher_->publish(msg);}private:rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr publisher_;
    };int main(int argc, char * argv[])                      
    {rclcpp::init(argc, argv); auto node = std::make_shared<PublisherNode>();rclcpp::Rate loop_rate(10);while(rclcpp::ok()) {auto msg = geometry_msgs::msg::Twist();msg.linear.x = 0.5;msg.angular.z = 0.2;node->publish(msg);RCLCPP_INFO(node->get_logger(), "Publishing: x: %.2f, z: %.2f", msg.linear.x, msg.angular.z);loop_rate.sleep();}   rclcpp::shutdown();                                return 0;
    }
    
  • 订阅者(订阅的话题存在消息即触发回调函数)

    class SubscriberNode : public rclcpp::Node
    {public:SubscriberNode() : Node("lab_topic_sub"){subscriber_ = create_subscription<geometry_msgs::msg::Twist>(       "/turtle1/cmd_vel", 10, std::bind(&SubscriberNode::OnPoseCallback, this, _1));}private:void OnPoseCallback(const geometry_msgs::msg::Twist & msg) const{RCLCPP_INFO(get_logger(), "Publishing: x: %.2f, z: %.2f", msg.linear.x, msg.angular.z);}rclcpp::Subscription<geometry_msgs::msg::Twist>::SharedPtr subscriber_; 
    };int main(int argc, char * argv[])                         
    {rclcpp::init(argc, argv);                 rclcpp::spin(std::make_shared<SubscriberNode>());     rclcpp::shutdown();                                  return 0;
    }
    

话题通信的效果如下所示:

在这里插入图片描述

计算图可视化为:

在这里插入图片描述

3 话题模型实现(Python)

实验目标:发布者发布控制消息到/turtle1/cmd_vel,控制乌龟其做圆周运动;订阅者订阅/turtle1/cmd_vel,在终端显示乌龟实时的位置坐标。

  • 发布者
    class PublisherNode(Node):def __init__(self, name):super().__init__(name) self.publisher_ = self.create_publisher(Twist, '/turtle1/cmd_vel', 10) def publish(self, msg: Twist):self.publisher_.publish(msg)
    
  • 订阅者
    class SubscriberNode(Node):def __init__(self, name):super().__init__(name)self.subscirber_ = self.create_subscription(Twist, '/turtle1/cmd_vel', self.OnPoseCallback, 10) def OnPoseCallback(self, msg):self.get_logger().info(f"Publishing: x: {msg.linear.x:.2f}, z: {msg.angular.z:.2f}")def main(args=None):                             rclpy.init(args=args)                        node = SubscriberNode("lab_topic_sub")rclpy.spin(node)                                        node.destroy_node()                                     rclpy.shutdown()   
    

话题通信的效果如下所示:

在这里插入图片描述

4 自定义消息

ROS2系统通过std_msgs封装了一些常用的原生数据类型,比如StringInt32Int64等,对于一些复杂数据应用场景,往往需要在std_msgs或其他消息库的基础上继续封装更高级的数据类型

自定义消息的通用流程如下:

  • 功能包下新建msg文件夹,在其中添加自定义消息xxx.msg
  • 功能包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.msg"DEPENDENCIES xxx_msgs
    )ament_export_dependencies(rosidl_default_runtime)
    
  • 编译自定义消息,在install/<pkg_name>/include中生成由xxx.msg编译的C++可识别的xxx.hpp头文件
  • 引入xxx.hpp即可调用自定义消息

下面给出一个实例:

添加如下自定义消息,并按上面步骤配置依赖

# Person.msg
string name
string gender
uint8 agegeometry_msgs/Point positionfloat64 xfloat64 yfloat64 z

定义一个发布者、一个订阅者测试自定义消息

  • 发布者
    // 初始化名为personPub的ROS节点, 该节点应在CMakeLists.txt中被构建为可执行文件
    ros::init(argc, argv, "personPub");
    // 创建节点句柄
    ros::NodeHandle pubNode;
    // 创建发布者, 该发布者属于pubNode节点, 发布话题为"/person/info",
    // 消息类型为"msgtest::Person", 发布队列长度为10
    ros::Publisher pub = pubNode.advertise<msg_lab::Person>("/person/info", 10);
    // 设置发布频率
    ros::Rate loopRate(10);
    while(ros::ok())
    {// 设置消息msg_lab::Person msg;msg.name = "winter";msg.gender = "man";msg.age = 20;msg.position.x = 10;msg.position.y = 20;msg.position.z = 30;// 发布消息pub.publish(msg);ROS_INFO("Publish Person Info[name: %s gender: %s age: %d pos: x-%.2f y-%.2f z-%.2f]", msg.name.c_str(), msg.gender.c_str(), msg.age, msg.position.x, msg.position.y, msg.position.z);// 按循环频率延时loopRate.sleep();
    }
    
  • 订阅者
    void personInfoCallBack(const msg_lab::Person::ConstPtr &msg)
    {ROS_INFO("Subscribe Person Info[name: %s gender: %s age: %d pos: x-%.2f y-%.2f z-%.2f]", msg->name.c_str(), msg->gender.c_str(), msg->age, msg->position.x, msg->position.y, msg->position.z);
    }int main(int argc, char** argv)
    {// 初始化名为personSub的ROS节点, 该节点应在CMakeLists.txt中被构建为可执行文件ros::init(argc, argv, "personSub");// 创建节点句柄ros::NodeHandle subNode;// 创建订阅者, 该订阅者属于subNode节点, 订阅话题为"/person/info",// 订阅队列长度为10, 收到订阅消息后出发回调函数personInfoCallBackros::Subscriber sub = subNode.subscribe("/person/info", 10, personInfoCallBack);// 循环等待回调函数ros::spin();return 0;
    }
    

实测效果如下:

在这里插入图片描述

完整代码通过下方博主名片联系获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

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

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

相关文章

正则表达式与re模块

目录 正则表达式 简介 语法&#xff1a; 常用元字符&#xff1a; 量词: 贪婪匹配和惰性匹配&#xff1a; re模块 简介&#xff1a; 常用的几个模块&#xff1a; 1.findall 2.search 3.finditer 4.compile 案例展示&#xff1a; 需求&#xff1a; 思路分析&#…

code摘录日记[矩阵变元素,变列向量,3D表面图,table行列设置] Matlab

矩阵变元素&#xff0c;变列向量 W1(Z1 < Z2) nan; % Z1,Z2 all matrix,Only plot points where Z1 > Z2;Z1 < Z2位置值填为NaNx x(:); % Now x is a 30-by-1 vector; matrix变列vector技巧3D表面图 hand figure; % Handle to the figure, for more plotting later…

彻底学会系列:一、机器学习之梯度下降(1)

1 梯度下降概念 1.1 概念 梯度下降是一种优化算法&#xff0c;用于最小化一个函数的值&#xff0c;特别是用于训练机器学习模型中的参数&#xff0c;其基本思想是通过不断迭代调整参数的值&#xff0c;使得函数值沿着梯度的反方向逐渐减小&#xff0c;直至达到局部或全局最小…

python网络编程:通过socket实现TCP客户端和服务端

目录 写在开头 socket服务端&#xff08;基础&#xff09; socket客户端&#xff08;基础&#xff09; 服务端实现&#xff08;可连接多个客户端&#xff09; 客户端实现 数据收发效果 写在开头 近期可能会用python实现一些网络安全工具&#xff0c;涉及到许多关于网络…

供电系统分类详解

一、供电系统分类 电力供电系统一般有5种供电模式&#xff0c;常用的有&#xff1a;IT系统&#xff0c;TT系统&#xff0c;TN系统&#xff0c;其中TN系统又可以分为TN-C&#xff0c;TN-S&#xff0c;TN-C-S。 1、TN-C系统&#xff08;三相四线制&#xff09; 优点: 该系统中…

Hadoop大数据应用:NFS网关 连接 HDFS集群

目录 一、实验 1.环境 2.NFS网关 连接 HDFS集群 3. NFS客户端挂载HDFS文件系统 二、问题 1.关闭服务报错 2.rsync 同步报错 3. mount挂载有哪些参数 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 主机架构软件版本IP备注hadoop NameNode &#xff08;…

【Mysql基础】查询01-去重、连接字符、模糊查询、通配符、检索表的结构信息

这里写目录标题 1 去重 distinct2 连接字符 concat(str1,str2,...)3 模糊查询3.1 like 包含3.2 通配符3.3 between and3.4 in3.5 is null 4 安全等于 <>5 检索表的结构信息 desc6 课后练习 1 去重 distinct 使用 DISTINCT 关键字&#xff0c;可以从结果集中去除重复的行…

Mac屏幕录制编辑软件

以下是一些Mac平台上受到推荐和好评的屏幕录制编辑软件&#xff1a; OBS Studio&#xff08;免费且开源&#xff09;&#xff1a; OBS 是一款功能强大的免费屏幕录制工具&#xff0c;不仅限于游戏直播&#xff0c;也适用于各种屏幕录制需求。它允许用户捕获屏幕、摄像头、音频&…

用c++实现装箱问题、数字回转方阵

3.4.1 装箱问题 【问题】有一个工厂制造的产品形状都是长方体&#xff0c;一共有6种型号,每种型号长方体的长和宽分别是11、22、33、44、55、66,高都是h。这些产品使用统一规格的箱子进行包装&#xff0c;箱子的长、宽和高分别是6、6和h。对于每个订单工厂希望用最少的箱子进行…

【蓝屏分析】WHEA_UNCORRECTABLE_ERROR 问题分析与解决

背景信息 电脑名字电脑类型厂商使用时间magicbook14 2020款 R5 4500U笔记本电脑荣耀HONOR3年9个月 内存CPUGPU硬盘焊死在主板上焊死在主板上集显PCIe 4.0 NVMe M.2 固态 软硬件错误源确定 电脑莫名频繁随机蓝屏&#xff0c;由于在软件环境上无迹可寻推测是硬件问题 蓝屏画面…

Windows系统部署hMailServer邮件服务结合内网穿透实现公网收发邮件

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

运动想象 (MI) 迁移学习系列 (9) : 数据对齐(EA)

运动想象迁移学习系列:数据对齐&#xff08;EA&#xff09; 0. 引言1. 迁移学习算法流程2. 欧式对齐算法流程3. 与RA算法进行对比4. 实验结果对比5. 总结欢迎来稿 论文地址&#xff1a;https://ieeexplore.ieee.org/abstract/document/8701679 论文题目&#xff1a;Transfer Le…

数据结构:链式二叉树

对于二叉树而言,如果不是完全二叉树,就不再适合用数组存储了 二叉树结构 typedef struct BinTreeNode {int val;struct BinTreeNode* left;struct BinTreeNode* right; }BTNode; 二叉树的遍历 顺序 访问顺序(n NULL) 1.前序 根,左子树…

软考81-上午题-【面向对象技术3-设计模式】-行为型设计模式01

一、行为型设计模式一览 二、责任链模式 2-1、意图 使多个对象都有机会处理请求&#xff0c;从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链&#xff0c;并沿着这条链传递该请求&#xff0c;直到有一个对象处理它为止。 1-2、结构 1-3、代码实现 1-4、适…

3D产品配置器能为企业的客户带来什么好处?

3D产品配置器能够为企业的客户带来多重好处&#xff0c;提升他们的整体购物体验和满意度。 主要优势分析&#xff1a; 1、 提升购物体验&#xff1a;3D产品配置器通过提供交互式的3D可视化体验&#xff0c;使客户能够从不同角度查看和理解产品&#xff0c;从而提升他们的购物体…

银行信息系统应用架构导论-引用

一级目录二级目录金融标准和参考文档一、银行企业级应用系统架构规划企业级应用系统架构规划《金融科技发展规划&#xff08;2022-2025年&#xff09;&#xff08;2022年1月中国人民银行印发&#xff09;》 《关于银行业保险业数字化转型的指导意见&#xff08;2022年1月中国银…

Python图像处理【23】分布式图像处理

分布式图像处理 0. 前言1. Dask 简介2. 使用 Dask 进行分布式图像处理2.1 将 RGB 图像块转换为灰度图像块2.2 使用分布式 Sobel 滤波器检测图像边缘 小结系列链接 0. 前言 Python 已逐渐成为数据分析/处理领域中的主要语言&#xff0c;这得益于 Python 丰富的第三方库&#xf…

【对顶队列】【中位数贪心】【前缀和】100227. 拾起 K 个 1 需要的最少行动次数

本文涉及知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 对顶队列&#xff08;栈&#xff09; 分类讨论 LeetCode100227. 拾起 K 个 1 需要的最少行动次数 给你一个下标从 0 开始的二进制数组 nums&#xff0c;其长度为 n &#x…

python redis中blpop和lpop的区别

python redis中lpop()方法是获取并删除左边第一个对象。 def lpop(self,name: str,count: Optional[int] None,) -> Union[Awaitable[Union[str, List, None]], Union[str, List, None]]:"""Removes and returns the first elements of the list name.By de…

VR历史建筑漫游介绍|虚拟现实体验店加盟|VR设备购买

VR历史建筑漫游是一种利用虚拟现实技术&#xff0c;让用户可以身临其境地参观和探索历史建筑的体验。通过VR头显和相关设备&#xff0c;用户可以在虚拟环境中自由移动和互动&#xff0c;感受历史建筑的真实氛围和文化内涵。 在VR历史建筑漫游中&#xff0c;您可以选择不同的历史…