当前位置: 首页 > news >正文

【ROS入门】使用 ROS 话题(Topic)机制实现消息发布与订阅及launch文件的封装

文章结构

  • 任务要求
  • 话题模型
  • 实现步骤
    • 创建工作空间并初始化
    • 创建功能包并添加依赖
    • 创建发布者代码(C++)
    • 创建订阅方代码(C++)
    • 配置CMakeLists.txt
    • 执行
      • 启动roscore
      • 编译
      • 启动发布和订阅节点
    • launch封装
    • 执行

任务要求

使用 ROS 话题(Topic)机制实现消息发布与订阅:

  • 创建一个发布者,每隔 100ms 依次发送斐波拉契数列的数字到话题/fibonacci 中;
  • 创建一个订阅者,订阅该话题,输出订阅结果。如,订阅者依次输出: 1 1 2 3 5 8…
  • 将发布者和订阅者分别封装成launch文件,并能成功实现上述功能

话题模型

在这里插入图片描述

实现步骤

创建工作空间并初始化

$ mkdir -p ROS_Topic_Demo/src
$ cd ROS_Topic_Demo
$ catkin_make

上述命令,首先会创建一个工作空间以及一个 src 子目录,然后再进入工作空间调用 catkin_make命令编译。

创建功能包并添加依赖

在工作空间的src文件夹的目录下打开终端并创建功能包

$ catkin_create_pkg ROS_Topic_Demo roscpp rospy std_msgs

创建发布者代码(C++)

如何实现一个发布者:

  • 初始化ROS节点
  • 向 ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
  • 创建消息数据
  • 按照一定频率循环发布消息

在ROS_Topic_Demo下的src文件夹中创建一个cpp文件:

$ touch topic_demo_pub_c.app
/*创建一个发布者,每隔 100ms 依次发送斐波拉契数列的数字到话题/fibonacci 中*///1.头文件
#include "ros/ros.h"    //万能头
// #include "iostream"
#include "std_msgs/String.h"    //普通文本类型的消息int main(int argc, char *argv[])
{//设置编码(其实这行在这个任务里头没啥用,只不过拿来凑行数而已,应要说的话就是能在打印的时候看的更加清楚而已)。setlocale(LC_ALL,"");//2.初始化ROS节点//ros::init()函数需要查看 argc 和 argv,以便执行命令行提供的任何 ROS 参数和名称重映射。//参数1和参数2用于传参,参数3为节点名称,需要保持名称唯一ros::init(argc,argv,"Publisher");   //3.实例化ROS节点句柄//节点句柄用来管理ROS相关的api资源。调用api时,经常需要使用节点句柄进行调用。ros::NodeHandle n;  //4.实例化发布者对象//advertise()函数用于告诉ROS需要发布的主题名称。这将调用ROS Master节点,该节点将会记录谁在发布,谁在订阅。//调用 advertise() 后,Master节点会通知任何试图订阅该主题名称的节点,并进行配对。//advertise() 返回一个发布者对象,它允许您使用该对象通过调用 publish() 在该主题上发布消息。 //一旦返回的 Publisher 对象的所有副本都被销毁后,该主题将自动销毁。//第一个参数为话题名称,第二个参数为发布消息队列缓冲区的大小。ros::Publisher fibonacci_pub = n.advertise<std_msgs::String>("/fibonacci",100);//5.组织被发布的数据,并编写逻辑发布数据//数据(动态组织)std_msgs::String msg;int num = 1;int temp = 0;//设置循环频率ros::Rate time(10);ros::Rate time1(1);time1.sleep();	//确保发布的代码比订阅的代码晚运行,保证订阅者可以完整的订阅到发布者的信息,防止漏掉一开始的信息。while(ros::ok()){//发布消息std::stringstream ss;ss<<num;msg.data = ss.str();fibonacci_pub.publish(msg);//打印发送的消息ROS_INFO("发送数据:%s",msg.data.c_str());int former = num;num+=temp;temp=former;//设置休眠时间time.sleep();}return 0;
}

创建订阅方代码(C++)

在ROS_Topic_Demo下的src文件夹中创建一个cpp文件:

