在使用栅格法进行移动机器人路径规划时,需要将机器人工作的环境地图—栅格矩阵,转换成邻接矩阵,这里介绍一下栅格地图转换成邻接矩阵的具体函数方法。
在栅格地图中,每一个栅格相当于一个节点;而在一条路径中,各个栅格是相邻的或者是对角的。比如一个4*4栅格,如下
对于其中一条路径1-2-7-11-16,它的每一个节点对应的栅格是相邻的或者是对角的。
也就是说这里的路径不可能是1-3或2-11或1-16这种不是相邻也不是对角。
如果此时在这样的栅格地图中加上障碍物,对于有障碍物的地图,障碍栅格和任何栅格都不相邻。如下图,假设7和10号栅格是障碍,认为6和7是不相邻的,6和10不相邻等。
此时定义一个邻接矩阵D,邻接矩阵D就是每个栅格之间的距离。对于上述4x4矩阵,有16个栅格,那么每一个栅格到其他所有(15个)栅格,就得到15个距离。且一般算上自己到自己的距离。这样每个栅格到其他栅格的距离就有16个,于是便构成16*16的矩阵。
对于上述障碍栅格地图,邻接矩阵D是16*16的矩阵,为了更好的理解,在此用可行性来代替距离,即0表示两个栅格不相邻不对角,即不可行,1表示两个栅格相邻或对角,即可行,且规定自己到自己的为不可行。这个和距离正好成倒数关系,即0表示距离为无穷大,1表示单位距离(对角距离根号2,这里近似为单位1),如D的第一行表示栅格1到其他各栅格的可行性如下:
栅格6到其他栅格的可行性如下:
其中7和10与栅格6不可行是以为7和10是障碍栅格,其他不可行是因为二者不相邻。
用上面方法可以分别得到栅格1~栅格16到其他栅格的可行性,得到16*16的邻接矩阵。
其中需要注意:寻找栅格地图的直角坐标表示法和序号表示法的映射关系。
如果是下面这样的映射方法:
上述两种标识方法的映射关系见式:
具体的映射方式根据自己的选择设计!
下面展示两种方法使用Matlab代码将栅格地图转换成邻接矩阵
方式一:
%% 栅格地图G转换成邻接矩阵D,G2D函数
% 在D矩阵中元素行下标第一个节点在栅格G中的位置,列下标代表第二个节点在栅格G中的位置,
% 若这两个节点在栅格地图中是自由栅格且是相邻或者对角的,则两点的距离则为邻接矩阵D的元素值,否则D的元素值为0
% 通过对栅格矩阵G的两次搜索遍历,寻找两个相邻或对角的自由栅格,计算它们之间的距离
function D=G2D(G)
h=size(G,1);
D=zeros(h*h,h*h);
%用i表示矩阵G的行下标,j表示矩阵G的列下标。这是外层嵌套循环,表示第一个自由栅格
%用m表示矩阵G的行下标,n表示矩阵G的列下标。这是内层嵌套循环,表示第二个自由栅格
for i=1:h %外层嵌套,遍历矩阵G
for j=1:h
if G(i,j)==0 %判断是否是自由栅格,确定第一个自由栅格
for m=1:h %内层嵌套,遍历矩阵G
for n=1:h
if G(m,n)==0 %判断是否是自由栅格,确定第二个自由栅格
%分别计算这两个自由栅格在栅格地图中x方向距离和y方向距离
im=abs(i-m);
jn=abs(j-n);
if im+jn==1||(im==1&&jn==1)
%用矩阵D中的部分元素存储栅格地图中两相邻或对角自由栅格在矩阵G中的位置和距离,其他元素值为0
%矩阵D的下标分别表示两个自由栅格在矩阵G中的位置,D中元素的值表示两个自由栅格的距离
D((i-1)*h+j,(m-1)*h+n)=(im+jn)^0.5;
end
end
end
end
end
end
end
end
方法二:
%% 栅格地图G转换成邻接矩阵D,G2D函数
function D=SecondG2D(G) %邻接矩阵就是每个栅格之间的距离
[m,n]=size(G); %返回矩阵G的尺寸并将行返回到m中,列返回到n中
N=m*n; %元素个数
D=zeros(N,N); %生成一个N*N的0矩阵
for Dx=1:N
for Dy=Dx:N
x1=ceil(Dx/n); %ceil向上取整,返回不小于x的最小整数值
y1=mod(Dx,n); %mod取余,Dx对n取余
if y1==0
y1=n;
end
x2=ceil(Dy/n);
y2=mod(Dy,n);
if y2==0
y2=n;
end
if Dx==Dy
D(Dx,Dy)=inf;
elseif (G(x1,y1)==1) || (G(x2,y2)==1);
D(Dx,Dy)=inf;
else
if (mod(Dx,n) ==1)
if(Dx==1)
if (Dy-Dx==1) || (Dy-Dx==n)
D(Dx,Dy)=1;
elseif (Dy-Dx==n+1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
elseif(Dx==N-n+1)
if (Dy-Dx==1) || (Dx-Dy==n)
D(Dx,Dy)=1;
elseif (Dx-Dy==n-1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
else
if (Dy-Dx==1) || (Dy-Dx==n) || (Dx-Dy==n)
D(Dx,Dy)=1;
elseif (Dx-Dy==n-1) || (Dy-Dx==n+1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
end
elseif mod(Dx,n) ==0
if(Dx==n)
if (Dx-Dy==1) || (Dy-Dx==n)
D(Dx,Dy)=1;
elseif (Dy-Dx==n-1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
elseif(Dx==N)
if (Dx-Dy==1) || (Dy-Dx==n)
D(Dx,Dy)=1;
elseif (Dy-Dx==n+1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
else
if (Dx-Dy==1) || (Dy-Dx==n) || (Dx-Dy==n)
D(Dx,Dy)=1;
elseif (Dy-Dx==n-1) || (Dx-Dy==n+1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
end
else
if (Dx-Dy==1) || (Dy-Dx==1) || (Dy-Dx==n) || (Dx-Dy==n)
D(Dx,Dy)=1;
elseif (Dx-Dy==n+1) || (Dy-Dx==n+1) || (Dy-Dx==n-1) || (Dx-Dy==n-1)
D(Dx,Dy)=sqrt(2);
else
D(Dx,Dy)=inf;
end
end
end
end
end
for i=1:N
for j=i:N
if(i~=j)
D(j,i)=D(i,j);
end
end
end
链接:
http://blog.sina.com.cn/s/blog_15e199e600102xvow.html
http://www.omegaxyz.com/2019/01/28/aco_routes2/
https://blog.csdn.net/KantsWang/article/details/83651954