拓冰建站拓冰建站
首页 / 资讯中心 / 正文

XTDrone中A-LOAM激光雷达SLAM:解决点云丢失与坐标系报错全指南

XTDrone里装好A-LOAM跑3D激光雷达SLAM对做无人机或机器人导航的同学来说是一个绕不开的“新手但必踩”的阶段。很多人不是原理不懂而是卡在两边一是Gazebo仿真里怎么都看不到点云二是A-LOAM一旦真跑起来又报一堆坐标系相关错误比如frame_id [velodyne] does not match或者Could not get transform from map to base_link。这篇文章我就用XTDrone平台的实操经验把这两类问题从头到尾拆开讲透并且给出可以直接照着改的排查流程。我默认你已经装好了XTDrone基础环境、ROS和Gazebo手里有一台能跑得动仿真的电脑。没有的话也没关系文章里该检查的地方我都会写出来。A-LOAM本身是一个基于LOAM思想但代码更简洁的开源激光里程计与建图方案用PCL处理点云、Ceres做优化搭配XTDrone里挂载的3D激光雷达模型完全可以验证完整的SLAM流程。1. 先在仿真里理解“激光雷达SLAM”到底跑的是什么1.1 XTDrone、A-LOAM、3D激光雷达这三者怎么组合XTDrone是一套基于PX4、ROS和Gazebo的多旋翼无人机仿真平台它不只有无人机动力学模型还内置了不少机载传感器模型其中就包括3D激光雷达。你可以把它理解成一个“有完整传感器反馈的飞行实验室”无人机在Gazebo世界里飞机载雷达不断扫描周围环境生成点云数据。A-LOAMAdvanced LOAM是港科大团队对经典LOAM的开源实现核心功能是处理这些点云得到两个东西一是无人机自身的运动轨迹也就是里程计二是增量式的环境点云地图。它比原始LOAM更容易读懂也比较适合拿来做学习、实验和二次开发。这三者组合后的链路可以用一句话概括XTDrone里的Gazebo世界产生环境、无人机挂载雷达产生点云点云通过ROS话题发布A-LOAM订阅这些点云再输出里程计和地图到ROS/可视化工具里。整个链路里任何一环没对上表现就是“没有点云”或者“坐标系报错”。1.2 仿真平台解决什么问题、适合谁跑仿真SLAM最直接的价值是你可以在一台电脑上反复验证算法不用担心真机坠毁、电池耗尽或者激光雷达损坏。XTDrone的优势在于它把PX4飞控、Gazebo环境、传感器模型和机载计算机的通信都整合好了你不需要自己从零手搓一架带雷达的无人机模型。适合参考这篇文章的人有三类第一类是在学《视觉SLAM十四讲》或SLAM相关课程想在真实传感器数据之外补一个仿真环境第二类是刚接触A-LOAM代码能编译但跑包时一头雾水第三类是已经在XTDrone里折腾过但被“没有点云”和“坐标系报错”折磨到怀疑人生。这篇文章不涉及复杂的理论推导更多是告诉你怎么找问题、怎么改配置让算法先跑起来跑起来之后再回头看书你会突然通透很多。2. 不搞懂这几件事后面报错你根本不知道怎么查2.1 A-LOAM的里程计节点和建图节点都干了什么A-LOAM编译完成后会生成两个核心节点一个叫scanRegistration一个叫laserOdometry还有一个用于建图的laserMapping节点。很多人只看教程里写了“启动三个节点”却不清楚它们分工所以一出错就不知道是哪一环断了。scanRegistration负责接收原始的3D激光雷达点云做“特征点提取”把环境中角点和平面点挑出来。判断角点和平面点的依据是局部曲率曲率大的是角点曲率小的是平面点。这一步输出的是过滤后的特征点云发布到类似/laser_cloud_corner和/laser_cloud_surface的话题。laserOdometry接收特征点后通过帧间匹配估计雷达的运动输出当前帧的位姿并发布里程计话题。laserMapping则把特征点与全局地图做配准不断优化位姿并更新地图。对排错来说你只需要清楚一点laserOdometry订阅的是scanRegistration输出的特征点laserMapping订阅的是laserOdometry输出的位姿和关联点云。如果中间任何一个话题名对不上或者时间戳不匹配后一级节点就会假装“没收到数据”。2.2 Gazebo里的雷达模型、点云话题与坐标系XTDrone里的3D激光雷达模型一般基于Gazebo的gpu_laser或ray传感器插件。注意gpu_laser在Gazebo 9和部分ROS版本里经常被吐槽“发布频率不够稳定”但在XTDrone中通常可以正常使用。雷达发布的话题一般是/lidar/point_cloud或类似于/cloud的名字具体要看XTDrone的机载模型配置文件。你可以用rostopic list查看所有话题找到名字里带point_cloud、cloud、lidar或velodyne的话题就是雷达点云。坐标系方面XTDrone默认的TF树一般包括map、odom、base_link或base_footprint以及雷达自身坐标系比如laser、velodyne、lidar_link。A-LOAM运行时会要求点云消息里的frame_id和TF树里雷达的坐标系一致否则后续的坐标变换会报“frame_id不匹配”或“未知坐标系”。这也是很多人“点云明明有但A-LOAM就是不动”的真实原因。3. 跑通A-LOAM之前先把环境这关过了3.1 依赖检查PCL、Eigen、Ceres缺哪个都不行A-LOAM对依赖版本比较敏感。它在ROS Melodic和Noetic下都能编译但前提是PCL版本、Eigen版本和Ceres版本匹配。XTDrone官方文档里推荐的是Ubuntu 18.04 ROS Melodic很多同学是在Ubuntu 20.04 ROS Noetic下尝试也能跑就是编译时偶尔会遇到Ceres或Eigen的接口变化。依赖检查可以按下面几条来PCLpcl_ros必须装A-LOAM的代码里大量用到PointCloud2和pcl::PointCloudpcl::PointXYZI。如果连PCL点云类型还没装好编译会直接卡在头文件层面。EigenA-LOAM需要Eigen3而且最好使用系统安装的版本。某些手搓安装的Eigen版本太新或太旧会导致alloca、aligned_allocator这类报错。Ceres用于后端优化。Ceres 1.14.0是A-LOAM最常见的适配版本如果你装了Ceres 2.0以上的版本编译时可能遇到ceres::LocalParameterization相关接口变化需要做适配。检查完依赖后进入A-LOAM的catkin_ws编译。这里我建议用catkin_make而不是catkin build虽然两者都可以但很多教程默认的A-LOAM的CMakeLists是按catkin_make风格来的用catkin build偶尔会出现找不到依赖的问题。3.2 编译A-LOAM最容易翻车的三个地方第一个是Ceres版本与代码不兼容。如果你编译时报error: ‘LocalParameterization’ is not a member of ‘ceres’说明Ceres版本太新代码里使用的ceres::LocalParameterization在新版中被改名或移除。解决办法是要么把Ceres降级到1.14.x要么按新版接口修改代码但新手不建议改代码直接降级最省事。第二个是编译过程中内存不足。A-LOAM的laserMapping.cpp模板实例化非常吃内存虚拟机或小内存机器编译时容易直接卡死。建议打开~/.bashrc里的ROS环境后用catkin_make -j2限制并行编译进程降低内存峰值。第三个是缺少/usr/include/eigen3软链接。部分系统安装Eigen后头文件在/usr/include/eigen3/Eigen而A-LOAM代码里#include Eigen/Dense需要在/usr/include/Eigen路径下能找到。遇到Eigen/Dense: No such file or directory时可以执行sudo ln -s /usr/include/eigen3/Eigen /usr/include/Eigen做完这一步大多数Eigen找不到的问题都能解决。还没编译过A-LOAM的人优先把这三个坑提前避开。3.3 启动XTDrone后先确认雷达数据是真的在发布不要一上来就launch A-LOAM先启动XTDrone仿真环境然后打开一个终端执行rostopic list查看是否有点云话题。如果有再执行rostopic hz /lidar/point_cloud这里的/lidar/point_cloud要替换成你的实际话题名。正常情况会看到类似average rate: 10.0的输出说明雷达正在以10Hz左右的频率发布数据。接着在Rviz里添加PointCloud2显示把固定坐标系Fixed Frame改成雷达坐标系或map再选择对应的点云话题如果能看到环境中建筑的点云轮廓说明XTDrone和雷达传感器工作正常。这一步非常关键因为“A-LOAM没点云”很可能不是你代码的问题而是仿真环境压根没把点云发出来。4. 没有点云从话题、时间戳和TF三个方向排查4.1 话题名对不上是“没有点云”最多见的原因A-LOAM默认订阅的话题名是/velodyne_points代码在laserMapping.cpp和scanRegistration.cpp初始化时写死了这个名称。XTDrone里雷达点云话题往往不叫这个名字可能叫/lidar/point_cloud、/cloud_registered或/gazebo/lidar/pointcloud。两者不一致A-LOAM自然收不到数据Rviz里选A-LOAM相关的话题也是空的。处理方法有两个。一是修改A-LOAM代码里的订阅话题名找到scanRegistration.cpp里的ros::Subscriber subLaserCloud nh.subscribesensor_msgs::PointCloud2(/velodyne_points, 100, laserCloudHandler);把/velodyne_points改成XTDrone里的实际话题名。二是用rosrun或launch文件里的remap参数在不改代码的情况下把话题重映射remap from/velodyne_points to/lidar/point_cloud/我建议优先用remap方式因为以后换雷达模型时不用重新编译代码。改完后用rostopic echo /velodyne_points | head验证一下确认消息真的在流动。4.2 时间戳和TF问题常常被误判成“没有点云”当你确认话题名正确Rviz里也能看到点云但A-LOAM仍然不输出任何东西时请把注意力转移到时间戳和TF上。A-LOAM里的laserOdometry节点不仅需要点云还需要TF树提供雷达坐标系到base_link或odom的变换。它内部使用tf::transformListener和tf::waitForTransform等待坐标变换。如果时间戳差距过大比如雷达点云的时间戳是Gazebo当前时间但TF树里的变换只发布到了过去某个时刻节点就会一直等待表现为“卡住不动”而不是直接报错。常见的排查手段是查看TF树rosrun tf view_frames或者用tf_monitor看一下各坐标系的发布频率和时间延迟。如果map、odom、base_link、雷达坐标系之间的TF断链A-LOAM是不可能正常启动的。很多人在XTDrone里直接启动A-LOAM却没有启动XTDrone自带的TF发布节点导致的结果就是“点云话题有数据A-LOAM没有任何反应”。另一个容易忽略的是使用rviz时设置了错误的固定坐标系。如果你把Fixed Frame设成map而当前没有map到雷达坐标系的TFRviz里的点云就会消失或漂移。这种情况不算A-LOAM的问题但很容易让人觉得“没有点云”。4.3 点云动了A-LOAM却没输出先看特征点话题还有一种情况原始点云话题一切正常Rviz里也能看到环境轮廓但是A-LOAM的里程计没有输出。这时不要死磕原始点云去看scanRegistration是否发布了特征点话题。执行rostopic echo /laser_cloud_corner如果这条命令完全没有输出那问题出在scanRegistration的特征提取环节。多半是它收到了点云但因为点的数量、时间戳或坐标系的问题没有成功发布特征点。你可以打开scanRegistration.cpp的源码在特征提取函数前加一行ROS_INFO打印点云点数看看是不是接收到的点云点数特别少。Gazebo中的雷达如果扫不到空旷区域以外的物体或者雷达模型安装高度导致点云几乎全是地面点特征点数量会非常少甚至为0。遇到这种情况不要急着改代码先把雷达的安装位置调高一点或在Gazebo世界里增加一些建筑物、箱子、墙等结构让周围环境有明显几何特征。A-LOAM对空旷环境很不友好它靠角点和平面点来匹配环境越有“棱角”越容易跑通。5. 坐标系报错frame_id与TF树的完整处理思路5.1 先把坐标系之间的关系捋清楚A-LOAM运行过程中的核心坐标系有三个map、odom和body或base_link。再加上雷达自身坐标系比如velodyne。它们之间的变换关系是map和odom之间的变换通常由建图或定位系统维护在A-LOAM里往往初始化为单位变换或由laserMapping输出。odom和body之间的变换表示无人机在里程计坐标系中的运动由A-LOAM的laserOdometry估计输出。body和雷达坐标系之间的变换通常是固定不变的安装外参比如雷达装在无人机下方、前方或顶部这个外参就是平移加旋转的static_transform_publisher。很多坐标系报错的本质是A-LOAM想要计算某个变换但TF树里缺少对应关系或者点云消息里的frame_id与TF树中的雷达坐标系名称不一致。5.2 frame_id不匹配时怎么定位和修改先做一次rostopic echo查看雷达点云消息里的frame_id到底叫什么rostopic echo /lidar/point_cloud/header/frame_id输出可能是laser、velodyne、lidar_link或base_link。记下这个名称。再看A-LOAM期望的是什么。A-LOAM在接收点云后会用header.frame_id作为点云所在坐标系然后通过TF查询该坐标系与机器人本体系、里程计系之间的变换。如果XTDrone里雷达坐标系叫laser但A-LOAM代码里硬编码的是velodyne就会出现“Could not get transform from laser to map”之类的错误。解决办法有两种一是修改XTDrone里雷达模型的坐标系名字让它叫velodyne二是修改A-LOAM代码中的坐标系名让它与XTDrone一致。我更推荐修改A-LOAM因为XTDrone里很多其他节点依赖laser这个坐标系动了雷达模型坐标系容易牵连别的功能。找到A-LOAM里使用tf::createQuaternionFromRPY或static_transform_publisher的地方把雷达坐标系名改成你的实际雷达坐标系名。需要修改的位置主要在scanRegistration.cpp、laserOdometry.cpp和laserMapping.cpp中的TF监听相关代码。5.3 常见坐标系报错的速查表报错信息原因方向Could not get transform from xxx to yyyTF树里缺少xxx到yyy的变换检查是否有对应坐标系的话题发布或时间戳是否同步frame_id [velodyne] does not match点云frame_id与A-LOAM期望不一致用remap或改代码统一坐标系名称Unknown frame_id [laser]TF树里没有laser这个坐标系检查XTDrone的TF发布节点是否启动Message from [/lidar/point_cloud] has a non-sequential timestamp时间戳乱序或使用rosbag播放时数据顺序不对在Gazebo中重启雷达节点或检查时间同步从实际使用频率来看Could not get transform和frame_id does not match是出现概率最高的两个。大多数情况下改坐标系名称或重映射话题后问题会立刻消失。6. 实操从启动XTDrone到A-LOAM正常出图的完整流程6.1 我建议的启动顺序很多人喜欢一次性launch所有东西结果出了错根本不知道是哪个环节的问题。我建议按下面顺序来每启动一个环节就确认一次数据第一步启动XTDrone仿真cd XTDrone roslaunch xtdrone x4.launch不同版本启动命令可能有差异关键是看到Gazebo界面加载完毕无人机模型出现在环境中。第二步激活机载传感器。XTDrone中有些传感器默认不启动需要额外launch。如果你用的是带激光雷达的机载配置可以查找类似sensors.launch或lidar.launch的文件并启动。第三步检查点云话题rostopic list | grep -E cloud|lidar|velodyne rostopic hz /实际话题名确认点云以某一固定频率发布。第四步启动TF相关节点。XTDrone里一般会发布odom、base_link等TF但如果雷达坐标系是单独维护的可能需要你额外发布一个静态变换连接base_link和雷达坐标系rosrun tf static_transform_publisher 0 0 0 0 0 0 base_link velodyne 100第五步启动A-LOAMsource ~/catkin_ws/devel/setup.bash roslaunch aloam_velodyne aloam_velodyne_VLP_16.launch这里用的是A-LOAM自带的launch文件。如果你的雷达线束或话题名不同记得改launch里的参数。6.2 参数调整话题重映射、雷达外参和频率A-LOAM的launch文件里一般会配置几个关键参数lidar类型VLP_16、HDL_32等、scan_line线束数、以及话题重映射。以VLP_16为例对应scan_line为16angle相关参数也需要匹配雷达的实际视场角。XTDrone里的雷达模型未必是16线有可能是32线或64线。你可以打开XTDrone的雷达传感器模型文件看它设置的horizontal_fov、vertical_fov和samples参数然后把这些数值对应到A-LOAM的launch参数中去。这一步不做好的话A-LOAM可能提取不到足够特征或者建图出现严重畸变。如果XTDrone雷达话题名不是/velodyne_points在A-LOAM的launch文件中添加重映射remap from/velodyne_points to/lidar/point_cloud/改完保存重新launch。此时Rviz里应该能看到A-LOAM输出的特征点云和里程计轨迹。6.3 怎么判断A-LOAM是否真的跑起来了一个最直接的标准是看Rviz里有没有出现/laser_cloud_map话题。这个点云是laserMapping节点累加出来的全局地图如果它能随着无人机移动不断更新并且有清晰的墙体轮廓就说明A-LOAM的整个链路已经通了。另一个判断标准是看/laser_odom_to_init这条路径。在Rviz的TF显示中如果odom和base_link之间的连线随着无人机运动而平滑变化说明laserOdometry正在输出位姿估计。同时你也可以在终端里观察A-LOAM各节点的日志输出。正常运行时会有类似“add point cloud”“match cost”之类的打印信息。如果长时间没有任何打印那说明节点虽然启动了但没有真正收到有效数据重点还是回头排查话题和TF。7. 常见问题与避坑记录7.1 问题速查表从现象直接跳到解法现象可能原因排查/解决Rviz里没有任何点云固定坐标系设置错误或话题没选对把Fixed Frame改成雷达坐标系选中实际点云话题话题有数据但A-LOAM没反应话题名不匹配用remap把实际话题重映射到/velodyne_points启动A-LOAM后卡住不动缺少TF或时间戳不同步检查tf_monitor补发静态TF重启节点报frame_id [velodyne] does not matchXTDrone里的雷达坐标系叫别的名字统一坐标系名称或改A-LOAM代码建图轮廓很模糊/漂移雷达线束参数与XTDrone模型不一致修改launch中的scan_line、FOV参数Gazebo世界里看不到雷达扫描线雷达模型没有挂载或初始位置在障碍物内部检查无人机的urdf/SDF模型调整雷达安装位置每次遇到问题不要把三个节点一起杀掉重启先定位到具体节点。最简单的排查顺序是rostopic list看话题rostopic hz看频率rostopic echo看frame_idrosrun tf view_frames看TF树。7.2 我踩过的几个坑第一个坑是直接在A-LOAM默认launch里跑XTDrone的点云结果Rviz里什么都没有。后来才发现XTDrone的雷达话题名根本不是/velodyne_points而是/lidar/point_cloud。只加了一行remap整个系统就通了。所以遇到问题先别急着怀疑算法先确认仿真环境的数据出口。第二个坑是启动A-LOAM时没有等XTDrone的TF完全发布。Gazebo里无人机刚加载时base_link到雷达坐标系的静态TF有时候还没发布成功导致A-LOAM在启动后的几十秒里一直在等待坐标变换。解决方法是等Gazebo完全加载完、点云稳定刷新后再启动A-LOAM或者在launch里给静态TF发布加一点延时。第三个坑是坐标系命名问题。XTDrone里雷达坐标系叫laser而A-LOAM很多代码默认是velodyne。我一开始改了半天雷达模型后来才意识到直接在A-LOAM的所有TF相关代码里把velodyne替换成laser更省事。全局搜索替换的时候要注意别把话题名/velodyne_points也一起换掉不然又会出现新的话题不匹配。第四个坑是编译时Ceres版本过高。我机器上原本装了Ceres 2.1编译A-LOAM时直接报LocalParameterization错误。后来用源码重新编译了Ceres 1.14.0并切换到对应的版本分支编译就过了。7.3 三个提高成功率的小技巧如果你已经排查完所有常规问题还是不尽如人意可以试试下面三个技巧。第一个技巧把Gazebo里的世界环境换成一个有明显结构的环境。A-LOAM在太开阔的空间里容易出现退化比如在一个巨大的平地上它能提取的特征非常少。可以给XTDrone的世界里添加一些柱子、箱子或墙体模型也可以用现成的地图包。第二个技巧在launch文件中给A-LOAM的点云订阅缓冲队列调大一点。默认的队列大小在某些机器上会因为消息积压而丢数据调到200或300可以明显提升稳定性。第三个技巧多利用Rviz里的Topic状态面板。打开Rviz的“Panels - Topic Display”可以看到所有话题的接收频率。如果一个话题频率忽高忽低说明上游发布不稳定如果一个话题一直没有数据说明订阅关系没建立成功。这个面板比满世界打命令高效得多。按照文章里的思路从检查XTDrone的点云话题开始再到统一坐标系名称最后确认A-LOAM的输出话题一步步来大多数“没有点云”和“坐标系报错”的问题都能在一个小时内解决。实际操作一段时间后你会发现仿真里能稳定跑通A-LOAM再迁移到真机或者换到其他传感器平台逻辑也是一样的。我的建议是第一次跑通后把整套启动命令和你改过的配置文件都存档记录一下不同Gazebo环境、不同雷达线束下的适配方法后面再做别的传感器实验会省下大量时间。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门