订阅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)是一种行为设计模式,用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时,它的所有依赖对象都会得到通知并自动更新。 在观察者模式中,主题和观察者之间是松耦合…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...

表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...