1. 项目概述:从“撞墙”到“丝滑”的进化之路
干了十几年机器人,从实验室的玩具车到工厂里满负荷跑的AGV,再到如今满大街跑的无人配送小车,我最大的感触就是:路径规划这玩意儿,真不是纸上谈兵。它就像机器人的“大脑导航”,决定了这玩意儿是像个没头苍蝇一样到处乱撞,还是能像个老司机一样在复杂环境里游刃有余。今天,咱不聊那些虚头巴脑的概念,就结合我这十多年踩过的坑、调过的参,把移动机器人路径规划那些核心算法掰开了、揉碎了讲清楚。无论你是刚入行的学生,还是正在为项目选型头疼的工程师,希望这篇总结能给你一个清晰的路线图,让你知道什么时候该用什么“武器”,以及怎么把这“武器”用得顺手。
移动机器人路径规划,说白了,就是给机器人找一条从A点到B点的“好”路。这个“好”字,学问可就大了。它可能意味着最短、最快、最省电、最平稳,或者最安全(不撞人、不撞墙、不翻车)。为了实现这个目标,算法江湖里门派林立,从古典的图搜索到现代的智能优化,再到如今火热的机器学习,各有各的绝活。但别被这些名词唬住,它们的核心思想往往非常直观。接下来,我们就按照从全局到局部、从静态到动态的逻辑,把这些算法捋一遍,重点讲明白它们为什么这么设计,以及在实际项目中怎么用、会踩什么坑。
2. 全局路径规划:先看地图再出发
全局路径规划,相当于出行前用手机地图做行程规划。它假设我们对整个环境了如指掌(有一张先验的静态地图),任务是在这张地图上,找出一条连接起点和终点的最优或次优路径。这是所有导航任务的第一步,也是最基础的一步。
2.1 经典图搜索算法:Dijkstra与A*
当环境被建模为一张图(Graph),其中节点代表位置,边代表可通行路径及其代价(如距离、时间)时,图搜索算法就派上用场了。
Dijkstra算法:这是最“老实”的算法。它从起点开始,像水波扩散一样,均匀地探索所有方向,直到触及终点。它保证找到的是全局最短路径(在图的定义下)。但它的缺点是“盲目”,会探索大量不必要的节点,计算效率较低,特别是在大地图上。
实操心得:Dijkstra算法实现简单,鲁棒性强,在小型栅格地图(比如100x100)或者路径节点数不多的拓扑地图中,完全够用。它的代码可以作为你验证地图数据结构和基础搜索逻辑的“试金石”。但在实际工程项目中,除非对最优性有极端要求且地图很小,否则一般不会直接用纯Dijkstra。
A*算法:这是Dijkstra的“聪明”升级版,也是工业界应用最广泛的全局规划算法之一。它的核心在于引入了启发式函数(Heuristic),通常是当前点到终点的欧几里得距离或曼哈顿距离。这个函数像一个“指南针”,在搜索过程中始终告诉算法“终点大概在哪个方向”,从而让搜索过程更有目的性,大幅减少探索的节点数。
为什么A*这么受欢迎?因为它在一个简单框架内,优雅地平衡了最优性和效率。只要启发式函数满足“可采纳性”(即不高估实际代价),A*就能保证找到最优路径。它的效率比Dijkstra高出一个数量级,且非常容易理解和实现。
A*的代价函数与核心参数: 路径代价通常表示为:f(n) = g(n) + h(n)
g(n):从起点到节点n的实际代价。h(n):从节点n到终点的估计代价(启发函数)。f(n):节点n的总估计代价。
这里就涉及到你提到的“路径规划的代价函数的条件”。对于A*,启发函数h(n)必须满足可采纳性和一致性(或称单调性)。
- 可采纳性:
h(n)永远不大于从节点n到终点的真实代价h*(n)。这保证了算法不会因为过于乐观而错过最优路径。 - 一致性:对于任意节点n及其后继节点n‘,满足
h(n) ≤ cost(n, n') + h(n')。这保证了路径代价非递减,使得A*在找到目标节点时,首次探索到该节点就是最优路径。
项目中的具体实现与调参:
# 一个极简的A*算法框架思路(伪代码风格) open_list = PriorityQueue() # 优先队列,按f(n)排序 open_list.put(起点, f(起点)=h(起点)) came_from = {} # 记录路径 g_score = {起点: 0} while not open_list.empty(): current = open_list.get() if current == 终点: return 重构路径(came_from, current) for neighbor in 获取邻居(current): tentative_g_score = g_score[current] + 距离(current, neighbor) if neighbor not in g_score or tentative_g_score < g_score[neighbor]: # 找到一条到neighbor的更优路径 came_from[neighbor] = current g_score[neighbor] = tentative_g_score f_score = tentative_g_score + heuristic(neighbor, 终点) if neighbor not in open_list: open_list.put(neighbor, f_score)常见问题与避坑指南:
- 启发函数选择:对于栅格地图,对角距离(Chebyshev或Octile)比曼哈顿距离更贴近机器人实际移动成本(允许走对角线)。对于几何自由度高的机器人(如全向轮),欧几里得距离更合适。
- 权重系数:有时为了进一步加快搜索,会使用加权A*:
f(n) = g(n) + ε * h(n)(ε > 1)。但这牺牲了最优性保证,可能找到的是次优解。ε越大,搜索越快,路径可能越长。需要根据场景权衡。 - 地图膨胀(Inflation):这是工程上的关键技巧!直接在原始障碍物地图上规划,路径会紧贴障碍物,非常危险。我们需要对障碍物进行“膨胀”,相当于给机器人加上一个安全半径。规划在膨胀后的地图上进行,生成的路径自然与障碍物保持安全距离。
- 动态障碍物:A*本身是静态规划器。对于动态环境,通常的架构是:全局规划器(A) + 局部规划器(负责动态避障)*。全局路径定期刷新(比如每秒1次),或者当机器人偏离全局路径太远时重新规划。
2.2 基于采样的算法:RRT与PRM
当机器人的工作空间是连续的高维空间(比如机械臂的关节空间)时,用栅格或图来离散化会带来“维度灾难”。这时,基于采样的规划算法就显示出优势了。
快速探索随机树(RRT):它的思想非常“暴力美学”。从起点开始,随机在空间里撒点,然后尝试把树向着随机点方向生长一步。如此反复,直到树触及终点附近。RRT不追求最优,但追求快速找到一条可行路径。它特别适合高维空间和复杂障碍物环境。
我在机械臂项目中的应用体会: 在为一个六轴机械臂做无碰撞运动规划时,A*根本没法用(状态空间是6维的)。我们采用了RRT-Connect(双向RRT),效果立竿见影。它的核心优势是“概率完备性”——只要运行时间足够长,就一定能找到解(如果存在的话)。但它的路径通常扭来扭去,不够优美。
路径优化是必须的:RRT生成的原始路径就像一根“毛线”,需要后处理。我们常用**路径修剪(Path Pruning)和轨迹平滑(如B样条插值)**来缩短路径并让机械臂运动更平滑。
概率路线图(PRM):分两步走。学习阶段:在空间中随机撒大量“里程碑”点,并连接那些能无碰撞直达的点,形成一张路线图。查询阶段:给定起点和终点,将它们连接到路线图上,然后用图搜索算法(如Dijkstra)在路线图中找路径。PRM适合多任务查询的场景,图一旦建好,后续规划就很快。
选择RRT还是PRM?
- 单次查询、高维空间:选RRT系列(RRT, RRT*, RRT-Connect)。
- 同一环境多次查询:选PRM。比如一个仓库的多台AGV,可以共享一张预先构建好的PRM。
- 追求最优性:考虑RRT或PRM,它们是渐近最优的,即随着采样点增多,路径会收敛到最优。但收敛速度较慢。
3. 局部路径规划与动态避障:应对未知与变化
全局路径给出了一条理想化的“参考线”,但真实世界充满意外:突然出现的人、移动的车辆、临时摆放的货箱……这就需要局部路径规划器来实时应对,它只关心机器人周围一小片区域。
3.1 动态窗口法(DWA)
这可能是最经典、最直观的局部规划器了。它的思想模拟了人类驾驶:在当前位置,根据机器人的动力学约束(最大速度、加速度),模拟出未来一小段时间(时间窗口)内所有可能的运动轨迹(速度对),然后从中挑选出一条最优的。
DWA的三层评价函数:
- 朝向目标:轨迹的终点是否朝向全局目标点?
- 前进速度:轨迹的速度是否够快?(提高效率)
- 与障碍物距离:轨迹上离最近障碍物有多远?(保证安全)
通过给这三项分配不同的权重,然后对所有模拟轨迹进行打分,选择最高分的轨迹执行。这个过程在每一个控制周期(如100ms)重复进行。
DWA的优缺点与调参血泪史:
- 优点:概念清晰,实现相对简单,能较好地考虑机器人动力学。
- 缺点:参数多(速度限制、模拟时间、评价权重),调参繁琐,且容易陷入局部最优(比如在狭窄走廊里“振荡”)。
- 关键参数:
sim_time(模拟时间):太短则目光短浅,太长则计算量大且不准确。通常设为2-3秒。vx_sample, vy_sample, w_sample(速度采样分辨率):采样越密,找到好轨迹的可能性越大,但计算量也越大。需要在实时性和效果间折衷。- 评价权重:这是调参的核心。安全权重必须占主导,否则机器人会冒险。在测试初期,可以先把“速度”权重设低,确保安全避障;稳定后再逐步提升速度权重。
踩坑记录:我们曾在一个服务机器人项目中使用DWA,在办公室环境遇到U型障碍(比如三面围住的工位)时,机器人经常在入口处“左右摇摆”,进不去。原因是DWA在每一个周期都只做局部最优选择,看不到进入U型区域后的好处。解决方案是加入一点“随机性”或者“历史记忆”,比如偶尔允许选择非最高分的轨迹,或者当持续振荡时,短暂地切换成更激进的参数。
3.2 时间弹性带(TEB)与模型预测控制(MPC)
对于像阿克曼转向的汽车机器人,或者对轨迹平滑性要求极高的场景(如高速移动、乘客舒适度),DWA就显得力不从心了。这时需要更高级的局部规划器。
时间弹性带(TEB):它把全局路径看作一根可以拉伸、挤压的“橡皮筋”。TEB优化的是整条带子上的一系列位姿点,同时考虑动力学约束(如阿克曼转向的曲率限制)、时间约束(总时间)、与障碍物的距离以及路径的平滑性。它本质上是一个带约束的非线性优化问题。
为什么TEB适合阿克曼机器人?因为它的优化变量中直接包含了机器人的位姿(x, y, θ),可以很方便地加入曲率约束:|κ| < κ_max,这正好对应了阿克曼转向车辆的最小转弯半径限制。这是DWA难以直接做到的。
模型预测控制(MPC):这是更通用的框架。在每一个控制周期,MPC基于当前的机器人状态和环境感知,预测未来一段时域内的系统行为,并通过求解一个优化问题,得到一系列最优的控制输入(速度、角速度),但只执行第一个控制输入。下一个周期,重复这个过程。TEB可以看作是MPC思想在路径规划问题上的一个具体实现。
TEB/MPC的工程挑战:
- 求解器:需要可靠高效的非线性优化求解器,如g2o、Ceres Solver或OSQP(对于二次规划问题)。
- 实时性:优化问题的计算量比DWA大得多,需要强大的处理器和精心设计的问题规模(优化时域长度、位姿点数量)。
- 数值稳定性:问题构建不好(约束冲突、初始值太差)会导致求解失败,机器人必须要有应对求解失败的降级策略(比如紧急停止或切回DWA)。
3.3 人工势场法(APF)及其变种
这是一种非常物理直观的方法:将目标点视为“引力场”,障碍物视为“斥力场”,机器人像一个小球一样在合力场中运动。计算简单,反应快速。
它的致命缺陷:容易陷入局部极小点。比如当机器人在一个U型障碍正前方时,来自目标和障碍的力可能恰好平衡,导致机器人停止不动。此外,在狭窄通道中,两侧障碍物的斥力可能把机器人“卡”在通道中央。
工程上的改进:
- 虚拟力:在局部极小点附近施加一个微小的随机扰动力或切向力,帮助机器人逃逸。
- 与其它方法结合:常作为DWA或TEB中“障碍物代价”项的计算方式,即用势场值来评价轨迹的安全性,而不是单独作为规划器。
4. 融合与进阶:应对更复杂的场景
单一的算法往往难以应对所有情况。现代移动机器人系统,特别是自动驾驶和高级AMR,普遍采用分层、融合的架构。
4.1 全局与局部规划的协同
这是最经典的架构,也就是你提到的“加入局部路径规划层”。
- 全局规划层:使用A*、Dijkstra等,在静态地图上生成一条从起点到终点的粗略路径(称为“全局路径”或“参考线”)。这个路径可能只是一系列稀疏的路径点(Waypoints)。
- 局部规划层:使用DWA、TEB等,以全局路径为引导,结合实时传感器数据(激光雷达、摄像头),生成机器人实际执行的、无碰撞的、符合动力学的速度指令。
如何“加入”这个局部层?关键在于路径跟踪(Path Following)。局部规划器不仅避障,还要努力让机器人跟随全局路径。在DWA中,这体现在评价函数的“目标朝向”项,该项计算的是轨迹终点与全局路径上局部目标点的方位差。这个局部目标点不是全局终点,而是全局路径上位于机器人前方一定距离(称为“前视距离”)的点。前视距离是一个关键参数,设置太短机器人会紧贴路径但可能不稳定;设置太长跟踪平滑但转弯时切割弯道。
4.2 融合感知信息:从激光雷达到语义理解
早期的路径规划只处理几何障碍。现在,我们需要更智能的避障。
- 动态障碍物预测:对于激光雷达检测到的移动物体(聚类点云),可以通过卡尔曼滤波等算法预测其未来轨迹。局部规划器在评价轨迹时,不仅要看当前是否碰撞,还要预测在未来几秒内是否会与移动物体的预测轨迹相交。
- 代价地图(Costmap):这不是简单的二值地图(障碍/非障碍),而是一个灰度地图。值越高,“代价”越大,机器人越不愿意去。我们可以根据传感器信息灵活设置代价:
- 静态障碍物:代价最高。
- 动态障碍物预测区域:根据碰撞概率设置不同代价。
- 未知区域:中等代价(鼓励探索但谨慎)。
- 危险区域(如靠近楼梯口):高代价。
- 偏好区域(如平整路面):低代价。 规划器(如A*、DWA)在代价地图上搜索,自然就会综合考虑安全性、舒适性和效率。
4.3 学习型方法:从模仿学习到强化学习
这是当前的研究热点,旨在让机器人通过数据自己学会如何规划。
模仿学习(IL):让机器人学习人类专家的驾驶/操作数据。例如,采集人在各种场景下的驾驶状态(图像、激光数据)和动作(方向盘、油门),训练一个神经网络来映射感知到动作。这种方法能学到非常拟人化的驾驶风格,但严重依赖高质量的数据,且遇到训练集中未见过的情况可能表现不佳。
强化学习(RL):让机器人在与环境的交互中试错学习。机器人采取动作,环境给予奖励(如到达目标、远离障碍),目标是最大化累积奖励。你提到的PPO算法就是目前非常流行的深度强化学习算法。它通过策略梯度的方法,稳定地优化机器人的决策策略。
RL在路径规划中的挑战与尝试:
- 状态与动作空间设计:如何将丰富的传感器信息(图像、激光)编码成有效的状态向量?动作是直接输出速度指令,还是输出更高层的意图?
- 奖励函数设计:这是RL的灵魂,设计不当会导致机器人学到奇怪的行为(比如原地转圈也能骗到“存活奖励”)。奖励需要精心平衡前进、到达目标、避障、平滑等多个目标。
- 训练效率与安全:在真实机器人上训练RL成本高、风险大。通常先在仿真环境(如Gazebo、CARLA)中进行大量训练,再迁移到实物。你提到的“无人机自主路径规划仿真”、“matlab 路径规划 ppo”正是这个思路。
我的看法:目前,纯学习型的规划器在工业落地中还不成熟,主要作为传统方法的补充或用于特定子任务(如决策超车、汇入车流)。更可行的路线是混合架构:用传统方法保证基础的安全和可靠性,用学习模型来处理复杂的、难以规则化的场景(如与行人的交互礼仪),或者用来优化传统方法中的参数(如DWA的权重)。
5. 算法选型与工程落地指南
纸上谈兵终觉浅。最后,结合不同类型机器人的需求,给出一些直接的选型建议和工程化要点。
5.1 不同机器人的算法适配
差分轮式机器人(如Roomba扫地机、大部分AGV):
- 全局规划:A*(栅格地图)或Dijkstra(拓扑地图)。
- 局部规划:DWA是绝配。因为它能很好地处理差分轮的运动学模型。调参是重点。
- 场景:室内仓储、服务引导。
阿克曼转向机器人(如自动驾驶车、叉车AGV):
- 全局规划:A*(但需考虑车辆几何,进行碰撞检查)或专门的道路网络搜索。
- 局部规划:TEB或MPC。必须考虑转弯半径约束和轨迹平滑性。DWA在这里可能生成不可执行的曲率。
- 场景:园区物流、停车场自动泊车(你提到的“泊车路径规划算法”常使用基于MPC或几何的方法)。
全向移动机器人(如麦轮、舵轮AGV):
- 全局/局部规划:选择更多。因为运动灵活,对轨迹平滑性要求可能低于阿克曼车辆。A*、DWA、TEB都可以用,甚至可以直接规划二维速度
(vx, vy, ω)。重点在于底层运动控制的精准实现。
- 全局/局部规划:选择更多。因为运动灵活,对轨迹平滑性要求可能低于阿克曼车辆。A*、DWA、TEB都可以用,甚至可以直接规划二维速度
无人机:
- 特点:三维空间运动,动力学复杂,能耗敏感。
- 规划:常用**基于采样的方法(RRT*)**在三维空间进行规划,并结合最小化加加速度(Jerk)或能耗的轨迹优化(如多项式轨迹)。你提到的“无人机路径规划算法”常指这类方法。
5.2 工程化核心:不是算法,是系统
在实际项目中,让算法跑起来只是第一步,让它稳定、可靠、易维护地跑下去,才是真正的挑战。
1. 地图表示与管理:
- 栅格地图(Occupancy Grid):最常用,直观,便于做膨胀。但内存消耗随分辨率平方增长。
- 代价地图(Costmap):栅格地图的升级,多层融合(静态层、障碍层、膨胀层)。
- 拓扑地图:用节点和边表示关键地点和通道,轻量级,适合大规模环境。全局规划用图搜索,局部规划再用栅格。
- 语义地图:在几何地图上叠加标签(门、桌子、充电桩),让规划更智能(如“去充电桩附近”)。
2. 传感器融合与状态估计: 规划的前提是知道“我在哪”。这依赖于状态估计(如卡尔曼滤波、粒子滤波)和传感器融合(激光、IMU、轮速计、GPS)。糟糕的定位会导致规划器基于错误的地图位置进行规划,后果灾难性。务必保证定位系统的稳定和精度。
3. 实时性与计算分配:
- 规划循环频率通常为5-20Hz。DWA、APF计算快;TEB、MPC、RRT较慢。
- 将耗时操作(如全局A*重规划)放在独立的中低频线程中,避免阻塞高频的局部控制循环。
- 使用规划器插件架构(如ROS的
nav_core),方便切换和测试不同算法。
4. 异常处理与降级策略: 机器人总会遇到规划失败的情况:无可行路径、求解器崩溃、传感器失效。系统必须有鲁棒的异常处理流程:
- 局部规划失败:尝试减速、停车、原地小范围旋转寻找新路径,或请求全局重新规划。
- 全局规划失败:尝试放宽约束(如允许临时穿过低代价区域),或进入“恢复行为”(如沿边行走)。
- 记录日志:记录规划失败时的机器人状态、传感器数据和地图,这是后期调试改进的最宝贵资料。
5. 仿真与测试: 在实车调试前,务必在仿真环境中进行充分测试。Gazebo + ROS是黄金组合。可以构建各种极端场景:狭窄通道、动态人流、传感器噪声等,批量测试算法的鲁棒性。这比在实地调试效率高百倍,也更安全。
路径规划算法的世界博大精深,从经典的A*到前沿的强化学习,没有一种算法是银弹。真正的工程智慧在于深刻理解每个算法的核心思想、适用边界和代价,然后根据你的机器人形态、应用场景、性能要求和开发资源,进行合理的选择、组合与调优。记住,最优雅的算法不一定是项目里最管用的,那个能稳定运行上万小时不出错的,才是好算法。希望这篇总结能帮你少走些弯路,把更多精力花在创造真正的价值上。