Dijistra和A star算法
Dijistra和A star算法在自动驾驶领域可用于路径的搜索,甚至在一定的场景下能用作轨迹的规划。
A star算法相当于是Dijistra算法的改进,在其基础上加上了绝对距离等判断条件,从而大大降低了路径搜索的范围,节约了算力。理解两个算法,我们要先从Dijistra算法开始。
1.Dijistra算法的思路
Dijistra算法的思路很简单,采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s。
然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点,然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。
算法的伪代码如下:
其中:
最小堆open:存储所有需要处理的节点
变量closed: 表示已经处理完的节点集
变量predecessors: 回溯最短路径上的已经访问过的节点
uCost:源节点到该点的距离
从下图可以大致理解一下Djistra的搜索过程:
假设一个从s到t的场景:
首先s可以到b和a,这是我们将其作为存储起来,这个时候从s到a的距离是大于从s到b的;因此再搜索b的下一步路径,将a保留存储。s到b再到c的距离是1.5还是小于s到a,因此继续从c向后搜索这时从s到b再到c再到d的距离大于从s到a的距离,因此从a再开始搜索,搜索一步后就到了目的地,整个算法的进程结束。
能力有限可能讲的不是很到位,大伙可以自行查阅资料,Dijistra算法还是比较好理解的。
2.A star算法的改进
A*算法其实就是在Dijistra算法加了一个欧氏距离或者曼哈顿距离的判断。
欧式距离:
曼哈顿距离:
其实现伪代码如图:
可以看出A*算法相对于Dijistra主要加上了绝对距离h,这个h代表的是当前点到终点的欧式距离或者曼哈顿距离。可以理解为如果我在搜索时,这个距离过大,那么这个点之后的路径将不在进行搜索。我们可以对这个欧式距离设定一定的权重,来使得A*算法探索路径的能力和得到最优路径的能力有一个很好的平衡。
3.两种算法的实现和结果对比
Dijistra算法:
"""
Grid based Dijkstra planning
"""import matplotlib.pyplot as plt
import mathshow_animation = Trueclass Dijkstra:def __init__(self, ox, oy, resolution, robot_radius):"""Initialize map for a star planningox: x position list of Obstacles [m]oy: y position list of Obstacles [m]resolution: grid resolution [m]rr: robot radius[m]"""self.min_x = Noneself.min_y = Noneself.max_x = Noneself.max_y = Noneself.x_width = Noneself.y_width = Noneself.obstacle_map = Noneself.resolution = resolutionself.robot_radius = robot_radiusself.calc_obstacle_map(ox, oy)self.motion = self.get_motion_model()class Node:def __init__(self, x, y, cost, parent_index):self.x = x # index of gridself.y = y # index of gridself.cost = costself.parent_index = parent_index # index of previous Nodedef __str__(self):return str(self.x) + "," + str(self.y) + "," + str(self.cost) + "," + str(self.parent_index)def planning(self, sx, sy, gx, gy):"""dijkstra path searchinput:s_x: start x position [m]s_y: start y position [m]gx: goal x position [m]gx: goal x position [m]output:rx: x position list of the final pathry: y position list of the final path"""
#设置起点start_node = self.Node(self.calc_xy_index(sx, self.min_x),self.calc_xy_index(sy, self.min_y), 0.0, -1)
#设置目标终点goal_node = self.Node(self.calc_xy_index(gx, self.min_x),self.calc_xy_index(gy, self.min_y), 0.0, -1)
#初始化两个字典open_set, closed_set = dict(), dict()
#给字典放元素,先放进去起始点open_set[self.calc_index(start_node)] = start_nodewhile 1:
#搜索最小的键值对c_id = min(open_set, key=lambda o: open_set[o].cost)
#得到当前可以保存的路径current = open_set[c_id]
#在图像中得到展示# show graphif show_animation: # pragma: no coverplt.plot(self.calc_position(current.x, self.min_x),self.calc_position(current.y, self.min_y), "xc")# for stopping simulation with the esc key.plt.gcf().canvas.mpl_connect('key_release_event',lambda event: [exit(0) if event.key == 'escape' else None])if len(closed_set.keys()) % 10 == 0:plt.pause(0.001)
#如果x,y已经等于目标点if current.x == goal_node.x and current.y == goal_node.y:print("Find goal")goal_node.parent_index = current.parent_indexgoal_node.cost = current.costbreak# Remove the item from the open setdel open_set[c_id]# Add it to the closed setclosed_set[c_id] = current# expand search grid based on motion modelfor move_x, move_y, move_cost in self.motion:node = self.Node(current.x + move_x,current.y + move_y,current.cost + move_cost, c_id)n_id = self.calc_index(node)if n_id in closed_set:continueif not self.verify_node(node):continueif n_id not in open_set:open_set[n_id] = node # Discover a new nodeelse:if open_set[n_id].cost >= node.cost:# This path is the best until now. record it!open_set[n_id] = noderx, ry = self.calc_final_path(goal_node, closed_set)return rx, rydef calc_final_path(self, goal_node, closed_set):# generate final pathrx, ry = [self.calc_position(goal_node.x, self.min_x)], [self.calc_position(goal_node.y, self.min_y)]parent_index = goal_node.parent_indexwhile parent_index != -1:n = closed_set[parent_index]rx.append(self.calc_position(n.x, self.min_x))ry.append(self.calc_position(n.y, self.min_y))parent_index = n.parent_indexreturn rx, rydef calc_position(self, index, minp):pos = index * self.resolution + minpreturn posdef calc_xy_index(self, position, minp):return round((position - minp) / self.resolution)def calc_index(self, node):return (node.y - self.min_y) * self.x_width + (node.x - self.min_x)def verify_node(self, node):px = self.calc_position(node.x, self.min_x)py = self.calc_position(node.y, self.min_y)if px < self.min_x:return Falseif py < self.min_y:return Falseif px >= self.max_x:return Falseif py >= self.max_y:return Falseif self.obstacle_map[node.x][node.y]:return Falsereturn Truedef calc_obstacle_map(self, ox, oy):self.min_x = round(min(ox))self.min_y = round(min(oy))self.max_x = round(max(ox))self.max_y = round(max(oy))print("min_x:", self.min_x)print("min_y:", self.min_y)print("max_x:", self.max_x)print("max_y:", self.max_y)self.x_width = round((self.max_x - self.min_x) / self.resolution)self.y_width = round((self.max_y - self.min_y) / self.resolution)print("x_width:", self.x_width)print("y_width:", self.y_width)# obstacle map generationself.obstacle_map = [[False for _ in range(self.y_width)]for _ in range(self.x_width)]for ix in range(self.x_width):x = self.calc_position(ix, self.min_x)for iy in range(self.y_width):y = self.calc_position(iy, self.min_y)for iox, ioy in zip(ox, oy):d = math.hypot(iox - x, ioy - y)if d <= self.robot_radius:self.obstacle_map[ix][iy] = Truebreak@staticmethoddef get_motion_model():# dx, dy, costmotion = [[1, 0, 1],[0, 1, 1],[-1, 0, 1],[0, -1, 1],[-1, -1, math.sqrt(2)],[-1, 1, math.sqrt(2)],[1, -1, math.sqrt(2)],[1, 1, math.sqrt(2)]]return motiondef main():print(__file__ + " start!!")# start and goal positionsx =10.0 # [m]sy = 10.0 # [m]gx = 50.0 # [m]gy = 50.0 # [m]grid_size = 2.0 # [m]robot_radius = 1.0 # [m]# set obstacle positionsox, oy = [], []for i in range(-10, 60):ox.append(i)oy.append(-10.0)for i in range(-10, 60):ox.append(60.0)oy.append(i)for i in range(-10, 61):ox.append(i)oy.append(60.0)for i in range(-10, 61):ox.append(-10.0)oy.append(i)for i in range(-10, 40):ox.append(20.0)oy.append(i)for i in range(0, 40):ox.append(40.0)oy.append(60.0 - i)for i in range(40, 55):ox.append(i)oy.append(30)if show_animation: # pragma: no coverplt.plot(ox, oy, ".k")plt.plot(sx, sy, "og")plt.plot(gx, gy, "xb")plt.grid(True)plt.axis("equal")dijkstra = Dijkstra(ox, oy, grid_size, robot_radius)rx, ry = dijkstra.planning(sx, sy, gx, gy)if show_animation: # pragma: no coverplt.plot(rx, ry, "-r")plt.pause(0.01)plt.show()if __name__ == '__main__':main()
A*算法实现(定义一个欧式距离或曼哈顿距离函数)
"""
A* grid planning
"""
import numpy as np
import mathimport matplotlib.pyplot as pltshow_animation = Trueclass AStarPlanner:def __init__(self, ox, oy, resolution, rr):"""Initialize grid map for a star planningox: x position list of Obstacles [m]oy: y position list of Obstacles [m]resolution: grid resolution [m]rr: robot radius[m]"""self.resolution = resolutionself.rr = rrself.min_x, self.min_y = 0, 0self.max_x, self.max_y = 0, 0self.obstacle_map = Noneself.x_width, self.y_width = 0, 0self.motion = self.get_motion_model()self.calc_obstacle_map(ox, oy)class Node:def __init__(self, x, y, cost, parent_index):self.x = x # index of gridself.y = y # index of gridself.cost = costself.parent_index = parent_indexdef __str__(self):return str(self.x) + "," + str(self.y) + "," + str(self.cost) + "," + str(self.parent_index)def planning(self, sx, sy, gx, gy):"""A star path searchinput:s_x: start x position [m]s_y: start y position [m]gx: goal x position [m]gy: goal y position [m]output:rx: x position list of the final pathry: y position list of the final path"""# 设置起点start_node = self.Node(self.calc_xy_index(sx, self.min_x),self.calc_xy_index(sy, self.min_y), 0.0, -1)# 设置目标终点goal_node = self.Node(self.calc_xy_index(gx, self.min_x),self.calc_xy_index(gy, self.min_y), 0.0, -1)# 初始化两个字典open_set, closed_set = dict(), dict()# 给字典放元素,先放进去起始点open_set[self.calc_grid_index(start_node)] = start_node
#添加欧式距离或者曼哈顿距离while 1:# 搜索最小的键值对,前一项和Dijstra一样,后面一项是添加的距离#c_id = min(open_set, key=lambda o: open_set[o].cost)#c_id = min(open_set, key=lambda o: open_set[o].cost + self.calc_heuristic(open_set[o], goal_node))#c_id = min(open_set, key=lambda o: open_set[o].cost + self.calc_euclidean(open_set[o], goal_node))c_id = min(open_set, key=lambda o: open_set[o].cost + self.calc_manhattan(open_set[o], goal_node))# 得到当前可以保存的路径current = open_set[c_id]# 在图像中得到展示# show graphif show_animation: # pragma: no coverplt.plot(self.calc_grid_position(current.x, self.min_x),self.calc_grid_position(current.y, self.min_y), "xc")# for stopping simulation with the esc key.plt.gcf().canvas.mpl_connect('key_release_event',lambda event: [exit(0) if event.key == 'escape' else None])if len(closed_set.keys()) % 10 == 0:plt.pause(0.001)# 如果x,y已经等于目标点if current.x == goal_node.x and current.y == goal_node.y:print("Find goal")goal_node.parent_index = current.parent_indexgoal_node.cost = current.costbreak# Remove the item from the open setdel open_set[c_id]# Add it to the closed setclosed_set[c_id] = current# expand search grid based on motion modelfor move_x, move_y, move_cost in self.motion:node = self.Node(current.x + move_x,current.y + move_y,current.cost + move_cost, c_id)n_id = self.calc_grid_index(node)if n_id in closed_set:continueif not self.verify_node(node):continueif n_id not in open_set:open_set[n_id] = node # Discover a new nodeelse:if open_set[n_id].cost >= node.cost:# This path is the best until now. record it!open_set[n_id] = noderx, ry = self.calc_final_path(goal_node, closed_set)return rx, rydef calc_final_path(self, goal_node, closed_set):# generate final path,用于更新最后的环境rx, ry = [self.calc_grid_position(goal_node.x, self.min_x)], [self.calc_grid_position(goal_node.y, self.min_y)]parent_index = goal_node.parent_indexwhile parent_index != -1:n = closed_set[parent_index]rx.append(self.calc_grid_position(n.x, self.min_x))ry.append(self.calc_grid_position(n.y, self.min_y))parent_index = n.parent_indexreturn rx, ry@staticmethod#三角形距离计算# def calc_heuristic(n1, n2):# w = 5.0 # weight of heuristic# d = w * math.hypot(n1.x - n2.x, n1.y - n2.y)# return d#欧氏距离计算# def calc_euclidean(n1,n2):# w=1.0# d=w*pow(pow(n1.x-n2.x,2)+pow(n1.y-n2.y,2),0.5)# return d#曼哈顿距离计算def calc_manhattan(n1,n2):"""添加曼哈顿距离w:权重系数n1:x方向noden2:y方向noded:距离"""w = 5.0d = w*(abs(n1.x-n2.x)+abs(n1.y - n2.y))return ddef calc_grid_position(self, index, min_position):"""calc grid position:param index::param min_position::return:"""pos = index * self.resolution + min_positionreturn pos
#获取下标的函数def calc_xy_index(self, position, min_pos):return round((position - min_pos) / self.resolution)
#获取网格下标def calc_grid_index(self, node):return (node.y - self.min_y) * self.x_width + (node.x - self.min_x)
#判断存入节点选择def verify_node(self, node):px = self.calc_grid_position(node.x, self.min_x)py = self.calc_grid_position(node.y, self.min_y)if px < self.min_x:return Falseelif py < self.min_y:return Falseelif px >= self.max_x:return Falseelif py >= self.max_y:return False# collision checkif self.obstacle_map[node.x][node.y]:return Falsereturn True
#生成地图def calc_obstacle_map(self, ox, oy):self.min_x = round(min(ox))self.min_y = round(min(oy))self.max_x = round(max(ox))self.max_y = round(max(oy))print("min_x:", self.min_x)print("min_y:", self.min_y)print("max_x:", self.max_x)print("max_y:", self.max_y)self.x_width = round((self.max_x - self.min_x) / self.resolution)self.y_width = round((self.max_y - self.min_y) / self.resolution)print("x_width:", self.x_width)print("y_width:", self.y_width)# obstacle map generationself.obstacle_map = [[False for _ in range(self.y_width)]for _ in range(self.x_width)]for ix in range(self.x_width):x = self.calc_grid_position(ix, self.min_x)for iy in range(self.y_width):y = self.calc_grid_position(iy, self.min_y)for iox, ioy in zip(ox, oy):d = math.hypot(iox - x, ioy - y)if d <= self.rr:self.obstacle_map[ix][iy] = Truebreak
#规定可执行动作行为@staticmethoddef get_motion_model():# dx, dy, costmotion = [[1, 0, 1],[0, 1, 1],[-1, 0, 1],[0, -1, 1],[-1, -1, math.sqrt(2)],[-1, 1, math.sqrt(2)],[1, -1, math.sqrt(2)],[1, 1, math.sqrt(2)]]return motiondef main():print(__file__ + " start!!")# start and goal positionsx = 10.0 # [m]sy = 10.0 # [m]gx = 50.0 # [m]gy = 50.0 # [m]grid_size = 2.0 # [m]robot_radius = 1.0 # [m]# set obstacle positionsox, oy = [], []for i in range(-10, 60):ox.append(i)oy.append(-10.0)for i in range(-10, 60):ox.append(60.0)oy.append(i)for i in range(-10, 61):ox.append(i)oy.append(60.0)for i in range(-10, 61):ox.append(-10.0)oy.append(i)for i in range(-10, 40):ox.append(20.0)oy.append(i)for i in range(0, 40):ox.append(40.0)oy.append(60.0 - i)
# #添加一个障碍for i in range(40, 55):ox.append(i)oy.append(30)if show_animation: # pragma: no cover
#显示中文标题plt.rcParams['font.sans-serif'] = ['SimHei'] # 显示中文标签plt.rcParams['axes.unicode_minus'] = Falseplt.title("路径规划实验结果")
#设置坐标轴字体字号plt.yticks(fontproperties='Times New Roman', size=16)plt.xticks(fontproperties='Times New Roman', size=16)
#更改作图颜色plt.plot(ox, oy, ".r")plt.plot(sx, sy, "og")plt.plot(gx, gy, "xb")plt.grid(True)plt.axis("equal")a_star = AStarPlanner(ox, oy, grid_size, robot_radius)rx, ry = a_star.planning(sx, sy, gx, gy)if show_animation: # pragma: no coverplt.plot(rx, ry, "-b")plt.pause(0.001)plt.show()plt.show()if __name__ == '__main__':main()
4.实现效果
Dijistra算法:
A*算法:
Dijistra和A star算法相关推荐
- A star算法优化一
A*算法 求最优解 算法一直维护两个表: Open和Close 将起点S加入Open中 将所有S可到达的点(障碍物以及位于Close表中的点均看成不可达)加入到Open中.将起点从Open中删去,并加 ...
- 「游戏」寻路算法之A Star算法原理及实现
前言 自动寻路是在一些如MMORPG等类型游戏中常见的一种功能,其给了玩家良好的游戏体验,使得玩家在游戏过程中省去了大量游戏坐标点的记录以及长时间的键盘操作,不必记忆坐标,不必担心迷路,用最快捷的方法 ...
- A star算法的一些研究
A Star算法是一智能找最短路径算法(下面简称A算法), 与 Dijkstra算法相比,A算法访问的节点比较少,因此可以缩短搜索时间.他的算法思想是: 这里有公式f 最终路径长度f = 起点到该点的 ...
- 算法提高课-搜索-A*(A star)算法-AcWing 179. 八数码:A星算法求解
题目分析 来源:acwing 分析: A*算法是什么呢? A算法是一种bfs的变式,需要用到一个"估价函数",用来计算任意状态到目标状态所需代价的估计值.然后在搜索中,维护一个堆, ...
- A star算法优化二
本文目的是对A*寻路算法所生成的路径进行一些人性化的调整,使其看起来不至于太机械化.关于A*算法的原理与实现,读者可以阅读其他资料,这里不再详细阐述. 如何写估价函数 A*寻路算法本质上是一个有方向性 ...
- A star 算法 (Python)
A*算法作为快速的寻路算法,可以快速查询两点之间的最短路径,下面是代码 参考网址:https://github.com/xclu/Python-1/blob/master/graphs/a_star. ...
- A星(A*, A Star)算法详解
MulinB按:经典的智能寻路算法,一个老外写的很透彻很清晰,很容易让人理解神秘的A*算法.以下是一个中文翻译版. A*寻路初探 GameDev.net 作者: Patrick Lester 译者:P ...
- matlab中求极值extr,extr.m · A.Star算法组/snowland-itd-matlab - Gitee.com
%EXTR finds extrema and zero-crossings function [indmin, indmax, indzer] = extr(x,t) %输出为极值点的坐标序号 if ...
- 贪吃蛇AI算法中的A star寻路算法
A*寻路算法 在之前的贪吃蛇游戏比赛里,计算蛇吃食物路径时要用到寻路算法,于是就去了解了一下,以下是我的算法演化过程. 1.简单寻路–按图索骥 我一开始想到的方法就是最简单的:目标在哪个方位就往哪个方 ...
最新文章
- sqlalchemy安装以及使用_电子皮带秤的安装使用条件以及对输送机的要求
- 关于.h .cpp和inline的讨论
- Visual Studio 2008 可扩展性开发(九):总结篇
- spring开发_Spring+Struts2
- spark streaming 消费 kafka入门采坑解决过程
- python knnsearch_sklearn之KNN详解+GridSearchCV使用方法
- 软考-信息系统项目管理师-信息文档管理与配置管理
- Apache Flink 零基础入门(十五)Flink DataStream编程(如何自定义DataSource)
- Color the ball HDU - 1556 (线段树)
- UITableView的使用及代理方法
- RTX5 | 互斥量01 - 互斥量的使用
- python add_argument()用法解析
- Spring: @Import @ImportResource引入资源
- STM32F103学习笔记(7)——ISP串口下载程序
- 单片机蓝牙模块与手机蓝牙通信(3)
- 服务器内存只支持双路主板,壕到没朋友,支持双路18核CPU、16条内存、3路显卡的主板来了...
- webservice(草稿)
- OpenGl L13深度测试
- 仿微信公众号界面实现
- oracle 11g duplicate database基于备份复制数据库(五)