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

8.2.3 路径规划可视化

文件astar.py实现了一个基于A*算法和D* Lite算法的路径规划程序。程序提供了一个可视化界面,允许用户在网格上绘制起始点、目标点和障碍物,然后根据用户选择的算法(A或D Lite)寻找最短路径。用户可以在设计模式下绘制网格,并在执行模式下执行路径搜索和路径跟踪。程序还提供了对象放置功能,用户可以在路径搜索的过程中动态放置对象来模拟实际环境中的障碍物。

(1)下面的代码定义了程序的窗口大小、颜色常量和其他参数。其中,窗口的高度根据给定的宽度和顶部菜单栏的高度进行计算,颜色常量用于绘制网格和路径搜索过程中的不同元素。

TOP_MENU_HEIGHT = 0.025 WIN_WIDTH = 800 WIN_HEIGHT = WIN_WIDTH + int((WIN_WIDTH * (TOP_MENU_HEIGHT))) # MAIN_GRID_HEIGHT = MAIN_GRID_WIDTH - (MAIN_GRID_WIDTH * (TOP_MENU_HEIGHT)) SCAN_RANGE = 1 WIN = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption("A* Path Finding Algorithm") pygame.font.init() RED = (200, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 255, 0) YELLOW = (255, 255, 0) WHITE = (255, 255, 255) BLACK = (0, 0, 0) PURPLE = (128, 0, 128) ORANGE = (255, 165 ,0) GREY = (128, 128, 128) TURQUOISE = (64, 224, 208) BROWN = (150, 75, 0)

(2)下面的代码定义了类Grid,用于创建和管理网格。类Grid中包含如下所示的成员方法:

  1. __init__方法用于初始化网格对象,并接受行数、宽度、起始坐标和结束坐标作为参数。
  2. make_grid方法用于创建网格,通过迭代行和列来实现。
  3. reset_grid方法用于重置网格,将其清空并重新创建。
  4. reset_search_area方法用于重置搜索区域,将网格中所有状态为“打开”“关闭”或“路径”的点恢复为初始状态。
  5. get_grid方法用于返回网格列表。
  6. get_spot方法用于根据给定的行列索引或坐标返回网格中的点。
  7. draw_grid方法用于绘制网格线条,通过迭代行和列来实现。
class Grid: def __init__(self, rows, width, start_coord, end_coord): self.gap = width // rows self.width = width self.rows = rows self.start_x, self.start_y = start_coord self.end_x, self.end_y = end_coord self.grid = [] def make_grid(self): for i in range(self.rows): self.grid.append([]) for j in range(self.rows): spot = Spot(i, j,self.gap, self.rows, (self.start_x, self.start_y, self.end_x, self.end_y)) self.grid[i].append(spot) def reset_grid(self): self.grid = [] self.make_grid() def reset_search_area(self): for row in self.grid: for spot in row: if spot.is_open() or spot.is_closed() or spot.is_path(): spot.reset() def get_grid(self): return self.grid def get_spot(self, row=None, col=None, x=None, y=None): if row and col: return self.grid[row][col] elif x and y: x = x - self.start_x y = y - self.start_y row = y // self.gap col = x // self.gap print(f"spot : [{row}][{col}]") return self.grid[row][col] else: pass def draw_grid(self, win): for i in range(self.rows): pygame.draw.line(win, GREY, (self.start_x, self.start_y + (i * self.gap)), (self.end_x, self.start_y + (i * self.gap))) for j in range(self.rows): pygame.draw.line(win, GREY, (self.start_x + (j * self.gap), self.start_y), (self.start_x + (j * self.gap), self.end_y))

(3)定义类Rectangle,用于创建和管理程序中的矩形对象,并在图形界面中绘制矩形和文本。该类具有以下功能:

  1. __init__方法用于初始化矩形对象,并接受矩形的起始坐标、宽度和高度作为参数。
  2. draw方法用于绘制矩形,通过调用pygame.draw.rect函数来实现。
  3. draw_text方法用于绘制文本,通过调用pygame.font.SysFont函数创建字体对象,然后调用render方法将文本渲染到表面上,并使用blit方法将文本绘制到窗口上。
