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日,广汽集团…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...