Astar路径规划算法复现-python实现

news2024/11/29 11:30:02
# -*- coding: utf-8 -*-
"""
Created on Fri May 24 09:04:23 2024


"""

import os
import sys
import math
import heapq
import matplotlib.pyplot as plt
import time

'''
传统A*算法
'''


class Astar:
    '''
    AStar set the cost + heuristics as the priority
    AStar将成本+启发式设置为优先级
    '''

    def __init__(self, s_start, s_goal, heuristic_type, xI, xG):
        self.s_start = s_start
        self.s_goal = s_goal
        self.heuristic_type = heuristic_type
        self.u_set = [(-1, 0), (0, 1), (1, 0), (0, -1)]

        # self.obs = self.obs_map()  # 障碍物位置
        self.Open = []  # 优先级序列,open集合
        self.Closed = []  # 相邻点集合,访问visited序列
        self.parent = dict()  # 相邻父节点
        self.g = dict()  # 成本
        self.x_range = 51  # 设置背景大小
        self.y_range = 51

        self.xI, self.xG = xI, xG
        self.obs = self.obs_map()

    def animation(self, path_l, visited_l, name, path_color='g'):

        # 绘制地图基础元素
        obs_x = [x[0] for x in self.obs]
        obs_y = [x[1] for x in self.obs]
        plt.plot(self.xI[0], self.xI[1], "bs")  # 起点
        plt.plot(self.xG[0], self.xG[1], "gs")  # 终点
        plt.plot(obs_x, obs_y, "sk")  # 障碍物
        plt.title(name)
        plt.axis("equal")

        # 移除起点和终点于visited_l列表中,避免它们被标记为已访问点
        visited_l = [node for node in visited_l if node != self.xI and node != self.xG]

        # 绘制所有已访问节点
        for x in visited_l:
            plt.plot(x[0], x[1], color='gray', marker='o')

        # 绘制路径
        path_x = [point[0] for point in path_l]
        path_y = [point[1] for point in path_l]
        plt.plot(path_x, path_y, linewidth=3, color=path_color)

        # 显示最终图形
        plt.show(block=True)

    def obs_map(self):
        """
        Initialize obstacles' positions
        :return: map of obstacles
        初始化障碍物位置
        返回:障碍物
        """
        x = 51
        y = 31
        self.obs = set()

        # 绘制边界
        self.obs.update((i, 0) for i in range(x))

        self.obs.update((i, y - 1) for i in range(x))

        self.obs.update((0, i) for i in range(y))

        self.obs.update((x - 1, i) for i in range(y))

        # 给出障碍物坐标集1
        self.obs.update((i, 15) for i in range(10, 21))
        self.obs.update((20, i) for i in range(15))

        # 给出障碍物坐标集2
        self.obs.update((30, i) for i in range(15, 30))

        # 给出障碍物坐标集3
        self.obs.update((40, i) for i in range(16))

        return self.obs

    def searching(self):
        """
        A_star Searching.
        :return: path, visited order

        Astart搜索,返回路径、访问集,
        """

        self.parent[self.s_start] = self.s_start  # 初始化 起始父节点中只有起点。
        self.g[self.s_start] = 0  # 初始代价为0
        self.g[self.s_goal] = math.inf  # 目标节点代价为无穷大

        # 将元素(self.f_value(self.s_start), self.s_start)插入到Open堆中,
        # 并保持堆的性质(最小堆中父节点的值总是小于或等于其子节点的值))
        # 这行代码的意思是:计算起始节点s_start的评估值f_value(self.s_start),
        # 然后将这对值(f_value, self.s_start)作为一个元组插入到self.Open这个最小堆中。
        # 这样做的目的是在诸如A*搜索算法等需要高效管理待探索节点的场景下,
        # 确保每次可以从堆顶(也就是当前评估值最小的节点)取出下一个待处理的节点。
        # 这对于寻找最短路径、最小成本解决方案等问题非常有用。
        heapq.heappush(self.Open, (self.f_value(self.s_start), self.s_start))

        while self.Open:
            # heappop会取出栈顶元素并将原始数据从堆栈中删除
            # 在这个例子中,heappop返回的元素假设是一个包含两个元素的元组,
            # 但代码中只关心第二个元素(实际的数据,比如一个状态、节点或其他任何类型的数据),
            # 所以用_占位符丢弃了第一个元素(通常是评估值或优先级),而把第二个元素赋值给了变量s
            _, s_current = heapq.heappop(self.Open)  # s_current存储的是当前位置的坐标
            # print('栈顶元素为{0}'.format(s_current))

            self.Closed.append(s_current)

            if s_current == self.s_goal:  # 迭代停止条件,判断出栈顶元素是否为目标点,如果为目标点,则退出
                break
            # 如果不是,更新该点附近的代价值
            # get_neighbor为获取附近点的坐标
            for s_next in self.get_neighbor(s_current):
                new_cost = self.g[s_current] + self.cost(s_current, s_next)

                if s_next not in self.g:
                    self.g[s_next] = math.inf

                if new_cost < self.g[s_next]:
                    self.g[s_next] = new_cost
                    self.parent[s_next] = s_current
                    # heappush入栈时需要存储的该点的代价值的计算方式为
                    heapq.heappush(self.Open, (self.f_value(s_next), s_next))

        # self.animation(self.extract_path(self.parent), self.Closed, "A*")
        return self.extract_path(self.parent), self.Closed

    def get_neighbor(self, s_current):
        """

        :param s_current:
        :return: 相邻点集合
        """
        return [(s_current[0] + u[0], s_current[1] + u[1]) for u in self.u_set]

    def cost(self, s_current, s_next):
        """
        :param s_current 表示当前点
        :param s_next 表示相邻点
        :return 若与障碍物无冲突,则范围欧式距离成本,否则为无穷大成本
        计算当前点与相邻点的距离成本
        """
        # 判断是否与障碍物冲突
        if self.is_collision(s_current, s_next):
            return math.inf
        # 这里返回欧式距离成本
        return math.hypot(s_next[0] - s_current[0], s_next[1] - s_current[1])

    def is_collision(self, s_current, s_next):
        """
            check if the line segment (s_start, s_end) is collision.
            :param s_current: start node
            :param s_next: end node
            :return: True: is collision / False: not collision
            检查起终点线段与障碍物是否冲突
        如果线段的起点或终点之一位于障碍物集合 self.obs 内,则直接判定为碰撞,返回 True。
        若线段不垂直也不水平(即斜线段),则分为两种情况检查:
            若线段为45度线(斜率为1:1或-1),则检查线段的端点形成的矩形框内是否有障碍物。
            否则检查线段端点形成的另一矩形框内是否有障碍物。
        若上述任一矩形框内有障碍,则判定为碰撞,返回 True
        若无碰撞情况,则返回 False
        """
        # obs是障碍物,如果遇到障碍物,则距离(成本)无穷大
        if s_current in self.obs or s_next in self.obs:
            return True
        ''''''
        # 如果该点s_start与相邻点s_end不相同
        if s_current[0] != s_next[0] and s_current[1] != s_next[1]:

            # 如果两点横纵坐标之差相等,即线段不垂直也不水平。135度线
            if s_next[0] - s_current[0] == s_current[1] - s_next[1]:
                s1 = (min(s_current[0], s_next[0]), min(s_current[1], s_next[1]))

                s2 = (max(s_current[0], s_next[0]), max(s_current[1], s_next[1]))
            # 如果两点横纵坐标之差不相等
            else:
                s1 = (min(s_current[0], s_next[0]), max(s_current[1], s_next[1]))
                s2 = (max(s_current[0], s_next[0]), min(s_current[1], s_next[1]))
            # obs是障碍物
            if s1 in self.obs or s2 in self.obs:
                return True
        return False

    def f_value(self, s_currrent):
        """
        f = g + h. (g: Cost to come, h: heuristic value)
        :param s: current state
        :return: f
        """

        return self.g[s_currrent] + self.heuristic(s_currrent)

    def extract_path(self, parent):

        path = [self.s_goal]
        s = self.s_goal

        while True:
            s = parent[s]
            path.append(s)

            if s == self.s_start:
                break

        return list(path)

    def heuristic(self, s_current):

        heuristic_type = self.heuristic_type  # heuristic type
        goal = self.s_goal  # goal node
        # 如果为manhattan,则采用曼哈顿距离,s存储的是中间点
        if heuristic_type == "manhattan":
            return abs(goal[0] - s_current[0]) + abs(goal[1] - s_current[1])
        # 否则就是欧几里得距离,符合勾股定理
        else:
            return math.hypot(goal[0] - s_current[0], goal[1] - s_current[1])