class Rectangle: def __init__(self, x, y, width, height): self.x = x self.y = y self.width = width self.height = height self.color = BLACK def draw(self, win): pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.height)) def draw_text(self, win, text, size, color, pos): # print(text, size, color, pos) font = pygame.font.SysFont("Comic Sans MS", size, True) text_surface = font.render(text, True, color) text_rect = text_surface.get_rect(topleft=pos) win.blit(text_surface, text_rect)

(4)定义类TopBar的,它继承自类Rectangle,用于创建和管理程序中的顶部菜单栏对象,并在图形界面中绘制相应的菜单信息。该类具有以下功能:

  1. __init__方法初始化顶部菜单栏对象,并接受菜单栏的起始坐标、宽度和高度作为参数。还初始化了当前模式、算法、模式字符串的位置、字符串大小和颜色等属性。
  2. update_mode方法用于更新当前模式,并在窗口上绘制更新后的菜单栏。
class TopBar(Rectangle): def __init__(self, x, y, width, height): self.current_mode = "DESIGN" self.alg = "" self.mode_string_pos = (x+5,y+2) # self.alg_string_pos = (x+200,y+2) self.mode_string_size = 10 self.mode_string_color = WHITE super().__init__(x, y, width, height) def update_mode(self, win, mode): self.current_mode = mode self.draw(win) self.draw_text(win, f"MODE: {self.current_mode}", self.mode_string_size, self.mode_string_color, self.mode_string_pos)

(5)定义类Spot,用于创建和管理程序中的路径规划格子,并在图形界面中绘制相应的格子信息。该类具有以下功能:

  1. __init__方法用于初始化格子对象,接受行、列、宽度、总行数、网格坐标、g值和rhs值作为参数。根据给定的行和列计算格子的位置,并初始化颜色、邻居列表等属性。
  2. get_pos方法用于返回格子的行列坐标。
  3. is_closed、is_open、is_barrier、is_object、is_start、is_end、is_path方法用于检查格子的状态。
  4. reset方法将格子的颜色重置为白色。
  5. make_start、make_closed、make_open、make_barrier、make_object、make_end、make_path方法用于将格子设置为起点、封闭、开放、障碍、对象、终点或路径。
  6. draw方法用于在窗口上绘制格子。
  7. update_neighbors方法用于根据给定的网格更新格子的邻居列表。
  8. __lt__方法用于比较格子对象的优先级,这里简单地返回False。
class Spot: def __init__(self, row, col, width, total_rows, grid_coord, g=None, rhs=None): self.row = row self.col = col self.g = g self.rhs = rhs ### cant be absolute X,Y self.x_start, self.y_start, self.x_end, self.y_end = grid_coord self.x = self.x_start + (col * width) self.y = self.y_start + (row * width) # self.x = (row * width) # self.y = (col * width) self.color = WHITE self.neighbors = [] self.width = width self.total_rows = total_rows def get_pos(self): return self.row, self.col def is_closed(self): return self.color == RED def is_open(self): return self.color == GREEN def is_barrier(self): return self.color == BLACK def is_object(self): return self.color == BROWN def is_start(self): return self.color == ORANGE def is_end(self): return self.color == TURQUOISE def is_path(self): return self.color == PURPLE def reset(self): self.color = WHITE def make_start(self): self.color = ORANGE def make_closed(self): self.color = RED def make_open(self): self.color = GREEN def make_barrier(self): self.color = BLACK def make_object(self): self.color = BROWN def make_end(self): self.color = TURQUOISE def make_path(self): self.color = PURPLE def draw(self, win): pygame.draw.rect(win, self.color, (self.x, self.y, self.width, self.width)) def update_neighbors(self, grid): self.neighbors = [] if self.row < self.total_rows - 1 and not grid[self.row + 1][self.col].is_barrier() and not grid[self.row + 1][self.col].is_object(): # DOWN self.neighbors.append(grid[self.row + 1][self.col]) if self.row > 0 and not grid[self.row - 1][self.col].is_barrier() and not grid[self.row - 1][self.col].is_object(): # UP self.neighbors.append(grid[self.row - 1][self.col]) if self.col < self.total_rows - 1 and not grid[self.row][self.col + 1].is_barrier() and not grid[self.row][self.col + 1].is_object(): # RIGHT self.neighbors.append(grid[self.row][self.col + 1]) if self.col > 0 and not grid[self.row][self.col - 1].is_barrier() and not grid[self.row][self.col - 1].is_object(): # LEFT self.neighbors.append(grid[self.row][self.col - 1]) def __lt__(self, other): return False

