当前位置: 首页 > news >正文

ROS 点云格式分析与应用

Pointcloud2 与 PCL点云

ROS 的 PointCloud2 是灵活的容器

PointCloud2 是 ROS 定义的消息类型,属于ROS生态,目的是为不同传感器(如激光雷达、深度相机)提供一种通用的点云数据传输格式。
PointCloud2 是一个“通用包装器”,允许任意字段(如 x, y, z, intensity, ring, time),因为不同厂商的激光雷达(Velodyne、Ouster、Livox)输出的数据字段可能不同。

PCL 的标准点类型是固定的

PCL 是一个独立的点云处理库,它提供了点云的数据结构(如 pcl::PointCloud)和算法(滤波、配准、分割等),但并非所有 ROS 的点云字段都能直接映射到 PCL 的标准点类型,实际应用时通常需要自定义扩展点云格式。PCL 默认提供的点类型(如 pcl::PointXYZI)是预定义的常用结构,仅包含最常见字段(如 x, y, z, intensity)。这是因为:

  • 性能优化:固定内存布局(如 Eigen::Vector4f 对齐)可以提高算法效率。
  • 标准化:大多数PCL算法(如 ICP、VoxelGrid)假设点云具有统一格式。

PointCloud2 格式分析

以 ROS2 为例,在终端中输入 ros2 interface show sensor_msgs/msg/PointCloud2 得到可以看到 ROS 系统中 PointCloud2 点云格式如下:

# This message holds a collection of N-dimensional points, which may
# contain additional information such as normals, intensity, etc. The
# point data is stored as a binary blob, its layout described by the
# contents of the "fields" array.
#
# The point cloud data may be organized 2d (image-like) or 1d (unordered).
# Point clouds organized as 2d images may be produced by camera depth sensors
# such as stereo or time-of-flight.# Time of sensor data acquisition, and the coordinate frame ID (for 3d points).
std_msgs/Header headerbuiltin_interfaces/Time stampint32 secuint32 nanosecstring frame_id# 2D structure of the point cloud. If the cloud is unordered, height is
# 1 and width is the length of the point cloud.
uint32 height
uint32 width# Describes the channels and their layout in the binary data blob.
PointField[] fieldsuint8 INT8    = 1uint8 UINT8   = 2uint8 INT16   = 3uint8 UINT16  = 4uint8 INT32   = 5uint8 UINT32  = 6uint8 FLOAT32 = 7uint8 FLOAT64 = 8string name      #uint32 offset    #uint8  datatype  #uint32 count     #bool    is_bigendian # Is this data bigendian?
uint32  point_step   # Length of a point in bytes
uint32  row_step     # Length of a row in bytes
uint8[] data         # Actual point data, size is (row_step*height)bool is_dense        # True if there are no invalid points
  • header 字段用于存储点云时间戳以及 frame_id。
  • height 字段用于表示雷达的线程数量。
  • width 字段用于表示雷达每个线程的点数量。
  • field 字段用于声明每个点有哪些属性。数据类型为 PointField[] 数组,没有规定数组大小,因为有的点云可能有XYZI四个属性,而有的点云有XYZIRT六个属性。其中前8行
    uint8 INT8    = 1
    uint8 UINT8   = 2
    uint8 INT16   = 3
    uint8 UINT16  = 4
    uint8 INT32   = 5
    uint8 UINT32  = 6
    uint8 FLOAT32 = 7
    uint8 FLOAT64 = 8
    
    是类型枚举,并不占用每个实例的内存空间,fields 的每个成员只有 name, offset, datatype, count四个属性占用内存空间。name表示成员名称;offset 表示内存偏移量,假如一个点占据了一定大小的内存,offset就表示从这块内存的第几个字节开始;datatype 表示成员的类型,值为前面列举的八个枚举之一;count表示这个成员所包含的元素数量,比如x只包含了一个元素,rgb包含了三个元素。
    # 单个点的内存布局(共12字节):
    字节0-3:   x 的数据  ← offset=0 指向这里
    字节4-7:   y 的数据  ← offset=4 指向这里
    字节8-11:  z 的数据  ← offset=8 指向这里
    
    举个例子:
    fields[0]: name="x", offset=0, datatype=FLOAT32, count=1
    fields[1]: name="y", offset=4, datatype=FLOAT32, count=1
    fields[2]: name="z", offset=8, datatype=FLOAT32, count=1
    
    表示这个点云的每个点都有 x, y, z 三个属性,单点数据块中的第0字节开始是x字段,第4字节开始是y字段,第8字节开始是z字段,数据类型均为 float32,都只包含了一个元素。
  • is_bigendian 字段表示点云字节数据在内存中的存储顺序,用于保证跨平台兼容性。
  • point_step 表示一个点占据了多少字节。
  • row_step 表示一个线程的点占据了多少字节,可由以下公式计算:row_step = width * point_step
  • data 储存实际的点云的数据,是一个扁平化的字节数组,通过前面的 fieldspoint_step 解析具体字段。
  • is_dense 是否剔除了无效点。

