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

ros2-3.4话题通信最佳实践

3.4.1 工程架构设计

需求背景:

第一,通过这个小工具可以看到系统的实时状态信息包括记录信息的时间、主机名称、CPU使用率、内存使用率、内存总大小、剩余内存、网络接收数据量和网络发送数据量;
第二,要有一个简单的界面,可以将系统信息显示出来;
第三,要能在局域网内其他主机上查看数据

设计:

第一,要能获取系统状态信息;Python库psutils
第二,要有一个展示界面:Qt
第三,要能共享数据。ROS2话题

3.4.2 自定义通信接口

在topic_practice_ws/src下面创建一个新的功能包

ros2 pkg create status_interfaces --dependencies builtin_interfaces rosidl_default_generators --license Apache-2.0

其中2个依赖:

builtin_interfaces 可以使用时间接口Time

rosidl_default_generators 是用来把自定义消息转换为C++、python的源码。

在功能包下新建msg文件夹,并在该文件夹下新建文件SystemStatus.msg。内容如下:

builtin_interfaces/Time stamp # 记录时间戳
string host_name 		# 系统名称
float32 cpu_percent 	# CPU使用率
float32 memory_percent 	# 内存使用率
float32 memory_total 	# 内存总量
float32 memory_available 	# 剩余有效内存
float64 net_sent 		# 网络发送数据总量
float64 net_recv 		# 网络接收数据总量

修改CMakeLists.txt,对接口文件进行注册,声明为接口文件,并增加builtin_interfaces 依赖。

cmake_minimum_required(VERSION 3.8)
project(status_interfaces)if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()# find dependencies
find_package(ament_cmake REQUIRED)
find_package(builtin_interfaces REQUIRED)
find_package(rosidl_default_generators REQUIRED)
#cmake 函数,来自依赖rosidl_default_generators,用于讲msg消息接口定义文件转换成库或者头文件
rosidl_generate_interfaces(${PROJECT_NAME}"msg/SystemStatus.msg"DEPENDENCIES builtin_interfaces
)if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()

修改packages.xml中,增加声明

<member_of_group>rosidl_interface_packages</member_of_group>

接下来构建,并查看

bohu@bohu-TM1701:~/3/topic_practice_ws$ colcon build
Starting >>> status_interfaces
Finished <<< status_interfaces [6.51s]                     Summary: 1 package finished [6.88s]
bohu@bohu-TM1701:~/3/topic_practice_ws$ source install/setup.bash 
bohu@bohu-TM1701:~/3/topic_practice_ws$ ros2 interface show status_interfaces/msg/SystemStatus 
builtin_interfaces/Time stamp # 记录时间戳int32 secuint32 nanosec
string host_name                # 系统名称
float32 cpu_percent     # CPU使用率
float32 memory_percent  # 内存使用率
float32 memory_total    # 内存总量
float32 memory_available        # 剩余有效内存
float64 net_sent                # 网络发送数据总量
float64 net_recv                # 网络接收数据总量

 还可以去install/status_interfaces/include下面,是否生成了C++文件及python库。

现在已经完成了自定义消息接口。

3.4.3 系统信息获取与发布

创建功能包status_publisher。

ros2 pkg create status_publisher --build-type ament_python --dependencies rclpy status_interfaces --license Apache-2.0

在功能包下创建文件sys_status_pub.py.代码如下:

import rclpy
from status_interfaces.msg import SystemStatus
from rclpy.node import Node
import psutil
import platformclass SysStatusPub(Node):def __init__(self, node_name):super().__init__(node_name)self.status_publisher_ = self.create_publisher(SystemStatus,'sys_status',10)self.timer_ = self.create_timer(1.0,self.timer_callback)def timer_callback(self):cpu_percent = psutil.cpu_percent()memory_info = psutil.virtual_memory()net_io_counters = psutil.net_io_counters()msg = SystemStatus()msg.stamp = self.get_clock().now().to_msg()msg.host_name = platform.node()msg.cpu_percent = cpu_percentmsg.memory_percent = memory_info.percentmsg.memory_total = memory_info.total/1024/1024msg.memory_available = memory_info.available/1024/1024msg.net_sent = net_io_counters.bytes_sent/1024/1024msg.net_recv = net_io_counters.bytes_recv/1024/1024self.get_logger().info(f'发布:{str(msg)}')self.status_publisher_.publish(msg)def main():rclpy.init()node = SysStatusPub('sys_status_pub')rclpy.spin(node)rclpy.shutdown

