zoukankan      html  css  js  c++  java
  • 1.2

      1 # 版本1.220180409
      2 # 所有节点的g值并没有初始化为无穷大
      3 # 当两个子节点的f值一样时,程序选择最先搜索到的一个作为父节点加入closed
      4 # 对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径
      5 # 最后closed表中的节点很多,如何找出最优的一条路径
      6 # 撞墙之后产生较多的节点会加入closed表,此时开始删除closed表中不合理的节点,1.1版本的思路
      7 # 1.2版本思路,建立每一个节点的方向指针,指向f值最小的上个节点
      8 # 参考《无人驾驶概论》、《基于A*算法的移动机器人路径规划》王淼驰,《人工智能及应用》鲁斌
      9 
     10 
     11 import numpy
     12 from pylab import *
     13 import copy
     14 
     15 # 定义一个含有障碍物的20×20的栅格地图
     16 # 10表示可通行点
     17 # 0表示障碍物
     18 # 7表示起点
     19 # 5表示终点
     20 map_grid = numpy.full((20, 20), int(10), dtype=numpy.int8)
     21 # print(map_grid)
     22 map_grid[3, 3:8] = 0
     23 map_grid[3:10, 7] = 0
     24 map_grid[10, 3:8] = 0
     25 map_grid[17, 13:17] = 0
     26 map_grid[10:17, 13] = 0
     27 map_grid[10, 13:17] = 0
     28 map_grid[5, 2] = 7
     29 map_grid[15, 15] = 5
     30 # 画出定义的栅格地图
     31 
     32 # plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
     33 # plt.colorbar()
     34 # xlim(-1, 20)  # 设置x轴范围
     35 # ylim(-1, 20)  # 设置y轴范围
     36 # my_x_ticks = numpy.arange(0, 20, 1)
     37 # my_y_ticks = numpy.arange(0, 20, 1)
     38 # plt.xticks(my_x_ticks)
     39 # plt.yticks(my_y_ticks)
     40 # plt.grid(True)
     41 # plt.show()
     42 
     43 
     44 class AStar(object):
     45     """
     46     创建一个A*算法类
     47     """
     48 
     49     def __init__(self):
     50         """
     51         初始化
     52         """
     53         self.f = 0
     54         self.g = 0
     55         self.last_point = numpy.array([])
     56         self.current_point = numpy.array([])  # 当前目标点不断取得更新
     57         self.open = numpy.array([[], []])  # 先创建一个空的open表
     58         self.closed = numpy.array([[], []])  # 先创建一个空的closed表
     59         # self.taboo = numpy.array([[], []])  # 创建一个禁忌表,用于放置不再搜索的点
     60         self.start = numpy.array([5, 2])  # 起点坐标
     61         self.goal = numpy.array([15, 15])  # 终点坐标
     62         self.record_direction = numpy.array([[], [], [], []])  # 记录坐标点和方向
     63         self.best_path_array = numpy.array([[], []])  # 回溯路径表
     64         self.point_f = numpy.array([[], [], []])  # 记录每个点的f值
     65 
     66     def h_value_tem(self, cur_p):
     67         """
     68         计算拓展节点和终点的h值
     69         :param cur_p:子搜索节点坐标
     70         :return:
     71         """
     72         h = (cur_p[0] - 15) ** 2 + (cur_p[1] - 15) ** 2
     73         h = numpy.sqrt(h)  # 计算h
     74         return h
     75 
     76     def g_value(self):
     77         """
     78         累计的g值
     79         :param x:
     80         :param y:
     81         :return:
     82         """
     83         self.g = self.g + self.g_value_tem(self.current_point, self.last_point)
     84 
     85     def g_value_tem(self, chl_p, cu_p):
     86         """
     87         计算拓展节点和父节点的g值
     88         其实也可以直接用1或者1.414代替
     89         :param chl_p:子节点坐标
     90         :param cu_p:父节点坐标,也就是self.current_point
     91         :return:返回子节点到父节点的g值,但不是全局g值
     92         """
     93         g1 = cu_p[0] - chl_p[0]
     94         g2 = cu_p[1] - chl_p[1]
     95         g = g1 ** 2 + g2 ** 2
     96         g = numpy.sqrt(g)
     97         return g
     98 
     99     def f_value_tem(self, chl_p, cu_p):
    100         """
    101         求出的是临时g值和h值的和,还需加上累计g值得到全局f值
    102         :param chl_p: 父节点坐标
    103         :param cu_p: 子节点坐标
    104         :return:
    105         """
    106         f = self.g_value_tem(chl_p, cu_p) + self.h_value_tem(cu_p)
    107         return f
    108 
    109     def min_f(self):
    110         """
    111         找出open中f值最小的节点坐标,记录为current_point
    112         :return:返回open表中最小值的位置索引和在map_grid中的坐标
    113         对撞墙后的处理方式是,随机选择一个方向进行搜索
    114         并且将open列表清零,不然一直是死循环
    115         这种处理方式以后待改进!!!--1.1
    116         1.2更新:
    117         建立方向指针
    118         """
    119         tem_f = []  # 创建一个记录f值的临时列表
    120         for i in range(self.open.shape[1]):
    121             # 计算拓展节点的全局f值
    122             f_value = self.f_value_tem(self.current_point, self.open[:, i]) + self.g
    123             tem_f.append(f_value)
    124         index = tem_f.index(min(tem_f))  # 返回最小值索引
    125         location = self.open[:, index]  # 返回最小值坐标
    126         print('打印位置索引和地图坐标:')
    127         print(index, location)
    128         return index, location
    129 
    130     def child_point(self, x):
    131         """
    132         拓展的子节点坐标
    133         :param x: 父节点坐标
    134         :return: 子节点存入open表,返回值是每一次拓展出的子节点数目,用于撞墙判断
    135         当搜索的节点撞墙后,如果不加处理,会陷入死循环
    136         """
    137         # tem_open = numpy.array([[], []])  # 统计拓展节点的临时数组
    138         # tem_open_shape = 0  # 统计临时数组的长度
    139         # 开始遍历周围8个节点
    140         for j in range(-1, 2, 1):
    141             for q in range(-1, 2, 1):
    142                 if j == 0 and q == 0:  # 搜索到父节点去掉
    143                     continue
    144                 m = numpy.array([x[0] + j, x[1] + q])
    145 
    146                 # print(map_grid[int(x[0] + j), int(x[1] + q)])
    147                 if map_grid[int(m[0]), int(m[1])] == 0:  # 搜索到障碍物去掉
    148                     continue
    149                 if m[0] < 0 or m[0] > 19 or m[1] < 0 or m[1] > 19:  # 搜索点出了边界去掉
    150                     continue
    151 
    152                 self.direction(x, m)  # 每产生一个子节点,记录一次方向
    153                 # 在closed表中,则去掉搜索点
    154                 b = self.judge_location(m, self.closed)
    155                 if b == 1:
    156                     numpy.delete(self.record_direction, -1, axis=1)
    157                     continue
    158 
    159                 # 在open表中,则去掉搜索点,但是需要更新方向指针和self.g值
    160                 # 而且只需要计算并更新self.g即可,此时建立一个比较g值的函数
    161                 a = self.judge_location(m, self.open)
    162                 if a == 1:
    163                     # 此时删除上面记录的方向并重新记录
    164                     numpy.delete(self.record_direction, -1, axis=1)
    165                     # self.direction(self.last_point, m)
    166 
    167                     continue
    168 
    169                 # # 在taboo表中,则去掉搜索点
    170                 # c = self.judge_location(x, j, q, self.taboo)
    171                 # if c == 1:
    172                 #     continue
    173 
    174                 # tem_open = numpy.c_[tem_open, m]  #
    175 
    176                 # tem_open_shape = tem_open.shape[1]  # 求出tem_open的长度
    177 
    178                 self.open = numpy.c_[self.open, m]  # 搜索出的子节点加入open
    179                 # print('打印第一次循环后的open:')
    180                 # print(self.open)
    181         # return tem_open_shape
    182 
    183     def judge_location(self, m, list_co):
    184         """
    185         判断拓展点是否在open表或者closed表中
    186         :return:
    187         """
    188         jud = 0
    189         for i in range(list_co.shape[1]):
    190 
    191             if m[0] == list_co[0, i] and m[1] == list_co[1, i]:
    192 
    193                 jud = jud + 1
    194             else:
    195                 jud = jud
    196         # if a != 0:
    197         #     continue
    198         return jud
    199 
    200     def direction(self, father_point, son_point):
    201         """
    202         建立每一个节点的方向,便于在closed表中选出最佳路径
    203         非常重要的一步,不然画出的图像参考1.1版本
    204         x记录子节点和父节点的x轴变化
    205         y记录子节点和父节点的y轴变化
    206         如(01)表示子节点在父节点的方向上变化0和1
    207         :return:
    208         """
    209         x = son_point[0] - father_point[0]
    210         y = son_point[1] - father_point[1]
    211         xy = [son_point[0], son_point[1], x, y]
    212         self.record_direction = numpy.c_[self.record_direction, xy]
    213         # return x, y
    214 
    215     # def g_compare(self, father, son, son_grandson):
    216     #     """
    217     #     g值比较函数
    218     #     :param father:
    219     #     :param son:
    220     #     :param son_grandson:
    221     #     :return:
    222     #     """
    223     #     pass
    224 
    225     def path_backtrace(self):
    226         """
    227         回溯closed表中的最短路径
    228         :return:
    229         """
    230         best_path = [15, 15]  # 回溯路径的初始化
    231         self.best_path_array = numpy.array([[15], [15]])
    232         j = 0
    233         while j <= self.record_direction.shape[1]:
    234             for i in range(self.record_direction.shape[1]):
    235                 if best_path[0] == self.record_direction[0][i] and best_path[1] == self.record_direction[1][i]:
    236                     x = self.record_direction[0][i]-self.record_direction[2][i]
    237                     y = self.record_direction[1][i]-self.record_direction[3][i]
    238                     best_path = [x, y]
    239                     self.best_path_array = numpy.c_[self.best_path_array, best_path]
    240                     break  # 如果已经找到,退出本轮循环,减少耗时
    241                 else:
    242                     continue
    243             j = j+1
    244         # return best_path_array
    245 
    246     def main(self):
    247         """
    248         main函数
    249         :return:
    250         """
    251         self.open = numpy.column_stack((self.open, self.start))  # 起点放入open
    252         self.current_point = self.start  # 起点放入当前点,作为父节点
    253         # self.closed
    254         ite = 1
    255         while ite <= 200:
    256 
    257                 # open列表为空,退出
    258                 if self.open.shape[1] == 0:
    259                     print('没有搜索到路径!')
    260                     return
    261 
    262                 self.last_point = self.current_point  # 上一个目标点不断取得更新
    263 
    264                 index, self.current_point = self.min_f()  # 判断open表中f值
    265                 print('检验第%s次当前点坐标' % ite)
    266                 print(self.current_point)
    267 
    268                 # 选取open表中最小f值的节点作为best,放入closed表
    269                 self.closed = numpy.c_[self.closed, self.current_point]
    270 
    271                 if self.current_point[0] == 15 and self.current_point[1] == 15:  # 如果best是目标点,退出
    272                     print('搜索成功!')
    273                     return
    274 
    275                 # tem_open_shape = self.child_point(self.current_point)  # 生成子节点并判断数目
    276                 self.child_point(self.current_point)  # 生成子节点并判断数目
    277 
    278                 self.open = delete(self.open, index, axis=1)  # 删除open中最优点
    279 
    280                 # if tem_open_shape == 0:
    281                 #     self.closed = delete(self.closed, -1, axis=1)  # 删除closed中不合理的点
    282                 #     self.taboo = numpy.c_[self.taboo, self.current_point]  # 将撞墙点加入禁忌表
    283                 #     self.current_point = last_point
    284                 #
    285                 #     continue
    286 
    287                 self.g_value()
    288 
    289                 # print(self.open)
    290 
    291                 ite = ite+1
    292 
    293 
    294 class MAP(object):
    295     """
    296     画出地图
    297     """
    298     def draw_init_map(self):
    299         """
    300         画出起点终点图
    301         :return:
    302         """
    303         plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    304         # plt.colorbar()
    305         xlim(-1, 20)  # 设置x轴范围
    306         ylim(-1, 20)  # 设置y轴范围
    307         my_x_ticks = numpy.arange(0, 20, 1)
    308         my_y_ticks = numpy.arange(0, 20, 1)
    309         plt.xticks(my_x_ticks)
    310         plt.yticks(my_y_ticks)
    311         plt.grid(True)
    312         # plt.show()
    313 
    314     def draw_path_open(self, a):
    315         """
    316         画出open表中的坐标点图
    317         :return:
    318         """
    319         map_open = copy.deepcopy(map_grid)
    320         for i in range(a.closed.shape[1]):
    321             x = a.closed[:, i]
    322 
    323             map_open[int(x[0]), int(x[1])] = 1
    324 
    325         plt.imshow(map_open, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    326         # plt.colorbar()
    327         xlim(-1, 20)  # 设置x轴范围
    328         ylim(-1, 20)  # 设置y轴范围
    329         my_x_ticks = numpy.arange(0, 20, 1)
    330         my_y_ticks = numpy.arange(0, 20, 1)
    331         plt.xticks(my_x_ticks)
    332         plt.yticks(my_y_ticks)
    333         plt.grid(True)
    334         # plt.show()
    335 
    336     def draw_path_closed(self, a):
    337         """
    338         画出closed表中的坐标点图
    339         :return:
    340         """
    341         print('打印closed长度:')
    342         print(a.closed.shape[1])
    343         map_closed = copy.deepcopy(map_grid)
    344         for i in range(a.closed.shape[1]):
    345             x = a.closed[:, i]
    346 
    347             map_closed[int(x[0]), int(x[1])] = 5
    348 
    349         plt.imshow(map_closed, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    350         # plt.colorbar()
    351         xlim(-1, 20)  # 设置x轴范围
    352         ylim(-1, 20)  # 设置y轴范围
    353         my_x_ticks = numpy.arange(0, 20, 1)
    354         my_y_ticks = numpy.arange(0, 20, 1)
    355         plt.xticks(my_x_ticks)
    356         plt.yticks(my_y_ticks)
    357         plt.grid(True)
    358         # plt.show()
    359 
    360     def draw_direction_point(self, a):
    361         """
    362         从终点开始,根据记录的方向信息,画出搜索的路径图
    363         :return:
    364         """
    365         print('打印direction长度:')
    366         print(a.record_direction.shape[1])
    367         map_direction = copy.deepcopy(map_grid)
    368         for i in range(a.best_path_array.shape[1]):
    369             x = a.best_path_array[:, i]
    370 
    371             map_direction[int(x[0]), int(x[1])] = 6
    372 
    373         plt.imshow(map_direction, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    374         # plt.colorbar()
    375         xlim(-1, 20)  # 设置x轴范围
    376         ylim(-1, 20)  # 设置y轴范围
    377         my_x_ticks = numpy.arange(0, 20, 1)
    378         my_y_ticks = numpy.arange(0, 20, 1)
    379         plt.xticks(my_x_ticks)
    380         plt.yticks(my_y_ticks)
    381         plt.grid(True)
    382 
    383     def draw_three_axes(self, a):
    384         """
    385         将三张图画在一个figure中
    386         :return:
    387         """
    388         plt.figure()
    389         ax1 = plt.subplot(221)
    390 
    391         ax2 = plt.subplot(222)
    392         ax3 = plt.subplot(223)
    393         ax4 = plt.subplot(224)
    394         plt.sca(ax1)
    395         self.draw_init_map()
    396         plt.sca(ax2)
    397         self.draw_path_open(a)
    398         plt.sca(ax3)
    399         self.draw_path_closed(a)
    400         plt.sca(ax4)
    401         self.draw_direction_point(a)
    402 
    403         plt.show()
    404 
    405 
    406 if __name__ == '__main__':
    407 
    408     a1 = AStar()
    409     a1.main()
    410     a1.path_backtrace()
    411     m1 = MAP()
    412     m1.draw_three_axes(a1)
  • 相关阅读:
    repair table
    rmtree函数
    alias 新的命令='原命令 -选项/参数'。举例说明,alias l=‘ls -lsh' 将重新定义 ls 命令,现在只需输入 l 就可以列目录了。
    MySQL DATE_SUB() 函数
    freebsd开启root远程登陆
    nbtscan ip地址
    FreeBSD 安裝 wget
    genlist -s 192.168.21.*
    /pentest/enumeration/0trace
    CSS的margin属性:详解margin属性
  • 原文地址:https://www.cnblogs.com/yangmingustb/p/8783278.html
Copyright © 2011-2022 走看看