A*算法原理及matlab代码

A算法与D算法在路径规划中应是用较为广泛的一类算法,D是A的增强版本,先来看看A算法。
一、A
原理
A算法结构相对来说较为复杂。
(1)首先注意区分两个词,当前已选定的栅格&当前已选定栅格的相邻栅格(后面简称相邻栅格)。
(2)两个概念:
启发距离:h=该相邻栅格到目标点的距离。
代价距离:g=已选定栅格到已选定栅格的某一相邻栅格的代价距离+已选定栅格与起点之间已生成的代价距离。
f=g+h
(3)两个列表:
openlist:该表中存放的栅格点都是以可达的相邻栅格的身份进入的。
closelist:该表中的栅格都是以可以作为父栅格身份进入的,父栅格很重要,因为直到寻路完成,所得到的所有父栅格构成起点至终点的路线。
A
过程大致如下:(与之后程序中的变量名称相对应)
1、从起点出发,进行初始化。
将起点(start)放入open list中。初始化将其作为当前已选定栅格(cell),并将起点本身作为自己的父栅格从openlist中移除放入closelist中。
2、提取cell的8个相邻栅格(s),判断每个相邻点是否为可达相邻点,即是否在地图范围内,是否为障碍物。
3、计算可达相邻栅格的h、g、f,并将当前选定栅格的可达相邻栅格放入openlist中。过程:
依次检查每个可达相邻栅格(s)是否已经存在于openlist中。
若已存在,比较两者的f值,(1)若当前值小,则将对应的已存在的栅格的父栅格替换为当前已选定栅格(cell),并更新对应的f、h、g值。(2)若原有值小,则不对其进行任何操作。
若不存在,则将其加入至openlist。
4、在当前的openlist中选择f值最小的相邻栅格作为下一个已选定栅格,并将当前已选定栅格(cell)作为该相邻栅格的父栅格,移入closelist中。
5、循环至将终点作为相邻栅格的身份加入到openlist中。
6、将父栅格依次连接起来,完成寻路。

