A*路径搜索超详细代码


前言

这里只记录代码以及代码详解,不讲解理论


提示:以下是本篇文章正文内容,下面案例可供参考

一、主函数main.m

main.m文件

close all; clear all; clc;

% 初始化起点,目标点,地图大小
xStart = 1.0;
yStart = 1.0;
xTarget = 9.0;
yTarget = 9.0;
MAX_X = 10;
MAX_Y = 10;
% 添加障碍物
map = obstacle_map(xStart, yStart, xTarget, yTarget, MAX_X, MAX_Y);

% 测试障碍物是否加载成功
% visualize_map(map, 0);
% A*寻找路径
path = A_star_search(map, MAX_X,MAX_Y);

% 显示路径
visualize_map(map, path);

二、障碍物obstacle_map.m文件

obstacle_map.m文件

 function map = obstacle_map(xStart,yStart,xTarget,yTarget,MAX_X,MAX_Y)
% map = 起始点 +障碍物+终点
    rand_map = rand(MAX_X,MAX_Y); % 随机生成障碍物矩阵
    map(1,1) = xStart;
    map(1,2) = yStart;
    k=2;
    obstacle_ratio = 0.25; %  障碍物矩阵 < 0.25才表示真正的障碍物
    for i = 1:1:MAX_X
        for j = 1:1:MAX_Y
            if( (rand_map(i,j) < obstacle_ratio) && (i~= xStart || j~=yStart) && (i~= xTarget || j~=yTarget))
                map(k,1) = i;
                map(k,2) = j;
                k=k+1;
            end    
        end
    end
    map(k,1) = xTarget;
    map(k,2) = yTarget;
end

三、可视化visualize_map.m文件

visualize_map.m文件

function visualize_map(map,path)
% 可视化,将障碍物,起始点,路径,目标点可视化
% -0.5表示将点偏至中间

    % 障碍物
    for obs_cnt = 2: size(map, 1) - 1
        scatter(map(obs_cnt, 1)-0.5,map(obs_cnt, 2)-0.5,250,155,'filled');
        hold on;
        grid on;
        axis equal;        
        axis ([0 10 0 10 ]);
        hold on;
    end
    % 起始点
    scatter(map(1, 1)-0.5, map(1, 2)-0.5,'b','*');
    hold on;
    % 目标点
	scatter(map(size(map, 1), 1)-0.5, map(size(map, 1), 2)-0.5, 'r','*');
    hold on;
    % 路径
    for path_cnt = 2:size(path,1)-1
        scatter(path(path_cnt,1) - 0.5,path(path_cnt,2) - 0.5,'b');
        hold on;
    end

end

四、A* 路径搜索A_star_search.m文件

A_star_search.m文件

function path = A_star_search(map,MAX_X,MAX_Y)
%%  

% map : 障碍物和起始点,终点信息
% MAX_X MAX_Y: 地图大小
% return : 路径

%%  初始化地图矩阵

    size_map = size(map,1);
    
    %Obstacle=-1, Target = 0, Start=1
    % 维护MAP地图
    MAP=3*(ones(MAX_X,MAX_Y));
    
    % 初始化目标点 0
    xval=floor(map(size_map, 1)) ;
    yval=floor(map(size_map, 2)) ;
    xTarget=xval;
    yTarget=yval;
    MAP(xval,yval)=0;
    
    %初始化障碍物 -1
    for i = 2: size_map-1
        xval=floor(map(i, 1)) ;
        yval=floor(map(i, 2)) ;
        MAP(xval,yval)=-1;
    end 
    
    % 初始化起始点
    xval=floor(map(1, 1)) ;
    yval=floor(map(1, 2)) ;
    xStart=xval;
    yStart=yval;
    MAP(xval,yval)=1;

    %% 
    % 维护open list
    OPEN=[];

    % 维护close list
    CLOSED=[];

    % 将障碍物添加到close list
    k=1;% 
    for i=1:MAX_X
        for j=1:MAX_Y
            if(MAP(i,j) == -1)
                CLOSED(k,1)=i;
                CLOSED(k,2)=j;
                k=k+1;
            end
        end
    end
    CLOSED_COUNT=size(CLOSED,1);
    
    % 将起始点加入open list 
    xNode=xStart;
    yNode=yStart;
    OPEN_COUNT=1;
    goal_distance=distance(xNode,yNode,xTarget,yTarget); % fn = gn + fn, 此时gn = 0
    path_cost=0; % gn
    OPEN(OPEN_COUNT,:)=insert_open(xNode,yNode,goal_distance,path_cost,goal_distance);

    flag = 0; % 找到路径标志
    find_path = 1; % 路径回溯索引
