ROS2核心模块

1.创建工作空间

先创建工作空间ws01_plumbing,

终端下进入工作空间的src目录,执行如下命令:

ros2 pkg create --build-type ament_cmake base_interfaces_demo

2.话题通信

话题通信是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息。

话题通信是一种以发布订阅的方式实现不同节点之间数据传输的通信模型。数据发布对象称为发布方,数据订阅对象称之为订阅方,发布方和订阅方通过话题相关联,发布方将消息发布在话题上,订阅方则从该话题订阅消息,消息的流向是单向的。

话题通信的发布方与订阅方是一种多对多的关系,也即,同一话题下可以存在多个发布方,也可以存在多个订阅方,这意味着数据会出现交叉传输的情况,当然如果没有订阅方,数据传输也会出现丢失的情况。

2.1话题通信案例

终端下进入工作空间的src目录,调用如下两条命令分别创建C++功能包和Python功能包。

ros2 pkg create cpp01_topic --build-type ament_cmake --dependencies rclcpp std_msgs base_interfaces_demo --node-name demo01_talker_str
ros2 pkg create py01_topic --build-type ament_python --dependencies rclpy std_msgs base_interfaces_demo --node-name demo01_talker_str_py

2.1.1 发送方案例(C++)

/*  需求:订阅发布方发布的消息,并输出到终端。步骤:1.包含头文件;2.初始化 ROS2 客户端;3.定义节点类;3-1.创建订阅方;3-2.定时器。3-3.组织并发布消息4.调用spin函数,并传入节点对象指针;5.释放资源。
*/#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"using namespace std::chrono_literals; //使用chrono库中的时间单位//自定义节点类
class Talker:public rclcpp::Node{public:Talker():Node("Talker_Node_cpp"),count(0){//初始化count=0RCLCPP_INFO(this->get_logger(),"发布节点");// 3-1.创建订阅方;publisher_=this->create_publisher<std_msgs::msg::String>("chatter",10);//创建一个名为"chater"的主题,队列长度为10// 3-2.定时器。// 参数:时间间隔,毁掉函数,返回值:当前对象指针timer_=this->create_wall_timer(1s,std::bind(&Talker::on_timer,this));//创建一个定时器,每隔1秒调用一次on_timer函数}private:size_t count;//定义一个计数器,用于记录发布的消息数量void on_timer(){// 3-3.组织并发布消息auto msg=std_msgs::msg::String();//创建一个String类型的消息对象msg.data="Hello ROS2 C++! "+std::to_string(count++);//给消息对象赋值RCLCPP_INFO(this->get_logger(),"发布消息:%s",msg.data.c_str());//输出日志信息publisher_->publish(msg);}rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;//定义一个发布者指针,类型为std_msgs::msg::Stringrclcpp::TimerBase::SharedPtr timer_;//定义一个定时器指针
};int main(int argc,char** argv){//初始化rclcpp::init(argc,argv);//调用spin,挂起当前rclcpp::spin(std::make_shared<Talker>());//释放rclcpp::shutdown();
}

在终端运行

colcon build --packages-select cpp01_topic
. install/setup.bash
ros2 run cpp01_topic demo01_talker_str

可以另外一个终端去验证chatter主题下是否有内容

. install/setup.bash
ros2 topic echo /chatter

2.1.2 订阅方案例(C++)

/*  需求:订阅发布方发布的消息,并输出到终端。步骤:1.包含头文件;2.初始化 ROS2 客户端;3.定义节点类;3-1.创建订阅方;3-2.定时器。3-3.组织并发布消息4.调用spin函数,并传入节点对象指针;5.释放资源。
*/#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"using namespace std::chrono_literals; //使用chrono库中的时间单位//自定义节点类
class Talker:public rclcpp::Node{public:Talker():Node("Talker_Node_cpp"),count(0){//初始化count=0RCLCPP_INFO(this->get_logger(),"发布节点");// 3-1.创建订阅方;publisher_=this->create_publisher<std_msgs::msg::String>("chatter",10);//创建一个名为"chater"的主题,队列长度为10// 3-2.定时器。// 参数:时间间隔,毁掉函数,返回值:当前对象指针timer_=this->create_wall_timer(1s,std::bind(&Talker::on_timer,this));//创建一个定时器,每隔1秒调用一次on_timer函数}private:size_t count;//定义一个计数器,用于记录发布的消息数量void on_timer(){// 3-3.组织并发布消息auto msg=std_msgs::msg::String();//创建一个String类型的消息对象msg.data="Hello ROS2 C++! "+std::to_string(count++);//给消息对象赋值RCLCPP_INFO(this->get_logger(),"发布消息:%s",msg.data.c_str());//输出日志信息publisher_->publish(msg);}rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;//定义一个发布者指针,类型为std_msgs::msg::Stringrclcpp::TimerBase::SharedPtr timer_;//定义一个定时器指针
};int main(int argc,char** argv){//初始化rclcpp::init(argc,argv);//调用spin,挂起当前rclcpp::spin(std::make_shared<Talker>());//释放rclcpp::shutdown();
}

需要去CMakeLists.txt三处添加demo02_listener_str

在终端运行(要先启动发送方,订阅方才有信息)

colcon build --packages-select cpp01_topic
. install/setup.bash
ros2 run cpp01_topic demo02_listener_str

2.1.3 发送方案例(python)

