Python 实现 Dijkstar 路径规划算法

🎏Dijstar 最短路径算法(用于计算起始点到最终点的最短路径),一般采用的是贪心算法策略=.=🎃

原理可以参考

图解 Open list 和 close list

Python 实现 Dijkstar 路径规划算法
Python 实现 Dijkstar 路径规划算法
Python 实现 Dijkstar 路径规划算法
Python 实现 Dijkstar 路径规划算法

; 环境

(Terminal) 需要预先安装两个库 matplotlib 和 math

pip3 install matplotlib
pip3 install math

可以运行 Python 的环境

程序思路

代码片段

  • 开始点和终止点的初始化,设置 x y z
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_node
  • 获取最小点节点,并且更新和替换掉当前的节点位置
c_id = min(open_set, key=lambda o: open_set[o].cost)
            current = open_set[c_id]

Python 实现 Dijkstar 路径规划算法
  • 机器人在栅格地图内的移动模型(3×3)
def get_motion_model():

    motion = [[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 motion

其中[第一位,第二位,第三位]表示在 x 方向和 y 方向移动的步数,第三位可以理解成为损失代价

  • 当前节点的 g(n) 运算,以及 cost
node = self.Node(current.x + move_x,
                 current.y + move_y,
                 current.cost + move_cost, c_id)

两个 List

设置的两个 list(Open list,Closed list)

  1. 将起点放到 Open list 当中
  2. 将循环的判断条件为 open list 是否为空
  3. 在循环体内不断的寻找 g(n) 的最小点,并且将其加入到 Closed list 当中
  4. 判断当前节点是否为终点,如果不是重点,继续遍历不在 Closed list 中的相邻的节点,与 Open list 中比较g(n),将值最小的存入到 Closed list 当中

总代码

"""
Dijkstra 栅格地图导航
author: Shen Mingsheng(@gcusms)
"""

import matplotlib.pyplot as plt
import math

show_animation = True

class Dijkstra:

    def __init__(self, ox, oy, resolution, robot_radius):
"""
        初始化地图

        ox: x 方向上的障碍物
        oy: y 方向上的障碍物
        resolution: 可以理解为栅格之间的步长(分辨率)
        rr: 机器人的半径
"""

        self.min_x = None
        self.min_y = None
        self.max_x = None
        self.max_y = None
        self.x_width = None
        self.y_width = None
        self.obstacle_map = None

        self.resolution = resolution
        self.robot_radius = robot_radius
        self.calc_obstacle_map(ox, oy)
        self.motion = self.get_motion_model()

    class Node:
        def __init__(self, x, y, cost, parent_index):
            self.x = x
            self.y = y
            self.cost = cost
            self.parent_index = parent_index

        def __str__(self):
            return str(self.x) + "," + str(self.y) + "," + str(
                self.cost) + "," + str(self.parent_index)

    def planning(self, sx, sy, gx, gy):

        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_node

        while 1:
            c_id = min(open_set, key=lambda o: open_set[o].cost)
            current = open_set[c_id]

            if show_animation:
                plt.plot(self.calc_position(current.x, self.min_x),
                         self.calc_position(current.y, self.min_y), "xc")

                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)

            if current.x == goal_node.x and current.y == goal_node.y:
                print("Find goal")
                goal_node.parent_index = current.parent_index
                goal_node.cost = current.cost
                break

            del open_set[c_id]

            closed_set[c_id] = current

            for 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:
                    continue

                if not self.verify_node(node):
                    continue

                if n_id not in open_set:
                    open_set[n_id] = node
                else:
                    if open_set[n_id].cost >= node.cost:

                        open_set[n_id] = node

        rx, ry = self.calc_final_path(goal_node, closed_set)

        return rx, ry

    def calc_final_path(self, goal_node, closed_set):

        rx, ry = [self.calc_position(goal_node.x, self.min_x)], [
            self.calc_position(goal_node.y, self.min_y)]
        parent_index = goal_node.parent_index
        while 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_index

        return rx, ry

    def calc_position(self, index, minp):
        pos = index * self.resolution + minp
        return pos

    def calc_xy_index(self, position, minp):
        return round((position - minp) / self.resolution)

    def calc_index(self, node):
        return node.y * self.x_width + node.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 False
        if py < self.min_y:
            return False
        if px >= self.max_x:
            return False
        if py >= self.max_y:
            return False

        if self.obstacle_map[node.x][node.y]:
            return False

        return True

    def calc_obstacle_map(self, ox, oy):
        ''' 第1步: 构建栅格地图 '''
        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)

        self.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] = True
                        break

    @staticmethod
    def get_motion_model():

        motion = [[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 motion

def main():

    sx = -5.0
    sy = -5.0
    gx = 50.0
    gy = 50.0
    grid_size = 2.0
    robot_radius = 1.0

    ox, 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)

    if show_animation:
        plt.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:
        plt.plot(rx, ry, "-r")
        plt.pause(0.01)
        plt.show()

if __name__ == '__main__':
    main()

路径规划算法

Python 实现 Dijkstar 路径规划算法

🌸🌸🌸🌸🌸完结撒花🌸🌸🌸🌸🌸🌸🌸🌸

🌈🌈Redamancy🌈🌈

Original: https://blog.csdn.net/Msyusheng/article/details/127599810
Author: splendid.rain生
Title: Python 实现 Dijkstar 路径规划算法

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/769777/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球