%% 寻找路径
    while(1) % 无限循环
        if flag == 1 || OPEN_COUNT == 0
            break; % 直到找到目标点或在 open list 为空(找不到有效路径), 退出循环
        end
        
        open_min_fn_idex= min_fn(OPEN, OPEN_COUNT); % 寻找open list,到目标点最小值fn的索引
        % 取出来的节点是否目标点
        if  (OPEN(open_min_fn_idex,1) == xTarget && OPEN(open_min_fn_idex,2) == yTarget)
            flag = 1; % 找到路径
        end
        node_x =  OPEN(open_min_fn_idex,1);
        node_y =  OPEN(open_min_fn_idex,2);

        gn = OPEN(open_min_fn_idex,4);        
        
        % 待扩展open节点  return x, y ,hn, gn, fn, parent_x, parent_y
        exp_open_array_new = expand_open_array(node_x, node_y,gn, xTarget,yTarget, CLOSED, MAX_X, MAX_Y);

        
        % 待扩展的点加入open list
        for i = 1 : size(exp_open_array_new, 1)
            in_open = 0; % 是否已经访问过标志
            % 是否已经在open节点里面
            for j = 1 : size(OPEN, 1)
                if exp_open_array_new(i, 1) == OPEN(j, 1) && exp_open_array_new(i, 2) == OPEN(j, 2)
                    in_open =1;
                    % 已存在open list,那么是否需要更新
                    if exp_open_array_new(i, 5) < OPEN(j, 5)
                         OPEN(j, :) = exp_open_array_new(i, :) ; % 更新
                    end
                    break;
                end
            end
            % 如何还没在open list, 添加新节点
            if in_open == 0
                OPEN_COUNT = OPEN_COUNT + 1;
                OPEN(OPEN_COUNT, :) = exp_open_array_new(i, :);
            end
        end
        
        % 将访问的节点和其父节点储存起来 [now_x, new_y, parent_x, parent_y]
        traj(find_path, :) = [OPEN(open_min_fn_idex, 1:2)  OPEN(open_min_fn_idex, 6:7)]; 
        find_path = find_path + 1; % 索引值增加1
        
        OPEN(open_min_fn_idex, :) = [ ]; % 移除已访问的节点
        OPEN_COUNT = OPEN_COUNT -1;  
        % 将其添加到close list
        CLOSED_COUNT = CLOSED_COUNT + 1;
        CLOSED(CLOSED_COUNT,1)=node_x;
        CLOSED(CLOSED_COUNT,2)=node_y;  
        
        
        
    end 
    %%  回溯路径
          
    path(1,:) = traj (end,1:2); % 从目标点开始回溯
    k =1;
     pin = traj(end,:); % 目标点x y,和其父节点 parent_x, parent_y
     condi = 0;
     while condi ==0
            for i = 1:length(traj)
                % 找出储存路径中父节点
                if traj(i,1) == pin(3) && traj(i,2) ==pin(4)
                    path(k+1,:) = [pin(3), pin(4)];
                     k = k+1;
                     pin = traj(i,:);
                end
            end
            % 回溯到起点
           if pin(1)== traj(1,1) &&pin(2) ==traj(1,2)
                condi =1; 
           end
     end
     path = path(1:end,:);
   
end

五、初始化open 表

insert_open.m文件

function new_node = insert_open(xNode,yNode,hn,gn,fn)
% xNode: 现在节点x
% yNode: 现在节点y
% hn: 
% gn: 
% fn: 

% return: 待插入的新节点

new_node(1,1) = xNode;
new_node(1,2) = yNode;
new_node(1,3) = hn;
new_node(1,4) = gn;
new_node(1,5) = fn;
new_node(1,6) = 0;
new_node(1,7) = 0;
end

六、取出open list 一个节点索引值

open_min_fn_idex= min_fn.m文件

function  open_min_fn_idex= min_fn(OPEN, OPEN_COUNT)
% OPEN: open表
% OPEN_COUNT: open表个数
% return: open_min_fn_idex索引
    temp_array = [];
    j = 1;
    for i = 1 : OPEN_COUNT
        temp_array(j,:) = [OPEN(i, : ) i];
        j = j + 1;
    end
    
    if (size(temp_array) ~=0)
        [~, temp_min] = min(temp_array(:,5));
        open_min_fn_idex = temp_min;
    else
        open_min_fn_idex = -1;
    end
    
end

七 扩展open list

expand_open_array.m文件

