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

相机-雷达标定(一):禾赛 QT128C2X 雷达点云采集程序封装说明

文档目的

说明qt_capture程序如何封装禾赛HesaiLidar_SDK_2.0,实现"点击按钮采集一帧点云"的功能。帮助快速理解架构、维护和扩展。


一、程序概览

功能

  • 启动后自动连接禾赛 QT128C2X 雷达
  • 实时显示帧数、点数、连接状态
  • 点击"采集一帧"按钮 → 保存当前一帧点云为 PCD 文件

文件结构

qt_capture/ ├── CMakeLists.txt # 构建配置(链接 SDK + Qt) ├── config.ini # 雷达连接配置(IP/端口) ├── main.cpp # 程序入口 ├── MainWindow.h/.cpp # 主窗口界面 ├── LidarWorker.h/.cpp # SDK 封装层(核心) └── pointcloud_output/ # PCD 输出目录

二、整体架构

程序采用双线程 + 信号槽架构,UI 与数据采集分离:

┌─────────────────────────────────────────────────┐ │ 主线程 (UI 线程) │ │ │ │ MainWindow │ │ ├── 界面控件 (按钮/状态标签) │ │ ├── 按钮点击 → 调用 worker->requestCapture() │ │ └── 接收信号 → 更新界面 │ │ │ └───────────────────▲─────────────────────────────┘ │ Qt 信号/槽 (跨线程队列) ┌───────────────────┴─────────────────────────────┐ │ 工作线程 (QThread) │ │ │ │ LidarWorker ← SDK 封装层 │ │ ├── 管理一个 HesaiLidarSdk 实例 │ │ ├── 注册回调函数 │ │ └── 通过 emit 信号通知主线程 │ │ │ │ ┌────────────────────┐ │ │ │ HesaiLidarSdk │ │ │ │ (禾赛官方 SDK) │ │ │ │ 内部自带收数线程 │ │ │ └────────────────────┘ │ └─────────────────────────────────────────────────┘

为什么需要工作线程?

禾赛 SDK 的Init()Start()会阻塞等待 PTC 连接、加载修正文件。如果放在主线程,界面会卡死。用QThread+moveToThreadLidarWorker移到工作线程执行,UI 保持流畅。


三、LidarWorker 封装层(核心)

LidarWorker是整个封装的关键,把禾赛 SDK 包成三个简单操作:

3.1 对外接口

接口类型作用
start()槽函数启动 SDK:加载配置 → 初始化 → 连接雷达
requestCapture()槽函数请求保存下一帧(设置标志位)
frameUpdated信号每帧触发,通知 UI 更新帧数/点数
frameCaptured信号一帧保存完成,通知 UI 弹提示
statusChanged信号连接状态变化通知

3.2 关键成员

