zoukankan      html  css  js  c++  java
  • A*算法基于栅格地图的全局路径规划2.0,python

      1 # 版本1.320180411
      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 map_grid[3, 3:8] = 0
     22 map_grid[3:10, 7] = 0
     23 map_grid[10, 3:8] = 0
     24 map_grid[17, 13:17] = 0
     25 map_grid[10:17, 13] = 0
     26 map_grid[10, 13:17] = 0
     27 map_grid[5, 2] = 7
     28 map_grid[15, 15] = 5
     29 
     30 
     31 class AStar(object):
     32     """
     33     创建一个A*算法类
     34     """
     35 
     36     def __init__(self):
     37         """
     38         初始化
     39         """
     40         # self.g = 0  # g初始化为0
     41         self.start = numpy.array([5, 2])  # 起点坐标
     42         self.goal = numpy.array([15, 15])  # 终点坐标
     43         self.open = numpy.array([[], [], [], [], [], []])  # 先创建一个空的open表, 记录坐标,方向,g值,f值
     44         self.closed = numpy.array([[], [], [], [], [], []])  # 先创建一个空的closed表
     45         self.best_path_array = numpy.array([[], []])  # 回溯路径表
     46 
     47     def h_value_tem(self, son_p):
     48         """
     49         计算拓展节点和终点的h值
     50         :param son_p:子搜索节点坐标
     51         :return:
     52         """
     53         h = (son_p[0] - self.goal[0]) ** 2 + (son_p[1] - self.goal[1]) ** 2
     54         h = numpy.sqrt(h)  # 计算h
     55         return h
     56 
     57     # def g_value_tem(self, son_p, father_p):
     58     #     """
     59     #     计算拓展节点和父节点的g值
     60     #     其实也可以直接用1或者1.414代替
     61     #     :param son_p:子节点坐标
     62     #     :param father_p:父节点坐标,也就是self.current_point
     63     #     :return:返回子节点到父节点的g值,但不是全局g值
     64     #     """
     65     #     g1 = father_p[0] - son_p[0]
     66     #     g2 = father_p[1] - son_p[1]
     67     #     g = g1 ** 2 + g2 ** 2
     68     #     g = numpy.sqrt(g)
     69     #     return g
     70 
     71     def g_accumulation(self, son_point, father_point):
     72         """
     73         累计的g值
     74         :return:
     75         """
     76         g1 = father_point[0] - son_point[0]
     77         g2 = father_point[1] - son_point[1]
     78         g = g1 ** 2 + g2 ** 2
     79         g = numpy.sqrt(g) + father_point[4]  # 加上累计的g值
     80         return g
     81 
     82     def f_value_tem(self, son_p, father_p):
     83         """
     84         求出的是临时g值和h值加上累计g值得到全局f值
     85         :param father_p: 父节点坐标
     86         :param son_p: 子节点坐标
     87         :return:f
     88         """
     89         f = self.g_accumulation(son_p, father_p) + self.h_value_tem(son_p)
     90         return f
     91 
     92     def child_point(self, x):
     93         """
     94         拓展的子节点坐标
     95         :param x: 父节点坐标
     96         :return: 子节点存入open表,返回值是每一次拓展出的子节点数目,用于撞墙判断
     97         当搜索的节点撞墙后,如果不加处理,会陷入死循环
     98         """
     99         # 开始遍历周围8个节点
    100         for j in range(-1, 2, 1):
    101             for q in range(-1, 2, 1):
    102 
    103                 if j == 0 and q == 0:  # 搜索到父节点去掉
    104                     continue
    105                 m = [x[0] + j, x[1] + q]
    106                 print(m)
    107                 if m[0] < 0 or m[0] > 19 or m[1] < 0 or m[1] > 19:  # 搜索点出了边界去掉
    108                     continue
    109 
    110                 if map_grid[int(m[0]), int(m[1])] == 0:  # 搜索到障碍物去掉
    111                     continue
    112 
    113 
    114 
    115                 record_g = self.g_accumulation(m, x)
    116                 record_f = self.f_value_tem(m, x)  # 计算每一个节点的f值
    117 
    118                 x_direction, y_direction = self.direction(x, m)  # 每产生一个子节点,记录一次方向
    119 
    120                 para = [m[0], m[1], x_direction, y_direction, record_g, record_f]  # 将参数汇总一下
    121                 print(para)
    122 
    123                 # 在open表中,则去掉搜索点,但是需要更新方向指针和self.g值
    124                 # 而且只需要计算并更新self.g即可,此时建立一个比较g值的函数
    125                 a, index = self.judge_location(m, self.open)
    126                 if a == 1:
    127                     # 说明open中已经存在这个点
    128 
    129                     if record_f <= self.open[5][index]:
    130                         self.open[5][index] = record_f
    131                         self.open[4][index] = record_g
    132                         self.open[3][index] = y_direction
    133                         self.open[2][index] = x_direction
    134 
    135                     continue
    136 
    137                 # 在closed表中,则去掉搜索点
    138                 b, index2 = self.judge_location(m, self.closed)
    139                 if b == 1:
    140 
    141                     if record_f <= self.closed[5][index2]:
    142                         self.closed[5][index2] = record_f
    143                         self.closed[4][index2] = record_g
    144                         self.closed[3][index2] = y_direction
    145                         self.closed[2][index2] = x_direction
    146                         self.closed = numpy.delete(self.closed, index2, axis=1)
    147                         self.open = numpy.c_[self.open, para]
    148                     continue
    149 
    150                 self.open = numpy.c_[self.open, para]  # 参数添加到open中
    151                 print(self.open)
    152 
    153     def judge_location(self, m, list_co):
    154         """
    155         判断拓展点是否在open表或者closed表中
    156         :return:返回判断是否存在,和如果存在,那么存在的位置索引
    157         """
    158         jud = 0
    159         index = 0
    160         for i in range(list_co.shape[1]):
    161 
    162             if m[0] == list_co[0, i] and m[1] == list_co[1, i]:
    163 
    164                 jud = jud + 1
    165 
    166                 index = i
    167                 break
    168             else:
    169                 jud = jud
    170         # if a != 0:
    171         #     continue
    172         return jud, index
    173 
    174     def direction(self, father_point, son_point):
    175         """
    176         建立每一个节点的方向,便于在closed表中选出最佳路径
    177         非常重要的一步,不然画出的图像参考1.1版本
    178         x记录子节点和父节点的x轴变化
    179         y记录子节点和父节点的y轴变化
    180         如(01)表示子节点在父节点的方向上变化0和1
    181         :return:
    182         """
    183         x = son_point[0] - father_point[0]
    184         y = son_point[1] - father_point[1]
    185         return x, y
    186 
    187     def path_backtrace(self):
    188         """
    189         回溯closed表中的最短路径
    190         :return:
    191         """
    192         best_path = [15, 15]  # 回溯路径的初始化
    193         self.best_path_array = numpy.array([[15], [15]])
    194         j = 0
    195         while j <= self.closed.shape[1]:
    196             for i in range(self.closed.shape[1]):
    197                 if best_path[0] == self.closed[0][i] and best_path[1] == self.closed[1][i]:
    198                     x = self.closed[0][i]-self.closed[2][i]
    199                     y = self.closed[1][i]-self.closed[3][i]
    200                     best_path = [x, y]
    201                     self.best_path_array = numpy.c_[self.best_path_array, best_path]
    202                     break  # 如果已经找到,退出本轮循环,减少耗时
    203                 else:
    204                     continue
    205             j = j+1
    206         # return best_path_array
    207 
    208     def main(self):
    209         """
    210         main函数
    211         :return:
    212         """
    213         best = self.start  # 起点放入当前点,作为父节点
    214         h0 = self.h_value_tem(best)
    215         init_open = [best[0], best[1], 0, 0, 0, h0]  # 将方向初始化为(00),g_init=0,f值初始化h0
    216         self.open = numpy.column_stack((self.open, init_open))  # 起点放入open,open初始化
    217 
    218         ite = 1  # 设置迭代次数小于200,防止程序出错无限循环
    219         while ite <= 1000:
    220 
    221                 # open列表为空,退出
    222                 if self.open.shape[1] == 0:
    223                     print('没有搜索到路径!')
    224                     return
    225 
    226                 self.open = self.open.T[numpy.lexsort(self.open)].T  # open表中最后一行排序(联合排序)
    227 
    228                 # 选取open表中最小f值的节点作为best,放入closed表
    229 
    230                 best = self.open[:, 0]
    231                 print('检验第%s次当前点坐标*******************' % ite)
    232                 print(best)
    233                 self.closed = numpy.c_[self.closed, best]
    234 
    235                 if best[0] == 15 and best[1] == 15:  # 如果best是目标点,退出
    236                     print('搜索成功!')
    237                     return
    238 
    239                 self.child_point(best)  # 生成子节点并判断数目
    240                 print(self.open)
    241                 self.open = numpy.delete(self.open, 0, axis=1)  # 删除open中最优点
    242 
    243                 # print(self.open)
    244 
    245                 ite = ite+1
    246 
    247 
    248 class MAP(object):
    249     """
    250     画出地图
    251     """
    252     def draw_init_map(self):
    253         """
    254         画出起点终点图
    255         :return:
    256         """
    257         plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    258         # plt.colorbar()
    259         xlim(-1, 20)  # 设置x轴范围
    260         ylim(-1, 20)  # 设置y轴范围
    261         my_x_ticks = numpy.arange(0, 20, 1)
    262         my_y_ticks = numpy.arange(0, 20, 1)
    263         plt.xticks(my_x_ticks)
    264         plt.yticks(my_y_ticks)
    265         plt.grid(True)
    266         # plt.show()
    267 
    268     def draw_path_open(self, a):
    269         """
    270         画出open表中的坐标点图
    271         :return:
    272         """
    273         map_open = copy.deepcopy(map_grid)
    274         for i in range(a.closed.shape[1]):
    275             x = a.closed[:, i]
    276 
    277             map_open[int(x[0]), int(x[1])] = 1
    278 
    279         plt.imshow(map_open, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    280         # plt.colorbar()
    281         xlim(-1, 20)  # 设置x轴范围
    282         ylim(-1, 20)  # 设置y轴范围
    283         my_x_ticks = numpy.arange(0, 20, 1)
    284         my_y_ticks = numpy.arange(0, 20, 1)
    285         plt.xticks(my_x_ticks)
    286         plt.yticks(my_y_ticks)
    287         plt.grid(True)
    288         # plt.show()
    289 
    290     def draw_path_closed(self, a):
    291         """
    292         画出closed表中的坐标点图
    293         :return:
    294         """
    295         print('打印closed长度:')
    296         print(a.closed.shape[1])
    297         map_closed = copy.deepcopy(map_grid)
    298         for i in range(a.closed.shape[1]):
    299             x = a.closed[:, i]
    300 
    301             map_closed[int(x[0]), int(x[1])] = 5
    302 
    303         plt.imshow(map_closed, 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_direction_point(self, a):
    315         """
    316         从终点开始,根据记录的方向信息,画出搜索的路径图
    317         :return:
    318         """
    319         print('打印direction长度:')
    320         print(a.best_path_array.shape[1])
    321         map_direction = copy.deepcopy(map_grid)
    322         for i in range(a.best_path_array.shape[1]):
    323             x = a.best_path_array[:, i]
    324 
    325             map_direction[int(x[0]), int(x[1])] = 6
    326 
    327         plt.imshow(map_direction, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
    328         # plt.colorbar()
    329         xlim(-1, 20)  # 设置x轴范围
    330         ylim(-1, 20)  # 设置y轴范围
    331         my_x_ticks = numpy.arange(0, 20, 1)
    332         my_y_ticks = numpy.arange(0, 20, 1)
    333         plt.xticks(my_x_ticks)
    334         plt.yticks(my_y_ticks)
    335         plt.grid(True)
    336 
    337     def draw_three_axes(self, a):
    338         """
    339         将三张图画在一个figure中
    340         :return:
    341         """
    342         plt.figure()
    343         ax1 = plt.subplot(221)
    344 
    345         ax2 = plt.subplot(222)
    346         ax3 = plt.subplot(223)
    347         ax4 = plt.subplot(224)
    348         plt.sca(ax1)
    349         self.draw_init_map()
    350         plt.sca(ax2)
    351         self.draw_path_open(a)
    352         plt.sca(ax3)
    353         self.draw_path_closed(a)
    354         plt.sca(ax4)
    355         self.draw_direction_point(a)
    356 
    357         plt.show()
    358 
    359 
    360 if __name__ == '__main__':
    361 
    362     a1 = AStar()
    363     a1.main()
    364     a1.path_backtrace()
    365     m1 = MAP()
    366     m1.draw_three_axes(a1)
  • 相关阅读:
    Java:如何正确地使用异常详解
    操作系统:基于页面置换算法的缓存原理详解(下)
    php 分页
    修改css
    /Home/Tpl/Equipment/rangeIndex.html 里调用魔板
    logstash 处理各种时间格式
    MySQL 没有索引 锁全表
    nginx 配置多个主机
    RR 插入不影响
    根据div 标签 查看数组@class=modulwrap 下面的/table/tbody/tr/td
  • 原文地址:https://www.cnblogs.com/yangmingustb/p/8823677.html
Copyright © 2011-2022 走看看