$ touch topic_demo_sub_c.app
//1.头文件
#include "ros/ros.h"    
#include "std_msgs/String.h" //5.利用回调函数读取数据
void callBack(const std_msgs::String::ConstPtr &msg)
{//通过msg获取并操作订阅到的数据ROS_INFO("订阅到的数:%s",msg->data.c_str());
}int main(int argc, char *argv[])
{setlocale(LC_ALL,"");//2.初始化ROS节点ros::init(argc,argv,"Subscriber");//3.实例化ROS节点句柄ros::NodeHandle n;//4.实例化发布者对象ros::Subscriber fibonacci_sub = n.subscribe<std_msgs::String>("/fibonacci",100,callBack);//6.设置循环调用回调函数ros::spin();    //循环读取接收的数据,并调用回调函数处理return 0;
}

配置CMakeLists.txt

add_executable(topic_demo_pub_c src/topic_demo_pub_c.cpp)
add_executable(topic_demo_sub_c src/topic_demo_sub_c.cpp)target_link_libraries(topic_demo_pub_c${catkin_LIBRARIES}
)target_link_libraries(topic_demo_sub_c${catkin_LIBRARIES}
)

位置如图所示:

在这里插入图片描述

执行

启动roscore

$ roscore

在这里插入图片描述

编译

$ catkin_make

在这里插入图片描述

启动发布和订阅节点

$ source ./devel/setup.bash
$ rosrun rosrun topic_demo topic_demo_sub_c

再开一个终端

$ source ./devel/setup.bash
$ rosrun rosrun topic_demo topic_demo_pub_c

效果如下:

在这里插入图片描述

launch封装

在功能包添加 launch 文件夹,并添加 launch 文件

在这里插入图片描述

<launch><node pkg="topic_demo" type="topic_demo_pub_c" name="Subscriber" output="screen"/><node pkg="topic_demo" type="topic_demo_sub_c" name="Publisher" output="screen"/>
</launch>
  • node: 包含的某个节点
  • pkg: 功能包
  • type: 被运行的节点文件
  • name: 为节点命名
  • output: 设置日志的输出目标

执行

$ roslaunch topic_demo topic_demo_launch.launch

在这里插入图片描述

相关文章:

【ROS入门】使用 ROS 话题(Topic)机制实现消息发布与订阅及launch文件的封装

文章结构 任务要求话题模型实现步骤创建工作空间并初始化创建功能包并添加依赖创建发布者代码&#xff08;C&#xff09;创建订阅方代码&#xff08;C&#xff09;配置CMakeLists.txt执行启动roscore编译启动发布和订阅节点 launch封装执行 任务要求 使用 ROS 话题(Topic)机制…...

【企业级SpringBoot单体项目模板 】——Mybatis-plus自动代码生成

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;SpringBoot项目模版、企业级、模版☀️每日 一言&#xff1a;我们之所以这样认为&#xff0c;是因为他们这样说。他们之所以那样说&#xff0c;是因为他们想让我们那样认为。所以实践才是检验真理…...

怒刷LeetCode的第14天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 方法二&#xff1a;栈 方法三&#xff1a;双指针 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;二分查找 方法二&#xff1a;线性扫描 方法三&#xff1a;递归 第三题 题目来源 …...

c语言 static

1、静态局部变量在程序加载时初始化&#xff0c;静态局部变量的初始值写入到了data段&#xff1a; 如下代码test_symbol.c int f() {static int x 0;return x; }int g() {static int x 9;return x; }使用命令gcc -c test_symbol.c -o test_symbol 编译 使用命令 readelf -a …...

java基础3

输入一个班学生的成绩&#xff0c;先显示所有及格的成绩&#xff0c;再显示所有不及格的成绩&#xff0c;最后显示及格人数和不及格人数 import java.util.Scanner; public class Hello{public static void main(String [] args) {int SIZE5;double grade[] new double[SIZE]…...

LeetCode 1194.锦标赛优胜者

