简介这套基于Q-Learning的路径规划MATLAB仿真系统面向机器学习与机器人路径规划初学者提供可在任意障碍物环境下自由选择起点与目标的完整仿真方案。资源共36个文件以24个M函数文件为主配合fig界面文件、txt说明文档、mat数据文件等涵盖Q表初始化、传感器感知、机器人运动控制、路径回放与统计绘图等模块同时包含可参考的GUI界面设计适合作为算法入门与二次开发的起点。资源已有1947人学习下载。压缩包仅221KB结构紧凑便于快速部署。通过研读源码可掌握Q-Learning核心流程理解状态-动作空间划分与奖励机制也可在此基础上尝试算法改进为后续学术论文写作或竞赛项目提供基础。附带说明与运行日志等材料有助于排查环境问题降低上手门槛。1. 基于Q-Learning的路径规划MATLAB仿真系统这可能是你跑通强化学习路径规划最快的路标题里写的Q-Learing其实是术语 Q-LearningQ 学习的常见拼写笔误下面统一用正确拼写。这个仿真系统的核心就一句话用强化学习里最经典的 Q-Learning 算法在 MATLAB 的二维栅格地图上让一个智能体从起点通过不断试错走到终点同时学会绕开障碍。相比 A*、RRT 这些传统路径规划算法Q-Learning 不需要预先掌握地图的解析模型也不需要手动设计启发式函数换个环境换个地图只要奖励函数不变重新训练就能出结果。对正在做课程设计、毕业设计或者想从传统路径规划转向学习方法验证电机控制、移动机器人、AGV 预研方案的工程师来说这套系统是性价比最高的起步方案。它看起来像玄学实际跑起来却非常直观几百行 MATLAB 代码就能把训练过程、Q 表更新和最终路径全部可视化。2. 为什么栅格地图 Q-Learning 是入局路径规划最顺的组合2.1 Q-Learning 在路径规划中的定位无模型、离策略、查表路径规划领域传统上被 A*、Dijkstra、RRT 这类算法主导。A* 在有完整地图时能给出最优路径RRT 适合高维连续空间但它们都有一个前提环境模型是已知的、静态的。一旦环境发生变化比如动态障碍物突然出现这些算法要么重跑一遍全局规划要么依赖局部避障模块打补丁。Q-Learning 的思路完全不同它属于无模型强化学习意思是智能体不需要知道环境的状态转移概率 P(s′|s,a)也就是从这个格子执行某个动作后一定会到哪个格子这个规律完全靠与环境交互得到的奖励信号来学习。更具体地说Q-Learning 是离策略off-policy算法。行为策略用来探索环境通常用 epsilon-greedy目标策略则是完全贪心的取下一状态所有动作中 Q 值最大的那个。这个离策略特性带来一个实际好处在训练阶段可以使用带随机性的探索策略充分尝试各种路线而学习目标始终是最优策略所以最终收敛出来的是全局最优的 Q 表而不是被探索策略带偏的次优策略。在地图规模不大的情况下Q-Learning 的实现就是一个查表过程。状态是栅格的行列坐标动作是上下左右四个方向Q 表就是一个 状态数 × 动作数 的矩阵。以 20×20 的地图为例状态数是 400动作数是 4Q 表只有 1600 个参数MATLAB 里一个 zeros 函数就能初始化。这正是它适合做仿真系统的核心原因参数规模小收敛过程肉眼可见方便调试。2.2 状态、动作、奖励怎么映射到栅格地图上要把路径规划问题翻译成 Q-Learning 能理解的马尔可夫决策过程需要确定三件事状态空间、动作空间、奖励函数。状态空间就是栅格地图上所有可行格子的集合。一般做法是直接用地图矩阵的行列坐标表示状态也可以用 sub2ind 把二维坐标压成一维索引方便查 Q 表。动作空间我建议从 4 邻域起步也就是上、右、下、左四个方向。8 邻域虽然能走出更短的斜线路径但会让动作选择变复杂而且容易规划出贴着障碍物走的危险路径这一点后面避坑章会专门讲。奖励函数的设计直接决定智能体能不能学会、学会后走出的路径是否合理。我的习惯是到达终点给一个较大的正奖励撞到障碍或越界给一个负奖励每走一步给一个小的负奖励作为时间代价。这样设计的好处是智能体不仅知道到终点好还能学会绕路不好、撞墙不好。如果你只设终点正奖励其他都是 0训练会非常慢因为智能体在到达终点之前收不到任何有效反馈这就是典型的稀疏奖励问题。参数上终点奖励 50、碰撞惩罚 -0.5、每步代价 -1 是一组经过了大量仿真验证的默认值。碰撞惩罚比每步代价小是为了避免智能体为了躲障碍绕太远的路因为绕远付出的步数代价总和会超过偶尔撞一次墙的代价这样智能体会学会宁可偶尔擦一下障碍也不走冤枉路。2.3 仿真系统框架环境、智能体、训练循环三件套在 MATLAB 里搭这个系统不需要用复杂的 App Designer 或 Simulink一个脚本加两个函数就够。整个框架分三层。环境层负责状态转移和奖励计算核心是一个 step_env 函数输入当前状态、动作、地图和终点输出下一个状态、即时奖励和是否结束。这一层是黑匣子智能体不关心内部怎么算只知道我做了动作 a环境给了我奖励 r把我送到了 s′。智能体层管策略和 Q 表更新。策略用 epsilon-greedy也就是以 epsilon 的概率随机选动作以 1-epsilon 的概率选 Q 值最大的动作。Q 表更新用经典公式Q(s,a) ← Q(s,a) α[r γ·maxQ(s′,·) − Q(s,a)]。训练循环层负责把环境和智能体串起来控制回合数、最大步数、探索率衰减。这里有一个经常被忽略的点探索率 epsilon 必须随训练进行衰减。如果一直保持 0.5 的探索率智能体永远有 50% 的概率在乱走Q 表很难稳定收敛。我一般每 50 个回合把 epsilon 乘一个 0.95 的衰减因子下限设在 0.05这样训练后期基本靠贪心策略走路径Q 值才能稳定下来。这套三件套结构同样适用于 Sarsa 和 DQN后面想横向对比算法差异时只需要换掉智能体层环境和训练循环几乎不用动。3. 在 MATLAB 里搭一个可复现的 Q-Learning 路径规划核心代码与参数设定3.1 生成栅格地图矩阵、障碍布局与可视化先在 MATLAB 里生成一张 20×20 的栅格地图。地图用矩阵表示0 是可行区域1 是障碍物。为了便于复现障碍位置我直接写死在脚本里读者可以随意改成自己的地图。% 生成 20x20 栅格地图0 表示可行1 表示障碍 map zeros(20, 20); map(3, 4:6) 1; % 横向障碍墙 map(8, 2:3) 1; % 左上角障碍块 map(10, 10:15) 1; % 中部横向长墙 map(13:16, 12) 1; % 纵向障碍墙 map(18, 5:8) 1; % 右下角障碍块 % 可视化地图白色为可行区域黑色为障碍 figure; imagesc(map); colormap(gray); axis equal; axis tight; title(20x20 栅格地图);这段代码本身不涉及算法但它决定了后面所有训练和验证的地图语义。用 imagesc 配合 colormap(gray) 是最简单的栅格可视化方案障碍物显示为黑色可行区域为白色。axis equal 保证每个格子是正方形不至于在视觉上把地图拉变形。我习惯把这张地图的生成放在脚本开头后面训练、路径回放、动画演示都复用 map 变量。如果你想测试不同障碍率下的表现可以把障碍位置改成随机生成但每次运行前最好固定随机种子否则地图每次都不一样排错时很难判断是算法问题还是地图问题。3.2 环境函数状态转移与奖励计算环境是整个仿真系统的核心智能体所有经验都来自和这个函数的交互。我把它写成一个独立的 MATLAB 函数便于在训练循环里反复调用。function [next_state, reward, done] step_env(state, action, map, goal) % 4邻域动作定义1上, 2右, 3下, 4左 moves [-1 0; 0 1; 1 0; 0 -1]; next_pos state moves(action, :); [R, C] size(map); % 处理越界和撞障碍原地不动并给惩罚 if next_pos(1) 1 || next_pos(1) R || ... next_pos(2) 1 || next_pos(2) C || ... map(next_pos(1), next_pos(2)) 1 next_state state; % 状态不变相当于撞墙被弹回 reward -0.5; % 碰撞惩罚 done false; return; end next_state next_pos; if isequal(next_state, goal) reward 50; % 到达终点的大奖励 done true; return; end reward -1; % 每走一步的时间代价 done false; end这个函数的关键设计有三个。第一撞墙后状态原地不动而不是取消这一步这样智能体能明确把这个方向会撞墙和奖励为负关联起来。如果写成撞墙后随机换方向经验信号会被噪声污染。第二碰撞惩罚设 -0.5低于每步代价 -1这是有意为之的目的在前面说过是让智能体不把绕远路当成躲避小代价碰撞的唯一手段。第三done 标志只在到达终点时为 true撞墙不结束回合这样单回合内智能体能多次试错。注意盲目调大碰撞惩罚未必是好事。有人把碰撞惩罚设成 -100结果智能体学成原地转圈因为任何移动都有风险不如停在起点安全。奖励设计要在敢探索和不犯错之间取平衡。3.3 Q 表更新与训练主循环一个可以反复用的模板有了地图和环境函数接下来是训练主循环。这是整个方案里最值得反复读的部分Q 表的更新公式就藏在这里。% 训练参数设置 alpha 0.1; % 学习率 gamma 0.95; % 折扣因子 epsilon 0.3; % 初始探索率 episodes 800; % 训练回合数 max_steps 300; % 单回合最大步数 % 起点和终点定义 start_pos [2, 2]; goal [18, 18]; % 初始化 Q 表状态数 x 动作数 n_states numel(map); n_actions 4; Q zeros(n_states, n_actions); % 状态索引匿名函数把二维坐标转成一维索引 sidx (s) sub2ind(size(map), s(1), s(2)); % 训练循环 episode_steps zeros(episodes, 1); % 记录每回合步数 for ep 1:episodes state start_pos; done false; step_count 0; while ~done step_count max_steps % epsilon-greedy 选动作 if rand() epsilon action randi(n_actions); % 探索随机动作 else [~, action] max(Q(sidx(state), :)); % 利用取最大 Q end % 与环境交互 [next_state, reward, done] step_env(state, action, map, goal); % Q 表更新核心公式 Q(sidx(state), action) Q(sidx(state), action) ... alpha * (reward gamma * max(Q(sidx(next_state), :)) - ... Q(sidx(state), action)); state next_state; step_count step_count 1; end episode_steps(ep) step_count; % 每 50 回合衰减探索率 if mod(ep, 50) 0 epsilon max(0.05, epsilon * 0.95); end end训练循环的逻辑很直白每次迭代从当前状态出发按 epsilon-greedy 选一个动作调 step_env 拿到下一状态和奖励再用 Q 表更新公式把这次的经验写回 Q 表如此反复直到到达终点或步数耗尽。sub2ind 把坐标转索引保证了 Q 表和地图格子的对应关系这个细节在被调时会让你少掉很多头发。参数设定的经验值我再解释一遍。学习率 alpha0.1 意味着每次更新只用新经验修正 10% 的旧 Q 值这样训练过程平稳不容易震荡。gamma0.95 表示智能体比较看重远期收益愿意为到达终点多走几步。如果 gamma 设成 0.5智能体会非常短视只盯着眼前的奖励很可能为了躲一步的惩罚而完全学不会长距离寻路。epsilon 的初始值 0.3 给训练前期留了足够探索空间而衰减下限 0.05 保证了训练后期仍保留少量随机性防止 Q 表陷入局部最优。3.4 路径回放与收敛曲线怎么确认它真的学会了训练结束后最重要的验证是两条一条是让训练好的 Q 表做过一次贪心路径回放看规划出的路线是否合理另一条是画每回合步数曲线看算法是否收敛。% 路径回放完全按 Q 表最大动作走一遍 state start_pos; path state; while ~isequal(state, goal) size(path, 1) max_steps [~, action] max(Q(sidx(state), :)); moves [-1 0; 0 1; 1 0; 0 -1]; state state moves(action, :); path(end1, :) state; end % 在栅格图上叠加规划路径 hold on; plot(path(:,2), path(:,1), r-, LineWidth, 2); plot(start_pos(2), start_pos(1), go, MarkerFaceColor, g); plot(goal(2), goal(1), r*, MarkerSize, 12); title(Q-Learning 规划路径);贪心回放和训练时的区别是回放过程中完全忽略探索每一步都取 Q 值最大的动作所以走出来的就是智能体学到的最优策略。把路径画在地图上一眼就能看出是否绕开了障碍、有没有明显的回头路这是最直观的验货方式。收敛曲线的画法更简单直接看 episode_steps 数组的变化趋势。% 每回合步数曲线反映训练收敛过程 figure; plot(episode_steps, LineWidth, 1.5); xlabel(训练回合); ylabel(到达终点的步数); title(收敛曲线越往后应该越平稳); grid on;理想情况下前 100 个回合的步数会剧烈波动因为智能体在乱撞200 回合之后步数会快速下降并趋于平稳。如果在训练后期步数仍然上下乱跳说明 Q 表没有收敛最常见的原因就是 epsilon 没有衰减或者学习率过大这两个坑下一章详细拆。4. Q-Learning 路径规划避坑指南从学不会到绕远路的排障记录4.1 训练几千回合仍频繁撞墙稀疏奖励加无惩罚的典型失败现象训练回合数开到了 3000episode_steps 曲线仍然居高不下路径回放时智能体撞墙撞得理直气壮好像根本没学过一样。原因奖励函数里只设了到达终点 50没设碰撞惩罚和每步代价。在前几百个回合智能体从起点走不到终点每一步拿到的奖励都是 0Q 表完全没有被有效更新。这就是稀疏奖励下的经典失败没有奖励信号就没有学习信号。解决把奖励函数改成终点 50、碰撞 -0.5、每步 -1的搭配让智能体每走一步都能收到反馈。改完之后你会发现前 50 回合它依然在乱走但在吃了几次碰撞惩罚后Q 表里对应障碍方向的 Q 值会被压低之后智能体会主动规避那个方向。这也是为什么我建议把碰撞惩罚设成 -0.5 而不是 -50惩罚太狠会让智能体不敢探索惩罚太轻又学不乖-0.5 配合 -1 的步代价是经过多轮调试的平衡点。4.2 Q 值震荡不收敛学习率、折扣因子和探索率的三角关系现象训练结束后Q 表看起来有数值但每回合步数曲线始终在 20 到 150 之间反复横跳找不到一条稳定的路径。原因三个最核心的超参互相没配合好。常见组合是 alpha0.5 过大加上 epsilon 不衰减导致 Q 表每次更新的幅度很大而又经常被随机动作覆盖Q 值一直在被新经验冲来冲去永远收敛不下来。解决把 alpha 降回 0.1并加入探索率衰减。按我前面的设置每 50 回合把 epsilon 乘 0.95下限 0.05。这个组合下训练后期随机扰动小Q 值更新幅度也小曲线会在几百回合内稳定下来。如果你发现改完还是震荡检查一下 gamma 是否设成了 1.0。gamma1.0 意味着智能体对未来每一笔奖励视为完全不打折在长路径场景下 Q 值会变得过于敏感我一般不会超过 0.98。4.3 路径贴着障碍物走4 邻域换 8 邻域后付出的隐蔽代价现象把动作从 4 邻域改成 8 邻域后路径确实变短了但规划的路径贴着障碍物边缘擦过去斜着穿越障碍墙的尖角看着就危险。原因8 邻域让智能体可以走斜线而斜线动作在对角方向上没有任何碰撞检测的额外约束。比如障碍物在右上角智能体从左上角向右下角移动时它的几何中心可能已经擦过障碍物角点但栅格判定只看目标格子是否为障碍这条动作被判定为合法。解决如果坚持用 8 邻域需要在环境函数里增加斜向移动的额外检测检查斜线经过的两个正交邻域格子是否至少有一个可行。也就是在动作定义里把斜着走拆成先横再竖或先竖再横的组合约束只有两条正交路径中至少一条完全可行时才允许斜走。这样路径长度和安全性可以兼顾代价是环境函数的逻辑复杂一些。4.4 终点附近来回抖动大奖励导致的价值饱和现象路径回放时智能体已经走到了终点旁边却在两个格子之间反复来回移动就是不踏入终点那一格。原因终点奖励设置过大比如 100而 Q 表更新的公式里终点旁边的状态会把下一步到终点的 Q 值学得非常大。如果学习率 alpha 也偏大Q 值可能超过合理范围导致智能体在到达终点前的那一刻更倾向于反复累积离终点最近的那个状态的高 Q 值而不真正结束回合。另一种常见情况是地图中终点被障碍包围只剩一个入口智能体在入口附近转圈是因为它还没学会进入入口后下一步一定到终点。解决把终点奖励降到 50同时适当提高每步代价到 -1 以上。可以在环境函数里加一句提示state 到达终点后立即返回 donetrue不要给智能体在终点停留的机会。如果问题仍然存在检查地图上终点周围是否被障碍封死很多时候不是算法问题是地图本身无解。4.5 换一张地图就失效栅格粒度与状态空间爆炸现象20×20 的地图训练得很漂亮一换成 100×100 的真实场景地图训练时间暴涨而且路径质量明显变差。原因Q 表规模随栅格数平方级增长。100×100 地图有 10000 个状态、4 个动作Q 表有 40000 个参数每个状态-动作对都需要足够的访问次数才能学到可靠 Q 值。如果训练回合数没有同步增加大概率欠拟合如果同步增加训练时间又会让人怀疑人生。解决在 Q-Learning 框架内先把地图分辨率降下来做粗路径规划再在关键点之间用局部细粒度规划加密路径。也就是常见的全局粗规划 局部细规划两段式方案粗规划用 Q-Learning 找拓扑正确的路线细规划在相邻关键点之间用 A* 或 DWA 补路径。如果环境是动态变化的直接换 DQN 这类用神经网络逼近 Q 函数的方法它是 Q-Learning 的自然延伸适合高维状态空间相关方向可以搜dqn 路径规划。但作为仿真系统我建议先把小地图上的 Q-Learning 吃透再考虑深度版本否则调试难度会陡增。5. 从静态栅格到动态避障扩展方向与方案对比5.1 动态障碍场景让小车学会应对移动的障碍物很多人做路径规划仿真时最终要面对的是动态避障小车路径规划问题也就是地图里有多个在移动的障碍物。这里要说明一个前提经典 Q-Learning 学出来的是一个静态策略它假设障碍物位置不变Q 表是状态到动作的固定映射。障碍物动了原来的 Q 表就失效了。常见做法有两种。第一种是环境刷新加重规划每一步检测障碍物最新位置如果和上一时刻相比变化超过一定阈值就把当前 Q 表作为初始值重新训练。这种做法的优势是快因为 Q 表已经保留了大部分状态的价值估计只需要在障碍物附近区域做增量更新。我在做 AGV 预研时就是这么处理的重规划一般只需要 20 到 50 个回合就能适应新障碍物位置。第二种是把障碍物位置加入状态空间变成形如 (自己位置, 障碍物A位置, 障碍物B位置) 的元组。这从理论上是完备的但状态空间随障碍物数量指数爆炸20×20 地图加上 3 个障碍物状态数就是 400 的三次方量级Q 表根本存不下。所以除非障碍物数量极少我一般不推荐第二种做法。实际工程里滑动窗口重训练配合局部避障算法是性价比最高的路线。5.2 和 DQN、Sarsa 同台对比Q-Learning 的边界到底在哪做过 Q-Learning 之后你一定会好奇它和 Sarsa、DQN 这些近亲算法的差别。我整理了一个对比表方便在方案选型时直接参考。对比维度Q-LearningSarsaDQN策略性质离策略目标策略取 max在线策略更新用行为策略的动作离策略目标用目标网络计算Q 值载体查表零函数逼近误差查表同 Q-Learning神经网络有函数逼近误差路径风格激进偏好最短路径保守偏好安全路径大状态空间下近似最优适合场景小地图、离散状态动态障碍多、安全优先高维连续状态、图像输入调试难度低Q 表可逐格检查低和 Q-Learning 几乎一样高网络结构和超参多训练速度快几十毫秒级快同左慢需要 GPU 或大量 CPU 核Sarsa 的更新公式把目标里的 maxQ(s′,·) 换成 Q(s′,a′)其中 a′ 是用当前行为策略真实执行的动作。这个小小的改动让 Sarsa 学出来的策略更保守因为它在估计价值时把探索的随机性也算进去了。在动态障碍场景下Sarsa 规划的路径往往绕得更远但更安全而 Q-Learning 更激进偏好贴着最优路径走。对比两者时你会发现Q-Learning 在静态地图上胜出而在有随机移动障碍的地图上Sarsa 的成功率通常更高。DQN 则是把 Q 表换成了深度网络用经验回放和目标网络稳定训练适合状态空间大到查表完全不可行的场景代价是你需要处理一整套深度学习的工程问题。从仿真系统的角度看我建议先跑 Q-Learning再改 Sarsa 对比最后有余力再上 DQN这样对强化学习的理解是递进的。5.3 策略矩阵与动画回放两类最实用的交付物仿真做完总要给别人看尤其是答辩或项目汇报。我有两个推荐的交付物。第一个是策略矩阵热力图。把 Q 表里每个状态对应的最优动作用不同颜色画出来一个格子一格色比如向上是红、向右是蓝、向下是绿、向左是黄障碍物涂黑。这张图能直观展示智能体在每一格学到的意图比单纯画路径信息量大得多而且一眼能看出有没有个别格子学出反常动作。% 从 Q 表提取每个状态的最优动作并可视化 [~, policy] max(Q, [], 2); policy_map reshape(policy, size(map)); policy_map(map 1) NaN; % 障碍物位置不显示 figure; imagesc(policy_map); colormap(hsv); axis equal; axis tight; title(Q-Learning 策略矩阵热力图);第二个是训练和路径回放的动画。用 MATLAB 的 VideoWriter 逐帧写入训练过程生成一个 MP4 文件。动画里智能体探索、绕障、收敛的过程远比静态图有说服力。我做项目汇报时通常会录两个片段前 100 回合的乱撞状态和第 500 回合之后的有序路径对比强烈评审一眼就能看懂强化学习的学习过程。6. 跑通之后值得做的三件事验证泛化能力、调细视觉呈现、搭可复用框架第一件事把地图参数化做批量泛化测试。把地图生成、起点终点、障碍布局封装成函数然后跑 50 组随机障碍地图统计成功率、平均路径长度和相对曼哈顿距离的代价。这一步能帮你回答一个关键问题这套仿真到底是记住了这一张地图还是学会了绕障能力。做法很简单循环里每次生成随机地图、重新训练、记录结果最后汇总成功率。如果成功率低于 80%优先检查障碍率是否过高或者起点终点是否经常被障碍完全隔断。第二件事把 4 邻域换成 8 邻域同时加上斜向碰撞约束把路径长度往更优方向压一压。这正好也验证了 4.3 节提到的坑是否被真正解决。改进之后对比路径长度和碰撞次数你会发现 8 邻域在开阔地图上能缩短约 20% 的路径但前提是斜向检测逻辑写对。另外你可以把每步代价从 -1 调成 -0.3看看路径倾向如何变化这一步会让你真正理解奖励函数对策略的塑造力。第三件事把这套脚本整理成环境函数 训练函数 可视化函数的独立文件把参数集中放到一个配置结构体里。这样以后换场景、换算法、换地图都不需要动核心代码只改配置。我自己的习惯是保存一份训练好的 Q 表到 .mat 文件作为后悔药——遇到参数改坏了的情况随时可以从上一版好结果重新出发。这三件事做完这套基于 Q-Learning 的路径规划 MATLAB 仿真系统才真正从能跑变成会做方案。强化学习的乐趣在于当你亲眼看到智能体从撞墙乱撞到走出第一条完整路径时你会有一种这代码真的有生命的错觉。这个方向不算新但它是通往 DQN、PPO 这些更复杂算法的必经起点值得你花一两个晚上把它彻底吃透。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?