(8-2-01)自动驾驶中的无地图环境路径探索:基于Pygame的交互式路径规划器(1)

8.2 实战案例:基于Pygame的交互式路径规划器

本项目是一个基于 Pygame 的交互式路径规划器,通过 A* 和 D* Lite 算法实现路径规划。用户可以在 GUI 界面中设置起点、终点和障碍物,并观察路径规划的过程和结果,以及实时更新的路径信息。

实例8-2基于Pygame的交互式路径规划器codes/8/dynamic-a-star/

8.2.1 项目介绍

在现代社会中,路径规划和算法优化已成为许多领域的重要问题,如物流管理、自动驾驶和游戏开发等。特别是在计算机科学和人工智能领域,路径规划算法的研究和应用愈发重要。A*(A-star)和D* Lite是两种常用的路径规划算法,分别用于寻找最短路径和在动态环境中更新路径。这些算法的实现不仅可以帮助人们理解路径规划的基本原理,还可以应用于实际项目中,如智能导航系统和游戏引擎等。

本项目旨在结合A* 和 D* Lite 算法,开发一个路径规划可视化工具,以帮助用户更直观地了解这两种算法的工作原理和应用场景。该工具提供了一个交互式的图形界面,用户可以在界面上设置起点、终点和障碍物,然后观察算法如何计算最优路径,并实时显示在界面上。通过这个工具,用户可以深入了解A*算法和D* Lite算法的运行过程,以及它们在不同场景下的优劣势。

本项目的核心代码分为两部分:A*算法和D* Lite算法的实现。A*算法用于在静态环境中寻找最短路径,而D* Lite算法则适用于动态环境下的路径更新和重新规划。图形界面部分基于Pygame库实现,用户可以通过鼠标和键盘与界面进行交互,设置参数和观察算法执行过程。该工具不仅是一个教学工具,还可以作为实验平台,用于测试和比较不同路径规划算法的性能和效果。

通过本项目,用户可以学习到A*算法和D* Lite算法的原理和实现细节,并通过可视化界面直观地感受到路径规划的过程和结果。同时,也为学术界和工程界提供了一个开放的平台,以促进路径规划算法的研究和应用。

8.2.2 实现路径规划算法

文件path_finding.py实现了两个路径规划算法:D* Lite和A*,具体实现流程如下所示。

(1)定义函数 h(p1, p2),用于计算两个二维点之间的曼哈顿距离。函数接受两个二维点 p1 和 p2,分别表示为 (x1, y1) 和 (x2, y2),然后计算它们之间的曼哈顿距离,并返回结果。曼哈顿距离是指两点在直角坐标系上的横纵坐标的差的绝对值之和。

def h(p1, p2): x1, y1 = p1 x2, y2 = p2 return abs(x1 - x2) + abs(y1 - y2)

(2)下面代码定义了一个用于计算节点关键值的函数 calculate_key(spot, current, k_m),该函数接受三个参数,分别是待计算关键值的节点 spot、当前节点 current 和额外的调整参数 k_m。它根据节点的属性以及当前节点和参数值,计算节点的两个关键值 k1 和 k2,然后返回一个元组 (k1, k2),表示节点的关键值。

def calculate_key(spot, current, k_m): # 计算节点的关键值 k1 = min(spot.g, spot.rhs) + h(spot.get_pos(), current.get_pos()) + k_m k2 = min(spot.g, spot.rhs) return (k1, k2)

(3)定义函数 top_key(queue),用于获取优先队列中关键值最小的节点的关键值。函数接受一个优先队列 queue 作为参数。函数 top_key(queue)的具体功能如下:

  1. 首先,对队列 queue 进行排序,使得队列中具有最小关键值的节点排在队列的前面。
  2. 然后,检查队列是否为空,如果队列不为空,则返回队列中第一个节点的关键值的前两个元素(即 queue[0][:2])。
  3. 如果队列为空,则返回一个表示无穷大的元组 (float('inf'), float('inf')),表示找不到最小关键值。
def top_key(queue): # 获取队列中关键值最小的节点的关键值 queue.sort() if len(queue) > 0: return queue[0][:2] else: return (float('inf'), float('inf'))

(4)定义函数update_vertex,功能是更新节点的状态。该函数接受六个参数,包括用于绘制的函数 draw,优先队列 queue,待更新状态的节点 spot,当前节点 current,目标节点 end,以及额外的调整参数 k_m。在函数update_vertex中,首先根据当前节点与目标节点的关系计算节点的 rhs 值,然后检查节点是否在队列中,并移除旧的状态。接着,根据节点的新状态将其重新加入队列,并更新节点的状态标记。最后,调用绘制函数 draw 更新可视化界面。综上所述,该函数实现了根据节点与目标节点的关系更新节点状态,并重新加入优先队列的功能。

