☰
EGO-Planner算法原理详解:无人机局部轨迹规划的梯度优化实践
2026/10/3 6:00:52 网站建设 项目流程

EGO-Planner这个名字,在无人机规划圈子里这几年热度一直没降过。港科大多旋翼飞行器团队提出的这个基于梯度优化的局部轨迹规划算法,论文发表在RA-L/IROS 2021,几年过去了,依然是很多自主导航项目里绕不开的范本。我前前后后在无人机项目中用过它,也自己复现过,最直观的感受是:它把“实时性”和“安全性”这对矛盾处理得非常漂亮,在机载算力有限的情况下,能做到几毫秒到几十毫秒出一段平滑、安全、动力学可行的轨迹。这篇系列文章的第一篇,我打算把EGO-Planner的论文原理和算法实现骨架彻底拆开来讲,适合正在做无人机/机器人自主导航、或者想把EGO-Planner用到自己项目里的同学。读完你不仅能搞懂它为什么能跑得这么快,还能自己搭出一个简化版的原型。

1. EGO-Planner到底解决什么问题

1.1 无人机规划中“最后一公里”的痛点

无人机自主飞行的核心链路通常是:感知定位 → 建图 → 路径规划 → 轨迹生成 → 控制跟踪。前面的感知定位解决“我在哪”,建图解决“周围有什么”,而路径规划和轨迹生成要回答最实际的问题——“接下来怎么走”。很多人在建图部分下了很大功夫,激光雷达、深度相机、VIO全上了,结果到轨迹生成这一步卡住了:规划出来的轨迹要么拐角太锋利,无人机飞起来一抖一抖;要么为了安全离障碍物远远的,飞行效率极低;要么计算太慢,机体都往前飞了两米,轨迹还没算出来。

EGO-Planner正是瞄准了这个“最后一公里”的问题。它要在一个局部环境中,快速找出一条从当前位置到目标点的、无碰撞的、平滑的、物理上能飞出来的轨迹。

这里有个很关键的前提:无人机并不知道全局地图。它手上只有传感器实时给的局部点云或者障碍物信息,下一时刻这些信息还会变。所以EGO-Planner本质上是一个局部规划器,它不期望你给它一张精细的全局地图,只要求“当前能看到的障碍物,别撞上就行”,然后每帧滚动更新轨迹。

1.2 对比传统方法:搜索、采样、优化的优劣势

要理解EGO-Planner的设计思路,先得看清它跟前几代方法有什么不同。传统规划方案大体分三类:基于搜索、基于采样、基于优化。

基于搜索的方法,最典型的是A*、JPS,在栅格地图上找一条从起点到终点的离散路径。这种方法的优点是有完备性,只要栅格分辨率够高、地图够准,一定能找到路径。但缺点是搜索结果是一串离散点,直接给无人机飞肯定不行——速度、加速度都不连续,曲线也是折线,所以要再做平滑处理。而且栅格地图的构建和维护在动态环境中代价很高,分辨率一高,内存和计算量都上去了。

基于采样的方法,比如RRT、RRT*,通过随机撒点来探索空间。这类方法在高维空间中比搜索法灵活,但随机性导致路径不稳定,相邻两帧规划出的轨迹可能差异巨大,而且收敛到最优解需要大量采样,在动态场景下实时性很难保证。

基于优化的方法是第三种思路:不显式地在离散空间里找路径,而是把轨迹表示成参数曲线,然后构造一个损失函数(代价函数),用梯度下降的方式去最小化它。优化法的优势是轨迹天然平滑,而且可以直接把动力学约束(最大速度、最大加速度)写进代价函数里。但它有个致命弱点:对初值很敏感。如果初始轨迹穿过了障碍物密集区,优化很容易卡在局部极小,跑出来的轨迹还是穿模的。所以很多优化类算法需要先找一个好的初值,或者依赖ESDF(欧几里得符号距离场)来提供避障梯度。

