基于Q-learning的栅格地图路径规划MATLAB仿真程序

MATLAB程序:Q-learning路径规划

%% ============================================================
% 基于Q-learning的路径规划MATLAB仿真程序
% 功能:在栅格地图中训练智能体从起点到终点找到最优路径
% ============================================================

clear; clc; close all;

%% 1. 创建栅格地图环境
fprintf('================== Q-learning路径规划 ==================\n');

% 地图参数设置
map_size = [10, 10];  % 10x10的栅格地图
start_pos = [1, 1];   % 起点 (行, 列)
goal_pos = [10, 10];  % 终点
obstacle_density = 0.2; % 障碍物密度 (20%)

% 生成随机障碍物地图
rng(42); % 固定随机种子,确保可重复性
map = ones(map_size);  % 1=自由空间,0=障碍物
num_obstacles = round(prod(map_size) * obstacle_density);
for i = 1:num_obstacles
    while true
        obstacle_pos = [randi(map_size(1)), randi(map_size(2))];
        % 确保障碍物不在起点和终点
        if ~isequal(obstacle_pos, start_pos) && ~isequal(obstacle_pos, goal_pos)
            map(obstacle_pos(1), obstacle_pos(2)) = 0;
            break;
        end
    end
end

% 显示地图
figure('Position', [100, 100, 800, 600]);
subplot(2, 3, [1, 2, 4, 5]);
imagesc(map);
colormap([0.3, 0.3, 0.3; 0.9, 0.9, 0.9]); % 障碍物深灰,自由区域浅灰
hold on;
plot(start_pos(2), start_pos(1), 'go', 'MarkerSize', 15, 'LineWidth', 2);
plot(goal_pos(2), goal_pos(1), 'r*', 'MarkerSize', 15, 'LineWidth', 2);
grid on;
set(gca, 'XTick', 1:map_size(2), 'YTick', 1:map_size(1));
xlabel('列坐标'); ylabel('行坐标');
title('栅格地图环境 (绿色:起点, 红色:终点)');
legend('起点', '终点', 'Location', 'northeastoutside');

%% 2. Q-learning参数设置
fprintf('设置Q-learning参数...\n');

% 学习参数
alpha = 0.1;        % 学习率 - 控制新信息的影响程度
gamma = 0.9;        % 折扣因子 - 控制未来奖励的重要性
epsilon = 0.3;      % 探索率 - 随机探索的概率
max_episodes = 500; % 最大训练回合数
max_steps = 100;    % 每个回合最大步数

% 动作空间: 上(1), 右(2), 下(3), 左(4)
actions = 4;
action_names = {'上', '右', '下', '左'};
action_vectors = [-1, 0; 0, 1; 1, 0; 0, -1];

% 初始化Q表 (状态数 x 动作数)
state_count = prod(map_size);
Q = zeros(state_count, actions);

% 奖励函数设置
R_goal = 100;       % 到达终点的奖励
R_obstacle = -100;  % 撞到障碍物的惩罚
R_step = -1;        % 每步的惩罚(鼓励最短路径)
R_boundary = -50;   % 撞到边界的惩罚

%% 3. 辅助函数:状态编码与解码
% 将二维位置编码为一维状态索引
state_to_index = @(pos) (pos(1)-1)*map_size(2) + pos(2);
% 将一维状态索引解码为二维位置
index_to_state = @(idx) [floor((idx-1)/map_size(2))+1, mod(idx-1, map_size(2))+1];

%% 4. Q-learning训练过程
fprintf('开始Q-learning训练...\n');

% 存储训练数据用于分析
rewards_history = zeros(max_episodes, 1);
steps_history = zeros(max_episodes, 1);
success_history = false(max_episodes, 1);

for episode = 1:max_episodes
    % 初始化状态(起点)
    current_state = start_pos;
    current_state_idx = state_to_index(current_state);
    episode_reward = 0;
    done = false;
    
    % 动态调整探索率(随时间衰减)
    epsilon_decayed = epsilon * (1 - episode/max_episodes);
    
    for step = 1:max_steps
        % ε-贪婪策略选择动作
        if rand() < epsilon_decayed
            % 探索:随机选择动作
            action = randi(actions);
        else
            % 利用:选择Q值最大的动作
            [~, action] = max(Q(current_state_idx, :));
        end
        
        % 执行动作,计算新状态
        next_state = current_state + action_vectors(action, :);
        
        % 检查边界
        if next_state(1) < 1 || next_state(1) > map_size(1) || ...
           next_state(2) < 1 || next_state(2) > map_size(2)
            reward = R_boundary;
            next_state = current_state; % 保持原地
            done = true;
        % 检查障碍物
        elseif map(next_state(1), next_state(2)) == 0
            reward = R_obstacle;
            done = true;
        % 检查是否到达终点
        elseif isequal(next_state, goal_pos)
            reward = R_goal;
            done = true;
        else
            reward = R_step;
        end
        
        % 计算下一个状态索引
        next_state_idx = state_to_index(next_state);
        
        % Q-learning更新公式
        Q_current = Q(current_state_idx, action);
        Q_max_next = max(Q(next_state_idx, :));
        Q(current_state_idx, action) = Q_current + alpha * (reward + gamma * Q_max_next - Q_current);
        
        % 更新累计奖励和状态
        episode_reward = episode_reward + reward;
        current_state = next_state;
        current_state_idx = next_state_idx;
        
        % 检查回合是否结束
        if done
            steps_history(episode) = step;
            success_history(episode) = isequal(current_state, goal_pos);
            break;
        end
        
        if step == max_steps
            steps_history(episode) = max_steps;
            success_history(episode) = false;
        end
    end
    
    rewards_history(episode) = episode_reward;
    
    % 每50回合显示进度
    if mod(episode, 50) == 0
        success_rate = mean(success_history(1:episode)) * 100;
        fprintf('  回合 %d/%d | 平均奖励: %.2f | 成功率: %.1f%%\n', ...
                episode, max_episodes, mean(rewards_history(1:episode)), success_rate);
    end