def update_vertex(draw, queue, spot, current, end, k_m): # 更新节点的状态 s_goal = end if spot != s_goal: min_rhs = float('inf') for neighbor in spot.neighbors: min_rhs = min(min_rhs, neighbor.g + h(spot.get_pos(), neighbor.get_pos())) spot.rhs = min_rhs id_in_queue = [item for item in queue if spot in item] if id_in_queue != []: if len(id_in_queue) != 1: raise ValueError('more than one spot (' + spot.get_pos() + ') in the queue!') queue.remove(id_in_queue[0]) if spot.rhs != spot.g: heapq.heappush(queue, calculate_key(spot, current, k_m) + (spot,)) spot.make_open() draw()

(5)定义函数next_in_shortest_path,用于在当前节点的邻居中找到路径代价最小的节点。该函数接受一个参数 current,表示当前节点。函数next_in_shortest_path的主要功能如下:

  1. 首先,初始化变量 min_rhs 为正无穷。
  2. 然后,检查当前节点的 rhs 是否为正无穷,如果是,则输出提示信息 "You are stuck!"。
  3. 接着,遍历当前节点的邻居节点,并计算每个邻居节点到当前节点的路径代价。
  4. 如果某个邻居节点的路径代价小于 min_rhs,则更新 min_rhs 和 next,分别记录当前找到的最小路径代价和对应的节点。
  5. 最后,如果找到了符合条件的邻居节点,则返回该节点,否则抛出异常 "No suitable child for transition!"。
def next_in_shortest_path(current): # 获取当前节点邻居中路径代价最小的节点 min_rhs = float('inf') next = None if current.rhs == float('inf'): print('You are stuck!') else: for neighbor in current.neighbors: child_cost = neighbor.g + h(current.get_pos(), neighbor.get_pos()) if (child_cost) < min_rhs: min_rhs = child_cost next = neighbor if next: return next else: raise ValueError('No suitable child for transition!')

(6)定义函数scan_obstacles,功能是扫描障碍物并更新路径。该函数接受六个参数,包括用于绘制的函数 draw,优先队列 queue,当前节点 current,目标节点 end,扫描范围 scan_range,以及额外的调整参数 k_m。函数scan_obstacles的主要功能如下:

  1. 首先,根据给定的扫描范围,初始化 spots_to_update 列表,并将当前节点的邻居节点加入其中,同时标记已经检查的范围为1。
  2. 然后,利用循环来扩展扫描范围,逐层向外扩展并记录新发现的节点。
  3. 接着,确保扫描到的节点具有唯一性,去除重复的节点。
  4. 最后,遍历扫描到的节点,如果发现障碍物或目标物体,则更新相应节点的状态,并将其加入优先队列中,同时标记 new_obstacle 为 True。
def scan_obstacles(draw, queue, current, end, scan_range, k_m): # 扫描障碍物并更新路径 spots_to_update = [] range_checked = 0 if scan_range >= 1: for neighbor in current.neighbors: print(f"adding {neighbor.get_pos()} to spots to update") spots_to_update.append(neighbor) range_checked = 1 while range_checked < scan_range: new_set = [] for spot in spots_to_update: new_set.append(spot) print(f"adding {spot.get_pos()} to spots to update") for neighbor in spot.neighbors: if neighbor not in new_set: new_set.append(neighbor) print(f"adding {neighbor.get_pos()} to spots to update") range_checked += 1 spots_to_update = new_set # 确保唯一性 spots_to_update = list(set(spots_to_update)) new_obstacle = False for spot in spots_to_update: if spot.is_barrier() or spot.is_object(): print('found obstacle in ', spot.get_pos()) for neighbor in spot.neighbors: update_vertex(draw, queue, spot, current, end, k_m) new_obstacle = True return new_obstacle