EGO-Planner的聪明之处在于:它把一条路径规划任务拆成了“前端快速搜索初值 + 后端快速梯度优化”两步,并且在后端优化时避开了对ESDF的依赖,直接使用传感器点云做碰撞代价计算。这个组合让它既有搜索法的可靠性,又有优化法的平滑和快速。

1.3 EGO-Planner的核心定位与整体框架

从系统层面的角度看,EGO-Planner的输入输出非常干净。输入是当前无人机位置、目标点(或前方参考路径)、以及局部的障碍物信息(点云或占据栅格)。输出是一串B样条控制点和对应的时间间隔,下层控制器拿到这串控制点就能生成位置、速度、加速度指令。

整个算法框架分三块:前端初始化、后端优化、时间重分配。

前端初始化负责找一条“拓扑正确”的初始路径。所谓拓扑正确,意思是这条路径穿过的障碍物“空洞”是正确的,比如左边有个墙、右边有个柱子,你得给出“从中间穿过去”或者“绕右边过去”的大致方向。这一步一般用A*或JPS在局部栅格上完成,也可以根据实际场景换成更快的搜索策略。初值不需要平滑,只要方向对。

后端优化是核心。它把轨迹表示成均匀B样条,然后把“平滑、安全、动力学可行”这三个目标写成三个代价项,用梯度法迭代更新控制点。这里最反直觉的是,后端压根不需要ESDF,它直接用原始点云去算碰撞代价和梯度。这个设计让它省去了整个ESDF的构建和更新开销,把单次规划时间压缩到了几毫秒级别。

时间重分配是很多人容易忽略的步骤。B样条轨迹的形状虽然决定了“走哪条路线”,但速度怎么变化是由控制点之间的时间间隔决定的。如果时间分配不合理,比如某个弯道给的时间太短,无人机物理上根本拐不过来。EGO-Planner通过调整每段的时间间隔来满足速度、加速度约束,相当于在“路线”和“节奏”之间做了一个联合优化。

2. 核心原理拆解:B样条与优化框架

2.1 为什么轨迹表示选B样条

EGO-Planner把轨迹表示成均匀B样条。B样条是一种参数曲线,由控制点、节点向量和阶数共同定义。阶数p的B样条曲线具有局部支撑性——移动一个控制点,只影响附近一小段曲线,不会让整条轨迹都跟着变形。这个性质对优化特别友好:你只需要在局部调整控制点,就能修正某个区段的轨迹形状,其他部分保持不动。

还有一个重要性质是凸包性:整条曲线落在控制点张成的凸包内。这意味着什么?如果你能把所有控制点都约束在安全区域内,那么曲线本身也基本是安全的,虽然不完全严格,但实际使用中已经非常有效了。凸包性还让轨迹的安全性判断变得很便宜,不需要对曲线逐点采样检测,直接检查控制点即可。

更妙的是均匀B样条的导数性质。对均匀节点间隔的B样条,速度曲线就是低一阶的B样条,它的控制点可以由原控制点的差分直接得到。加速度曲线类似,是二阶差分。因为优化过程中要反复计算速度、加速度是否超限,这个性质让导数的计算变成简单的线性运算,非常快。

实际使用中,我们一般用三次B样条,也就是阶数p=3。它保证位置曲线具有二阶连续性(C2连续),速度是连续的折线,加速度是分段常数。三次B样条足够平滑,又不会因为阶数太高产生不必要的震荡。

2.2 损失函数三座大山:平滑、碰撞、动力学

EGO-Planner优化的损失函数由三部分构成,外加一个终点引导项。假设控制点序列为P = [p0, p1, ..., pn],每个控制点是一个三维位置向量,那么总损失可以写成:

J(P) = λs * Js + λc * Jc + λd * Jd + λg * Jg

平滑性代价Js衡量轨迹的“顺滑程度”。在均匀B样条里,加速度控制点就是二阶差分,所以Js可以取所有加速度控制点的平方和。直观理解就是:让加速度尽量小,轨迹自然就平滑,急转弯会带来大加速度,会被惩罚。这里有个细节,最小化加速度其实是在最小化“轨迹对时间的变化率”,如果时间间隔固定,它等价于让轨迹更接近一条直线。

