简介:围绕机器人路径规划问题,将神经网络与遗传算法结合,用于环境特征学习、路径寻优与避障决策,适合机器学习、智能优化方向的研发人员或相关课程学习者参考。压缩包共182个文件,体量约1.2MB,文件类型以Java源程序、class编译产物、json网络参数配置、png可视化效果图、xml界面布局为主,并带有Gradle构建配置,便于导入开发环境后直接运行与调试。目前已有103人学习/浏览。通过源码可完整看到遗传算法负责种群初始化、交叉、变异与适应度评价,神经网络负责前向推理与反向传播训练,二者协同完成从起点到目标点的路径搜索;同时涉及A*、Dijkstra等基础搜索算法以及动态避障思路,可直接作为机器人路径规划课程设计、毕业设计或工程项目二次开发的基础蓝本。
1. 不只是两个算法拼盘:神经网络+遗传算法做机器人路径规划,解决什么问题
看到「基于神经网络+遗传算法实现机器人路径规划」这个标题,我脑子里先浮现的是一个很具体的场景:已知栅格地图、障碍物形状不规则、机器人要从起点走到目标点。纯遗传算法也能做,但适应度函数里的碰撞惩罚要么写得非常「手工」,要么对复杂障碍无能为力;把神经网络加进来,本质上是把障碍物环境变成一张可学习的危险度场——网络对任意坐标输出一个 0 到 1 的风险值,遗传算法拿着这个风险值去组合路点。这就是这个标题背后最常见、也最容易复现的工程路线。这篇文章会把四件事拆透:框架怎么搭、遗传算法怎么实现、神经网络怎么训、以及那些最容易被当成玄学的参数和坑。适合正在做课程设计或毕业设计、想真正改得动代码的人,也适合做移动机器人或 AGV 路径规划的工程师——你不只想看它能不能跑,还想知道它为什么这样设计、坏在哪个环节。
2. 神经网络和遗传算法怎么分工:两条集成路线与三项代价
2.1 两条集成路线:让神经网络当环境模型,还是当路径评分器
遗传算法是个全局搜索器,它的一切行为都由适应度函数驱动。所以神经网络加进来的方式,本质上只有两个主流方向:当环境模型,或者当路径评分器。
路线 A:神经网络当危险度模型。网络输入一个坐标 (x,y),输出该点的碰撞风险 0~1。训练样本由栅格地图的距离变换生成,遗传算法在评价路径时逐个查询采样点的风险。这个路线的优势非常明显:任意形状的障碍物都能被覆盖,只要训练样本铺满地图;输出是连续值而不是 0/1,遗传算法的小步变异能感受到「越来越危险」,搜索有梯度可循;网络可批量计算,还能被反向传播求梯度,后续做局部优化很方便。代价是需要先离线训练一轮,而且网络有近似误差。
路线 B:神经网络当路径评分器。输入整条路径的特征,比如总长、最大转角、到最近障碍的最小距离、危险点占比,输出一个 0~1 的综合评分,遗传算法用这个评分当适应度。这条路线的问题是:网络成了彻头彻尾的黑匣子,路径得 0.3 分你根本说不清哪里扣分;训练需要大量带标签的历史路径,得靠仿真器批量生成;对静态单地图来说性价比很低。我经手的这类打包项目里,绝大多数采用的是路线 A,因为它可解释、样本量小、职责清晰。
| 对比项 | 路线 A:NN 当危险度模型 | 路线 B:NN 当路径评分器 |
|---|---|---|
| 网络输入 | 单个坐标 (x,y) | 整条路径的特征向量 |
| 网络输出 | 该点风险 0~1 | 路径评分 0~1 |
| 训练样本 | 栅格点 + 距离场,轻松上万 | 大量带标签的历史路径 |
| 可解释性 | 高,风险场可直接可视化 | 低,黑匣子 |
| 与 GA 耦合方式 | GA 逐点查询风险 | GA 整条路径打分 |
| 适合场景 | 单地图 / 固定环境的工程与课题 | 离线仿真数据非常充足时 |
我的习惯是严格分工:遗传算法管路点组合这种组合优化问题,神经网络只管「这个点危不危险」。两边各干各的,出了问题才能定位——要么是搜索没收敛,要么是风险场不准。
2.2 染色体编码决定搜索空间:连续坐标编码与栅格编码
染色体怎么编码,决定了后面所有算子的写法。这个项目里最常见的两种:
连续坐标编码。每个基因是一个 (x,y) 真实坐标,一条染色体就是 N_WP 个路点的数组,形状是 (N_WP, 2)。优点是适应度里直接用几何距离公式算长度,算术交叉天然合法,高斯变异也符合「小幅微调」的思路,搜索结果可以直接给机器人用。缺点是搜索空间无界,需要把坐标裁剪回地图边界。
栅格编码。每个基因是栅格编号,路径是一串格子序号。优点是搜索空间有限且更小,碰撞查询就是查格子。但痛点很突出:交叉很容易产生重复格子和断裂序列,需要额外写修复算子;而且路径沿栅格中心走锯齿线,机器人根本没法跟踪,最后还得再做平滑。所以对差速驱动机器人,我一般推荐连续坐标编码,但碰撞查询时把坐标换算成栅格索引——这样两边优势都能拿到。
关于路点数量 N_WP:太小,比如 2~4 个点,表达不了绕障的复杂路径;太大,比如 30 个以上,搜索维度暴涨,收敛很慢。在 10m×10m 地图、0.1m 栅格分辨率下,8~16 个中间路点比较合适。地图里窄走廊越多,越取上限。
2.3 适应度函数三项折中:路程代价、危险代价、平滑代价
适应度我建议写成三项求和,而不是某单一指标:
cost = length + danger + smooth
路程代价好理解,就是所有路径段长度之和,单位米。危险代价要拆开说:沿每条路径段均匀采样若干点,送入神经网络得到风险 r∈[0,1]。这里有个关键技巧——最大值和均值要分开用。我的做法是:如果 r.max() > 0.9,判定为碰撞,直接加一个 100 的固定惩罚,数量级上压倒路程代价,保证任何碰撞路径都没有竞争力;否则加 12.0 × r.mean() × length。均值乘上路径长度,含义是「每走一米承担的平均风险」,这样一条穿过中等风险区域的短路径,和一条绕很远的安全路径,会在这个项上真实博弈。
平滑代价计算相邻路径段的航向角之差,取绝对值并规范化到 [0, π],再求和。系数通常在 0.5~2.0。三项目前看着简单,但权重一旦失衡,就会出现后面避坑章节里贴墙走、锯齿走这些典型问题。
3. 遗传算法主循环:从种群初始化到精英保留的可运行代码
3.1 路径个体初始化:在起点到终点的直线上加扰动
初始种群质量决定搜索起点。常见做法是:先在起点到终点的直线上均匀插值,再叠加高斯噪声。这样每个个体都是一条「大致合理但局部走形」的路径,前几代就具备绕障的潜力。
import numpy as np np.random.seed(20240101) # 地图与任务 MAP_W, MAP_H = 10.0, 10.0 start = np.array([0.5, 0.5], dtype=float) goal = np.array([9.5, 9.2], dtype=float) # 遗传算法参数 N_POP = 60 # 种群规模 N_WP = 12 # 中间路点数 N_GEN = 80 # 最大代数 CROSS_PB = 0.85 # 交叉概率 MUT_PB = 0.15 # 每个路点的变异概率 MUT_STEP = 0.5 # 变异步长(米) def init_individual(): """在起点到终点的直线上均匀插值,再叠加高斯噪声""" xs = np.linspace(start[0], goal[0], N_WP + 2)[1:-1] ys = np.linspace(start[1], goal[1], N_WP + 2)[1:-1] ind = np.stack([xs, ys], axis=1).copy() ind += np.random.normal(0, 0.6, size=ind.shape) return np.clip(ind, 0.1, np.array([MAP_W - 0.1, MAP_H - 0.1])) pop = [init_individual() for _ in range(N_POP)] print(pop[0].shape) # (12, 2)这段代码里,np.linspace 生成 N_WP+2 个点是因为首尾包含起点和终点,切片 [1:-1] 把端点去掉,染色体只保留中间路点。高斯噪声的标准差取 0.6m:太小,初始种群几乎都贴在同一条直线上,多样性不足;太大,初始个体就退化成随机点了。np.clip 把坐标限制在距地图边界 0.1m 的范围内,防止个体飘出地图。
3.2 锦标赛选择、算术交叉和高斯变异
选择、交叉、变异三个算子,对应连续坐标编码有一套非常顺手的实现:
def tournament_select(pop, costs, k=3): """锦标赛:随机挑 k 个个体,取代价最小的作为父代""" idx = np.random.choice(len(pop), k, replace=False) return pop[idx[np.argmin(costs[idx])]] def arithmetic_crossover(p1, p2): """算术交叉:子代路点取父母同位置路点的加权平均""" alpha = np.random.uniform(0.3, 0.7) c1 = alpha * p1 + (1.0 - alpha) * p2 c2 = (1.0 - alpha) * p1 + alpha * p2 return c1, c2 def mutate(ind): """高斯变异:按概率扰动每个路点,并裁剪回地图内""" for i in range(N_WP): if np.random.rand() < MUT_PB: ind[i] += np.random.normal(0, MUT_STEP, size=2) return np.clip(ind, 0.1, np.array([MAP_W - 0.1, MAP_H - 0.1]))锦标赛选择 k=3 是经验值。k 越小选择压力越小、越能保持多样性;k 越大收敛越快但容易早熟,3~4 是个稳妥区间。算术交叉不会打乱路点顺序,只是把父母同位置的路点做加权平均,所以后代天然是合法路径,不需要修复。MUT_PB 要特别注意:它按「每个路点」计,12 个路点的个体期望变异点数是 12×0.15≈1.8 个。如果你把这个概率当成个体级的变异概率,那每一代基本不会有任何变异发生,种群很快就僵住了——这是最容易踩的坑之一。
注意:MUT_PB 是点均概率,不是个体概率。写成 0.15 意味着每个路点有 15% 的概率被扰动。
3.3 主循环:先用几何碰撞跑通,再替换成神经网络评估
训练神经网络之前,适应度里的风险项先用精确几何碰撞检测顶替。这非常重要:如果 GA + NN 一上来就组合跑,路径穿墙了你无法判断是搜索的问题还是网络的问题。
RES = 0.1 # 栅格边长(米) def load_occupancy_grid(): """按你自己的地图格式读取 0/1 栅格,1 表示障碍物""" # 返回 H x W 的 numpy 数组 pass def geometric_risk(points): """精确几何碰撞检测:返回 0/1,1 表示该点落在障碍栅格里""" occ = load_occupancy_grid() H, W = occ.shape risks = np.zeros(len(points)) for i, p in enumerate(points): col = int(p[0] / RES) row = int(p[1] / RES) if 0 <= row < H and 0 <= col < W and occ[row, col] == 1: risks[i] = 1.0 return risks def fitness(ind, use_nn=False): pts = np.vstack([start, ind, goal]) seg = np.diff(pts, axis=0) length = float(np.linalg.norm(seg, axis=1).sum()) # 沿每段均匀采样 8 个点(不含端点) samples = [] for i in range(len(seg)): t = np.linspace(0, 1, 8, endpoint=False) samples.append(seg[i][None, :] * t[:, None] + pts[i][None, :]) samples = np.concatenate(samples, axis=0) # risk_net_predict 在 4.2 节定义:把物理坐标转归一化后送入网络 risk = risk_net_predict(samples) if use_nn else geometric_risk(samples) danger = 100.0 if risk.max() > 0.9 else 12.0 * float(risk.mean()) * length ang = np.arctan2(seg[:, 1], seg[:, 0]) turn = np.abs(np.diff(ang)) turn = np.minimum(turn, 2 * np.pi - turn) smooth = float(turn.sum()) return length + danger + 1.5 * smooth def run_ga(use_nn=False): pop = [init_individual() for _ in range(N_POP)] best_path, best_cost = None, float("inf") for gen in range(N_GEN): costs = np.array([fitness(ind, use_nn) for ind in pop]) elite_idx = int(np.argmin(costs)) if costs[elite_idx] < best_cost: best_cost = float(costs[elite_idx]) best_path = pop[elite_idx].copy() # 精英直接进入下一代,保证最优个体不丢失 new_pop = [pop[elite_idx].copy()] while len(new_pop) < N_POP: p1 = tournament_select(pop, costs) p2 = tournament_select(pop, costs) if np.random.rand() < CROSS_PB: c1, c2 = arithmetic_crossover(p1, p2) else: c1, c2 = p1.copy(), p2.copy() new_pop.append(mutate(c1)) if len(new_pop) < N_POP: new_pop.append(mutate(c2)) pop = new_pop if gen % 10 == 0: print(f"gen {gen:3d} best_cost = {best_cost:.3f}") return best_path, best_cost # 先用几何碰撞跑通 best_path, best_cost = run_ga(use_nn=False)这段代码里,路径有 N_WP+1=13 段,每段采样 8 个点,也就是每个个体需要评估 104 个点。60 个个体跑 80 代,总共约 50 万次风险查询,小网络在 CPU 上几秒就能算完,性能完全不是瓶颈。danger 项用「max>0.9 则罚 100」的思路,是让碰撞代价大到无法用路程换; 而 r.mean() × length 的写法,让危险代价和路程代价在同一量纲上博弈,系数 12.0 的含义就是「你愿意为降低单位平均风险多绕多少米」。
4. 神经网络训练:把栅格地图变成可导的危险度场
4.1 训练数据生成:距离变换 + 负指数标签
神经网络输出的风险值,不是靠手工标注出来的,而是从栅格地图的距离变换自动生成。距离变换给每个自由栅格算出到最近障碍物的欧氏距离,然后我们对距离做一个负指数映射:距离越近风险越接近 1,距离越远风险趋近 0。
from scipy.ndimage import distance_transform_edt GRID_RES = 0.1 # 栅格边长(米) def load_occupancy_grid(): # 返回 H x W 的 0/1 数组,1 表示障碍物 pass occ = load_occupancy_grid() H, W = occ.shape # 所有栅格中心的物理坐标(米) xs = (np.arange(W) + 0.5) * GRID_RES ys = (np.arange(H) + 0.5) * GRID_RES xx, yy = np.meshgrid(xs, ys) coords = np.stack([xx.ravel(), yy.ravel()], axis=1).astype(np.float32) # 坐标归一化到 [0,1] 附近,方便网络收敛 coords_norm = coords / np.array([MAP_W, MAP_H], dtype=np.float32) # 每个格子到最近障碍物的欧氏距离(米) dist = distance_transform_edt(1 - occ) * GRID_RES sigma = 0.3 risk = np.exp(-dist.ravel() / sigma).astype(np.float32) print(coords_norm.shape, risk.shape) # (10000, 2) (10000,)坐标除以地图边长归一化到 [0,1] 附近,这是网络输入的常规预处理。sigma 决定「危险晕圈」的半径:0.3m 意味着离障碍物 0.3m 处风险约 e^-1≈0.37,离障碍物 1m 处风险只有约 0.036。sigma 太小,风险场在障碍边界附近变化过陡,网络逼近困难;sigma 太大,整个地图都处于中等风险,路径会被推得过度保守。障碍物内部栅格距离为 0,风险标签为 1,这没问题——路径采样点落在障碍物里就该被重罚。
4.2 训练一个全连接风险评估网络
有了坐标和风险标签,训练就是一个标准的回归任务。网络结构不需要大,两个输入一个输出,两层 32 维的全连接加 Sigmoid 足够。
import torch import torch.nn as nn class RiskNet(nn.Module): def __init__(self): super().__init__() self.net = nn.Sequential( nn.Linear(2, 32), nn.ReLU(), nn.Linear(32, 32), nn.ReLU(), nn.Linear(32, 1), nn.Sigmoid(), ) def forward(self, x): return self.net(x) def train_risk_net(coords_norm, risk, epochs=200, lr=1e-3, batch=256): model = RiskNet() opt = torch.optim.Adam(model.parameters(), lr=lr) loss_fn = nn.MSELoss() X = torch.from_numpy(coords_norm) y = torch.from_numpy(risk).reshape(-1, 1) n = len(X) for ep in range(epochs): perm = torch.randperm(n) total_loss = 0.0 for i in range(0, n, batch): idx = perm[i:i + batch] opt.zero_grad() pred = model(X[idx]) loss = loss_fn(pred, y[idx]) loss.backward() opt.step() total_loss += loss.item() * len(idx) if ep % 20 == 0: print(f"epoch {ep:3d} loss = {total_loss / n:.5f}") return model def risk_net_predict(points): """把物理坐标批量送入网络,返回 0~1 风险""" pts = torch.from_numpy(points.astype(np.float32)) pts_norm = pts / torch.tensor([MAP_W, MAP_H], dtype=torch.float32) with torch.no_grad(): return model(pts_norm).numpy().ravel()最后一层用 Sigmoid 是因为标签范围是 [0,1],输出必须压到这个区间; MSE 损失和这个平滑回归任务很匹配,不需要用交叉熵。训练时对样本做随机打乱再按 batch 切分,避免连续坐标产生梯度方向偏移。模型训练完成后,把它接回第三章的主循环:
model = train_risk_net(coords_norm, risk, epochs=200, lr=1e-3) best_path, best_cost = run_ga(use_nn=True)这样 GA 的风险评估就从精确几何检测切换成了神经网络。200 个 epoch 在 CPU 上也就一两分钟,完全没必要上 GPU。
4.3 关键参数表与调参顺序
| 参数 | 建议范围 | 说明 |
|---|---|---|
| 种群规模 N_POP | 40~80 | 路点数 8~16 时够用,太小容易早熟 |
| 路点数 N_WP | 8~16 | 窄走廊多取上限,地图简单取下限 |
| 交叉概率 CROSS_PB | 0.7~0.9 | 算术交叉破坏性小,可以偏大 |
| 变异概率 MUT_PB | 0.08~0.25 | 按路点计,别当个体概率 |
| 变异步长 MUT_STEP | 0.2~0.6 m | 后期可衰减到 0.1 附近 |
| 危险代价系数 | 8~16 | 理解为「愿为降风险多绕的米数」 |
| 平滑代价系数 | 0.5~2.0 | 越大路径越直,但也越容易绕远 |
| 风险标签 sigma | 0.2~0.5 m | 决定危险晕圈半径 |
| 网络结构 | 32×2 层起步 | 单地图 2 输入,更深的网络只会过拟合 |
调参顺序比参数值本身更重要。我的套路是:先用几何碰撞检测把 GA 跑通,确认路径基本不穿墙;再训练神经网络,拿一组随机采样点对比网络输出和几何检测的误判率,确认风险场总体可信;然后把 GA 切到神经网络评估,先动危险系数,路径贴墙就加大、绕太远就减小;最后才动平滑系数去锯齿。调参这件事多少有点玄学,但不按这个顺序调,出了问题你连是哪一块的锅都不知道。
5. 避坑:神经网络+遗传算法路径规划最常见的 5 个翻车点
5.1 现象一:训练损失很低,路径却横穿障碍物边缘
现象:神经网络在训练集上的 loss 已经降到 0.01 以下,但 GA 找到的最优路径仍会贴着障碍物边缘穿过,采样点明明离障碍只有半个栅格,网络却给出很低的危险值。
原因:训练样本只取了栅格中心点,而路径采样点大量落在栅格边界附近; 负指数标签在障碍边缘变化很陡,网络对快速变化区域的插值天然不可靠。这是典型的「数据覆盖盲区」问题。
解决:三管齐下。生成样本时加入抖动,把坐标随机偏移半个栅格以内;把 sigma 从 0.3 调大到 0.5,让边界附近的标签变化平滑一些;在适应度里保留 max>0.9 的重罚分支,让路径整体被推离障碍。更稳妥的做法是建立两级检查:神经网络做引导,精确几何检测做最终把关,两者不一致时按几何检测结果重罚。
5.2 现象二:最优个体 30 代不更新,路径一直贴着墙走
现象:每 10 代打印一次最优代价,后面连续三四次打印值完全不变;把路径画出来,它贴着障碍物走,虽然没碰撞但毫无安全余量。
原因:精英保留让最优个体一直占据种群,但变异步长太大,精英附近的微调根本落不到更好的点;同时危险系数太小,贴墙路径和留出 0.3m 余量的路径在适应度上只差零点几,选择压力不足以推动改进。
解决:危险系数加到 12~16,让障碍附近的适应度有明显「坡度」;变异步长随代数衰减,比如从 0.6 线性降到 0.15;再就是对最优个体做局部爬山搜索,在每个路点周围用小步长扰动尝试十几次。这个局部细化经常比让 GA 继续跑 50 代更有效。
5.3 现象三:路径不碰障碍,但机器人没法走——锯齿和急转
现象:路径在栅格视角下完全可行,但相邻路点之间的方向左一下右一下,形成锯齿; 或者出现接近 90° 的急转,实际机器人的最小转弯半径根本跟不住。
原因:平滑代价算的是相邻段航向角差值的绝对值之和,小幅锯齿比如 5°、8° 累积起来总共也就几十度,在几十米的路程代价面前微不足道; 而且 N_WP 如果偏大,冗余路点本身就会制造微型锯齿。
解决:平滑项改成「转向角绝对值之和 + 方向反转次数 × 惩罚」,方向每反转一次加一个固定值,比如 2.0; 平滑系数上调到 2~4; 规划完成后用 B 样条对路点做后处理平滑。这三个动作里,最容易见效的是给方向反转加惩罚,因为锯齿的本质就是频繁反转。
5.4 现象四:换一张地图模型就失效,路径乱窜
现象:同一套代码,把地图 A 换成地图 B,重新生成训练数据并训练,路径却直接穿过 B 里的新障碍; 网络在 B 上的输出明显失真。
原因:网络输入只有 (x,y),没有任何障碍物信息。对单张地图训练时,网络本质上是把这张地图的距离场背下来了——它学的是「这张图的障碍在哪」,而不是「什么样的局部环境危险」。换图等于让模型出了自己的训练域。
解决:先明确适用边界。如果地图固定,重新生成数据重训就行,一万个样本加 200 epoch 只要几分钟,这是成本最低的解法。如果希望模型跨地图泛化,输入必须加入局部环境特征,比如把该坐标周围 k×k 窗口的栅格占用值拼进输入向量,输入维度变成 2+k²,网络才可能学到「局部看起来像障碍的东西是危险的」。对这个项目来说,固定地图重训是最可靠的路径。
5.5 现象五:多次运行结果方差大,绕路时近时远
现象:同样参数换随机种子跑,有时候路径很合理,有时候绕一个大圈,多次运行的平均代价波动超过 20%。
原因:初始种群全部从「直线加噪声」生成,如果起点到终点的直线恰好穿过一大片障碍,初始种群几乎没有任何个体能给出绕障的可行雏形; 锦标赛加精英保留收敛快,多样性崩塌后很容易停在差的局部最优。
解决:初始化时混入 20%~30% 的纯随机个体,路点坐标完全随机生成,保证障碍两侧都有探索者; 加上重启机制,最优代价连续 20 代不更新就把种群重新初始化,只保留精英; 最终验证时固定跑 5~10 个种子看均值和方差,而不是信任单次结果。
6. 验证与进阶:仿真验证三件套,和三个能搬的扩展方向
6.1 验证三件套:可视化、多种子统计、与纯几何 GA 对比
路径规划的结果必须可视化,不然你永远不知道代价函数在奖励什么。把栅格地图和路径画在同一张图上,是最低成本的验证手段:
import matplotlib.pyplot as plt def plot_result(occ, path, start, goal): fig, ax = plt.subplots(figsize=(6, 6)) ax.imshow(occ, cmap="gray_r", origin="lower") pts = np.vstack([start, path, goal]) ax.plot(pts[:, 0] / GRID_RES, pts[:, 1] / GRID_RES, "o-", color="tab:red", lw=2, markersize=4) ax.set_title("planned path") plt.show()可视化之后做两件事:一是沿路径加密采样,用几何碰撞检测确认没有任何一个点落在障碍栅格里; 二是多种子统计,固定参数跑 10 个随机种子,记录最优代价的均值和标准差。标准差超过均值 10%,说明算法稳定性不够,优先回看初始化和变异概率。
更严格的对比是和「纯几何 GA」比:同一套 GA 参数,一个用精确碰撞,一个用神经网络风险场。如果神经网络版的平均代价明显高于几何版,说明风险场有系统性偏差;如果两者代价接近但神经网络版更平滑,那就说明混合方案的价值被验证了——用近似模型换来更平滑的搜索梯度。
6.2 进阶方向:梯度细化、动态障碍、机械臂关节空间
第一个值得做的扩展是梯度细化。神经网络风险场是可导的,GA 负责给出全局合理的初始路径,之后直接把路点当作优化变量,用 PyTorch 自动求导对「长度 + 风险 + 平滑」做几十步梯度下降。GA 提供好的起点,梯度下降负责精修局部,这个组合比单纯让 GA 多跑几十代快得多,代码量大约五十行。
第二个扩展是动态障碍。障碍位置变化时,不需要重新规划整条路,只需要更新风险场标签并重训网络,或者把局部窗口栅格拼进网络输入,让机器人边移动边评估当前风险。环境整体剧变时才从当前位置重启 GA。神经网络的优势在这里体现得最明显——单次评估是微秒级,重规划成本很低。
第三个扩展是机械臂。把染色体里的 (x,y) 换成关节角向量,网络输入变成关节状态,输出改成末端在工作空间里的碰撞概率; 「长度」项变成关节运动量,「平滑」项变成关节速度变化。算法框架完全不用动,只换编码和风险模型——这也是这类项目最常被扩展的方向。我现在拿到任何一个混合规划工程,第一件事都不是看 README,而是先跑数据生成脚本,把风险场画出来看一眼。标签对不对、坐标系有没有对齐、sigma 合不合理,一眼就能看出来; 后面算法调不通,回过头来八成还是数据的问题。这个习惯帮我少走了很多冤枉路,希望今天的拆解也能帮你少踩几次坑。
本文还有配套的精品资源,点击获取