
简介本资源是一个基于OpenAI Gym框架构建的多智能体追逃博弈强化学习教学与开发平台面向人工智能、自动化、电子信息等专业的高校学生、教师及科研人员适用于毕业设计、课程实践与算法原型验证。平台完整实现2D/3D环境下的多智能体协同追逐与规避策略包含FlightGear、JSBSim、Fdm等多类仿真引擎适配模块并提供自组织均匀多边形编队、高度错开防碰撞等典型算法实现。压缩包共53个文件以31个Python源码含envs环境定义、agent策略、test测试脚本、5个XML配置、2个PNG流程图、1个GIF动态演示及1份详尽设计报告DOCX为核心总大小3.1MB结构清晰、模块解耦便于理解强化学习环境建模与多智能体协作机制。目前已有79人下载学习配套源码经严格测试可直接运行附带requirements依赖说明与多维度测试用例支持快速复现、调试与二次开发。1. 这不是“多个智能体一起跑”而是让追击者与逃逸者真正学会博弈——一个基于 Gym 的多智能体追逃环境能复现论文级交互逻辑支持策略热插拔、状态可追溯、训练过程可中断续训你可能已经用过单智能体的 CartPole 或 LunarLander但当场景变成「2个追击者围堵1个高机动逃逸者」时Gym 原生环境就彻底失效了动作空间不统一、观测无法隔离、奖励函数无法按角色差异化设计、甚至 step() 返回的 tuple 根本不兼容多智能体语义。这个名为“多智能体追逃博弈强化学习平台”的项目正是为解决这一断层而生——它不是简单地把多个 agent 塞进同一个 env而是重构了 Gym 的底层交互契约每个 agent 拥有独立动作空间离散/连续可选、角色专属观测域含相对位置、速度矢量、视野遮挡掩码、可解耦的 per-agent reward追击成功0.8逃逸存活每步0.1碰撞惩罚-0.5且所有状态变更严格遵循同步 step 协议。它面向两类人一是想在真实博弈场景中验证 MARL 算法如 MAPPO、QMix、IQL的研究者二是需要快速搭建对抗仿真基座的机器人控制/无人系统工程师。源码中已预置 PyTorch 训练脚本、完整设计报告含状态空间建模推导、纳什均衡存在性分析、通信带宽约束下的局部观测设计、以及三个收敛模型MAPPO-v1 追击策略、IQL-v2 逃逸策略、混合策略 checkpoint开箱即可启动对抗 rollout无需从零实现环境胶水层。2. 用 Gym 兼容接口定义多智能体追逃环境从状态空间建模到 step 协议重载为什么必须绕过 gym.wrappers 而选择直接继承 gym.Env2.1 追逃博弈的核心状态变量设计为什么不能直接复用 single-agent 的 Box 观测空间在单智能体环境中observation_space gym.spaces.Box(low-np.inf, highnp.inf, shape(4,))足以描述小车杆角度与角速度。但在追逃场景中每个 agent 的观测必须满足角色一致性与信息不对称性双重约束追击者需感知逃逸者相对方位与距离但无法获知其内部决策状态逃逸者需感知最近追击者的朝向与加速度但不应看到其他追击者的隐藏指令队列。因此本平台采用分层观测结构# 在 env/__init__.py 中定义 self.observation_space { pursuer_0: gym.spaces.Dict({ relative_pos: gym.spaces.Box(-10.0, 10.0, shape(2,)), # 相对逃逸者坐标 (dx, dy) relative_vel: gym.spaces.Box(-5.0, 5.0, shape(2,)), # 相对速度矢量 pursuer_1_pos: gym.spaces.Box(-10.0, 10.0, shape(2,)), # 另一追击者位置仅提供粗粒度协同信息 obstacle_mask: gym.spaces.MultiBinary(4) # 4方向障碍物存在性0/1 }), pursuer_1: ... # 同构但视角不同 evader: gym.spaces.Dict({ nearest_pursuer_dist: gym.spaces.Box(0.0, 15.0, shape(1,)), nearest_pursuer_angle: gym.spaces.Box(-np.pi, np.pi, shape(1,)), self_velocity: gym.spaces.Box(-3.0, 3.0, shape(2,)), escape_route_score: gym.spaces.Box(0.0, 1.0, shape(1,)) # 基于势场法实时计算的逃生路径质量分 }) }注意gym.spaces.Dict是 Gym 0.26 的正式特性早于该版本需手动 patch__contains__方法。若使用旧版 Gym必须将 Dict 展平为Box(shape(N,))并在 reset()/step() 中硬编码索引映射——这会导致状态维度随 agent 数量线性膨胀且丧失语义可读性。本平台强制要求 Gym ≥ 0.26避免此类技术债。2.2 重载 step() 实现真正的多智能体同步更新为什么 action 字典必须按 agent key 对齐Gym 原生step(action)接收单个标量或数组而多智能体必须接收{agent_id: action}字典。关键在于所有 agent 的动作必须在同一物理时间步内生效且状态更新顺序不可依赖。本平台通过以下逻辑保证原子性def step(self, action_dict): # 1. 验证输入完整性确保所有活跃 agent 的 action 均存在 assert set(action_dict.keys()) set(self.agents), \ fMissing actions for agents {set(self.agents) - set(action_dict.keys())} # 2. 批量解析动作避免循环中调用物理引擎导致精度漂移 velocities {} for agent_id in self.agents: if pursuer in agent_id: # 追击者动作[thrust_x, thrust_y, rotate_rate] → 三维连续控制 thrust np.clip(action_dict[agent_id][:2], -1.0, 1.0) rotate np.clip(action_dict[agent_id][2], -0.5, 0.5) velocities[agent_id] self._apply_dynamics(agent_id, thrust, rotate) else: # evader # 逃逸者动作[steer_angle, throttle] → 二维连续控制 steer np.clip(action_dict[agent_id][0], -0.8, 0.8) throttle np.clip(action_dict[agent_id][1], 0.0, 1.0) velocities[agent_id] self._apply_car_dynamics(agent_id, steer, throttle) # 3. 统一更新所有 agent 位置使用固定时间步长 0.1s for agent_id in self.agents: self.state[agent_id][pos] velocities[agent_id] * 0.1 self.state[agent_id][vel] velocities[agent_id] # 4. 计算 per-agent reward termination condition rewards, dones, infos self._compute_rewards_and_dones() # 5. 构建符合 PettingZoo/MARL 标准的返回元组 obs_dict {aid: self._get_observation(aid) for aid in self.agents} return obs_dict, rewards, dones, infos表step() 返回值字段说明与 MARL 框架兼容性对照字段类型说明兼容框架obs_dictDict[str, Any]键为 agent_id值为该 agent 的观测字典PettingZoo, RLlib, TorchMARLrewardsDict[str, float]每个 agent 的即时奖励含正负值所有主流 MARL 训练器donesDict[str, bool]agent 级终止标志非全局 done支持部分 agent 终止RLlib 的multiagentmodeinfosDict[str, Dict]包含collision_count,min_distance_to_evader等调试字段自定义 callback 解析2.3 reward 函数的博弈论设计如何用稀疏奖励引导纳什均衡收敛单纯设置“追到即 1”会导致策略坍缩为守株待兔——逃逸者学会原地打转追击者放弃协同。本平台采用分层奖励塑形基础层稀疏evader_captured True → pursuer_reward 0.8, evader_reward - 1.0行为层稠密pursuer_reward -0.01 * distance_to_evader鼓励逼近evader_reward 0.05 * (1.0 / (distance_to_nearest_pursuer 0.1))惩罚被围协同层隐式当两追击者距离 1.5m 且夹角 120° 时额外 0.2 协同奖励通过_compute_rewards_and_dones()内部计算这种设计使 MAPPO 在 200k 步内稳定收敛到「三角包抄」策略而 IQL 在逃逸任务中学会利用障碍物折返——这正是设计报告第 3.2 节所论证的局部最优与全局纳什均衡的可分离性。3. 训练脚本实操用 PyTorch 复现 MAPPO 追击策略从环境加载到模型保存的完整命令链3.1 环境注册与实例化为什么必须调用 register_env() 而非直接 importGym 本身不支持动态注册多智能体环境因此本平台在env/__init__.py中显式调用from gym.envs.registration import register register( idMultiAgentPursuitEvade-v0, entry_pointenv.pursuit_evade_env:MultiAgentPursuitEvadeEnv, max_episode_steps256, kwargs{num_pursuers: 2, num_evaders: 1, map_size: 10.0} )这样做的好处是RLlib、Ray Tune 等分布式训练框架可通过字符串 ID 加载环境无需修改训练器源码。验证注册是否成功python -c import gym; env gym.make(MultiAgentPursuitEvade-v0); print(env.reset())若报错gym.error.UnregisteredEnv请确认PYTHONPATH包含项目根目录并执行pip install -e .项目根目录下有 setup.py。3.2 MAPPO 训练脚本核心参数配置哪些超参决定收敛速度与策略鲁棒性训练脚本train_mappo.py的关键参数如下对应config.yaml# config.yaml env_config: num_pursuers: 2 num_evaders: 1 map_size: 10.0 use_local_obs: true # 是否启用局部观测关闭则提供全局状态用于消融实验 algorithm: name: MAPPO lr: 3e-4 gamma: 0.99 gae_lambda: 0.95 clip_param: 0.2 ppo_epoch: 10 num_mini_batch: 8 network: actor_hidden_dim: [256, 256] critic_hidden_dim: [256, 256] use_orthogonal_init: true gain: 0.01 # 防止初始策略过于激进 train: num_env_steps: 200000 num_processes: 4 # 并行环境数 num_steps: 128 # 每个进程的 rollout 长度 use_linear_lr_decay: true提示num_steps: 128是平衡训练稳定性与 GPU 显存的关键——小于 64 会导致 GAE 估计偏差增大大于 256 则易因 long-horizon 依赖引发梯度爆炸。实际训练中建议先用num_steps: 64快速验证环境逻辑再逐步提升。3.3 一行命令启动训练并监控如何用 TensorBoard 查看多智能体 reward 分布# 启动训练假设已在项目根目录 python train_mappo.py --config config.yaml --log-dir ./logs/mappo_pursuit --seed 42 # 实时查看各 agent reward 曲线TensorBoard tensorboard --logdir./logs/mappo_pursuit --bind_all在 TensorBoard 的SCALARS标签页中你会看到三条 reward 曲线reward/pursuer_0主追击者累积 rewardreward/pursuer_1协同追击者 reward应与 pursuer_0 高度相关reward/evader逃逸者 reward应呈缓慢下降趋势表明被有效压制若pursuer_0reward 在 50k 步后停滞在 0.3~0.4而evaderreward 仍 -0.2说明协同不足——此时应检查config.yaml中的use_local_obs: false强制全局观测或增加clip_param: 0.1提升策略更新保守性。3.4 模型保存与加载为什么 checkpoint 必须包含 optimizer state训练脚本默认每 10k 步保存一次完整 checkpoint# 在 train_mappo.py 的 save_checkpoint() 中 torch.save({ epoch: epoch, actor_state_dict: actor.state_dict(), critic_state_dict: critic.state_dict(), optimizer_actor_state_dict: optimizer_actor.state_dict(), # ← 关键 optimizer_critic_state_dict: optimizer_critic.state_dict(), best_reward: best_reward, }, f{args.log_dir}/checkpoint_{epoch}.pth)注意若只保存模型参数state_dict()从中断点恢复训练时 optimizer 的 momentum、Adam 的 running averages 将丢失导致前 1k 步性能大幅波动。本平台提供的model_final.pth已包含 optimizer state可直接python train_mappo.py --load-path ./models/model_final.pth续训。4. 追逃策略可视化与对抗测试用 rollout.py 生成 GIF 并定量分析胜率、平均追捕时长、策略熵4.1 生成对抗 rollout GIF如何用 matplotlib.animation 渲染多智能体轨迹rollout.py提供一键渲染功能python rollout.py \ --env-id MultiAgentPursuitEvade-v0 \ --model-path ./models/mappo_pursuit/model_final.pth \ --num-episodes 5 \ --render-gif ./gifs/pursuit_vs_evader.gif \ --fps 24该命令会加载训练好的 MAPPO 追击策略pursuer_0,pursuer_1使用预置的 IQL 逃逸策略evader位于./models/evader_iql.pth每 episode 渲染 256 帧叠加 agent 轨迹线、速度矢量箭头、碰撞区域高亮生成的 GIF 中你能清晰观察到追击者如何动态调整三角阵型两追击者夹角维持 110°±15°逃逸者在障碍物边缘的蛇形机动每 3~5 步改变转向方向当距离 0.8m 时触发的红色碰撞标记表示追捕成功4.2 定量评估指标提取从 rollout 日志中解析胜率与策略熵rollout.py默认输出 JSON 格式评估报告{ episodes: 5, success_rate: 0.8, avg_capture_step: 142.6, evader_survival_rate: 0.2, pursuer_entropy: [0.42, 0.38], evader_entropy: 0.67, collision_count: 3 }其中pursuer_entropy是策略网络输出动作概率分布的香农熵连续动作通过 Gaussian policy 的 std 计算值越低说明策略越确定。若pursuer_entropy 0.2表明策略过拟合特定地图布局——此时应启用env_config.random_obstacles: true增加环境随机性。表关键评估指标阈值参考基于 100 场对抗测试指标合格阈值优秀阈值诊断意义success_rate≥ 0.7≥ 0.85追击策略有效性avg_capture_step≤ 160≤ 120策略效率步数越少越优pursuer_entropy0.3 ~ 0.50.4 ~ 0.45策略鲁棒性过高随机过低死板evader_survival_rate≤ 0.3≤ 0.15逃逸策略抗压能力4.3 策略热替换实战如何在不重启环境的情况下切换逃逸者算法rollout.py支持运行时策略注入# 启动一个长期运行的 rollout 进程监听策略文件变化 python rollout.py \ --env-id MultiAgentPursuitEvade-v0 \ --pursuer-model ./models/mappo_pursuit/model_final.pth \ --evader-model ./models/evader_iql.pth \ --watch-models # ← 启用文件监听此时当你将新训练的evader_ppo.pth覆盖原文件进程会在下一个 episode 自动加载——这使得 A/B 测试不同逃逸算法IQL vs PPO vs Rule-based变得极其高效。设计报告第 5.1 节指出IQL 在障碍密集区胜率比 PPO 高 12%但 PPO 在开阔地形响应延迟低 37ms这种差异只有通过热替换才能实时对比。5. 进阶技巧用 world model 预测多智能体交互将 rollout 延伸至 10-step 未来状态推演5.1 为什么标准 rollout 不足以支撑长周期规划——从 1-step 到 multi-step 的 gap当前rollout.py的step()调用是单步物理仿真每次调用都触发完整动力学计算含碰撞检测、摩擦力积分。若想预测「如果 pursuer_0 向左急转3 步后 evader 的最优反制动作是什么」逐帧仿真 3 步耗时约 120msCPU无法满足实时决策需求。解决方案是构建轻量级 world model本平台在world_model/目录下提供预训练的 MLP-based dynamics predictor# world_model/dynamics_predictor.py class DynamicsPredictor(nn.Module): def __init__(self, state_dim12, action_dim3, hidden_dim128): super().__init__() self.net nn.Sequential( nn.Linear(state_dim action_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, hidden_dim), nn.Tanh(), nn.Linear(hidden_dim, state_dim) # 预测 next_state delta ) def forward(self, state, action): # state: [p0_x,p0_y,p0_vx,p0_vy, p1_x,p1_y,p1_vx,p1_vy, e_x,e_y,e_vx,e_vy] # action: [p0_thrust_x,p0_thrust_y,p0_rotate, p1_thrust_x,...] → 截取对应 agent 动作 delta self.net(torch.cat([state, action], dim-1)) return state delta * 0.1 # 0.1s 时间步长该模型在 100k 条真实 rollout 数据上训练MAE 0.08m位置误差可在 2ms 内完成单步预测。5.2 用 world model 实现 10-step rollout 并可视化预测轨迹predict_rollout.py提供多步推演接口python predict_rollout.py \ --model-path ./world_model/dynamics_predictor.pth \ --init-state ./data/init_state_001.npz \ --horizon 10 \ --pursuer-policy ./models/mappo_pursuit/model_final.pth \ --evader-policy ./models/evader_iql.pth \ --output-gif ./gifs/predicted_trajectory.gif生成的 GIF 中白色虚线显示预测的 10 步轨迹红色实线为实际执行轨迹——二者在前 5 步高度重合误差 0.15m第 6 步开始因未建模的随机扰动如数值积分误差累积出现发散。这正是设计报告第 4.3 节强调的world model 的有效 horizon 为 5~6 步超出此范围需引入 belief state 更新机制。5.3 将 world model 集成到训练循环用 model-based auxiliary loss 提升样本效率在train_mappo.py中添加 world model 辅助任务只需 3 行代码# 在 training loop 中 pred_next_state world_model(current_state, action) loss_world F.mse_loss(pred_next_state, next_state) # next_state 来自真实 env.step() total_loss ppo_loss 0.1 * loss_world # 权重 0.1 防止主导梯度实测表明加入该辅助 loss 后达到相同 success_rate 所需的环境交互步数减少 22%从 200k → 156k尤其在稀疏奖励阶段前 50k 步提升显著——因为模型通过预测任务隐式学习了状态转移的底层规律而非仅拟合 reward signal。本文还有配套的精品资源点击获取