碰撞代价Jc是安全性的核心。对每个控制点,计算它到最近障碍物的距离d。如果d大于安全阈值d_th,说明这个点离障碍物足够远,没有碰撞代价;如果d小于d_th,就施加一个惩罚,惩罚力度随距离减小而增大。常用形式是(d - d_th)²或类似构造,目的是用一个平滑的二次函数把控制点“推”离障碍物。

动力学可行性代价Jd用来保证轨迹能被无人机物理执行。对每个速度控制点,如果它的模长超过了最大速度v_max,就加惩罚;对每个加速度控制点,如果模长超过了最大加速度a_max,也加惩罚。因为B样条的凸包性,约束了控制点的速度/加速度,整条曲线上的实际速度/加速度也就被框住了。

终点引导项Jg的作用是让轨迹往目标点靠拢。局部规划器每帧都需要把无人机引向最终目标,如果没有这一项,优化器可能收敛到一条“很平滑但完全跑偏”的轨迹。通常取最后一个控制点到目标点的距离平方,有时也会对路径上多个采样点做软约束。

这几个分量不是孤立的,它们之间有一个天然的博弈。把平滑性权重调大,轨迹会趋于平直但可能更贴近障碍物;把碰撞权重调大,轨迹会绕开障碍物但可能抖得厉害。EGO-Planner的核心调试工作,其实就是在这几个权重之间找到平衡。

2.3 前端与后端:快速路径搜索 + 梯度优化的协作

后端优化再厉害,也怕初始轨迹给得离谱。如果初始B样条的控制点穿过了障碍物中心,碰撞代价的梯度会非常大,优化器可能把控制点推得乱七八糟,甚至发散。所以EGO-Planner把“搜索”和“优化”做了清晰的职责划分。

前端搜索要的是“快速”和“拓扑正确”。它不需要精细的路径,只需要在环境里找到一条大致可行的通道。最简单可行的方案是在栅格地图上跑A*,然后把得到的离散路径隔几个点取一个,作为B样条的初始控制点。更讲究一点的做法是论文中提到的“拓扑路径搜索”——在空间里找多条不同拓扑的候选路径,比如“从左边绕”和“从右边绕”,然后让后端优化从中选择代价最低的一条。这个做法的好处是可以跳出局部极小。

后端优化负责“精修”。初值已经提供了大致走向,优化器在控制点的小邻域内进行调整,把轨迹拉得更平滑、更远离障碍物、更满足动力学约束。由于每个控制点的调整范围有限,优化收敛非常快,通常迭代几十次就能得到可用轨迹。EGO-Planner在实际中能做到几毫秒一帧,靠的就是这种“初值定拓扑、优化做精修”的分工。

3. 算法实现的关键细节

3.1 控制点、雅可比与优化器选择

实现EGO-Planner的优化部分,最核心的是计算损失函数对控制点的梯度。由于优化变量是控制点坐标(实际是3×(n+1)维的向量),梯度就是损失函数对每个控制点坐标的偏导数。

平滑性代价的梯度最好算。如果平滑损失是加速度控制点的平方和,而加速度控制点Ai = (pi+2 - 2pi+1 + pi) / Δt²,那么对pi求偏导,只需要考虑pi在Ai、Ai-1、Ai-2这几项中的贡献。数学推导很直接,最终会得到一个稀疏的带状矩阵形式的梯度。因为B样条的局部支撑性,这个梯度矩阵是稀疏的,计算量随控制点数量线性增长。

动力学代价的梯度也不复杂。速度控制点Vi = (pi+1 - pi) / Δt,加速度控制点如上。如果某个速度控制点的模长超过v_max,就对该控制点求导并让它往速度减小的方向更新。