定义了SysStatusPub类,继承了Node.初始化创建发布者status_publisher_跟定时器timer_。定时器每秒调用一次回调timer_callback来发布数据,timer_callback内部使用了psutil获取系统信息。还有单位转换为MB.

接下来去setup.py中去注册节点sys_status_pub。编译运行。

ros2 run status_publisher sys_status_pub

bohu@bohu-TM1701:~/3/topic_practice_ws$ ros2 run status_publisher sys_status_pub 
[INFO] [1736234385.803543118] [sys_status_pub]: 发布:status_interfaces.msg.SystemStatus(stamp=builtin_interfaces.msg.Time(sec=1736234385, nanosec=761086615), host_name='bohu-TM1701', cpu_percent=7.1, memory_percent=77.4, memory_total=7824.6953125, memory_available=1771.0078125, net_sent=484.4188470840454, net_recv=5299.850911140442)
[INFO] [1736234386.762844262] [sys_status_pub]: 发布:status_interfaces.msg.SystemStatus(stamp=builtin_interfaces.msg.Time(sec=1736234386, nanosec=760874264), host_name='bohu-TM1701', cpu_percent=10.2, memory_percent=77.3, memory_total=7824.6953125, memory_available=1774.328125, net_sent=484.4210395812988, net_recv=5299.852033615112)
[INFO] [1736234387.763212697] [sys_status_pub]: 发布:status_interfaces.msg.SystemStatus(stamp=builtin_interfaces.msg.Time(sec=1736234387, nanosec=760907123), host_name='bohu-TM1701', cpu_percent=9.0, memory_percent=77.2, memory_total=7824.6953125, memory_available=1781.57421875, net_sent=484.4244565963745, net_recv=5299.8582944869995)

可以看到能够获取系统状态并发布了。

3.4.4 在功能包中使用QT

这个就是为了熟悉下QT的使用。

先在 src下创建功能包status_display

ros2 pkg create status_display --build-type ament_cmake  --dependencies  rclcpp status_interfaces --license Apache-2.0

测试类hello_qt.cpp,效果如下

消除引用警告,修改c_cpp_properties.json

{"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/opt/ros/humble/include/**","/usr/include/x86_64-linux-gnu/qt5/**"],"defines": [],"compilerPath": "/usr/bin/gcc","cStandard": "c17","cppStandard": "gnu++17","intelliSenseMode": "linux-gcc-x64"}],"version": 4
}

 3.4.5 订阅数据并用QT显示

在src/status_display/src下新建sys_status_display.cpp.代码如下

#include <QApplication>
#include <QLabel>
#include <QString>
#include <rclcpp/rclcpp.hpp>
#include <status_interfaces/msg/system_status.hpp>using SystemStatus = status_interfaces::msg::SystemStatus;
using namespace std;class SysStatusDisplay :public rclcpp::Node
{
private:/* data */rclcpp::Subscription<SystemStatus>::SharedPtr subscriber_;QLabel* label_;
public:SysStatusDisplay(/* args */):Node("sys_status_display"){label_ = new QLabel();subscriber_ = this->create_subscription<SystemStatus>("sys_status",10,[&](const SystemStatus::SharedPtr msg)->void{label_->setText(get_qstr_from_msg(msg));});label_->setText(get_qstr_from_msg(std::make_shared<SystemStatus>()));label_->show();};QString get_qstr_from_msg(const SystemStatus::SharedPtr msg){stringstream show_str;show_str << "================可视化状态显示===============\n"<< "数 据 时 间:\t" << msg->stamp.sec << "\ts\n"<< "用  户  名:\t" << msg->host_name << "\t\n"<< "CPU使用率:\t" << msg->cpu_percent << "\t%\n"<< "内存使用率:\t" << msg->memory_percent << "\t%\n"<< "内存总大小:\t" << msg->memory_total << "\tMB\n"<< "剩余有效内存:\t" << msg->memory_available << "\tMB\n"<< "网络发送量:\t" << msg->net_sent << "\tMB\n"<< "网络接收量:\t" << msg->net_recv << "\tMB\n"<< "==========================================";return QString::fromStdString(show_str.str());}};int main(int argc,char * argv[]){rclcpp::init(argc,argv);QApplication app(argc,argv);auto node = std::make_shared<SysStatusDisplay>();std::thread spin_thread([&]()->void{rclcpp::spin(node);});spin_thread.detach();app.exec();//执行,阻塞代码rclcpp::shutdown();return 0;
}

