1 简介
基本的迷宫搜索算法被称为无信息规划算法是一种盲从状态下的搜索算法。所谓的无信息规划,指的是除了起点和终点之间的点以外的中间节点都是可扩展节点,且它们成为系统后续搜索节点的概率是相同的。无信息规划算法中最常见的是广度优先和深度优先两种。而传统的向心法则是由右手法则、左手法则、中左法则和中右法则按照一定规则有机组合起来的一种深度优先的搜索法则。这种算法首先将迷宫分为 4 个区域,当电脑鼠处在不同区域时再根据电脑鼠的行进方向选择不同的搜索法则,其具体组合方式如图 1所示。大多数情况下其搜索效率优于右手法则和左手法则。但在一些特定的迷宫中,其搜索效率可能更低,搜索处的路径可能更长,或者只比右手法则的搜索效率略高。
2 部分代码
function robotSimulation
% robotSimulation - Robotic exploration simulation.
% This function serves to show how one can use the A* path finding
% function, astar_jw.
%
% A random world is made with starting and goal locations. A simple robot
% with the ability to sense nearby obstacles is used to move towards the
% goal location according to the output of the astar_jw function. At each
% step the robot senses the world (updating its own map of the world) and
% recomputes the optimal path to the goal according to its own map. Each
% simulation trial ends when either the robot reaches the goal or no path
% to the goal can be found.
home
while true % Simulation never stops
% Generate a random world with starting and goal locations
n = 30; % World size is n by n
wallpercent = 0.45; % Percent of world that is a wall
[world, init, goal] = initializeWorld(n,wallpercent);
% Initialize the world as the robot knows it (aka the 'grid')
grid = zeros(size(world));
% Initialize the current robot location
loc = init;
% Set up figures
h = figure(1); drawWorld(world, init, goal, h);
g = figure(2); % figure for grid
% Explore the world until we reach the goal or deem reaching the
% goal impossible
while true
% Start the clock for this loop iteration
tic
% Sense world (update grid)
grid = senseWorld(world, grid, loc);
% Compute path/directions to goal using known grid
[path, directions] = astar_jw(grid, loc, goal);
% If we couldn't find the goal then there is no path to goal
if numel(path)==0
drawGrid(grid, init, goal, loc, g);
home; disp('No path to goal!'); pause(1)
break
end
% Draw the grid
drawGrid(grid, init, goal, loc, g);
% Draw path overlayed on the grid
drawPath(path, g);
% Move robot according to directions
loc = loc + directions(1,:);
% Detect if we made it to the goal
if loc(1)==goal(1) && loc(2)==goal(2)
home; disp('Reached goal!'); pause(1)
break
end
% Slow down simulation
pause(0.15-toc)
end
end
end
function drawWorld(world, init, goal, h)
world = 1-world;
world(init(1),init(2)) = 0.66;
world(goal(1),goal(2)) = 0.33;
figure(h)
imagesc(world); colormap(gray); axis off; hold on
end
function drawGrid(grid, init, goal, loc, h)
grid = 1-grid;
grid(init(1),init(2)) = 0.66;
grid(goal(1),goal(2)) = 0.33;
figure(h)
imagesc(grid); colormap(gray); axis off; hold on
plot(loc(2), loc(1), 'go')
end
function drawPath(path, g)
figure(g); hold on
plot(path(:,2), path(:,1), 'co', 'LineWidth', 2)
plot(path(1,2), path(1,1), 'gs', 'LineWidth', 4)
plot(path(end,2),path(end,1), 'rs', 'LineWidth', 4)
drawnow
hold off
end
function grid = senseWorld(varargin)
% This function senses the world and updates the robot's grid. The calling
% form for this function is:
%
% grid = senseWorld(world, grid, loc[, senseScheme, option])
%
% where the optional 'senseScheme' can be one of:
% {'line of sight'}
% {'circle', vision radius}
% by default senseScheme is set to 'line of sight'
% (note: in the case of two arguments for 'senseScheme' you need them both)
world = varargin{1};
grid = varargin{2};
loc = varargin{3};
radius = 1;
if nargin==3
senseScheme = 'line of sight';
elseif nargin>3
senseScheme = varargin{4};
if strcmp(senseScheme, 'circle')
if nargin==5
radius = varargin{5};
else
warning('You need to input a radius measurement if you set senseScheme to ''circle''!')
return
end
end
end
worldSize = size(world);
sightDir = [[-1 0]
[ 0 -1]
[ 1 0]
[ 0 1]];
for R = 1:size(sightDir,1)
sightLoc = loc(1:2);
canSee = true;
while canSee
xMin = max(1, sightLoc(2)-radius);
xMax = min(worldSize(2), sightLoc(2)+radius);
yMin = max(1, sightLoc(1)-radius);
yMax = min(worldSize(1), sightLoc(1)+radius);
grid(yMin:yMax, xMin:xMax) = world(yMin:yMax, xMin:xMax);
canSee = false;
nextPos = sightLoc + sightDir(R,:);
% If we're not going off the grid
if nextPos(1)>=1 && nextPos(1)<=worldSize(1) ...
&& nextPos(2)>=1 && nextPos(2)<=worldSize(2)
% And while we aren't seeing through obstacles
if world(nextPos(1), nextPos(2))==0
% Continue viewing down the corridor
canSee = true;
sightLoc = nextPos;
end
end
end
end
end
function [world, init, goal] = initializeWorld(n,wallpercent)
% This function will create an example n by n world where wallpercent of it
% is blocked off. 1s denote walls and 0s denote traversable terrain.
% create the world and place walls with infinite cost
world = ones(n,n) + 10*rand(n,n);
world(ind2sub([n n],ceil(n^2.*rand(floor(n*n*wallpercent),1)))) = Inf;
world(world==inf) = 1;
world(world~=1) = 0;
% set random starting and ending locations
init = randi(n, [1 2]); world(init(1),init(2)) = 0;
goal = randi(n, [1 2]); world(goal(1),goal(2)) = 0;
end
3 仿真结果
4 参考文献
[1]周宇杭等. "基于A星算法的移动机器人路径规划应用研究." 电脑知识与技术:学术版 16.13(2020):4.
5 MATLAB代码与数据下载地址
见博客主页