碰撞代价的梯度稍微麻烦一点,但理解了之后也很直观。假设每个控制点pi到最近障碍物的距离为di,当di < d_th时,损失是(di - d_th)²。对pi求导,需要知道di对pi的梯度。如果已知最近障碍物点的坐标oi,那么距离梯度就是单位向量(pi - oi) / di。所以碰撞代价对pi的梯度等于 2*(di - d_th) * (pi - oi) / di。这个推导意味着,只要你能快速找到每个控制点的最近障碍物点,就能算出碰撞梯度。下面小节我详细说怎么找。

优化器选择上,我个人推荐L-BFGS。它是一种拟牛顿方法,只需要计算损失和梯度,不需要海森矩阵,内存开销小,在嵌入式平台上也能跑。EGO-Planner的开源实现里用的也是类似思路。如果你只是想快速验证,用梯度下降配合学习率衰减也能工作,只是收敛速度会慢一些。

3.2 无ESDF的碰撞代价:如何用最近邻点算梯度

传统梯度优化方法大多依赖ESDF,因为ESDF能提供任意位置到最近障碍物的距离和梯度。但ESDF有个问题:它是全局地图结构,构建和更新成本高,尤其在地图较大时非常耗时。EGO-Planner的核心创新之一就是绕开了ESDF,直接用传感器点云算碰撞代价。

实现上,先把传感器点云做体素滤波下采样,减少点数,然后构建一个Kd-tree用于最近邻查询。对每个控制点,查询它在障碍物点云中的K个最近邻点(K一般取5到10)。计算控制点到这些最近邻点的平均距离或加权距离,作为“该控制点到障碍物的距离估计”。

当距离小于安全阈值时,利用K个最近邻点加权生成一个“排斥方向”,让控制点沿着这个方向移动。这里有个和论文相关的细节:如果只用单个最近邻点,梯度会非常不平滑,因为当控制点移动时,最近邻点的索引会跳变,导致梯度和距离函数不连续。用多个近邻点做加权平均,可以让梯度平滑许多。加权方式可以简单设置为距离越近权重越大,或者干脆用平均值,实际效果差别不大。

这个设计的性能优势非常明显。构建一个Kd-tree只需要几毫秒,查询也是O(log n)级别。同时省掉了整个ESDF的维护流程,每次地图更新不需要重建全局距离场,只需要增量地更新点云Kd-tree。在动态环境中,这意味着你可以用传感器刷新频率(比如30Hz)去滚动更新障碍物信息,规划能始终跟上环境变化。

3.3 时间重分配:被忽视的隐形维度

做轨迹优化的时候,大多数人会下意识地把注意力放在“控制点位置”上,而忽略了“控制点之间的时间间隔”。实际上,对于无人机这种高阶系统,时间分配不合理,即使位置轨迹再平滑,飞行器也执行不出来。

在均匀B样条中,每个控制点对应的时间间隔Δt是相同的。轨迹的速度控制点Vi = (pi+1 - pi) / Δt,加速度控制点类似。如果某个转弯处的位移向量(pi+1 - pi)很大,而Δt又很小,那么速度控制点Vi的模长就会很大,可能超过无人机能承受的最大速度。解决方式有两种。

第一种叫“时间缩放”:算完轨迹后检查最大速度/加速度,如果超限,就按比例把所有Δt放大。这是一种全局操作,会把整条轨迹的时间都拉长,虽然安全但效率不高——明明只有一段弯道速度太快,结果所有路段都变慢了。

第二种是EGO-Planner的做法,更精细的“时间重分配”。它把每个Δt也当作优化变量,在“更快到达”和“动力学可行”之间找一个平衡点。实现上可以和位置优化交替进行:固定Δt优化控制点位置,再固定控制点位置优化Δt,反复迭代。因为位置和时间相互影响,交替优化几个回合后,能够得到一个速度和加速度都满足约束的轨迹。