if __name__ == '__main__':
    time_start = time.time()
    s_start = (5, 5)
    s_goal = (45, 26)

    star_m = Astar(s_start, s_goal, "ee", s_start, s_goal)

    path, visited = star_m.searching()
    star_m.animation(path, visited, "A*")  # animation
    time_end = time.time()
    print("程序运行时间:", time_end - time_start)
	

在这里插入图片描述

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

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

相关文章

企业里面最常用的6大管理系统!附6个模板下载!

企业管理系统旨在帮助企业优化工作流程&#xff0c;提高工作效率的信息化系统。它通过对一些流程的规范&#xff0c;可以极大地减少企业存在的一些流程重复造成的浪费&#xff0c;并通过规范每个员工的动作来提高效率。企业在选择管理系统时&#xff0c;注重功能的全面性、流程…

CentOS7下快速升级至OpenSSH9.7p2安全版本

一、CentOS7服务器上编译生成OpenSSH9.3p2的RPM包 1、编译打包的shell脚本来源于该项目 https://github.com/boypt/openssh-rpms解压zip项目包 unzip openssh-rpms-main.zip -d /opt cd /opt/openssh-rpms-main/ vim pullsrc.sh 修改第23行为source ./version.env 2、sh pull…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(三十一)- 微服务(11)

