使用 Python 的自主机器人算法 Dijkstra 路径规划

news2024/11/16 15:37:14

迪杰斯特拉算法

  • Dijkstra 算法是一种广泛使用的算法,用于查找图中的最短路径。
  • 它通过从起始节点迭代选择成本最小的节点来探索搜索空间。
  • Dijkstra 算法计算到达每个节点的成本,并在找到更短路径时更新成本。
  • 它会持续下去,直到到达目标节点或探索完所有可到达的节点。

公式

  • math.hypot()

  • math.sqrt()

import matplotlib.pyplot as plt
import math

class Dijkstra:
    def __init__(self, ox, oy, resolution, robot_radius):
        """
        Initialize map for a star planning

        ox: x position list of Obstacles [m]
        oy: y position list of Obstacles [m]
        resolution: grid resolution [m]
        rr: robot radius[m]
        """

        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  # index of grid
            self.y = y  # index of grid
            self.cost = cost
            # self.grid = grid
            self.parent_index = parent_index  # index of previous Node

        def __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 search

        input:
            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 path
            ry: 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_node

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

            # show graph
            if show_animation == True # pragma: no cover
                plt.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)

            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

            ''' Remove the item on open set '''
            del open_set[c_id]
            
            ''' Add it to the closet set '''
            closed_set[c_id] = current

            ''' expand search grid based on motion model'''
            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  # Discover a new node
                else:
                    if open_set[n_id].cost >= node.cost:
                        # This path is the best until now. record it!
                        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):
        # generate final course
        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.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 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):

        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 generation
        self.obstacle_map = []
        ''' Iterate over the x, y indices '''
        for _ in range(self.x_width):
            row = []
            for _ in range(self.y_width):
                row.append(False)
            self.obstacle_map.append(row)
        ''' Iterate over x indices '''
        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)
                ''' Iterate over obstacles' x and y coordinates '''
                for iox, ioy in zip(ox, oy):
                    ''' Calculate Euclidean distance between obstacle and current point '''
                    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 model for obstacle '''
        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():
    print(__file__ + " start!!")

    # start and goal position
    sx = 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 positions
    ox, oy = [], []
    for i in range(60):
        ox.append(i)
        oy.append(0.0)
    for i in range(60):
        ox.append(60.0)
        oy.append(i)
    for i in range(61):
        ox.append(i)
        oy.append(60.0)
    for i in range(61):
        ox.append(0.0)
        oy.append(i)
    for i in range(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 = True # pragma: no cover
        plt.plot(ox, oy, ".k")
        plt.plot(sx, sy, "og")
        plt.plot(gx, gy, "xb")
        plt.grid(True)
        plt.axis("equal")
        plt.show()
    else:
        show_animation = False
       
    dijkstra = Dijkstra(ox, oy, grid_size, robot_radius)
    rx, ry = dijkstra.planning(sx, sy, gx, gy)

    if show_animation = True  # pragma: no cover
        plt.plot(rx, ry, "-r")
        plt.grid(True)
        plt.pause(0.01)
        plt.show()
    else:
        show_animation = False

if __name__ == '__main__':
    main()

Djikstra算法结果

Dijkstra算法优点

  • 最佳解决方案:Dijkstra 算法保证找到起始节点和图中所有其他节点之间的最短路径,前提是该图具有非负边权重。这种最优性确保机器人采用最有效的路线到达目的地。
  • 完整性:Dijkstra 算法是完整的,这意味着如果存在解决方案,它总是会找到解决方案如果从起始节点到目标节点存在有效路径,Dijkstra 算法就会发现它。
  • 可扩展性:Dijkstra 算法在具有适度数量的节点和边的图上表现良好。其时间复杂度为O((V + E) log V),其中V是节点数,E是边数。这使得它适用于许多现实世界的路径规划场景。
  • 灵活性:Dijkstra 算法可以应用于各种图表示,包括有向图和无向图。它还可以处理加权图,其中不同的边具有不同的成本或距离
  • 增量更新:Dijkstra 算法允许对图进行增量更新。如果环境发生变化或出现新的障碍物,算法可以重新运行以找到更新的最短路径,而无需从头开始。
  • 广泛的适用性:Dijkstra 的算法广泛应用于各种应用,包括机器人、导航系统、网络路由和物流。其多功能性和经过验证的有效性使其成为自主机器人路径规划的热门选择

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1047710.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Esp32-cam在无外部 PIR 传感器情况下实现运动检测(一)

关于无需外部 PIR 传感器的 Esp32-cam 运动检测的世界最佳指南。从 A 到 Z 您需要了解的一切 无需外部 PIR 传感器的 Esp32-cam 运动检测一直是该网站上最热门的话题。 几个月来我付出了很大的努力来完善本指南,但它始终感觉不够好。 所以我继续工作。现在我感到很满足。 现在…

ElasticSearch - 基于 拼音分词器 和 IK分词器 模拟实现“百度”搜索框自动补全功能

目录 一、自动补全 1.1、效果说明 1.2、安装拼音分词器 1.3、自定义分词器 1.3.1、为什么要自定义分词器 1.3.2、分词器的构成 1.3.3、自定义分词器 1.3.4、面临的问题和解决办法 问题 解决方案 1.4、completion suggester 查询 1.4.1、基本概念和语法 1.4.2、示例…

【c语言中数组和指针的联系】

C语言中的数组和指针之间存在紧密的联系&#xff0c;因为数组名本质上就是指向数组首元素的指针。这种联系使得在处理数组时可以像处理指针一样操作&#xff0c;同时也使得数组和指针可以互相转换。 下面详细说明数组和指针之间的联系&#xff0c;并提供一些示例来演示这种联系…

多线程入门知识点及代码详解及相关面试八股文

多线程详解及相关面试八股文 多线程 线程概述 * 多线程&#xff1a;进程&#xff1a;当前正在运行的程序&#xff0c;一个应用程序在内存中的执行区域线程&#xff1a;进程中的一个执行控制单元&#xff0c;执行路径* 一个进程可以有一个线程&#xff0c;也可以有多个线程* …

B+tree 与 B-tree区别

原理:分批次的将磁盘块加载进内存中进行检索,若查到数据,则直接返回,若查不到,则释放内存,并重新加载同等数据量的索引进内存,重新遍历 结构: 数据 向下的指针 指向数据的指针 特点: 1&#xff0c;节点排序 2 .一个节点了可以存多个元索&#xff0c;多个元索也排序了 结构: 数…

vscode 打开后 默认terminal power shell 报错 名为“.C”的驱动器不存在。

这是 默认terminal power shell 打开报的错 Test-Path : 找不到驱动器。名为“.C”的驱动器不存在。 所在位置 C:\Users\HUAWEI\Documents\WindowsPowerShell\profile.ps1:4 字符: 5 If (Test-Path "C:\Users\HUAWEI\AppData\Local\Temp\_MEI319962\Scripts\ ... …

Java列表查询Long(id)到前端转换出错

Java列表查询Long到前端转换出错 问题描述排查思路思路一&#xff1a;SQL问题思路二&#xff1a;Long类型转换出错 解决方法 问题描述 做了一个列表查询功能&#xff0c;本来不应该有啥大问题的&#xff0c;但是往往事与愿违。 诶&#xff0c;你越觉得不可能出问题&#xff0c…

深入探讨 Presto 中的缓存

【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 Presto是一种流行的开源分布式SQL引擎&#xff0c;使组织能够在多个数据源上大规模运行交互式分析查询。缓存是一种典型的提高 Presto 查询性能的优化技术。它为 Prest…

网络安全——黑客——自学

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01;&#xff01;&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队…

信创办公–基于WPS的PPT最佳实践系列 (将文字转换为SmartArt)

信创办公–基于WPS的PPT最佳实践系列 &#xff08;将文字转换为SmartArt&#xff09; 目录 应用背景操作步骤第一种&#xff1a;将已有文字列表转换生成SmartArt形状。第二种&#xff1a;直接插入SmartArt形状。 应用背景 如何清晰有效的呈现文字信息&#xff1f;通常使用视觉效…

BM4 合并两个排序的链表

思路&#xff1a;先选择最小的作为Head&#xff0c;每次从两个队列中取最小的挂到Head后面&#xff0c;如果一个合并空&#xff0c;后面直接挂。此外判断几个为空链表的情况 /*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) : val(x), next(nullp…

排序算法一 直接插入排序,希尔排序,直接选择排序,堆排序和冒泡排序

什么是排序 排序&#xff1a;排序就是使一串记录,按照其中的某个或者某些关键字的大小,递增或递减的排列起来的操作 稳定性: 假定在排序序列中,存在多个具有相同的关键字记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,存在r[i] r[j],且r[i]在 r[j] 之前&#xf…

Oracle-通过BBED强制打开数据库

前言: 在通过备份进行数据恢复时&#xff0c;经常会遇到由于备份的不完整&#xff0c;特别是归档日志的缺失&#xff0c;导致虽然数据文件已经顺利恢复&#xff0c;但是数据文件的恢复时间点没有完全一致或者数据文件的fuzzy的状态不一致&#xff0c;从而数据库无法正常的打开&…

三维模型3DTile格式轻量化压缩处理重难点分析

三维模型3DTile格式轻量化压缩处理重难点分析 在对三维模型3DTile格式进行轻量化压缩处理的过程中&#xff0c;存在一些重要而又困难的问题需要解决。以下是几个主要的重难点&#xff1a; 1、压缩率和模型质量之间的平衡&#xff1a;压缩技术的目标是尽可能地减少数据大小&…

用CRM系统提高客户转化率

影响客户转化的因素有很多&#xff0c;例如潜在客户是否真实有效、销售跟进策略、销售跟进流程和及时性等。不少企业正在使用CRM销售管理系统&#xff0c;下面说说CRM系统如何提高提高客户转化率&#xff1f; 1、甄别高质量获客渠道 CRM系统可以对获取的客户线索进行分析&…

premire 两个视频叠加显示

1 背景视频放到 v1 视频轨道 前视 视频 放到 v2 视频轨道 2 调整 前视 视频颜色参数 2.1 曲线 亮度 暗度 调整 黑白鲜明对比 2.2 基本校正 对比度 白色 黑色 饱和度 曝光 3 效果控件 -> 混合模式 -> 滤色 4 视频人物大小调整 位置调整

基于微信小程序的宠物交易商城系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言运行环境说明用户的主要功能有&#xff1a;管理员的主要功能有&#xff1a;具体实现截图详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考论文参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌…

电设备工厂的BOM管理系统

一、什么是BOM管理系统&#xff1f; BOM管理系统是一种软件工具&#xff0c;用于管理和跟踪产品的物料清单。它包括产品的组成结构、零部件的规格、数量和关联信息。BOM管理系统提供了一个集中存储和更新BOM数据的平台&#xff0c;并确保所有相关部门和团队都能够访问最新的BO…

2023工博会 | 上海添力网络营销公司 | 助力工业品线上推广

2023年9月23日&#xff0c;为期五天的工博会正式落下帷幕。本届工博会不仅有数量&#xff0c;更加有质量&#xff0c;国内外企业纷纷拿出看家本领&#xff0c;围绕着“绿色低碳”、“数字化转型”、“数字经济”、“科技创新”、“智能制造”等主题进行推陈出新。 本次工博会也…

未来预判:跨境电商全球化的下一个步伐

在当今全球化的时代&#xff0c;跨境电商已经成为了国际贸易和全球商业的主要驱动力之一。跨境电商不仅仅改变了消费者的购物方式&#xff0c;也对传统零售业产生了深远的影响。 然而&#xff0c;随着技术和市场的不断发展&#xff0c;跨境电商也在不断演化&#xff0c;其全球…