我在实际项目中观察到一个很有用的经验:在有狭窄通道的场景中,时间重分配对轨迹质量的影响比位置优化更大。因为通道里往往没有太多绕行空间,位置很难大幅调整,但通过合理分配时间——进通道前减速、出通道后加速——可以让轨迹在物理上完全可行。如果你的轨迹明明没有穿障碍,但无人机飞起来却剧烈抖动,先检查时间分配,往往比调碰撞权重更有效。

4. 实操过程:从零搭一个EGO-Planner原型

4.1 伪代码级流程拆解

结合前面的原理,我给出一个简化但完整的EGO-Planner流程。这份伪代码可以直接照着翻译成C++或Python原型:

def ego_planner(p0, pg, local_pointcloud, obstacles): # 1. 前端初始化:快速搜索 grid_path = astar_search(p0, pg, obstacles) if not grid_path: return None # 没有可行路径,需要重新制定目标或扩大搜索范围 # 2. 初始化B样条控制点 ctrl_pts = sample_control_points(grid_path, num=16) dt = 0.15 # 初始时间间隔,单位秒 # 3. 后端优化 for iter in range(max_iterations): # 计算每个控制点到最近障碍物的距离与梯度 for i in range(len(ctrl_pts)): nearest_pts = kd_tree.query(ctrl_pts[i], k=5) d_i = compute_distance(ctrl_pts[i], nearest_pts) grad_collision[i] = compute_collision_gradient(ctrl_pts[i], nearest_pts) # 计算各项代价与梯度 J_s, grad_s = smoothness_cost(ctrl_pts, dt) J_c, grad_c = collision_cost(ctrl_pts, grad_collision) J_d, grad_d = dynamic_cost(ctrl_pts, dt, v_max, a_max) J_g, grad_g = goal_cost(ctrl_pts, pg) # 合并梯度 grad = lambda_s * grad_s + lambda_c * grad_c + lambda_d * grad_d + lambda_g * grad_g # L-BFGS更新控制点 ctrl_pts = l_bfgs_update(ctrl_pts, grad) # 收敛检查 if loss_change < epsilon: break # 4. 时间重分配 ctrl_pts, dt = time_reallocation(ctrl_pts, dt, v_max, a_max) return ctrl_pts, dt

这个流程里每个步骤都有可以深挖的细节。比如A*搜索的终止条件、控制点采样的间距、优化迭代次数的设置、时间重分配的闭式解,下面一节逐个说明。

4.2 关键参数怎么选:权重、阶数、时间间隔

控制点数量是第一个要考虑的参数。控制点太少,轨迹的表达能力不够,可能无法精细地绕过密集障碍物;控制点太多,优化变量维度增加,实时性下降。我一般取12到20个控制点,具体看规划距离和环境复杂度。规划距离短(比如5米内)取12个,距离长(10米以上)取20个。采样控制点时,要保证路径上的关键转角都被覆盖到,否则优化初值就丢失了拓扑信息。

B样条阶数固定取3,也就是三次B样条。二次B样条虽然计算更快,但位置连续性不够好,加速度不稳定;再往上取4阶、5阶意义不大,只会让控制点的影响范围变大,削弱局部调整能力。

时间间隔dt的初始值一般取0.1到0.2秒。dt越小,同一段轨迹上的控制点越密集,轨迹越“精细”,但对控制器的跟踪频率要求越高,同时速度控制点会变大,动力学约束更容易触发。dt越大,轨迹越平滑,但整体到达时间会变长。我习惯从0.15秒起步,跑仿真看速度曲线是否贴近v_max,再微调。

代价权重方面,我的经验是先固定基础值,再按需调整。建议初始值如下:

代价项权重说明
平滑性λs1.0基准项,一般不轻易动
碰撞λc0.5如果穿障碍,逐步提高到2.0
动力学λd0.5如果速度加速度超限频繁,提高
终点引导λg0.5如果轨迹终点离目标太远,提高