(5)函数reverse_path用于在路径规划中获取从终点到起点的路径字典,以便进行反向查找路径。首先,将当前节点设置为路径的终点,然后从当前节点开始,沿着路径逐步向前遍历,将沿途经过的节点依次添加到一个列表中。然后,将列表中的节点顺序反转,构建反转后的路径列表。接着,通过遍历反转后的路径列表,将每个节点及其后一个节点的关系添加到一个字典中。最后,将路径的最后一个节点与当前节点相连,并返回反转后的路径字典。

def reverse_path(path, current): end = current path_list = [] reverse = {} while current in path: current = path[current] path_list.append(current) path_list.reverse() for pos in range(len(path_list)-1): reverse[path_list[pos]] = path_list[pos+1] reverse[path_list[len(path_list)-1]] = end return reverse

(6)函数 draw的功能是,在 Pygame 窗口中绘制网格、顶部菜单以及更新显示内容。首先用白色填充整个窗口,然后根据当前模式绘制网格和顶部菜单,并更新窗口的显示内容。

  1. win:Pygame 窗口对象,用于绘制图形。
  2. mode:表示当前的模式,可以是 "DESIGN" 或 "EXECUTION"。
  3. alg:表示当前使用的路径规划算法。
  4. grid_list:包含一个或多个网格对象的列表,用于绘制网格。
  5. top_menu:顶部菜单对象,用于在窗口顶部显示当前模式和算法。
  6. rows:网格的行数。
  7. width:窗口的宽度。
def draw(win, mode, alg, grid_list, top_menu, rows, width): win.fill(WHITE) # if mode == "DESIGN": design_grid = grid_list[0] grid = design_grid.get_grid() for row in grid: for spot in row: spot.draw(win) design_grid.draw_grid(win) top_menu.update_mode(win, mode) top_menu.update_alg(win, alg) pygame.display.update()

(7)函数get_clicked_spot_grid的功能是,根据点击位置获取所在网格的对应的网格单元(Spot)对象。

  1. pos:包含点击位置的元组 (x, y)。
  2. grids:包含一个或多个网格对象的列表。

函数get_clicked_spot_grid首先将点击位置的坐标解包为 x 和 y,然后遍历 grids 列表中的每个网格对象,检查点击位置是否在网格范围内。如果找到了所在的网格,则调用该网格对象的 get_spot 方法,根据点击位置的坐标获取对应的网格单元对象(Spot)。最后,返回获取到的网格单元对象。

def get_clicked_spot_grid(pos, grids): x, y = pos clicked_grid = None for grid in grids: print(x,y) print(grid.start_x, grid.end_x, grid.start_y, grid.end_y) if (grid.start_x <= x <= grid.end_x) and (grid.start_y <= y <= grid.end_y): print("grid found!" ) clicked_grid = grid break if clicked_grid: spot = clicked_grid.get_spot(x=x, y=y) return spot

(8)下面这段代码实现了一个交互式路径规划程序,用户可以通过 GUI 界面设置起点、终点和障碍物,并选择执行 A* 或 D* Lite 算法进行路径规划,然后观察路径规划的过程和结果。

