介绍

LidarView是由Kitware开发的针对激光雷达点云展示、数据分析处理的3D软件,它是一个开源的项目,目前适配的雷达厂商有Velodyne、Ouster、HeSai、速腾聚创等;这个软件的前身是paraview,也是一个开源项目;LidarView通过复用paraview的核心组件来实现获取、解析、处理、渲染、展示3D点云数据,其实它本身的代码量并不多,整个框架有点类似于前后端实现:前端是用python写的,后端是调用C++来完成数据获取、处理、渲染、展示;想要定制开发LidarView软件,首先要解决解析器的问题,根据雷达厂商的点云协议开发对应的解析器,解析器的路径:Plugins\XxxPlugin\Plugin\XxxLidar\XxxPacketInterpreter

虚函数

关键的几个虚函数:

1
2
3
4
5
6
7
8
9
10
11
void LoadCalibration(const std::string& filename) override;

bool PreProcessPacket(unsigned char const * data, unsigned int dataLength, fpos_t filePosition = fpos_t(), double packetNetworkTime = 0, std::vector<FrameInformation>* frameCatalog = nullptr) override;

bool IsLidarPacket(unsigned char const * data, unsigned int dataLength) override;

void ProcessPacket(unsigned char const * data, unsigned int dataLength) override;

std::string GetSensorInformation(bool shortVersion = false) override;

vtkSmartPointer<vtkPolyData> CreateNewEmptyFrame(vtkIdType numberOfPoints, vtkIdType prereservedNumberOfPoints = 60000) override;

加载原始的标定配置文件,这个文件是LiDAR初始校正文件,跟算法密切相关,默认是用JSON格式的数据文件

1
void LoadCalibration(const std::string& filename) override;

包数据预处理,将buffer转化成数据包,获取分帧信息

1
bool PreProcessPacket(unsigned char const *data, unsigned int dataLength, fpos_t filePosition = fpos_t(), double packetNetworkTime = 0, std::vector<FrameInformation> *frameCatalog = nullptr) override;

包数据校验(跟点云协议密切相关)

1
bool IsLidarPacket(unsigned char const * data, unsigned int dataLength) override;

packet解包,解析成可视化的VTK三位数据

1
void ProcessPacket(unsigned char const * data, unsigned int dataLength) override;

自定义解析器名称

1
std::string GetSensorInformation(bool shortVersion = false) override;

给新的一帧数据划定缓冲

1
vtkSmartPointer<vtkPolyData> CreateNewEmptyFrame(vtkIdType numberOfPoints, vtkIdType prereservedNumberOfPoints = 60000) override;

数据结构

原始点云帧的数据结构分为三个部分:header、blocks、tail

1
2
3
4
5
6
7
8
#pragma pack(push, 1)
//! @brief class representing the Xxx Packet
struct XxxPacket {
XxxHeader header;
XxxBlock blocks[Xxx_BLOCK_NUM];
XxxTail tail;
};
#pragma pack(pop)

点云3D数据容器:

1
2
3
4
5
6
7
8
9
10
11
vtkSmartPointer<vtkPoints> Points;
vtkSmartPointer<vtkDoubleArray> PointsX;
vtkSmartPointer<vtkDoubleArray> PointsY;
vtkSmartPointer<vtkDoubleArray> PointsZ;
vtkSmartPointer<vtkDoubleArray> Azimuth;
vtkSmartPointer<vtkDoubleArray> Elevation;
vtkSmartPointer<vtkUnsignedIntArray> PointID;
vtkSmartPointer<vtkUnsignedCharArray> LaserID;
vtkSmartPointer<vtkUnsignedCharArray> Intensities;
vtkSmartPointer<vtkDoubleArray> Timestamps;
vtkSmartPointer<vtkDoubleArray> Distances;

点云数据类型详解

变量名 类型 备注
Points vtkPoints 三维点集合
PointsX vtkDoubleArray X轴坐标(笛卡尔)
PointsY vtkDoubleArray Y轴坐标(笛卡尔)
PointsZ vtkDoubleArray Z轴坐标(笛卡尔)
Azimuth vtkDoubleArray 方位角
Elevation vtkDoubleArray 俯仰角
PointID vtkUnsignedIntArray 点序号
LaserID vtkUnsignedIntArray 激光模组序号
Intensities vtkUnsignedIntArray 点的反射强度
Timestamps vtkDoubleArray 帧时间戳
Distances vtkDoubleArray 点的距离

流程分析

整个解析器的数据处理流程如下:

  1. unsigned char const * data
  2. 自定义packet
  3. 解析时间戳信息
  4. 解析分帧信息
  5. 极坐标数据转化位笛卡尔坐标系数据
  6. 解析自定义点云数据(laserID、intensity、帧ID等)
  7. 往vtkPolyData类型里边填充三维坐标信息

流程图如下:

graph TD
    A[开始] --> B[1. 输入原始数据<br/>unsigned char const * data];
    B --> C[2. 解析自定义packet<br/>识别数据包结构];
    C --> D[3. 解析时间戳信息<br/>提取时间数据];
    D --> E[4. 解析分帧信息<br/>确定数据帧边界];
    E --> F[5. 极坐标转笛卡尔坐标<br/>转换计算];
    F --> G[6. 解析自定义点云数据<br/>提取laserID, intensity, 帧ID];
    G --> H[7. 填充vtkPolyData<br/>构建可视化数据结构];
    H --> I[结束];
    
    %% 处理细节说明
    subgraph "数据解析阶段"
        C
        D
        E
        G
    end
    
    subgraph "坐标转换阶段"
        F
    end
    
    subgraph "可视化构建阶段"
        H
    end
    
    %% 技术细节注释
    B -.->|"原始二进制数据流"| C;
    F -.->|"x=r·sinθ·cosφ<br/>y=r·sinθ·sinφ<br/>z=r·cosθ"| G;
    G -.->|"包含:<br/>- 三维坐标(x,y,z)<br/>- laserID<br/>- 强度值<br/>- 帧ID<br/>- 时间戳"| H;

下里巴人
海纳百川,文以载道
hywing技术自留地
总访问 113701 次 | 本页访问 326