A*算法是比较流行的启发式搜索算法之一,被广泛应用于路径优化领域。它的独特之处是检查最短路径中每个可能的节点时引入了全局信息,对当前节点距终点的距离做出估计,并作为评价该节点处于最短路线上的可能性的量度。
在正式实现算法之前介绍一种地图建模的方法,栅格法如图所示,栅格法实质上是将机器人工作环境进行单元分割,将其用大小相等的方块表示出来,这样栅格大小的选取是影响规划算法性能的一个很重要的因素。栅格较小的话,由栅格地图所表示的环境信息将会非常清晰,但由于需要存储较多的信息,会增大存储开销,同时干扰信号也会随之增加,规划速度会相应降低,实时性得不到保证;反之,由于信息存储量少,抗干扰能力有所增强,规划速随之增快,但环境信息划分会变得较为模糊,不利于有效路径的规划。
算法实验地图: 寻路要求从左上角开始到右下角
栅格法对环境进行建模: 将环境用 16×15的矩阵表示,其中0表示障碍物、1表示可移动位置
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
111111111111111111111111111111000000011111111000000011111111000000011000000000000011000000000000011000000000000011111111111111111111111111111000000000111111000000000111111000000000111111000000000111111111111111111111111111111111111111111111
编写算法:
1. 把起点加入 open list 。
2. 重复如下过程:
a. 遍历open list ,查找F值最小的节点,把它作为当前要处理的节点,然后移到close list中
b. 对当前方格的 8 个相邻方格一一进行检查,如果它是不可抵达的或者它在close
list中,忽略它。否则,做如下操作:
□ 如果它不在open list中,把它加入open list,并且把当前方格设置为它的父亲
□ 如果它已经在open list中,检查这条路径 ( 即经由当前方格到达它那里 )
是否更近。如果更近,把它的父亲设置为当前方格,并重新计算它的G和F值。如果你的open
list是按F值排序的话,改变后你可能需要重新排序。
c. 遇到下面情况停止搜索:
□ 把终点加入到了 open list 中,此时路径已经找到了,或者
□ 查找终点失败,并且open list 是空的,此时没有路径。
3.
从终点开始,每个方格沿着父节点移动直至起点,形成路径。
Java Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
packagecom;importjava.util.ArrayList;publicclassMain {privatestaticcharmap[][] = null;privatestaticintrol_num,col_num;privatestaticStringstr_list[] = {"1 1 1 1 1 1 1 1 1 1 1 1 1 1 1","1 1 1 1 1 1 1 1 1 1 1 1 1 1 1","0 0 0 0 0 0 0 1 1 1 1 1 1 1 1","0 0 0 0 0 0 0 1 1 1 1 1 1 1 1","0 0 0 0 0 0 0 1 1 0 0 0 0 0 0","0 0 0 0 0 0 0 1 1 0 0 0 0 0 0","0 0 0 0 0 0 0 1 1 0 0 0 0 0 0","0 0 0 0 0 0 0 1 1 1 1 1 1 1 1","1 1 1 1 1 1 1 1 1 1 1 1 1 1 1","1 1 1 1 1 1 0 0 0 0 0 0 0 0 0","1 1 1 1 1 1 0 0 0 0 0 0 0 0 0","1 1 1 1 1 1 0 0 0 0 0 0 0 0 0","1 1 1 1 1 1 0 0 0 0 0 0 0 0 0","1 1 1 1 1 1 1 1 1 1 1 1 1 1 1","1 1 1 1 1 1 1 1 1 1 1 1 1 1 1","1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"};publicstaticvoidmain(String[] args) {
build_map();
find_path();
print_path();
}privatestaticvoidbuild_map(){//将地图创建到二维数组中rol_num = str_list.length;
col_num = str_list[0].split(" ").length;
map =newchar[rol_num][col_num];for(inti =0;i
map[i][j] = list[j].charAt(0);
}
}
System.out.println("------以下为环境地图------");for(inti =0;i
System.out.print(map[i][j]);
}
System.out.println();
}
}//声明内部类 GridprivatestaticclassGrid {intG,H;intI,J;
Grid parent = null;//指向上一个节点publicGrid(inti,intj) {this.I = i;this.J = j;
}voidupdate(Grid min_grid){this.G = min_grid.G +1;this.H = (rol_num - I) + (col_num - J) -2;this.parent = min_grid;
}
}privatestaticGrid [][]grid = null;privatestaticvoidfind_path(){
grid =newGrid[rol_num][col_num];for(inti =0;i
grid[i][j] =newGrid(i,j);
}
}
ArrayList open_list =newArrayList();
ArrayList closed_list =newArrayList();//开始寻找初始化grid[0][0].G =0;
grid[0][0].H = rol_num + col_num -2;
open_list.add(grid[0][0]);//将起点加入open_list中while(!closed_list.contains(grid[rol_num -1][col_num -1]) && !open_list.isEmpty()){//寻找最小的F作为下一个节点Grid min_grid = open_list.get(0);intmin_F = min_grid.G + min_grid.H;for(inti =0;i
Grid temp_grid = open_list.get(i);inttemp_F = temp_grid.G + temp_grid.H;if(min_F > temp_F){
min_grid = temp_grid;
min_F = temp_F;
}
}
open_list.remove(min_grid);
closed_list.add(min_grid);//然后将周围节点加入open_list中intI = min_grid.I;intJ = min_grid.J;intt_I,t_J;
t_I = I -1; t_J = J -1;if(check(t_I, t_J, open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I -1; t_J = J;if(check(t_I, t_J,open_list, closed_list,min_grid)){
grid[t_I][t_J].update(min_grid);//更新其父节点为min_grid,并更新G、H值open_list.add(grid[t_I][t_J]);//加入open_list}
t_I = I -1; t_J = J +1;if(check(t_I, t_J , open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I; t_J = J +1;if(check(t_I, t_J , open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I +1; t_J = J +1;if(check(t_I, t_J, open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I +1; t_J = J;if(check(t_I, t_J, open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I +1; t_J = J -1;if(check(t_I, t_J, open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
t_I = I; t_J = J -1;if(check(t_I, t_J, open_list, closed_list ,min_grid)){
grid[t_I][t_J].update(min_grid);
open_list.add(grid[t_I][t_J]);
}
}
}privatestaticbooleancheck(intI,intJ,ArrayList open_list,ArrayList closed_list,Grid min_grid){//超出边界if(I <0|| I >= rol_num || J <0|| J >= col_num ){returnfalse;
}//有阻碍if(map[I][J] =='0'){returnfalse;
}if(closed_list.contains(grid[I][J])){returnfalse;
}if(open_list.contains(grid[I][J]) && grid[I][J].parent != null && grid[I][J].G <= min_grid.G +1){returnfalse;
}returntrue;
}privatestaticvoidprint_path(){
Grid next = grid[rol_num -1][col_num -1];//反向找出路径while(next != null){
map[next.I][next.J] ='+';
next = next.parent;
}
System.out.println("------以下为寻路结果------");for(inti =0;i
System.out.print(map[i][j]);
}
System.out.println();
}
}
}
路径搜寻结果: 其中“+”表示路径
C++ Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+111111111111111++++++111111110000000+111111100000001+11111100000001+00000000000001+00000000000001+0000000000000+1111111111111+1111111111111+00000000011111+00000000011111+00000000011111+000000000111111+111111111111111+111111111111111+++++++