安全阈值d_th取0.3到0.5米。这个值取决于无人机尺寸和传感器噪声。如果是小型四旋翼(轴距250mm),0.3米足够;如果是大一点的平台,要放宽到0.5米甚至更大。注意安全阈值设得太大会让轨迹“过于胆小”,离障碍物远远的,在狭窄通道里可能直接找不到路。

4.3 在Gazebo/RViz中的验证经验

我第一次用EGO-Planner是在Gazebo仿真里,配合PX4和MAVROS,传感器用深度相机生成点云。第一次跑通只用了不到一天,但踩了一些坑,值得分享。

第一个坑是坐标系问题。深度相机的点云在camera_link坐标系下,必须变换到无人机机体坐标系或者世界坐标系,否则碰撞检测会失效。规划器以为控制点在障碍物附近,实际相机看到的障碍物在完全不同的位置。这个坑非常隐蔽,因为看起来程序没报错,轨迹也很平滑,就是偶尔会“莫名其妙”穿过一个障碍物。最后我打印了点云和控制点的坐标,对不上,才定位到是坐标变换没做。

第二个坑是点云数量太多导致规划频率骤降。深度相机一帧点云可能上万甚至几十万点,直接用这个点云构建Kd-tree,查询一次要好几毫秒,几十次迭代下来单帧规划就要几百毫秒,完全没法实时。解决办法是先用VoxelGrid滤波器把点云下采样到0.05到0.1米分辨率,点云数量降到几千个,Kd-tree查询瞬间就快了。这个操作对规划质量影响很小,因为障碍物的几何结构在降采样后依然保持完整。

第三个经验是RViz可视化的重要性。EGO-Planner的调试很大程度上依赖肉眼观察,我会同时显示三样东西:原始点云、B样条控制点、优化后的轨迹。控制点用大圆点显示,轨迹用细线显示。如果轨迹离障碍物很近但没有碰撞,并且控制点都落在安全区域外沿,说明算法工作正常。如果控制点在一个区域内反复震荡,很可能是代价权重失衡或者梯度计算有bug。

5. 常见问题与排查技巧实录

5.1 轨迹老是穿障碍物,问题出在哪

轨迹穿障碍物是最常见的现象,可能的原因有好几种,我按出现频率排列。

原因一:碰撞代价权重太低。默认λc=0.5可能不够,尤其在狭窄环境中,平滑性代价会“引诱”轨迹走捷径穿过障碍物。解决办法是把λc提高到1.5到2.0,观察轨迹是否被推开。

原因二:安全阈值d_th设得太小。如果d_th只有0.15米,优化器认为只要离障碍物0.15米就安全,但无人机本身有物理半径(电机、机臂、负载),再加上控制误差,0.15米根本不够。至少设为0.3米。

原因三:最近邻查询失败。这个问题最隐蔽。如果Kd-tree是从降采样点云构建的,而降采样后障碍物变得稀疏,某个控制点附近可能出现“查询不到近邻点”的情况,导致碰撞梯度为0,轨迹就穿过去了。我遇到过一次,墙的点云在体素滤波后只剩两三个点,最近邻距离算出来很大,碰撞惩罚完全没有激活。解决方法是提高局部体素地图的分辨率,或者对稀疏区域做点云膨胀。

原因四:安全阈值内的障碍物点太少,梯度方向不稳定。如果只用1个最近邻点,当控制点刚好处在两个障碍物点中间时,最近邻点会在两个点之间跳动,梯度方向也会反复横跳,优化可能无法收敛。用K个近邻加权的方案能明显改善这个情况。

5.2 优化发散与震荡的处理

优化震荡的表现是:轨迹在几个状态之间反复跳动,或某个控制点疯狂抖动,损失函数忽高忽低不上不下。

先看优化器学习率是否过大。L-BFGS一般不用手动设置学习率,但如果自己实现梯度下降,学习率太大会导致越过最优点后震荡。可以加一个line search,沿梯度方向一维搜索最优步长,能解决大部分发散问题。