SysStatusDisplay 类继承来Node节点,定义了两个属性:label_ 用于显示,subscriber_ 订阅话题。

接着对它们进行初始化,subscriber_ 使用了lambda表达式作为回调函数。处理显示字符串放在方法get_qstr_from_msg()。

主函数设计比较巧妙,因为之前默认的rclcpp::spin(node);会阻塞执行。app.exec();也会阻塞程序运行。无论调整顺序不满足需求导致无法正常显示,所以小鱼老师讲spin单独放到一个线程中进行处理。界面退出后app.exec()退出,接着调用rclcpp::shutdown();程序正常退出。

修改CMakeLists.txt,添加节点及依赖。

cmake_minimum_required(VERSION 3.8)
project(status_display)if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic)
endif()# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(status_interfaces REQUIRED)
find_package(Qt5 REQUIRED COMPONENTS Widgets)add_executable(hello_qt src/hello_qt.cpp)
target_link_libraries(hello_qt Qt5::Widgets)
add_executable(sys_status_display src/sys_status_display.cpp)
target_link_libraries(sys_status_display Qt5::Widgets)# 对于非ROS功能包使用Cmake原生指令进行链接库
ament_target_dependencies(sys_status_display rclcpp status_interfaces)if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUND TRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()
install(TARGETS hello_qt sys_status_display
DESTINATION lib/${PROJECT_NAME})ament_package()

 构建并运行运行,依赖上一个sys_status_pub节点发布话题,

ros2 run status_publisher sys_status_pub

ros2 run status_display sys_status_display

效果如下:

本节一下子接触的知识点还是挺多的。

相关文章:

ros2-3.4话题通信最佳实践

3.4.1 工程架构设计 需求背景&#xff1a; 第一&#xff0c;通过这个小工具可以看到系统的实时状态信息包括记录信息的时间、主机名称、CPU使用率、内存使用率、内存总大小、剩余内存、网络接收数据量和网络发送数据量; 第二&#xff0c;要有一个简单的界面&#xff0c;可以将…...

Vmware安装centos

用来记录自己安装的过程 一、创建虚拟机安装centos镜像 点击完成后&#xff0c;等待一会会进入centos的系统初始化界面 二、centos初始化配置 三、配置网络 1、虚拟网络编辑器&#xff0c;开启VMnet1、VMnet8的DHCP vmware左上角工具栏&#xff0c;点击【编辑】->【虚拟网…...

51单片机——按键实验

由于机械点的弹性作用&#xff0c;按键开关在闭合时不会马上稳定的接通&#xff0c;在断开时也不会一下子断开&#xff0c;因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的&#xff0c;一般为 5ms 到 10ms&#xff0c;为了确保 CPU 对按键的…...

QT c++ 自定义按钮类 加载图片 美化按钮

如果你有需要利用图片美化按钮的情况&#xff0c;本文能帮助你。 鼠标左键按下按钮和松开&#xff0c;按钮显示不同的图片。 1.按钮类 //因为此类比较简单&#xff0c;1个头文件搞定&#xff0c;没有cpp文件 #ifndef CUSTOMBUTTON_H #define CUSTOMBUTTON_H #include <Q…...

Django:构建高效Web应用的强大框架

在当今快速发展的Web开发领域&#xff0c;选择一个合适的框架对于项目的成功至关重要。Django&#xff0c;作为Python编程语言中最受欢迎的Web框架之一&#xff0c;凭借其强大的功能、高度的可扩展性和简洁的语法&#xff0c;成为了众多开发者心中的首选。本文将深入探讨Django…...

代码随想录算法【Day11】