(7)定义函数move_and_rescan,功能是移动并重新扫描。该函数接受六个参数,包括用于绘制的函数 draw,优先队列 queue,当前节点 current,目标节点 end,扫描范围 scan_range,以及额外的调整参数 k_m。函数move_and_rescan的主要功能如下:

  1. 首先,检查当前节点是否为目标节点,如果是,则返回字符串 'goal' 和当前调整参数 k_m,表示已到达目标。
  2. 否则,记录当前节点为上一步节点 last,并通过调用 next_in_shortest_path 函数找到路径中的下一个节点 new。
  3. 如果下一个节点是障碍物或目标物体,则输出提示信息 "obstacle" 并将下一个节点 new 设为当前节点,以避免移动到障碍物。
  4. 接着,调用 scan_obstacles 函数重新扫描障碍物并更新路径,同时将新的调整参数 k_m 计算为上一步节点到当前节点的曼哈顿距离加上当前 k_m。
  5. 最后,调用 calc_shortest_path 函数重新计算最短路径,并返回新的当前节点 new 和更新后的调整参数 k_m。
def move_and_rescan(draw, queue, current, end, scan_range, k_m): # 移动并重新扫描 if current == end: return 'goal', k_m else: last = current new = next_in_shortest_path(current) if new.is_object() or new.is_barrier(): print("obstacle") new = current results = scan_obstacles(draw, queue, new, end, scan_range, k_m) k_m += h(last.get_pos(), new.get_pos()) calc_shortest_path(draw, queue, current, end, k_m) return new, k_m

(8)定义函数calc_shortest_path,功能是计算最短路径。首先,使用 while 循环,条件为起始节点的 rhs 不等于 g 或者队列中最小关键值小于计算得到的起始节点的关键值。在循环中,首先获取队列中最小关键值 k_old 及对应的节点 u,并将其从队列中弹出。然后,根据条件比较 k_old 和节点 u 的关键值,分别进行不同的处理:

  1. 如果 k_old 小于节点 u 的关键值,则将节点 u 再次加入队列,并标记为开放状态。
  2. 如果节点 u 的 g 值大于 rhs 值,则更新节点 u 的 g 值为 rhs 值,并更新其邻居节点的状态。
  3. 否则,将节点 u 的 g 值设为正无穷,并更新其邻居节点的状态。

最后,将节点 u 标记为关闭状态,并调用绘制函数 draw 更新可视化界面。

def calc_shortest_path(draw, queue, start, end, k_m): # 计算最短路径 while (start.rhs != start.g) or (top_key(queue) < calculate_key(start, start, k_m)): k_old = top_key(queue) u = heapq.heappop(queue)[2] if k_old < calculate_key(u, start, k_m): heapq.heappush(queue, calculate_key(u, start, k_m) + (u,)) u.make_open() elif u.g > u.rhs: u.g = u.rhs for neighbor in u.neighbors: update_vertex(draw, queue, neighbor, start, end, k_m) else: u.g = float('inf') update_vertex(draw, queue, u, start, end, k_m) for neighbor in u.neighbors: update_vertex(draw, queue, neighbor, start, end, k_m) u.make_closed() draw()

(9)定义函数d_star_lite,实现了 D* Lite 算法的核心功能,包括初始化节点属性、计算关键值、更新最短路径等步骤,用于寻找起始节点到目标节点的最短路径。该函数接受六个参数,包括用于绘制的函数 draw,网格 grid,优先队列 queue,起始节点 start,目标节点 end,以及额外的调整参数 k_m。函数d_star_lite的具体实现流程如下所示。

  1. 首先,通过两个嵌套的循环,将网格中所有节点的 g 和 rhs 属性初始化为正无穷。
  2. 然后,将目标节点 end 的 g 和 rhs 属性都设为0。
  3. 接着,使用 calculate_key 函数计算目标节点 end 的关键值,并将其加入优先队列 queue 中。
  4. 调用 calc_shortest_path 函数计算最短路径,更新节点的状态。
  5. 最后,返回更新后的优先队列 queue 和调整参数 k_m。
def d_star_lite(draw, grid, queue, start, end, k_m): # D* Lite算法 for row in grid: for spot in row: spot.g = float("inf") spot.rhs = float("inf") end.g = 0 end.rhs = 0 heapq.heappush(queue, calculate_key(end, start, k_m) + (end,)) calc_shortest_path(draw, queue, start, end, k_m) return queue, k_m

(10)定义函数a_star实现A*算法,该算法用于在给定的网格中寻找从起始节点到目标节点的最短路径。该函数接受四个参数:用于绘制的函数 draw、网格 grid、起始节点 start 和目标节点 end。函数a_star首先初始化计数器和优先队列,然后通过计算节点间的成本来搜索最短路径。在搜索过程中,它记录每个节点的父节点以及从起始节点到每个节点的实际成本和综合成本,并使用优先队列来动态选择下一个要探索的节点。最终,当找到路径或搜索到达终点时,算法返回从起始节点到目标节点的路径。

