如何仅通过PCL 1.8实现ROS sensor_msgs::PointCloud2到pcl::PointCloud2的转换
解决ROS sensor_msgs::PointCloud2 转独立PCL 1.8的pcl::PointCloud2问题
嘿,我之前在项目里也碰到过一模一样的情况——为了用上PCL 1.8的新特性放弃了ros_pcl包,一开始也卡在上云转换这一步。其实不用依赖ros_pcl的桥接工具,我们可以直接手动完成转换,因为这两个类型的底层结构几乎是一致的,只是命名空间不同而已。
核心思路
sensor_msgs::PointCloud2 和 pcl::PointCloud2 的数据结构高度匹配,都包含头信息、点云尺寸、字段定义、原始数据缓冲区这些部分。我们只需要逐个字段把ROS的消息内容映射到PCL的结构体里就行,不需要复杂的解析逻辑。
具体实现代码
你可以直接用这个转换函数:
#include <sensor_msgs/PointCloud2.h> #include <pcl/point_cloud.h> #include <cstring> // 用于memcpy void rosMsgToPCLPointCloud2(const sensor_msgs::PointCloud2& ros_cloud, pcl::PointCloud2& pcl_cloud) { // 拷贝头信息 pcl_cloud.header.frame_id = ros_cloud.header.frame_id; pcl_cloud.header.stamp = ros_cloud.header.stamp.toNSec(); // ROS时间转纳秒,适配PCL的时间格式 // 拷贝点云基本尺寸 pcl_cloud.width = ros_cloud.width; pcl_cloud.height = ros_cloud.height; pcl_cloud.is_dense = ros_cloud.is_dense; pcl_cloud.point_step = ros_cloud.point_step; pcl_cloud.row_step = ros_cloud.row_step; // 拷贝字段定义 pcl_cloud.fields.resize(ros_cloud.fields.size()); for (size_t i = 0; i < ros_cloud.fields.size(); ++i) { pcl_cloud.fields[i].name = ros_cloud.fields[i].name; pcl_cloud.fields[i].offset = ros_cloud.fields[i].offset; pcl_cloud.fields[i].datatype = ros_cloud.fields[i].datatype; pcl_cloud.fields[i].count = ros_cloud.fields[i].count; } // 拷贝原始数据缓冲区 pcl_cloud.data.resize(ros_cloud.data.size()); memcpy(pcl_cloud.data.data(), ros_cloud.data.data(), ros_cloud.data.size() * sizeof(uint8_t)); }
注意事项
- 时间戳转换:ROS的
ros::Time转成PCL需要的纳秒级整数,这里用toNSec()刚好匹配。 - 字段兼容性:ROS点云的字段类型和PCL的枚举值是等价的(比如
sensor_msgs::PointField::FLOAT32和pcl::PCLPointField::FLOAT32底层值相同),所以直接赋值不会有问题。 - 自定义字段:如果你的点云有自定义字段,这个函数也能直接处理,只要ROS和PCL的字段定义一致就行。
用这个函数之后,你就能把ROS的点云消息转换成PCL 1.8的pcl::PointCloud2,然后就可以尽情使用PCL的新特性处理了。
内容的提问来源于stack exchange,提问作者Hakaishin
相关产品推荐
相关产品推荐

