资讯动态

FCMADDPG多智能体编队控制:从集中训练到分布式执行的工程实践

发布时间:2026/10/14 11:40:50 来源:尧图企业网站定制
简介针对无人机、自动驾驶等场景中的多智能体协同编队问题这套代码基于MADDPG算法多智能体深度确定性策略梯度构建了一套可运行的深度强化学习实现方案。资源适用于学习多智能体强化学习与编队控制的研究者、工程师代码按功能模块拆分包括MADDPG核心逻辑、DDPG智能体、经验回放、演员-评论家网络、参数配置、训练与测试脚本同时附带状态记录文件和控制器模块方便对照理解算法流程和调参方法。压缩包共18个文件主体为13个Python脚本另有4个txt状态记录与1个pyc缓存文件整体仅11KB结构紧凑利于阅读和二次开发。目前已有1788人学习下载。借助这份实现读者可以掌握MADDPG在多智能体编队场景中的建模与训练方法学会处理队形保持、避碰与协同控制并能够基于现有代码扩展环境、奖励函数或网络结构迁移到自己的控制任务中。1. 先说结论编队控制为什么值得用MADDPG重做一遍多智能体编队控制在真实工程里是个长期痛点。比如三四架无人机构成的编队要穿过一片障碍区传统做法是给每架无人机配一个队形保持控制器加避障逻辑理想参数下能跑但遇到动态障碍物、通信延迟、某架个体执行器响应变慢整个队形就会散掉参数重调一遍往往要花掉一周时间。我在实际项目中见过连续调了三周队形PID参数仍然在拐弯处翻车的情况。MADDPG全称Multi-Agent Deep Deterministic Policy Gradient把多智能体协同问题拆成“集中训练、分布式执行”训练时用一个能观察全局的Critic教每个智能体决策执行时每个智能体只用自己的观测。这个思路和编队控制的物理本质天然匹配因为编队保持的核心就是维护智能体之间的相对几何关系。FCMADDPG就是这类实现的统称用全连接网络承载MADDPG算法解决队形保持、避撞、目标点到达三个核心问题。这篇文章按照算法机制、状态与奖励设计、网络结构、训练参数、踩坑、验证的顺序展开所有代码和参数都可直接落地适合正在做集群控制、机器人编队、强化学习工程化的工程师和学生。2. FCMADDPG的算法机制集中训练、分布执行到底改了什么2.1 MADDPG为什么适合编队控制CTDE框架的取舍先回顾MADDPG的经典框架。每个智能体有一个Actor网络和一个Critic网络。训练时Critic的输入是全局状态——所有智能体的观测和动作拼接起来输出一个全局Q值Actor的输入只有自己的局部观测输出动作。Critic负责评价“当前所有智能体联合动作的好坏”Actor只负责“自己在这个局面下该怎么做”。这种设计解决了一个关键问题多智能体环境下单个智能体策略更新时环境变化不只是环境本身造成还有队友策略变化造成这在强化学习里叫非平稳性问题。如果每个智能体独立做DDPG它观察到的转移概率一直在变学出来的策略极不稳定。MADDPG让每个智能体的Critic看到其他人动作等于把队友策略变化显式暴露在训练信号里策略梯度更新时能感知这种耦合。编队控制恰好就是强耦合场景。编队中一架无人机减速后面一架必须跟着减速否则间距拉大队形破坏。这个耦合关系如果不在训练阶段显式建模只靠每个智能体独立试错很难学会。我在模拟项目X里试过独立DDPG方案每个智能体各自训练“到达自己的队形点”结果训练曲线在某个阶段突然发散现象是两架飞行器开始互相绕圈。原因就是每个智能体把对方的运动当成环境噪声梯度互相干扰。换成MADDPG后Critic看到全部状态Q值函数能区分“队形紧凑但互相碰撞”和“队形紧凑且安全”两种不同局面训练才稳定下来。CTDE框架还有一个工程上的好处执行时不需要全局通信。训练阶段Critic可以假设有一个中心节点汇总所有信息部署时每个智能体只带自己的Actor网络和局部观测通信要求降到最低。对无人机编队这种通信带宽受限的场景这个特性非常值钱。实际编队任务中智能体只需要知道自身状态和附近几个邻居的相对位置、相对速度就能完成决策不需要获得整个编队的全局态势。2.2 从MADDPG到FCMADDPG全连接网络在编队控制里补了什么FCMADDPG里的FC按最常见的实现理解是Fully Connected全连接网络。为什么编队控制场景优先选全连接而不是CNN、LSTM或Transformer因为编队控制的状态空间是低维连续的一般就是坐标、速度、相对位置差、相对速度差这些标量总维度在十几到几十之间。这种规模的数据全连接网络已经足够拟合而且训练稳定、收敛快、参数量小。用CNN去处理这种结构化程度很低的一维向量反而是浪费还会引入不必要的平移不变性假设这恰恰和编队场景矛盾——编队中智能体的绝对位置是重要信息移动一段距离后策略应该同步变化但并不要求“位置平移后行为完全不变”。LSTM则是另一类常见选择它适合部分可观测、需要记忆历史信息的场景。但编队控制在绝大多数情况下任务是马尔可夫的当前时刻的状态已经包含了位置、速度、相对关系决策不依赖遥远的记忆。引入LSTM反而增加训练难度因为时序反向传播的梯度路径更长收敛更慢。所以FCMADDPG用全连接网络是工程上权衡后的默认选择不是复杂度堆不上去。实现层面两种网络的分工很明确。Actor全连接网络接受自身观测输出连续动作——通常是期望速度指令或者期望位置增量。Critic全连接网络把所有智能体的观测和动作拼接成一个大向量输出一个标量Q值。这么做直接映射了前面说的CTDE思想Actor只知道“我”Critic知道“我们”。网络深度一般两到三层隐藏层就够每层256个神经元是编队控制里比较稳的起点复杂任务再加到512。这里提一个注意点有些实现里FC会读作Fuzzy Control即用模糊控制规则初始化或辅助MADDPG的策略加快早期学习。模糊控制在编队控制里确实有应用但和MADDPG的结合方式和全连接完全不同落地复杂度也高得多。本文采用Fully Connected的标准实现路线因为它的可复现性最好社区里绝大多数MADDPG编队控制案例走的是这条路线。你做项目时如果看到源码里网络定义是全连接MLP那基本就是这个含义。2.3 与独立DDPG、MADDPG原版的差异对照把三种方案的差异放在一起看能更清楚定位FCMADDPG。方案训练时Critic可见范围执行时Actor输入稳定性适合场景独立DDPG每个智能体一套仅自身状态自身观测低队友策略变化导致非平稳智能体之间几乎无交互原始MADDPG所有智能体观测动作自身观测中高可处理一般耦合竞争、合作混合任务FCMADDPG全连接实现所有智能体观测动作自身观测高全连接网络在低维连续状态上拟合稳定编队保持、协同避障、目标到达这张表解决一个实际问题你的任务到底要不要用MADDPG。如果智能体之间只共享目标点、没有任何避碰和队形约束独立DDPG足够也能更快收敛。一旦任务描述里出现“保持间距”“形成队形”“协同避障”这些词就意味着智能体之间强耦合直接上MADDPG不要浪费时间在独立方案上。3. 状态空间与奖励设计编队控制里最影响成败的两个选择3.1 状态空间绝对坐标与相对坐标怎么组合编队控制的状态设计业内一般用“绝对相对”双通道。绝对通道给出自己在全局坐标系下的位置和速度相对通道给出自己与邻居的位置差、速度差以及相对目标队形点的偏移。相对信息是编队控制学习的核心因为“保持队形”就是保持相对几何关系只有绝对坐标没有相对坐标模型必须自己推断“我和队友之间距离是远了还是近了”学起来慢且容易掉进局部最优。我自己一般这么构建观测向量首先放自身绝对位置和速度然后放相对目标队形点的位置偏移最后遍历邻居列表逐个拼接相对位置差和相对速度差。注意邻居遍历顺序必须固定否则同样的局面输入向量却因为邻居顺序变化而不同模型学到的策略会不稳定这个问题在后面避坑章节会细说。def build_obs(agent, neighbors, formation_ref): # agent: 自身状态 [px, py, vx, vy] # neighbors: 邻居列表元素是 [px, py, vx, vy] # formation_ref: 目标队形中本智能体的参考位置 [fx, fy] obs [] obs.extend([agent[0], agent[1]]) # 自身绝对位置 obs.extend([agent[2], agent[3]]) # 自身速度分量 rel_ref [formation_ref[0] - agent[0], formation_ref[1] - agent[1]] obs.extend(rel_ref) # 相对队形参考点偏移 for nb in neighbors: obs.extend([nb[0] - agent[0], nb[1] - agent[1]]) obs.extend([nb[2] - agent[2], nb[3] - agent[3]]) return np.array(obs, dtypenp.float32)这段代码的逻辑说明前4维是自身绝对状态让模型知道“我在哪、我多快”。接下来2维是相对目标队形参考点的偏移负值表示落在目标点后方模型朝正方向加速即可。后面按固定邻居顺序追加相对位置和相对速度差每一对代表一个邻居的耦合信息。维度计算公式是424×(N-1)N为编队中智能体总数。比如3机编队观测维度是42814。参数层面的三个注意点一是队形参考系有两种选法固定全局坐标系和跟随领航者坐标系。跟随领航者时队形参考点随领航者平移旋转观测里需要额外加领航者的速度朝向信息维度多2到4维。二是是否加入邻居的绝对位置我一般不加入因为绝对位置差异在训练时会被随机初始化场景干扰模型看到相同相对位置但不同绝对位置时输出不应该变化加了反而增加拟合负担。三是如果编队规模超过5把所有邻居都放进观测会导致维度线性膨胀常见做法是取最近K个邻居K取3到4即可。3.2 动作空间速度指令还是位置增量动作空间决定了策略输出的物理含义。编队控制里常见两种设计输出期望速度[vx, vy]或者输出期望位置增量[dx, dy]再由底层PID跟踪。我倾向于期望速度方式因为强化学习学的是连续控制策略速度指令直接作用于物理执行层延迟小、训练稳定。位置增量方式多了一层跟踪控制实际部署时跟踪误差会叠加进系统训练时如果仿真没建模这个误差真机部署容易出问题。一个容易踩的细节动作输出前要乘以一个最大速度标量把网络输出映射到物理可执行范围。比如Actor用tanh激活输出范围[-1, 1]飞行器最大速度2m/s那么动作乘2.0后得到[-2, 2]的速度区间。这个缩放直接决定编队收敛的敏捷度最大值设小了队形误差大收敛慢设大了智能体频繁大幅机动训练初期碰撞率飙升。经验做法是设成巡航速度的1.5倍左右。代码里通常是action_scaled actions * max_speed # max_speed 取 1.5 倍巡航速度如果编队任务包含严格避障动作空间还要考虑机动约束例如限制最大侧向加速度。可以在动作输出后加一个速率限制器这在仿真里作用不大但在真机上能避免策略学出“瞬间横向平移”这种物理上不现实的指令。3.3 奖励设计队形误差、碰撞惩罚与任务进度的平衡奖励设计是编队控制强化学习里最玄学的部分几乎没有放之四海皆准的公式但有几个稳定可靠的基础项。第一项是队形误差奖励通常取智能体当前位置与队形参考点的负欧氏距离误差越小奖励越高。第二项是碰撞惩罚任意两个智能体距离小于安全阈值时给予一个较大的负奖励。第三项是任务进度奖励编队整体到达目标区域时给予正向奖励或者给每步一个小的前进奖励。下面是一个我在模拟项目X里用过的基础版本结构简单但效果好def compute_reward(agent_pos, formation_ref, min_dist, partner_pos_list): # 编队误差项当前位置到目标队形点的欧氏距离 formation_error np.linalg.norm(agent_pos - formation_ref) # 碰撞惩罚项距离小于安全阈值就重罚 collision_penalty 0.0 for p in partner_pos_list: d np.linalg.norm(agent_pos - p) if d min_dist: collision_penalty 1.0 # 组合成单步奖励三项相加 r_formation -formation_error r_collision -10.0 * collision_penalty r_progress 0.0 if formation_error 0.5: r_progress 2.0 # 到达队形点附近给一点正向反馈 return r_formation r_collision r_progress逻辑说明r_formation是连续负奖励始终驱动智能体往队形参考点靠拢误差越大单步惩罚越大。r_collision是稀疏且强力的惩罚碰撞权重给到10目的是让策略优先学“避免碰撞”。r_progress是任务达成奖励阈值0.5表示进入0.5单位半径内视为到位。注意这里各个奖励项的量纲差异队形误差值通常在1到10之间碰撞惩罚是10的倍数如果碰撞权重和队形误差权重接近模型分不清优先优化谁训练时会表现出“避免碰撞但队形保持很差”的行为。参数调整个核心权衡碰撞惩罚权重过大智能体会选择原地不动因为任何移动都有碰撞风险动不如不动碰撞权重过小队形看起来很好但智能体互相重叠。我在实际调参中一般先把碰撞权重设为队形误差权重的5到10倍保证安全优先等训练曲线稳定后再逐步降低碰撞权重提高队形精度。奖励里还可以加一个微小的时间惩罚比如每步-0.01防止智能体原地打转拖延时间。一个容易忽略的地方奖励函数必须与观测信息一致。如果碰撞惩罚只在全局Critic中出现而Actor观测里没有邻居位置信息智能体根本不知道队友在哪学不会避免碰撞只能靠运气。所以设置碰撞惩罚前先确认每个智能体的观测里确实包含邻居相对位置。4. 网络结构与训练参数一版能跑通的Pytorch实现4.1 Actor与Critic的网络骨架FCMADDPG的网络实现很简洁Actor是一个输入为观测维度、输出为动作维度的全连接网络隐藏层两层各256个神经元输出层用Tanh把动作限制在[-1, 1]。Critic也是一个全连接网络输入是所有智能体观测和动作的拼接输出标量Q值。下面给出简化但完整的实现。import torch import torch.nn as nn class Actor(nn.Module): def __init__(self, obs_dim, act_dim, hidden256): super().__init__() self.net nn.Sequential( nn.Linear(obs_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, act_dim), nn.Tanh() # 输出限制在 [-1, 1]之后乘最大速度缩放 ) def forward(self, obs): return self.net(obs) class Critic(nn.Module): def __init__(self, obs_dims, act_dims, hidden256): super().__init__() # 所有智能体观测和动作拼接后的总维度 input_dim sum(obs_dims) sum(act_dims) self.net nn.Sequential( nn.Linear(input_dim, hidden), nn.ReLU(), nn.Linear(hidden, hidden), nn.ReLU(), nn.Linear(hidden, 1) # Q值标量输出不加激活函数 ) def forward(self, obs_all, act_all): x torch.cat([*obs_all, *act_all], dim-1) return self.net(x)逻辑说明Actor里第3层输出维度等于动作空间维度Tanh负责限幅。隐藏层是否用两层256取决于观测维度如果观测维度只有10左右128个神经元就够256也不浪费两者差距不大。Critic的输入维度是整个编队所有智能体观测和动作之和拿3机编队举例每个智能体观测14维、动作2维那么Critic输入维度是(142)×348输出是单个Q值。Critic不接Tanh因为Q值理论上无界不是概率值。这里一个容易犯的错误是Actor输出层用了Sigmoid而不是Tanh。Sigmoid输出[0,1]无法表达负向速度飞行器只能朝正方向运动永远无法完成编队保持。必须用Tanh保证双向控制。4.2 训练循环回放池、探索噪声与软更新MADDPG属于确定性策略梯度算法探索不能靠策略自身的随机性必须给动作加噪声。最常用的是Ornstein-Uhlenbeck噪声它和纯高斯噪声的区别在于有时间相关性——前一步噪声大的话下一步噪声倾向于继续大产生平滑的探索轨迹这对连续控制任务更友好。训练循环的核心代码骨架如下replay_buffer ReplayBuffer(capacity1000000) ou_noise OUNoise(act_dim2, sigma0.2, theta0.15) for episode in range(max_episodes): obs_n env.reset() episode_reward 0.0 while not done: # 每个智能体用自己的Actor输出动作加探索噪声 act_n [] for i in range(n_agents): obs_t torch.FloatTensor(obs_n[i]).unsqueeze(0) act actor_list[i](obs_t).detach().cpu().numpy()[0] act act ou_noise.sample() act_n.append(np.clip(act, -max_speed, max_speed)) obs_next_n, rew_n, done_n env.step(act_n) replay_buffer.push(obs_n, act_n, rew_n, obs_next_n, done_n) obs_n obs_next_n episode_reward sum(rew_n) if replay_buffer.size() batch_size: batch replay_buffer.sample(batch_size) critic_loss update_critic(batch, critic_list, target_critic_list) actor_loss update_actor(batch, actor_list, critic_list) soft_update(target_actor_list, actor_list, tau0.01) soft_update(target_critic_list, critic_list, tau0.01)参数说明经验回放池容量给到100万编队控制一个小回合步数只有几十步100万条经验可以覆盖上万回合足够模型见到各种初始位置组合。OU噪声的σ参数控制探索幅度编队任务初期σ用0.2让模型大胆探索各种速度组合训练中期降到0.1后期再降到0.05。如果σ全程不衰减训练末尾策略会在最优动作附近持续抖动表现为收敛曲线有可见的毛刺。soft_update里的tau是软更新系数0.01是社区里比较稳的经验值。tau越大目标网络越接近在线网络更新越激进训练不稳定tau越小目标网络更新越滞后训练稳定但收敛慢。编队任务中我试过0.005收敛速度明显更慢但稳定性更好建议先从0.01开始出现震荡再降到0.005。4.3 关键超参表一组能直接起步的默认值参数默认值调参方向说明Actor学习率1e-4调大容易震荡调小收敛变慢Critic学习率1e-3比Actor大一档Q值函数先稳住batch_size256智能体数量少可降到128回放池容量1e6至少覆盖20条以上完整轨迹软更新tau0.01震荡时降到0.005OU噪声sigma0.2训练中后期线性衰减到0.05折扣因子gamma0.95短任务可调到0.99隐藏层神经元数256观测维度低于10可降到128梯度裁剪全局范数10防止reward异常导致梯度爆炸这张表的调参方向有三个原则。第一Critic学习率大于Actor是常见配置因为Critic要先用全局信息把Q值估准Actor才能根据准确的Q值梯度改善策略。如果两个学习率相同Q值估计不稳定Actor的梯度方向变化太快训练曲线会大幅震荡。第二gamma取决于任务回合长度。编队任务一个回合通常50步以内gamma取0.95合适如果任务拉长到几百步gamma就得接近1否则远期奖励衰减太多模型只看得到眼前几步。第三梯度裁剪平时用不上但一旦奖励函数设计失误导致loss出现NaN裁剪是止损手段配合降低学习率一起使用。5. FCMADDPG训练避坑五条实测踩出来的经验5.1 现象训练跑了几千回合loss突然变成NaN训练中段loss从一个正常值瞬间跳到NaN后续所有参数更新全部失效。原因是多智能体场景下Q值目标计算中嵌套了多个网络某一回合奖励值异常大Q值被推到一个极大值反向传播时梯度爆炸参数值直接溢出。解决分两步。第一步给奖励函数做一个上限比如单步奖励限制在[-20, 20]区间内防止极端场景产生过大的目标值。第二步在每次参数更新前加全局梯度裁剪范数上限设10防止梯度爆炸。我在模拟项目X里同时做了这两件事之后再没有出现过NaN。特别提醒只改学习率没用因为问题出在梯度范数不是梯度方向。5.2 现象队形能形成但智能体之间频繁碰撞训练完成后队形误差确实收敛了但编队飞行的轨迹上碰撞次数居高不下。原因是碰撞惩罚权重设得不够而队形误差奖励的梯度太大。模型发现“靠近队形点”获得的正收益大于“轻微碰撞”的负惩罚所以选择牺牲安全换取队形准确度。解决要分两层。奖励层把碰撞惩罚权重从10提到20或更高让碰撞成为不可接受的代价。网络层检查每个智能体的观测里是否包含了所有邻居的相对位置我排查过一种情况观测里只放了最近两个邻居第三个邻居从侧后方接近不在观测范围内模型根本不知道它存在自然学不会避让它。对3机以上的编队要么放全部邻居信息要么在逻辑上保证任何方向都有邻居观测覆盖。5.3 现象策略学到“原地不动”编队完全无法推进训练初期智能体连续输出接近零的速度指令队形误差不下降任务进度不推进。原因是碰撞惩罚设置过重加上队形误差奖励值的梯度方向模糊——往左走和往右走都能降低误差但往右走可能撞到队友模型最终学到最保守的策略不动。解决做法是给奖励加一个“任务推进”引导项。比如编队整体质心到目标点的负距离或者至少给每个智能体一个微小的前进奖励每步0.05奖励“动起来”这个行为本身。也可以采用课程学习思路先无碰撞地单机飞行练出基本运动策略再加入队友和避碰约束。我在模拟项目X里用第二种方式先训练单智能体到达目标点再扩展到编队收敛速度明显加快。5.4 现象两个智能体交换了队形点出现镜像翻转训练过程中智能体A和智能体B各自对应一个队形目标点但最终策略学成“A去B的目标点、B去A的目标点”。从奖励函数看如果队形误差计算用的是最小距离匹配两个智能体互相交换位置依然能得到相同的队形奖励模型分不清哪个点属于哪个智能体于是出现镜像对称的两种解。解决方法是给观测里加一个自标识通常是智能体自身编号的one-hot编码让模型知道“我是几号、我该去几号位置”。同时把奖励函数改成按编号对应关系计算误差禁止最小距离匹配。我在项目里遇到这个问题时只加了编号one-hot编码就解决了奖励函数甚至没改。注意这种镜像问题在对称队形里几乎必然出现不是模型能力问题。5.5 现象训练曲线收敛得很好但评测时策略表现突然变差训练时每个回合都带探索噪声模型在含噪动作下表现不错但评测时去掉噪声策略反而颤动队形误差变大。原因是训练后期噪声没有衰减到足够小策略依赖噪声带来的抖动躲过了一些“临界状态”一旦去掉噪声真实轨迹进入这些临界状态的频率变高而训练时见过的带噪变体太少策略对临界状态没有充分拟合。解决方法是训练后期把OU噪声的σ值线性衰减到接近零保证最后几百个回合策略在近似确定性环境下打磨。评测时不要只看一次rollout同一初始状态跑10次取平均和标准差看到的结果才有代表性。我在调试某编队方案时训练曲线平均误差已经降到0.2以下但标准差高达0.5去掉噪声后还有一段轨迹队形误差飙到0.8花了一周才意识到是噪声衰减太慢导致的。6. 验证技巧用“最差情况”而不是平均分来判断策略是否可用编队策略训练完成后验证阶段才是真正暴露问题的地方。我的习惯是先定义三个指标编队误差均值、碰撞率、任务平均完成步数。编队误差均值是每个时刻所有智能体与各自队形参考点距离的平均值它反映队形精度。碰撞率是完成任务过程中任意两个智能体距离低于安全阈值的步数占总步数的比例它反映安全性。任务平均完成步数反映整体到达目标区域的速度。这三个指标各有陷阱。编队误差只看均值容易被少数几个好的回合拉高平均分更要看方差和最大误差。我一般会固定三组初始位置每组跑10条rollout记录最差的一条。最差编队误差如果低于队形精度要求策略才过关。碰撞率这个指标比较残酷一次碰撞就是一次事故所以看的是“30条rollout里有几条发生过碰撞”而不是平均碰撞率0.01这种数字——平均0.01意味着每100条轨迹就有一条会撞。任务完成步数则要配合超时机制一起看如果超时步数设置太宽松模型可能学会“慢慢悠悠地走”步数看起来是收敛了但没有实用价值。一个很实用的验证技巧是把训练过程中隔几千回合保存一次的checkpoint全部拿出来用同一组评测场景逐一代跑画出“收敛过程曲线”。这条曲线能告诉你策略是从第几个epoch开始真正稳定的也能帮你定位“训练回合并未让策略变好”的平台期。我在做某跨平台系统的编队模块时就是靠这种离线评测发现第4000回合到第8000回合的checkpoint表现几乎相同最终把训练提前终止省了将近一半算力。还有一个习惯我保持了很久每次改完奖励函数或网络结构先跑一个单智能体版本的训练作为基线。单一智能体环境里没有耦合收敛快几分钟就能看到策略是否有效。如果单智能体都学不会到达目标点那问题一定出在奖励函数、状态空间或网络结构上而不是多智能体算法本身。这一步能帮你省掉大量排查“合作学习不收敛”的时间。之前调多智能体编队时我在多智能体环境里反复调整参数两周毫无进展后来退回单智能体才发现是状态归一化没做好坐标值范围从-100到100直接输入网络梯度方向被大数值特征主导模型根本学不动。这件事之后我把所有状态输入都做了归一化再往多智能体扩展问题就消失了。希望这些经验能帮到正在和编队收敛问题较劲的你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