地平线征程5域控试用报告:从零搭建激光雷达3D感知
一、背景与目标
评估地平线征程5域控制器在自动驾驶激光雷达感知场景下的开发体验与推理能力。核心目标:从零搭建一条 16 线激光雷达 3D 目标检测的完整工程链,包括数据收发、模型部署、BPU 推理、后处理解码与精度验证。
技术路线:VLP-16 协议 UDP 数据流 → 点云解包与累积 → 体素化预处理 → CenterPoint + PointPillars 模型 BPU 推理(hbDNN API)→ Heatmap 解码 + Rotated IoU NMS → 3D 边界框输出。
二、硬件与软件环境
项 | 详情 |
|---|
域控芯片 | 地平线征程5(J5),BPU 架构 bayes |
SDK | Open Explorer v1.1.77 (2024-08-02) |
推理运行时 | HBRT 3.15.53.0,DNN Runtime 1.24.3,BPU Platform 1.3.3 |
开发环境 | Docker 容器(openexplorer/ai_toolchain_ubuntu_20_j5)+ VS Code Remote |
交叉编译器 | GCC Linaro 9.3.0 / GCC Ubuntu 9.3 x86_64 → aarch64 |
检测模型 | CenterPoint + PointPillars(nuScenes 训练),7.2MB .hbm |
雷达协议 | Velodyne VLP-16,1248 字节/包,UDP 端口 2368 |
三、SDK 工程架构
Open Explorer SDK 按功能分为三大模块:bsp/(系统镜像与驱动)、ddk/package/(板端/宿主机运行时组件)、ddk/samples/(模型评测、工具链、DSP 示例)。
核心亮点是插件化 Pipeline 架构——InputPlugin → WorkflowPlugin → OutputPlugin,JSON 驱动配置,支持 J3/J5/X5 多平台。预处理可下沉到 VDSP 加速,推理通过简洁的 hbDNNInfer API 完成。
四、开发过程
4.1 激光雷达收发程序
lidar_receiver:创建 UDP Socket 绑定 2368 端口,解析 VLP-16 1248 字节数据包——42 字节头 + 12 个 100 字节数据块 + 4 字节时间戳 + 2 字节厂商标识。结合 16 线垂直角度表进行极坐标 → 笛卡尔坐标转换,支持 --save 导出 PCD 二进制点云。
lidar_sender:模拟 10Hz 扫描频率,精确控制发包间隔(~666μs/包,150 包/圈完成 360° 扫描)。可配置 30m×30m 房间场景,含地面、墙壁和半径 1.5m 的圆柱体障碍物,模拟真实 LiDAR 的距离噪声(±2%)和反射强度衰减。
踩坑:LidarDataBlock 结构体初始仅 68 字节,遗漏了 32 字节填充字段,导致 sizeof(LidarPacket) = 864 ≠ 1248,触发 -Warray-bounds。补齐 pad[32] 后 Packet 正确对齐到 1248 字节。
4.2 交叉编译环境
J5 板为 aarch64 架构,x86 宿主机编译的二进制会报 syntax error: unexpected word。参照项目内 build_ptq_j5.sh 编写 build.sh,通过 LINARO_GCC_ROOT 环境变量自动定位 Linaro 交叉工具链,设置 CC/CXX 指向 aarch64-linux-gnu-gcc/g++。
链接依赖:libdnn.so 间接依赖 libcnn_intf.so(CNN 硬件接口)和 libhbmem.so(BPU 内存管理),需从 vdsp_rpc_sample/deps/aarch64/system/lib/ 引入,并在 CMakeLists 中添加 cnn_intf hbmem 链接。
4.3 模型确认
在 J5 板上通过 strings model.hbm | head -n 30 确认:
模型 7.2MB,BPU 架构 bayes,完全匹配 J5 平台。
4.4 推理程序实现
将全流程串联为独立程序 lidar_infer(~600 行 C++):
数据输入:支持 UDP 实时流(--ip)和离线文件(--file)两种模式。UDP 模式以 100ms 时间窗口累积点云帧,文件模式直接读 .bin。
预处理:参照 qat_centerpoint_preprocess_method.cc 实现 ARM 端体素化——GenVoxel 生成 Pillar 索引和粗体素数据,GenFeatureDim5 进行归一化(以 input tensor 的 scale 为因子),TransposeDim5 转置为 5×20×40000 布局。
BPU 推理:hbDNNInitializeFromFiles 加载 .hbm → hbDNNInfer 提交 → hbDNNWaitTaskDone 等待。输入 2 路 tensor(coords + features),输出 36 路 tensor。
后处理:对 6 个检测头分别进行 heatmap sigmoid → top_k 筛选 → reg/height/dim/rot/vel 反量化解码 → 坐标范围过滤 → Rotated IoU NMS,输出 (x, y, z, w, l, h, rot, vel_x, vel_y, score, class) 的 3D 边界框。
4.5 关键踩坑汇总
# | 问题 | 根因 | 解决 |
|---|
1 | Packet 大小不匹配 | 协议结构体缺 32B 填充 | 补 pad[32],Block=100B |
2 | J5 无法运行 x86 二进制 | 架构不匹配 | Linaro aarch64 交叉编译 |
3 | 链接 undefined reference | 缺 cnn_intf、hbmem | 添加 system/lib 路径和链接 |
4 | 36 输出仅处理 3 个 head | head < 3 hardcode | 改为 head < 6 |
5 | 特征 scale 写死 1.0 | 未从模型读取 | 自动读 tensor[1].scale |
6 | -Wreorder 初始化顺序 | 成员声明与初始化列表不一致 | 调整声明顺序 |
五、测试验证
5.1 模拟数据环路联调
用 lidar_sender 模拟 30m×30m 房间场景,J5 本地回环:
圆柱体被误判为 car、z 坐标偏负(-2.6 ~ -3.0m)、置信度极低(0.10~0.19)。根因是模拟场景非真实道路 + 传感器/车体坐标系不一致。但此测试验证了 UDP 接收 → 体素化 → BPU 推理 → 后处理全链路数据通路正确。
5.2 真实 nuScenes 数据验证
用 SDK 自带的 nuScenes 测试文件 49f8376cd6b34f07b20ed6d5b5b42acd.bin(6MB,150,000 点):
检测统计:
类别 | 数量 | 最高 score | 尺寸范围 (L×W×H) |
|---|
car | 26 | 0.875 | 4.14.9 × 1.82.0 × 1.5~2.0 m |
truck | 2 | 0.284 | 5.15.5 × 2.12.3 × 2.1~2.7 m |
construction_vehicle | 3 | 0.373 | 2.93.9 × 1.82.3 × 2.1~2.9 m |
典型检测:
5.3 精度分析
高置信度(>0.7):9 个,均为 car 类别
中置信度(0.4~0.7):10 个,含 car / construction_vehicle
car 平均尺寸 4.3×1.9×1.6m,与 nuScenes 真值标注一致
z 坐标分布 -1.7 ~ +1.1m,符合车顶 LiDAR 安装高度物理规律
成功区分 car / truck / construction_vehicle 三个类别
不存在明显误检(如将建筑物识别为车辆),漏检率合理
六、性能与总结
指标 | 数值 |
|---|
单帧点云量 | 150,000 点/帧 |
模型大小 | 7.2 MB(.hbm) |
推理耗时 | 预处理(ARM 端)+ BPU 推理(hbDNNInfer) |
运行模式 | UDP 实时流 / 离线 .bin 文件 |
帧率 | ≥10 FPS(100ms 累积窗口 + 推理延迟) |
核心成果:
优点:BPU 推理 API 简洁(三步完成推理)、交叉编译流程标准化、Docker 开发环境一键启动、SDK 内已有丰富的 LiDAR 模型参考实现(CenterPoint / PointPillars / FCOS3D 等)。