ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

镭神N10激光雷达ROS集成实战:从驱动配置到SLAM建图避坑指南

镭神N10激光雷达ROS集成实战:从驱动配置到SLAM建图避坑指南 镭神N10这款激光雷达在机器人圈子里算是性价比相当能打的一款几百块的价格能拿到10米测距、360度扫描的二维点云数据对于做SLAM建图和自主导航的入门玩家来说门槛很低。但便宜归便宜从拆箱到在ROS里跑出干净可用的点云中间要趟的坑一点都不少——串口权限、波特率匹配、TF树配置、点云方向修正每一步出问题都会让你对着rviz里那团乱七八糟的数据怀疑人生。这篇内容就是把我自己从零集成N10的完整过程拆开来讲包括每个环节为什么要这么配、配错了会怎样、以及那些官方文档里不会写的细节。不管你是刚接触ROS的新手还是换过好几款雷达的老玩家应该都能从中找到有用的东西。1. 先搞清楚N10到底吐出来的是什么1.1 雷达的物理连接与数据链路镭神N10的物理接口很简单一根线缆出来分成两路一路是USB转串口内部用的是CP2102或CH340芯片批次不同会有差异另一路是供电线。供电这块要注意N10的额定电压是5V但启动瞬间的电流峰值能到500mA以上如果你直接从树莓派的USB口取电在雷达高速旋转的时候可能会因为供电不足导致数据丢包甚至雷达重启。我的做法是单独用一块5V/2A的降压模块给它供电USB线只走数据不走电这样稳定性会好很多。插上USB之后在Ubuntu下用ls /dev/ttyUSB*应该能看到设备。但这里第一个坑就来了如果你同时插了其他USB串口设备比如STM32底盘、IMU等ttyUSB的编号可能会变。今天雷达是ttyUSB0明天重启之后可能就变成ttyUSB1了。解决办法有两个一是用udev规则绑定固定的设备名二是每次手动确认。我强烈建议用udev规则一劳永逸。创建规则文件/etc/udev/rules.d/n10_lidar.rules内容如下KERNELttyUSB*, ATTRS{idVendor}10c4, ATTRS{idProduct}ea60, MODE:0666, SYMLINKlidar_n10这里的idVendor和idProduct需要用lsusb命令确认你手上这台N10的实际值。CP2102的厂商ID通常是10c4产品ID是ea60CH340的话厂商ID是1a86产品ID是7523。写完规则之后执行sudo udevadm control --reload-rules sudo udevadm trigger重新插拔雷达就能用/dev/lidar_n10这个固定名字来访问了。注意MODE:0666给的是读写权限省去了每次chmod的麻烦。但如果你对系统安全有要求可以改成把当前用户加入dialout组的方式sudo usermod -aG dialout $USER然后重新登录生效。1.2 串口参数与协议解析N10的默认串口波特率是230400数据位8停止位1无校验。这个波特率不算低有些质量一般的USB转串口线在这个速率下会丢数据。如果你发现点云断断续续或者帧率不稳定先换一根好点的线试试别急着怀疑雷达本身。数据协议方面N10输出的是标准的串口数据包每个包包含角度、距离、强度等信息。镭神官方提供了ROS驱动包但网上流传的版本比较混乱有的基于ros_arduino_bridge改的有的是自己写的serial节点。我建议直接用镭神官方GitHub仓库里的lslidar_n10驱动虽然文档写得比较粗糙但代码本身是靠谱的。编译驱动之前确认你的ROS版本。Ubuntu 20.04对应NoeticUbuntu 22.04对应Humble。N10的驱动在Noetic下验证得最充分Humble下需要稍微改一下CMakeLists里的依赖路径。如果你用的是鱼香ROS一键安装的ROS环境基本的编译工具链都已经齐了直接catkin_make就行。编译过程中最常见的报错是找不到serial包。这是因为驱动依赖ROS的serial库需要先sudo apt install ros-noetic-serialHumble对应ros-humble-serial。另外如果报错提到pcl_ros同样用apt装一下对应的包就行。1.3 点云数据的坐标系定义这是很多人容易忽略但非常关键的一点N10输出的点云数据自带一个坐标系这个坐标系的原点在雷达的旋转中心X轴指向雷达线缆出口的反方向也就是雷达的正前方Y轴指向左侧Z轴指向正上方。这个定义和ROS里常见的base_link坐标系不一定一致所以在配置TF变换的时候要特别注意旋转关系。如果你把雷达正装在小车顶部线缆出口朝后那雷达坐标系和车体坐标系之间只需要一个平移变换Z轴方向的高度差。但如果你把雷达倒装或者侧装就需要额外的旋转变换。我见过有人把雷达倒装在机器人底部结果rviz里看到的点云全是镜像的排查了半天才发现是TF的旋转矩阵写错了。在URDF或者TF的static_transform_publisher里旋转可以用四元数或者RPY角来表示。用RPY角更直观一些比如倒装180度就是0 3.14159 0绕Y轴转180度。但要注意ROS里四元数的顺序是(x, y, z, w)而RPY转四元数的公式容易搞混建议直接用tf2_ros提供的转换工具来算。2. 驱动配置里那些让人抓狂的参数2.1 launch文件的关键字段拆解镭神N10的驱动launch文件看起来不长但每个参数都有讲究。我拿实际用的launch文件来逐项说明launch node namelslidar_n10_driver pkglslidar_n10_driver typelslidar_n10_driver outputscreen param nameserial_port value/dev/lidar_n10/ param nameserial_baudrate value230400/ param nameframe_id valuelaser_link/ param nameangle_disable_min value0/ param nameangle_disable_max value0/ param namemin_range value0.02/ param namemax_range value10.0/ param namefrequency value10/ param namepublish_scan valuetrue/ param namepublish_point_cloud valuetrue/ param namereversion valuefalse/ param nameinverted valuefalse/ /node /launchserial_port填的就是前面udev规则绑定的设备名。frame_id是点云数据在TF树里的父坐标系名称这个名字必须和后面TF变换里的child_frame_id一致否则rviz里会报no transform from [laser_link] to [map]之类的错误。angle_disable_min和angle_disable_max是用来屏蔽某个角度范围的默认都是0表示不屏蔽。这个功能在雷达被遮挡的时候有用比如雷达前方有个立柱挡住了几度到十几度的范围你可以把这段屏蔽掉避免这些无效点云干扰建图。但要注意这两个值的单位是度不是弧度而且屏蔽范围是逆时针方向计算的。reversion和inverted这两个参数特别容易搞混。reversion控制的是点云旋转方向inverted控制的是点云上下翻转。如果你发现rviz里点云的旋转方向和实际环境相反比如实际顺时针转rviz里显示逆时针就把reversion改成true。如果点云整体上下颠倒就把inverted改成true。这两个参数的具体效果和雷达的安装方式有关没有绝对的对错以实际显示为准。2.2 点云与激光扫描的取舍N10驱动可以同时发布sensor_msgs/PointCloud2和sensor_msgs/LaserScan两种消息。PointCloud2包含完整的3D信息虽然N10是2D雷达但每个点还是有Z坐标只是Z值都是0LaserScan是压缩过的2D格式数据量小很多。如果你只是做2D SLAM建图比如gmapping、hector_slam、cartographer的2D模式用LaserScan就够了数据量小处理速度快。但如果你要做3D建图或者点云配准就必须用PointCloud2。我一般两个都开着建图用LaserScan调试和可视化用PointCloud2反正N10的数据量不大同时发布两种消息对CPU的负担可以忽略。这里有个细节LaserScan的angle_min和angle_max默认是-π到π但N10的实际扫描范围是0到360度。驱动内部会做转换把角度映射到-π到π的范围。如果你发现LaserScan的角度范围不对检查一下驱动版本早期版本在这个转换上有个bug会导致角度偏移180度。2.3 频率设置与数据丢包排查frequency参数控制的是雷达的扫描频率N10支持5Hz到20Hz可调默认10Hz。提高频率可以获得更密集的数据但也会增加串口带宽的压力。在230400的波特率下10Hz是比较稳妥的选择。如果你设到20Hz串口可能来不及传输所有数据导致丢包。判断是否丢包有个简单的方法在rviz里观察点云的连续性。正常情况下N10的点云应该是一圈完整的圆环如果出现明显的缺口或者扇形缺失大概率是丢包了。另一个方法是看驱动的日志输出如果频繁出现checksum error或者incomplete packet之类的警告也说明数据传输出问题了。丢包的排查顺序是这样的先换USB线再换USB口尽量插在主板原生的USB口上不要用前面板或者USB Hub然后检查供电是否充足最后才考虑降低波特率或者扫描频率。我遇到过最诡异的一次丢包是USB线太长导致的换了根短的就好了这种问题真的很难从代码层面发现。3. TF树配置从雷达坐标系到车体坐标系3.1 静态TF发布与URDF的取舍把雷达坐标系接入机器人的TF树有两种方式一种是用static_transform_publisher发布静态变换另一种是在URDF模型里定义关节。两种方式各有适用场景。如果你只是做雷达和车体的相对定位用static_transform_publisher最简单node pkgtf2_ros typestatic_transform_publisher namelaser_tf args0.1 0 0.25 0 0 0 base_link laser_link/这行命令的意思是雷达相对于base_link在X方向偏移0.1米Z方向偏移0.25米没有旋转。args的前三个是平移后三个是RPY旋转弧度制。但如果你要做一个完整的机器人模型包含底盘、雷达、相机、机械臂等多个部件那就应该在URDF里统一管理。URDF的好处是可视化直观在rviz里能看到整个机器人的模型而且修改起来方便。缺点是每次改URDF都要重新启动robot_state_publisher调试的时候稍微麻烦一点。我的建议是如果机器人只有雷达和底盘两个部件用static_transform_publisher就够了如果有三个以上的传感器或者执行器果断上URDF。3.2 雷达安装位置对建图的影响雷达装在哪里直接影响建图的质量。理想情况下雷达应该装在车体的最高点视野无遮挡。但实际做小车的时候往往受限于结构设计雷达可能装在比较低的位置或者周围有立柱、线缆等遮挡物。如果雷达装得比较低一个常见的问题是看到自己的车体。比如雷达扫描平面刚好切过车轮或者底盘边缘这些点云会被当成障碍物导致建图时出现莫名其妙的障碍。解决办法有两个一是调整雷达高度让它高于车体最高点二是在驱动里用angle_disable_min和angle_disable_max屏蔽掉被遮挡的角度范围。还有一种情况是雷达装在车体前方扫描范围覆盖了车头前方的地面。如果地面是光滑的比如瓷砖激光打到地面会产生镜面反射点云数据会很不稳定。这时候可以考虑给雷达加一个遮光罩或者稍微向上倾斜几度让扫描平面避开正前方的地面。3.3 多传感器TF树的常见冲突当机器人上同时有雷达、IMU、里程计等多个传感器时TF树的管理就变得复杂了。最常见的冲突是多个节点同时发布同一个坐标系变换导致TF树出现TF_REPEATED_DATA警告rviz里的模型会抖动甚至消失。避免这个问题的原则是每个坐标系变换只能有一个发布者。比如base_link到laser_link的变换要么由static_transform_publisher发布要么由URDF发布不能两个都发。同样odom到base_link的变换只能由里程计节点发布map到odom的变换只能由SLAM节点发布。如果你不确定当前TF树的结构可以用rosrun tf2_tools view_frames.py生成一个PDF图直观地看到所有坐标系之间的连接关系。这个工具在排查TF问题时非常有用强烈建议每个ROS玩家都掌握。4. 建图实战从gmapping到cartographer的选择4.1 gmapping的快速上手与局限gmapping是ROS里最经典的2D SLAM算法优点是配置简单、计算量小、在树莓派上也能跑。用N10配合gmapping建图基本流程就是启动雷达驱动、启动gmapping、启动键盘控制节点然后推着车走一圈。gmapping的核心参数在launch文件里配置几个关键参数如下param namemaxUrange value8.0/ param namemaxRange value10.0/ param namesigma value0.05/ param namekernelSize value1/ param namelstep value0.05/ param nameastep value0.05/ param nameiterations value5/ param namelsigma value0.075/ param nameogain value3.0/ param namelskip value0/ param nameminimumScore value30/ param namesrr value0.1/ param namesrt value0.2/ param namestr value0.1/ param namestt value0.2/ param namelinearUpdate value0.2/ param nameangularUpdate value0.2/ param nametemporalUpdate value1.0/ param nameresampleThreshold value0.5/ param nameparticles value30/ param namexmin value-10.0/ param nameymin value-10.0/ param namexmax value10.0/ param nameymax value10.0/ param namedelta value0.05/maxUrange是雷达的最大有效距离设成8米比N10的标称10米略小是为了留出余量避免边缘数据不稳定。particles是粒子数30个对于小场景够用了如果场景大或者特征少可以加到50甚至80但计算量会明显增加。gmapping最大的局限是它依赖里程计。如果你的小车没有轮式里程计或者里程计精度很差gmapping建出来的图会重影严重。我试过用N10配合一个便宜的编码器里程计在小场景里效果还行但走到长走廊这种特征少的地方就开始飘了。4.2 cartographer的配置要点与性能调优cartographer是Google开源的SLAM算法支持2D和3D建图最大的优势是自带回环检测建图精度比gmapping高一个档次。但配置也复杂得多尤其是lua配置文件里的参数没调好的话效果可能还不如gmapping。用N10跑cartographer的2D建图核心配置文件需要改这几个地方TRAJECTORY_BUILDER_2D.min_range 0.1 TRAJECTORY_BUILDER_2D.max_range 10.0 TRAJECTORY_BUILDER_2D.missing_data_ray_length 5.0 TRAJECTORY_BUILDER_2D.use_imu_data false TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching true TRAJECTORY_BUILDER_2D.motion_filter.max_angle_radians math.rad(0.1)use_imu_data设成false是因为N10本身不输出IMU数据如果你车上没有独立的IMU这个必须关掉否则cartographer会一直等IMU数据导致建图无法启动。use_online_correlative_scan_matching打开在线相关性扫描匹配对N10这种数据量不大的雷达来说能明显提升匹配精度计算量也在可接受范围内。motion_filter.max_angle_radians控制的是角度变化超过多少才插入新的子图。设成0.1弧度约5.7度是个比较平衡的值太小会导致子图过多、内存暴涨太大则建图精度下降。cartographer跑起来之后如果发现建图过程中地图突然跳变或者错位大概率是回环检测出了问题。可以检查一下POSE_GRAPH.constraint_builder.min_score这个参数默认是0.55如果场景里相似的地方比较多比如长走廊可以适当提高到0.6或0.65减少误回环。4.3 建图飘移的排查思路激光雷达建图飘是搜索热词里经常出现的问题N10用户遇到这个情况的也不少。飘移的表现是地图重影、墙壁变厚、回环对不上。排查思路可以按以下顺序来先看里程计。如果里程计数据本身就不准SLAM算法再强也救不回来。把机器人推着走直线看/odom话题里的位姿变化是否和实际距离一致。如果偏差超过5%先修里程计。再看时间同步。雷达数据、里程计数据、TF变换的时间戳必须对齐。如果雷达驱动发布的消息时间戳用的是系统时间而里程计用的是ROS时间两者不一致会导致SLAM算法计算出错误的运动量。检查方法是用rosbag record录一段数据然后用rqt_bag查看各话题的时间戳是否对齐。最后看雷达安装。如果雷达在机器人运动过程中有轻微晃动比如固定螺丝没拧紧点云数据会产生额外的噪声SLAM算法会把这些噪声当成环境变化导致建图飘移。用手轻轻推一下雷达看是否有松动有的话加固。5. 那些官方文档不会告诉你的实操细节5.1 点云数据的时间戳问题N10驱动默认使用ROS的ros::Time::now()作为点云消息的时间戳这意味着时间戳是驱动收到数据包的瞬间而不是雷达实际扫描的瞬间。在机器人低速运动时这个差异可以忽略但在高速运动或者快速转向时这个时间差会导致点云和实际环境错位。解决方法是使用雷达数据包里的硬件时间戳。N10的数据协议里每个包都带有一个时间信息驱动可以解析出来作为消息的时间戳。但镭神官方驱动在这个功能上做得不够完善需要自己改代码。具体来说在解析数据包的函数里把ros::Time::now()替换成从数据包中解析出的时间值。如果你不想改代码另一个折中方案是降低机器人的运动速度让时间差的影响降到最小。建图的时候慢一点走效果会好很多。5.2 rviz显示配置的优化rviz是调试雷达数据的主要工具但默认配置下显示效果往往不理想。几个优化点把PointCloud2的Style从Points改成Flat SquaresSize设成0.02左右这样点云看起来更清晰也更容易判断密度。Color Transformer选Intensity可以根据反射强度给点云上色不同材质的物体墙壁、玻璃、地面会显示成不同颜色方便区分。Decay Time设成0.1秒左右这样点云会有轻微的拖尾效果能看出雷达的旋转方向。但不要设太长否则点云会糊成一团。如果点云数据量太大导致rviz卡顿可以在驱动里把publish_point_cloud关掉只发布LaserScan然后在rviz里用LaserScan显示。LaserScan的显示效果虽然不如PointCloud2丰富但流畅度会好很多。5.3 长时间运行的稳定性保障N10连续跑几个小时之后偶尔会出现数据停止更新的情况。这个问题在夏天特别明显怀疑是雷达内部温度过高导致的。解决办法是在雷达底部贴一块小散热片或者用一个小风扇对着吹。如果雷达装在封闭的车体里一定要留通风孔。软件层面可以写一个简单的监控节点定期检查/scan话题是否有数据更新。如果超过2秒没有新数据就自动重启雷达驱动节点。这个监控节点用Python写很简单核心逻辑就是订阅/scan话题用一个定时器检查最后一次收到消息的时间。import rospy from sensor_msgs.msg import LaserScan import subprocess last_msg_time rospy.Time.now() def scan_callback(msg): global last_msg_time last_msg_time rospy.Time.now() def check_callback(event): if (rospy.Time.now() - last_msg_time).to_sec() 2.0: rospy.logwarn(Lidar data timeout, restarting driver...) subprocess.call([rosnode, kill, /lslidar_n10_driver]) subprocess.call([roslaunch, lslidar_n10_driver, lslidar_n10.launch]) rospy.init_node(lidar_monitor) rospy.Subscriber(/scan, LaserScan, scan_callback) rospy.Timer(rospy.Duration(1.0), check_callback) rospy.spin()这个监控节点虽然简单但在实际跑长时间建图任务的时候能省不少心。我试过连续跑8小时的建图任务中间雷达驱动重启了3次但地图没有断因为cartographer有断点续建的能力。5.4 与其他传感器的联合标定如果机器人上还有相机或者IMU雷达和它们之间的外参标定就很重要。雷达和相机的标定可以用cam_lidar_calibration这个包但需要制作一个特殊的标定板棋盘格加反光标记。标定过程比较繁琐但标定一次之后可以长期使用。雷达和IMU的标定主要是时间同步和安装角度。时间同步可以用message_filters做近似时间同步安装角度则需要在TF树里正确配置。如果IMU和雷达的安装角度偏差较大融合后的位姿会有系统性误差表现为建图时地图整体旋转了一个角度。标定完成之后建议用rosbag record录一段包含所有传感器数据的bag然后用离线工具验证标定结果。如果发现标定参数有问题可以反复调整直到融合效果满意为止。6. 从建图到导航的过渡建好图之后下一步通常是做自主导航。N10在导航环节主要提供实时障碍物信息配合move_base或者nav2做路径规划和避障。这里有几个N10特有的注意点。N10的测距范围是10米在导航时costmap的obstacle_range不要设得太大建议设成3到5米就够了。设太大反而会让costmap里充满远处的障碍物导致规划器找不到可行路径。raytrace_range设成3.5米左右比obstacle_range略大一点用于清除已经消失的障碍物。N10的角分辨率是0.48度左右在10米距离上的点间距大约是8厘米。这个分辨率对于导航来说够用了但在通过窄通道时可能会因为点云稀疏而误判。如果机器人经常在窄通道里卡住可以考虑在costmap里把inflation_radius调小一点给规划器更多空间。导航过程中如果发现机器人对某些障碍物视而不见比如玻璃门或者黑色物体这是因为激光雷达对这些材质的反射率低点云强度不够。解决办法是在这些位置手动添加虚拟障碍物或者融合超声波、红外等传感器做补充检测。从我个人经验来看N10在ROS下的集成难度属于中等偏下大部分坑都有成熟的解决方案。关键是要有耐心遇到问题不要急着换硬件先把软件层面的配置排查一遍。我见过太多人因为TF配置错误或者串口权限问题就放弃了一款雷达其实这些问题花十分钟就能解决。希望这篇内容能帮你少走一些弯路把N10的潜力充分发挥出来。
返回列表