def a_star(draw, grid, start, end): # A*算法 count = 0 open_set = PriorityQueue() open_set.put((0, count, start)) came_from = {} g_score = {spot: float("inf") for row in grid for spot in row} g_score[start] = 0 f_score = {spot: float("inf") for row in grid for spot in row} f_score[start] = h(start.get_pos(), end.get_pos()) open_set_hash = {start} while not open_set.empty(): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() current = open_set.get()[2] open_set_hash.remove(current) if current == end: return came_from for neighbor in current.neighbors: temp_g_score = g_score[current] + 1 if temp_g_score < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = temp_g_score f_score[neighbor] = temp_g_score + h(neighbor.get_pos(), end.get_pos()) if neighbor not in open_set_hash: count += 1 open_set.put((f_score[neighbor], count, neighbor)) open_set_hash.add(neighbor) neighbor.make_open() if current != start: current.make_closed() draw() return None

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

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

相关文章

Unity3D AI Navigation 详解:从基础概念到实战应用

引言在 Unity 游戏开发中&#xff0c;实现智能的 AI 角色移动是提升游戏体验的关键。Unity 提供的 AI Navigation 系统&#xff0c;能够帮助开发者轻松创建能够自主寻路、规避障碍、跨越特殊地形的角色。无论你是初学者还是有经验的开发者&#xff0c;掌握这套系统都能让你在游…

计及多能耦合的区域综合能源系统电气热能流计算Matlab实现

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f34…

Unity 的AI Navigation 系统详细总结

Unity 的AI Navigation 系统&#xff08;2022.2 及以上版本通过 AI Navigation 包实现&#xff09;可让角色在游戏世界智能导航&#xff0c;核心基于自动生成的导航网格&#xff08;NavMesh&#xff09; &#xff0c;支持动态障碍物实时调整导航、OffMesh Link实现跳跃 / 开门等…

Unity3D AI Navigation 完全指南:从基础到实战,让角色智能导航

在 Unity 开发中&#xff0c;让游戏角色自主避开障碍、找到最优路径&#xff0c;是提升玩法体验的关键。Unity 的 AI Navigation 系统&#xff08;2022.2 版本已整合为 AI Navigation 包&#xff09;通过导航网格&#xff08;NavMesh&#xff09;、智能 Agent 和动态障碍物机制…

Unity3D AI导航系统完全指南:从核心概念到动画耦合

在游戏开发中&#xff0c;让角色智能地在场景中移动是提升沉浸感的关键。Unity的AI Navigation包通过导航网格&#xff08;NavMesh&#xff09;和寻路系统&#xff0c;让开发者轻松实现角色的自主导航。本文将基于官方文档&#xff0c;带你全面了解AI导航的核心概念、新功能、实…

RabbitMQ在大数据风控系统中的应用案例

RabbitMQ在大数据风控系统中的应用案例 关键词:RabbitMQ、大数据风控、消息队列、实时计算、分布式系统 摘要:在金融科技(FinTech)领域,大数据风控系统如同"数字安全卫士",需要724小时实时监控用户行为、交易数据,快速识别欺诈风险。本文将以"快递中转站…

CRM服务质量差?提示工程架构师的3个Prompt解决方案

CRM服务质量差&#xff1f;提示工程架构师的3个Prompt解决方案 一、引言&#xff1a;为什么你的CRM总是“答非所问”&#xff1f; 1. 一个让客户崩溃的真实场景 上周&#xff0c;我朋友小琳遇到了一件糟心的事&#xff1a;她在某美妆品牌官网买了一瓶精华&#xff0c;快递延迟了…

AI智能侦测开箱即用方案: Docker镜像+示例代码全家桶

AI智能侦测开箱即用方案&#xff1a; Docker镜像示例代码全家桶 引言&#xff1a;为什么你需要这个方案&#xff1f; 想象一下&#xff0c;你是一个外包团队的负责人&#xff0c;刚接到一个AI项目&#xff0c;客户催着要demo&#xff0c;但团队里没人有AI开发经验。这时候&am…

AI安全技能树:零基础到精通的资源地图

AI安全技能树&#xff1a;零基础到精通的资源地图 引言&#xff1a;为什么你需要这份AI安全学习指南&#xff1f; 作为一名从其他行业转型AI安全的新手&#xff0c;你可能正面临这样的困境&#xff1a;网上充斥着碎片化的技术文章&#xff0c;各种专业术语让人眼花缭乱&#…

智能实体哨兵系统:7×24小时云端值守,月费不足人力1/10

