1 # 版本2,2018—04—09 2 # 所有节点的g值并没有初始化为无穷大 3 # 当两个子节点的f值一样时,程序选择最先搜索到的一个作为父节点加入closed 4 # 对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径 5 # 最后closed表中的节点很多,如何找出最优的一条路径 6 # 撞墙之后产生较多的节点会加入closed表,此时开始删除closed表中不合理的节点 7 8 9 import numpy 10 from pylab import * 11 import copy 12 13 # 定义一个含有障碍物的20×20的栅格地图 14 # 10表示可通行点 15 # 0表示障碍物 16 # 7表示起点 17 # 5表示终点 18 map_grid = numpy.full((20, 20), int(10), dtype=numpy.int8) 19 # print(map_grid) 20 map_grid[3, 3:8] = 0 21 map_grid[3:10, 7] = 0 22 map_grid[10, 3:8] = 0 23 map_grid[17, 13:17] = 0 24 map_grid[10:17, 13] = 0 25 map_grid[10, 13:17] = 0 26 map_grid[5, 2] = 7 27 map_grid[15, 15] = 5 28 # 画出定义的栅格地图 29 30 # plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10) 31 # plt.colorbar() 32 # xlim(-1, 20) # 设置x轴范围 33 # ylim(-1, 20) # 设置y轴范围 34 # my_x_ticks = numpy.arange(0, 20, 1) 35 # my_y_ticks = numpy.arange(0, 20, 1) 36 # plt.xticks(my_x_ticks) 37 # plt.yticks(my_y_ticks) 38 # plt.grid(True) 39 # plt.show() 40 41 42 class AStar(object): 43 """ 44 创建一个A*算法类 45 """ 46 47 def __init__(self): 48 """ 49 初始化 50 """ 51 self.f = 0 52 self.g = 0 53 self.last_point = numpy.array([]) # 上一个目标点不断取得更新 54 self.current_point = numpy.array([]) # 当前目标点不断取得更新 55 self.open = numpy.array([[], []]) # 先创建一个空的open表 56 self.closed = numpy.array([[], []]) # 先创建一个空的closed表 57 self.taboo = numpy.array([[], []]) # 创建一个禁忌表,用于放置不再搜索的点 58 self.start = numpy.array([5, 2]) # 起点坐标 59 self.goal = numpy.array([15, 15]) # 终点坐标 60 61 def h_value_tem(self, cur_p): 62 """ 63 计算拓展节点和终点的h值 64 :param cur_p:子搜索节点坐标 65 :return: 66 """ 67 h = (cur_p[0] - 15) ** 2 + (cur_p[1] - 15) ** 2 68 h = numpy.sqrt(h) # 计算h 69 return h 70 71 def g_value_tem(self, chl_p, cu_p): 72 """ 73 计算拓展节点和父节点的g值 74 其实也可以直接用1或者1.414代替 75 :param chl_p:子节点坐标 76 :param cu_p:父节点坐标,也就是self.current_point 77 :return:返回子节点到父节点的g值,但不是全局g值 78 """ 79 g1 = cu_p[0] - chl_p[0] 80 g2 = cu_p[1] - chl_p[1] 81 g = g1 ** 2 + g2 ** 2 82 g = numpy.sqrt(g) 83 return g 84 85 def f_value_tem(self, chl_p, cu_p): 86 """ 87 求出的是临时g值和h值的和,还需加上累计g值得到全局f值 88 :param chl_p: 父节点坐标 89 :param cu_p: 子节点坐标 90 :return: 91 """ 92 f = self.g_value_tem(chl_p, cu_p) + self.h_value_tem(cu_p) 93 return f 94 95 def min_f(self): 96 """ 97 找出open中f值最小的节点坐标,记录为current_point 98 :return:返回open表中最小值的位置索引和在map_grid中的坐标 99 对撞墙后的处理方式是,随机选择一个方向进行搜索 100 并且将open列表清零,不然一直是死循环 101 这种处理方式以后待改进!!! 102 """ 103 tem_f = [] # 创建一个记录f值的临时列表 104 for i in range(self.open.shape[1]): 105 # 计算拓展节点的全局f值 106 f_value = self.f_value_tem(self.current_point, self.open[:, i]) + self.g 107 tem_f.append(f_value) 108 index = tem_f.index(min(tem_f)) # 返回最小值索引 109 location = self.open[:, index] # 返回最小值坐标 110 print('打印位置索引和地图坐标:') 111 print(index, location) 112 return index, location 113 114 def child_point(self, x): 115 """ 116 拓展的子节点坐标 117 :param x: 父节点坐标 118 :return: 子节点存入open表,返回值是每一次拓展出的子节点数目,用于撞墙判断 119 当搜索的节点撞墙后,如果不加处理,会陷入死循环 120 """ 121 tem_open = numpy.array([[], []]) # 统计拓展节点的临时数组 122 tem_open_shape = 0 # 统计临时数组的长度 123 # 开始遍历周围8个节点 124 for j in range(-1, 2, 1): 125 for q in range(-1, 2, 1): 126 if j == 0 and q == 0: # 搜索到父节点去掉 127 continue 128 129 # print(map_grid[int(x[0] + j), int(x[1] + q)]) 130 if map_grid[int(x[0] + j), int(x[1] + q)] == 0: # 搜索到障碍物去掉 131 continue 132 if x[0] + j < 0 or x[0] + j > 19 or x[1] + q < 0 or x[1] + q > 19: # 搜索点出了边界去掉 133 continue 134 # 在open表中,则去掉搜索点 135 a = self.judge_location(x, j, q, self.open) 136 if a == 1: 137 continue 138 # 在closed表中,则去掉搜索点 139 b = self.judge_location(x, j, q, self.closed) 140 if b == 1: 141 continue 142 143 # 在taboo表中,则去掉搜索点 144 c = self.judge_location(x, j, q, self.taboo) 145 if c == 1: 146 continue 147 148 m = numpy.array([x[0] + j, x[1] + q]) 149 150 tem_open = numpy.c_[tem_open, m] # 151 152 tem_open_shape = tem_open.shape[1] # 求出tem_open的长度 153 154 self.open = numpy.c_[self.open, m] # 搜索出的子节点加入open 155 # print('打印第一次循环后的open:') 156 # print(self.open) 157 return tem_open_shape 158 159 def judge_location(self, x, j, q, list_co): 160 """ 161 判断拓展点是否在open表或者closed表中 162 :return: 163 """ 164 jud = 0 165 for i in range(list_co.shape[1]): 166 167 if x[0] + j == list_co[0, i] and x[1] + q == list_co[1, i]: 168 169 jud = jud + 1 170 else: 171 jud = jud 172 # if a != 0: 173 # continue 174 return jud 175 176 def draw_path_closed(self): 177 """ 178 画出closed表中的坐标点图 179 :return: 180 """ 181 map_closed = copy.deepcopy(map_grid) 182 for i in range(self.closed.shape[1]): 183 x = self.closed[:, i] 184 185 map_closed[int(x[0]), int(x[1])] = 5 186 187 plt.imshow(map_closed, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10) 188 # plt.colorbar() 189 xlim(-1, 20) # 设置x轴范围 190 ylim(-1, 20) # 设置y轴范围 191 my_x_ticks = numpy.arange(0, 20, 1) 192 my_y_ticks = numpy.arange(0, 20, 1) 193 plt.xticks(my_x_ticks) 194 plt.yticks(my_y_ticks) 195 plt.grid(True) 196 # plt.show() 197 198 def draw_init_map(self): 199 """ 200 画出起点终点图 201 :return: 202 """ 203 204 plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10) 205 # plt.colorbar() 206 xlim(-1, 20) # 设置x轴范围 207 ylim(-1, 20) # 设置y轴范围 208 my_x_ticks = numpy.arange(0, 20, 1) 209 my_y_ticks = numpy.arange(0, 20, 1) 210 plt.xticks(my_x_ticks) 211 plt.yticks(my_y_ticks) 212 plt.grid(True) 213 # plt.show() 214 215 def draw_path_open(self): 216 """ 217 画出open表中的坐标点图 218 :return: 219 """ 220 map_open = copy.deepcopy(map_grid) 221 for i in range(self.closed.shape[1]): 222 x = self.closed[:, i] 223 224 map_open[int(x[0]), int(x[1])] = 1 225 226 plt.imshow(map_open, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10) 227 # plt.colorbar() 228 xlim(-1, 20) # 设置x轴范围 229 ylim(-1, 20) # 设置y轴范围 230 my_x_ticks = numpy.arange(0, 20, 1) 231 my_y_ticks = numpy.arange(0, 20, 1) 232 plt.xticks(my_x_ticks) 233 plt.yticks(my_y_ticks) 234 plt.grid(True) 235 # plt.show() 236 237 def draw_three_axes(self): 238 """ 239 将三张图画在一个figure中 240 :return: 241 """ 242 plt.figure() 243 ax1 = plt.subplot(221) 244 245 ax2 = plt.subplot(222) 246 ax3 = plt.subplot(223) 247 plt.sca(ax1) 248 self.draw_init_map() 249 plt.sca(ax2) 250 self.draw_path_open() 251 plt.sca(ax3) 252 self.draw_path_closed() 253 plt.show() 254 255 def main(self): 256 """ 257 main函数 258 :return: 259 """ 260 self.open = numpy.column_stack((self.open, self.start)) # 起点放入open 261 self.current_point = self.start # 起点放入当前点,作为父节点 262 # self.closed 263 ite = 1 264 while ite <= 2000: 265 266 # open列表为空,退出 267 if self.open.shape[1] == 0: 268 print('没有搜索到路径!') 269 return 270 271 last_point = self.current_point # 上一个目标点不断取得更新 272 273 while True: 274 275 index, self.current_point = self.min_f() # 判断open表中f值 276 print('检验第%s次当前点坐标' % ite) 277 print(self.current_point) 278 279 # 选取open表中最小f值的节点作为best,放入closed表 280 self.closed = numpy.c_[self.closed, self.current_point] 281 282 if self.current_point[0] == 15 and self.current_point[1] == 15: # 如果best是目标点,退出 283 print('搜索成功!') 284 return 285 286 tem_open_shape = self.child_point(self.current_point) # 生成子节点并判断数目 287 self.open = delete(self.open, index, axis=1) # 删除open中最优点 288 289 if tem_open_shape == 0: 290 self.closed = delete(self.closed, -1, axis=1) # 删除closed中不合理的点 291 self.taboo = numpy.c_[self.taboo, self.current_point] # 将撞墙点加入禁忌表 292 self.current_point = last_point 293 self.g = self.g + self.g_value_tem(self.current_point, last_point) 294 continue 295 else: 296 break 297 298 # print(self.open) 299 300 301 302 ite = ite+1 303 304 305 if __name__ == '__main__': 306 307 a1 = AStar() 308 a1.main() 309 a1.draw_three_axes()
转载于:https://www.cnblogs.com/yangmingustb/p/8761705.html