classLidarWorker:publicQObject{private:HesaiLidarSdk<LidarPointXYZICRT>*sdk_;// 禾赛 SDK 实例std::atomic<bool>capture_flag_;// 采集请求标志(线程安全)std::string output_dir_;// PCD 输出目录};

3.3 启动流程start()

start() │ ├─ 1. 读 config.ini → DriverParam ├─ 2. 创建 SDK 实例:sdk_ = new HesaiLidarSdk() ├─ 3. 初始化:sdk_->Init(param) ├─ 4. 注册点云回调:sdk_->RegRecvCallback(...) ├─ 5. 启动:sdk_->Start() ← SDK 内部开线程收 UDP └─ 6. emit statusChanged("已连接")

四、核心机制:标志位 + 回调

这是整个封装最巧妙的设计。

4.1 问题

禾赛 SDK 是持续推数据模型 — 启动后每秒发 10 帧到回调函数。但用户需求是点击才存一帧

4.2 解决方案

用一个原子标志位capture_flag_作为"开关":

// ① 用户点击按钮 → 只设标志(瞬时操作,不阻塞)voidLidarWorker::requestCapture(){capture_flag_=true;}// ② SDK 每收到一帧都进这里voidLidarWorker::onFrameCallback(constLidarDecodedFrame&frame){// 每帧都更新状态栏(实时性)emitframeUpdated(frame.points_num,frame.frame_index);// 检查是否有采集请求if(capture_flag_.load()&&frame.points_num>0){capture_flag_=false;// 立刻复位,防止存多帧QString path=saveFrameAsPCD(frame);emitframeCaptured(path,frame.points_num);// 通知主线程}}

4.3 工作时序

时间 → SDK 后台: ─帧─帧─帧─帧─帧─帧─帧─帧─帧─帧─→ (每秒10帧) ↓ 回调检查: flag=0 flag=0 flag=1 flag=0(存!) flag=0 ... ↑ 用户点击: 点击按钮→flag=1 ↓ emit frameCaptured → UI弹框

优点

  • SDK 持续运行,无需反复建连/断开
  • 点击后最多等 100ms(下一帧)即保存
  • 标志位用std::atomic保证线程安全

五、跨线程通信

SDK 回调运行在SDK 内部线程,界面在主线程。通过 Qt 信号槽安全通信:

// MainWindow 构造函数中连接信号connect(worker_,&LidarWorker::frameUpdated,this,&MainWindow::onFrameUpdated,Qt::QueuedConnection);// ← 关键:跨线程自动排队

工作原理

Qt::QueuedConnection让信号在接收线程(主线程)的事件队列里执行,Qt 自动处理线程安全。因此回调函数里可以直接emit,不必担心 UI 操作的线程冲突。


六、PCD 保存

saveFrameAsPCD()把一帧点云写成标准 PCD v0.7 格式:

// 写 PCD 头部ofs<<"VERSION 0.7\n"<<"FIELDS x y z intensity confidence ring\n"<<"WIDTH "<<frame.points_num<<"\n"<<"DATA ascii\n";// 遍历点数组for(uint32_ti=0;i<frame.points_num;++i){ofs<<pts[i].x<<" "<<pts[i].y<<" "<<pts[i].z<<" "<<(int)pts[i].intensity<<" "<<(int)pts[i].confidence<<" "<<pts[i].ring<<"\n";}

文件命名frame_<时间戳>_<序号>.pcd,避免重复点击覆盖。


七、界面交互流程

程序启动 │ ├─ 创建 LidarWorker,移到工作线程 ├─ 线程启动 → worker->start() │ └─ 连接雷达(按钮禁用,状态:"正在连接...") │ ├─ 收到第一帧 → emit frameUpdated │ └─ 按钮启用,状态:"已连接",显示帧数/点数 │ ├─ 用户点击按钮 → worker->requestCapture() │ └─ 状态:"采集请求已发送,等待下一帧..." │ ├─ 下一帧回调 → 存 PCD → emit frameCaptured │ └─ 弹出成功框,显示文件路径 │ └─ 用户关闭窗口 → 退出工作线程 → SDK 停止

八、构建与运行

依赖

组件版本
Qt5.15.2 (msvc2019_64)
Visual Studio2019/2022
HesaiLidar_SDK_2.0v2.0.12

编译

cdqt_capture/build cmake-G"Visual Studio 17 2022"-Ax64..cmake--build.--configRelease

运行

cdbuild/ReleasesetPATH=C:\Qt\5.15.2\msvc2019_64\bin;%PATH% qt_capture.exe

九、常见问题

问题原因解决方案
界面中文乱码源文件编码CMake 加/utf-8选项,源文件存 UTF-8 BOM
一直显示"正在连接"端口被占用或雷达异常taskkill /IM qt_capture.exe /F;重启雷达
收不到数据雷达未发数据或端口不对用 PowerShell UDP 监听验证;检查 config.ini 端口
关闭后下次连不上僵尸进程占端口用窗口 X 正常关闭,勿强制结束

十、扩展指南

连续保存多帧

修改回调,去掉capture_flag_复位或加帧数计数:

if(capture_flag_){saveFrameAsPCD(frame);if(++saved_count_>=target_count_){// 存够 N 帧capture_flag_=false;}}

添加实时可视化

MainWindow添加 OpenGL Widget,收到frameCaptured信号后渲染点云(需引入 PCL 或自写 OpenGL)。

改用其他雷达型号

只需改config.ini中的device_ip_addressudp_port和 correction 文件路径,代码无需改动(SDK 自动识别协议)。

http://www.jsqmd.com/news/1250077/

相关文章:

  • 2026 年至今,桂东可靠的无机纤维棉喷涂施工定做厂家找哪家,别再用传统材料!揭秘无机纤维棉喷涂的惊人效率-祥实无机纤维喷涂 - 行业严选官
  • 2026金华防水补漏维修公司口碑实测推荐 专业防水公司排名推荐(2026年7月防水补漏最新TOP权威排名) - 鼎万建筑修缮
  • 制造业如何通过DeepSeek推广获客?哪家公司可以做DeepSeek推广广告? - 2027品牌AI展
  • KeyStone I处理器电源完整性设计:滤波与去耦电容实战指南
  • 融资平台引导_finta-hello-world
  • 【2019-12-21】可信执行环境TEE介绍
  • OpenCvSharp读取、显示和写入图像
  • 抖音小店一件代发如何找蓝海商品?新手选品和类目竞争分析方法 - 电商分享
  • day7
  • 2026 抖音去水印工具怎么选?实测这几款解析快又合规 - 免费软件工具方法教程
  • 深圳猎头公司收费标准大揭秘:2026深圳企业HRD与CFO必备招聘手册
  • 有没有一键转换智谱清言到 Word 的工具?AI 导出鸭一站式完成智谱清言内容转 Word,高效省心
  • 2026金华漏水维修公司严选推荐盘点 - 鼎万建筑修缮
  • AI大模型开发学习路线:从Python基础到多模态实战
  • 2026美国留学中介测评:案例多的高端留学中介有哪些 - 2027品牌AI展
  • 传统 RPA 技术瓶颈深度解析:基于大模型 Agent 的替代路径与落地实践——企业智能自动化范式迁移指南
  • 【成都信息工程大学主办 | IEEE(ISBN: 979-8-3195-3661-7)出版 | EI Compendex、Scopus检索】2026年数据与信息系统国际学术会议(DIS 2026)
  • Reliable Curation of EHR Dataset via Large Language Models under Environmental Constraints
  • 20MB,管理70+种数据库!DBX太好用了!
  • Android CameraServer架构理解
  • 2026年工业超声波清洗机采购测评:巴克选型指南 - 资讯纵览
  • 2026重庆南川管道疏通避坑指南 - 余生黄金回收
  • GDB调试C++段错误与内存分配失败:从原理到实战
  • 指纹浏览器生态闭环:如何设计灵活的插件系统让第三方扩展浏览器功能?
  • 深入解析TI TMS470R1A256:ARM7TDMI内核与实时控制外设实战指南
  • 企业级基础软件领域中远超国外的国货
  • 2026 年平鲁口碑好的景观闸门订制厂家推荐几家,揭秘隐藏的流量密码:景观闸门如何改变你的视野? - 企业推荐官【认证】
  • 干了3年运维,我转行了网络安全,聊一下我是怎么想的!
  • 在昆明出手旧金首饰注意什么?称重、验金、报价避坑全流程指南 - 日常比对手册
  • shared_ptr的一个最大的陷阱是循环引用,如何解决循环引用