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 工程架构设计 需求背景: 第一,通过这个小工具可以看到系统的实时状态信息包括记录信息的时间、主机名称、CPU使用率、内存使用率、内存总大小、剩余内存、网络接收数据量和网络发送数据量; 第二,要有一个简单的界面,可以将…...
Vmware安装centos
用来记录自己安装的过程 一、创建虚拟机安装centos镜像 点击完成后,等待一会会进入centos的系统初始化界面 二、centos初始化配置 三、配置网络 1、虚拟网络编辑器,开启VMnet1、VMnet8的DHCP vmware左上角工具栏,点击【编辑】->【虚拟网…...
51单片机——按键实验
由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms,为了确保 CPU 对按键的…...
QT c++ 自定义按钮类 加载图片 美化按钮
如果你有需要利用图片美化按钮的情况,本文能帮助你。 鼠标左键按下按钮和松开,按钮显示不同的图片。 1.按钮类 //因为此类比较简单,1个头文件搞定,没有cpp文件 #ifndef CUSTOMBUTTON_H #define CUSTOMBUTTON_H #include <Q…...
Django:构建高效Web应用的强大框架
在当今快速发展的Web开发领域,选择一个合适的框架对于项目的成功至关重要。Django,作为Python编程语言中最受欢迎的Web框架之一,凭借其强大的功能、高度的可扩展性和简洁的语法,成为了众多开发者心中的首选。本文将深入探讨Django…...
代码随想录算法【Day11】
150. 逆波兰表达式求值 class Solution { public:int evalRPN(vector<string>& tokens) {// 力扣修改了后台测试数据,需要用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 时报错: 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实现文件上传和下载
关注:CodingTechWork 介绍 在现代的 web 应用中,文件上传和下载是常见的需求。MinIO 是一个开源的高性能分布式对象存储服务,可以用来存储和管理大量的非结构化数据,如图片、视频、日志文件等。本文将介绍如何在 Spring Boot 应用…...
企业手机号搜索API接口
每日免费每次消耗:按量每日限制:10 次每次请求积分消耗:50 积分 / 次总次数限制:10000 次每次请求间隔:0 秒,并发:50 请求地址 http(s)://api.aiqimao.com/index/apiphoneget/ 调试 请求方法…...
VirtualBox Main API 学习笔记
1. Philosophy 1.1 对于Python,推荐使用"WEBSERVICE"连接方式 Gemini 2.0 Flash Experimental: 对于 Java 和 Python: 文档建议您首先使用"WEBSERVICE",因为它提供了一种更直观的方式来使用 API。 2. Configuration pi…...
[Linux]Mysql9.0.1服务端脱机安装配置教程(redhat)
前言 本教程适用于在yum源不可用的LInux主机上安装Mysql的场景。 以redhat系主机做操作示例,debian系主机可参照步骤,将对应的rpm -ivh命令换成dpkg -i。 1. 官网下载安装包 https://dev.mysql.com/downloads/mysql/ 1.1 版本分类 MySQL Enterprise…...
uniapp--HBuilder开发
提示:本文为学习内容,若有错误,请联系作者,谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…...
计算机毕业设计学习项目-P10080 基于springboot+vue的社团管理系统的设计与实现
项目说明 本号所发布的项目均由我部署运行验证,可保证项目系统正常运行,以及提供完整源码。 如需要远程部署/定制/讲解系统,可以联系我。定制项目未经同意不会上传! 项目源码获取方式放在文章末尾处 注:项目仅供学…...
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半链接数溢出分析及处理全过程
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…...
计算机毕业设计Python中华古诗词知识图谱可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析模型 自然语言处理NLP 机器学习 深度学习
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
分布式ID生成-雪花算法实现无状态
雪花算法这里不再赘述,其缺点是有状态(多副本隔离时,依赖手动配置workId和datacenterId),代码如下: /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...
【问题】配置 Conda 与 Pip 源
通常情况下,使用 conda 命令或者 pip 命令都是从国外的服务器上下载需要的模块包的,这在网速不佳的情况下会消耗大量的时间。所以这里建议更换国内的源来进行模块下载,速度会大大提升。 具体方法如下: 打开命令行 cmd 工具,输入以下命令。 ① Conda 换源 conda config…...
Zookeeper是如何保证事务的顺序一致性的?
大家好,我是锋哥。今天分享关于【Zookeeper是如何保证事务的顺序一致性的?】面试题。希望对大家有帮助; Zookeeper是如何保证事务的顺序一致性的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过多个机制来保证事务的顺序一…...
东土科技参股广汽集团飞行汽车初创公司,为低空经济构建新型产业生态
近日,广汽集团旗下专注于飞行汽车领域的初创公司广东高域科技有限公司于2024年12月31日正式成立,在穿透后的股东信息中,东土科技通过广州瓴云科技投资合伙企业(有限合伙)赫然在列。 此前12月18日,广汽集团…...
自如”增益租3.0”模式:以真实案例解析,做值得信赖的资产托管方案
一、从真实案例出发:理解增益租模式的运作逻辑近期,网络上流传着一些关于自如“增益租3.0”模式的案例讨论。其中,有业主反馈将毛坯房委托后,因选择分期支付装修费用,导致前期每月到手租金较低,且短期内未获…...
如何用QtScrcpy实现Android设备实时投屏:终极免费解决方案
如何用QtScrcpy实现Android设备实时投屏:终极免费解决方案 【免费下载链接】QtScrcpy Android实时投屏软件,此应用程序提供USB(或通过TCP/IP)连接的Android设备的显示和控制。它不需要任何root访问权限 项目地址: https://gitcode.com/barry-ran/QtScr…...
WSL2 Ubuntu迁移,导出Ubuntu,导入Ubuntu(存储位置)
一、Ubuntu虚拟硬盘文件路径 网上说的 C:\Users\admin\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx 我没有CanonicalGroupLimited.Ubuntu22.04LTS_79rhkp1fndgsc这个目录 搜索ext4.vhdx C:\Users\admin\AppData\Local\…...
基于STM32LXXX的数字电位器(TPL0401A-10QDCKRQ1)驱动应用程序设计
一、简介: TPL0401A-10QDCKRQ1 是德州仪器(TI)推出的一款车规级单通道数字电位器,主要面向STM32LXXX等低功耗平台。 二、主要技术特性: 核心规格:128抽头(7位分辨率)、10kΩ端到端电阻、IC接口、SC-70-6小型封装、车规级(AEC-Q100)[-40℃至+125℃]。 电气特性:工…...
MySQL 单表查询练习题汇总
一、练习数据表(my_student_score)表结构说明班级:高三 1-5 班(共 5 个)科目:语文、数学、英语、物理、化学、生物(共 6 个)数据量:300 条(覆盖多班级、多科目…...
收藏备用|中国AI大模型产业链全景解析(小白程序员必看)
当下中国AI大模型市场正加速完成从“技术探索”到“规模化应用”的关键转型,多模态融合、端侧轻量化两大趋势持续拓展应用边界,无论是办公自动化、代码生成还是智能交互,都能看到大模型的身影。企业数字化转型浪潮叠加“人工智能”政策红利&a…...
x64dbg调试器完全指南:5步掌握Windows逆向工程核心技术 [特殊字符]
x64dbg调试器完全指南:5步掌握Windows逆向工程核心技术 🚀 【免费下载链接】x64dbg An open-source user mode debugger for Windows. Optimized for reverse engineering and malware analysis. 项目地址: https://gitcode.com/gh_mirrors/x6/x64dbg …...
突破付费墙限制:从技术原理到个性化解决方案的完整指南
突破付费墙限制:从技术原理到个性化解决方案的完整指南 当你在研究某个专业领域的前沿动态时,是否曾因遇到"订阅后阅读全文"的提示而被迫中断探索?在信息获取成本日益增加的今天,如何合法合规地突破内容访问限制&#x…...
JW Player插件开发教程:如何快速扩展播放器功能
JW Player插件开发教程:如何快速扩展播放器功能 【免费下载链接】jwplayer No Longer Maintained 项目地址: https://gitcode.com/gh_mirrors/jw/jwplayer JW Player是一款功能强大的开源媒体播放器,通过插件系统可以轻松扩展其功能。本文将带你快…...
K8s面试官最爱问的5个冷门知识点,答对直接加薪!
K8s面试官最爱问的5个冷门知识点,答对直接加薪! 在Kubernetes技术面试中,大多数候选人能够流畅回答Pod、Deployment、Service等基础概念,但当面试官深入追问一些冷门却关键的设计机制时,往往成为区分普通工程师与高级专…...
