十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

速腾Helios-16P与Lego-loam实战:从编译到点云地图全流程指南

速腾Helios-16P与Lego-loam实战:从编译到点云地图全流程指南 速腾Helios-16P配Lego-loam这套组合前阵子我又重新捡起来完整跑了一遍。说实话现在网上讲Lego-loam原理的文章不少讲速腾雷达驱动的也算多但能把这两样东西放在一起、从零编译到真正把点云地图跑出来一条龙说清楚的还真不多。尤其是Helios-16P发布的话题名和Lego-loam默认订阅的话题名对不上这一类问题对老手就是一分钟的事对新手却是一道看不见的墙卡住就是一下午。这篇是系列的第二篇重点只聚焦编译和运行。从依赖安装、gtsam版本选择、Lego-loam编译报错处理到Helios-16P驱动配置、话题对齐最后三个终端把图跑出来、保存成pcd文件全程按我实测的顺序走。搞毕业设计、做无人车或机器人实验、或者刚从Velodyne切到速腾雷达的朋友这篇可以参考着照做。1. 项目整体思路与环境准备1.1 老算法为什么还能打先聊聊为什么这个组合放到今天依然有意义。Helios-16P是速腾聚创一颗16线激光雷达标称探测距离45米左右垂直视场角不算小点频中等偏上整体点云密度在16线雷达里算不错的。它本身定位就是中近距离感知非常适合室内外小范围建图、AGV导航验证、机器人避障这类场景。Lego-loam则是2018年前后开源的一套轻量级激光SLAM方案。它最大的特点是做了地面分割和聚类把地面点单独处理再基于分割对象提取特征整体计算量比原版LOAM小不少在低算力工控机上也能跑得动。虽然现在新算法一大把但Lego-loam胜在工程化成熟、参数少、上手快配合Helios-16P这种“轻量级雷达”正好是绝配。我身边好几个做无人车课题的朋友最终验收用的还是这套组合。另外提醒一句虽然这个算法能实时建图但它本质是雷达里程计加后端优化不是完整的语义地图方案。它解决的是“我从哪来、周围长什么样”的问题适合当作上层导航、路径规划的前端定位模块来用。1.2 环境版本这么选Melodic优先环境版本这个问题我在踩过一轮坑之后态度很明确优先用Ubuntu 18.04加ROS Melodic这是Lego-loam最稳的“原配”。为什么这么说Lego-loam的源码里面有大量C11风格的老代码在Ubuntu 20.04的GCC 9编译器下编译会冒出一堆标准库兼容性问题比如std::integer_sequence找不到、index_sequence不在std命名空间里等等。这些问题倒不是不能解决但网上能搜到的报错讨论和现成解决方案绝大多数都基于Melodic环境。你用Noetic去跑很可能改完一处又冒出一处纯浪费时间。如果你手头只有Ubuntu 20.04的机器也不是完全不能做后面编译章节我会提到怎么改C标准来绕过问题。但如果你还没装系统听我一句劝直接用18.04。ROS Melodic官方对18.04的支持也最完整驱动适配、社区资料都是最多的何必拿自己的时间给编译器版本做测试。有一点需要提前说明如果你打算用Docker也可以考虑直接跑带ROS Melodic的容器镜像然后把雷达网口和USB设备映射进容器。不过涉及实时网络通信和驱动权限Docker要多配不少东西建议还是物理机装双系统最省心。1.3 开始之前检查硬件链路环境准备不只是装系统硬件链路提前通了后面软件调试才不闹心。我的建议是按照“雷达供电、网口通信、驱动自检”三步过一遍。Helios-16P一般通过网口输出点云数据默认IP是192.168.1.200一类的固定地址具体以你手里那台的铭牌或说明书为准。电脑网口需要设置成同一个网段比如192.168.1.102子网掩码255.255.255.0这样雷达才能被正常发现。供电这块很多人忽略Helios-16P工作电流不低最好用原装电源或者适配的PoE模块别用普通USB口供电硬撑实测会导致点云丢包、断流严重时雷达直接重启。链路检查最简单的办法就是ping雷达的IPping 192.168.1.200能通说明物理层没问题。接下来安装驱动后能收到话题数据链路就算彻底通了。2. 依赖安装与源码准备2.1 先装ROS基础依赖系统装好、ROS Melodic装好之后先别急着拉代码把编译要用的ROS包装齐了能少踩一半的坑。我编译Lego-loam实际用到的依赖主要是pcl_ros、tf相关、rviz这些安装命令sudo apt-get update sudo apt-get install ros-melodic-pcl-ros ros-melodic-pcl-conversions ros-melodic-tf2-geometry-msgs ros-melodic-tf2-ros ros-melodic-rviz如果你是Ubuntu 20.04加ROS Noetic把包名的melodic换成noetic即可。这里重点提醒ros-melodic-pcl-conversions稍不留神就会漏。漏掉的后果是编译时报错找不到pcl_conversions/pcl_conversions.h很多人不知道这个头文件在单独的包里会误以为自己PCL装错了实际就是少装了一个ROS桥接包。在正式编译Lego-loam之前我还会顺手确认一下PCL和Eigen的版本。ROS Melodic自带的PCL 1.8、Eigen 3.3完全满足要求不需要额外升级。版本太新反而可能出现API不兼容的问题原理上和编译器版本问题一样都属于“环境越新兼容性越差”的典型。2.2 GTSAM版本坑必须用4.0.0-alpha2Lego-loam后端用的位姿图优化库是GTSAM这个库的版本选择非常关键网上很多人编译不过去十有八九是栽在这。Lego-loam源码里用到的是GTSAM比较老的接口我实测能正常编译通过的版本是4.0.0-alpha2。如果你用4.0.0正式版或者4.1、4.2这些新版本会碰到GTSAM_ERROR这类宏已经移除、NonlinearFactorGraph接口变化等一堆编译错误处理起来非常麻烦。推荐用源码方式安装4.0.0-alpha2cd ~ wget -O gtsam.zip https://github.com/borglab/gtsam/archive/4.0.0-alpha2.zip unzip gtsam.zip cd gtsam-4.0.0-alpha2 mkdir build cd build cmake -DGTSAM_BUILD_TESTSOFF -DGTSAM_BUILD_UNSTABLEON -DGTSAM_WITH_TBBOFF .. sudo make install -j$(nproc)这里面的几个cmake参数解释一下GTSAM_BUILD_TESTSOFF是关掉自带测试能省一大半编译时间GTSAM_BUILD_UNSTABLEON是必须的Lego-loam依赖GTSAM里标记为不稳定模块的代码GTSAM_WITH_TBBOFF是关掉TBB并行支持避免老版本GTSAM和TBB库之间的兼容问题。整个GTSAM编译过程大概需要十几分钟看机器性能。装完之后GTSAM的库文件会安装到/usr/local/lib下头文件在/usr/local/include/gtsam。如果后续Lego-loam编译时找不到GTSAM头文件可以检查一下这两个路径是否存在。2.3 拉取Lego-loam源码依赖装好之后正式拉Lego-loam源码。mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/RobustFieldAutonomyLab/LeGO-LOAM.git拉完之后先别急着编译建议打开LeGO-LOAM/CMakeLists.txt看一眼现有的编译选项。我记得源码里的默认C标准是C11这个我们后面大概率要改先记着这事。另外源码目录下会有launch文件夹和rviz文件夹里面自带测试用的rviz配置。后面启动Rviz可以直接用这个配置省得自己手工添加话题。到这里代码和依赖都准备好了可以进入最折磨人也最有收获的环节——编译。3. 编译Lego-loam把报错一个个按回去3.1 第一次编译报错是正常的直接说结论Lego-loam在现在的主流环境下裸编译大概率会报错。这不是你操作的问题而是源码太老、编译器太新导致的必然结果。第一次编译我建议直接执行cd ~/catkin_ws catkin_make把报错信息完整看一眼然后根据报错类型对症下药。我自己遇到的主要有两类问题一类是C标准太老一类是特殊字符编码问题。下面分别说。3.2 C标准不匹配引发的一串报错如果你用的是Ubuntu 18.04的GCC 7或者更高版本的GCC很可能会在编译mapOptimization.cpp或utility.h相关文件时看到类似这样的报错error: ‘integer_sequence’ is not a member of ‘std’ error: ‘index_sequence’ in namespace ‘std’ does not name a template type原因其实不复杂。Lego-loam的代码里包含了nlohmann json这个第三方头文件而这个头文件在某些实现下会用到C14才有的std::integer_sequence和std::index_sequence。但工程默认的编译标准是C11编译器自然找不到这些类型。解决办法很简单把C标准从C11升到C14或者C17。打开LeGO-LOAM/CMakeLists.txt找到类似这一行set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -stdc11 -O3)改成set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -stdc14 -O3)改完保存重新catkin_make这一串报错基本就消失了。如果你的编译器很新C14还不够可以改成-stdc17一般也能过。这里有个细节-O3优化选项建议保留。Lego-loam是实时算法对性能敏感开-O3能让特征提取和配准快一些实测体感差异明显。3.3 颜文字符号与字符集报错第二个经典报错比较隐蔽编译时如果出现类似error: converting to execution character set: Invalid argument那就不是语法问题了而是源码里某个文件包含特殊Unicode字符在当前系统locale下无法转换。Lego-loam源码里有一段日志打印的字符串里面用了一些比较特殊的框线字符类似“━”这种在部分locale环境下会触发编译器的字符集转换错误。网上戏称它为“颜文字报错”其实本质是字符编码问题。解决方案很直接找到出错的文件把特殊字符删掉或者替换成普通ASCII字符。我遇到的位置在src/utility.h具体行数不同版本可能不一样可以用grep定位grep -n ━ src/utility.h如果grep没有结果就搜更宽泛的非ASCII字符grep -nP [^\x00-\x7F] src/utility.h找到之后把那一行的特殊符号改成普通横线比如-或者直接整行注释掉保存退出重新编译即可。这个报错说实话有点无厘头但处理起来也快。就当作熟悉编译流程的一个小插曲。3.4 编译成功的判断标准处理完上面两三个问题重新执行catkin_make正常情况下会编译好一会儿最后没有error就是成功了。成功后会生成四个核心可执行文件imageProjectionfeatureAssociationmapOptimizationtransformFusion这四个节点分别在终端的catkin_ws工作空间里生成。可以用以下命令确认ls ~/catkin_ws/devel/lib/lego_loam/看到这四个文件编译部分就正式通关了。还有一个细节每次改完CMakeLists再重新编译之前不建议频繁catkin_clean直接重新catkin_make即可增量编译速度快很多。如果改了C标准或者gtsam路径之类的大改动才需要删掉build目录重新编。4. Helios-16P驱动配置与话题对齐4.1 驱动选择和自检Lego-loam编译好了接下来把雷达的点云喂进去。Helios-16P的驱动主要有两个选择老牌的rslidar_pointcloud和新版的rslidar_sdk。新版rslidar_sdk功能更全支持多款速腾雷达但配置结构更复杂一些依赖也更多。我这里以新版为主但操作思路对旧版同样适用。把驱动拉到工作空间cd ~/catkin_ws/src git clone https://github.com/RoboSense-LiDAR/rslidar_sdk.git cd rslidar_sdk git submodule update --init --recursive新版rslidar_sdk的编译方式有点特殊它既可以单独cmake构建也可以放进catkin_ws用catkin_make编译。我更建议放进catkin_ws一起编译这样ROS话题接口直接可用。cd ~/catkin_ws catkin_make编译完了先编辑驱动配置文件路径一般在rslidar_sdk/config/config.yaml。核心配置项包括雷达型号、接收端口、发布话题名、frame_id其中雷达型号一定要改成RS16lidar: - driver: lidar_type: RS16 ros: ros_recv_port: 6699 ros_send_point_cloud_topic: /rslidar_points frame_id: rslidar这里的lidar_type: RS16对应Helios-16P这一类16线雷达。不同固件版本默认端口可能不同6699是速腾比较常用的点云数据接收端口具体以驱动文档为准。启动驱动source ~/catkin_ws/devel/setup.bash roslaunch rslidar_sdk start.launch用rostopic检查话题是否正常rostopic hz /rslidar_points如果能看到稳定的频率输出说明驱动链路OK。一般Helios-16P是10Hz能看到8到10Hz之间波动就正常。4.2 点云话题对齐的三种方案驱动跑通后紧接着就是那个最经典的问题Lego-loam默认订阅的是/velodyne_points而Helios-16P默认发布的是/rslidar_points两个名字对不上算法收不到数据。处理方案有三种我一个个说你任选其一。方案一改launch文件参数。在lego_loam的launch文件里增加参数设置Lego-loam的imageProjection节点会从参数服务器读取点云话题名。在launch文件顶部加上param namepointCloudTopic value/rslidar_points /不同版本的参数名可能不完全一样有的叫pointCloudTopic有的直接读取cloudTopic稳妥的做法是先打开源码src/utility.h或src/imageProjection.cpp看一眼实际读取的参数名。这种方式最干净不用改驱动。方案二用remap重映射。不动任何源码和参数直接在lego-loam的launch文件里给订阅点云的节点加remapnode pkglego_loam typeimageProjection nameimageProjection outputscreen remap from/velodyne_points to/rslidar_points / /node只有imageProjection这个节点订阅原始点云所以其他节点不需要加remap。这个方案的好处是完全不用改代码只是在ROS层面做了一个话题名的转发映射出问题随时能撤销。方案三改驱动发布的话题名。在rslidar_sdk的config.yaml里把ros_send_point_cloud_topic改成/velodyne_points。这样驱动直接发布的是Lego-loam默认订阅的名字。我实测下来最推荐方案一或者方案二。它们的共同优点是不动雷达驱动因为驱动可能还要给其他模块供数据改成/velodyne_points之后其他程序如果按照/rslidar_points订阅就得跟着改波及面太大。我个人的习惯是改Lego-loam这一侧保持雷达驱动的发布话题始终是原始名称。4.3 frame_id与点云类型检查话题对齐之后还有两个隐藏点需要检查点云类型和坐标系。Lego-loam内部会把收到的sensor_msgs/PointCloud2消息转成PCL的PointXYZI点云。PointXYZI除了xyz坐标之外还有一个intensity强度字段。Helios-16P的点云是有强度信息的但驱动里可能需要显式开启。如果你的rviz里看到点云颜色全是一个值、没有强度差异多半是驱动配置里没有填充intensity不过不影响建图定位只是可视化效果差一些。坐标系的坑更隐蔽。Lego-loam初始化时会把第一帧点云所在的位置作为世界系原点它内部有三个坐标系camera_init、base_link、camera。其中camera_init是全局地图坐标系base_link是车体坐标系camera是雷达坐标系。launch里通常会有一个静态tf发布node pkgtf typestatic_transform_publisher namecamera_init_to_base_link args0 0 0 0 0 0 /camera_init /base_link 10 /注意这里只有camera_init到base_link的变换。如果雷达驱动发布的点云frame_id不是base_link而是rslidar那么base_link到rslidar之间的tf变换缺失rviz里可能无法正常显示。最简单的解决办法是把驱动配置里的frame_id改成base_linkframe_id: base_link这和Lego-loam里static_transform_publisher发布的base_link正好对上坐标系在原点重合不需要额外做tf变换。如果你的雷达安装位置和车体base_link之间存在明显平移或旋转那就要把static_transform_publisher的平移和旋转参数改成真实外参不能直接0 0 0。5. 实际运行三个终端把图跑起来5.1 修改run.launch参数运行前先改一下Lego-loam自带的launch文件把话题对齐和坐标系的设置固化进去。我用方案二演示打开~/catkin_ws/src/LeGO-LOAM/launch/run.launch改成类似这样launch param namepointCloudTopic value/rslidar_points / node pkglego_loam typeimageProjection nameimageProjection outputscreen remap from/velodyne_points to/rslidar_points / /node node pkglego_loam typefeatureAssociation namefeatureAssociation outputscreen/ node pkglego_loam typemapOptimization namemapOptimization outputscreen/ node pkglego_loam typetransformFusion nametransformFusion outputscreen/ node pkgtf typestatic_transform_publisher namecamera_init_to_base_link args0 0 0 0 0 0 /camera_init /base_link 10 / /launch提醒一下如果你选了话题名参数方案那remap这行可以不要两选一即可。同时再确认驱动配置里的frame_id是base_link这样整体tf链路就完整了。保存launch文件后建议先用rospack find lego_loam确认路径正常再进入下一步。5.2 依次启动雷达和算法一切就绪后按顺序开三个终端。第一个终端启动雷达驱动source ~/catkin_ws/devel/setup.bash roslaunch rslidar_sdk start.launch看到/rslidar_points有稳定频率输出后第二个终端启动Lego-loamsource ~/catkin_ws/devel/setup.bash roslaunch lego_loam run.launch第三个终端开Rviz。严格来说run.launch里已经带了rviz节点会自动加载test.rviz配置但如果你的自动打开的rviz显示空白就手动再开一个source ~/catkin_ws/devel/setup.bash rosrun rviz rviz -d $(rospack find lego_loam)/launch/test.rviz在rviz左侧的Global Options里把Fixed Frame设为camera_init。这是最容易漏的一步fixed frame设置错了点云和地图大概率不显示或者显示错乱。如果一切正常你会看到雷达点云被实时投影成深度图并且随着雷达移动地图点云会逐渐拼接到/laser_cloud_map话题上。5.3 从Rviz判断建图是否正常这里分享几个判断建图质量的实用经验。第一看话题频率。正常运行时/velodyne_cloud_registered的话题频率应该和雷达频率接近也就是10Hz左右。如果这个频率很低说明前端特征提取和帧间匹配耗时过高可能是工控机性能不足或者点云分辨率设置太高。第二看地图累积。拿雷达在房间或者走廊里缓慢走一圈回看/laser_cloud_map墙角和柱子轮廓应该是清晰的直线和直角如果出现明显的重影、分叉说明帧间匹配出现了漂移。轻度漂移一般是运动太快或特征太少重度漂移要检查雷达外参和tf是否正确。第三看控制台输出。Lego-loam的mapOptimization节点会周期性打印优化信息和当前坐标值。如果输出一直在更新且数值平滑变化说明后端优化正常。如果打印停住不动大概率是节点挂了或者输入点云中断。我实测时还遇到过一个现象地图显示正常但突然跳到很远的位置然后又慢慢回来。这通常是后端因子图优化过程中检测到了回环或者异常帧属于算法自身的调整行为偶尔出现不用太紧张频繁出现就要考虑是不是点云时间戳抖动导致的。5.4 地图保存成pcd文件跑完一圈图也建出来了怎么把地图存下来最简单的方式是用pcl_ros自带的pointcloud_to_pcd工具。source ~/catkin_ws/devel/setup.bash rosrun pcl_ros pointcloud_to_pcd _topic:/laser_cloud_map这个工具会持续监听话题并将每一帧点云保存成带时间戳的pcd文件保存位置在当前运行目录。跑几秒后按CtrlC停止目录下会出现类似0000000000.pcd、0000000005.pcd这样的文件选最后一个时间戳的pcd就是最新最完整的全局地图。如果你想要一个干净的地图建议保存前先把雷达静止几秒钟让后端把局部地图优化收敛再触发保存。实测这样保存下来的地图边缘质量和重叠度都会好不少。pcd文件后续可以用CloudCompare打开查看或者用PCL库写个plugin直接转成octomap用于导航扩展性很好。6. 常见问题速查表与个人心得6.1 编译与运行阶段问题速查把我在实际搭建过程中遇到的典型问题整理一下问题现象根本原因解决手段catkin_make找不到pcl_conversions头文件缺ROS桥接包安装ros-melodic-pcl-conversions编译报integer_sequence / index_sequence不在std中C标准太低CMakeLists中改-stdc14或c17编译报converting to execution character set源码含特殊Unicode字符删除utility.h中特殊字符编译报GTSAM相关接口错误GTSAM版本不对安装4.0.0-alpha2版本雷达有ping但rostopic hz为0驱动lidar_type或端口配置错误检查config.yaml中RS16与端口启动lego-loam后Rviz无地图话题名未对齐remap或参数改为/rslidar_pointsRviz报错base_link不存在frame_id不一致驱动frame_id改为base_link地图重影漂移严重运动过快或外参不对降低移动速度检查tf外参mapOptimization打印停止节点异常或点云输入中断查看话题hz重启节点6.2 新手最容易忽略的三个操作第一个是source。很多人开了新终端直接跑rostopic或者roslaunch报找不到package。这不是代码问题是环境变量没刷新。每个终端都要先执行source ~/catkin_ws/devel/setup.bash或者一次性写进~/.bashrc。第二个是Rviz里的Fixed Frame。这个我上面提过但还是要单独强调它是新手阶段最常卡住的地方。明明话题有数据就是什么都不显示改一下fixed frame就全出来了。第三个是工作空间路径。Lego-loam和rslidar_sdk要放在同一个catkin_ws/src下面同时编译这样devel目录里的环境变量才能一次性覆盖两个包。如果分开编译经常出现驱动能起、lego_loam却找不到的尴尬情况。6.3 一点个人建议我做这套方案最大的体会是Lego-loam这种老算法的拦路虎不在算法本身而在编译兼容性上。版本组合一旦正确运行稳定性其实非常高。如果遇到报错先按GCC版本、C标准、gtsam版本、依赖包这四样去核对能解决九成问题。另外想给用Helios-16P的朋友提个醒室外强光环境下点云会出现一些噪点建议在驱动配置里打开滤波选项或者在跑算法之前增加一个体素滤波节点把离群点先清掉建图效果会明显更干净。这个优化对实时性影响不大但对最终地图精度帮助很直接。如果再往下扩展可以把这个方案输出的地图接到move_base做导航或者改成离线处理rosbag的方式做大规模建图。Lego-loam作为整套定位建图链路的地基多花点时间把它跑透后面的路会顺很多。
返回列表