尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

无人机2D激光二维运动规划实战:XTDrone SLAM建图与move_base避障详解

无人机2D激光二维运动规划实战:XTDrone SLAM建图与move_base避障详解 最近一直在折腾XTDrone这个无人机仿真平台想把“无人机基于2D激光Lidar做二维运动规划”这一整套流程彻底跑通。说老实话用2D激光做平面规划原理上并不复杂无非是SLAM建图加路径规划但真要在Gazebo仿真里把XTDrone、PX4、ROS和激光雷达这四样东西串起来还是能让你的心态崩上一回。这篇文章就是我实际调试过程中的细节汇总重点记录那些文档里不会写的小坑以及我踩过的几个高频报错和对应的解决方案。XTDrone是目前大家用得比较多的无人机仿真平台之一基于ROS和Gazebo集成PX4 SITL可以仿真多旋翼、固定翼和无人车也能挂上多种传感器模型2D激光就是其中最常见的一种。对做路径规划、避障算法验证的人来说XTDrone的价值很明显算法在真机上试错成本太高在仿真环境里先跑通再上真机效率会高很多。这篇文章适合谁看呢就是那些打算用XTDrone做二维导航、二维避障或者正在被“为什么我的激光雷达没数据”“为什么move_base一直报TF错误”折磨的同学。1. 拆解XTDrone做二维运动规划的技术链路1.1 XTDrone这套仿真平台能帮你验证什么先说一个我自己的认知XTDrone不是一个开箱即用的软件它更像一套组合件。它把ROS、Gazebo、PX4、MAVROS这些工具整合在一起让你在电脑里就能拥有一个可以正常起飞的虚拟无人机。你可以在里面测试飞控参数、传感器处理算法、决策规划算法甚至多机协同。对二维运动规划这个方向来说XTDrone最常被用到的场景是验证“无人机能否在某个固定高度上根据2D激光数据构建环境地图并规划出一条避开障碍物的二维路径”。听起来好像就是“小车导航plus版本”但无人机和地面无人车有个本质区别无人车天生在一个平面上运动而无人机是通过改变姿态和推力来控制位置的。所以无人机接住“二维速度指令”之后还要经过飞控那一层姿态控制才能真正飞起来这意味着整个链路由两部分组成上层的规划算法和下层的飞行控制。我在实际测试中习惯把这两部分分得很清楚。规划算法只管输出“尽量往哪个方向以多大速度走”飞控负责“让飞机真的往那个方向走”。只有先把边界划出来出了问题你才知道该去查哪一头。1.2 为什么偏偏选2D激光而不是3D激光或视觉同类的传感器方案其实不少3D激光雷达信息丰富、性能强视觉方案成本低、潜力大。那为什么很多二维运动规划项目还是会优先选择2D激光我自己总结下来有三个非常现实的原因。第一数据量小、实时性高。2D激光一帧LaserScan消息可能只有几百个浮点数以10Hz到20Hz的频率刷新在嵌入式设备上也跑得动。做规划的时候占据栅格地图更新、障碍物膨胀、局部避障这些计算都能很轻松地跟上。第二精度和稳定性好。2D激光测距精度在厘米级且不受光照影响这让它在建图和定位时非常可靠。在仿真里尤其典型激光模型比视觉相机模型好调得多。第三二维场景下配2D激光是够用的。如果飞行高度固定场景里障碍物的高度分布又比较均匀那么在某一高度平面上的激光扫描已经足够覆盖建图和避障的信息需求。当然2D激光也有明显的短板。它只有一个扫描平面如果无人机面对的是高低不一的障碍物比如桌子、椅子、垂下来的树枝2D激光就很容易漏掉障碍物或者把高处的物体当成可以穿越的平面。所以在XTDrone里做二维运动规划我强烈建议先把使用场景限定在比较平坦的室内环境或者低空平面运动中先验证算法链路再逐步增加复杂度。别一上来就找一个上下错落障碍物很多的世界那样出现问题的时候都分不清是传感器覆盖不够还是算法参数没调好。1.3 一条完整的二维运动规划链路长什么样先看整体链路Gazebo场景中的激光雷达发布/scan数据机器人底盘或飞控发布/odom里程计数据SLAM节点比如gmapping接收/scan和/odom产出占据栅格地图move_base等导航框架接收地图、里程计和激光数据规划全局路径并输出速度指令/cmd_vel无人机场景中速度指令还需要通过MAVROS转发给PX4飞控最终作用到电机输出。我经常提醒身边同学遇到问题先按链路分层排查。不知道是该查Gazebo还是查SLAM还是查move_base那就一层层看。比如地图质量不好就去看SLAM输入的两个数据——激光和里程计到底哪个有问题比如规划器明明输出了速度飞机却不动那就去看MAVROS转发和飞控模式是否正常。这种分段测试的思路能省掉大量猜谜时间。2. 仿真准备与激光雷达数据流验证2.1 启动XTDrone仿真环境的常见方式和检查项XTDrone的安装网上教程很多我这里不重复叙述重点说说装完之后怎么判断环境是否正常。一般按官方文档把PX4和XTDrone源码编译好后需要先用脚本启动PX4 SITL和Gazebo仿真世界。不同版本XTDrone的启动脚本名可能不同我以自己常用的一种为例# 先source工作空间 source ~/catkin_ws/devel/setup.bash # 设置PX4固件路径 export PX4_HOME... # 启动PX4Gazebo的仿真环境 cd ~/XTDrone/scripts ./px4_start.sh如果你的版本里没有这个脚本也可以直接通过roslaunch方式启动比如启动一个带有车辆的仿真world。关键是启动完成后确认这些内容都已经就绪Gazebo窗口出现场景中有一架多旋翼或者无人车ROS master正常你可以在另一个终端里执行rostopic list看到话题mavros相关节点已经跑起来能够和PX4 SITL通信。我最常遇到的一个问题就是另开终端后rostopic list为空或者提示无法连接ROS master。这种情况下百分之九十都是环境变量问题。检查一下~/.bashrc里的ROS_MASTER_URI是不是指向localhost以及是否source了正确的工作空间。如果这些都没问题再检查是不是同时开了多个roscore。有一个干净的做法把需要用到的source语句和PX4_HOME写进一个独立的脚本每次开终端先执行它避免跟其他ROS环境串了。2.2 激光雷达数据流怎么确认是通的仿真环境起来后第一步不是急着跑SLAM而是先确认激光数据有没有正常发布。最简单的办法rostopic list | grep scan如果看到了类似/scan的话题再打印一帧看看内容rostopic echo /scan -n1正常会输出LaserScan消息里面有angle_min、angle_max、angle_increment、range_min、range_max和ranges等字段。ranges数组就是激光测距的距离值。看一眼ranges长度就能估算出激光的角分辨率比如360个点对应1度一束720个点对应0.5度一束。这个参数会影响后面的建图精度和避障灵敏度。再推荐用RVIZ做可视化。打开RVIZ把Fixed Frame设置成laser或者base_link添加LaserScan显示就能在界面上看到激光点云。如果什么都看不到先点开LaserScan的属性检查话题名是否正确再检查Fixed Frame是否选对了坐标系。很多时候激光是正常发布的只是RVIZ里Fixed Frame设置成了map而map对应的TF树还没建立所以显示不出来。这里给新手留个细节不同仿真模型发布激光的话题名不一样可能是/scan也可能是/rplidar/scan、/laser/scan这些。后面跑SLAM或者move_base的时候一定要把所用参数里的话题名跟实际话题对齐。最常见的“明明有激光但算法就是收不到”的问题根源就是消息话题名没对上。解决的方法是在launch文件里用remap把话题统一。比如在move_base的launch中写上remap fromscan to/scan/这样不管传感器真实发布在哪个话题算法内部都订阅统一的/scan能少踩很多坑。2.3 坐标系和TF树最容易忽略但影响最大的环节接下来我要重点强调一个特别容易被忽略的环节就是坐标系和TF树。二维运动规划看起来是“拿激光扫一圈然后建图、导航”但背后依赖的是一棵完整的TF树。不同坐标系之间的转换如果断了gmapping、amcl、move_base统统都会报错。做二维导航时至少要保证这样的TF链路完整map或odom→ base_link → laser_frame。如果此时还有一个无人车或者机架模型那么base_link下面可能还挂着base_footprint、laser_link这样的子坐标系。在启动仿真环境后我建议立刻用这两个工具检查TF树rosrun rqt_tf_tree rqt_tf_tree # 或者 rosrun tf view_framesrqt_tf_tree可以实时看TF树当前有哪些坐标系、哪些frame之间的变换在发布view_frames会生成一个PDF帧图文件。如果看到laser_frame是孤立的或者根本没有laser_frame那就说明激光雷达模型的坐标系没有挂到机器人模型上。排查的思路通常有两个方向。一是检查机器人的URDF或者模型SDF文件看有没有定义laser到base_link的joint。另一种是检查Gazebo激光插件的配置看插件的frameName是否和URDF里一致。如果只是临时调试也可以先用静态坐标系发布节点应急顶上rosrun tf2_ros static_transform_publisher 0 0 0.1 0 0 0 base_link laser这条命令会把laser坐标系固定在base_link上方0.1米的位置。对于仿真中的快速验证来说这个应急方案能让你先跑通算法但后续还是要回到模型文件里把坐标定义写正确否则在更复杂的多机场景或真机环境中会出大问题。3. 从激光建图到路径规划完整实操记录3.1 用gmapping快速产出占据栅格地图确认激光和TF都正常之后就可以开始建图了。二维激光建图最常用的开源方案是gmapping它在ROS里多年稳定参数比较保守适合做最初的链路验证。启动命令很简单roslaunch gmapping slam_gmapping.launch如果gmapping参数里订阅的话题跟你环境里的激光话题不一致先remap一下。启动后用rostopic list确认一下有没有/map话题再用rviz打开map显示就能看到地图在慢慢建出来。但建图不是自动完成的你需要让机器人跑一跑。在无人车仿真里很简单用teleop_twist_keyboard手动键盘遥控车跑一圈就行在无人机场景里就麻烦一些你需要先通过PX4起飞到一定高度再让飞机平移或者旋转。我在实测中习惯先用脚本把无人机发送到目标高度再通过MAVROS发送速度指令让飞机以较慢速度绕场一圈同时观看rviz里地图的建造成果。建图完成后一定要记得保存地图rosrun map_server map_saver -f ~/maps/indoor_map这条命令会生成一个.pgm图像文件和一个.yaml参数文件。地图保存好之后后续做路径规划就可以直接加载这张静态地图不必每次重新建图。对于仿真里的重复测试来说这个步骤能明显提高效率。建图过程中需要特别留意的是如果速度太快、转弯太急里程计和激光对不上地图就容易出现重影、扭曲。这就像你一边快速转动手机一边打开全景拍照照片多半是糊的。所以在建图阶段尽量让机器人低速、匀速、小角度转弯地图质量会明显好很多。3.2 配置move_base全局路径规划与局部避障建完图之后下一步就是把规划层跑起来。ROS里的move_base框架是二维运动规划的标准组合它内部集成了全局成本地图、局部成本地图、全局规划器、局部规划器和恢复行为是一个比较完善的导航框架。在无人机固定高度平面运动场景下move_base的行为跟无人车非常类似。一个最简的启动方式是通过launch文件拉起move_base同时加载三份参数全局成本地图参数、局部成本地图参数和规划器参数。这里我给出一个非常基础但能跑的配置骨架重点是让大家看清楚各个参数的作用。launch node pkgmove_base typemove_base respawnfalse namemove_base outputscreen param namebase_frame valuebase_link/ param nameglobal_frame valuemap/ param nameodom_frame valueodom/ rosparam file$(find your_pkg)/cfg/costmap_common.yaml commandload nsglobal_costmap/ rosparam file$(find your_pkg)/cfg/costmap_common.yaml commandload nslocal_costmap/ rosparam file$(find your_pkg)/cfg/local_costmap.yaml commandload/ rosparam file$(find your_pkg)/cfg/global_costmap.yaml commandload/ rosparam file$(find your_pkg)/cfg/teb_local_planner.yaml commandload/ /node /launch在costmap_common参数里最关键的是把observation_sources改为laser_scanner并指定sensor_frame、data_type为LaserScantopic为/scan。这样move_base才能动态感知周围的障碍物。在local_costmap参数里我一般把局部规划器选为TebLocalPlannerROS或DWAPlannerROS。两者中TEB对轨迹平滑性和速度约束的支持更好适合需要保持稳定飞行的无人机场景如果只是快速验证链路DWA更简单一些。启动move_base后可以先用rviz里的2D Nav Goal按钮设置一个目标点让规划器自动生成路径。如果路径能出来并且move_base有/cmd_vel输出说明规划链路已经通了。用命令行也可以发布目标但格式稍复杂我还是建议新手先在rviz里操作直观很多。3.3 无人机场景把cmd_vel转给PX4飞控前面我提到move_base输出的是/cmd_vel话题这个消息给无人车用没问题给无人机用就还得转一道手。XTDrone里PX4飞控和ROS通信是通过MAVROS完成的无人机需要在offboard模式即外环控制模式下接收来自上位机的速度指令。实际项目中我写了一个非常简单的ROS转发节点订阅move_base的/cmd_vel转换为TwistStamped消息后发布到/mavros/setpoint_velocity/cmd_vel。核心代码如下#!/usr/bin/env python3 import rospy from geometry_msgs.msg import Twist, TwistStamped def cmd_vel_cb(msg): out TwistStamped() out.header.stamp rospy.Time.now() out.header.frame_id base_link # ROS: x前y左z上PX4 NED: x前y右z下 out.twist.linear.x msg.linear.x out.twist.linear.y -msg.linear.y out.twist.linear.z 0.0 out.twist.angular.z -msg.angular.z pub.publish(out) rospy.init_node(cmd_vel_to_mavros) pub rospy.Publisher(/mavros/setpoint_velocity/cmd_vel, TwistStamped, queue_size1) rospy.Subscriber(/cmd_vel, Twist, cmd_vel_cb) rospy.spin()这段代码里我特意做了坐标系的符号处理因为ROS用的是ENU东北天PX4常用NED北东地直接原样转发的话y轴和z轴速度方向会不对飞机很可能横着飞甚至往下掉。这是我在实际调试中踩过的一个很关键的坑。另外offboard模式下MAVROS要求速度指令必须以一定频率持续发送一般要超过2Hz否则PX4会自动退出offboard模式。所以这个转发节点一定不要用单次发布要在回调里持续发送或者用定时器维持输出。最简单的做法就是像上面代码一样每收到一个/cmd_vel就立刻转发只要move_base还在运行频率通常足够。3.4 起飞和导航之间的安全切换策略还有一点是关于控制模式切换的顺序。不要一启动仿真就让飞机进入offboard模式然后直接发速度。无人机起飞阶段最好先让PX4自稳起飞用MAVROS的takeoff指令起飞到安全高度确认高度稳定之后再切换到offboard模式并且速度指令的z值强制为0保持高度稳定。下落时也要有一个下限判断一旦飞机高度低于某个阈值就要强制切换回位置控制或自稳模式。我见过不少同学在仿真里“一起飞就乱飞”排查到最后往往并不是规划算法有问题而是offboard模式没有正确切换或者速度指令坐标系符号问题导致的。所以建议在转发节点里加日志把输入和输出的速度实时打印出来。这样一旦飞机走偏你能很快判断是规划器给的指令不对还是转发环节出了问题。这种调试习惯很重要在真机上甚至能避免炸机。4. 高频报错实录与解决方案速查4.1 半天等不来/scan数据话题名、frame_id、插件全排查先收录一个我几乎每次都会被问到的报错gmapping启动了但是地图一直不更新rostopic list里明明能看到/scan但echo没有数据。这种情况首先要区分“话题存在但没数据”和“话题根本不存在”。如果话题存在但echo没数据大概率是Gazebo里的激光插件没正常工作先看Gazebo日志检查无人机模型是否真的挂载了激光雷达插件插件的传感器名字和话题名是否匹配。如果话题根本不存在就要检查启动的模型文件里是否包含激光传感器或者是否在launch文件里被注释掉或remap成了别的名字。另一个常见原因是frame_id不匹配。比如雷达插件的frameId配置成了laser_frame但你的模型里坐标系叫laser导致tf关系对不上gmapping拿不到有效数据。这种情况在Gazebo里往往表现为激光数据有话题、有值但就是不参与建图。解决方法是统一命名把雷达插件的frameName和URDF/SDF里的link名改成一致然后重启仿真。这个细节很小但排查起来相当浪费时间。4.2 TF断链报错找不到从map到laser的变换这个报错几乎是二维运动规划里最常见的。错误提示一般是Could not get transform from [map] to [laser]或者Could not get robot pose in map出现这些报错说明move_base或gmapping拿不到完整的TF树。原因无外乎以下三种一是里程计odom没有发布看/odom话题是否有数据二是base_link和odom之间的变换缺失这通常是底盘驱动节点没起来或者MAVROS/底盘控制器没正确发布TF三是laser与base_link之间的变换缺失这在2.3里讲过了检查模型文件或补静态TF。排查顺序我一般是这样先看TF树图形定位断链位置再针对断链的位置去看对应的发布节点是否运行、话题是否有数据最后再去修改模型或配置。千万不要一上来就乱改参数容易制造新的问题。如果同时运行了多个机器人发布同一话题也可能导致TF树混乱这也是多机仿真中常见的错误根源。4.3 地图建得歪七八扭降速度、查里程计、换方案gmapping在建图时偶尔会出地图重影、漂移、歪斜的情况。这个问题的根因一般不在gmapping而在上游的激光和里程计。你可以先打印看一下/odom观察机器人静止的时候位置是否基本不变如果静止时里程计都在飘那地图肯定建不好。在XTDrone的无人机仿真里里程计通常由PX4 SITL的机载状态估计提供通过MAVROS发布。有时候机体一直有微小漂移比如风的影响、飞控参数扰动会导致里程计缓慢偏移。解决的办法有几个一是在建图时降低速度和角速度让数据尽量稳定二是查看PX4的EKF2/IMU参数有没有明显问题三是换用cartographer这种更鲁棒的SLAM算法。如果只是做二维规划链路验证我个人推荐先用无人车仿真模型跑通流程因为轮式底盘在Gazebo里的里程计通常更稳定能少掉一半烦恼。等算法稳定之后再把同一套逻辑搬到无人机上验证飞行控制部分。这种由易到难的递进方式能让你把“规划问题”和“飞行控制问题”分开排查。4.4 Move_base启动报错和话题不对齐move_base启动时报错可以列一个速查表这些是我实际遇到的最高频的几个错误现象可能原因解决办法No valid odometry data里程计话题为空或频率过低检查/odom发布确认odom话题在costmap配置里正确Could not get transform from map to base_linkTF树断链或缺map检查map是否发布SLAM/amcl是否在跑补全TF链路LaserScan from sensor does not have required timestamp激光话题时间戳异常检查Gazebo激光插件调整仿真更新频率或时间戳设置global costmap cannot update没有可用传感器数据检查LaserScan话题名、sensor_frame参数如果出现话题不对齐的问题最稳的解决方法就是remap。不要在多个文件里反复copy一遍话题名而是统一在move_base的launch里用remap把分散的话题规整到一起。这个做法在项目里也便于维护别人接手项目时一眼就能看清数据流。4.5 无人机乱飞、掉高、offboard模式失灵无人机场景最让人揪心的“报错”不是文字报错而是飞机突然乱飞。从调试经验看原因集中在三类。第一offboard模式没有正确进入。PX4对offboard模式有严格的条件比如要求已经有持续的速度或姿态指令在发送否则拒绝切换。第二坐标系符号问题就像3.3里提到的ROS的ENU到PX4的NED不转换飞机就会按错误方向飞。第三速度指令发送频率不够导致PX4超时自动退出offboard模式恢复为自稳模式飞机表现就是突然不受上位机控制。解决的方法也很直接检查MAVROS的mavros/state话题确认当前控制模式正确确保转发节点以足够频率持续发送在代码里加高度保护如果低于安全距离立刻切回位置控制或手动模式。这是二维运动规划里最容易破坏“二维”假象的地方——很多算法只输出平面速度却忘了无人机的高度也需要被管住。4.6 Gazebo卡顿严重仿真性能如何取舍最后说一个很现实的问题跑XTDrone时Gazebo常常卡得要命。二维激光数据量不大真正吃资源的是3D渲染、物理引擎和各种关节的碰撞计算。如果场景里对象太多加上RVIZ显示大量点云掉帧是必然的。我的建议是做算法验证时把Gazebo的画质参数降到最低去掉动态物体减少光照特效。RVIZ里只保留必要的LaserScan、Map和Path显示不要开PointCloud2显示那样会非常占GPU资源。还可以降低激光的更新频率比如把Gazebo里URDF激光插件的update_rate从10Hz降到5Hz对规划算法来说完全够用卡顿能明显缓解。性能优化不一定影响算法结论但能让你的调试效率翻倍。5. 真实调试体会与建议写到这里我想分享一个自己反复验证过的经验。第一次跑通XTDrone二维运动规划时我把大量时间花在排查各种报错上后来才发现那些看似吓人的报错绝大多数是TF树断链、话题名不统一、坐标系符号错误这三个问题导致的。所以现在我做这套流程时会先花十分钟检查三样东西rostopic list里有哪些关键话题、rqt_tf_tree里TF链路是否完整、RVIZ里LaserScan是否正常显示。这三项都没问题后面的算法调试基本就是按部就班。如果你也在做类似的方向建议不要照搬网上所有命令先理解这几个要素无人机是什么控制模式、激光数据发布在哪个话题、坐标系的定义是什么、规划的最终目标是什么。把这几个问题想清楚比别人给你一百个解决报错的命令都管用。希望这篇记录能帮你在XTDrone里少走点弯路早点把二维运动规划跑出自己的效果。
返回列表