智能实体哨兵系统&#xff1a;724小时云端值守&#xff0c;月费不足人力1/10 引言&#xff1a;为什么小区需要AI哨兵&#xff1f; 最近几年&#xff0c;越来越多的老旧小区开始升级监控系统&#xff0c;但传统方案往往面临两个痛点&#xff1a;一是需要专人24小时盯着监控屏幕…

智能监控AI懒人包:一键部署复杂模型,省去7天配置时间

智能监控AI懒人包&#xff1a;一键部署复杂模型&#xff0c;省去7天配置时间 引言&#xff1a;传统安防的AI转型痛点 对于传统安防厂商来说&#xff0c;向AI智能监控转型就像让一位机械手表匠突然学习编程——技术栈完全不同&#xff0c;学习成本高得吓人。我接触过不少这类企…

跨平台用户画像构建:多源数据实体对齐,隐私合规

跨平台用户画像构建&#xff1a;多源数据实体对齐与隐私合规实践指南 引言&#xff1a;当广告技术遇上隐私合规挑战 想象一下你经营着一家连锁咖啡店&#xff0c;每位顾客可能通过小程序下单、在官网浏览新品、到实体店使用会员卡消费。如何把这些分散的行为串联起来&#xf…

【46】骰子数据集(有v5/v8模型)/YOLO骰子点数检测

文章目录 1 数据集介绍1.1 说明1.2 类别 2 训练好的模型结果2.1 YOLOv5模型结果2.2 YOLOv8模型结果 3 数据集获取 ➷点击跳转至数据集及模型获取处☇ 1 数据集介绍 1.1 说明 图片数量705张&#xff0c;已标注txt格式 训练集验证集按564:141划分&#xff0c;可直接用于目标检测…

AI侦测模型微调教程:云端GPU加速,3小时完成迭代

AI侦测模型微调教程&#xff1a;云端GPU加速&#xff0c;3小时完成迭代 引言 作为一名算法工程师&#xff0c;你是否遇到过这样的困境&#xff1a;公司GPU资源被其他项目占用&#xff0c;但你又急需优化行业专用模型&#xff1f;传统本地训练动辄需要数天时间&#xff0c;而项…

AI安全检测5大模型横评:云端3小时完成,比本地省时80%

AI安全检测5大模型横评&#xff1a;云端3小时完成&#xff0c;比本地省时80% 引言&#xff1a;为什么企业需要自主AI安全检测能力&#xff1f; 想象一下这样的场景&#xff1a;凌晨2点&#xff0c;公司服务器突然出现异常流量&#xff0c;安全团队需要快速判断这是正常业务高…

UEBA行为分析避坑指南:云端GPU免配置,比自建省90%成本

UEBA行为分析避坑指南&#xff1a;云端GPU免配置&#xff0c;比自建省90%成本 1. 为什么企业需要UEBA行为分析&#xff1f; 用户和实体行为分析&#xff08;UEBA&#xff09;是企业安全防护的"智能哨兵"。想象一下&#xff0c;你的公司有100名员工&#xff0c;每天…

百万行级行业代码如何做AI解读

对“上百万行”级行业代码做AI解读&#xff0c;目前业界已沉淀出一套“分层-增量-闭环”的落地套路&#xff0c;可直接套用到银行、电信、能源等存量系统。下面按“准备→宏观→微观→治理→持续迭代”5步给出可复制的工程方案&#xff0c;并标注可落地的商业大模型/工具。1. 准…

AI健身动作识别:预置运动实体模型,APP快速集成

AI健身动作识别&#xff1a;预置运动实体模型&#xff0c;APP快速集成 引言&#xff1a;让健身APP拥有专业教练的眼睛 想象一下这样的场景&#xff1a;用户在家跟着健身APP做深蹲时&#xff0c;手机摄像头能像专业教练一样实时指出"膝盖内扣了""下蹲幅度不够&…

VisionPro二开之日志Log模块

VisionPro二开之日志Log模块 一 配置log4net.config文件 <?xml version"1.0" encoding"utf-8" ?> <configuration><configSections><section name"log4net" type"System.Configuration.IgnoreSectionHandler"/…

智能体多语言支持测试:云端GPU秒切语言包,0等待

智能体多语言支持测试&#xff1a;云端GPU秒切语言包&#xff0c;0等待 引言&#xff1a;出海App的测试痛点 想象一下你正在开发一款面向全球市场的智能客服App&#xff0c;需要支持12种语言的对话测试。传统方式每次切换语言都需要重装测试环境&#xff0c;就像每次换国家旅…