150. 逆波兰表达式求值 class Solution { public:int evalRPN(vector<string>& tokens) {// 力扣修改了后台测试数据&#xff0c;需要用longlongstack<long long> st; for (int i 0; i < tokens.size(); i) {if (tokens[i] "" || tokens[i] &…...

[SeaTunnel] [MySql CDC] Generate Splits for table db.table error

在使用 SeaTunnel 的 MySQL CDC 时报错&#xff1a; Caused by: org.apache.seatunnel.engine.common.exception.SeaTunnelEngineException: java.lang.RuntimeException: Generate Splits for table db.table error SeaTunnel 版本为 2.3.8 在 GitHub 上找到一种解决方法&am…...

Spring Boot | 基于MinIO实现文件上传和下载

关注&#xff1a;CodingTechWork 介绍 在现代的 web 应用中&#xff0c;文件上传和下载是常见的需求。MinIO 是一个开源的高性能分布式对象存储服务&#xff0c;可以用来存储和管理大量的非结构化数据&#xff0c;如图片、视频、日志文件等。本文将介绍如何在 Spring Boot 应用…...

企业手机号搜索API接口

每日免费每次消耗&#xff1a;按量每日限制&#xff1a;10 次每次请求积分消耗&#xff1a;50 积分 / 次总次数限制&#xff1a;10000 次每次请求间隔&#xff1a;0 秒&#xff0c;并发&#xff1a;50 请求地址 http(s)://api.aiqimao.com/index/apiphoneget/ 调试 请求方法…...

VirtualBox Main API 学习笔记

1. Philosophy 1.1 对于Python&#xff0c;推荐使用"WEBSERVICE"连接方式 Gemini 2.0 Flash Experimental: 对于 Java 和 Python&#xff1a; 文档建议您首先使用"WEBSERVICE"&#xff0c;因为它提供了一种更直观的方式来使用 API。 2. Configuration pi…...

[Linux]Mysql9.0.1服务端脱机安装配置教程(redhat)

前言 本教程适用于在yum源不可用的LInux主机上安装Mysql的场景。 以redhat系主机做操作示例&#xff0c;debian系主机可参照步骤&#xff0c;将对应的rpm -ivh命令换成dpkg -i。 1. 官网下载安装包 https://dev.mysql.com/downloads/mysql/ 1.1 版本分类 MySQL Enterprise…...

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…...

计算机毕业设计学习项目-P10080 基于springboot+vue的社团管理系统的设计与实现

项目说明 本号所发布的项目均由我部署运行验证&#xff0c;可保证项目系统正常运行&#xff0c;以及提供完整源码。 如需要远程部署/定制/讲解系统&#xff0c;可以联系我。定制项目未经同意不会上传&#xff01; 项目源码获取方式放在文章末尾处 注&#xff1a;项目仅供学…...

with as提高sql的执行效率

实战sql with cte(UNIT_ID, UNIT_NAME, PARENT_UNIT_ID, UNIT_CODE ) as (select UNIT_ID, UNIT_NAME, PARENT_UNIT_ID , UNIT_CODEfrom HPFM_UNITunion allselect t.UNIT_ID, t.UNIT_NAME, t.PARENT_UNIT_ID, t.UNIT_CODEfrom HPFM_UNIT tjoin cte on t.PARENT_UNIT_ID cte.U…...

【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…...

计算机毕业设计Python中华古诗词知识图谱可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析模型 自然语言处理NLP 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述&#xff0c;其缺点是有状态&#xff08;多副本隔离时&#xff0c;依赖手动配置workId和datacenterId&#xff09;&#xff0c;代码如下&#xff1a; /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...

【问题】配置 Conda 与 Pip 源

通常情况下,使用 conda 命令或者 pip 命令都是从国外的服务器上下载需要的模块包的,这在网速不佳的情况下会消耗大量的时间。所以这里建议更换国内的源来进行模块下载,速度会大大提升。 具体方法如下: 打开命令行 cmd 工具,输入以下命令。 ① Conda 换源 conda config…...

Zookeeper是如何保证事务的顺序一致性的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper是如何保证事务的顺序一致性的?】面试题。希望对大家有帮助&#xff1b; Zookeeper是如何保证事务的顺序一致性的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过多个机制来保证事务的顺序一…...

东土科技参股广汽集团飞行汽车初创公司,为低空经济构建新型产业生态

近日&#xff0c;广汽集团旗下专注于飞行汽车领域的初创公司广东高域科技有限公司于2024年12月31日正式成立&#xff0c;在穿透后的股东信息中&#xff0c;东土科技通过广州瓴云科技投资合伙企业&#xff08;有限合伙&#xff09;赫然在列。 此前12月18日&#xff0c;广汽集团…...

stm32G473的flash模式是单bank还是双bank?

今天突然有人stm32G473的flash模式是单bank还是双bank&#xff1f;由于时间太久&#xff0c;我真忘记了。搜搜发现&#xff0c;还真有人和我一样。见下面的链接&#xff1a;https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

AspectJ 在 Android 中的完整使用指南

一、环境配置&#xff08;Gradle 7.0 适配&#xff09; 1. 项目级 build.gradle // 注意&#xff1a;沪江插件已停更&#xff0c;推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...