二、具体代码:其中valid中的第一位为列表标志位,1为openlist成员,0为closelist成员
valid=[flag|s_x |s_ y | parent_x(cell) | parent_y(cell) | h(n) | g(n) | f(n)
1、主程序:

%valid中的第一列为列表标志位,1:代表该栅格在openlist中,0:代表该栅格在closelist中。
%in_valid中为障碍物节点+当前点作为夫栅格的点。
%(cell_x,cell_y)当前选定点
%(s_x,s_y)当前选定点的相邻点
clc
clear
close all

%坐标轴最大范围
max_x=20; 
max_y=20;

environment=2*(ones(max_x,max_y));%20*20矩阵中每个元素值为2

j=0;
x_val = 1; 
y_val = 1;
axis([1 max_x+1 1 max_y+1]) %axis设置坐标轴范围
grid on;
hold on;
n=0;

%设置终点坐标
xval=18;
yval=18;
x_target=xval; 
y_target=yval;

environment(xval,yval)=0; %初始化环境中的目标点置0
plot(xval+.5,yval+.5,'gd'); %将目标点设置为绿色菱形
text(xval+1,yval+.5,'Target')%并在目标点上做Target标注

% 设置障碍物位置,障碍物位置处元素值为-1,显示效果填充为黑色
for i = 3:5
    for j = 13:16
        environment(i,j) = -1; 
        %plot(i+.5,j+.5,'rd'); 
    end
end
x = [3, 6, 6, 3];
y = [13, 13, 17, 17];
fill(x,y,'k'); %fill:填充为黑色(k)
% obstacle 2
for i = 7:9
    for j = 11:14 
        environment(i,j) = -1;
        %plot(i+.5,j+.5,'rd'); 
    end
end
x = [7, 10, 10, 7];
y = [11, 11, 15, 15];
fill(x,y,'k');
% obstacle 3
for i = 11:13
    for j = 11:17 
        environment(i,j) = -1;
        %plot(i+.5,j+.5,'rd'); 
    end
end
x = [11, 14, 14, 11];
y = [11, 11, 18, 18];
fill(x,y,'k');
% obstacle 4
for i = 12:13
    for j = 6:9 
        environment(i,j) = -1;
        %plot(i+.5,j+.5,'rd'); 
    end
end
x = [12, 14, 14, 12];
y = [6, 6, 10, 10];
fill(x,y,'k');
% obstacle 5
for i = 15:16
    for j = 6:17 
        environment(i,j) = -1;
        %plot(i+.5,j+.5,'rd'); 
    end
end
x = [15, 17, 17, 15];
y = [6, 6, 18, 18];
fill(x,y,'k');
%plot(19+.5,19+.5,'gd');

%设置起始点位置
xval=3;
yval=3;
x_start=xval;%Starting Position
y_start=yval;%Starting Position

environment(xval,yval)=1;%起始点位置元素值为1
 plot(xval+.5,yval+.5,'bo');%起点处用蓝色圆圈表示

valid=[]; % x | y | parent_x | parent_y | h(n) | g(n) | f(n) 

in_valid=[]; % x | y

%获取障碍物位置
k=1;
for i=1:max_x
    for j=1:max_y
        if(environment(i,j) == -1) % check if obstacle
            in_valid(k,1)=i; 
            in_valid(k,2)=j; 
            k=k+1;
        end
    end
end
in_valid_size=size(in_valid,1);%障碍物个数

%A*过程开始
cell_x=x_start;%将起点作为当前已选定
cell_y=y_start;
valid_size=1; % initialize size of valid_list
path_cost=0;
goal_distance=sqrt((cell_x-x_target)^2 + (cell_y-y_target)^2);%起点与终点的欧式距离

new_row=[1,8];
new_row(1,1)=1;
new_row(1,2)=cell_x;%cell_x为当前选定点坐标
new_row(1,3)=cell_y;%cell_y当前选定点坐标
new_row(1,4)=cell_x; % parent x
new_row(1,5)=cell_y; % parent y 
new_row(1,6)=path_cost;
new_row(1,7)=goal_distance;
new_row(1,8)=goal_distance;

valid(valid_size,:)=new_row; % 用开始位置初始化valid
valid(valid_size,1)=0;

in_valid_size=in_valid_size+1;
in_valid(in_valid_size,1)=cell_x; % make it invalid for further iterations
in_valid(in_valid_size,2)=cell_y;

path_not_found=1;

while((cell_x ~= x_target || cell_y ~= y_target) && path_not_found == 1)
   %h=distance(当前选定点,该当前选定点的一个相邻点),g=distance(目标点,该当前选定点的一个相邻点),f=h+g
    successors=explore_successors(cell_x,cell_y,path_cost,x_target,y_target,in_valid,max_x,max_y);%successors返回当前点的所有周围可选点的 的x | y | h | g | f 信息
    successors_size=size(successors,1);%获取当前选定点相邻点可达的个数
    for i=1:successors_size%遍历当前选定点的可达相邻点
    flag=0;%标志位清零
    for j=1:valid_size %遍历valid中之前的点,判断当前选定点的可达相邻点是否已经存在
        if(successors(i,1) == valid(j,2) && successors(i,2) == valid(j,3) ) % 判断当前点的周围可达点是否已存在于valid中

        valid(j,8)=min(valid(j,8),successors(i,5)); %如果已经存在,判断当前的f值与之前的比哪个小,若以前的小则不管,若现在的小,将当前选定点
            if valid(j,8) == successors(i,5) %在判断一遍valid中的f值是否与当前的f值相同,若上一步判断现在的f值小,则不相等,需要执行以下步骤
                valid(j,4)=cell_x;% 将当前选定点替换该点作为父节点parent x,并更新记录其h,g值
                valid(j,5)=cell_y;% parent y
                valid(j,6)=successors(i,3); % h
                valid(j,7)=successors(i,4); % g
            end;
            flag=1;%该标志位置1表示valid矩阵中已经含有该节点。
        end;
    end;
    if flag == 0 % if new cell with minimum f(n) then add to valid_path,若当前点周围可选点不在valid中,标志位为0,并将其加入valid中
        valid_size= valid_size+1;
        new_row=[1,8];
        new_row(1,1)=1;%valid标志位,为0相当于该点已经移入closelist,不可在用,为1可用相当于在openlist中
        new_row(1,2)=successors(i,1);
        new_row(1,3)=successors(i,2);
        new_row(1,4)=cell_x; % valid中4,5位为当前选定点相邻点的当前点,作为parent x
        new_row(1,5)=cell_y; % parent y
        new_row(1,6)=successors(i,3); % h
        new_row(1,7)=successors(i,4); % g
        new_row(1,8)=successors(i,5); % f
        valid(valid_size,:)= new_row; 
     end;
    end;

    index_min_cell = min_f(valid,valid_size,x_target,y_target);%获取valid中的最小值
    if (index_min_cell ~= -1) % 得到下一个最小值的点,if index with minimum fn is obstacle no path exists    
        cell_x=valid(index_min_cell,2);%将f值最小的相邻点设为新的当前点
        cell_y=valid(index_min_cell,3);
        path_cost=valid(index_min_cell,6);%记录目前的h值

        in_valid_size=in_valid_size+1; % 将最小f值的相邻点移入in_valid中,put the cell in_valid so we dont come back on it again
        in_valid(in_valid_size,1)=cell_x;
        in_valid(in_valid_size,2)=cell_y;
        valid(index_min_cell,1)=0;%将该相邻点在valid中所在行的第一个元素置0,不在检查。其对应的当前选定点设为父节点
    else
        path_not_found=0;
    end;
end;  %

% backtracking to find the path回溯找到路径
i=size(in_valid,1);%i为parents个数
path=[];
xval=in_valid(i,1); % 取in_valid最后一点,pick last in in_valid_list that must be target
yval=in_valid(i,2);
i=1;
path(i,1)=xval;%取in_valid最后一个点
path(i,2)=yval;
i=i+1;

%若in_valid中最后一点为目标点,则将其作为父节点
if ( (xval == x_target) && (yval == y_target)) %判断in_valid最后一点是否为终点
    inode=0;
   parent_x=valid(find((valid(:,2) == xval) & (valid(:,3) == yval),1),4);%find返回valid的第二列、第3列中第一个同时等于xval,yval的行数,即找到终点的上一个点,即终点的父节点
   parent_y=valid(find((valid(:,2) == xval) & (valid(:,3) == yval),1),5);
   
   while( parent_x ~= x_start || parent_y ~= y_start)  %如果当前父节点不是起始点
           path(i,1) = parent_x;%将当前父节点写入路径
           path(i,2) = parent_y;
           
           inode=find((valid(:,2) == parent_x) & (valid(:,3) == parent_y),1);%查找valid中第一个等于当前父节点的点所在的行数,inode为行数
           parent_x=valid(inode,4);%取当前父节点的父节点,循环往复,直到当前的夫节点为起点,路点记录为从终点向起点方向
           parent_y=valid(inode,5);
           i=i+1;
    end;
    
% plottin path画图
%path中记录的路点从上往下依次为由终点向起点方向的路点,因此此处path取值应从下想上取才为从起点向终点运动的方向
j=size(path,1);
 p=plot(path(j,1)+.5,path(j,2)+.5,'bo');
  j=j-1;
 for i=j:-1:1%画从起点向终点的运动过程
  pause(.25);%pause(n) 暂停执行 0.25秒,然后继续执行。
  set(p,'XData',path(i,1)+.5,'YData',path(i,2)+.5);
 drawnow ;%刷新屏幕,实时显示plot
 end;
 plot(path(:,1)+.5,path(:,2)+.5);%得出路径
else
disp( 'Sorry, No path exists to the Target!');
end

explore_successors.m

for k= 1:-1:-1    %分别获取当前点周围8个相邻点的信息
        for j= 1:-1:-1
            if (k~=j || k~=0)  %把当前选定点排除掉,只获取当前选定点周围的可选点信息
                s_x = x_cell+k;  %(s_x,s_y)是8个相邻点坐标
                s_y = y_cell+j;
                if( (s_x >0 && s_x <=max_x) && (s_y >0 && s_y <=max_y)) % 该相邻点是否在地图范围内
                    flag=1;    %当前点在地图范围内标志位为1                
                    for c1=1:c2 % 遍历所有障碍物位置,检查当前点是否为障碍物
                        if(s_x == in_valid(c1,1) && s_y == in_valid(c1,2)) 
                            flag=0;%当前点为不可达点,标志位为0
                        end;
                    end;
                    if (flag == 1) %当前点可达,将当前点加入successors中
                        successors(successor_count,1) = s_x;
                        successors(successor_count,2) = s_y;
                        successors(successor_count,3) = h+distance(x_cell,y_cell,s_x,s_y);%h
                        successors(successor_count,4) = distance(x_target,y_target,s_x,s_y);%g
                        successors(successor_count,5) = successors(successor_count,3)+successors(successor_count,4);%f
                        successor_count=successor_count+1;
                    end
                end
            end
        end
    end

min_f.m

%   相当于取openlist中f值的最小值。index_min_cell = min_f(valid,valid_size,x_target,y_target)
function index_of_min = min_f(valid,valid_len,x_target,y_target)
 temp_array=[];
 k=1;
 flag=0;%标志位清零
 goal_index=0;
 for j=1:valid_len  %遍历valid中已加入的所有值,判断是否为终点
     if (valid(j,1)==1)%若节点状态标志位为1相当于该相邻点在openlist中,为1该相邻点的父节点已经移入close list,不必再看
         temp_array(k,:)=[valid(j,:) j]; %将valid中第一位=1的自由点依次加入到temp_array中,并在该行最后一位记录其在valid中的行数
         if (valid(j,2)==x_target && valid(j,3)==y_target)   %判断该相邻点是否为为终点,若是,标志位置1
             flag=1;
             goal_index=j;%目标索引指向valid中对应的该相邻点的行数
         end;
         k=k+1;
     end;
 end;
 if flag == 1 %若是终点,最小值索引为终点
     index_of_min=goal_index;  
 end
 
 if size(temp_array ~= 0)%统计自由节点的个数
  [min_f,temp_min]=min(temp_array(:,8)); %取其中f值最小的点的最小值及在temp_array中的行数,
  %min_f
  index_of_min=temp_array(temp_min,9);%取该行最后对应的valid的行号
  fprintf('Cell with minimum f found to be x : %d y : %d with f = %f',valid(index_of_min,2),valid(index_of_min,3),valid(index_of_min,8));
 else
     index_of_min=-1;
 end
### 回答1: A*算法是一种常用的启发式搜索算法,用于在图形网络中寻找最短路径。以下是一个基本的A*算法MATLAB代码实现: ```MATLAB function [path, G, F, H] = A_star(start, goal, graph) % 初始化 num_nodes = size(graph, 1); openList = start; closeList = []; G = Inf(num_nodes, 1); F = Inf(num_nodes, 1); H = zeros(num_nodes, 1); G(start) = 0; F(start) = H(start) + G(start); while ~isempty(openList) % 寻找F值最小的节点 [~, current] = min(F(openList)); current = openList(current); % 找到目标节点,生成路径并返回 if current == goal path = getPath(goal, closeList); return; end % 将当前节点移至closeList openList(openList == current) = []; closeList = [closeList, current]; % 寻找当前节点的相邻节点 neighbors = find(graph(current, :) ~= Inf); for i = 1:length(neighbors) neighbor = neighbors(i); % 如果相邻节点已在closeList中,则跳过 if ismember(neighbor, closeList) continue; end % 计算G值和H值 temp_G = G(current) + graph(current, neighbor); temp_H = heuristic(neighbor, goal); % 启发函数,用于估计相邻节点到目标节点的代价 % 如果该相邻节点不在openList中,则加入openList if ~ismember(neighbor, openList) openList = [openList, neighbor]; % 如果G值更新更小,则更新父节点为当前节点 elseif temp_G >= G(neighbor) continue; end % 更新相邻节点的G值、H值和F值 G(neighbor) = temp_G; H(neighbor) = temp_H; F(neighbor) = G(neighbor) + H(neighbor); end end % 如果openList为空,表示无法找到路径 path = []; end function path = getPath(endNode, closeList) path = [endNode]; while closeList(endNode) ~= start path = [closeList(endNode), path]; endNode = closeList(endNode); end path = [start, path]; end function h = heuristic(node, goal) % 启发函数的实现,可以根据实际问题进行自定义 % 例如,可以使用曼哈顿距离或欧几里得距离作为启发函数 h = 0; end ``` 上述代码中,A*算法根据节点之间的代价和启发函数的值来选择下一个扩展的节点,最终找到一条从起始点到目标点的最短路径。代码包含注释以帮助理解算法的实现流程。请根据具体问题修改注释中的启发函数部分以适应你的需求。 ### 回答2: A*算法是一种在图遍历和路径搜索中常用的启发式搜索算法。其基本思想是在搜索过程中综合考虑当前位置到目标位置的距离和当前位置到起始位置的代价,选择代价最小的路径。以下是一个用MATLAB实现A*算法的示例代码: ``` function path = astar(map,start,goal) % 输入参数:map表示地图,start表示起始点坐标,goal表示目标点坐标 % 输出参数:path表示找到的路径 % 地图用二维矩阵表示,元素为0表示可通行,元素为1表示障碍物 % 初始化地图和起始点 [row, col] = size(map); G = zeros(row, col) + inf; % 起始点到每个点的代价 F = zeros(row, col) + inf; % F = G + H,H表示当前点到目标点的估计代价 openList = []; closedList = []; G(start(1), start(2)) = 0; F(start(1), start(2)) = heuristic(start, goal); % 开始搜索 while ~isempty(openList) [~, current] = min(F(:)); [current_row, current_col] = ind2sub(size(F), current); % 如果找到目标点,生成路径并返回 if [current_row, current_col] == goal path = backtrace(start, current); return; end % 将当前点加入闭合列表 openList(current) = []; closedList = [closedList; current]; % 寻找当前点相邻的可通行点 for i = -1:1 for j = -1:1 neighbor_row = current_row + i; neighbor_col = current_col + j; % 跳过无效的邻居 if neighbor_row < 1 || neighbor_row > row || neighbor_col < 1 || neighbor_col > col continue; end if map(neighbor_row, neighbor_col) == 1 || any(closedList == sub2ind(size(F), neighbor_row, neighbor_col)) continue; end % 计算邻居节点的代价 tentative_G = G(current_row, current_col) + dist(current_row, current_col, neighbor_row, neighbor_col); % 如果邻居节点已经在开启列表中并且代价更大,则跳过 if any(openList == sub2ind(size(F), neighbor_row, neighbor_col)) && tentative_G >= G(neighbor_row, neighbor_col) continue; end % 更新邻居节点的代价、父节点和估计代价 G(neighbor_row, neighbor_col) = tentative_G; F(neighbor_row, neighbor_col) = G(neighbor_row, neighbor_col) + heuristic([neighbor_row, neighbor_col], goal); openList = [openList; sub2ind(size(F), neighbor_row, neighbor_col)]; end end end % 如果没有找到路径,返回空 path = []; end function h = heuristic(current, goal) % 计算当前点到目标点的曼哈顿距离 h = abs(current(1) - goal(1)) + abs(current(2) - goal(2)); end function d = dist(x1, y1, x2, y2) % 计算两个点之间的直线距离 d = sqrt((x2 - x1)^2 + (y2 - y1)^2); end function path = backtrace(start, current) % 从目标点回溯路径 path = []; while current ~= sub2ind(size(path), start(1), start(2)) path = [current; path]; [current_row, current_col] = ind2sub(size(path), current); current = path(current_row, current_col); end path = [start; path]; end ``` 这段代码实现了一个基本的A*算法,通过启发式估计函数和代价函数来搜索从起始点到目标点之间的最短路径。在代码中,首先根据输入的起始点和目标点初始化地图和代价矩阵,然后在搜索过程中根据A*算法原理不断更新代价矩阵,并选择代价最小的路径。最后,返回找到的最短路径。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值