基于matlab仿真A*算法

资源文件换一下 剩下的看注释即可 很详细的哦


% 定义地图大小   十行十列
ROWS = 10;
COLS = 10;

% % 初始化地图
% grid = zeros(ROWS, COLS);
% % 设置固定位置的障碍物
% obstacle_positions = [2, 3; 4, 5; 6, 7;]; % 障碍物位置坐标
% % 将障碍物位置设置为1
% for i = 1:size(obstacle_positions, 1)
%     grid(obstacle_positions(i, 1), obstacle_positions(i, 2)) = 1;
% end

 % 初始化地图和障碍物
 grid = zeros(ROWS, COLS);
 for i = 1:ROWS
     for j = 1:COLS
         if rand < 0.2 % 随机生成20%的障碍物
             grid(i, j) = 1;% 将单元格设置为1 表示有障碍物
         end
     end
 end

% 定义起点和终点
start = [1, 1];
end_point = [ROWS, COLS];
end_point_point = [1,10];
% 定义多个目标点
% A*算法是逐个处理目标点的,所以路径规划是按顺序进行的,而不是并行进行的。因此,两个目标点的路径规划是依次执行的,一个目标点的路径计算完成后才会开始计算另一个目标点的路径。
targets = [end_point;end_point_point];

% 实现A*算法的核心部分 在计算路径时,考虑多个目标点


% 迭代次数是指在算法中重复执行某个过程的次数。在很多算法中,特别是优化算法或者搜索算法中,通常需要通过多次迭代来逐步优化结果或者搜索空间,直至满足某个条件或者达到预设的最大迭代次数为止。
% 在路径规划算法中,比如使用启发式搜索算法或者遗传算法来寻找最优路径时,每次迭代可能会尝试探索新的路径或者调整当前路径,然后根据某种评价标准(比如路径长度或者成本)来评估路径的优劣,并更新当前的路径状态。
% 迭代次数的增加通常会使得算法有更多机会发现更优的解决方案,但也可能增加算法的计算复杂度

% 定义最大迭代次数
max_iterations = 1000;% 算法在进行路径规划最多的迭代次数

