资讯动态

人工势场法详解:MATLAB与C++实现避障路径规划

发布时间:2026/8/31 7:35:25 来源:尧图企业网站定制
简介本资源是一套面向机器人路径规划初学者与开发者的实用代码包聚焦人工势场法APF原理实现与跨平台移植解决移动机器人在静态障碍环境中自主寻路与避障的核心问题。压缩包共5个文件4个MATLAB脚本1个C源文件总大小仅8KB轻量易读MATLAB部分含主程序及引力、斥力、角度计算等模块化函数并配有详尽中文注释C版本则提供可编译的APF核心逻辑便于嵌入实时控制系统。已有1451人学习下载体现了其在教学与工程实践中的广泛认可。读者可直接运行MATLAB代码观察势场可视化效果理解梯度下降更新机制与局部极小值现象通过对比C实现掌握算法移植要点如向量运算优化与内存管理策略同时获得一套参数可调、结构清晰、注释完备的双语言参考模板显著降低路径规划算法入门与二次开发门槛。 做移动机器人路径规划的朋友大概率都绕不过人工势场法这个名字。它把目标点设计成引力源、障碍物设计成斥力源机器人沿着合力方向运动像流水绕石头一样避开障碍、抵达终点。我这篇文章就是把手写的带中文注释的MATLAB版和可编译运行的C版都拆开讲透从公式到代码、从参数到坑点一次说清。适合正在做课程设计、毕业设计的学生也适合刚上手机器人导航、想快速落地一个避障算法的工程师。人工势场法的思路看着简单真正动手写代码才会碰到一堆问题参数怎么配、为什么路径会来回震荡、困在局部极小值里怎么跑出来。这些坑我在MATLAB和C两个版本里都踩过下面把我调试通过的代码思路、参数调优经验、以及几个经典问题的改进方案全部整理出来每段代码都标注了中文注释你看完可以直接复制改参数跑。1. 人工势场法的算法思路与适用场景1.1 物理类比与核心逻辑人工势场法Artificial Potential Field简称APF的核心思想借用了物理学里的“场”概念。你可以想象一个地形目标点是个洼地障碍物是凸起的山包机器人是一个小球它在地形上滚动总是往低处走最终滚进目标点的洼地同时不会撞上障碍物的山包。放到数学里这个“地形”就是一个势场函数。目标点产生的势场是引力势场距离目标越远势能越高机器人受指向目标点的引力障碍物产生的势场是斥力势场距离障碍物越近势能越高机器人受背离障碍物的斥力。机器人每一步都沿着“引力加斥力”的合力方向移动直到抵达目标点。这个思路相比A*、Dijkstra这类基于栅格搜索的算法最大的优势在于不需要对整个地图建栅格也就没有分辨率的概念路径是连续的计算量极小每一步只算当前位置的合力适合实时控制实现起来很直观几十行代码就能跑通一个基础版本我在实际项目中一般把它用作局部避障层上一层用全局路径规划给出目标方向APF负责应对动态障碍物和突发情况。不过单说这个算法本身它也是路径规划入门非常好的教学案例——公式不复杂可视化之后能看到很多有意思的现象。1.2 它能做什么、不能做什么先说能做什么二维平面内的静态避障路径规划、简单的动态障碍物避让、机械臂末端避障、无人机低空飞行避让这些都是APF常见的应用场景。因为它计算快所以很多需要实时响应的导航系统都会用它作为一个快速避障模块。不能做什么也很重要。最典型的两个问题一个是局部极小值另一个是目标不可达。前者表现为机器人在某个非目标点的位置卡住因为引力势场和斥力势场在某处合力恰好为零后者表现为机器人明明可以看到目标点但就是走不过去因为目标点附近的障碍物斥力把机器人“推”在门外。这两个问题不是代码写错了而是这个算法本身的天然缺陷。后面我会专门讲怎么针对它们做改进。你先记住一个结论APF不是万能的它适合“大部分时间空旷、少数几个障碍物”的场景不适合狭窄通道、密集障碍物这种复杂环境。2. 数学原理详解引力场、斥力场与合力求解2.1 引力势场与引力计算引力势场最常用的定义是二次型势场公式写成这样U_att(q) 0.5 * k_att * ||q - q_goal||^2其中 q 是机器人当前位置q_goal 是目标点位置k_att 是引力增益系数||q - q_goal|| 是机器人到目标点的欧氏距离。对位置求负梯度得到引力F_att(q) -grad(U_att) -k_att * (q - q_goal)注意这个公式里 (q - q_goal) 是个向量从目标点指向机器人当前位置加负号之后方向就反过来变成从机器人指向目标点。这说明引力大小和距离成正比距离越远拉力越大机器人靠近目标之后力会变小方便收敛。选择二次型而不是线性势场是因为它的导数是线性的力的大小随距离平滑变化不会在远处出现过大冲击力。实际工程里我见过用线性势场的版本效果差不多但到了目标点附近收敛不够平滑不如二次型用得顺手。2.2 斥力势场与斥力计算斥力势场只在障碍物一定范围内起作用超出这个范围斥力为零。经典公式如下U_rep(q) 0.5 * k_rep * (1/ρ(q) - 1/ρ0)^2, ρ(q) ≤ ρ0 U_rep(q) 0, ρ(q) ρ0ρ(q) 是机器人到障碍物的最近距离ρ0 是障碍物斥力场的最大影响半径k_rep 是斥力增益系数。对位置求负梯度得到斥力F_rep(q) k_rep * (1/ρ - 1/ρ0) * (1/ρ^2) * ▽ρ(q)这里 ▽ρ(q) 是从障碍物指向机器人方向的单位向量。所以斥力的方向总是背离障碍物大小随着距离变小急剧增大。有个容易忽略的细节ρ→0 的时候斥力趋于无穷大这保证了机器人理论上不会撞上障碍物但实际数值计算中 ρ 可能会变得非常小导致斥力溢出。所以代码里我一般会加一个判断当距离小于某个极小值比如 1e-6时直接给一个安全方向上的大推力。这个在仿真里少见真机上传感器噪声大容易踩到。2.3 合力方向与迭代运动模型把引力和所有障碍物的斥力叠加就是机器人受到的合力F_total F_att Σ F_rep_i有了合力接下来就是迭代移动。最简单的方法是固定步长法q_next q_current step * F_total / ||F_total||step 是每次迭代的步长单位是米或者任意长度单位。把合力归一化之后乘上步长好处是机器人每一步走的路程恒定不会因为合力大小变化导致步幅忽大忽小更容易控制。这里的步长值很关键。步长太大路径会锯齿状震荡甚至跳过窄缝步长太小迭代次数变多计算量大而且在小地图上看不出问题、大地图上会非常慢。我一般取机器人尺寸的 1/10 到 1/20 作为初始值后面再根据实际路径平滑度微调。迭代终止条件一般是机器人到达目标点附近距离小于阈值或者达到最大迭代次数。如果最大迭代次数到了人还没到目标多半是卡在局部极小值了这时候得用后面的改进方案处理。3. MATLAB实现带中文注释的完整思路3.1 程序结构设计MATLAB版本我建议按“初始化配置—主循环计算—结果可视化”三段式来组织。这样结构清楚改参数、调逻辑都很方便。初始化部分负责定义起点、终点、障碍物坐标以及所有算法参数。主循环部分是核心每一步计算当前点的引力和斥力更新位置并记录路径。可视化部分用 plot 函数把路径画出来同时画出障碍物和目标点一眼就能看到效果。为什么要把参数集中放在文件开头因为调参是APF使用中最频繁的操作每次仿真很可能要试几十组参数。集中定义后只需改几行数字不用在代码里到处找。我早期写代码时参数散落各处改一次就要全局搜索替换非常痛苦。3.2 核心代码与中文注释下面这段是MATLAB版本的核心循环我加了比较详细的中文注释你可以在MATLAB R2016以上任何版本直接跑% 人工势场法路径规划 - 核心循环 % 坐标系二维平面单位保持一致即可 start [0, 0]; % 起点坐标 goal [10, 10]; % 目标点坐标 obs [5, 5; 4, 7; 7, 4]; % 障碍物坐标每行一个障碍物 % 算法参数 k_att 1.0; % 引力增益系数控制向目标靠拢的力度 k_rep 100; % 斥力增益系数控制避开障碍物的强度 rho0 2.0; % 障碍物斥力影响半径 step 0.1; % 每次迭代步长 max_iter 1000; % 最大迭代次数防止死循环 pos start; % 机器人当前位置初始等于起点 path pos; % 路径记录矩阵每行一个位置点 for i 1:max_iter % 计算引力向量 % 公式F_att -k_att * (pos - goal) % 结果是一个指向目标点的向量 F_att -k_att * (pos - goal); % 计算斥力向量对所有障碍物求和 % 只有距离小于影响半径的障碍物才产生斥力 F_rep [0, 0]; for j 1:size(obs, 1) dist norm(pos - obs(j, :)); % 当前点到第j个障碍物的距离 if dist rho0 % 斥力公式k_rep * (1/dist - 1/rho0) * (pos - obs) / dist^2 % 方向是背离障碍物大小随距离减小急剧增大 F_rep F_rep k_rep * (1/dist - 1/rho0) * (pos - obs(j, :)) / dist^2; end end % 合力 引力 所有斥力之和 F_total F_att F_rep; % 归一化并按固定步长移动 % 这里加一个极小值保护防止合力为零时除零报错 if norm(F_total) 1e-6 break; % 合力为零说明陷入局部极小值提前结束 end pos pos step * F_total / norm(F_total); % 记录路径 path [path; pos]; % 到达判定距离目标点小于0.1视为到达 if norm(pos - goal) 0.1 break; end end % 可视化结果 figure; plot(path(:, 1), path(:, 2), b-, LineWidth, 1.5); hold on; plot(obs(:, 1), obs(:, 2), ro, MarkerSize, 10, MarkerFaceColor, r); plot(start(1), start(2), go, MarkerSize, 10, MarkerFaceColor, g); plot(goal(1), goal(2), b^, MarkerSize, 10, MarkerFaceColor, b); grid on; axis equal; xlabel(X); ylabel(Y); title(人工势场法路径规划结果); legend(规划路径, 障碍物, 起点, 目标点, Location, best);这段代码跑出来的效果基本上是一条从起点出发、绕过障碍物、到达目标点的平滑曲线。如果障碍物位置摆放得比较“刁钻”比如两个障碍物正好夹出一条窄缝你可能会看到路径在缝口来回抖动那就是参数需要调节的信号。3.3 仿真结果解读与常见问题现象我第一次跑通这个代码的时候测试场景很简单起点(0,0)、终点(10,10)、一个障碍物在(5,5)路径非常漂亮一条弧线绕过去。后来我把场景改成三个障碍物路径就开始出现问题了。最典型的现象是路径陷入两个障碍物之间机器人来回小幅震荡就是不往前走了。这就是局部极小值的典型表现——机器人在那个位置引力被两个方向相反的斥力抵消合力为零。另一个现象是“死贴障碍物”路径贴着障碍物边缘走距离非常近看着都揪心。这是因为斥力增益太小、影响半径太小或者步长太大导致机器人“冲”进了斥力区。解决办法是把 k_rep 调大或者把 rho0 调大让斥力在更远的地方就开始起效果。MATLAB版本调试的心得是先画势场图再调参数。在网格上计算每个点的势场值并画等高线图能直观看到障碍物周围“鼓起”的山包和目标的“洼地”机器人走不过去的地方在势场图上一定有一道“山脊”。我调试时经常同时画等高线图和路径图这样很快就知道参数差在哪。4. C版实现从算法到可运行工程4.1 类设计与数据结构C版本和MATLAB版本在思路上一样但工程组织上差异很大。MATLAB是脚本式编程变量不用声明类型循环写起来随意C讲究数据结构和类的封装尤其当你想把这个算法搬到ROS节点、嵌入式设备或者游戏AI里时好的设计能省很多事。我建议定义一个 PlannerConfig 结构体保存所有参数定义一个 PotentialFieldPlanner 类对外提供 plan 接口。内部用 vector 保存路径和障碍物坐标Point 是一个简单的二维坐标结构体带一个 norm 成员函数。为什么要把参数单独抽成结构体因为现实项目里参数很可能来自配置文件、命令行或动态调参服务。结构体打包之后序列化和反序列化都很方便不会出现参数散落在代码里改一处漏一处的尴尬情况。我之前在ROS里用的时候配置就是从一个 yaml 文件读进来的结构体直接映射配置项非常方便。这个设计思想在MATLAB版本里不太需要因为MATLAB本身就是交互式的但C项目一定要从一开始就想清楚。4.2 关键代码实现下面是C版本的核心实现包含结构体定义、类定义和主循环逻辑三个部分。我用 vector 做容器没有依赖第三方库标准C11就能编译配好编译器环境后新建一个 cpp 文件复制进去即可。#include vector #include cmath #include iostream // 二维坐标点结构体 struct Point { double x, y; Point(double x 0, double y 0) : x(x), y(y) {} // 返回向量模长 double norm() const { return std::sqrt(x * x y * y); } // 重载运算两个点相减得到从q到this的向量 Point operator-(const Point p) const { return Point(x - p.x, y - p.y); } Point operator(const Point p) const { return Point(x p.x, y p.y); } Point operator*(double scalar) const { return Point(x * scalar, y * scalar); } Point operator(const Point p) { x p.x; y p.y; return *this; } }; // 算法参数配置结构体 struct PlannerConfig { double k_att 1.0; // 引力增益 double k_rep 100.0; // 斥力增益 double rho0 2.0; // 斥力影响半径 double step 0.1; // 迭代步长 int max_iter 1000; // 最大迭代次数 double goal_threshold 0.1; // 到达判定阈值 }; class PotentialFieldPlanner { public: PotentialFieldPlanner(const PlannerConfig cfg, const Point start, const Point goal, const std::vectorPoint obstacles) : cfg_(cfg), start_(start), goal_(goal), obstacles_(obstacles) {} // 执行路径规划返回路径点序列 std::vectorPoint plan() { std::vectorPoint path; Point pos start_; path.push_back(pos); for (int i 0; i cfg_.max_iter; i) { // 计算引力向量 // F_att -k_att * (pos - goal) Point f_att (pos - goal_) * (-cfg_.k_att); // 计算所有障碍物的斥力总和 Point f_rep(0, 0); for (const auto obs : obstacles_) { Point d pos - obs; // 从障碍物指向机器人的向量 double dist d.norm(); if (dist cfg_.rho0 dist 1e-6) { // F_rep k_rep * (1/dist - 1/rho0) * d / dist^2 double coef cfg_.k_rep * (1.0/dist - 1.0/cfg_.rho0) / (dist * dist); f_rep.x coef * d.x; f_rep.y coef * d.y; } } // 合力和移动 Point f_total f_att f_rep; double norm f_total.norm(); if (norm 1e-6) { // 合力接近零认为陷入局部极小值 std::cout Local minimum detected, break.\n; break; } pos f_total * (cfg_.step / norm); path.push_back(pos); // 到达目标判定 if ((goal_ - pos).norm() cfg_.goal_threshold) { break; } } return path; } private: PlannerConfig cfg_; Point start_, goal_; std::vectorPoint obstacles_; }; // 使用示例 int main() { // 配置参数 PlannerConfig cfg; cfg.k_att 1.0; cfg.k_rep 100.0; cfg.rho0 2.0; cfg.step 0.1; // 定义场景 Point start(0, 0); Point goal(10, 10); std::vectorPoint obstacles {Point(5, 5), Point(4, 7), Point(7, 4)}; // 执行规划 PotentialFieldPlanner planner(cfg, start, goal, obstacles); std::vectorPoint path planner.plan(); // 输出路径点 for (const auto p : path) { std::cout p.x , p.y std::endl; } return 0; }这段代码在Linux下用 g 编译或者Windows下用Visual Studio、VSCode配好C环境都能直接跑。输出就是一行行坐标点把这些点连起来就是路径。4.3 MATLAB与C版本的核心差异两个版本跑同一套逻辑结果应该完全一致。但工程实践中差异不小我用一个表格总结对比维度MATLAB版C版上手难度低脚本式改数即跑中需要编译环境可视化内置plot几步出图需要OpenCV/Qt或导出数据到MATLAB画图运行性能循环慢仿真够用快适合实时控制和嵌入式部署方式仅在装有MATLAB的机器上运行可交叉编译到嵌入式设备、ROS节点调试方式命令行交互随时观测变量IDE断点、日志输出相对繁琐如果你只是做课程仿真、验证算法用MATLAB就好。如果是做实物机器人、无人机、机械臂那C版本几乎是必须的——你不能指望小车里装一个MATLAB。我实际做过一个移动底盘项目就是用C版接在ROS的move_base后面做局部避障主循环跑在100Hz完全没压力。还有一个细节想提醒C版本里我加了dist 1e-6的保护条件这是从真机上踩坑得来的。有一次传感器报了一个极近距离的点dist 接近零斥力直接变成了 inf路径直接飞了出去。加了这个保护之后极端情况至少不会让程序崩溃。5. 绕不开的坑局部极小值与目标不可达5.1 为什么会出现局部极小值局部极小值是APF最出名的问题。它指的是机器人在某个非目标位置受到的引力和斥力方向相反、大小相等合力为零于是机器人永远停在那里。数学上势场函数的梯度为零有两种情况一种是最小值点也就是目标点另一种是鞍点或者局部极小值。在APF的场景里典型的局部极小值出现在机器人、障碍物、目标点三者近似一条直线而且障碍物挡住必经之路的时候。举个例子目标点在正前方障碍物在正中间机器人正对着障碍物走过去。障碍物的斥力把机器人往左后方推目标点的引力把它往右前方拉两个力在某个位置正好平衡机器人就卡住了。这事情的麻烦在于它不是一个bug而是算法本身的性质。我在MATLAB仿真里第一次遇到时还以为是代码写错了花了半天检查公式。后来才明白这是所有基于梯度下降算法的通病——只要函数有局部极值就可能被困住。5.2 目标不可达问题GNRON目标不可达问题稍微隐蔽一点但更让人头疼。它在数学上有一个专门的名字GNRONGoals Nonreachable with Obstacles Nearby目标点附近有障碍物时无法到达。原因是这样的经典APF的斥力场只跟机器人与障碍物的距离有关跟机器人与目标点的距离无关。当目标点紧挨着障碍物时机器人走到目标点附近目标点的引力趋近于零但障碍物的斥力仍然很大合力指向远离障碍物的方向结果机器人被“推”在目标点外面怎么都进不去。我在调参的时候遇到过这个情况目标点放在(10,10)障碍物放在(9.8, 10)看着只差0.2的距离但路径就是停在(9.2,10)附近来回打转。最后我把障碍物挪开才跑通。5.3 几种实用的改进方向针对局部极小值最直接的办法是加一个“随机扰动”。当检测到合力小于某个阈值时给机器人一个随机方向上的微小偏移打破力的平衡让它有机会走出局部极小值点。这个办法实现简单效果也不错但不保证100%成功复杂环境下可能会反复抖动。更好的办法是引入“虚拟目标点”或者“子目标点”。先用A*或者RRT这类全局搜索算法规划一条粗路径然后在粗路径上取几个子目标点APF依次追着子目标点走。这样全局路径保证了拓扑正确性APF保证了局部避障的实时性两个算法互补工程上非常常见。我在导航项目里用的就是这个方案。针对GNRON问题经典的解法是改进斥力场函数。把机器人与目标点的距离因子引入斥力公式中让机器人在靠近目标点时斥力也自动衰减。改进后的斥力公式长这样F_rep F_rep1 F_rep2其中 F_rep1 是原有的斥力分量F_rep2 是额外增加的、方向指向目标点的分量。具体公式不同论文里写法有些差异核心思想是一致的当机器人靠近目标点时斥力作用减弱引力能“压过”斥力保证目标点可达。改进方向这块我建议你先理解问题产生的原因再去翻论文找不同的公式。网上很多资料直接套公式看起来高大上但不知道为什么要加、加在哪出了问题还是不会改。我一开始就是直接把论文公式搬进来结果代码跑起来比原来还差后来仔细画力分解图才明白是哪里出了问题。6. 参数调优经验与常见问题排查6.1 增益系数、影响半径和步长怎么定参数调优是APF使用中最耗时间的环节而且没有一组参数能适应所有场景。下面是我实践下来比较合理的初始值和调整思路参数初始值建议调大之后的效果调小之后的效果k_att1.0路径更趋向直线避障不明显路径更绕收敛慢k_rep50~200避障更激进路径离障碍物更远可能撞障碍物路径贴障碍物走rho0机器人尺寸的2~5倍机器人更早开始避障路径平滑接近障碍物才避让容易反应不及step机器人尺寸的1/10收敛快但路径粗糙、可能震荡路径平滑但迭代次数多、计算慢这里最需要留意的经验是k_rep/k_att 的比例才是真正的敏感点。我调试时经常保持 k_att 不变只调 k_rep。如果路径贴着障碍物走就增大 k_rep如果机器人还没接近障碍物就在远处绕大圈就减小 k_rep。一般这个比例在50到200之间能覆盖大部分场景。rho0 的大小和地图的障碍物密度强相关。障碍物稀疏的环境rho0 可以设大点路径更早开始转向整体更平滑障碍物密集的环境rho0 设太大反而会出问题因为多个障碍物的斥力叠加可能把机器人逼进一条错误的路。步长的选择有一种简单实用的标准观察路径是否平滑、有没有来回振荡。如果有振荡先把步长减半试试。减半之后如果路径明显变好说明原步长偏大如果变化不大那问题多半出在增益比例上。6.2 常见现象与排查思路我在调试两个版本的过程中遇到过不少看起来莫名其妙的问题。下面列一个速查表你遇到类似现象可以对照排查现象可能原因解决办法路径在中途打转走走停停局部极小值合力在某点失衡加随机扰动或改用子目标点策略路径锯齿状震荡步长过大或参数比例不匹配减小步长调整k_rep/k_att比例目标近在眼前但走不过去目标点附近有障碍物GNRON问题换用改进斥力场公式路径整体偏斜不朝目标走k_att太小或k_rep太大增大k_att或减小k_repMATLAB直接报错矩阵维度不匹配初始坐标写成了行向量/列向量不一致统一所有坐标都是1×2的向量C编译报错结构体或类定义顺序问题、类型不匹配检查Point类定义放在使用之前C路径点全是NaN某步距离计算出了inf/inf确认没有除以零检查dist的保护条件6.3 从二维到三维以及动态障碍物扩展如果要把算法扩展到三维比如无人机避障其实改动很小。坐标从二维变成三维Point结构体里加一个 z 字段所有向量运算是三维的距离公式变成三维欧氏距离其他逻辑完全一样。我之前做过一个多旋翼的仿真几乎是把二维代码平移到三维半小时就完成了。动态障碍物的情况略微复杂。最直接的办法是每帧更新障碍物的坐标然后重新计算合力和下一步位置。只要传感器更新频率够快、步长够小APF天然有一种“动态避障”的效果。我在移动底盘上测试过障碍物慢慢横穿机器人路径时机器人会主动停下来或者绕开。问题只在速度差上——障碍物速度太快APF的反应速度跟不上。这时候可以结合预测算法把障碍物的预计位置提前算进斥力场。还有一个容易被忽略的点把APF和全局路径规划器结合起来之后子目标点的选择很重要。子目标点不能离当前机器人位置太远否则APF可能重新陷入局部极小值也不能太近否则全局路径的全局最优性就丢了。我在实践里的经验是子目标点取全局路径上距离当前点 5~10 个步长位置的那个点效果比较稳定。6.4 我的调参流程实战记录最后分享一个我实际调参数的流程仅作参考。场景是起点(0,0)、终点(10,10)、三个障碍物用的就是前面给出的代码和参数。第一次跑路径在(4.8,6)附近卡住了机器人打转出不来。我把 step 从0.1减到0.05震荡消失了但还是卡在同一片区域。确定了这是局部极小值。我先是加了随机扰动机器人确实从卡住的位置“挣脱”了但绕了一大圈路径不太自然。然后我改成子目标点方案在从起点到终点的直线上每隔3个单位设一个子目标点让APF依次追。结果路径非常自然从第一个子目标跑到第二个避开障碍物最终顺利到达终点。调完路径形态接着调避障距离。我发现路径离障碍物最近的地方只有0.2米考虑到机器人本身有尺寸太危险了。于是把 rho0 从2.0调到2.5k_rep 从100调到150。重跑一遍最近距离变成了0.6米这个值我更放心。整个调参过程大概花了一个小时。如果换成自动搜索的方式比如网格搜索或者贝叶斯优化可能更快但调试经验还得靠手工探索积累——你总不能连要搜哪个参数范围都不知道。我个人的体会是人工势场法最大的价值不在“最优”而在“快”和“简单”。你不需要它解决所有极端场景因为它本来就是局部避障器不是全局规划器。把它放在正确的位置上配合全局路径规划能解决很多实际问题。这两套代码我一直在用MATLAB版本用来快速验证新想法C版本用来落地到真实机器人上。你如果照着文章跑通了基础版再亲手调一次参数我相信你对路径规划这整个领域的理解都会深一截。最后一个小技巧调参时把势场等高线图和路径轨迹图画在一起叠加显示你能看到机器人看似“玄学”的路径其实一直在严格沿着势场下降方向走那一刻你会对这个算法有完全不一样的感知。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价