壹、函数构成
函数名 | 类型 | 功能 |
---|---|---|
init | 构造器 | 初始化环境参数 |
__init__map | 初始化方法 | 地图初始化控制中心 |
__parse_connections | 工具方法 | 解析连接关系 |
__init_special_tiles | 工具方法 | 加载预设奖励点 |
__init_random_start | 随机方法 | 随机生成智能体起点 |
__init_random_golds | 随机方法 | 随机生成奖励点 |
generate_random_maze | 随机方法 | 生成随机迷宫地图 |
detect_obstacles | 工具方法 | 检测障碍物 |
validate_connectivity | 检查方法 | 检查地图是否连通 |
_check_path_exists | 检查方法 | 检查奖励点是否可达 |
__check_reachable_from | 检查方法 | 检查某点是否能到达目标 |
get_vision | 观测方法 | 获取智能体视野信息 |
step | 执行方法 | 执行动作并返回结果 |
一、地图的初始化
init
│
└──> __init__map
│
├──> __parse_connections
├──> __init_special_tiles
├──> __init_random_start ───────┐
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad │
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad └──> __check_reachable_from ──> _check_wall
├──> generate_random_maze ─────┐
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad │
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad ├─> detect_obstacles
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad ├─> _check_path_exists ──> _check_wall
│ \quad \quad \quad \quad \quad \quad \quad \quad\quad \quad \quad \quad └─> validate_connectivity ──> _check_wall
└──> detect_obstacles
🧩 1. init 方法
功能:
初始化环境,设置网格大小、智能体数量、动作映射、地图结构、奖励点、起点等基础参数,并调用 __init__map 初始化地图。
调用关系:
调用:self.__init__map(...)
🗺️ 2. __init__map 方法
功能:
根据配置(随机或固定)初始化地图信息,包括墙、障碍物、起点、奖励点等。
调用关系:
调用:
self.__parse_connections(connections)
:解析连接关系。
self.__init_special_tiles()
:加载预定义的特殊奖励格子。
self.__init_random_start()
:随机生成智能体起点。
self.generate_random_maze(wall_prob)
:生成随机迷宫地图。
self.detect_obstacles()
:检测并更新障碍物。
self.validate_connectivity()
:验证地图连通性。
🔗 3. __parse_connections 方法
功能:
将传入的节点连接关系转换为地图中的“墙”的开闭状态,用于构建路径连通性。connection =[(0,1),(0,9),(1,2),(1,10),……(43,44),(43,53),],数据中的(i,j),表示连通性,转化为其坐标的化有row_i, col_i = divmod(i, self.size)
被调用者:__init__map
🎯 4. __init_special_tiles 方法
功能:
将预定义的 titlesTarget 奖励点转换为地图上的具体坐标位置,并存入 self.Golds
。
被调用者:__init__map
🚶 5. __init_random_start 方法
功能:
随机选择多个非障碍物格子作为智能体的初始位置,并确保这些位置能到达所有奖励点。
调用关系:
调用:self.__check_reachable_from(pos, targets)
被调用者:__init__map
💎 6. __init_random_golds 方法
功能:
在非障碍物格子中随机生成一定数量的奖励点,并赋予 [bool, int] 格式的属性。
被调用者:__init__map
(当启用随机模式时)
🔄 7. generate_random_maze 方法
功能:
根据指定概率随机生成水平和垂直墙,构造迷宫,并保证地图连通性和奖励点可达性。
调用关系:
调用:
self.detect_obstacles()
self._check_path_exists()
self.validate_connectivity()
被调用者:__init__map
🧱 8. detect_obstacles 方法
功能:
根据墙的状态判断每个格子是否为障碍物(四向封闭则视为障碍物)。
被调用者:
__init__map
generate_random_maze
🌐 9. validate_connectivity 方法
功能:
使用 BFS 检查整个地图是否连通,返回不可达的孤岛区域。
调用关系:
调用:self._check_wall(...)
判断是否被墙阻挡
被调用者:
__init__map
generate_random_maze
🔄 10. _check_path_exists 方法
功能:
检查从任意一个奖励点出发是否能到达所有其他奖励点。
调用关系:
调用:self._check_wall(...)
判断是否被墙阻挡
被调用者:generate_random_maze
🚶 11. __check_reachable_from 方法
功能:
使用 BFS 算法检查某个起点是否能到达一组目标点。
调用关系:
调用:self._check_wall(...)
判断是否被墙阻挡
被调用者:
__init_random_start
二、执行动作
👁️ 12. get_vision 方法
功能:
获取当前智能体周围 8 个方向的视野信息(障碍物、奖励点、其他智能体、空地),用于局部观测。
调用关系:
在 step 中更新智能体视野时调用。
🚦 13. step 方法
功能:
执行每个智能体的动作,处理移动、拾取、卸载逻辑,返回新的观测值、奖励、终止标志等。
调用关系:
调用:
self.get_vision(new_pos) 更新视野
self._check_wall(…) 判断是否被墙阻挡
🔄 14. reset 方法
功能:
重置环境状态,初始化所有智能体的位置、视野和状态。
三、加载地图
地图中的要素分为:
网格大小:size
智能体数量:num_agent
墙与通路:h_walls(水平墙,分割上下),v_walls(竖直墙,分割左右)
起始位置:listsStart,tuplesStart—>self.tarts
奖励格子:titlesGold---->self.Golds
出口位置:listExit,tupleExit—>self.Exits
生成地图分为三种模式
- 输入所有需要的数据生成完全固定的地图
- 输入部分需要的数据其他性质随机生成部分随机的地图
- 不输入任何数据,只输入随机种子,生成完全随机的地图
墙的理解
在该环境中,墙是以两个独立矩阵表示的:
- self.h_walls: 表示 水平方向的墙(即横向的墙),形状为 (size+1, size )。
h_walls[i][j] 表示位于 (i, j) 格子上方是否有墙。 - self.v_walls: 表示 垂直方向的墙(即纵向的墙),形状为 (size , size+1)。
v_walls[i][j] 表示位于 (i, j) 格子左侧是否有墙。
四、网格世界
import numpy as np
import gym
from gym import spaces
from collections import deque, defaultdict
from typing import Optional, List, Tuple, Dict, Union
import random
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle,Patch
# 9*9 ,用0~80开始标记grid的连通关系,且关系是双向的
titlesTarget = {
6: [False, 5],
7: [False, 3],
20: [True, 8],
21: [True, 6],
26: [True, 5],
42: [True, 4],
47: [False, 5],
52: [True, 4],
54: [False, 7],
58: [False, 4],
67: [False, 3]
} # False:代表车辆取,True代表车辆拿
class MapEnv(gym.Env):
def __init__(self, size, num_agent,
*,
randomStyle: bool = False,
startboder: bool = False,
connections: Optional[List[Tuple[int, int]]] = None,
num_gold: int=10,
num_exit:int =6,
titlesTarget: Optional[
Union[Dict[int, List[Union[bool, int]]], Dict[Tuple[int, int], List[Union[bool, int]]]]] = None,
starts: Optional[Union[List[int], List[Tuple[int, int]]]] = None, # 自定义起点
exits: Optional[Union[List[int], List[Tuple[int, int]]]] = None, # 自定义出口
wall_prob: Optional[float] = 0.7,
seed: Optional[int] = None):
self.size = size
self.num_agent = num_agent
self.randomStyle = randomStyle
self.seed = seed # 保存 seed
self.rng =None
# 设置全局随机种子(如果提供)
if self.seed is not None:
random.seed(self.seed)
np.random.seed(self.seed)
self._action_to_dela = {
0: (-1, 0), # 上
1: (1, 0), # 下
2: (0, -1), # 左
3: (0, 1), # 右
4: (-1, 1), # 拾起 (站点容量-1,站点空闲+1)
5: (1, -1) # 卸载 (站点容量+1,站点空闲-1)
} # action 的坐标变化
self._direction_to_action = {
(-1, 0): 0, # 上
(1, 0): 1, # 下
(0, -1): 2, # 左
(0, 1): 3 # 右
} ##仅仅是位移坐标
self.end_direction = (0,1)
agent_action_space = spaces.Discrete(6)
# 根据智能体数量动态创建动作空间
# self.action_space = spaces.Dict({f'agent{i}': agent_action_space for i in range(num_agent)}) #字典不太方便
self.action_space = spaces.Tuple([agent_action_space for _ in range(num_agent)])
self.currenttime = 0
self.deltatime = 10 # 公共间隔时间
####初始化信息###
self.Golds ={
}
self.Starts=[]
self.Exits =[]
###生成地图
self.__init__map(randomStyle=randomStyle,startboder =startboder,
num_gold=num_gold,num_exit=num_exit,
connections=connections,
titlesTarget=titlesTarget, starts=starts, exits=exits,
wall_prob=wall_prob, )
self.__info__()
def __info__(self):
print("起点信息:",self.Starts)
print("出口信息:",self.Exits_Sum)
print("奖励格子位置:", list(self.Golds.keys()))
print("障碍物位置:", [(int(x), int(y)) for x, y in zip(*np.where(self.obstacles))])
print("随机种子:",self.seed)
print("------")
def reset(self):
"""
1.初始化每个智能体的状态:当前位置,局部视野,装卸累计
2.根据动作,检测可行性,执行结果,变更状态
3.获得即时奖励。
"""
agents = {
}
for i in