# 所有节点的g值并没有初始化为无穷大
# 当两个子节点的f值一样时,程序选择最先搜索到的一个作为父节点加入closed
# 对相同数值的不同对待,导致不同版本的A*算法找到等长的不同路径
# 最后closed表中的节点很多,如何找出最优的一条路径
# 撞墙之后产生较多的节点会加入closed表,此时开始删除closed表中不合理的节点,1.1版本的思路
# 1.2版本思路,建立每一个节点的方向指针,指向f值最小的上个节点
# 参考《无人驾驶概论》、《基于A*算法的移动机器人路径规划》王淼驰,《人工智能及应用》鲁斌 import numpy
from pylab import *
import copy # 定义一个含有障碍物的20×20的栅格地图
# 10表示可通行点
# 0表示障碍物
# 7表示起点
# 5表示终点
map_grid = numpy.full((20, 20), int(10), dtype=numpy.int8)
map_grid[3, 3:8] = 0
map_grid[3:10, 7] = 0
map_grid[10, 3:8] = 0
map_grid[17, 13:17] = 0
map_grid[10:17, 13] = 0
map_grid[10, 13:17] = 0
map_grid[5, 2] = 7
map_grid[15, 15] = 5 class AStar(object):
"""
创建一个A*算法类
""" def __init__(self):
"""
初始化
"""
# self.g = 0 # g初始化为0
self.start = numpy.array([5, 2]) # 起点坐标
self.goal = numpy.array([15, 15]) # 终点坐标
self.open = numpy.array([[], [], [], [], [], []]) # 先创建一个空的open表, 记录坐标,方向,g值,f值
self.closed = numpy.array([[], [], [], [], [], []]) # 先创建一个空的closed表
self.best_path_array = numpy.array([[], []]) # 回溯路径表 def h_value_tem(self, son_p):
"""
计算拓展节点和终点的h值
:param son_p:子搜索节点坐标
:return:
"""
h = (son_p[0] - self.goal[0]) ** 2 + (son_p[1] - self.goal[1]) ** 2
h = numpy.sqrt(h) # 计算h
return h # def g_value_tem(self, son_p, father_p):
# """
# 计算拓展节点和父节点的g值
# 其实也可以直接用1或者1.414代替
# :param son_p:子节点坐标
# :param father_p:父节点坐标,也就是self.current_point
# :return:返回子节点到父节点的g值,但不是全局g值
# """
# g1 = father_p[0] - son_p[0]
# g2 = father_p[1] - son_p[1]
# g = g1 ** 2 + g2 ** 2
# g = numpy.sqrt(g)
# return g def g_accumulation(self, son_point, father_point):
"""
累计的g值
:return:
"""
g1 = father_point[0] - son_point[0]
g2 = father_point[1] - son_point[1]
g = g1 ** 2 + g2 ** 2
g = numpy.sqrt(g) + father_point[4] # 加上累计的g值
return g def f_value_tem(self, son_p, father_p):
"""
求出的是临时g值和h值加上累计g值得到全局f值
:param father_p: 父节点坐标
:param son_p: 子节点坐标
:return:f
"""
f = self.g_accumulation(son_p, father_p) + self.h_value_tem(son_p)
return f def child_point(self, x):
"""
拓展的子节点坐标
:param x: 父节点坐标
:return: 子节点存入open表,返回值是每一次拓展出的子节点数目,用于撞墙判断
当搜索的节点撞墙后,如果不加处理,会陷入死循环
"""
# 开始遍历周围8个节点
for j in range(-1, 2, 1):
for q in range(-1, 2, 1): if j == 0 and q == 0: # 搜索到父节点去掉
continue
m = [x[0] + j, x[1] + q]
print(m)
if m[0] < 0 or m[0] > 19 or m[1] < 0 or m[1] > 19: # 搜索点出了边界去掉
continue if map_grid[int(m[0]), int(m[1])] == 0: # 搜索到障碍物去掉
continue record_g = self.g_accumulation(m, x)
record_f = self.f_value_tem(m, x) # 计算每一个节点的f值 x_direction, y_direction = self.direction(x, m) # 每产生一个子节点,记录一次方向 para = [m[0], m[1], x_direction, y_direction, record_g, record_f] # 将参数汇总一下
print(para) # 在open表中,则去掉搜索点,但是需要更新方向指针和self.g值
# 而且只需要计算并更新self.g即可,此时建立一个比较g值的函数
a, index = self.judge_location(m, self.open)
if a == 1:
# 说明open中已经存在这个点 if record_f <= self.open[5][index]:
self.open[5][index] = record_f
self.open[4][index] = record_g
self.open[3][index] = y_direction
self.open[2][index] = x_direction continue # 在closed表中,则去掉搜索点
b, index2 = self.judge_location(m, self.closed)
if b == 1: if record_f <= self.closed[5][index2]:
self.closed[5][index2] = record_f
self.closed[4][index2] = record_g
self.closed[3][index2] = y_direction
self.closed[2][index2] = x_direction
self.closed = numpy.delete(self.closed, index2, axis=1)
self.open = numpy.c_[self.open, para]
continue self.open = numpy.c_[self.open, para] # 参数添加到open中
print(self.open) def judge_location(self, m, list_co):
"""
判断拓展点是否在open表或者closed表中
:return:返回判断是否存在,和如果存在,那么存在的位置索引
"""
jud = 0
index = 0
for i in range(list_co.shape[1]): if m[0] == list_co[0, i] and m[1] == list_co[1, i]: jud = jud + 1 index = i
break
else:
jud = jud
# if a != 0:
# continue
return jud, index def direction(self, father_point, son_point):
"""
建立每一个节点的方向,便于在closed表中选出最佳路径
非常重要的一步,不然画出的图像参考1.1版本
x记录子节点和父节点的x轴变化
y记录子节点和父节点的y轴变化
如(0,1)表示子节点在父节点的方向上变化0和1
:return:
"""
x = son_point[0] - father_point[0]
y = son_point[1] - father_point[1]
return x, y def path_backtrace(self):
"""
回溯closed表中的最短路径
:return:
"""
best_path = [15, 15] # 回溯路径的初始化
self.best_path_array = numpy.array([[15], [15]])
j = 0
while j <= self.closed.shape[1]:
for i in range(self.closed.shape[1]):
if best_path[0] == self.closed[0][i] and best_path[1] == self.closed[1][i]:
x = self.closed[0][i]-self.closed[2][i]
y = self.closed[1][i]-self.closed[3][i]
best_path = [x, y]
self.best_path_array = numpy.c_[self.best_path_array, best_path]
break # 如果已经找到,退出本轮循环,减少耗时
else:
continue
j = j+1
# return best_path_array def main(self):
"""
main函数
:return:
"""
best = self.start # 起点放入当前点,作为父节点
h0 = self.h_value_tem(best)
init_open = [best[0], best[1], 0, 0, 0, h0] # 将方向初始化为(0,0),g_init=0,f值初始化h0
self.open = numpy.column_stack((self.open, init_open)) # 起点放入open,open初始化 ite = 1 # 设置迭代次数小于200,防止程序出错无限循环
while ite <= 1000: # open列表为空,退出
if self.open.shape[1] == 0:
print('没有搜索到路径!')
return self.open = self.open.T[numpy.lexsort(self.open)].T # open表中最后一行排序(联合排序) # 选取open表中最小f值的节点作为best,放入closed表 best = self.open[:, 0]
print('检验第%s次当前点坐标*******************' % ite)
print(best)
self.closed = numpy.c_[self.closed, best] if best[0] == 15 and best[1] == 15: # 如果best是目标点,退出
print('搜索成功!')
return self.child_point(best) # 生成子节点并判断数目
print(self.open)
self.open = numpy.delete(self.open, 0, axis=1) # 删除open中最优点 # print(self.open) ite = ite+1 class MAP(object):
"""
画出地图
"""
def draw_init_map(self):
"""
画出起点终点图
:return:
"""
plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
# plt.colorbar()
xlim(-1, 20) # 设置x轴范围
ylim(-1, 20) # 设置y轴范围
my_x_ticks = numpy.arange(0, 20, 1)
my_y_ticks = numpy.arange(0, 20, 1)
plt.xticks(my_x_ticks)
plt.yticks(my_y_ticks)
plt.grid(True)
# plt.show() def draw_path_open(self, a):
"""
画出open表中的坐标点图
:return:
"""
map_open = copy.deepcopy(map_grid)
for i in range(a.closed.shape[1]):
x = a.closed[:, i] map_open[int(x[0]), int(x[1])] = 1 plt.imshow(map_open, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
# plt.colorbar()
xlim(-1, 20) # 设置x轴范围
ylim(-1, 20) # 设置y轴范围
my_x_ticks = numpy.arange(0, 20, 1)
my_y_ticks = numpy.arange(0, 20, 1)
plt.xticks(my_x_ticks)
plt.yticks(my_y_ticks)
plt.grid(True)
# plt.show() def draw_path_closed(self, a):
"""
画出closed表中的坐标点图
:return:
"""
print('打印closed长度:')
print(a.closed.shape[1])
map_closed = copy.deepcopy(map_grid)
for i in range(a.closed.shape[1]):
x = a.closed[:, i] map_closed[int(x[0]), int(x[1])] = 5 plt.imshow(map_closed, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
# plt.colorbar()
xlim(-1, 20) # 设置x轴范围
ylim(-1, 20) # 设置y轴范围
my_x_ticks = numpy.arange(0, 20, 1)
my_y_ticks = numpy.arange(0, 20, 1)
plt.xticks(my_x_ticks)
plt.yticks(my_y_ticks)
plt.grid(True)
# plt.show() def draw_direction_point(self, a):
"""
从终点开始,根据记录的方向信息,画出搜索的路径图
:return:
"""
print('打印direction长度:')
print(a.best_path_array.shape[1])
map_direction = copy.deepcopy(map_grid)
for i in range(a.best_path_array.shape[1]):
x = a.best_path_array[:, i] map_direction[int(x[0]), int(x[1])] = 6 plt.imshow(map_direction, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
# plt.colorbar()
xlim(-1, 20) # 设置x轴范围
ylim(-1, 20) # 设置y轴范围
my_x_ticks = numpy.arange(0, 20, 1)
my_y_ticks = numpy.arange(0, 20, 1)
plt.xticks(my_x_ticks)
plt.yticks(my_y_ticks)
plt.grid(True) def draw_three_axes(self, a):
"""
将三张图画在一个figure中
:return:
"""
plt.figure()
ax1 = plt.subplot(221) ax2 = plt.subplot(222)
ax3 = plt.subplot(223)
ax4 = plt.subplot(224)
plt.sca(ax1)
self.draw_init_map()
plt.sca(ax2)
self.draw_path_open(a)
plt.sca(ax3)
self.draw_path_closed(a)
plt.sca(ax4)
self.draw_direction_point(a) plt.show() if __name__ == '__main__': a1 = AStar()
a1.main()
a1.path_backtrace()
m1 = MAP()
m1.draw_three_axes(a1)

A*算法基于栅格地图的全局路径规划

[python] A*算法基于栅格地图的全局路径规划的更多相关文章

  1. 全局路径规划算法Dijkstra(迪杰斯特拉算法)- matlab

    参考博客链接:https://www.cnblogs.com/kex1n/p/4178782.html Dijkstra是常用的全局路径规划算法,其本质上是一个最短路径寻优算法.算法的详细介绍参考上述 ...

  2. ROS源码解读(二)--全局路径规划

    博客转载自:https://blog.csdn.net/xmy306538517/article/details/79032324 ROS中,机器人全局路径规划默认使用的是navfn包 ,move_b ...

  3. customizable route planning 工业界地图产品的路径规划

    https://www.microsoft.com/en-us/research/publication/customizable-route-planning/?from=http%3A%2F%2F ...

  4. move_base的全局路径规划代码研究

    algorithmn parameter code 主要是以下三个函数 计算所有的可行点 怎么计算一个点的可行点 从可行点中计算路径path todo algorithmn 算法的解释 Dijkstr ...

  5. 利用Matlab快速绘制栅格地图

    代码演示 % 基于栅格地图的机器人路径规划算法 % 第1节:利用Matlab快速绘制栅格地图 clc clear close all %% 构建颜色MAP图 cmap = [1 1 1; ... % ...

  6. ROS机器人路径规划介绍--全局规划

    ROS机器人路径规划算法主要包括2个部分:1)全局路径规划算法:2)局部路径规划算法: 一.全局路径规划 global planner ROS 的navigation官方功能包提供了三种全局路径规划器 ...

  7. DWA局部路径规划算法论文阅读:The Dynamic Window Approach to Collision Avoidance。

    DWA(动态窗口)算法是用于局部路径规划的算法,已经在ROS中实现,在move_base堆栈中:http://wiki.ros.org/dwa_local_planner DWA算法第一次提出应该是1 ...

  8. 【路径规划】 Optimal Trajectory Generation for Dynamic Street Scenarios in a Frenet Frame (附python代码实例)

    参考与前言 2010年,论文 Optimal Trajectory Generation for Dynamic Street Scenarios in a Frenet Frame 地址:https ...

  9. 如何用HMS Core位置和地图服务实现附近地点路径规划功能

    日常出行中,路径规划是很重要的部分.用户想要去往某个地点,获取到该地点的所有路径,再根据预估出行时间自行选择合适的路线,极大方便出行.平时生活中也存在大量使用场景,在出行类App中,根据乘客的目的地可 ...

随机推荐

  1. javascript算法-单链表

    链表相比数组更具灵活性和扩展性.主要有节点数据以及指向节点的指针所构成. 链表中节点的实现[元素和指针]: let Node = function( element ){ this.element = ...

  2. JavaScript String常用方法和属性

    在JavaScript中,字符串是不可变的,如果使用索引对字符串进行修改浏览器不会报错,但也没有任何效果.JavaScript提供的这些方法不会修改原有字符串的内容,而是返回一个新的期望的字符串. 一 ...

  3. SAP FI配置步骤

    http://blog.sina.com.cn/s/blog_8eda1a620100uwzj.html No. 配置对象 事务代码 配置内容 路径 备注 1 定义公司 OX15 企业结构>定义 ...

  4. HashMap的resize方法中尾部遍历出现死循环问题 Tail Traversing (多线程)

    一.背景介绍: 在看HashMap源码是看到了resize()的源代码,当时发现在将old链表中引用数据复制到新的链表中时,发现复制过程中时,源码是进行了反序,此时是允许反序存储的,同时这样设计的效率 ...

  5. Android为TV端助力 计算每个目录剩余空间丶总空间以及SD卡剩余空间

    ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...

  6. Ubuntu添加新分区

    1.查看分区 ~$ sudo fdisk -l 2.添加分区 ~$ fdisk /dev/sda 3.输入m查看帮助 ~$ m 4.输入n新建分区,即添加分区 ~$ n 这里会出现设置分区大小 5.输 ...

  7. Android IPC机制(五)用Socket实现跨进程聊天程序

    1.Socket简介 Socket也称作“套接字“,是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信.它分为流式套接字和数据包套接 ...

  8. NFV一种提高进程消息高可用性的方法

    1.背景及概述 1.1 背景 在做NFV的过程中,由于控制面进程被放置到不同虚拟机中,中间可能跨越路由器,因此期间网络有可能震荡,这种情况下保证高可用性就必须有保护机制,本文正是在这种背景下的考虑. ...

  9. Spring(mvc)思维导图

    spring mvc简介与运行原理 Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器 ...

  10. C#-hello world(二)

     1.C# 程序构成 命名空间(Namespace) 一个 class Class 方法 Class 属性 一个 Main 方法 语句(Statements)和 表达式(Expressions) 注释 ...