12.7 DSL查询语法 查询的基本语法 GET /indexName/_search{"query": {"查询类型": {"查询条件": "条件值"}}} 查询所有 GET /hotel/_search{"query": {"match_all": {}}} 12.7.1 全文检索查询 全文检索查询,会…

OZON云仓靠谱吗,OZON云仓垫资提货模式

在电商飞速发展的今天&#xff0c;物流仓储成为了支撑整个电商生态的重要基石。OZON云仓作为市场上新兴的仓储物流服务提供商&#xff0c;凭借其先进的技术和灵活的服务模式&#xff0c;受到了不少电商卖家和消费者的关注。但随之而来的是一系列疑问&#xff1a;OZON云仓靠谱吗…

【八股系列】react里组件通信有几种方式,分别怎样进行通信?

文章目录 1. props传递&#xff08;父向子通信&#xff09;:2. 回调函数作为props&#xff08;子向父通信&#xff09;:3. Context API&#xff1a;4. Redux或MobX等状态管理库&#xff1a;4.1 Redux使用示例 5. refs&#xff1a; 1. props传递&#xff08;父向子通信&#xff…

社区新标准发布!龙蜥社区标准化 SIG MeetUp 圆满结束

5 月 31 日&#xff0c;「龙蜥社区“走进系列”」第 9 期之走进阿里云于北京圆满结束。来自阿里云、浪潮信息、红旗软件、中兴通讯|中兴新支点、中科曙光、中科方德、统信软件、麒麟软件、万里红、普华基础软件、飞腾信息、凝思、申威、新华三等公司的 30 余位专家出席会议。会…

C#开源软件:OneNote组件oneMore轻松打造自己的公众号编辑器

OneMore是一款为Microsoft OneNote设计的插件&#xff0c;它提供了许多扩展功能来增强OneNote的使用体验。 插件功能概述&#xff1a; OneMore插件拥有多达一百多个扩展功能&#xff0c;这些功能覆盖了笔记编辑、搜索、导出等多个方面&#xff0c;为用户提供了更加便捷和高效的…

人工智能超万卡集群的设计架构解读

超万卡集群的核心设计原则和总体架构 超万卡集群建设正起步&#xff0c;现主要依赖英伟达GPU及其配套设备。英伟达GPU在大模型训练中优势显著。国产AI芯片虽在政策与应用驱动下取得进步&#xff0c;但整体性能与生态建设仍有不足。构建一个基于国产生态、技术领先的超万卡集群&…

Flutter-使用MethodChannel 实现与iOS交互

前言 使用 MethodChannel 在 Flutter 与原生 Android 和 iOS 之间进行通信&#xff0c;可以让你在 Flutter 应用中调用设备的原生功能。 基础概念 MethodChannel&#xff1a;Flutter 提供的通信机制&#xff0c;允许消息以方法调用的形式在 Flutter 与原生代码之间传递。方法…