def main(win, win_size, top_menu_height): ROWS = 50 start = None end = None planned_path = None current = None k_m = 0 queue = [] g_score = {} rhs_score = {} mode = "DESIGN" alg = "NONE" width, height = win_size # in design mode start with only one grid start_coord_grid = (0, top_menu_height) end_coord_grid = (width, height) grid_width = width # Make design grid design_grid = Grid(ROWS, grid_width, start_coord_grid, end_coord_grid) design_grid.make_grid() grids = [design_grid] top_menu = top_menu = TopBar(0, 0, width, top_menu_height) run = True while run: draw(win, mode, alg, grids, top_menu, ROWS, width) if mode == "DESIGN": # run = False for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if pygame.mouse.get_pressed()[0]: # 按下左移健 pos = pygame.mouse.get_pos() spot = get_clicked_spot_grid(pos, grids) if not start and spot != end: start = spot start.make_start() elif not end and spot != start: end = spot end.make_end() elif spot != end and spot != start: spot.make_barrier() elif pygame.mouse.get_pressed()[2]:# 按下右移健 pos = pygame.mouse.get_pos() spot = get_clicked_spot_grid(pos, grids) spot.reset() if spot == start: start = None elif spot == end: end = None if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and start and end: upd_grid = grids[0].get_grid() for row in upd_grid: for spot in row: spot.update_neighbors(upd_grid) mode = "EXECUTION" alg = "a-star" if event.key == pygame.K_RETURN and start and end: upd_grid = grids[0].get_grid() for row in upd_grid: for spot in row: spot.update_neighbors(upd_grid) mode = "EXECUTION" alg = "d-star-lite" if event.key == pygame.K_c: start = None end = None planned_path = None current = None mode = "DESIGN" grids[0].reset_grid() # grid = make_grid(ROWS, width) if mode == "EXECUTION": if alg == "a-star": planned_path = a_star(lambda: draw(win, mode, alg, grids, top_menu, ROWS, width), upd_grid, start, end) #制作从起点到终点的路径 planned_path = reverse_path(planned_path, end) print("alg execution ended! ") mode = "WALK" end.make_end() current = start elif alg == "d-star-lite": #D Lite 算法* last = start current = start print("running D*") queue, k_m = d_star_lite(lambda: draw(win, mode, alg, grids, top_menu, ROWS, width), upd_grid, queue, start, end, k_m) print("FINISHED running D*") mode = "WALK" start.make_start() end.make_end() if mode == "WALK": for event in pygame.event.get(): if event.type == pygame.QUIT: run = False #放置一个物体 if pygame.mouse.get_pressed()[0]: # LEFT pos = pygame.mouse.get_pos() spot = get_clicked_spot_grid(pos, grids) #如果点击的点不是起点、终点或障碍物 if spot != end and spot != start and not spot.is_barrier() and not spot.is_path(): spot.make_object() upd_grid = grids[0].get_grid() for row in upd_grid: for spot in row: spot.update_neighbors(upd_grid) #撤销物体放置 elif pygame.mouse.get_pressed()[2]: # RIGHT pos = pygame.mouse.get_pos() spot = get_clicked_spot_grid(pos, grids) if spot.is_object(): spot.reset() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and planned_path: next = planned_path[current] if next != end: #撞到一个物体 if next.is_object(): #A *算法的行为 start, current = current, start start.make_start() current.reset() current = None planned_path = None #现在在每次放置物体时完成 grids[0].reset_search_area() upd_grid = grids[0].get_grid() for row in upd_grid: for spot in row: spot.update_neighbors(upd_grid) mode = "EXECUTION" else: current = next current.make_path() if event.key == pygame.K_RETURN: print(f"current position {current.get_pos()} ") next, k_m = move_and_rescan(lambda: draw(win, mode, alg, grids, top_menu, ROWS, width), queue, current, end, SCAN_RANGE, k_m) print(f"next position {next.get_pos()} ") current = next current.make_path() if event.key == pygame.K_c: start = None end = None planned_path = None current = None mode = "DESIGN" grids[0].reset_grid() pygame.quit() main(WIN, (WIN_WIDTH, WIN_HEIGHT), int(WIN_WIDTH * (TOP_MENU_HEIGHT)))

上述代码的实现流程如下所示:

  1. 创建一个 GUI 界面,其中包含顶部菜单栏、网格区域和状态显示区域。
  2. 用户可以在网格区域中设计障碍物、起点和终点,通过点击鼠标左键设置障碍物、起点和终点,通过点击鼠标右键取消障碍物或者取消起点和终点。
  3. 用户可以选择执行不同的路径规划算法,包括 A*算法和 D* Lite 算法。
  4. 在执行路径规划算法后,程序会展示规划的路径,并提供步进执行和连续执行两种模式。在步进执行模式下,用户可以逐步移动代理,并观察路径规划的实时结果。在连续执行模式下,程序会自动执行路径规划,并展示最终结果。
  5. 用户可以在路径规划过程中对特定位置进行障碍物设置,并在路径规划完成后自动重新规划路径。
  6. 用户可以随时清空网格并重新设计路径规划环境。
  7. 当程序执行完成或者用户关闭窗口时,会退出程序。

