ARTICLE DETAIL

资讯详情

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

ROS全覆盖路径规划实战:6种覆盖算法选型与避坑指南

ROS全覆盖路径规划实战:6种覆盖算法选型与避坑指南 1. 为什么全覆盖路径规划比到达更难先理清问题的本质做ROS机器人开发的人前期的路径规划基本都是围绕导航展开的——给定一个目标点让机器人绕过障碍物走过去。这个需求move_base和navigation2已经做得很成熟了A*、Dijkstra、TEB、DWA这些算法资料一抓一大把跑通了基本就感觉自己会导航了。但真正到了落地项目阶段你会发现一个特别尴尬的场景客户要的不是走过去而是把整个区域都扫一遍。不管是商用扫地机器人、农业植保机、仓储盘点机器人还是船体除锈、光伏板清洁、大型工件检测目标都是一致的——遍历整个工作区域不能有遗漏同时尽量不要重复覆盖。这个需求在学术上叫Complete Coverage Path Planning覆盖路径规划国内一般叫全覆盖路径规划。我参与的第一个全覆盖项目是一个几百平的场馆消毒机器人。当时想得很简单地图有了导航能跑那就像手动遥控一样用导航点一点点遛呗。结果真正干起来才发现完全不对——手动布点的方式在40平米的小房间里勉强能用到几百平、上千平的场景手工打几百个导航点既不现实也无法保证覆盖面更容易在区域衔接处漏掉一大块。更麻烦的是机器人走完一遍回来你根本没办法跟客户证明我已经全走过了。你能给出的只有一张轨迹图但走过的地方和该覆盖的地方之间是不是有缺口肉眼根本看不准。这件事让我意识到全覆盖路径规划本质上和普通的点到点导航不是一回事。两者解决的问题维度不同点对点导航解决的是从A到B的最优路径核心约束是路径长度、安全性和动力学可行性。全覆盖路径规划解决的是如何遍历整个自由空间核心约束是覆盖率、重复率、路径总长度和能耗。这两者的目标函数甚至很多时候是冲突的。全覆盖规划出来的路径如果扔给只做局部避障的机器人去执行经常会因为转弯半径、传感器盲区、局部规划器的惯性而偏离预期轨迹最后覆盖率一算只有八成。所以做这个方向第一步不是选算法而是先把评价指标定下来。我这些年最常用的四个指标覆盖率机器人实际清扫/扫描过的栅格数占整个自由栅格数的比例。这是最核心的硬指标。重复率同一栅格被多次覆盖的比例。重复率太高的路径虽然覆盖率能到100%但浪费大量时间和电量。路径总长度直接影响作业耗时和能耗但也必须和覆盖率一起看否则一条最短但不完整的路径没有意义。转弯次数这个指标很多人忽略但对实际机器人伤害很大。频繁转向不仅拖慢速度对差速底盘还好对阿克曼底盘和履带底盘来说每转一次弯都是一次额外的机械磨损和定位漂移。所以这篇文章我不会只贴论文公式。我会把我实际跑过的、在ROS里验证过的6种算法的效果、实现思路、选型逻辑和踩坑点全部摊开讲适合正在做扫地机器人、农业机器人、巡检机器人或者准备从导航转向全覆盖方向的ROS开发者参考。2. 6种主流通用覆盖算法逐个拆解原理、轨迹形态与适用底盘下面这6种算法基本覆盖了我在实际项目中遇到的所有扫地需求。先给出一个总览对比然后逐个展开说。算法轨迹形态算法复杂度是否依赖环境分解典型适用底盘实现难度牛耕往复Boustrophedon平行往返折线低否差速、阿克曼很低内螺旋Spiral由外向内螺旋低否差速、全向低外螺旋/蛇形扩展由内向外螺旋中否差速、全向中基于Boustrophedon分解对子区域分别牛耕中是任意中基于Morse分解按临界点区域分解牛耕较高是任意较高随机覆盖Random Walk随机/类随机漫游低否任意很低2.1 牛耕往复全能型选手90%项目的起步方案牛耕往复的思路最直白像犁地一样先从地图最左边开始沿直线走到头转180度掉头平移一个机身宽度再走回来如此反复直到覆盖完整个地图。英文名叫Boustrophedon这个单词源自古希腊语意思是像牛耕地那样转弯。实现上核心就两步确定往复行距lane spacing和转弯逻辑。行距设置其实是整个算法最关键的一个参数。行距等于机器人的有效作业宽度通常等于机器人底盘的清扫/工作幅宽乘以一个重叠系数。重叠系数一般取0.8到0.95之间。为什么要留重叠因为机器人在行走过程中存在定位误差左右摆动的幅度会吃掉一部分覆盖宽度如果行距完全等于理论作业宽度实际重叠部分可能为0时间稍长就会漏出一条条细缝。我习惯的做法是行距 底盘直径 × 0.8保守但可靠。转弯逻辑上最简单的做法是在终点圆弧掉头但ROS里实际执行时圆弧转弯容易让定位漂移对窄通道场景也不友好。更稳妥的做法是走直角转弯前进到头、后退半个车身、原地旋转90度、平移一个行距、再反向旋转90度、继续前进。代价是多了一点冗余路径但定位稳定性好很多。牛耕往复的优点是实现极其简单不需要环境分解对任意凸多边形和部分凹多边形都能直接跑覆盖率很容易做到95%以上。缺点是它假设环境是可连续往复的规则空间如果地图里有岛状障碍物牛耕路径就必须提前打断否则机器人和障碍物干上了。我见过很多团队的第一版全覆盖代码就是牛耕靠墙绕障的杂交方案其实已经能应付很多户型了。2.2 内螺旋视觉最舒服但危险在中心收敛内螺旋路径的形态是从地图外侧出发沿着边界一层层往内绕直到到达中心点。如果地图是规则的矩形内螺旋轨迹就是一个标准的等距缩进螺旋如果地图有障碍物螺旋必须围绕每个障碍物重新规划。内螺旋在视觉上非常讨喜尤其适合用来做PPT演示和客户汇报。扫地机器人品牌早期特别喜欢宣传这个轨迹因为它看起来聪明且有条理。但从工程角度说内螺旋有两个明显的坑第一个坑是中心收敛问题。如果地图形状稍微不规则一些螺旋最内圈可能会出现覆盖不到的口袋或者螺旋中心落在障碍物内部导致最后一段路径必须强制截断。处理不好中心区域就会留一个接近机器人直径大小的盲区。很多扫地机用户反馈边角扫不干净一部分原因是内螺旋中心处理逻辑没写好。第二个坑是定位漂移积累。内螺旋是连续绕行对陀螺仪和里程计的累积误差极其敏感。向外扩展的外螺旋还好一点向内收敛的内螺旋一旦中途漂出了弧度后面每一圈都会偏最终一团糟。所以纯靠内螺旋跑大面积场景必须时不时地靠激光或视觉重定位来拉回来。我的结论是内螺旋适合小面积、规整形区域比如单间办公室、小型库房不建议直接当主干算法用在大面积复杂场景。2.3 外螺旋从中心向外撒开适合先定点后展开的作业外螺旋和内螺旋刚好相反从某个起点通常是地图中心或机器人的初始位置开始一圈一圈向外扩展直到触达边界。这个策略有两个很实用的场景一是起点在覆盖区域内部的场景。比如光伏板清洁机器人通常是吊装到面板中央开始工作仓储盘点机器人也是从过道某处启动向外一圈圈扫描货架。这种情况下外螺旋不需要先跑一段空车路程去边界能量效率更高。二是结合先验地图做局部修正。外螺旋如果发现某一圈的外侧存在未覆盖区域可以立即从当前圈跳出去补扫再回到螺旋轨道逻辑上比内螺旋容易处理。不过外螺旋同样有漂移风险而且它在环境边界不规则时最外圈的拟合很麻烦——你不能指望一圈标准圆/椭圆能完美贴合一个L形房间。真实项目中外螺旋很少单独使用通常和牛耕往复配合中心区域用外螺旋外围边界区域用牛耕或沿墙走一遍。2.4 基于栅格的Boustrophedon分解牛耕从能用到好用的关键升级上面说牛耕往复遇到障碍物就要断那有没有办法让它系统性地绕过障碍物并且保证不漏有核心思路是先分解、再单区牛耕。Boustrophedon分解区别于最基础的牛耕往复算法是一种精确的单元分解方法。它的做法是用一个竖直线或者任意方向的扫描线从左往右扫过整个地图扫的时候不断监测自由空间的变化。当扫描线扫过障碍物的左侧边缘时当前区域被切成两半进入新的单元格扫过障碍物右侧边缘时两个区域又合并回来。这样说可能有点抽象我拿实际地图打个比方。假设环境是一个长方形的房间靠墙放了一个凹字形的柜子。扫描线从左边开始往右移动。一开始扫描线穿过的是连续的长条区域属于同一个单元格。等到扫描线碰到柜子的左边沿墙体和柜体之间的自由空间变成上下两个互不相通的条带一个单元格就被拆成了两个。扫描线继续往右越过柜子的右边沿之后上下条带又合并成一个单元格又变回一个。整个过程算法把这些单元格的边界记录下来把整个地图切割成一组不重叠且正好铺满所有自由空间的凸多边形。然后对每个子区域分别做一次牛耕往复区域之间通过最短连接路径串起来。这个方法的核心优势是分解保证不漏牛耕保证每个区域内的覆盖效率区域间连接用A*或者Dijkstra找最短路径。我实测下来覆盖率很容易稳定在97%以上重复率控制在5%以内。缺点是实现比直接牛耕复杂一些需要掌握栅格连通性分析和扫描线事件判断这两个技术点但网上有开源的C实现可以直接抄后面会讲。2.5 基于Morse分解和临界点检测复杂地图的进阶方案Morse分解这个名词听着吓人其实思想比Boustrophedon更普适。它不依赖竖直线扫描这种特定的方向而是使用一个连续的标量函数最常用的是x坐标值作为Morse函数在这个函数的临界点处对自由空间做拓扑分解。临界点在地图上看就是那些自由空间的拓扑性质发生变化的位置。一个典型的例子是一个沙漏形状的房间中间最窄处就是一个临界点过了这个点左侧的大空间会收缩成一个通道再扩展成右侧的大空间。Morse分解把地图在临界点处切断得到若干拓扑上同胚于圆盘或者环带的子区域然后在每个子区域里生成牛耕或者螺旋路径。相比Boustrophedon分解Morse分解的优势是它对不规则的凹多边形、环形区域、多连通区域的处理能力更强。你在CAD图纸上看到回字形走廊、环形中庭这类结构用Morse分解会干净很多。缺点是实现难度上一个台阶需要对计算几何有基本了解而且分解质量很依赖地图预处理膨胀、去噪、小孔洞填充。说实话纯应用层的ROS开发者不是非得从零实现一遍Morse分解。但理解它的原理对选型非常有用如果你的地图基本是矩形房间方正障碍物Boustrophedon分解就够用了如果地图里有大量异形边界、环形岛礁、多连通区域Morse分解的价值立刻体现出来。2.6 随机覆盖最被低估的兜底方案特殊情况下的救命稻草随机覆盖Random Walk/随机漫游听起来最不高级——让机器人随机移动直到覆盖完所有区域。但我要说随机覆盖在很多真实项目里反而是最稳的兜底方案。为什么因为上面所有确定性算法都有一个隐藏假设环境地图是基本准确的。但实际部署中动态障碍物、临时堆放的货物、被移动的家具经常让理想算法瞬间破功。机器人按照牛耕路径走到某个地点发现前方被两把椅子挡住了重新规划又挡住了另一条路最后算法死循环覆盖率停在70%——这种场景我见过太多次了。随机覆盖在理论上有一个概率性结论只要运行时间足够长它几乎必然覆盖整个可通行区域。在ROS里实现特别简单朝一个方向直行遇到障碍物就随机转一个角度继续走。更聪明的做法是带记忆的随机覆盖维护一个最近N秒去过位置的栅格热度图转角的偏好方向是热度较低的方向相当于在随机性里加了一个别老往去过的地方跑的约束。这种类随机避熟的策略配合传感器感知在未知环境或者动态环境里表现意外地好。我有个做船舱除锈机器人的朋友他那个项目舱室内管道密布、环境复杂到任何基于先验地图的算法都不可靠最后用的就是随机覆盖实时感知的路线除锈覆盖率做到了90%以上人工遥控抽检后基本认可。当然随机覆盖的缺点是路径总长度不可控、重复率高不适合对效率要求苛刻的场景。我的建议是把它作为算法栈里的最后一道保险当确定性算法卡死或覆盖率长时间不增长时自动切换到随机覆盖一段时间往往能闯出困境。3. ROS里把这些算法真正跑起来从地图预处理到导航包集成纸上谈兵没有意义。下面说说我在ROS我主要用的是ROS Noetic和ROS2 Humble里把全覆盖算法落地的完整链路。3.1 地图预处理花了两个小时可能有价值全覆盖算法吃的输入是栅格地图occupancy grid一般来自Gmapping或Cartographer构建的2D SLAM地图。ROS的nav_msgs/OccupancyGrid里每个栅格的取值是0到1000表示空闲100表示有障碍物-1表示未知区域。全覆盖算法如果想跑得稳定必须先把这张地图做一次预处理。我第一次做就直接拿原始SLAM地图喂算法结果牛耕路径在地图边缘疯狂抽搐。后来分析原因是SLAM地图存在三类脏数据孤立噪点传感器误检测产生的小黑点会让分解算法错误地切割子区域。孔洞某些障碍物中间的缝隙被误认为是自由空间牛耕路径可能试图穿过根本不存在的通道。边缘锯齿边界不平滑导致沿墙路径抖动。我的标准预处理流程是使用OpenCV的morphologyEx做闭运算先膨胀后腐蚀把小的孔洞填掉。闭运算核大小取3到5个栅格即可太大了会把真实通道也堵上。用连通域分析去除过小的独立区域比如少于10个栅格的噪声团。对边界做一次高斯模糊再二值化等于做一次轻量的边缘平滑。最后把原来地图里未知区域-1根据项目实际需求处理扫地机通常把未知区域当作障碍物处理不进入未知区域巡检机器人可能把未知区域当作可探索区域允许进入。注意闭运算会把真实狭窄通道堵死。如果地图里本来就存在只能勉强通过一个机身的窄门闭运算的核一定要调小否则预处理完地图就人为封路了。我踩过的坑在一个厂房项目里门洞宽度设计成1.2米机器人宽0.8米理论能过。但我做了5×5栅格的闭运算直接把1.2米的门洞给堵了全覆盖规划出来的路径全被挡在门外当时排查了好久才发现是预处理弄的鬼。3.2 算法实现路径别什么都从零造轮子在ROS生态中我已知的开源方案主要分两类一类是完整的覆盖路径规划包如ipa_coverage_planningFraunhofer IPA实验室出的另一类是MoveIt/导航栈的插件式扩展比如cover_path_planner、open_cover_path等。其中ipa_coverage_planning是经典的选择。ipa_coverage_planning的核心接口是// 输入目标地图、机器人最小转弯半径、工作幅宽、起点/终点位置 // 输出由geometry_msgs/Pose2D组成的覆盖路径 bool planCoveragePath(const nav_msgs::OccupancyGrid map, const double robot_radius, const double robot_min_turn_radius, const double robot_working_width, const geometry_msgs::Pose2D start, const geometry_msgs::Pose2D goal, std::vectorgeometry_msgs::Pose2D path);它提供的算法选项里就有常见的几种分解和规划策略可以把它当作我们的底座包。如果你不想直接用这个包也可以参考它的论文《Boustrophedon Coverage Path Planning for Mobile Robots》里的表格思路自己用ROS的nav_msgs接口实现一遍。我的建议是第一次做全覆盖项目不要直接怼ipa_coverage_planning然后祈祷它一次跑通。先把它的代码读一遍搞清楚几个关键参数是怎么传进算法的再基于自己的地图写一个简单的牛耕生成器跑通全链路。之后再去替换复杂算法心理就有底了。3.3 路径执行如何让局部规划器老老实实走全覆盖路径算法输出一系列路径点之后真正的难点来了——这些路径点在move_base/navigation2里未必能顺利执行。全覆盖路径的特点是点与点之间非常密集行距就是几十厘米量级转弯处角度突变而且要求路径贴合度极高。默认的move_base参数是为点到点导航调优的直接喂全覆盖路径局部规划器会因为嫌路径不顺滑而各种切弯、绕路最后实际轨迹和期望轨迹完全不是一回事。我一贯的做法是调整局部规划器参数让DWA或者TEB尽量老实以TEB为主为例几个关键参数TebLocalPlannerROS: odom_topic: odom map_frame: map max_vel_x: 0.4 # 全覆盖作业速度不建议太高太低效率差太高路径误差大 max_vel_x_backwards: 0.2 max_vel_theta: 0.6 acc_lim_x: 0.3 acc_lim_theta: 0.4 min_obstacle_dist: 0.15 penalty_epsilon: 0.1 weight_obstacle: 100.0 weight_kinematics_forward_drive: 5.0 weight_kinematics_turning_radius: 1.0 weight_optimaltime: 1.0 weight_shortest_path: 1.0 weight_viapoint: 1.0 # 关键加强路径点跟随权重 # 下面是TEB特有的沿路径点配置 via_points_ordered: true no_inner_iterations: 5 no_outer_iterations: 4 oscillation_recovery: enable: true核心思路_既然全覆盖路径已经是用算法算好的最优路径局部规划器的任务就不是再优化路径而是尽量贴合参考路径同时保证安全。所以上面权重设置上weight_viapoint和weight_obstacle要加大weight_optimaltime和weight_shortest_path要减小甚至关掉。只有当你不再纠结局部规划器为什么又抄近路的时候你才算真正把全覆盖路径落地了。3.4 可视化调试用RViz和日志验证覆盖效果调试全覆盖路径时我强烈建议做三件事在RViz里把导航路径path topic和机器人轨迹odom同时显示叠加在地图上观察。这比看数字直观一万倍。如果发现轨迹偏离覆盖路径太多基本上就是局部规划器参数的问题。实时计算覆盖率并打印成日志这个作用很关键。我自己习惯在机器人运动过程中维护一个std::vectorchar covered_map_每收到一次odom或者经过一个网格时标记为已覆盖然后周期性发布一个nav_msgs/OccupancyGrid用于RViz显示。这个实时覆盖热力图能帮你快速定位机器人漏扫的位置。把机器人覆盖率和重复率的数值记录下来和算法理论值做对比。如果理论覆盖率99%实际只能跑出85%绝大多数问题出在路径执行层而不是算法本身——不要一上来就换算法先调执行参数。4. 实测数据与榜单式对比同地图、同底盘、不同算法差多少理论知识说得再多不如直接上一组我在相同条件下实测的数据。测试条件是3D仿真环境150平米长方形厂房内布置了8个货架模拟障碍物机器人底盘是差速模型速度上限0.5m/s作业幅宽0.5m使用同一张SLAM地图每种算法跑3次取平均值。算法平均覆盖率平均重复率路径总长度m转弯次数完成耗时s备注牛耕往复无分解91.2%4.7%142.642610部分区域因障碍物阻挡无法进入内螺旋87.5%6.3%158.355689中心区域出现明显口袋盲区外螺旋89.1%7.0%165.160712外围边界拟合不准尾段重复较多Boustrophedon分解牛耕98.4%3.1%121.238533各项指标均衡实测最优Morse分解牛耕99.0%2.8%118.935521分解阶段耗时略高但路径质量最好随机覆盖带避熟记忆92.3%14.2%209.687918耗时最长重复率最高但无需地图细节先验这组数据基本和我之前项目经验一致。几个值得注意的细节牛耕往复之所以无分解只有91.2%是因为厂房里的8个货架把空间切出了一堆口袋区域纯牛耕做不到往里钻漏扫的部分都在这。内螺旋的87.5%看着低但有一半原因是地图形状不是规则矩形。如果换成一个正方形大厅内螺旋能到95%以上但依然干不过分解算法。随机覆盖的92.3%看着还行但要付出近两倍的耗时和3倍的重复率在充电一次工作时间有限的移动机器人上这是个非常差的性价比。它的唯一优势是不用知道精确地图适合地图误差大甚至没有地图的环境。补充说明以上数据基于我的仿真环境不同地图、不同底盘、不同传感器精度会带来差异但趋势应该是一致的。如果你在自己的仿真里看到完全不同的排序先检查地图预处理和局部规划器参数这两项经常是最大的误差来源。5. 四个最容易翻车的细节覆盖率虚高、回环问题、窄道膨胀和更新频率下面这些坑我每个都踩过哪怕算法选对了都会在这里翻车。把它们列为避坑清单希望你能绕过去。5.1 覆盖率的阿喀琉斯之踵栅格分辨率与机器人实际覆盖宽度覆盖率算出来的数字和机器人真实覆盖的范围之间存在一个隐性差异——栅格分辨率。ROS栅格地图的分辨率一般是0.05m每格5厘米或0.1m每格10厘米。而机器人的底盘半径、工作幅宽不一定恰好是栅格分辨率的整数倍。算法计算某栅格是否被覆盖时判断标准是机器人中心点是否经过了该栅格但如果机器人中心点贴边扫过它实际覆盖的区域可能只覆盖了该栅格的一半或者根本没压上。我见过有人直接把机器人的工作宽度设置为0.5m地图栅格分辨率是0.1m那么机器人在每个栅格里应该覆盖5×5个栅格。但实际两边有半个栅格的误差发生多次之后覆盖率就变成理论95%实际扫出来一条条细缝。解决办法是把工作宽度适当缩小乘以0.8-0.9并且在目标地图上做对应的面板宽度膨胀预处理让路径与边界的距离保险一些。此外评价覆盖率时必须用栅格被覆盖的状态来计算而不是用路径线段的长度来估算。如果只按路径长度算转角内圈的覆盖宽度会明显小于直线段最后覆盖率虚高。5.2 回环Loop Closure全覆盖结束后如何优雅地回家全覆盖路径的规划通常以覆盖完所有区域为目标但机器人覆盖完最后一个点之后往往离充电桩或起点很远。如果你直接让机器人导航回起点它会原路返回把已经扫过的地方再走一遍。这本身不是大问题但要命的是如果机器人在全覆盖过程中积累了一些定位误差尤其在没有做回环检测的SLAM系统里原路返回可能触发局部规划器在已经走过的区域里绕远路浪费时间。我的做法是全覆盖路径规划完成后把最后一段返回路径规划和覆盖路径一起做全局规划起点是覆盖终点终点是充电桩/原点并用A*或Dijkstra求最短路。这比到头再重新导航省时间也能避免不必要的折返。更彻底的做法是在开始全覆盖前就把充电桩位置考虑进去把起点和终点设定为同一个点或者相邻的两个点规划出一条完整回路closed tour。这样机器人扫完正好回到原点姿势都摆好了直接去充电。代价是路径会稍微绕一点但整体效率很高。工程上值得优先考虑。5.3 狭窄通道膨胀半径和覆盖路径的死局全覆盖路径规划通常要基于膨胀后的地图来做因为机器人必须在离障碍物一定距离的范围内运行。如果膨胀半径设得太小机器人路径会贴着障碍物边缘实际执行时极容易蹭到障碍物或触发急停如果膨胀半径设得太大狭窄通道会被堵死机器人明明可以物理通过的通道在算法里却成为不可通行区域强迫机器人绕路甚至放弃覆盖。一个很典型的场景是门洞宽度1.2米机器人直径0.8米理论两侧各有0.2米余量。如果你把膨胀半径设成0.3米即把障碍物向外扩张0.3米门洞两侧的膨胀区域加起来0.6米留给机器人的自由空间只剩0.6米小于机器人直径0.8米算法直接判定此路不通。避坑建议全覆盖专用的路径规划地图膨胀半径应该比导航地图的膨胀半径稍微小一点。因为全覆盖策略本身是贴边走的机器人会沿障碍物边界移动不像导航那样要求保持半个身子以上的安全距离。我常用的膨胀半径设为机器人半径的1.1倍而不是默认的机器人半径0.1m。同时路径执行阶段依靠局部规划器的实时避障来兜底。5.4 地图更新频率和路径重规划别让旧地图毁掉新路径做全覆盖项目的机器人通常在一个区域内反复运行有些场景还涉及地图的动态更新比如货架位置变了、家具挪过。这里有一个常见误解不是地图更新频率越高越好而是重规划策略要跟上地图变化。map_server默认只在启动时发一次地图之后不再更新。如果你接了实时SLAM建图节点比如Cartographer地图会持续更新。全覆盖算法如果已经基于旧地图生成了一条完整路径并且正在执行中此时新地图突然到达——要不要打断当前路径重新规划我的经验是如果机器人处于执行早期比如覆盖率不到30%且地图变化较大可以触发重新规划打断成本低。如果机器人已经执行了较长时间比如覆盖率超过70%就算是地图有变化也不建议频繁重规划。原因很简单重规划后机器人要从当前点重新走一条完整覆盖路径那已经覆盖过的区域必然会被再次覆盖重复率飙升能耗浪费严重。我的做法是维护一张已完成覆盖区域的掩码图covered mask。无论地图是否更新全覆盖重规划只针对未覆盖区域来做。这比全图重来效率高一个数量级。6. 选型决策树一句话说清什么时候选谁很多人问我要一个终极答案但全覆盖这块真的没有万能算法。根据我这几年做过的项目整理出一个简化版的选型决策树你可以当作自查清单地图是否精确且静态是进入第2步。否/动态变化大优先考虑随机覆盖实时探测兜底辅以局部牛耕在小范围内使用。地图形状是否基本规则矩形/凸多边形是直接用牛耕往复或内螺旋。简单场景不需要复杂分解。否有大量凹多边形、岛状障碍物进入第3步。是否对覆盖率有硬性要求是选Boustrophedon分解或Morse分解。实测覆盖率都能达到97%以上。否只求大概扫一遍牛耕靠墙绕障即可成本最低。是否有明确的起点/终点和充电桩逻辑是选带闭环回路的分解牛耕方案把起点终点统一考虑。否分解牛耕优先保证覆盖率返回路径单独规划。底盘类型是什么差速/全向牛耕、螺旋、分解都可以。阿克曼/汽车底盘优先选分解牛耕因为这种底盘转弯需要额外的前向空间和转弯半径螺旋路径容易卡死。履带底盘优先牛耕往复减少原地转弯次数履带原地转对地面磨损太严重了。这套决策树我不保证覆盖所有场景但能让团队在一开始就把技术路线定下来避免先跑通再说然后反复返工。7. 我保留的一个个性化技巧把全覆盖路径和沿墙路径混搭全覆盖规划的主流思路是区域分解单元覆盖但我在一些特殊项目里发现了一种混合策略效果意外地好先用全覆盖算法生成主体覆盖路径再用沿墙路径覆盖边界区域最后把两条路径按先边界后中心或者先中心后边界的顺序拼接起来。为什么这么做因为全覆盖算法的路径在环境边界附近往往不够贴边留下边界盲区。比如牛耕路径转弯处机器人需要一个转弯半径导致角落扫不到。而专门的沿墙路径Wall following可以很精确地沿着墙壁把角落和边缘走一遍正好补上这个缺口。实现上沿墙路径可以当作一个贴边覆盖路径生成器来用把地图膨胀后的边界提取出来然后沿边界生成一条偏移量为机器人半径的轨迹最后把这条轨迹作为全覆盖主路径的补充。这样做的代价是多了一段沿墙路径路径总长度大概增加5%-8%但覆盖率可以进一步提升到接近100%而且墙边这种用户最容易拿手检验的地方扫得很干净客户满意度提升明显。扫地机器人产品里很多旗舰机型也是这么干的——先弓字形全覆盖再自动沿墙补扫一圈道理一模一样。最后提醒一句覆盖率100%在很多场景里是个伪需求。如果你一味追求100%覆盖重复率和耗时都会成倍增加机器人的电池可能撑不住。现实项目里设定一个覆盖率≥98%重复率≤8%的工程目标往往是最理性的选择。先把执行稳定性解决好再抠那最后2个点的覆盖率顺序千万别搞反了。
返回列表