强化学习驱动的双足机器人:从仿真训练到真机部署全解析
发布时间:2026/10/7 7:31:00 作者:尧图编辑部 阅读量:1,286

1. 为什么一只鸭形双足机器人值得深挖很多朋友第一次看到我桌上那只黏着线材、顶着传感器堆的“小鸭子”时第一反应都是“这不就是个玩具吗”从外表看它确实和市面上几十块钱的鸭子玩具没什么区别但真正让这一堆零件从“会动”变成“会走”的是背后那套由强化学习驱动的开源架构。这篇内容就是要把这套微小型双足鸭形机器人系统从头到尾拆一遍说清楚硬件怎么选、软件怎么搭、强化学习训练怎么做、实机迁移会踩哪些坑以及这套思路能延伸到哪些场景。做这个小项目之前我其实先认真考虑过要不要直接搞一台人形机器人但看到高昂的电机成本和复杂的动力学模型之后我果断放弃了。双足行走本身就是机器人控制里的“硬骨头”人形机器人在小尺寸下更是难上加难——重心高、支撑面积小、舵机响应慢每一个问题都能让人崩溃。于是我把目光转向了鸭形结构身体短、重心低、两条腿短而粗脚掌宽大天生自带“稳定性”。事实证明用这个形态来验证强化学习在连续动作空间上的控制能力是性价比极高的选择。这篇内容适合三类人来看想入门强化学习但没有合适练手场景的人对双足机器人和sim-to-real迁移感兴趣的硬件爱好者以及想把仿真里训练的RL策略真正部署到低成本真机上的开发者。整篇文章不追求“玄学”也不堆数学公式而是按我实际做项目的顺序把每个核心决策的来龙去脉讲清楚。我自己从零折腾这个项目前后花了大概三个月。刚开始最难的不是跑通强化学习算法而是让这只鸭子在一个仿真环境里能“站住”后来才慢慢学会走最后移植到真机上连续走好几米也而不再摔得四脚朝天。这条路走下来踩过的坑比收获的经验多得多所以想一次性把我认为最值得分享的内容都整理出来。2. 拆硬件微小型双足机器人的“身体基础”2.1 为什么鸭形结构是新手最友好的双足方案如果单纯讲“双足”很多人的第一反应是两条笔直的腿和直立的躯干。但传统人形机器人的稳定控制非常依赖精确的动力学模型一旦舵机扭矩不足或者关节有间隙ZMP零力矩点之类的经典方法就很难在小尺寸系统上落地。鸭形结构恰好把这个问题压缩到了可以接受的范围躯干低、腿短、大腿外张两条腿之间天然形成一个稳定的支撑三角形。我做的这只鸭子整体尺寸大约14厘米长、10厘米宽、18厘米高重量控制在420克左右。两条腿各有两个自由度髋关节左右摆动roll和髋关节前后摆动pitch。没有设计复杂的膝盖和脚踝脚掌直接用一片加宽的TPU软垫模拟“鸭蹼”。这样的设计有三个直接好处一是减少了舵机数量成本低、控制简单二是脚蹼接触地面积大即使姿态控制有一点偏差也不太容易瞬间翻倒三是重心非常低给强化学习探索阶段留出了很大的容错空间。所以如果你也想复现一个双足强化学习项目我强烈建议先别急着做人形先做一个“矮胖型”结构。把腿做得短一点脚做得宽一点你会发现训练收敛速度快得多。这个设计取舍不是偷懒而是在为算法探索期的随机策略留余地——试想一下如果初始策略随机一推就倒那学习效率会低到让人想放弃。2.2 舵机、主控和传感器怎么选才不浪费钱微型双足机器人的关节执行器是整套硬件的核心。一开始我用的是普通PWM模拟舵机比如常见的SG90和MG90S便宜是便宜但实际用下来问题很多位置精度差、响应速度慢、而且四个舵机同时工作的时候PWM信号容易互相干扰。后来我换成了串行总线舵机价格虽然贵一些但每个舵机自带角度反馈和温度、电压读取而且可以菊链式连接只占用主控一个串口就能控制所有关节。主控和上层计算单元我拆成了两层。底层用一片STM32F407负责舵机控制、IMU数据读取和串口通信上层计算用树莓派Zero 2W来跑轻量级的策略网络推理。这套架构的好处是调试的时候可以在树莓派上随便跑Python代码不需要反复烧录单片机只有底层控制逻辑稳定之后才需要固化到STM32里。如果你不想用树莓派也可以把策略网络导出成TFLite模型直接塞进ESP32-S3里跑但那样调试成本会高不少我建议还是保留一层Linux环境更舒服。传感器方面IMU用的是BMI088这个模块的零漂比较小温漂也还好在微型机器人上完全够用。另外在两只脚底下各贴了一片FSR薄膜压力传感器用来检测脚掌是否着地。FSR的精度虽然不高但用来做步态阶段判断已经够了。这里要特别提醒一句微型机器人的传感器不能贪多IMU数据如果有几十Hz的毛刺强化学习策略在真机上很容易抖动宁可从硬件滤波做起也不要指望算法能把脏数据洗干净。2.3 电气拓扑小机身里的供电与通信布局有了舵机、主控和传感器接下来要解决的是电气拓扑问题。先算一笔账四个串行总线舵机单个舵机正常工作电流大约250毫安堵转时能达到650毫安以上。瞬时峰值电流可能超过3安培。如果使用2S锂电池标称7.4V直接给舵机供电电池内阻稍微大一点就会发生“舵机一转主控重启”的尴尬现象。所以我在电源设计上采用了一个很老但有效的方案电池出来先经过一个低内阻的5V降压稳压器比如MP1584或者TPS563200给所有舵机供电同时再独立分出一路3.3V LDO给主控和传感器供电。底层MCU直接由3.3V供电树莓派则由5V供电。为了防止瞬时压降我在舵机电源输入端并联了两颗470微法的电解电容和一个100微法的陶瓷电容实测下来即使鸭子原地快速摆腿也不会再导致树莓派重启了。通信拓扑方面走的是“串行总线舵机一条线”的思路四个舵机通过TTL串口接到STM32IMU用SPI接口连接FSR传感器通过ADC采集STM32再和树莓派之间用USB转串口通信波特率设置在460800这样上层策略输出的关节角度增量能稳定地传给底层。整体信号链路非常干净没有复杂的总线仲裁问题。这里我想特意强调一下接地主控电源和舵机电源的地一定要在单点汇合否则舵机电流变化会在地线上产生很高的噪声IMU数据会变得一塌糊涂。3. 搭软件开源架构的每一层都要能干活3.1 嵌入式端和上层推理端的分工硬件定下来之后软件架构直接决定了你会不会在后期被自己写的一团乱麻逼疯。这套系统的开源架构我分为四个层次仿真训练层、策略接口层、底层控制层、真机通信层。仿真训练层跑在普通PC上用的是PyTorch和Gymnasium环境训练完成后导出一个策略文件。策略接口层跑在树莓派上主要任务是加载策略参数把真机传感器数据拼成观测向量然后产出动作向量。底层控制层跑在STM32上负责接收动作指令平滑处理后转换成舵机目标角度。真机通信层则只是简单的串口协议我定义了一个非常轻量的帧格式帧头、动作数据、校验、帧尾。这个分工的核心原则是尽量把会频繁修改的东西放在上层把性能敏感和硬件相关的东西放在下层。比如PD增益、舵机角度范围、IMU滤波参数都放在STM32里而策略网络、奖励估计、状态归一化参数都放在树莓派上。这样每次调参不需要反复烧录MCU省下来的时间足够你再训练好几次策略了。有一个小细节值得分享我在策略接口层和底层控制层之间加了一个“动作平滑器”也就是对动作输出做一阶低通滤波滤波系数是0.35左右。如果你直接采用策略网络输出的原始动作舵机会剧烈抖动因为策略网络在真机上观测到的高频噪声和仿真里完全不一样而低通滤波能非常显著地缓解这个问题代价只是延迟增加几十毫秒。对双足这种中低速运动来说这个延迟可以接受换成高速四足机器人就需要更小心地权衡了。3.2 搭建一个简化版的Gymnasium训练环境强化学习训练环境是整个软件栈的重心。我参照OpenAI Gymnasium的接口写了一个非常简化的鸭子仿真环境。这个环境不追求极度精确的物理引擎而是把重点放在“动作-状态-奖励”通路的一致性上。先说观测空间。每个时刻送入策略网络的观测向量由以下几部分组成四个舵机的当前角度、四个舵机的角速度、IMU测得的鸭子机体roll和pitch角度、机体roll和pitch角速度、脚底两个FSR的接触状态、目标速度指令。这加起来大约是16维的向量维度不高非常适合用一个小的MLP策略网络来拟合。很多初学者会犯一个错误就是把所有能拿到的数据全部塞进观测空间结果策略网络确实能记住训练数据但一到真机上就抓瞎。真正的设计思路是尽可能只给算法“对决策有直接影响”的量。动作空间方面我定义为四个舵机目标角度增量每个维度的取值范围限制在-1到1之间再缩放成实际的舵机角度偏移。这种增量式的动作表达比直接输出绝对角度要温和得多训练初期策略不会一下子跳出合理范围。这样做还有个额外好处在真机上同一套策略可以直接复用不依赖特定的初始关节角度。环境基本动力学是在PyBullet里实现的模拟频率设置为240Hz控制频率设置为30Hz即每8个仿真步执行一次策略推理。之所以不用Gazebo是因为对这只小鸭子来说PyBullet的仿真速度更快、安装配置更简单而且跨平台很稳定。Gazebo配合ROS生态在大型移动机器人或AGV场景里更有优势这些后文再展开。3.3 为什么最终选择了PyTorch加上ONNX的转换链训练完策略之后最重要的一步就是把PyTorch模型安全地部署到树莓派上。我没有直接在树莓派上重新安装PyTorch然后加载模型参数因为ARM平台上的PyTorch版本兼容问题会让人浪费大量时间。我更推荐的路径是PyTorch模型训练好之后先转存成ONNX再用ONNX Runtime在树莓派上运行。整个转换过程非常简单但有几个坑必须注意一是策略网络里的输入归一化层和输出缩放层要一起导出否则拿到真机上推理时输入分布完全不同策略会直接失效二是动作分布的随机性要关闭在导出模型前要把模型设置为评估模式并且去掉所有dropout或随机采样逻辑三是对动作的tanh压缩函数要保留在模型内部不要在外面再解一遍。最终跑在树莓派Zero 2W上的推理模型只有几十KB一次前向推理大约耗时1到3毫秒完全满足30Hz的控制周期。而且ONNX Runtime用起来也非常轻量几乎不占系统资源这对微型机器人来说非常重要——整机功耗本来就很紧张不能把宝贵的电池能量花在无谓的模型加载和重复计算上。4. 强化学习训练从零到能走的全部套路4.1 算法选型为什么首先考虑PPO强化学习算法选型往往是被讨论最多的问题。对于这只鸭形双足机器人我最终选择了PPOProximal Policy Optimization作为主力算法原因不是它最新而是它在连续动作空间控制任务上足够稳定、足够简单。PPO的核心思想是限制每次更新的幅度不要让新策略一下偏离旧策略太远这样训练曲线就算不太平滑也不会轻易崩溃。相比之下DQN很难处理连续动作空间DDPG对超参数和随机种子非常敏感动不动就发散发散SAC虽然样本效率更高但需要调节熵系数等一堆参数对于刚入门的人来说并不友好。我用的是stable-baselines3库中的PPO实现结合SubprocVecEnv开了32个并行的仿真环境同时采样。训练配置大致如下学习率3e-4PPO clip范围0.2batch size是4096GAE中的gamma设为0.99lambda设为0.95。这个配置并不是最优的但它是一个非常稳定的起点绝大多数机器人连续控制任务都可以从这套参数开始调。训练量上我让整个系统跑了约200万步。实际观察到的收敛过程很有意思前20万步完全是在原地乱扭基本看不出什么进步到50万步左右开始出现明显的“站立式前倾”动作大约100万步可以踉踉跄跄走几步200万步之后已经能稳定地以大约0.3米/秒的速度前进并且可以抵抗轻微的侧向推力。4.2 奖励函数设计每个分项都是血泪教训如果你问我这个项目里最值得反复打磨的部分是什么我会毫不犹豫地说奖励函数。很多RL新手上来就用“到达目标点给一个正奖励摔倒给一个负奖励”这种稀疏奖励对双足行走来说几乎不可能收敛因为探索空间太大了随机动作根本碰不到“走得快”这个事件。我的奖励函数拆成四个分项。第一项是速度奖励即鸭子在水平面的真实前向速度与目标速度之差的负指数函数。这个项是“主驱动”鼓励策略沿着目标方向前进。第二项是姿态惩罚当机体roll或pitch角偏离零度太多时给予惩罚惩罚力度随角度增加而指数上升。没有这个惩罚策略很容易学会一种“原地蹦跳”的偷懒方式鸭子姿态乱七八糟但速度居然也不慢。第三项是能量惩罚对动作幅值和动作变化率施加二次惩罚避免舵机高频抖动和突然换向。第四项是步态节奏奖励我是通过检测FSR接触状态判断左右脚是否在合理时间间隔内交替着地如果腿像螃蟹一样拖着走就给一点小惩罚。这里有一个非常关键的教训奖励之间需要控制比例。我第一版奖励里速度奖励权重给得太大结果训出来的策略像一个被打了兴奋剂的青蛙一下地就疯狂蹬腿脚蹼拍地咚咚响。后面把速度奖励权重降下来、姿态惩罚提上去之后步态才慢慢变得正常。奖励函数没有万能模板只能靠反复实验和观察训练视频来调。4.3 训练稳定性的优化技巧与工程化手段训练强化学习策略和训练深度学习模型有一个显著区别强化学习的数据分布会随策略变化而变化所以训练曲线波动大是常态。为了让最终部署到真机上的策略更可靠我做了三个工程化处理。第一个是域随机化。在仿真环境里我随机化了鸭子质量±10%、脚底摩擦系数0.4到1.0之间变化、舵机PD增益±20%、控制时延0到40毫秒等参数。域随机化的目的就是让策略在真机面对各种未建模误差时依然能工作这个方法在业界已经被大量验证过对小型双足机器人尤其有效。第二个是状态归一化的导入和导出。训练时观测向量的每一维都被标准化到零均值、单位方差训练完成后我把这些归一化参数的均值、方差和策略参数一起导出到真机。很多人在这一步会遗漏结果真机上策略完全失灵表现就是鸭子站在原地发呆或者疯狂摆腿但不知道前进。第三个是周期性的模型存档。我每隔5万步保存一个检查点训练结束后不是直接取最后一个模型而是在多个检查点里挑一个在“验证环境”中表现最稳定的版本。验证环境使用了与训练不同的随机种子和初始姿态这样可以降低模型过拟合训练分布的概率。最终部署到真机上的那个模型未必是训练总奖励最高的但一定是仿真里最稳的那个。4.4 进阶方向IQL离线强化学习和因果强化学习训练到稳定之后我开始思考一个现实问题真机实验成本太高不可能每次改进算法都让鸭子在真机上摔几百次。这时候离线强化学习和因果强化学习这两条进阶路线就很有意义了。IQLImplicit Q-Learning是一种离线强化学习算法它允许我们只用一批预先采集好的数据来训练策略而不需要和环境在线交互。对微型机器人来说这个思路太实用了可以先在仿真中或真机上部署一个表现不错的“教师策略”让它跑出大量状态-动作-奖励数据然后对数据做清洗和筛选再用IQL训练出一个新策略。这样调整奖励函数或者策略结构时完全不需要重新让机器人做大量随机探索避免了真机损耗。因果强化学习Causal RL则是我最近在研究的方向。它的核心是把因果推断工具嵌入到强化学习流程中关键能力包括从高维观测中识别出真正影响决策的因果变量、剔除掉“看似相关但实际是混淆因素”的特征、提高策略在环境变化下的泛化性。放到鸭形机器人上最直观的例子就是IMU温度显然会随时间漂移电池电压会随电量下降这些变量都与状态相关但不是导致步态控制失败的原因。如果能让策略自动忽略这些无关变量那从仿真到真机的迁移会顺利得多。我的建议是如果你刚接触强化学习先别急着上这些进阶算法把PPO和域随机化练好已经能解决绝大多数sim-to-real问题。但如果你的项目必须减少真机实验次数或者需要在多种工作环境下部署同一个控制策略那IQL和因果强化学习绝对值得深入学。5. 实机迁移与调试踩坑实录5.1 第一步永远是零点标定和初始姿态把仿真里训练好的策略搬到真机上最容易被忽略、又最致命的问题不是算法而是零点标定。仿真环境里舵机角度是精确的、零位是绝对的但真机舵机通过电位器反馈出来的零点可能与机械结构定义的零位有偏差。如果四个舵机的零点都不一致一开始鸭子就站姿歪斜策略输出再正确也无法纠正基底姿态。我专门写了一个标定程序让鸭子以腿部微张、躯干水平的姿态平放在桌面上然后读取每个舵机的编码器值作为“零点偏移”。标定之后这个偏移会保存到STM32的Flash里每次上电自动读取。还有一个容易踩坑的细节舵机存在死区即微小角度指令不会产生实际转动所以实机控制时一定要在底层加入死区补偿否则策略输出的小幅修正动作在真机上会完全丢失导致鸭子慢慢偏向一侧。初始姿态也对迁移效果影响极大。仿真环境里每回合都是从一个标准的站立姿态开始的但真机上如果人放置鸭子的位置、角度稍有不同策略第一帧看到的观测就可能超出训练分布。我给树莓派端写了一个“启动检查”逻辑上电后必须先让鸭子达到指定的关节角度范围并且IMU测得的俯仰角小于10度才送第一个推理动作否则就一直守候待命。5.2 仿真到现实的差距延迟、噪声和摩擦都不可忽视仿真模型的物理参数再精确和真机也是两套世界。我踩过最深刻的坑是执行器延迟。仿真里我假设动作指令立刻生效但真机上从树莓派发送动作到STM32解析再到舵机实际转到目标角度整个过程至少有20到40毫秒的延迟。这个延迟对步态控制来说非常致命因为双足行走必须依赖相位正确的姿态调整延迟会让策略感觉“世界比预期慢半拍”结果就是步子越走越乱。解决这个问题的办法有两个。一是在训练时故意在环境中加入随机延迟比如在动作发送后随机等待0到2个控制周期再执行让策略学会在延迟环境下依然保持稳定。二是实机端要尽量压缩链路延迟我把STM32里的舵机控制频率提高到了300Hz并在底层使用前馈补偿让舵机更快接近目标位置。我实测下来这两招联合使用之后真机步态的稳定性大幅提升。摩擦系数的问题也非常令人头疼。仿真里的地面通常被建模成均匀摩擦但真机桌面上的一点灰尘、TPU脚垫的磨损都会导致左右脚摩擦力不对称。所以我在脚垫设计上做了点文章左右脚垫采用相同的TPU材质但表面纹理方向一致防止鸭子“朝一侧打滑”。必要时还可以在桌面上铺一张防滑垫这是最简单也最暴力的解决方案。5.3 常见故障速查表与操作建议实机调试没有一帆风顺的我把自己的经历整理成一个速查表几乎每次故障都能在里面找到条目现象最常见的根因处理建议鸭子往一个方向持续倾斜IMU零点漂移左右舵机零点不一致重新标定IMU和舵机零点检查机械装配是否对称原地剧烈抖动步态混乱奖励函数里姿态惩罚太低执行器延迟过大提高姿态惩罚权重训练时加入随机延迟域随机化训练曲线看着很好真机完全不动状态归一化参数未同步到真机导出模型时连带保存输入均值和方差加载后逐项校验舵机过热或烧毁机械卡滞堵转电流保护失效检查关节活动范围是否干涉配置舵机限流和温度保护树莓派重启瞬时压降导致供电跌落在舵机电源端加大电容确保3.3V和5V独立稳压FSR数据一直是0或满值接错ADC引脚或者脚垫粘贴位置偏移用万用表/串口打印原始值确认机械接触后再训练在此基础上我强烈建议第一次真机测试时加装一个安全挂架用一根细绳把鸭子从背上吊住这样即使突然摔倒也不会砸坏舵机。还有一个操作技巧把所有电源开关集中到一个物理急停按钮上一旦看到步态发散第一时间断电。强化学习训练出来的策略有时候会输出一些看起来“可能性不高”的动作不要相信模型一定不会胡来该有的安全冗余一样都不能少。6. 从鸭形机器人往外走同一套思维能用到哪6.1 多AGV路径规划里的强化学习借鉴做完了双足机器人我最大的感受是强化学习控制框架并不局限于人形或鸭形机器人。最近我在关注多AGV路径规划问题发现很多设计思路和这套鸭形系统是互通的。AGV调度中的强化学习通常把多台车看作多个智能体每台车载着货物奖励函数里同时考虑到达时间、能耗和碰撞惩罚这和双足机器人里速度奖励、能量惩罚、姿态惩罚的权衡本质上是同一类问题。更关键的是“决策和执行分离”的思想。双足鸭形系统里上层策略负责“怎么走”底层控制器负责“怎么驱动舵机”多AGV系统里上层强化学习负责“走哪条路径、要不要让行”底层负责“电机速度控制和安全避障”。如果你把鸭形机器人这套分层架构理解透了再去看调度问题会变得很轻松。另外域随机化和延迟鲁棒性这两个概念也可以在AGV场景里复用。AGV在仓库地面上的摩擦特性、负载重量变化很大如果只在单一仿真环境里训练调度策略上线后必然会出问题。提前对车辆动力学参数、地图布局做域随机化和在仿真里随机化鸭子质量、摩擦系数是完全一样的套路。6.2 开源生态与入坑路径建议现在做机器人强化学习最大的利好就是有大量开源生态可以借用。PyTorch、Stable-Baselines3、PyBullet、MuJoCo、Gymnasium这些工具组合起来基本可以覆盖“环境搭建到策略部署”的整条链路。如果你是零基础我的建议是不要从理论啃起先跑通一个简单的仿真控制任务哪怕只是一个“倒立摆”都没关系先把强化学习的观察、动作、奖励闭环印在脑子里再上双足机器人。理论学习方面David Silver的强化学习公开课和Sutton与Barto的《强化学习导论》是绕不开的经典。但不要等全部看完再动手经典课程可以慢慢补项目却可以立刻开始否则学到第5章你就忘了前面在干什么了。6.3 最后分享一点个人体会做这只鸭形机器人我最大的收获不是“让鸭子走得更稳”而是完整地走通了强化学习从仿真到真机落地的那条链路。现在我回头看仿真里的每一次摔倒真机上每一次突发故障最终都变成了对控制问题的更深刻理解。这只鸭子的原始设计、硬件图纸、训练配置和部署代码我都整理进了开源仓库如果你也想复现只需要准备好一套舵机、一片STM32、一个树莓派Zero 2W和足够的耐心。最后再分享一个小技巧每次训练时记得录屏。强化学习训练过程中会出现很多“意想不到”的步态有些是失败有些却是惊喜录下视频会让你对策略行为的理解远超只看reward曲线。我自己很多次深夜调试就是靠翻看训练录像找到了问题的真正原因。做小机器人这件事慢一点没关系关键是每一步都踩得明白。