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…

【QED】血压高的天依

文章目录 题目测试样例 思路代码 题目 题目链接&#x1f517; 天依最近迷上了《Battlefield1》&#xff0c;游戏中每种武器都有不同的攻击伤害值。天依跟敌人对枪&#xff0c;经常在被敌人击杀后发现自己击杀了敌人99滴血&#xff0c;因此血压常常升高。为了降低天依的血压&am…

后台管理系统和前台页面的关联

一、项目bug 1、多人开发的项目冲突 2、相关框架的的运用 3、后台数据的处理 4、antd框架日期框的回显 5、上传图片的回显 6、请求的端口号不一致&#xff0c;需要做前端反向代理 二、项目用到的技术栈 reactts来进行开发后台后台用到的工具则是vite这一去轻量化工具去…

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

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

如何使用SFC和DISM命令修复损坏的Windows系统文件?这有详细步骤

前言 Windows内置的系统文件检查器工具可以扫描Windows系统文件是否损坏或任何其他更改。如果文件已被修改,它将自动用正确的版本替换该文件。以下是如何使用它。 何时应该运行SFC或DISM 如果Windows出现蓝屏或其他崩溃,应用程序出现故障,或者某些Windows功能无法正常工作…

HBase常用命令

简介&#xff1a; HBase Shell 是一种操作HBase的交互模式&#xff0c;支持完整的HBase命令集。 hbase shell # 打开Hbase Shell目录: 命令类别常用命令Generalversion&#xff0c;status&#xff0c;whoami&#xff0c;helpDDLalter&#xff0c;creater&#xff0c;descri…

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; 优点: 该系统中…

【无标题】自用款。。。

#include #include // #include <string.h> // 定义结构体 struct Student { char name[30]; int age; float score; }; // 定义比较函数&#xff0c;用于std::sort对结构体数组进行排序 bool compareStudentsByScore(const Student& a, const Student& b) {…

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

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

JavaAPI(含面试大厂题含源码)

在Java编程中&#xff0c;API&#xff08;应用程序编程接口&#xff09;是一套常用于执行特定任务或与系统交互的预定义函数和协议集合。Java标准库&#xff08;也称为Java API&#xff09;提供了广泛的功能&#xff0c;包括集合操作、文件处理、网络编程等&#xff0c;这些都是…

计算机网络的功能和特点

<计算机网络的功能> 1、数据通信 这是最基本的功能。用来传送各种类型的信息&#xff0c;包括文字信件、新闻消息、资讯信息、图片资料、声音、视频流等各种多媒体信息。 2、资源共享 资源是指网络中所有的软件、硬件和数据&#xff0c;共享则是指网络中的用户能够部…

高级Redis应用进阶 一站式Redis解决方案

源代码在https://github.com/629y/food-social-contact-parent Redis-1 Redis Redis-2 Redis基础数据类型与基本使用 Redis-3 Redis高阶类型与高级应用 Redis-4 Redis数据持久化 Redis-5 主从复制和读写分离 Redis-6 哨兵监控 Redis-7 集群搭建 Redis-8 集群高可用

【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;可以从结果集中去除重复的行…

他山之石可以攻玉

《赫畅&#xff5c;我42岁&#xff0c;从25亿到退网5年后的再次归来》 虽然行业不同&#xff0c;但是很多基本原理都是相通的。 1、不能什么都自己干。平台这么大&#xff0c;应用这么多&#xff0c;自己干不可能&#xff0c;多半也干不好。要尽可能多的形成统一战线&#xf…

Mac屏幕录制编辑软件

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

蓝桥杯day3刷题日记--P9240 冶炼金属

P9240 [蓝桥杯 2023 省 B] 冶炼金属 经典二分&#xff0c;先在第一组中找到最小值&#xff0c;在利用最小值限制范围寻找最大值 #include <iostream> #include <algorithm> using namespace std; int n,kk; int m[10001],num[10001]; int maxs,mins;bool check1…

在Spring Boot中使用Validation进行表单验证

在开发Web应用程序时&#xff0c;表单验证是确保用户提供的数据符合预期格式和规则的重要步骤之一。Spring Boot提供了强大的支持来简化表单验证的实现&#xff0c;其中包括了Validation框架的集成。本文将介绍如何在Spring Boot应用程序中集成Validation&#xff0c;并展示如何…

Python每日三道经典面试题(十二)

1.Python中的函数是什么&#xff1f; 在Python中&#xff0c;函数是一个组织好的、可重复使用的代码块&#xff0c;用于执行一个特定的任务。函数提供了代码模块化和代码复用的能力。你可以将程序划分为多个独立的、功能性的小块&#xff1b;当你需要执行某个任务时&#xff0…