end

%% 5. 训练结果可视化
fprintf('训练完成!可视化结果...\n');

% 绘制训练曲线
subplot(2, 3, 3);
plot(1:max_episodes, rewards_history, 'b-', 'LineWidth', 1);
xlabel('训练回合');
ylabel('回合奖励');
title('奖励收敛曲线');
grid on;

subplot(2, 3, 6);
success_rate_moving = movmean(success_history, 50) * 100;
plot(1:max_episodes, success_rate_moving, 'r-', 'LineWidth', 2);
xlabel('训练回合');
ylabel('成功率 (%)');
title('学习成功率(50回合移动平均)');
ylim([0, 100]);
grid on;

%% 6. 使用训练好的Q表规划最优路径
fprintf('使用训练好的策略规划路径...\n');

% 从起点开始
path = [start_pos];
current_state = start_pos;
current_state_idx = state_to_index(current_state);
path_found = true;
max_path_length = 50; % 最大路径长度

for i = 1:max_path_length
    % 使用贪婪策略选择动作
    [~, action] = max(Q(current_state_idx, :));
    
    % 执行动作
    next_state = current_state + action_vectors(action, :);
    
    % 检查有效性
    if next_state(1) < 1 || next_state(1) > map_size(1) || ...
       next_state(2) < 1 || next_state(2) > map_size(2) || ...
       map(next_state(1), next_state(2)) == 0
        fprintf('警告:路径规划遇到障碍物或边界!\n');
        path_found = false;
        break;
    end
    
    % 添加到路径
    path = [path; next_state];
    
    % 检查是否到达终点
    if isequal(next_state, goal_pos)
        fprintf('成功找到路径!路径长度:%d步\n', size(path, 1)-1);
        break;
    end
    
    % 更新状态
    current_state = next_state;
    current_state_idx = state_to_index(current_state);
    
    if i == max_path_length
        fprintf('警告:达到最大路径长度,可能未找到终点!\n');
        path_found = false;
    end
end

%% 7. 可视化最终路径
subplot(2, 3, [1, 2, 4, 5]);
hold on;

if path_found
    % 绘制路径
    path_x = path(:, 2);
    path_y = path(:, 1);
    plot(path_x, path_y, 'b-', 'LineWidth', 2);
    plot(path_x, path_y, 'bo', 'MarkerSize', 8, 'MarkerFaceColor', 'b');
    
    % 显示路径信息
    text(1, map_size(1)+0.5, sprintf('路径长度: %d步', size(path, 1)-1), ...
         'FontSize', 10, 'FontWeight', 'bold');
else
    text(map_size(2)/2, map_size(1)/2, '路径未找到!', ...
         'HorizontalAlignment', 'center', 'FontSize', 14, 'FontWeight', 'bold', 'Color', 'r');
end

% 添加图例
legend_items = {'起点', '终点', '路径'};
h_legend = legend(legend_items, 'Location', 'northeastoutside');
set(h_legend, 'FontSize', 10);

%% 8. 可视化策略(箭头图)
figure('Position', [950, 100, 800, 600]);
subplot(1, 2, 1);

% 创建策略矩阵
policy_map = zeros(map_size);
for r = 1:map_size(1)
    for c = 1:map_size(2)
        if map(r, c) == 1 && ~isequal([r, c], goal_pos)
            state_idx = state_to_index([r, c]);
            [~, best_action] = max(Q(state_idx, :));
            policy_map(r, c) = best_action;
        end
    end
end

% 绘制策略热图
imagesc(policy_map);
colormap(jet(4));
colorbar('Ticks', 1:4, 'TickLabels', action_names);
hold on;

% 标记起点和终点
plot(start_pos(2), start_pos(1), 'go', 'MarkerSize', 15, 'LineWidth', 2);
plot(goal_pos(2), goal_pos(1), 'r*', 'MarkerSize', 15, 'LineWidth', 2);

% 绘制障碍物
[obs_r, obs_c] = find(map == 0);
plot(obs_c, obs_r, 'ks', 'MarkerSize', 10, 'MarkerFaceColor', 'k');

title('最优策略可视化(颜色表示动作方向)');
xlabel('列坐标'); ylabel('行坐标');
set(gca, 'XTick', 1:map_size(2), 'YTick', 1:map_size(1));
grid on;

