1. 二维栅格地图上的A*路径规划

二维栅格地图上的A*路径规划 学习卡片

任务说明

在二维栅格地图上实现A*路径规划算法,给定起点与终点坐标,算法输出从起点到终点的最短路径点序列,并以可视化方式展示栅格地图、障碍物与最终路径。本案例聚焦于A*核心逻辑与可视化闭环,不涉及动态障碍物或全局平滑优化。

实现方案

栅格地图以二维列表表示,0为可通行区域,1为障碍物。A*算法采用曼哈顿距离作为启发函数,使用优先队列(heapq)按f值(g+h)扩展节点,并维护g值与父节点指针以回溯路径。可视化使用matplotlib绘制栅格、起点、终点与规划路径。

S G 起点 终点 障碍物 规划路径 列: 01234 行:01234

代码实现


import heapq
import matplotlib.pyplot as plt
import numpy as np

def astar(grid, start, goal):
    """A*路径规划,返回路径点列表[(row,col),...]"""
    rows, cols = len(grid), len(grid[0])
    open_set = []
    heapq.heappush(open_set, (0, start))
    came_from = {}
    g_score = {start: 0}
    f_score = {start: heuristic(start, goal)}
    
    while open_set:
        _, current = heapq.heappop(open_set)
        if current == goal:
            return reconstruct_path(came_from, current)
        
        for neighbor in get_neighbors(current, rows, cols):
            if grid[neighbor[0]][neighbor[1]] == 1:
                continue  # 跳过障碍物
            tentative_g = g_score[current] + 1
            if neighbor not in g_score or tentative_g < g_score[neighbor]:
                came_from[neighbor] = current
                g_score[neighbor] = tentative_g
                f = tentative_g + heuristic(neighbor, goal)
                f_score[neighbor] = f
                heapq.heappush(open_set, (f, neighbor))
    return None  # 无可行路径

def heuristic(a, b):
    """曼哈顿距离"""
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

def get_neighbors(pos, rows, cols):
    """四邻域扩展"""
    r, c = pos
    neighbors = []
    for dr, dc in [(-1,0),(1,0),(0,-1),(0,1)]:
        nr, nc = r + dr, c + dc
        if 0 <= nr < rows and 0 <= nc < cols:
            neighbors.append((nr, nc))
    return neighbors

def reconstruct_path(came_from, current):
    """回溯路径"""
    path = [current]
    while current in came_from:
        current = came_from[current]
        path.append(current)
    path.reverse()
    return path

# ===== 地图定义与算法调用 =====
grid = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]
# 设置障碍物(示例:一堵斜墙)
for i in range(5, 10):
    grid[i][5] = 1
for i in range(5, 10):
    grid[i][6] = 1

start = (0, 0)
goal = (9, 11)

path = astar(grid, start, goal)

# ===== 可视化 =====
def visualize(grid, path, start, goal):
    grid_arr = np.array(grid)
    fig, ax = plt.subplots(figsize=(8, 8))
    # 绘制栅格
    ax.imshow(grid_arr, cmap='gray_r', origin='upper')
    # 绘制路径
    if path:
        path_arr = np.array(path)
        ax.plot(path_arr[:, 1], path_arr[:, 0], 'y-o', linewidth=3, markersize=6, label='Path')
    # 标记起点终点
    ax.plot(start[1], start[0], 'go', markersize=12, label='Start')
    ax.plot(goal[1], goal[0], 'bo', markersize=12, label='Goal')
    ax.set_xticks(range(len(grid[0])))
    ax.set_yticks(range(len(grid)))
    ax.grid(True, which='both', color='gray', linewidth=0.5)
    ax.legend()
    plt.title('A* Path Planning on 2D Grid')
    plt.show()

visualize(grid, path, start, goal)

运行与验证

运行方式:将代码保存为 astar_grid.py,在已安装 numpy 与 matplotlib 的Python环境中执行 python astar_grid.py。

验证方法:观察弹出的可视化窗口,确认黄色路径从绿色起点(0,0)出发,绕过红色障碍物区域,最终到达蓝色终点(9,11)。路径应连续且不穿越任何障碍物栅格。

判定标准:若路径成功显示且未与障碍物重叠,则算法实现正确。可将起点改为(0,0)、终点改为(9,11),预期输出路径长度(步数)为19步(曼哈顿距离下界为20,因绕行障碍物增加1步),该数值可由代码逻辑直接推出,用于核对路径正确性。