多A*算法路径规划(附MATLAB代码)

 A*算法介绍

A*算法是一种常用的寻路算法,被广泛应用于人工智能和游戏开发中。该算法通过评估每个节点的代价和启发式函数来找到最佳路径。在这篇博文中,我们将深入探讨A*算法的原理。

A*算法的核心思想是在搜索过程中综合考虑两个因素:已经花费的代价和还需要花费的代价。具体而言,A*算法通过计算每个节点的综合评估函数f(n)来确定下一个最优的节点进行探索。其中,f(n)的计算方式为:

f(n) = g(n) + h(n)

其中,g(n)表示从起始节点到当前节点的实际代价,h(n)表示从当前节点到目标节点的估计代价。通过计算f(n),A*算法可以选择具有最小f(n)值的节点作为下一个探索的节点。

A*算法的启发式函数h(n)在很大程度上决定了算法的搜索效率。一般来说,h(n)应该是一种乐观估计,即不会高估实际代价。如果h(n)准确地估计了到目标节点的代价,那么A*算法将以最短路径找到目标节点。

总的来说,A*算法是一种高效且可靠的寻路算法,适用于许多领域的问题解决。通过深入理解A*算法的原理,我们可以更好地应用该算法,提高问题解决的效率和准确性。希望这篇博文能帮助您更好地理解A*算法的工作原理和应用场景。感谢阅读!

代码原理

这段代码实现了A*搜索算法,用于在二维网格中找到从起点到终点的最短路径。以下是对代码每个部分的详细解释:

function [dis, road] = Axing_fun(startx, starty, endx, endy, Estart_x, Estart_y, Weight, High, C, show_flag)
  • 输入参数:

    • startx, starty:起点坐标。
    • endx, endy:终点坐标。
    • Estart_x, Estart_y:网格的起始坐标。
    • Weight, High:网格的宽度和高度。
    • C:成本矩阵,表示每个格子的代价。
    • show_flag:显示标志,用于控制是否绘制路径。
  • 输出参数:

    • dis:从起点到终点的总距离。
    • road:从起点到终点的路径。

 初始化

f = 0 + abs(startx - endx) + abs(starty - endy);  % 初始估计总代价(曼哈顿距离)
already_frontier = {f, startx, starty, 0, [startx, starty]};  % 已探索节点列表
  • f:起始节点的估计总代价,使用曼哈顿距离。
  • already_frontier:已探索节点列表,包含起始节点信息。

 寻找邻居点

frontier = cell(0, 5);
N = find_frontier(startx, starty, Estart_x, Estart_x + Weight, Estart_y, Estart_y + High, C, already_frontier);
  • frontier:待探索节点列表。
  • N:起始节点的邻居点,通过find_frontier函数找到。

处理邻居点

for i = 1:size(N, 2)
    g = norm([startx, starty] - [N(1, i), N(2, i)]);  % 计算当前代价
    f = g + abs(N(1, i) - endx) + abs(N(2, i) - endy);
    frontier{i, 1} = f;
    frontier{i, 2} = N(1, i);
    frontier{i, 3} = N(2, i);
    frontier{i, 4} = g;
    frontier{i, 5} = [[startx, starty]; [N(1, i), N(2, i)]];  % 记录路径
end
frontier = sortrows(frontier, 1);  % 按总代价排序

计算邻居点的代价g和估计总代价f,并将它们添加到frontier中。

主循环:探索节点

while isempty(frontier) == 0
    current = frontier(1, :);  % 取出当前节点
    already_frontier(end + 1, :) = frontier(1, :);  % 将当前节点移入已探索列表
    frontier(1, :) = [];  % 从待探索列表中移除当前节点

    mx = current{1, 2};  % 当前节点的坐标
    my = current{1, 3};
    if show_flag == 2
        plot(current{1, 2}, current{1, 3}, 'g*');  % 用绿色*号标记当前节点
    end

    % 查找当前节点的邻居
    N = find_frontier(mx, my, Estart_x, Estart_x + Weight, Estart_y, Estart_y + High, C, already_frontier);
    for i = 1:size(N, 2)
        b = find([frontier{:, 2}] == N(1, i));
        a = b([frontier{b, 3}] == N(2, i));
        g = current{1, 4} + norm([mx, my] - [N(1, i), N(2, i)]);
        f = g + abs(N(1, i) - endx) + abs(N(2, i) - endy);
        if a > 0  % 如果节点已经在frontier中,检查是否有更小的代价
            if frontier{a, 4} > g
                frontier{a, 5} = [current{1, 5}; [N(1, i), N(2, i)]];
                frontier{a, 4} = g;
                frontier{a, 1} = f;
            end
        else  % 如果节点不在frontier中,加入frontier
            temp{1, 1} = f;
            temp{1, 2} = N(1, i);
            temp{1, 3} = N(2, i);
            temp{1, 4} = g;
            temp{1, 5} = [current{1, 5}; [N(1, i), N(2, i)]];
            temp_frontier = [temp; temp_frontier];
            if show_flag == 2
                plot(N(1, i), N(2, i), 'bs');  % 用蓝色正方形标记待检测节点
            end
        end
    end

    % 如果终点在already_frontier中,跳出循环
    if already_frontier{end, 2} == endx && already_frontier{end, 3} == endy
        plot(already_frontier{end, 5}(:, 1), already_frontier{end, 5}(:, 2), 'b', 'LineWidth', 2);
        drawnow;
        break;
    end

    % 插入排序,将新节点按代价插入frontier中
    for i = 1:size(temp_frontier, 1)
        j = 0;
        while j <= size(frontier, 1) + 1
            j = j + 1;
            if j == size(frontier, 1) + 1
                frontier = [frontier; temp_frontier(i, :)];
                break;
            end
            if temp_frontier{i, 1} < frontier{j, 1}
                if j == 1
                    frontier = [temp_frontier(i, :); frontier];
                else
                    frontier = [frontier(1:j-1, :); temp_frontier(i, :); frontier(j:end, :)];
                end
                break;
            end
        end
    end
    temp_frontier = cell(0, 5);  % 清空临时列表

    if show_flag == 1 || show_flag == 2
        p = plot(already_frontier{end, 5}(:, 1), already_frontier{end, 5}(:, 2), 'b', 'LineWidth', 2);
        drawnow;
        delete(p);
    end