对于现代雷达,点云中点的时间戳有如下约定俗成:uint32 类型与字段名称 t 搭配,表示相对于点云起始帧的微秒偏移,使用 32 位无符号整数可以表示大约 71 分钟的时常。float 类型与字段名称 time 搭配,表示相对于点云帧起始时间的秒数,是许多软件处理中的内部表示,直观,易于进行插值等数学运算。double 类型与字段名称 timestamp 搭配,通常代表绝对时间戳,最常见的是Unix时间戳,即自1970年1月1日00: 00: 00 UTC以来的秒数,这是更现代的、追求高精度和绝对时间的系统,timestamp名字明确表达了它是时间戳而不是相对偏移。

自定义 PCL 点云格式

PCL 预定义点云格式仅包含最常见字段(x, y, z, intensity),实际应用中处理不同 LiDAR 点云时通常需要自定义点云格式。

// 定义点云结构
struct PointXYZIRT
{
PCL_ADD_POINT4D; // XYZ + padding
float intensity;
uint16_t ring;
double timestamp;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
} EIGEN_ALIGN16;// 注册点云到pcl
POINT_CLOUD_REGISTER_POINT_STRUCT(
PointXYZIRT,
(float, x, x)
(float, y, y)
(float, z, z)
(float, intensity, intensity)
(uint16_t, ring, ring)
(double, timestamp, timestamp)
);

需要注意的是 x, y, z, i 在不同雷达的驱动程序中定义的格式虽然可能不是 float, 但其通过 ROS 发送时,还是float, 因此需要通过 float 接收。其它自定义变量的类型与名称根据实际情况而定。

接收 sensor_msgs::PointCloud2 转换为 pcl::PointCloud 点云

这里以ROS C++程序为例:

void pointCloudCallback(const sensor_msgs::PointCloud2ConstPtr& msg)
{
pcl::PointCloud<PointXYZIRT> cloud;
pcl::fromROSMsg(*msg, cloud);
}
http://www.jsqmd.com/news/441166/

相关文章:

  • Qwen3-Reranker-8B在MySQL数据检索中的优化实践
  • Windows系统HEIC缩略图显示解决方案:从问题诊断到技术实现
  • 3个技术突破:InVideo如何解决UE5视频处理的核心挑战
  • 基于Agent的智能客服系统实战:从架构设计到性能优化
  • 寻音捉影·侠客行镜像免配置:自动检测硬件并启用最佳后端(ONNX Runtime/OpenVINO)
  • vue如何做分页
  • ChatGPT与Chatbot开发入门:从零构建你的第一个智能对话系统
  • 解决VS Code中cl.exe构建调试活动文件仅在Developer Command Prompt中可用的技术方案
  • Gemma-3-270m开源大模型教程:Ollama平台下模型选择与交互界面详解
  • 快速搭建ResNet18图像识别:CPU版部署教程,支持Web可视化交互
  • VisualGGPK2完全指南:游戏资源包管理与高效编辑全攻略
  • ollama部署QwQ-32B多场景落地:科研辅助、CTF解题、数学证明应用
  • 万象熔炉·丹青幻境风格迁移效果:将照片转化为Latex技术插图风格
  • SOONet模型Java面试题精讲:如何设计一个视频片段检索系统
  • 拯救失灵键盘:KeyboardChatterBlocker让旧设备焕发新生
  • 颠覆式视频提取:3步实现抖音无水印资源的高效获取方案
  • Swift-All快速体验:5分钟完成大模型推理,效果实测分享
  • 基于multisim的简易日历逻辑电路设计
  • CHORD-X视觉战术指挥系统多模态Agent构建:自主感知与决策
  • 物联网设备国密升级失败率高达67%?基于237款主流MCU的C语言国密库移植成功率数据报告(含STM32L4+GD32E系列实测对比)
  • 基于multisim的简易工序逻辑电路设计
  • 【参数辨识】基于遗传算法和系统辨识的无人机自动驾驶仪参数优化框架matlab实现
  • FireRedASR Pro与自研模型融合:利用Agent框架构建智能语音助手
  • 如何解决机械键盘连击问题:KeyboardChatterBlocker实用指南
  • Chatbot 使用详解:从架构设计到生产环境最佳实践
  • APK Editor Studio v1.7.2:跨版本适配引擎引领Android逆向工程新范式
  • 键盘连击顽疾终结指南:KeyboardChatterBlocker如何让旧键盘焕发新生?
  • Qwen3开源模型本地部署进阶:OpenClaw社区方案实践
  • WPS-Zotero开源工具:提升学术写作效率的文献管理解决方案
  • KeyboardChatterBlocker:智能防抖终结机械键盘连击 | 程序员与设计师必备工具