)
rplidar_ros源码精读node.cpp主循环如何把原始雷达数据变成ROS话题完整指南【免费下载链接】rplidar_ros项目地址: https://gitcode.com/gh_mirrors/rp/rplidar_rosrplidar_ros 是速腾聚创 RPLIDAR 激光雷达的官方 ROS 驱动包它通过串口、TCP 或 UDP 通道读取雷达输出的原始扫描数据解析成结构化的测距节点后发布为标准sensor_msgs/LaserScan类型的/scan话题供建图、导航等上层功能使用。本文带你精读核心文件node.cpp看它的主循环如何一步步把原始字节流变成ROS 话题。一、项目结构node.cpp 在整个 rplidar_ros 中的位置整个驱动包的分层非常清晰理解这一点是读源码的前提层次关键文件职责ROS 节点层src/node.cpp参数加载、驱动初始化、主循环、发布/scan话题测试客户端src/client.cpp订阅/scan并在终端打印扫描结果用于快速验证驱动接口层sdk/include/sl_lidar_driver.h定义ILidarDriver抽象接口连接、扫描、取数协议解析层sdk/src/dataunpacker/把串口字节流解包成测距节点构建配置CMakeLists.txt编译出rplidarNode和rplidarNodeClient两个可执行文件一句话概括数据链路串口字节流 → SDK 协议解包 → 测距节点数组 → 角度排序/补偿 → LaserScan 消息 → /scan 话题。二、启动准备参数加载与雷达连接进入 src/node.cpp 的main()函数前几件事都在主循环之前完成读取私有参数通过nh_private.param加载串口、波特率、坐标系等参数见 src/node.cpp#L244-L261channel_type通信方式serial/tcp/udpserial_port默认/dev/ttyUSB0serial_baudrateA1/A2 系列用 115200A3 建议 256000frame_id雷达坐标系名字默认laser_frameinverted雷达是否倒装影响角度翻转angle_compensate是否开启角度补偿让点云更均匀scan_frequency扫描频率目标值串口/TCP 默认 10 HzUDP 默认 20 Hz创建通道与驱动根据channel_type分别创建串口、TCP 或 UDP 通道再调用createLidarDriver()和drv-connect()完成连接见 src/node.cpp#L271-L294。读取设备信息与健康检查getRPLIDARDeviceInfo()打印雷达型号、固件版本、序列号checkRPLIDARHealth()检查雷达是否处于自保护状态见 src/node.cpp#L113-L188。启动旋转A 系列直接setMotorSpeed(600)通过 PWM 控制电机S/T 系列则等到抓到第一圈数据后再按scan_frequency*60设置 RPM 转速见 src/node.cpp#L395-L410。开始扫描调用startScan()或按指定scan_mode调用startScanExpress()并把当前扫描模式的us_per_sample换算成每圈点数points_per_circle见 src/node.cpp#L346-L384。三、主循环精读每一圈 360° 扫描的诞生核心就是while (ros::ok())这个无限循环见 src/node.cpp#L395-L471每一轮做四件事1. 抓取一整圈数据grabScanDataHq每轮循环先准备一个 8192 个节点的缓冲数组调用drv-grabScanDataHq(nodes, count)阻塞等待完整的一圈 360° 扫描见 src/node.cpp#L396-L402。这里的一整圈由 SDK 内部保证返回的第一个节点一定是扫描起点同步位为 1所有节点属于同一圈。每个节点是一个 8 字节的紧凑结构定义见 sdk/include/sl_lidar_cmd.h#L272-L278angle_z_q14角度定点数乘以 16384 即 Q14 格式dist_mm_q2距离毫米定点数除以 4 才是真实毫米值quality回波质量高 2 位是同步标志flag标志位2. 角度排序ascendScanData雷达硬件输出点的角度不一定是升序的所以调用drv-ascendScanData(nodes, count)按角度重排见 src/node.cpp#L411这是发布前的关键一步。3. 角度补偿让点云更均匀可选如果开启angle_compensateA1 launch 文件默认开启见 launch/rplidar_a1.launch驱动会创建一个360 * angle_compensate_multiple长度的新数组把每个有效测距点按角度插值填进对应槽位见 src/node.cpp#L415-L440。效果是即使某些角度点缺失发布出去的点云角度分布依然均匀扫描图更平滑。关闭补偿时代码会先找出首尾两个有效节点只发布有效区间内的数据见 src/node.cpp#L441-L458。4. 转换并发布publish_scan最后是publish_scan()函数见 src/node.cpp#L56-L111把原始节点数组转换成LaserScan消息LaserScan 字段来源与计算header.stamp抓数开始时刻start_scan_timeheader.frame_id参数frame_idangle_min / angle_max由节点角度换算弧度且做了π - angle翻转配合inverted参数适配安装方向angle_increment(angle_max - angle_min) / (node_count - 1)scan_time抓一圈实际耗时range_min / range_max固定 0.15 m / 当前扫描模式最大测距ranges[i]dist_mm_q2 / 4.0 / 1000即毫米转米距离为 0 时填infinity表示无回波intensities[i]quality 2取出质量值发布完成后调用ros::spinOnce()处理回调然后进入下一轮循环——如此周而复始/scan话题就以设定的频率持续刷新。 注意ranges中的 0 值距离被转成了infinity这是 RViz 中缺测点不画线的关键也是 ROS 激光雷达消息的惯例写法。四、坐标系与安装理解角度翻转的背景雷达发布的坐标系遵循如下约定frame_id默认laser_frameZ 轴指向外部、Y 轴为雷达 0° 方向。这正是publish_scan里要做M_PI - angle翻转的原因——把雷达私有角度定义映射到 ROS 标准激光雷达角度约定。A1 系列的坐标系定义如下图所示五、上手验证从零跑通 /scan 话题以最经典的 A1 为例两条命令就能验证主循环的完整产出命令来自 README.md# 启动雷达节点并用 RViz 可视化launch 文件见 launch/view_rplidar_a1.launch roslaunch rplidar_ros view_rplidar_a1.launch不想开 RViz可以单独起节点再用测试客户端在终端打印每一圈的角度与距离roslaunch rplidar_ros rplidar_a1.launch rosrun rplidar_ros rplidarNodeClient客户端的回调函数就是src/client.cpp里的scanCallback见 src/client.cpp#L43-L53——它正是主循环发布的那条/scan话题的终端版消费者输出格式恰好帮你确认angle_min、angle_increment和每个点的距离都符合预期。不同系列雷达只需替换对应的 launch 文件如 launch/rplidar_a3.launch、launch/rplidar_s1.launch并注意 S1 还支持 TCP 模式launch/rplidar_s1_tcp.launch。六、精读小结一张图看懂主循环把node.cpp主循环浓缩成一行公式原始字节流 →SDK 解包→ 节点数组 →升序排序→角度补偿→ LaserScan 消息 → /scan 话题几个值得新手记住的设计点缓冲复用nodes[8192]是栈上复用数组一圈数据约 64 KB避免频繁堆分配。解耦分层节点层node.cpp只面向ILidarDriver接口编程串口/TCP/UDP 的差异被通道抽象完全屏蔽换接口只需改 launch 参数。参数驱动inverted、angle_compensate、scan_mode、scan_frequency全部由私有参数控制不用改代码即可适配不同硬件与安装方式。优雅退出循环结束后先停电机、再stop()并释放驱动保证雷达硬件状态干净。读懂了这个不到 500 行的主循环你就掌握了 rplidar_ros 的全部核心逻辑协议解包、多通道支持等细节则沉淀在sdk/目录中可按需深入。【免费下载链接】rplidar_ros项目地址: https://gitcode.com/gh_mirrors/rp/rplidar_ros创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考