     # 需求:订阅发布方发布的消息,并输出到终端。# 步骤:#     1.包含头文件;#     2.初始化 ROS2 客户端;#     3.定义节点类;#         3-1.创建订阅方;#         3-2.定时器。#         3-3.组织并发布消息#     4.调用spin函数,并传入节点对象指针;#     5.释放资源。import rclpy
from rclpy.node import Node
from std_msgs.msg import String# 定义节点类
class Puublisher(Node):def __init__(self):super().__init__('talker_node_py')self.get_logger().info('发布节点')# 3-1.创建发布方self.publisher_ = self.create_publisher(String, 'chatter', 10)# 3-2.定时器self.timer = self.create_timer(1.0, self.on_timer)self.count = 0def on_timer(self):# 3-3.组织并发布消息msg = String()msg.data = f"Hello ROS2 Python! {self.count}"self.get_logger().info(f'发布消息:{msg.data}')self.publisher_.publish(msg)self.count += 1def main():# 初始化 ROS2 客户端rclpy.init()# 创建节点对象node = Puublisher()# 调用 spin 函数,传入节点对象指针rclpy.spin(node)# 释放资源rclpy.shutdown()if __name__ == '__main__':main()

2.1.4 订阅方案例(python)

    # 需求:订阅发布方发布的消息,并在终端输出# 流程:#     1.头文件#     2.初始化客户端#     3.自定义节点类#         3-1.创建订阅方#         3-2.解析并输出数据#     4.调用spin函数,传入节点对象指针#     5.释放资源import rclpy
from rclpy.node import Node
from std_msgs.msg import String# 自定义节点类
class Subscriber(Node):def __init__(self):super().__init__('listener_node_py')# 创建订阅方self.subscription=self.create_subscription(String,"chatter",self.listen_callback,10,)self.subscription  # 订阅对象指针#处理订阅到的消息def listen_callback(self, msg):# 解析并输出数据self.get_logger().info(f'订阅到消息:{msg.data}')   def main(args=None):# 初始化 ROS2 客户端rclpy.init(args=args)# 创建节点对象node = Subscriber()# 调用 spin 函数,传入节点对象指针rclpy.spin(node)# 释放资源rclpy.shutdown()if __name__ == '__main__':main()

订阅方创建好之后需要到setup.py文件下修改entry_points参数,将demo02加进去:

然后编译运行

colcon build --packages-select py01_topic
. install/setup.bash
ros2 run py01_topic demo01_talker_str_py//再重开一个终端运行
. install/setup.bash
ros2 run py01_topic demo02_listener_str_py

2.1.5 自定义接口消息

创建并编辑 .msg 文件

功能包base_interfaces_demo下新建 msg 文件夹,msg文件夹下新建Student.msg文件,文件中输入如下内容:

string   name
int32    age
float64  height
在package.xml文件添加

如果有报错的直接删掉

在CMakeList.txt添加

在终端编译测试
colcon build --packages-select base_interfaces_demo. install/setup.bash
ros2 interface show base_interfaces_demo/msg/Student

输出内容和Student.msg一致

2.1.6 自定义发布方(C++)

/*需求:以固定频率发布学生信息。步骤:1.包含头文件;2.初始化 ROS2 客户端;3.定义节点类;3-1创建发布方3-2创建定时器3-3组织并发布消息4.调用spin函数,并传入节点对象指针;5.释放资源。
*/
#include <rclcpp/rclcpp.hpp>
#include "std_msgs/msg/string.hpp"
#include "base_interfaces_demo/msg/student.hpp" // 引入自定义消息类型using base_interfaces_demo::msg::Student; // 使用自定义消息类型的命名空间
using namespace std::chrono_literals; // 使用 chrono 的时间单位
// 自定义节点类
class TalkStu : public rclcpp::Node
{
public:TalkStu() : Node("TalkStu_node_cpp"){// 3-1创建发布方publisher_=this->create_publisher<Student>("chat_stu", 10); // 创建一个名为 "chat_stu" 的发布者,队列长度为 10// 3-2创建定时器timer_=this->create_wall_timer(1s,std::bind(&TalkStu::timer_callback, this)); // 每秒调用一次 timer_callback 函数                }private:int age=0;void timer_callback(){// 3-3组织并发布消息auto stu=Student();stu.name="张三";stu.age=age++;stu.height=1.75;age++;publisher_->publish(stu); // 发布消息RCLCPP_INFO(this->get_logger(), "发布学生信息: name=%s,age=%d,height=%.2f)",stu.name.c_str(), stu.age, stu.height);};rclcpp::Publisher<Student>::SharedPtr publisher_; // 定义发布者指针rclcpp::TimerBase::SharedPtr timer_; // 定义定时器指针};int main(int argc, char const *argv[])
{// 初始化rclcpp::init(argc, argv);// 调用spin,挂起当前rclcpp::spin(std::make_shared<TalkStu>());// 释放rclcpp::shutdown();return 0;
}

package.xml无需更改,需要在CMakeList.txt文件下添加这两个文件

2.1.7 自定义订阅方(C++)

/*  需求:订阅发布方发布的消息,并输出到终端。步骤:1.包含头文件;2.初始化 ROS2 客户端;3.定义节点类;3-1创建订阅方;3-2创建回调函数;订阅并解析数据4.调用spin函数,并传入节点对象指针;5.释放资源。
*/
#include <rclcpp/rclcpp.hpp>
#include "std_msgs/msg/string.hpp"
#include "base_interfaces_demo/msg/student.hpp"using base_interfaces_demo::msg::Student; // 使用自定义消息类型的命名空间//自定义节点类
class ListenerStu:public rclcpp::Node{
public:ListenerStu():Node("ListenerStu_node_cpp"){// 3-1创建订阅方;subscription_=this->create_subscription<Student>("chat_stu",10,std::bind(&ListenerStu::topic_callback,this,std::placeholders::_1));}
private:void topic_callback(const Student &stu){// 3-2创建回调函数;订阅并解析数据RCLCPP_INFO(this->get_logger(),"订阅信息: name=%s, age=%d, height=%.2f",stu.name.c_str(), stu.age, stu.height);};rclcpp::Subscription<Student>::SharedPtr subscription_; // 定义订阅者指针
};int main(int argc,char const *argv[]){//初始化rclcpp::init(argc,argv);//调用spin,挂起当前rclcpp::spin(std::make_shared<ListenerStu>());//释放rclcpp::shutdown();
}

在两个终端分别运行

colcon build --packages-select cpp01_topic
. install/setup.bash
ros2 run cpp01_topic demo03_talker_stu. install/setup.bash
ros2 run cpp01_topic demo04_listener_stu

2.1.8 自定义发布方(python)

"""
流程:1. 导包2. 初始化ROS2客户端3. 自定义节点类3-1. 创建发布者/订阅者3-2. 处理数据(回调函数)4. 调用 spin 函数,传入节点对象5. 资源释放
"""import rclpy
from rclpy.node import Node
from base_interfaces_demo.msg import Student # 可根据需要替换为其他消息类型class TalkerStu(Node):def __init__(self):super().__init__('my_node_py')self.get_logger().info("节点已启动:my_node_py")# 3-1. 创建发布者(可选)self.publisher_ = self.create_publisher(Student, 'chat_stu', 10)self.timer = self.create_timer(0.5, self.timer_callback)  # 每0.5秒发布一次self.count=0# 3-2. 处理数据def timer_callback(self):msg = Student()msg.name = '张三'msg.age = self.countmsg.height=1.72self.publisher_.publish(msg)self.count+=1self.get_logger().info('发布消息: name=%s,age=%d,height=%.2f' % (msg.name, msg.age, msg.height))def main(args=None):# 2. 初始化ROS2客户端rclpy.init(args=args)# 3. 创建节点对象node = TalkerStu()# 4. 调用 spin,传入节点对象rclpy.spin(node)# 5. 释放资源rclpy.shutdown()if __name__ == '__main__':main()
from base_interfaces_demo.msg import Student # 可根据需要替换为其他消息类型

这一段需要crtl+shift+p搜索dettings.json
然后在文件种添加

{"python.autoComplete.extraPaths": ["/home/sun/ws01_pluming/install/base_interfaces_demo/local/lib/python3.10/dist-packages",],"python.analysis.extraPaths": ["/home/sun/ws01_pluming/install/base_interfaces_demo/local/lib/python3.10/dist-packages",]
}

然后Student才会生效。

之后进入到setup.py文件下添加

2.1.9 自定义订阅放(python)

"""
流程:1. 导包2. 初始化ROS2客户端3. 自定义节点类3-1. 创建发布者/订阅者3-2. 处理数据(回调函数)4. 调用 spin 函数,传入节点对象5. 资源释放
"""import rclpy
from rclpy.node import Node
from base_interfaces_demo.msg import Student   # 可根据需要替换为其他消息类型class ListenerStu(Node):def __init__(self):super().__init__('my_node_py')self.get_logger().info('节点已启动:my_node_py')# 3-1. 创建订阅者(可选)self.subscription = self.create_subscription(Student,'chat_stu',self.listener_callback,10)self.subscription  # 防止未使用警告# 3-2. 处理数据def listener_callback(self, msg):self.get_logger().info('收到消息: name=%s,age=%d,height=%.2f' % (msg.name, msg.age, msg.height))def main(args=None):# 2. 初始化ROS2客户端rclpy.init(args=args)# 3. 创建节点对象node = ListenerStu()# 4. 调用 spin,传入节点对象rclpy.spin(node)# 5. 释放资源rclpy.shutdown()if __name__ == '__main__':main()

然后在终端运行

colcon build --packages-select py01_topic
. install/setup.bash
ros2 run py03_topic demo03_talker_stu_py. install/setup.bash
ros2 run py04_topic demo04_listener_stu_py

2.1.10 同一个订阅主题下不同程序的发送和订阅

rqt可视化

新开一个终端输入rqt,在打开的窗口以此plugins->intrispection->node graph

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

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

相关文章

Mac 上安装并使用 frpc(FRP 内网穿透客户端)指南

一、先装好 Homebrew&#xff08;macOS 的包管理器&#xff09;打开终端&#xff08;Terminal&#xff09;&#xff0c;先装命令行开发工具 xcode-select --install弹窗点“安装”&#xff0c;等待 3~5 分钟。一键安装 Homebrew /bin/bash -c "$(curl -fsSL https://raw.g…

04_接口与包管理

第4课:接口与包管理 课程目标 深入理解Go语言接口的概念和用法 掌握接口的组合和空接口 学会使用Go Modules进行包管理 理解包的导入和导出规则 1. 接口基础 1.1 接口定义 // 基本接口定义 type Shape interface {Area() float64Perimeter()

福昕PDF编辑软件高级版下载与详细图文安装教程!!

软件下载 【软件名称】&#xff1a; 福昕PDF编辑器高级版 【软件大小】&#xff1a;668.9MBa a【系统要求】&#xff1a;awin10/win11或更高 福昕&#xff0c;软件下载&#xff08;夸克网盘需手机打开&#xff09;&#xff1a;&#xff1a;福昕丨夸克网盘-资源免费下载 软件介…

利用无事务方式插入数据库解决并发插入问题(最小主键id思路)

一、背景 由于某业务需要回退某产品数据缓存列表Asset资源&#xff0c;主任务执行后&#xff0c;通过并行执行批量子任务进行数据回退&#xff0c;子任务中会记录缓存列表Asset和缓存列表行AssetLine数据&#xff0c;并行执行过程会出现缓存列表行AssetLine重复插入问题&#…

如何制作免费的比特币冷钱包

本文主要从技术上讨论冷钱包的操作机制和原理&#xff0c;并不作为投资建议。对于国外的比特币玩家&#xff0c;或者打算长期囤币来对抗通货膨胀的&#xff0c;或者是想短期持有的&#xff0c;那么将比特币存储在哪里是一个Common的问题。一般是两类选择。第一种选择是存储在交…

新手向:Python制作简易音乐播放器

使用Python构建简易音乐播放器音乐播放器是现代数字生活中不可或缺的工具&#xff0c;从智能手机到电脑系统&#xff0c;几乎每个设备都内置了音乐播放功能。对于Python初学者来说&#xff0c;开发一个简易的音乐播放器是一个很好的实践项目&#xff0c;既能学习编程基础&#…

【StarRocks】TabletChecker逻辑

TabletChecker是StarRocks FE里的一个组件,它的主要工作是检查出所有的处于不健康状态的tablets。 注意,它的职责就是check(检查)。 至于tablet修复、均衡等调度工作不是TabletChecker的职责。 相关配置项 // 20秒执行一次check,代码里是执行runAfterCatalogReady()publi…

低空经济展 | 优翼仿真携eVTOL全动飞行模拟器亮相2025深圳eVTOL展

2025深圳eVTOL展将于2025年9月23-25日在深圳坪山燕子湖国际会展中心举行。展会以“低空经济・eVTOL・航空应急救援・商载大型无人运输机”为主题&#xff0c;以 “2天大会3天展览项目考察飞行表演颁奖盛典项目路演”的多元模式&#xff0c;打造覆盖 eVTOL全产业链的专业化合作平…

AI驱动商业革新:开源大模型与零售精准营销引领产业升级

在当今数字化浪潮中&#xff0c;AI 正以迅猛之势渗透至商业的每一处脉络&#xff0c;掀起一场影响深远的变革风暴&#xff0c;从根本上改写着商业运转的底层逻辑&#xff0c;创造出无数崭新的商业契机。基础模型领域&#xff0c;新的突破正在重塑行业格局。Meta 旗下的 LLaMA 3…

【表的操作】

文章目录 一、查看所有表 1、语法 二、创建表 1、语法 2、⽰例 3、表在磁盘上对应的⽂件 4、创建数据加时使⽤校验语句[if not exists] 三、查看表结构 1、语法 2、⽰例 四、修改表 1、语法 2、⽰例 (1)向表中添加⼀列 (2)修改某列的⻓度 (3)重命名某列 (4)删除某个字段…

【Java后端】Spring Boot 全局异常处理最佳实践

Spring Boot 全局异常处理最佳实践 在日常开发中&#xff0c;异常处理几乎是绕不过去的一个话题。尤其在 后端 API 项目 中&#xff0c;如果没有统一的异常处理机制&#xff0c;很容易出现以下问题&#xff1a; Controller 层代码里充斥着 try-catch&#xff0c;显得冗余。前端…

K8S-Configmap资源

目录 一、核心概念​ ​定义​ ​核心价值​ ​与Secret的区别​ ​二、核心特性​ ​数据存储​ ​生命周期​ ​作用域​ 什么是 Configmap&#xff1f; Configmap 能解决哪些问题&#xff1f; ConfigMap 的主要作用 三、命令行直接创建 四、通过文件创建&#xf…

MySQL InnoDB事务acid特性的原理和隔离级别的实现原理

InnoDB存储引擎 InnoDB存储结构表空间 则每张表都会有一个表空间&#xff08;xxx.ibd&#xff09;&#xff0c;一个mysql实例可以对应多个表空间 系统表空间 存储数据字典&#xff08;表结构定义、索引信息等&#xff09;、Change Buffer、Doublewrite Bufferundo log&#xff…

Linux系统之部署nullboard任务管理工具

Linux系统之部署nullboard任务管理工具一、nullboard介绍1.1 nullboard简介1.2 任务看板工具介绍1.3 nullboard使用场景二、本次实践介绍2.1 本地环境规划2.2 本次实践介绍三、安装httpd软件3.1 检查yum仓库3.2 安装httpd软件3.3 启动httpd服务3.4 查看httpd服务状态3.5 防火墙…

Qt设置软件使用期限【新版防修改系统时间】

在工业软件或其他领域中&#xff0c;经常会对软件进行授权&#xff0c;软件需要付费进行有期限的使用。以下是我用Qt设计的设置软件使用期限的两种方案。 主体思想&#xff1a; 1.软件需要绑定机器&#xff0c;让用户无法通过复制在另一台机器上运行。 2.由厂家提供激活码供用户…

【JavaEE】多线程(线程安全问题)

有些代码在单个线程环境下执行正确&#xff0c;如果同样的代码在多个线程下同时执行可能就会出现问题&#xff0c;这个就是线程安全问题&#xff08;或者称线程不安全问题&#xff09;&#xff0c;简而言之就是&#xff1a;线程安全问题是由于多线程出现的问题&#xff0c;原因…

NodeJs 桌面开发学习 electron.js (一)

今天开始学习NodeJs 关于 桌面应用的内容&#xff0c;长期目标是 React electron 实现一个桌面应用。今天先实现一个简单的目标&#xff0c;搭建一个Electron ts 项目架构&#xff0c;并实现主业务线程 和前端渲染线程的交互一、代码结构和配置例子项目结构大致如下&#xff…

diffusion model(1.4) 相关论文阅读清单

以下是阅读清单&#xff1a; 《Deep Unsupervised Learning using Nonequilibrium Thermodynamics》扩散模型&#xff0c;arxiv链接《Denoising Diffusion Probabilistic Models》DDPM论文 arxiv链接

ESP32-C3_SMARTCAR

前言: 前面用stm32f103c8t6 rt-thread 写了个智能小车程序 这章用esp32-c3 重新来遍 1&#xff1a;环境 vscodeidf5.4 esp32-3c 找到一块MIN的底板 凑合用&#xff08;138 cm左右&#xff09; 一个L298N 一个船型开关&#xff0c; 一个665mm 2脚按钮 锂电池 186502 及电池盒&a…

消费者API

目录独立消费者案例&#xff08;订阅主题&#xff09;独立消费者案例&#xff08;订阅分区&#xff09;消费者组案例独立消费者案例&#xff08;订阅主题&#xff09; package com.tsg.kafka.consumer;import org.apache.kafka.clients.consumer.ConsumerConfig; import org.ap…