% 寻找路径
% 创建一个1行、目标点数量列的空cell数组
% 通过 size(targets, 1) 获取了 targets 矩阵的行数,即目标的数量
% 如果 targets 表示的是第十行第十列的位置,则 size(targets, 1) 将返回1,因为只有一个元素(一个位置)。因此,path 将是一个包含一个元素的单元格数组,用于存储与该目标相关的路径信息
% cell是一种特殊的数据类型,表示单元格数组。它可以用来存储不同类型和大小的数据,类似于其他编程语言中的二维数组或列表。您可以使用cell函数来创建单元格数组,也可以直接使用大括号 {} 来访问和操作单元格数组中的元素。
path = cell(1, size(targets, 1)); % 存储路径
for i = 1:size(targets, 1)% for循环遍历每一行
    iteration = 0;% 记录迭代次数 初始化操作
    % 计算起点到目标点的路径
    target_path = []; % 初始化空数组 存储单个目标点的路径
    
    % 在路径未找到且迭代次数未达到最大值时,循环执行特定操作
    % isempty() 是 MATLAB 中的一个函数,用于判断某个数组或者矩阵是否为空。
    while isempty(target_path) && iteration < max_iterations
        % A*算法核心部分
        % 定义了一个匿名函数heuristic,用于计算启发式估价函数的值
        % 启发式估价函数在A*算法中用于估计当前节点到目标节点的代价,以辅助路径搜索过程
        % 在 A* 算法的上下文中,这两个元素通常表示二维平面上的坐标。例如,如果 a 和 b 是二维平面上的两个点,则 a(1) 和 b(1) 表示这两个点的 x 坐标,a(2) 和 b(2) 表示这两个点的 y 坐标。
        % 曼哈顿距离
        heuristic = @(a, b) abs(a(1)-b(1)) + abs(a(2)-b(2));
        % 定义了一个二维数组directions,其中包含了四个方向的偏移量。每个方向偏移量是一个包含两个元素的行向量,表示在二维平面上的移动方向
        directions = [[-1, 0]; [1, 0]; [0, -1]; [0, 1]];
        % 初始化openList结构体数组,包含起点的位置、g值、h值、f值和父节点信息 :提取整行的元素
        % 这行代码初始化了一个结构体数组 `openList`,用于存储 A* 算法中待处理的节点信息。下面是对这行代码中每个字段的解释:
        % 'pos', start`:表示节点的位置,即起始位置。这个位置通常是一个二维坐标,在这段代码中使用了 `start` 变量,它可能是起始点的坐标。
        % 'g', 0`:表示节点的实际代价(也称为路径成本),在这里初始化为0。`g` 代表从起点到当前节点的实际代价。
        % 'h', heuristic(start, targets(i, :))`:表示节点到目标的估计代价,即启发式函数的值。在 A* 算法中,`h` 代表从当前节点到目标的预计代价。这里使用了启发式函数 `heuristic` 来计算当前节点到目标的曼哈顿距离。
        % 'f', 0`:表示节点的综合代价。在 A* 算法中,`f` 是一个综合考虑实际代价和估计代价的值,通常定义为 `f = g + h`。在这里,由于刚初始化节点,实际代价和估计代价都是0,所以 `f` 也初始化为0。
        %'parent', []`:表示当前节点的父节点。在 A* 算法中,每个节点都有一个指向其父节点的指针,以便在找到最佳路径时能够回溯到起点。在这里,因为是初始化节点,所以父节点为空。
        openList = struct('pos', start, 'g', 0, 'h', heuristic(start, targets(i, :)), 'f', 0, 'parent', []);
        % closedList通常用于存储已经考虑过的节点,以避免对它们进行重复处理
        closedList = [];
        
        % while ~isempty(openList):这是一个 while 循环,它会持续执行直到 openList 变量为空。~isempty(openList) 表示当 openList 不为空时循环会继续执行。
        while ~isempty(openList)% 进入while循环,直到openList为空
            % ~ 表示要忽略的值。在 MATLAB 中,波浪线 ~ 用于指示忽略或丢弃某个值。idx 表示要获取的值。在这个例子中,idx 是变量名,用于存储从函数返回的某个值。
            [~, idx] = min([openList.f]);% 找到openList中具有最小f值的节点,并返回该节点在openList中的索引
            current = openList(idx);% 获取具有最小f值的节点
            
            % A*算法中的路径搜索和路径重建
            % isequal(current.pos, targets(i, :)):这一行代码用于检查当前节点的位置是否与目标位置相匹配。current.pos 可能是当前节点的位置,而 targets(i, :) 则表示第 i 个目标的位置。isequal 函数用于比较两个变量是否相等。
            % target_path = reconstructPath(current);:如果当前节点的位置与某个目标位置相匹配,则调用 reconstructPath 函数来重建路径。reconstructPath 函数通常是一个自定义函数,用于从当前节点向起始节点回溯,并重建完整的路径。
            % break;:一旦找到目标并重建了路径,就会跳出循环。这个循环可能是 A* 算法的主循环,也可能是一个搜索节点的循环,具体取决于整个算法的实现。

            % 搜索路径:在路径搜索问题中,我们需要找到从起点到目标点的有效路径。这通常需要使用搜索算法(比如 A* 算法)来遍历图或者网络中的节点,并找到一条满足特定条件(比如最短路径或者最低成本路径)的路径。
            % 搜索路径的目的是找到一条从起点到目标点的有效通路。重建路径:一旦找到了有效路径,我们需要将其呈现出来或者用于后续的任务。重建路径是指根据搜索算法找到的节点信息,将这些节点连接起来,形成完整的路径。这个过程通常需要从目标节点开始,沿着每个节点的父节点指针向上回溯,直到回溯到起始节点,从而找到一条完整的路径
            % 在 A* 算法中,重构路径通常是在找到目标节点后执行的,以便确定最佳路径,并将其用于后续的任务,比如路径规划、导航或者图形化显示
            if isequal(current.pos, targets(i, :))
                target_path = reconstructPath(current);
                break;
            end
            
            % openList(idx) = [];:这行代码用于从开放列表中移除已经处理过的节点。在A*算法中,开放列表通常用于存储待处理的节点,当算法对某个节点进行处理后,需要将其从开放列表中移除,以确保下次搜索时不会再次处理已经处理过的节点。通过将 idx 索引处的节点移除,可以实现这一操作。
            % closedList = [closedList current];:这行代码则是将当前处理的节点添加到关闭列表中。关闭列表通常用于存储已经处理过的节点,以避免对它们进行重复处理。在A*算法中,当一个节点被处理后,通常会将其添加到关闭列表中,以确保不会再次处理该节点。这样可以避免进入无限循环,也可以优化算法的性能
            % 从openList中移除具有最小f值的节点
            openList(idx) = [];
            % 确保下次搜索时不会再次处理已经处理过的节点
            closedList = [closedList current];
            
            % 通过for循环遍历四个方向(上、下、左、右)
            for dir = 1:size(directions, 1)
                
                % 当前节点位置加上对应方向的偏移
                neighbor = current.pos + directions(dir, :);
                % if neighbor(1) < 1 || neighbor(1) > size(grid, 1) || neighbor(2) < 1 || neighbor(2) > size(grid, 2)
                % neighbor(1) 是邻居节点的行索引,neighbor(2) 是邻居节点的列索引。
                % size(grid, 1) 返回地图 grid 的行数,size(grid, 2) 返回地图 grid 的列数。
                % 这个条件语句检查邻居节点是否超出了地图的边界范围:
                % neighbor(1) < 1 检查邻居节点的行索引是否小于1,即是否在地图的上方边界之外。
                % neighbor(1) > size(grid, 1) 检查邻居节点的行索引是否大于地图的行数,即是否在地图的下方边界之外。
                % neighbor(2) < 1 检查邻居节点的列索引是否小于1,即是否在地图的左侧边界之外。  
                % neighbor(2) > size(grid, 2) 检查邻居节点的列索引是否大于地图的列数,即是否在地图的右侧边界之外。
                % 如果邻居节点的行或列索引超出了地图边界范围的任何一侧,条件成立,说明邻居节点不在地图范围内,因此继续下一次循环处理下一个方向的邻居节点。
                % if grid(neighbor(1), neighbor(2)) == 1
                % 这行代码检查邻居节点是否为障碍物。
                % grid(neighbor(1), neighbor(2)) 获取地图中邻居节点的值,如果邻居节点在地图中的值为1,则表示它是一个障碍物。
                % 如果邻居节点是障碍物,条件成立,说明无法通过这个邻居节点进行移动,因此继续下一次循环处理下一个方向的邻居节点。
                % 检查邻居节点是否在地图范围内,如果邻居节点超出地图边界,则继续下一次循环
                if neighbor(1) < 1 || neighbor(1) > size(grid, 1) || neighbor(2) < 1 || neighbor(2) > size(grid, 2)
                    continue;
                end
                % 检查邻居节点是否为障碍物(grid中的值为1),如果是障碍物,则继续下一次循环
                if grid(neighbor(1), neighbor(2)) == 1
                    continue;
                end
                
                % 计算邻居节点的g值,即当前节点的g值加1,表示从当前节点到邻居节点的距离 
                % 计算邻居节点的h值,即启发式函数计算当前节点到目标点的估计距离。
                % 计算邻居节点的f值,即g值和h值的和
                % g = current.g + 1;
                % current.g 是当前节点到起始节点的实际代价(也称为路径长度)。
                % 1 表示从当前节点到其邻居节点的距离。在这里假设邻居节点之间的距离都是1,这是因为在许多路径规划问题中,邻居节点通常在相邻的单元格中,每次移动的成本是固定的。
                % g 表示从起始节点到当前邻居节点的实际代价,即路径长度。
                % h = heuristic(neighbor, targets(i, :));
                % heuristic 是一个启发式函数,用于估计从当前邻居节点到目标节点的代价。
                % neighbor 是当前邻居节点的位置。
                % targets(i, :) 是第 i 个目标节点的位置。
                % h 表示从当前邻居节点到目标节点的启发式估计代价。
                % f = g + h;
                % f 表示从起始节点经过当前邻居节点到目标节点的综合代价,是实际代价和启发式估计代价的和。
                % 综合代价 f 的计算是A*算法中的关键部分,它同时考虑了当前路径的实际代价和对目标的估计代价,帮助算法选择最有希望的节点进行扩展。
                g = current.g + 1;
                h = heuristic(neighbor, targets(i, :));
                f = g + h;
                % arrayfun(@(x) isequal(x.pos, neighbor), closedList) 的作用是检查 closedList 数组中的每个元素 x 是否与 neighbor 相等。如果 x.pos 与 neighbor 相等,则返回逻辑值 true,否则返回 false。这样就可以确定当前的邻居节点是否已经在 closedList 中了
                if any(arrayfun(@(x) isequal(x.pos, neighbor), closedList))
                    continue;
                end
                
                idx = find(arrayfun(@(x) isequal(x.pos, neighbor), openList));
                
                if ~isempty(idx)
                    if g < openList(idx).g
                        openList(idx).g = g;
                        openList(idx).f = f;
                        openList(idx).parent = current;
                    end
                else
                    openList = [openList struct('pos', neighbor, 'g', g, 'h', h, 'f', f, 'parent', current)];
                end
            end
        end
        
        iteration = iteration + 1;
    end
    
    path{i} = target_path;% 将找到的目标点i的路径target_path存储在cell数组path的第i个位置,即将当前目标点的路径存储起来
end


% % 标记起点和终点
% plot(start(2), start(1), 'ro', 'MarkerSize', 10, 'MarkerFaceColor', 'r');
% plot(end_point(2), end_point(1), 'go', 'MarkerSize', 10, 'MarkerFaceColor', 'g');

% % 显示障碍物
% [row, col] = find(grid == 1);
% plot(col, row, 'bs', 'MarkerSize', 10);

% 载入路障图片
obstacle_img = imread('3b47fb003d5d2eb42af403c7d62a254f.png');
% 可视化地图和路径
figure;
image(grid*255); % 将地图转换为灰度图像
colormap(ones(256,3)); % 使用全白色作为背景色
hold on;

% 显示障碍物图片
[row, col] = find(grid == 1);
for i = 1:length(row)
    x = col(i);
    y = row(i);
    image([x-0.5 x+0.5], [y-0.5 y+0.5], obstacle_img);
end
% 标记起点和终点
text(start(2), start(1), '起点', 'Color', 'red', 'FontSize', 12, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
text(end_point(2), end_point(1), '终点', 'Color', 'green', 'FontSize', 12, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');
text(end_point_point(2), end_point_point(1), '终点', 'Color', 'green', 'FontSize', 12, 'HorizontalAlignment', 'center', 'VerticalAlignment', 'middle');

title('多目标路径规划结果');
% 显示路径
for i = 1:size(path, 2)
    for j = 1:size(path{i}, 1)
        plot(path{i}(j, 2), path{i}(j, 1), 'b.', 'MarkerSize', 20);
        pause(0.25); % 自动寻路的延时
    end
end


axis equal;
axis off;
hold off;

% A*算法实现  用于生成最终的路径结果
% 定义reconstructPath函数
function path = reconstructPath(node)
    path = [];
    while ~isempty(node)
        path = [node.pos; path];
        node = node.parent;
    end
end





% pos:表示节点的位置。这里使用变量start作为起始节点的位置。它是一个表示坐标的向量。
% g:表示从起始节点到当前节点的实际代价,即已经经过的路径长度。在这里,初始节点的实际代价被设置为0,因为还没有经过任何路径。
% h:表示启发式函数对当前节点到目标节点的估计代价。启发式函数在代码中通过调用heuristic函数来计算,通过传入start作为当前节点的位置,以及targets(i, :)作为目标节点的位置来计算估计代价。
% f:表示综合考虑实际代价和估计代价的综合代价值。在初始情况下,将初始节点的综合代价设置为0。后续会根据具体算法来更新这个值,通常是在拓展节点时根据实际代价和估计代价计算得出。
% parent:表示当前节点的父节点。初始情况下,父节点为空,因为这是起始节点。后续在路径搜索算法中,可以根据搜索过程来更新这个字段,用于还原最终路径

在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值