2026/10/19 14:25:03

MoB行为多样性分层策略提升足式机器人地形泛化

MoB行为多样性分层策略提升足式机器人地形泛化 做足式机器人运动策略的朋友大概率都遇到过这种情况训练时各种地形都喂得够成功率也刷得很高但一旦换成训练分布之外的地面策略立刻“原形毕露”。我最近在复跑一个叫 walk_these_ways 的项目核心思路是通过行为多样性Modality of Behavior简称 MoB实现地形泛化。翻译成大白话就是不让策略只学会一种“最佳走法”而是逼它学会一批在动力学上真实可行、彼此又有明显区别的动作模态再由一个高层策略根据当前环境自动调度。这篇是学习记录的第一篇重点讲三件事MoB 为什么能改善地形泛化、行为库和调度策略是怎么训练出来的、以及我复现时踩过哪些坑。适合正在做强化学习足式控制、或者想了解分层策略如何提升迁移能力的朋友。如果你连 PPO 都还没跑通那建议先补点基础再回来看这篇内容会顺很多。1. 这个项目到底在解决什么问题从“一个动作打天下”聊起1.1 地形泛化为什么这么难足式机器人在地形泛化上的难点本质上是“一种策略工具应对无数种物理工况”的矛盾。传统方案里模型预测控制MPC依赖精确的动力学模型和接触假设地面稍微复杂一点预测就崩。端到端强化学习稍好但常规单策略训练学到的其实是所有训练地形的“平均行为”。这个平均行为在训练分布内看着没问题一旦遇到分布外的地形比如木箱堆、泥地、钢板缝隙拼接的路面策略输出的动作会迅速落在分布边缘最后只剩摔倒一种结果。我在复现前先跑过一个朴素实验把某开源四足机器人平台放在一个包含碎石、坡道、台阶的训练环境里单策略训练到收敛普通地形成功率能过 95%但放进一个没见过的“沙袋钢板”拼接路面成功率直接掉到 41%。我把日志拉出来看发现策略不是没有能力走而是它只会一种步态——遇到需要小碎步高抬腿的组合工况时它试图用原来的大步幅走法硬过结果脚被钢板边缘卡住。这其实暴露了一个深层问题常规 RL 策略把“观测到动作”压成了一个单一映射运动模式被隐式锁死。地形多样性在数据里确实存在但策略最终只提取出一个最“划算”的模式把它当作唯一答案。泛化失败不是模型容量不够而是模型把多模态问题简化成了单模态问题。1.2 MoB 的思路不让策略“只会走一种路”MoB 的核心态度是既然真实地形会激发不同的最佳步态那不如显式地把“多种走法”作为训练目标的一部分。项目的名字 walk_these_ways 本身就在玩这个梗——不是 walk this way而是 walk these ways强调“用这些多样的方式行走”。我特别喜欢一个类比以前是给机器人发一把固定规格的扳手遇到不同螺丝只能硬拧MoB 是给你一整层工具箱扳手、套筒、六角棒都在而且分门别类摆好。你不需要知道眼前螺丝的具体型号只要判断“它像哪种”然后抽对应工具就行。在技术实现上这个思路落地成分层策略低层策略学会一批行为Behavior高层策略负责根据地形特征选择行为。关键在于行为库本身覆盖了任务可能遇到的运动模式空间。新地形即使从未见过只要它能触发行为库中的某个或某几个行为机器人就能通过组合、切换甚至插值来应对而不是从头推理一套新步态。相比单策略MoB 的三个优势很明显。第一抗扰动某个行为在特定地形失效还有别的行为可切整体不会崩。第二可解释训练后每个行为对应的步态能被可视化描述比如“高抬腿跨步”“小碎步平走”比一张黑盒策略网络靠谱得多。第三决策频率低高层策略可以低频运行降低切换成本。2. MoB 核心机制拆解行为库、调度策略与多样性奖励2.1 三个模块行为库、调度策略、执行策略整个 MoB 系统可以拆成三个模块理解这三个模块的分工基本就懂了大半。行为库是一组可复用动作模态的容器。实现上我用的是一组低维嵌入向量比如 K8 个行为每个行为用 16 维向量表示。这些向量不是凭空定义的而是在训练中自动学习出来的——机器人发现“这样走能更快”“那样走更稳”“另一种方式能爬高”于是自然形成了不同的行为簇。调度策略是高层策略输入是环境描述和一段时间的历史观测输出是行为选择。它不需要管具体关节怎么动只看“当前该用哪个行为”。因为地形是慢变量这个策略的决策频率可以很低我设的是 20Hz而低层控制策略是 200Hz。执行策略是低层策略输入由两部分组成本体感受观测关节角、角速度、IMU、接触状态等加上当前被选中的行为嵌入向量输出是 12 个关节的动作目标。这个结构最妙的地方在于行为嵌入向量可以看作“风格参数”它的每一维都可能在引导网络去表达不同的步频、步高、侧向跨距等特征。模块输入输出运行频率行为库可学习参数K 个行为嵌入向量训练期更新高层调度策略地形特征 历史观测窗口行为选择编号或权重约 20Hz低层执行策略本体感受 行为嵌入12 关节动作目标约 200Hz为什么要拆两层而不是让一个网络自己学会多模态核心原因是时间尺度分离。地形变化是秒级的关节控制是毫秒级的如果放一个网络里同时处理训练会不稳定而且两个任务会互相干扰。分层后高层享受低频、低噪声的地形判断低层专心做本体的精细控制互不添乱。2.2 多样性奖励怎么设计才不翻车要让机器人自然分化出多种行为不能只靠网络自己涌现必须显式地在奖励函数里加“多样性”这一项。我参考常见实践用的奖励结构是R_total R_task λ · R_diversity任务奖励 R_task 保证行为“有用”包含前进速度、身体姿态稳定性、能耗惩罚等。多样性奖励 R_diversity 保证行为“不同”。我最初的设计是用足端轨迹特征来计算行为两两之间的距离距离越大多样性奖励越高。具体实现时有个细节不能用所有行为之间的平均距离得用“最小距离”。因为如果用平均距离网络会把行为们均匀推开结果每个行为都不够突出。用最小距离的话训练会让最相近的那两个行为持续互相排斥行为库的覆盖度更均匀。我复现时的经验是λ 初始给 0.05 左右然后每 100 万步查看行为嵌入之间的 pairwise 距离如果距离和 R_task 相比太小就把 λ 往上调一点否则不动。也有更高级的做法用判别器Discriminator来估计行为之间的可区分性。可以理解成玩捉迷藏——判别器负责猜“这段轨迹是哪个行为”策略负责让自己的轨迹带上稳定的个体特征。如果判别器一猜就中说明行为特征已经很鲜明如果判别器猜不中说明行为之间混沌不清需要加大多样性压力。这个方案训练更稳定但要控制判别器的更新频率否则策略会被“带节奏”。我的建议是先试简单的距离项不够再上判别器不要一上来就堆复杂度。2.3 行为表征为什么用嵌入向量而不是标签我最开始以为行为库就是一个离散列表每个行为一个 ID选的时候输出一个 one-hot。试过之后发现一个问题离散标签切不动平滑的动作空间。比如从“大步幅行走”切到“高抬腿跨越”中间存在大量过渡步态离散 ID 无法表达这种连续关系切换瞬间动作容易跳变。嵌入向量就不一样。行为嵌入空间天然是连续的网络能学到不同行为之间在步频、步高、姿态等维度上的渐进关系。极端情况下调度策略甚至可以输出两个行为的混合权重让执行策略做一个“行为插值”这在离散标签体系里完全做不到。我的低层策略条件输入大致长这样# K 个行为每个行为 16 维可学习向量 behavior_embedding nn.Parameter(torch.randn(K, 16)) # 低层策略每次输入 本体感受 当前行为的嵌入 obs_low torch.cat([proprio_obs, behavior_embedding[behavior_id]], dim-1) action low_level_policy(obs_low)这里有个实操心得行为嵌入作为可学习参数直接训练是最省事的方案。它自己就会慢慢长出有语义的维度——训练好后把每个行为的嵌入向量拿出来看会发现某些维度对应步高某些维度对应步频。不需要手工设计行为特征把空间留给优化过程自己摸索就好。3. 实操复现从仿真环境到训练参数的手把手记录3.1 仿真地形与域随机化设置复现第一步是搭环境。我用了常见的 GPU 并行物理仿真器跑在四足机器人平台模型上地形生成器按“分布”而不是“固定清单”来生成场景。训练区域是半径 8 米左右的圆形场地每次重置随机生成地形组合主要包括以下类型地形类型难度参数覆盖比例平地无30%斜坡5°~20°25%台阶高度 2~10cm20%乱石地石块高度 3~12cm15%湿滑地面摩擦系数 0.3~0.810%除了地形本身域随机化也做了不少。摩擦系数、地面阻尼、足端接触恢复系数、机器人质心偏移、关节力矩增益偏差全都在一定范围内随机化。这一步不能省它相当于给机器人打“环境免疫针”让它不会过拟合仿真器里特定的接触物理。另一个关键点训练地形分布要有梯度不能一开始就是满难度。行为库需要先在地形难度较低的时候完成分化如果一上来就复杂地形 多样性压力机器人既调不成行为库的特殊步态又追不上速度奖励两头不讨好。具体做法我会在下一节展开。3.2 三阶段训练流程与关键参数我最终把训练拆成三个阶段每个阶段完成不同的任务。这个顺序不是随便定的而是试出来的——一开始我图省事把所有奖励一次性全开结果好几天都在看不收敛的曲线。阶段一是平地预训练。只开任务奖励让机器人先学会基本行走。这一步的目的是给机器人一个“运动能力底座”让它先知道什么是走而不是一上来各种行为乱飞。我用了约 2500 万步模拟训练跑完以后平地速度奖励已经收敛机器人能稳定走直线。阶段二是行为分化。在阶段一的基础上加入多样性奖励K8。这一阶段只看行为库是否分化不看任务表现。每 50 万步记录一次行为嵌入之间的 pairwise 距离我观察到距离从早期的 0.2 左右一路涨到约 1.6然后趋于平稳。速度奖励会有短暂下降这是正常的因为策略不再只追求最快而是在“快”和“多样”之间找平衡。阶段三是联合训练。加入复杂地形、域随机化和高层调度策略整个系统一起训练。这个阶段我跑了约 3000 万步直到复杂地形成功率和行为切换频率都稳定。训练参数表如下这些值是我在自己环境里调出来的不是项目原版的最佳值但跑通完全够用参数数值算法PPO学习率3e-4GAE λ0.95折扣因子 γ0.99clip 范围0.2并行环境数4096行为数 K8行为嵌入维度16控制频率200Hz调度策略频率20Hz关于算法选型为什么用 PPO 而不是 SAC两个原因一是 PPO 在大量并行环境 连续控制任务上足够稳定接近开箱即用二是这个任务天然是 on-policy 的行为采集效率比 off-policy 更重要。有过 SAC 迁移到真机时对超参数敏感得让人头疼的经历之后这种项目前提下我更愿意相信 PPO。3.3 训练日志里最值得盯的四个指标训练过程中不要只看 total reward那个指标太混合看不出问题。我每次实验固定盯四个指标基本能覆盖大部分异常行为嵌入 pairwise 距离看行为库是否真的分化了。小于 0.5 说明行为之间还不够清晰可能坍缩大于 2.0 说明行为之间差异过大切换时容易不稳定。行为覆盖比统计每个行为在实际轨迹中被选中的频率。如果某些行为长期没有被选中说明它们是死掉的模态白白占了容量。切换频率高层策略每秒切换行为的次数。太高说明调度在抖动太低说明调度可能陷入某个局部最优没有自适应地改变策略。我的经验是稳态下 0.2~0.5 次/秒比较健康。复杂地形成功率每隔固定步数单独评估一遍所有训练地形上的成功率。这个不用多解释是最直观的泛化指标。我复现时阶段三完成后复杂地形成功率从之前单策略的 41% 提升到了 83%而且训练地形的平均速度只降低了 12%但能耗降低了约 20%。速度慢了但整体“通过效率”其实是提高了因为不再频繁摔倒重试。4. 复现中踩过的坑行为坍缩、切换振荡与真机迁移4.1 行为坍缩所有行为变成了同一种走法我遇到的第一个大坑是行为坍缩。训练跑了 300 万步打开日志一看8 个行为的嵌入向量之间的距离全在 0.3 以内行为库基本退化成了一个行为。问题出在多样性奖励被任务奖励“碾压”了——速度奖励的梯度幅度远大于多样性奖励网络发现与其花容量去分化不如直接把速度提上去。解决思路有几个我最终是把这些全部做了。一是在阶段一先把任务奖励跑到收敛再开多样性二是多样性奖励用“最小距离”而不是平均距离这样即使任务奖励很强最相近的两个行为也始终有压力拉开三是对行为嵌入向量加 L2 正则防止所有嵌入漂到原点附近。如果还不行可以把 K 降到 4等行为分化出来了再逐步升到 8。另一个不那么明显的原因是行为库容量不足。行为嵌入只有 16 维时有些情况下不足以表达 8 个完全不同的步态。我试过把维度升到 32多样性确实变好了但训练时间长了差不多 30%。后来我在 16 维下也能解决只是需要把 λ 调得更大。建议先固定 16 维遇到实在分不开的情况再升维。4.2 行为切换振荡机器人像有选择困难第二个坑是高层策略在行为之间疯狂横跳。最早哪边奖励多一点调度策略就切到哪边结果切换频率高达每秒 3 次。动作目标不断在“小碎步”和“高抬腿”之间跳变关节指令抖动很厉害机器人走起来像喝多了。排查后确认两个原因。首先是调度策略的输入噪声太大单帧的接触状态和 IMU 读数波动剧烈导致决策边界不断被跨越。解决方法是给调度策略喂一个历史窗口的统计特征比如过去 0.5 秒内的接触事件计数、躯干姿态方差、速度方差而不是看瞬时值。其次是缺少切换代价。我在奖励里加了一项负惩罚只要高层输出的行为和上一帧不同就扣一个惩罚项。简单粗暴但非常有效。加了之后切换频率降到了 0.3 次/秒左右成功率不降反升——机器人不再纠结动作平滑了自然不容易摔倒。另外高层策略的输出可以再过一层指数平滑让行为权重渐变而不是突变这个小技巧也帮了大忙。4.3 真机迁移失败仿真里好看真机上站不住仿真里各项指标都很好迁移到真机时我遇到了首次实验就全部扑街的情况。机器人一落地就走了三步然后开始高频抖腿接着摔倒和仿真里判若两机器人。我排查后发现两个问题。第一行为库中有几个行为在真机上天然不稳定。它们在仿真里依赖摩擦系数很高的地面而真机场地的接触特性根本给不了那么大的力。解决办法是把域随机化中摩擦系数的范围从 0.3~0.8 扩大到 0.2~1.2重新训练一个版本仿真里那些“靠高摩擦硬撑”的行为自然就消失了。第二行为切换瞬间的目标速度突变。仿真里切换时关节冲击无所谓真机上就是实打实的机械磨损和平稳性破坏。我在执行策略的输出端加了一个限速斜坡让目标关节位置/力矩在 20~40ms 内渐变到新值。做个对比斜坡滤波后真机实验的摔倒次数从 12 次降到了 2 次。我特别建议一类做法真机测试前先单独冻结每个行为 ID把 8 个行为逐个放到简单地面上跑几遍确认哪些行为在真机上稳定。把稳定行为筛选出来之后再放开高层调度只让它从“已验证行为”里选。这是我在一次失败后的复盘里得出的结论能省掉大量排查时间——不要一开始就让调度策略在真机上随便选哪怕仿真里它表现再好。4.4 复现者可以先带走的几条经验如果只让我挑几条最值得带走的内容第一是不要把多样性奖励当成训练后期加上的“装饰品”。MoB 的核心思想是泛化不是记住更多地形而是给机器人装配足够多的后路。行为库就是这条后路而多样性奖励是后路的施工队不认真对待它行为库就是摆设。第二是训练时一定要把行为轨迹可视化。我复现时把 8 个行为的足端轨迹投影到平面上看行为分化是否成功一目了然。有个行为是步频很高的碎步有个是步幅很大的跨越还有一个带明显的侧向偏移。看到这些图你才会对“行为是有意义的单元”有直觉。第三是别贪多。行为数 K 一开始用 8 就够了16 个行为的训练难度和调试成本远不是翻倍而是指数级增长。K8 时行为库已经能覆盖大部分常见地形模式等真机验证完再考虑扩充。最后提一句MoB 也不是银弹。如果地形本身只有一种运动模式加多样性奖励只会浪费模型容量徒增切换风险。它真正适用的场景是那些“不同地形需要不同步态”的复杂任务。选方向之前先想清楚这一点能省下不少时间。