再看初值是否太离谱。前端搜索出来的路径如果穿过了障碍物核心区域,后端优化的梯度会非常大,控制点可能被推出很远,甚至飞出地图边界。这时候可以限制每次迭代控制点的最大位移量,或者先运行几轮“纯避障”模式——把平滑性权重暂时调小,让轨迹先脱离障碍物,再恢复平滑优化。

还要检查梯度计算是否正确。我在调试时经常用“数值梯度 vs 解析梯度”对比法:手动给控制点加一个小扰动,用差分估计梯度,和解析计算的梯度比对。如果两者差异超过5%,说明某个代价项的导数推错了。这个方法虽然笨,但能省下大量排查时间。

5.3 动态障碍物场景下的局限性

EGO-Planner在静态环境中表现出色,但在动态障碍物较多的场景中,有些固有限制需要清楚。

如果你用真实传感器(比如深度相机),点云处理链路本身的延迟是一个重要瓶颈。即使规划器只需要几毫秒,但点云从传感器采集、坐标变换、滤波降采样、Kd-tree构建整个流程如果串行执行,会拉到几十毫秒。当动态障碍物快速移动时,规划器拿到的障碍物信息可能已经是“过去的画面”,轨迹自然来不及避让。解决办法是把感知、规划、控制放在不同线程,点云更新频率尽量做到和传感器刷新率一致。

控制点数量对响应速度的影响也很大。控制点越多,优化变量越多,单帧规划时间越长,规划频率越低。在动态环境中,我倾向于减少控制点数量到10个左右,牺牲一点轨迹精细度,换取更高的规划频率。

还需要注意一个哲学层面的问题:EGO-Planner是局部规划器,它不考虑未来障碍物的运动轨迹。如果障碍物突然出现在离无人机极近的地方,任何局部规划器都来不及避开——这需要全局的决策层或更高级的“反应式”策略来兜底。EGO-Planner的定位是接管“本能的路径选择”,而不是预测未来。

5.4 调参优先级与速查表

调参这件事,顺序错了会浪费时间。我总结的调参优先级是:先保安全、再保可飞、最后保效率。

第一步,先保证轨迹不穿障碍。专注调λc和d_th两步。如果穿障碍,把λc从0.5往上加,同时把d_th从0.3往上加,直到轨迹在所有测试场景中都不穿障碍物。第二步,保证轨迹物理可飞。检查速度曲线和加速度曲线,如果超限,优先做时间重分配,再考虑调λd。如果还是超限,可以适当增大Δt或者降低v_max、a_max的期望值。第三步,才是调整体效率——减小平滑性权重让轨迹更直,或者增大终点引导权重让无人机更快接近目标。

下面这个速查表是我整理的排障优先级,可以直接抄作业。

现象可能原因排查/解决
轨迹穿障碍碰撞权重低/安全阈值小/点云稀疏先调λc到2.0,再调d_th到0.5,最后检查体素分辨率
优化发散震荡学习率大/初值差/梯度错误加line search,改进前端搜索,数值梯度对比
动态场景反应慢点云链路延迟/控制点太多线程化点云处理,减少控制点数到10-12
轨迹抖动、飞得不稳时间分配不合理/dt太小时间重分配,增大dt到0.2s
轨迹终点离目标远终点引导权重太低提高λg,或在优化完后对末段做重规划
狭窄通道卡住安全阈值太大/碰撞惩罚过强降低d_th到0.25m,降低λc到0.3

最后再分享一点个人体会。我在实际调试EGO-Planner的过程中,最大的收获不是学会了怎么用这个算法,而是彻底理解了“优化类规划器为什么需要好初值、为什么需要分模块设计”。纸上谈兵的理论,只有真正对着点云、轨迹、控制点一步一步排查问题时,才会变成肌肉记忆。下一篇系列文章我准备把工程实现细节继续往下拆,重点聊ROS节点怎么设计、代价地图怎么维护,以及官方开源代码里那些不起眼但特别关键的常数。如果你也在复现EGO-Planner,欢迎把遇到的问题留下来,下一篇我可以针对性展开讲。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询