运行文件astar.py会启动pygame可视化界面,可以使用鼠标进行以下操作:

  1. 左键单击:放置起点、终点和障碍物。
  2. 右键单击:取消放置的起点、终点或障碍物。
  3. 空格键:启动路径规划算法(A或D Lite)。
  4. 回车键:执行路径规划过程中的下一步操作(仅限D* Lite算法)。
  5. 'c'键:清除界面上的所有内容,重新开始设计路径。

例如绘制的路径规划图效果如图8-2所示。

+

图8-2 绘制的路径规划图

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

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

相关文章

InstallerX完整指南:如何快速配置你的专属Android安装器

InstallerX完整指南&#xff1a;如何快速配置你的专属Android安装器 【免费下载链接】InstallerX A modern and functional Android app installer. (You know some birds are not meant to be caged, their feathers are just too bright.) 项目地址: https://gitcode.com/G…

ResNet18图像分类镜像上线|40MB小模型,毫秒级响应

ResNet18图像分类镜像上线&#xff5c;40MB小模型&#xff0c;毫秒级响应 &#x1f441;️ 通用物体识别-ResNet18&#xff1a;轻量高效、开箱即用的AI视觉服务 在边缘计算与实时推理需求日益增长的今天&#xff0c;如何在资源受限的设备上实现高精度、低延迟、小体积的图像分类…

5分钟快速上手:免费在线简历生成工具dnd-resume完整指南

5分钟快速上手&#xff1a;免费在线简历生成工具dnd-resume完整指南 【免费下载链接】dnd-resume &#x1f680; Resume Builder 在线简历生成工具 项目地址: https://gitcode.com/gh_mirrors/dn/dnd-resume 还在为制作简历而烦恼吗&#xff1f;dnd-resume 是一款完全免…

ASPICE(Automotive SPICE)流程落地,研发管理工具自研,如何从量化数据体现研发效率提升的

今天我们聊下如何自研研发管理工具,落地ASPCIE流程,工具里设计什么样的量化指标来体现研发效率的提升。 ASPICE(Automotive SPICE)带来的效率提升是显著且可量化的,尤其体现在质量、成本和时间这三个核心维度。下表汇总了关键的量化数据,方便你直观了解其成效。 效率提升…

AI万能分类器应用指南:教育领域文本分类最佳实践

AI万能分类器应用指南&#xff1a;教育领域文本分类最佳实践 1. 引言 1.1 教育场景下的文本分类需求 在当前教育信息化快速发展的背景下&#xff0c;学校、在线教育平台和教务系统每天都会产生大量非结构化文本数据——包括学生反馈、课程评价、家长留言、教学建议、投诉咨询…

Ultimate Vocal Remover终极指南:AI音频分离技术深度解析

Ultimate Vocal Remover终极指南&#xff1a;AI音频分离技术深度解析 【免费下载链接】ultimatevocalremovergui 使用深度神经网络的声音消除器的图形用户界面。 项目地址: https://gitcode.com/GitHub_Trending/ul/ultimatevocalremovergui 还在为如何从复杂音频中提取…

如何快速上手Kikoeru Express:5步完成音声流媒体部署完整指南

如何快速上手Kikoeru Express&#xff1a;5步完成音声流媒体部署完整指南 【免费下载链接】kikoeru-express kikoeru 后端 项目地址: https://gitcode.com/gh_mirrors/ki/kikoeru-express Kikoeru Express是一个专为同人音声爱好者打造的高效音声流媒体服务后端&#xf…

Vivado仿真时钟域处理:UltraScale+多时钟系统实践

Vivado仿真中的多时钟域实战&#xff1a;UltraScale系统设计避坑指南你有没有遇到过这样的情况&#xff1f;代码在Vivado里仿真跑得稳稳当当&#xff0c;波形干净利落&#xff0c;断言一个没报错。结果一上板&#xff0c;功能莫名其妙失效——某个状态机卡死、数据流突然中断&a…

IPTV播放源质量评估:5步掌握iptv-checker稳定性测试方案

IPTV播放源质量评估&#xff1a;5步掌握iptv-checker稳定性测试方案 【免费下载链接】iptv-checker IPTV source checker tool for Docker to check if your playlist is available 项目地址: https://gitcode.com/GitHub_Trending/ip/iptv-checker 问题分析&#xff1a…