function exp_open_array = expand_open_array(node_x, node_y,gn, xTarget,yTarget, CLOSED,  MAX_X, MAX_Y)
% return x, y ,hn, gn, fn, parent_x, parent_y

    close_size = size(CLOSED, 1);
    exp_count = 1;
    exp_open_array =[];
    
    for i =1 : -1 : -1
        for j = 1 : -1 : -1
            
            if (i~=j || i~=0) 
                exp_x = node_x + i;
                exp_y = node_y + j;
                if exp_x > 0 && exp_y > 0 && exp_x < MAX_X && exp_y < MAX_Y
                    Flag = 1; % 扩展的节点不是已经在close list
                    for k = 1 : close_size
                        if exp_x == CLOSED(k, 1) && exp_y == CLOSED(k, 2)
                            Flag = 0; % 以访问
                        end
                    end
                    
                    if Flag == 1 % 未访问
                        exp_open_array(exp_count, 1)= exp_x;
                        exp_open_array(exp_count, 2) = exp_y;
                        exp_open_array(exp_count, 3) = distance(xTarget, yTarget, exp_x,exp_y);
                        exp_open_array(exp_count, 4) = gn + distance(node_x, node_y, exp_x,exp_y);
                        exp_open_array(exp_count, 5) = exp_open_array(exp_count, 3)  + exp_open_array(exp_count, 4); 
                        exp_open_array(exp_count, 6) = exp_x - i;
                        exp_open_array(exp_count, 7) = exp_y - j;
                        exp_count = exp_count + 1;
                    end
                end
            end
        end
    end                    
end

结果展示

在这里插入图片描述

增加障碍物
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: a*算法是一种常用于栅格路径规划的启发式搜索算法。它基于启发式估计函数来评估每个节点的优先级,以找到最佳路径。 a*算法栅格路径规划代码主要包括以下几个步骤: 1. 创建一个二维栅格地,其中包含起始点和目标点,并标记障碍物或不可行走区域。 2. 初始化开放列表和关闭列表。开放列表用于存储待扩展的节点,关闭列表用于存储已经扩展过的节点。 3. 将起始点加入到开放列表,并设置起始点的代价和启发式估计值。 4. 当开放列表不为空时,进行以下操作: - 从开放列表中选择具有最小代价的节点作为当前节点。 - 如果当前节点是目标节点,则路径已找到。 - 将当前节点从开放列表移到关闭列表。 - 对当前节点的邻居节点进行遍历,计算每个邻居节点的代价和启发式估计值,并更新其父节点和总代价。 - 如果邻居节点已经在开放列表中,检查是否有更优的路径,如果有则更新其父节点和总代价。 - 如果邻居节点不在开放列表中,则将其添加到开放列表。 5. 如果开放列表为空但还未找到目标节点,则表示无法到达目标点,搜索失败。 6. 从目标点开始,通过父节点逐步回溯到起始点,即可获得最佳路径。 以上是a*算法栅格路径规划代码的基本过程。在具体的实现中,还可添加一些优化措施,如避免重复扩展节点、使用二叉堆来加速节点查找等,以提高搜索效率和减少内存占用。 ### 回答2: a*算法是一种广泛应用于栅格路径规划的搜索算法。它通过综合考虑启发式函数和已知距离来选取下一步最优的节点,以达到目标位置。 在栅格路径规划代码中,首先需要建立一个矩阵表示地,每个格子的值表示该位置的可通行状态。接着定义节点类以及启发式函数。节点类包含了节点位置、已知距离、总距离等属性,启发式函数基于当前节点和目标节点的距离来评估下一个节点的优先级。 然后,定义a*算法函数,该函数输入起始节点和目标节点,并返回最优路径。在函数内部,首先创建一个优先队列用于存储待扩展的节点。然后,将起始节点加入队列并标记为已访问。进入循环,直到队列为空或者达到目标位置为止。在每次循环中,首先从队列中取出优先级最高的节点。如果该节点为目标节点,则路径找到。否则,通过遍历上下左右四个方向的相邻节点,计算新的已知距离和总距离,然后将新节点加入队列中。 最后,回溯从起始节点到目标节点的路径。根据节点的父节点指针,反向遍历找到路径上的节点,并将其保存到一个列表中。最后,返回该列表作为最优路径。 总而言之,a*算法栅格路径规划代码是通过综合考虑启发式函数和已知距离来选取下一步最优的节点,以找到起始节点到目标节点的最优路径。其基本流程包括建立地矩阵、定义节点类和启发式函数、实现a*算法函数以及回溯最优路径

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值