1. 从零开始:为什么选择Gym框架来训练你的Go2机器人?
如果你对机器人控制感兴趣,尤其是看到宇树Go2这种灵活的四足机器人,心里肯定痒痒的,想让它学会点新技能,比如走个复杂地形或者自己爬起来。但直接对着真机编程,成本高、风险大,一不小心就可能让机器人“翻车”。这时候,仿真训练就成了必经之路。而OpenAI的Gym框架,就是进入这个世界的绝佳入口。
Gym本质上是一个标准化的“健身房”,它为各种智能体(比如我们的机器人)提供了一套统一的“锻炼”接口。你不需要每次都从头搭建物理引擎、设计奖励函数,Gym帮你把这些脏活累活都封装好了。对于Go2机器人来说,这意味着我们可以把它的数字模型(URDF文件)放进一个模拟的物理世界里,然后用强化学习算法去“教”它。算法通过不断试错,根据我们设定的“奖励”(比如走得稳、走得快)来调整机器人的动作,最终让它学会我们期望的行为。
我刚开始接触时也觉得有点复杂,但实际走一遍流程就会发现,社区生态已经相当成熟。特别是有了像legged_gym这样专门为足式机器人优化的Gym扩展环境后,很多底层工作已经被简化了。我们只需要做好“配置”和“组装”的工作,就能快速启动训练。这就像你拿到了一套高级乐高,说明书(框架)已经写好,你只需要把属于Go2的那几块特殊零件(URDF和配置文件)装到正确的位置上。
所以,无论你是机器人专业的学生,还是业余的强化学习爱好者,只要你想在仿真环境里“驯服”一只Go2,基于Gym框架的方案是目前最主流、也最可行的一条路。它把复杂的机器人学和强化学习理论,转化成了相对清晰的代码配置问题。接下来,我就带你一步步走通这个流程,分享我配置和训练时踩过的坑和总结的经验。
2. 环境搭建:获取Go2模型与准备训练战场
在开始写代码之前,我们得先把“训练场地”和“机器人模型”准备好。这个过程有点像装修房子,先把毛坯房(基础环境)弄好,再把定制的家具(Go2模型)搬进去。
2.1 获取Go2机器人的URDF数字模型
URDF文件是机器人的“数字蓝图”,它描述了机器人所有连杆、关节的几何形状、物理属性以及连接关系。没有它,仿真环境就不知道Go2长什么样、关节怎么动。
宇树科技官方已经将Go2的模型开源了,这为我们省去了大量自己建模的麻烦。获取方式很简单,就是通过Git克隆他们的资源库。打开你的终端,找一个合适的工作目录,执行以下命令:
git clone https://github.com/unitreerobotics/unitree_rl_gym.git
克隆完成后,你会得到一个名为unitree_rl_gym的文件夹。我们需要的是里面的机器人模型文件。具体路径在resources/robots/go2/下。你会看到里面包含了urdf、meshes等子文件夹,urdf文件夹里的go2.urdf就是核心的模型描述文件,而meshes里存放的是机器人的3D外观网格文件。
接下来,我们需要把这个go2文件夹整个复制到我们即将使用的训练环境legged_gym的资源目录下。假设你的legged_gym项目目录是/path/to/legged_gym,那么复制命令大致如下:
cp -r unitree_rl_gym/resources/robots/go2 /path/to/legged_gym/resources/robots/
这一步千万不能错,因为后续的配置文件会严格按照这个路径去寻找go2.urdf。我一开始就曾因为路径不对,导致仿真加载失败,报了找不到文件的错误,排查了半天。
2.2 配置基础训练环境:安装Legged Gym
有了机器人模型,我们还需要一个功能强大的“健身房”——也就是足式机器人专用的Gym环境。这里我们使用Isaac Gym的社区版本结合legged_gym这个开源项目。legged_gym基于NVIDIA的Isaac Gym构建,专门为四足机器人强化学习做了大量优化,性能非常出色。
首先,你需要确保你的系统满足Isaac Gym的依赖,主要是CUDA和合适的NVIDIA显卡驱动。然后,按照legged_gym仓库的README进行安装。通常的步骤包括:
- 克隆仓库:
git clone https://github.com/leggedrobotics/legged_gym.git - 创建Python虚拟环境:强烈建议使用conda或venv创建一个独立环境,避免包冲突。
- 安装依赖:
pip install -r requirements.txt - 安装Isaac Gym:根据官方指引下载并安装Isaac Gym的Python包。
安装过程可能会遇到一些环境问题,比如PyTorch版本与CUDA的匹配问题。我的经验是,严格按照legged_gym项目推荐的版本号来安装,不要随意升级到最新版,可以避免很多不必要的麻烦。安装成功后,你可以尝试运行一个已有的例子(比如训练A1机器人),来验证环境是否正常。
3. 核心配置:为Go2量身定制训练参数
环境搭好了,模型也有了,现在是最关键的一步:告诉legged_gym如何训练我们的Go2。这需要通过编写一个配置文件来完成。这个文件定义了机器人的初始状态、控制参数、奖励函数等所有训练细节。
3.1 创建Go2的专属配置目录与文件
首先,在legged_gym/legged_gym/envs/目录下,为Go2创建一个单独的文件夹,比如就叫go2。这样做的目的是为了模块化管理,以后Go2的不同任务(平地走、崎岖地形走)配置都可以放在这里,不会和其他机器人模型混在一起。
cd /path/to/legged_gym/legged_gym/envs
mkdir go2
cd go2
touch go2_config.py
然后,用你喜欢的编辑器打开go2_config.py,开始编写配置。配置文件的结构是继承自legged_gym已有的基础配置类,我们只需要覆盖那些针对Go2需要调整的参数即可。
3.2 详解配置文件:从初始姿态到奖励函数
下面我结合代码,逐块解释每个配置部分的作用和调整思路。你可以直接参考使用,但理解其含义更重要,这样你才能根据自己的训练目标进行调整。
from legged_gym.envs.base.legged_robot_config import LeggedRobotCfg, LeggedRobotCfgPPO
class GO2RoughCfg(LeggedRobotCfg):
class init_state(LeggedRobotCfg.init_state):
pos = [0.0, 0.0, 0.42] # x, y, z [m]
default_joint_angles = { # 动作输出为0时,关节的目标角度 [rad]
'FL_hip_joint': 0.1, # 前左髋关节
'RL_hip_joint': 0.1, # 后左髋关节
'FR_hip_joint': -0.1, # 前右髋关节
'RR_hip_joint': -0.1, # 后右髋关节
'FL_thigh_joint': 0.8, # 前左大腿关节
'RL_thigh_joint': 1.0, # 后左大腿关节
'FR_thigh_joint': 0.8, # 前右大腿关节
'RR_thigh_joint': 1.0, # 后右大腿关节
'FL_calf_joint': -1.5, # 前左小腿关节
'RL_calf_joint': -1.5, # 后左小腿关节
'FR_calf_joint': -1.5, # 前右小腿关节
'RR_calf_joint': -1.5, # 后右小腿关节
}
- 初始状态:
init_state类定义了机器人仿真开始时的样子。pos是机器人的初始位置,[0,0,0.42]意味着放在世界坐标原点,离地0.42米高(这是Go2的大致站立高度)。default_joint_angles极其重要,它定义了机器人的“中立姿态”。当神经网络输出的动作值为0时,关节就会朝向这个角度运动。这里设置的是一个微微下蹲、准备发力的姿态,类似于动物起跑前的姿势。如果设置成一个笔直站立的姿态,机器人反而容易失稳。
class control(LeggedRobotCfg.control):
control_type = 'P' # 使用比例控制
stiffness = {'joint': 20.} # 关节刚度 [N*m/rad]
damping = {'joint': 0.5} # 关节阻尼 [N*m*s/rad]
action_scale = 0.25 # 动作缩放系数
decimation = 4 # 控制频率降采样
- 控制参数:这里定义了底层控制器如何将神经网络的输出转化为关节力矩。
control_type='P'表示使用简单的比例控制器。stiffness和damping是PD控制器的参数,分别影响关节的“硬度”和“缓冲”,需要根据机器人实际动力学调整。action_scale是一个缩放因子,神经网络的输出(通常在-1到1之间)会乘以这个系数,再加到default_joint_angles上,得到最终的目标关节角度。decimation=4意味着物理仿真每步更新4次,策略网络才输出一次新动作,这能平衡精度和计算效率。
class asset(LeggedRobotCfg.asset):
file = '{LEGGED_GYM_ROOT_DIR}/resources/robots/go2/urdf/go2.urdf'
name = "go2"
foot_name = "foot" # 足端连杆的名称,用于碰撞检测和奖励计算
penalize_contacts_on = ["thigh", "calf"] # 这些部位接触地面会被惩罚
terminate_after_contacts_on = ["base"] # 这些部位接触地面会直接结束本轮训练
self_collisions = 1 # 1表示禁用自碰撞检测,0表示启用
- 资产与物理属性:
file路径指向我们之前拷贝的URDF文件。foot_name必须和URDF文件中定义的足端连杆名称严格一致,否则算法无法正确识别哪部分是脚,导致奖励计算错误。penalize_contacts_on列表里的身体部位如果碰到地面,机器人会收到一个负奖励(惩罚),鼓励它只用脚走路。terminate_after_contacts_on列表里的部位(比如躯干base)碰到地面,则视为严重失败,直接终止当前训练回合。这模拟了机器人摔倒的情况。
class rewards(LeggedRobotCfg.rewards):
soft_dof_pos_limit = 0.9 # 关节位置软限制的系数
base_height_target = 0.25 # 期望的躯干高度目标 [m]
class scales(LeggedRobotCfg.rewards.scales):
torques = -0.0002 # 关节力矩惩罚的权重(负号表示惩罚)
dof_pos_limits = -10.0 # 关节位置超限惩罚的权重
- 奖励函数:这是强化学习的“指挥棒”,决定了机器人学习的方向。
rewards类里定义了一些奖励项的参数,比如base_height_target是希望机器人保持的躯干高度。更关键的是scales类,它定义了各个奖励或惩罚项的权重。torques惩罚关节使用过大扭矩,鼓励节能;dof_pos_limits惩罚关节角度接近物理极限,保护机器人模型。权重的正负和大小需要仔细调校,是训练成功与否的关键。一开始可以沿用其他成功模型的权重,后期再微调。
最后,我们还需要定义用于PPO算法的训练超参数配置:
class GO2RoughCfgPPO(LeggedRobotCfgPPO):
class algorithm(LeggedRobotCfgPPO.algorithm):
entropy_coef = 0.01 # 熵系数,鼓励探索
class runner(LeggedRobotCfgPPO.runner):
run_name = '' # 单次运行名称,可用于区分不同实验
experiment_name = 'rough_go2' # 实验名称,用于组织日志和模型
entropy_coef是PPO算法中的一个超参数,增加一点熵奖励可以防止策略过早收敛到局部最优,保持一定的探索性。experiment_name会作为保存日志和模型文件夹的名称,取个有意义的名字方便后期管理。
4. 注册环境:让Gym认识你的Go2
配置文件写好了,但Gym框架还不知道它的存在。我们需要在legged_gym的环境注册表中“注册”我们的Go2任务。这就像给新员工办理工牌,系统里有了记录,才能调用它。
找到legged_gym/legged_gym/envs/__init__.py这个文件。我们需要在适当的位置添加几行导入和注册代码。
首先,在文件顶部附近,找到其他机器人配置导入的地方,添加对我们刚写的配置文件的导入:
# ... 其他导入 ...
from .a1.a1_config import A1RoughCfg, A1RoughCfgPPO
# 添加go2的导入 **********************************************************************
from .go2.go2_config import GO2RoughCfg, GO2RoughCfgPPO
然后,向下滚动,找到task_registry.register函数调用的地方。这里已经注册了a1、cassie等机器人。我们在最后同样添加一行,注册我们的go2任务:
# ... 其他注册 ...
task_registry.register("cassie", Cassie, CassieRoughCfg(), CassieRoughCfgPPO())
# 添加go2的注册 **********************************************************************
task_registry.register("go2", LeggedRobot, GO2RoughCfg(), GO2RoughCfgPPO())
这行代码告诉系统:当任务名task为"go2"时,使用LeggedRobot这个环境类,并传入我们刚定义的两个配置类GO2RoughCfg()和GO2RoughCfgPPO()的实例。
这一步虽然简单,但至关重要。我遇到过因为拼写错误(比如把go2写成go2_rough)或者导入路径不对,导致训练时提示找不到任务的情况。添加完后,最好简单运行一下Python解释器,尝试导入一下GO2RoughCfg,看看有没有报错,确保万无一失。
5. 启动训练:见证Go2从零开始学走路
一切准备就绪,最激动人心的时刻到了——启动训练,看着你的Go2从一堆随机动作中,逐渐学会协调四肢,稳步前进。
5.1 训练命令与参数解析
在legged_gym项目的根目录下,运行训练脚本。最基本的命令如下:
python legged_gym/scripts/train.py --task=go2
这条命令会使用默认参数开始训练go2任务。但为了更高效的训练,我们通常需要调整一些关键参数:
python legged_gym/scripts/train.py --task=go2 --num_envs=4096 --headless
--task=go2:指定我们要训练的任务,必须和我们注册的名字一致。--num_envs=4096:这是并行环境数量,是Isaac Gym性能强大的关键。它意味着同时在4096个独立的仿真环境中训练409个Go2机器人。数量越大,数据收集效率越高,训练越快,但对GPU显存要求也越高。你可以根据自己显卡的显存(如24G的RTX 4090)适当调整,比如从1024或2048开始尝试。--headless:这个参数表示不开启图形化渲染界面。在服务器上训练或者需要节省资源时非常有用,能大幅提升训练速度。如果你想实时观看训练过程,可以去掉这个参数。
训练开始后,终端会输出大量的日志信息,包括当前训练步数、平均奖励、 episode长度等。更重要的是,程序会在logs目录下(具体路径由experiment_name决定)创建文件夹,里面会保存:
- 训练曲线图:在
wandb或tensorboard日志中(如果配置了),可以实时查看奖励、步长等指标的变化。 - 模型检查点:定期保存的神经网络模型参数文件(
.pt格式),用于后续的继续训练或测试。 - 配置文件副本:保存本次训练使用的完整配置,确保实验可复现。
5.2 训练过程观察与调参经验
训练初期,你可能会看到平均奖励很低,甚至为负,机器人各种摔倒、抽搐,这都是正常的。强化学习就是一个从随机探索中逐渐找到规律的过程。你需要关注的是奖励曲线整体的上升趋势。
如果训练了很久奖励不见增长,或者增长到某个值就停滞了,可能就需要回头调整配置文件了。常见的调试点包括:
- 奖励权重:如果机器人总是摔倒,可以增加保持躯干高度稳定的奖励权重,或者加大摔倒惩罚。
- 初始姿态:微调
default_joint_angles,一个更稳定的初始姿态有助于学习。 - 动作缩放:如果机器人动作僵硬或幅度太小,可以调整
action_scale。 - PPO超参数:如学习率、熵系数等,但这些参数相对敏感,建议先微调奖励函数。
训练时间取决于任务难度和硬件。在RTX 4090上,使用几千个并行环境,让Go2学会在平地上稳健行走,可能只需要几十分钟到几个小时。而要学习复杂地形,则可能需要更长时间。
6. 测试与部署:让你的训练成果动起来
训练完成后,我们肯定想看看机器人的学习成果。legged_gym提供了一个很方便的脚本来加载训练好的模型并进行可视化测试。
6.1 加载模型进行可视化测试
假设你的训练实验名叫rough_go2,训练完成后会在logs/rough_go2/目录下生成带有日期时间戳的子文件夹,里面就存放着模型文件(如model_1000.pt,表示第1000次迭代保存的模型)。
运行测试脚本,并指定模型路径:
python legged_gym/scripts/play.py --task=go2 --checkpoint=logs/rough_go2/日期时间文件夹/model_1000.pt
运行这个命令会启动一个图形化窗口,加载Go2模型和训练好的策略网络。你会看到一个(或一小组)Go2机器人根据神经网络决策开始运动。你可以用鼠标和键盘调整视角,观察它的步态是否自然、稳健。
测试时,你可以尝试:
- 推它一下:在仿真界面里,有时可以通过快捷键给机器人施加一个外力,测试其抗干扰能力。
- 更换地形:如果训练时使用了随机化地形,测试时也可以看到机器人在不同地形上的表现。
- 录制视频:使用屏幕录制工具或仿真环境自带的录制功能,保存机器人的运动视频,用于展示或分析。
6.2 从仿真到实机的思考
看到仿真里的Go2走得有模有样,很多人会想:能不能把这个策略直接部署到真实的Go2机器人上?这是一个非常前沿且具有挑战性的课题,被称为“Sim-to-Real”(仿真到现实)。
直接部署通常行不通,因为仿真和现实之间存在“现实差距”。仿真的物理参数(摩擦、阻尼、电机模型)不可能和现实完全一致,传感器噪声、通信延迟等在仿真中也难以完美模拟。
目前常见的Sim-to-Real技术包括:
- 域随机化:在训练时,随机化仿真环境的一系列物理参数(如地面摩擦系数、机身质量、电机响应延迟等)。这样训练出来的策略会学会适应一个“范围”内的动力学,而不仅仅是单一模型,从而提高了对现实世界不确定性的鲁棒性。我们在配置文件中其实可以看到一些随机化的种子,更高级的随机化需要修改环境代码。
- 系统辨识与动力学适配:先采集真实机器人的运动数据,然后反过来调整仿真模型的参数,让仿真尽可能贴近真实机器人的动力学特性。
- 在线自适应:在真实机器人上运行时,策略网络能够根据实时传感器数据微调自己的输出。
对于个人开发者和小团队,直接从零实现Sim-to-Real难度很大。更实际的路径是,利用仿真环境快速进行算法原型验证和策略初训,然后将策略作为一个很好的初始点,在真实机器人上通过少量实际数据,进行微调或在线学习。宇树科技官方也提供了一些真实的控制接口和SDK,可以结合使用。
7. 避坑指南与进阶建议
回顾整个流程,我踩过不少坑,这里总结几个最常见的,希望能帮你节省时间:
- URDF路径错误:这是最典型的错误。务必确认
go2_config.py中asset.file的路径是正确的,并且{LEGGED_GYM_ROOT_DIR}这个环境变量是否已正确设置。一个简单的检查方法是,在Python中尝试用open()函数打开这个URDF文件,看是否能成功。 - 关节名称不匹配:URDF文件中定义的关节名称(如
FL_hip_joint)必须和配置文件中default_joint_angles字典的键完全一致,包括大小写。一个字母之差都会导致控制器找不到对应关节。 - 足端名称错误:
asset.foot_name也必须和URDF中足端连杆的名称一致。如果错了,算法无法判断哪些接触是有效的“脚触地”,哪些是无效的“身体触地”,奖励计算会完全混乱。 - 训练不收敛:如果奖励曲线一直不上升,首先检查奖励函数的权重设置是否合理。可以尝试先从一个非常简单的任务开始,比如只给“向前移动速度”和“存活时间”奖励,让机器人先学会往前走,再逐步增加保持高度、减少能耗等复杂要求。
- 显存不足:如果设置
--num_envs过大,可能会导致GPU显存溢出(OOM)。训练时会报CUDA out of memory错误。解决方法是逐步减小num_envs,直到能够稳定运行。同时,在配置文件中可以尝试减小env.num_observations或env.num_actions(如果支持),或者降低仿真视觉渲染的分辨率(如果用了视觉输入)。
对于想深入优化的朋友,可以探索以下方向:
- 自定义地形:修改环境代码,生成更复杂、更有挑战性的地形,如楼梯、碎石路等。
- 引入传感器噪声:在观测值中加入高斯噪声,让策略对传感器误差更鲁棒。
- 尝试其他算法:
legged_gym默认使用PPO,你也可以尝试集成SAC、TD3等其他强化学习算法,看看在足式机器人控制上是否有更好的效果。 - 结合真实数据:如果你有真实的Go2机器人,可以尝试记录一些运动数据,用于校正仿真模型或进行模仿学习。
配置和训练一个机器人强化学习环境,第一次做会觉得步骤繁琐,但一旦跑通,你会发现这是一套非常高效的流程。它把复杂的机器人控制问题,抽象成了配置文件和训练超参数的调整问题。最重要的是动手实践,从修改一个参数、观察一次训练曲线开始,你会对机器人如何学习运动产生更直观和深刻的理解。
551



被折叠的 条评论
为什么被折叠?