RISC-V指令集入门必看:零基础快速理解核心架构

RISC-V指令集入门&#xff1a;从零开始理解它的设计哲学与实战逻辑你有没有遇到过这样的问题——想做个智能传感器&#xff0c;却发现主流MCU的授权费高得离谱&#xff1f;或者在FPGA上实现一个轻量处理器核时&#xff0c;被ARM或x86复杂的指令编码搞得焦头烂额&#xff1f;如果…

AI如何帮你快速实现I2C通信协议开发

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 请生成一个完整的I2C通信协议实现代码&#xff0c;要求包含以下功能&#xff1a;1) I2C主设备初始化函数 2) I2C从设备地址设置 3) 数据读写函数实现 4) 错误处理机制 5) 使用标准…

AI万能分类器技术揭秘:StructBERT模型优势解析

AI万能分类器技术揭秘&#xff1a;StructBERT模型优势解析 1. 技术背景与问题提出 在当今信息爆炸的时代&#xff0c;文本数据的自动化处理已成为企业智能化运营的核心需求。无论是客服工单、用户反馈、新闻资讯还是社交媒体内容&#xff0c;都需要高效、准确地进行分类打标&…

Jetson平台YOLOv8终极实战:TensorRT加速性能优化全攻略

Jetson平台YOLOv8终极实战&#xff1a;TensorRT加速性能优化全攻略 【免费下载链接】YOLOv8-TensorRT YOLOv8 using TensorRT accelerate ! 项目地址: https://gitcode.com/gh_mirrors/yo/YOLOv8-TensorRT 本文将深入探讨在Jetson嵌入式平台上如何通过TensorRT技术实现Y…

HyperDown:现代Markdown解析终极指南

HyperDown&#xff1a;现代Markdown解析终极指南 【免费下载链接】HyperDown 一个结构清晰的&#xff0c;易于维护的&#xff0c;现代的PHP Markdown解析器 项目地址: https://gitcode.com/gh_mirrors/hy/HyperDown 你是否曾为Markdown解析器的性能瓶颈和代码维护难题而…

SpringBoot+Vue 课程答疑系统平台完整项目源码+SQL脚本+接口文档【Java Web毕设】

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着信息技术的快速发展…

零基础教程:5分钟玩转硅基流动免费API

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 编写一个极简的Python示例代码&#xff0c;展示硅基流动API最基本的使用方法。要求&#xff1a;1. 不超过50行代码 2. 包含获取免费密钥的步骤说明 3. 实现一个最简单的文本分类功…

3分钟搞定家庭网络卡顿:SmartDNS客户端规则与IPv6优化实战

3分钟搞定家庭网络卡顿&#xff1a;SmartDNS客户端规则与IPv6优化实战 【免费下载链接】smartdns A local DNS server to obtain the fastest website IP for the best Internet experience, support DoT, DoH. 一个本地DNS服务器&#xff0c;获取最快的网站IP&#xff0c;获得…

AI万能分类器应用案例:招聘简历自动分类

AI万能分类器应用案例&#xff1a;招聘简历自动分类 1. 引言&#xff1a;AI 万能分类器的现实价值 在企业人力资源管理中&#xff0c;每天都会收到大量来自不同渠道的求职简历。传统的人工筛选方式不仅耗时耗力&#xff0c;还容易因主观判断导致优秀人才被遗漏。随着人工智能…

HyperDown:终极PHP Markdown解析解决方案

HyperDown&#xff1a;终极PHP Markdown解析解决方案 【免费下载链接】HyperDown 一个结构清晰的&#xff0c;易于维护的&#xff0c;现代的PHP Markdown解析器 项目地址: https://gitcode.com/gh_mirrors/hy/HyperDown 在当今数字内容创作时代&#xff0c;Markdown已成…

Webots机器人仿真平台实战指南:从新手到专家的完整进阶路径

Webots机器人仿真平台实战指南&#xff1a;从新手到专家的完整进阶路径 【免费下载链接】webots Webots Robot Simulator 项目地址: https://gitcode.com/gh_mirrors/web/webots 作为一名长期从事机器人仿真开发的工程师&#xff0c;我发现Webots这款开源机器人模拟器在…