%% 9. 绘制Q值热图
subplot(1, 2, 2);

% 计算每个状态的最高Q值
max_Q_map = zeros(map_size);
for r = 1:map_size(1)
    for c = 1:map_size(2)
        if map(r, c) == 1
            state_idx = state_to_index([r, c]);
            max_Q_map(r, c) = max(Q(state_idx, :));
        end
    end
end

% 将障碍物的Q值设为NaN(显示为白色)
max_Q_map(map == 0) = NaN;

imagesc(max_Q_map);
colormap(jet);
colorbar;
hold on;

% 标记起点和终点
plot(start_pos(2), start_pos(1), 'go', 'MarkerSize', 15, 'LineWidth', 2);
plot(goal_pos(2), goal_pos(1), 'r*', 'MarkerSize', 15, 'LineWidth', 2);

title('状态最大Q值热图');
xlabel('列坐标'); ylabel('行坐标');
set(gca, 'XTick', 1:map_size(2), 'YTick', 1:map_size(1));
grid on;

%% 10. 性能统计与输出
fprintf('\n=============== 训练结果统计 ===============\n');
final_success_rate = mean(success_history) * 100;
fprintf('最终成功率: %.2f%%\n', final_success_rate);
fprintf('平均回合奖励: %.2f\n', mean(rewards_history));
fprintf('平均步数: %.2f\n', mean(steps_history(success_history)));
fprintf('Q表大小: %d 状态 × %d 动作\n', size(Q, 1), size(Q, 2));

% 保存训练结果
save('q_learning_path_planning_results.mat', ...
     'Q', 'map', 'start_pos', 'goal_pos', ...
     'rewards_history', 'success_history', 'steps_history', ...
     'alpha', 'gamma', 'epsilon', 'max_episodes');

fprintf('\n结果已保存到 q_learning_path_planning_results.mat\n');

参考代码 基于增强学习Q-learning方法的路径规划matlab仿真程序 www.3dddown.com/cna/45533.html

关键模块详解

1. 环境建模

  • 使用栅格地图表示环境(1=自由,0=障碍)
  • 状态编码:将二维位置 (row, col) 编码为一维索引
  • 动作空间:4个方向(上、下、左、右)

2. Q-learning核心算法

  • Q值更新公式

    Q(s,a) = Q(s,a) + α * [r + γ * max(Q(s',a')) - Q(s,a)]
    

    其中:

    • α:学习率(控制新信息的影响)
    • γ:折扣因子(权衡即时/未来奖励)
    • ε:探索率(平衡探索与利用)
  • ε-贪婪策略:以ε概率随机探索,否则选择当前最优动作

3. 奖励函数设计

% 奖励函数是关键,它引导智能体学习:
% 到达终点: +100     (鼓励完成任务)
% 撞障碍物: -100     (避免碰撞)
% 每走一步: -1       (鼓励最短路径)
% 出边界: -50        (保持在边界内)

参数调优

参数 典型范围 影响 调整建议
学习率 α 0.01-0.5 学习速度 从0.1开始,收敛慢则增大,震荡则减小
折扣因子 γ 0.8-0.99 未来奖励重要性 长期任务用0.9-0.99,短期用0.8
探索率 ε 0.1-0.5 探索程度 训练初期0.3,后期衰减到0.1
训练回合数 500-5000 训练充分性 简单地图500,复杂地图2000+

扩展与改进方向

1. 添加动态障碍物

% 在训练过程中随机移动障碍物
if mod(episode, 100) == 0
    % 随机选择一个障碍物移动到新位置
    map = move_obstacle_randomly(map, start_pos, goal_pos);
end

2. 使用深度Q网络(DQN)处理大状态空间

% 当地图很大时,可以用神经网络近似Q函数
% 替换Q表为神经网络
net = create_dqn_network(map_size);

3. 多目标路径规划

% 修改奖励函数,使智能体依次访问多个目标点
goal_sequence = {[5,5], [10,10], [3,8]};
current_goal_index = 1;

4. 实时路径重规划

% 检测环境变化时重新规划
function new_path = replan_path(Q, current_pos, goal_pos, new_map)
    % 使用当前Q表和新地图重新规划
end

使用建议与调试技巧

  1. 训练失败常见原因

    • 学习率太高:Q值震荡不收敛 → 减小α
    • 探索率太低:陷入局部最优 → 增大ε
    • 奖励设计不合理:调整奖励值比例
    • 训练回合不足:增加max_episodes
  2. 性能优化

    % 使用稀疏矩阵存储Q表(大型地图)
    Q = sparse(state_count, actions);
    
    % 并行训练多个智能体
    parfor episode = 1:max_episodes
        % 并行训练代码
    end
    
  3. 可视化调试

    • 观察奖励曲线是否上升
    • 检查成功率是否提高
    • 可视化中间路径了解学习过程

这个程序提供了完整的Q-learning路径规划实现。你可以通过修改地图大小、障碍物分布、奖励函数等来适应不同场景。

posted @ 2026-01-12 11:59  yes_go  阅读(7)  评论(0)    收藏  举报