k8s学习--kubernetes服务自动伸缩之水平伸缩(pod副本伸缩)HPA详细解释与案例应用

文章目录 前言HPA简介简单理解详细解释HPA 的工作原理监控系统负载模式HPA 的优势使用 HPA 的注意事项应用类型 应用环境1.metircs-server部署2.HPA演示示例&#xff08;1&#xff09;部署一个服务&#xff08;2&#xff09;创建HPA对象&#xff08;3&#xff09;执行压测 前言…

【免费Web系列】大家好 ,今天是Web课程的第十九天点赞收藏关注,持续更新作品 !

1. Vue工程化 前面我们在介绍Vue的时候&#xff0c;我们讲到Vue是一款用于构建用户界面的渐进式JavaScript框架 。&#xff08;官方&#xff1a;Vue.js - 渐进式 JavaScript 框架 | Vue.js&#xff09; 那在前面的课程中&#xff0c;我们已经学习了Vue的基本语法、表达式、指令…

Etcd Raft架构设计和源码剖析2:数据流

Etcd Raft架构设计和源码剖析2&#xff1a;数据流 | Go语言充电站 前言 之前看到一幅描述etcd raft的流程图&#xff0c;感觉非常直观&#xff0c;但和自己看源码的又有些不同&#xff0c;所以自己模仿着画了一下&#xff0c;再介绍一下。 下图从左到右依次分为4个部分&…

探索在线问诊系统的安全性与隐私保护

随着远程医疗的普及&#xff0c;在线问诊系统成为医疗服务的重要组成部分。然而&#xff0c;随着医疗数据的在线传输和存储&#xff0c;患者的隐私保护和数据安全面临巨大挑战。本文将探讨在线问诊系统的安全性与隐私保护&#xff0c;介绍常见的安全措施和技术实现&#xff0c;…

【问题记录】VMware 17.5.1下载VMware tools失败报错的解决方法

一&#xff0c;问题现象 Ubuntu可以上网&#xff0c;但是下载VMware tools失败&#xff0c;报错提示&#xff1a;“连接到更新服务器时发生证书错误。请检查您的Internet设置或联系您的系统管理员。” 下载安装VMware tools&#xff1a; 报错提示&#xff1a; 二&#xff0…

品质卓越为你打造App UI 风格

品质卓越为你打造App UI 风格

网络安全到底是什么?一篇概念详解(附学习资料)

一、什么是网络安全&#xff1f;&#xff08;文末有资料&#xff09; “网络安全是指网络系统的硬件、软件及其系统中的数据受到保护&#xff0c;不因偶然的或者恶意的原因而遭受到破坏、更改、泄露、系统连续可靠正常地运行&#xff0c;网络服务不中断。” 说白了网络安全就…

【精品方案】某咨询公司的大数据解决方案(32页PPT),干货满满!

引言&#xff1a;随着信息技术的快速发展和大数据时代的到来&#xff0c;企业面临着海量数据的挑战与机遇。如何高效、准确地收集、处理、分析和利用这些数据&#xff0c;成为了企业提升业务效率和决策质量的关键。本咨询公司结合多年的行业经验和先进的大数据技术&#xff0c;…

Electron+Vue开源软件:洛雪音乐助手V2.8畅享海量免费歌曲

洛雪音乐助手是一款功能全面且完全免费的开源音乐软件&#xff0c;支持在Windows、Android和iOS平台上使用。 平台支持&#xff1a; 桌面版&#xff1a;采用Electron Vue技术栈开发&#xff0c;支持Windows 7及以上版本、Mac OS和Linux&#xff0c;具有广泛的用户群体覆盖。 …

spring boot3登录开发-邮箱登录/注册接口实现

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途 目录 写在前面 上文衔接 内容简介 功能分析 所需依赖 邮箱验证登录/注册实现 1.创建交互对象 2.登录注册业务逻辑实…

绿洲生态【OAS】爱护环境--保护地球

绿洲生态(OAS)&#xff0c;是由新加坡绿洲基金会联合世界绿色环保组织联合发行OAS通证。总发行量9亿&#xff0c;致力于形成辐射全球的“绿洲生态(OAS)”探索环保应用流通通证&#xff08;OAS&#xff09;生态体系。 绿洲生态通过&#xff08;OAS&#xff09;分配来提高玩家的参…