end
dis = already_frontier{end, 1};  % 返回总路程
road = already_frontier{end, 5};  % 返回最短路径
  • 步骤1:取出当前代价最小的节点,将其移到already_frontier
  • 步骤2:找到当前节点的邻居点,计算邻居点的代价。
  • 步骤3:如果邻居点已在frontier中,检查并更新代价;如果不在,加入frontier
  • 步骤4:检查是否找到终点,如果找到则绘制路径并跳出循环。
  • 步骤5:按代价将新节点插入frontier中。
  • 步骤6:更新显示路径。

 最后返回最短路径的总路程和路径坐标。

 代码运行效果图

 

 代码获取链接

哔哩哔哩工房 (bilibili.com)icon-default.png?t=N7T8https://gf.bilibili.com/item/detail/1106192108

  • 24
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的A*算法路径规划MATLAB示例代码: ```matlab function [path, cost] = astar(start, goal, map) % A*算法路径规划 % start: 起点坐标 [x,y] % goal: 终点坐标 [x,y] % map: 地图,1为可通过,0为障碍物 % path: 路径坐标 [x1,y1;x2,y2;...] % cost: 路径总代价 % 地图尺寸 [nrows, ncols] = size(map); % 节点代价 g = Inf(nrows, ncols); % 节点启发式代价 h = heuristic(start, goal); % 节点总代价 f = g + h; % 节点父节点坐标 parent = zeros(nrows, ncols, 2); % 起点代价 g(start(1), start(2)) = 0; % 待扩展节点列表 open_list = [start, f(start(1), start(2))]; % 已扩展节点列表 closed_list = []; % 扩展节点 while ~isempty(open_list) % 选择最小代价节点 [~, idx] = min(open_list(:, 3)); curr = open_list(idx, 1:2); % 到达终点 if isequal(curr, goal) path = reconstruct_path(parent, start, goal); cost = g(goal(1), goal(2)); return; end % 从待扩展列表中移除 open_list(idx, :) = []; % 添加到已扩展列表 closed_list = [closed_list; curr]; % 扩展邻居 [x, y] = meshgrid(curr(1)-1:curr(1)+1, curr(2)-1:curr(2)+1); neighbors = [x(:), y(:)]; neighbors = neighbors(neighbors(:,1) > 0 & neighbors(:,1) <= nrows & ... neighbors(:,2) > 0 & neighbors(:,2) <= ncols & ... ~ismember(neighbors, closed_list, 'rows') & ... map(sub2ind([nrows, ncols], neighbors(:,1), neighbors(:,2))) == 1, :); for i = 1:size(neighbors, 1) neighbor = neighbors(i, :); % 计算邻居代价 tentative_g = g(curr(1), curr(2)) + distance(curr, neighbor); % 更新邻居代价 if tentative_g < g(neighbor(1), neighbor(2)) parent(neighbor(1), neighbor(2), :) = curr; g(neighbor(1), neighbor(2)) = tentative_g; h(neighbor(1), neighbor(2)) = heuristic(neighbor, goal); f(neighbor(1), neighbor(2)) = g(neighbor(1), neighbor(2)) + h(neighbor(1), neighbor(2)); % 添加到待扩展列表 if ~any(ismember(open_list(:, 1:2), neighbor, 'rows')) open_list = [open_list; neighbor, f(neighbor(1), neighbor(2))]; end end end end % 找不到路径 path = []; cost = Inf; end function d = distance(a, b) % 计算两点距离 d = norm(a - b, 2); end function h = heuristic(a, b) % 启发式函数,使用曼哈顿距离 h = abs(a(1) - b(1)) + abs(a(2) - b(2)); end function path = reconstruct_path(parent, start, goal) % 重构路径 path = [goal]; while ~isequal(path(1,:), start) path = [parent(path(1,1), path(1,2), :); path]; end path = reshape(path, [], 2); end ``` 使用示例: ```matlab % 定义地图 map = [1 1 1 1 0 1 1 1 1 1; 1 0 1 1 1 1 0 1 1 1; 1 0 1 1 1 1 0 1 1 1; 1 0 1 1 1 1 0 1 1 1; 1 0 1 1 1 1 0 1 1 1; 1 0 1 1 1 1 0 1 1 1; 1 1 1 1 1 1 0 1 1 1; 1 1 1 1 1 1 0 1 1 1; 1 1 1 1 1 1 0 1 1 1; 1 1 1 1 1 1 0 1 1 1]; % 路径规划 start = [1, 1]; goal = [10, 10]; [path, cost] = astar(start, goal, map); % 显示结果 figure; imagesc(map); hold on; plot(start(2), start(1), 'go', 'MarkerSize', 10, 'LineWidth', 2); plot(goal(2), goal(1), 'ro', 'MarkerSize', 10, 'LineWidth', 2); plot(path(:,2), path(:,1), 'b', 'LineWidth', 2); axis equal; axis tight; grid on; title(sprintf('Path cost: %.2f', cost)); ``` 该示例代码中使用了曼哈顿距离作为启发式函数,可以根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值