数据准备 Create table If Not Exists Players (player_id int, group_id int); Create table If Not Exists Matches (match_id int, first_player int, second_player int, first_score int, second_score int); Truncate table Players; insert into Players (player_id, g…...

多旋翼无人机组合导航系统-多源信息融合算法(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

如何用ArkUI实现一个加入购物车效果?

关键词&#xff1a;ArkUI的动效能力&#xff0c;动效开发&#xff0c;ArkUI动画 我们在购买商品时&#xff0c;往往习惯将商品先加入购物车&#xff0c;然后在购物车里确认后再下订单&#xff0c;这是一个典型的访问者模式。对于这个高频场景&#xff0c;增添一些动效可以增加a…...

ChatGLM GPT原理介绍

图解GPT 除了BERT以外,另一个预训练模型GPT也给NLP领域带来了不少轰动,本节也对GPT做一个详细的讲解。 OpenAI提出的GPT-2模型(https://openai.com/blog/better-language-models/) 能够写出连贯并且高质量的文章,比之前语言模型效果好很多。GPT-2是基于Transformer搭建的,相…...

2015年蓝桥杯省赛C/C++ A组 灾后重建题解(100分)

10. 灾后重建 Pear市一共有N&#xff08;<50000&#xff09;个居民点&#xff0c;居民点之间有M&#xff08;<200000&#xff09;条双向道路相连。这些居民点两两之间都可以通过双向道路到达。这种情况一直持续到最近&#xff0c;一次严重的地震毁坏了全部M条道路。 震后…...

Elasticsearch(四)深分页Scroll

一、前言 1.1、scroll与fromsize区别 ES对于fromsize的个数是有限制的&#xff0c;二者之和不能超过1w。当所请求的数据总量大于1w时&#xff0c;可用scroll来代替fromsize。 fromsize在ES查询数据的方式步骤如下&#xff1a; 1、先将用户指定的关键字进行分词&#xff1b;…...

JavaWeb后端开发 JWT令牌解析 登录校验 通用模板/SpringBoot整合

目录 实现思路 会话跟踪的三个方案--引出Jwt令牌技术 1.访问cookie的值,在同一会话的不同请求之间共享数据 2.session 3.现代普遍采用的令牌技术--JWT令牌 JWT令牌技术 ​第一步--生成令牌 1.引入依赖 2.生成令牌 第二步--校验令牌 第三步--登录下发令牌 需要解决的…...

Sparta工具用法描述之信息收集(漏洞分析)

声明:本文仅做学习与交流,任何用于非法用途、行为等造成他人损失的,责任自负。本文不承担任何法律责任。 Sparta是python GUI应用程序,它通过在扫描和枚举阶段协助渗透测试仪来简化网络基础结构渗透测试。 通过点击并单击工具箱并以方便的方式显示所有工具输出,它可以使测…...

Vue复选框批量删除示例

Vue复选框批量删除 通过使用v-model指令绑定单个复选框 例如<input type"checkbox" id"checkbox" v-model"checked"> 而本次我们要做的示例大致是这样的&#xff0c;首先可以增加内容&#xff0c;然后通过勾选来进行单独或者批量删除&…...

Docker自定义镜像

一、镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 镜像是分层结构&#xff0c;每一层称为一个Layer BaseImage层&#xff1a;包含基本的系统函数库、环境变量、文件系统其它&#xff1a;在BaseImage基础上添加依赖、安装程序、完成整个应用的…...

ardupilot的编译过程

环境 树莓派4b ubuntu20.04 git 2.25.1 python3.8.10 pixhawk2.4.8 下载源码 &#xff08;已经配置好git环境和ssh&#xff09; git clone --recurse-submodules gitgithub.com:ArduPilot/ardupilot.gitcd ardupilotgit status使用git status检查是否下载完整 如果不完整&a…...

Unity中Shader实现模板测试Stencil

文章目录 前言一、UI中的遮罩1、Mask ——> 模板测试2、RectMask2D ——> UNITY_UI_CLIP_RECT 二、模板缓冲区Stencil一般是和Pass平行的部分&#xff0c;Pass部分写的是颜色缓冲区Stencil:Comp&#xff08;比较操作&#xff09;Pass(模版缓冲区的更新) 三、实际使用1、在…...

多线程与并发

多线程与高并发 线程的创建方式1.继承Thread类 重写run方法2.实现Runnable接口 重写run方法3. 实现Callable 重写call方法&#xff0c;配合FutureTask 线程的使用1.线程的状态1.1. 传统操作系统层面5种状态1.2.Java中给线程准备的6种状态 2.线程的常用方法2.1 获取当前线程2.2 …...

手写call方法

Function.prototype.myCallfunction (context,args) {console.log(arguments)//context 表示call里面的第一个参数也就是需要改变this指向的那个对象。//this表示这个方法//把这个方法挂到需要改变指向的对象身上调用&#xff0c;相当于把this指向了这个对象身上&#xff0c;从…...

基于FPGA的图像直方图统计实现,包括tb测试文件和MATLAB辅助验证

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1、图像数据传输 4.2、直方图统计算法 4.3、时序控制和电路设计 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 vivado2019.2 matlab2022a 3.部分核心程序 timescal…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...