订阅ROS2中相机的相关话题并保存RGB、深度和点云图
系统:Ubuntu22.04
ROS2版本:ROS2 humble
1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图
ros2 topic list/stellar_1/rgb/image_raw
/camera/depth/image_raw
/stellar_1/points2
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(bag_to_image)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(sensor_msgs REQUIRED)
find_package(cv_bridge REQUIRED)
find_package(OpenCV REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)add_executable(bag_to_image_node src/bag_to_image_node.cpp)# ROS2中指定节点或库的依赖项
ament_target_dependencies(bag_to_image_node rclcpp) # 核心C++客户端库,旨在简化开发和实现机器人应用程序
ament_target_dependencies(bag_to_image_node sensor_msgs) # 消息包,提供了一系列标准化的消息类型,用于传输来自各种传感器的数据
ament_target_dependencies(bag_to_image_node cv_bridge) # 用于连接ROS与OpenCV,提供在ROS消息格式与OpenCV图像格式之间的转换
ament_target_dependencies(bag_to_image_node OpenCV)install(TARGETSbag_to_image_nodeDESTINATION lib/${PROJECT_NAME})if(BUILD_TESTING)find_package(ament_lint_auto REQUIRED)set(ament_cmake_copyright_FOUND TRUE)set(ament_cmake_cpplint_FOUND TRUE)ament_lint_auto_find_test_dependencies()
endif()ament_package()
bag_to_image_node.cpp
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/image.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <cv_bridge/cv_bridge.h>
#include <opencv2/opencv.hpp>
#include <filesystem>
#include <fstream>
#include <queue>class ImageSaver : public rclcpp::Node
{
public:ImageSaver() : Node("image_saver"), frame_count(0){// 新建RGB图像、深度图像、点云图像文件夹std::filesystem::create_directories("rgb_images");std::filesystem::create_directories("depth_images");std::filesystem::create_directories("point_clouds");// 订阅话题 rgb_subscriber = this->create_subscription<sensor_msgs::msg::Image>("/stellar_1/rgb/image_raw",10,std::bind(&ImageSaver::rgb_callback, this, std::placeholders::_1));depth_subscriber = this->create_subscription<sensor_msgs::msg::Image>("/camera/depth/image_raw",10,std::bind(&ImageSaver::depth_callback, this, std::placeholders::_1));point_cloud_subscriber = this->create_subscription<sensor_msgs::msg::PointCloud2>("/stellar_1/points2",10,std::bind(&ImageSaver::point_cloud_callback, this, std::placeholders::_1));}private:std::queue<sensor_msgs::msg::Image::SharedPtr> rgb_queue;std::queue<sensor_msgs::msg::Image::SharedPtr> depth_queue;void rgb_callback(const sensor_msgs::msg::Image::SharedPtr msg){rgb_queue.push(msg);process_frames();}void depth_callback(const sensor_msgs::msg::Image::SharedPtr msg){depth_queue.push(msg);process_frames();}void point_cloud_callback(const sensor_msgs::msg::PointCloud2::SharedPtr msg){// 保存点云图为.bin格式std::ofstream outfile("point_clouds/frame_" + std::to_string(frame_count) + ".bin", std::ios::binary);outfile.write(reinterpret_cast<const char *>(msg->data.data()), msg->data.size());outfile.close();frame_count++;process_frames(); // Check if we can process frames after saving point cloud}void process_frames(){while (!rgb_queue.empty() && !depth_queue.empty() && frame_count > 0) {auto rgb_msg = rgb_queue.front();auto depth_msg = depth_queue.front();// 计算时间戳差值int64_t rgb_time = rgb_msg->header.stamp.sec * 1e9 + rgb_msg->header.stamp.nanosec;int64_t depth_time = depth_msg->header.stamp.sec * 1e9 + depth_msg->header.stamp.nanosec;// 检查时间戳是否足够接近if (std::abs(rgb_time - depth_time) < 100000000) { // 100 mscv_bridge::CvImagePtr cv_rgb_ptr = cv_bridge::toCvCopy(rgb_msg, sensor_msgs::image_encodings::BGR8);cv::imwrite("rgb_images/frame_" + std::to_string(frame_count) + ".png", cv_rgb_ptr->image);// TYPE_32FC1:// 32F:表示每个元素是 32 位(4 字节)浮点数(float)。// C1:表示单通道(Channel 1),即每个像素只有一个值。常用于灰度图像或单通道浮点数据。// TYPE_16UC1:// 16U:表示每个元素是 16 位(2 字节)无符号整数(unsigned int)。// C1:同样表示单通道,即每个像素只有一个值。常用于灰度图像或单通道整数数据,通常用于深度图等场景。cv_bridge::CvImagePtr cv_depth_ptr =cv_bridge::toCvCopy(depth_msg, sensor_msgs::image_encodings::TYPE_16UC1);cv::imwrite("depth_images/frame_" + std::to_string(frame_count) + ".png", cv_depth_ptr->image);rgb_queue.pop();depth_queue.pop();} else if (rgb_time < depth_time) {rgb_queue.pop(); // 移除旧的 RGB 消息} else {depth_queue.pop(); // 移除旧的深度消息}}}rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr rgb_subscriber;rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr depth_subscriber;rclcpp::Subscription<sensor_msgs::msg::PointCloud2>::SharedPtr point_cloud_subscriber;int frame_count;
};int main(int argc, char **argv)
{std::cout << "bag to image node start.." << std::endl;rclcpp::init(argc, argv);rclcpp::spin(std::make_shared<ImageSaver>());rclcpp::shutdown();return 0;
}
运行:
source install/setup.bash
ros2 run bag_to_image bag_to_image_node

2.将点云图.bin格式转换为.pcd格式
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <thread>// 将点云图.bin转换为.pcd
void convert_bin_to_pcd(const std::string &bin_file, const std::string &pcd_file)
{// 读取二进制点云数据std::ifstream infile(bin_file, std::ios::binary);if (!infile) {std::cerr << "Error opening binary file!" << std::endl;return;}pcl::PointCloud<pcl::PointXYZ> cloud;pcl::PointXYZ point;// 假设每个点包含x, y, z坐标while (infile.read(reinterpret_cast<char *>(&point), sizeof(pcl::PointXYZ))) {cloud.points.push_back(point);}cloud.width = cloud.points.size();cloud.height = 1; // 单个点云infile.close();// 保存为 PCD 文件pcl::io::savePCDFileASCII(pcd_file, cloud);std::cout << "Converted to PCD file: " << pcd_file << std::endl;
}int main(int argc, char **argv)
{convert_bin_to_pcd("frame_0.bin", "frame_0.pcd");return 0;
}
相关文章:
订阅ROS2中相机的相关话题并保存RGB、深度和点云图
系统:Ubuntu22.04 ROS2版本:ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…...
Open WebUI | 自托管的类 ChatGPT 网站
Open WebUI 是一个扩展性强、功能丰富且用户友好的自托管 WebUI,旨在完全离线操作。它支持各种 LLM 服务,包括 Ollama 和 OpenAI 兼容的 API。该项目在 GitHub 上已有 38k 星,非常受欢迎。 功能介绍 废话不多说,上图!…...
【Python】Python知识总结浅析
Python是一种高级编程语言,由Guido van Rossum于1991年首次发布。它以简洁的语法和强大的功能著称,适用于多种应用场景,包括Web开发、数据分析、人工智能、自动化脚本等。 易于学习和使用:Python的语法简洁明了,适合初…...
c#代码介绍23种设计模式_20策略者模式
目录 1、策略模式的定义 2、策略模式的结构 3、涉及到三个角色: 4、策略者模式在.NET中应用 5、策略者模式的适用场景 6、策略者模式的优缺点 7、实现思路 在现实生活中,策略模式的例子也非常常见,例如,中国的所得税,分为企业所得税、外商投资企业或外商企业所得税…...
FPGA-UART串口接收模块的理解
UART串口接收模块 背景 在之前就有写过关于串口模块的文章——《串口RS232的学习》。工作后很多项目都会用到串口模块,又来重新理解一下FPGA串口接收的代码思路。 关于串口相关的参数,以及在文章《串口RS232的学习》中已有详细的描述,这里就…...
复习HTML(基础)
目录 HTML含义 HTML作用 HTML的常用元素 元素的特点 元素的分类 1 是否嵌套关系 2 是否独占一行 块元素:独占一行 行内元素:共享一行 行内元素与块级元素的转换 3是否有结束标签 常用标签 1 标题标签:有六级 我们用h1 ~h6 表…...
Linux聊天集群开发之环境准备
一.windows下远程操作Linux 第一步:在Linux终端下配置openssh,输入netstate -tanp,查看ssh服务是否启动,默认端口22.。 注:如果openssh服务,则需下载。输入命令ps -e|grep ssh, 查看如否配有, ssh-agent …...
can 总线入门———can简介硬件电路
文章目录 0. 前言1. CAN简介2. 主流通讯协议对比3. CAN 硬件电路4. CAN 电平标准5. CAN 收发器 0. 前言 博客内容来自B站上CAN总线入门教程视频讲解,博客中的插图和内容均为视频中的内容。视频链接 CAN总线入门教程 1. CAN简介 先来看看一它名字的意思,…...
【重学 MySQL】六十、空间类型
【重学 MySQL】六十、空间类型 空间数据类型的分类空间数据类型的属性空间数据的表示方式空间数据的操作应用场景 在MySQL中,空间类型(Spatial Types)主要用于支持地理特征的生成、存储和分析。这些地理特征可以表示世界上具有位置的任何东西…...
python实现DES算法
DES算法 一、算法介绍1.1 背景1.2 原理1.3 基本功能函数1.3.1 初始置换函数 I P IP IP1.3.2 f f f 轮函数1.3.3 逆初始置换函数 I P − 1 IP^{-1} IP−1 1.4 子密钥的生成 二、代码实现2.1 子密钥生成实现2.2 DES加解密实现2.3 完整代码 三、演示效果 一、算法介绍 1.1 背景…...
基于LORA的一主多从监测系统_框架搭建
第一节、框架搭建 打开CubeMAX,选择好芯片,进行基础配置 第一步、先配置时钟源 第二步、配置SYS选项 配置debug口以及计数器源,我这里选择TIM1 第三步、选择I2C接口 配置如下即可,默认配置不用改 第四步、串口选择 我们这里使…...
优化理论及应用精解【25】
文章目录 优化学习率调度1. 阶梯衰减(Step Decay)2. 余弦退火(Cosine Annealing)3. 多项式衰减(Polynomial Decay)4. 指数衰减(Exponential Decay)总结 梯度弥散效应 参考文献 优化 …...
贝锐蒲公英网盘首发,秒建私有云,高速远程访问
虽然公共网盘带来了不少便利,但是大家对隐私泄露和重要数据泄密的担忧也随之增加。如果想要确保数据安全,自建私有云似乎是一条出路,然而面对搭建私有云的复杂步骤,许多人感到力不从心,NAS设备的成本也往往让人望而却步…...
[ 蓝桥 ·算法双周赛 ] 第 19 场 小白入门赛
🔥博客介绍: EvLast 🎥系列专栏: <<数据结构与算法>> << 算法入门>> << C项目>> 🎥 当前专栏: << 算法入门>> 专题 : 帮助小白快速入门算法竞赛 👍…...
HTML+CSS基础 第二季课堂笔记
一、列表 列表都不是单打独斗的,通常都是一组标签组成 1 无序列表 作用:定义一个没有顺序的列表结构 由两个标签组成,ul(容器级标签),li(容器级) ul:英文ulordered …...
【Easy RL】Easy RL蘑菇书全书学习笔记
【Easy RL】Easy RL蘑菇书全书学习笔记 第一章 强化学习基础1.1 强化学习概述监督学习强化学习与监督学习的不同之处二者的区别总结强化学习的特征强化学习的优越性预演(rollout)和 轨迹(trajectory)的概念端到端的概念深度强化学…...
JavaWeb(二)
Servlet开发技术 [外链图片转存中…(img-Cnu8X2V4-1728026684827)] 简述Servlet的创建过程? package servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; …...
【C++】--类和对象(2)
👌个人主页: 起名字真南 👆个人专栏:【数据结构初阶】 【C语言】 【C】 目录 1 类的默认成员函数2 构造函数3 析构函数4 拷贝构造5 赋值运算符重载5.1 运算符重载5.2 赋值运算符的重载 1 类的默认成员函数 默认成员函数就是用户没有显示实现,…...
最新BurpSuite2024.9专业中英文开箱即用版下载
1、工具介绍 本版本更新介绍 此版本对 Burp Intruder 进行了重大改进,包括自定义 Bambda HTTP 匹配和替换规则以及对扫描 SOAP 端点的支持。我们还进行了其他改进和错误修复。 Burp Intruder 的精简布局我们对 Burp Intruder 进行了重大升级。现在,您可…...
C++ 观察者模式
观察者模式(Observer Pattern)是一种行为设计模式,用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时,它的所有依赖对象都会得到通知并自动更新。 在观察者模式中,主题和观察者之间是松耦合…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
