Nvidia Isaac Lab 8 - 在 Isaac Lab 中,训练第二个机器人 - 2. 在 Isaac Lab 中配置机器人
1. 概述
在 Isaac Lab 中,可以通过多种方式,开发机器人训练任务,本教程使用模板选项,该方式适用于外部独立项目。
2. 还可以通过哪些方式进行 Isaac Lab 开发?
可以“Fork”整个 Isaac Lab 仓库,直接在其中进行开发。开发新功能、向代码库贡献代码,或补充文档时常采用该方式。使用这种方式时,由于自己的项目位于 Isaac Lab 仓库的内部结构中,所以项目不够独立清晰,升级 Isaac Lab 版本也更复杂。
Isaac Lab 提供用于生成项目模板的命令行工具。该工具既可以生成内部任务,也可以生成外部项目。为简单起见,本教程使用外部项目,仓库里只包含自己项目相关的代码!
3. 创建 Isaac Lab 项目
下面创建新项目。
3.1. 使用外部项目模版
- 打开新终端。
- 导航到 Isaac Lab 文件夹。
- 激活虚拟环境。
- 使用
—-new参数运行 Isaac Lab 脚本,创建模版项目。./isaaclab.sh --new
- 模版项目将询问若干问题。在命令行菜单中,使用箭头移动,使用空格选择选项,然后按回车键确认选项。
- 任务类型:选择 External。
- 项目路径:按需设置,只需记下即可。
- 项目名称:比如 Reach。
- Isaac Lab 工作流:选择 Manager-based | single-agent 工作流。
- RL 库:选择
skrl作为强化学习库。
- RL 算法:选择 PPO,即近端策略优化(Proximal Policy Optimization)的缩写。
3.2. 安装项目
- 进入新项目文件夹。
- 运行以下命令安装外部项目。该命令以“可编辑”模式安装包,这在开发过程中很有用。注意命令末尾使用项目名称。
python -m pip install -e source/Reach
至此,已经准备好机器人 USD 文件,也创建好包含训练代码的项目。下面在 Isaac Lab 框架中实现训练所需的配置和逻辑,将两者结合起来。
4. 在 Isaac Lab 中配置机器人
4.1. Articulation 配置
在项目内部,使用 ArticulationCfg 类(即 Articulation Configuration)为机器人创建配套配置。
Articulation 是通过关节连接的刚体层级结构,比如组成 UR10 机器人的旋转关节。

4.1.1. 可视化 UR10 的关节和连杆
下面创建配置,将其添加到场景中,进行预览,确认是否已经正确设置。
注意
为什么同时在 Isaac Sim 和 Isaac Lab 中配置机器人?
原因有多个。比如训练机器人时需要桌子或道具,但不希望将这些资源保存到核心机器人的 USD 文件中。
Isaac Lab 支持在不覆盖已有 USD 的情况下,尝试不同的关节结构属性,或在训练过程中模拟不同类型的执行器。
4.2. 创建配置
在单独的文件中创建配置,可以在其它训练任务中复用该配置:同一机器人,不同用途。模块化是 Isaac Lab 的关键特性之一!
- 在项目文件夹内,在
Reach/source/Reach/Reach/tasks/manager_based/reach下创建新 Python 文件,命名为ur_gripper.py。该文件用于保存
Articulation Configuration,可以在当前训练任务中使用,也可以在未来的训练项目中复用。
- 复制粘贴以下代码:
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause """Configuration for the Universal Robots. Reference: https://github.com/ros-industrial/universal_robot """ import isaaclab.sim as sim_utils from isaaclab.actuators import ImplicitActuatorCfg from isaaclab.assets.articulation import ArticulationCfg UR_GRIPPER_CFG = ArticulationCfg( # Where is the USD file for this robot? spawn=sim_utils.UsdFileCfg( usd_path=f"/home/ubuntu/Reach/UR-with-gripper.usd", activate_contact_sensors=False, rigid_props=sim_utils.RigidBodyPropertiesCfg( rigid_body_enabled=True, max_linear_velocity=1000.0, max_angular_velocity=1000.0, max_depenetration_velocity=5.0, ), articulation_props=sim_utils.ArticulationRootPropertiesCfg( enabled_self_collisions=True, solver_position_iteration_count=8, solver_velocity_iteration_count=0 ), ), # What is its initial position of the robot, and its joints? init_state=ArticulationCfg.InitialStateCfg( joint_pos={ "shoulder_pan_joint": 0.0, "shoulder_lift_joint": -1.712, "elbow_joint": 1.712, "wrist_1_joint": 0.0, "wrist_2_joint": 0.0, "wrist_3_joint": 0.0, }, ), # What parts of the robot move, and how stiff / damped are they? actuators={ "arm": ImplicitActuatorCfg( joint_names_expr=[".*"], effort_limit=87.0, stiffness=800.0, damping=40.0, ), "gripper": ImplicitActuatorCfg( joint_names_expr=["finger_joint"], stiffness=280, damping=28 ), } )
从高层次拆解这段代码:
- 机器人 USD 文件在哪里?
- 机器人的初始位置和关节状态是什么?默认情况下各个关节应处于什么位置,机器人在空间中的什么位置?
- 机器人的哪些部分运动?刚度和阻尼是多少?
- 本教程使用隐式执行器,即理想化的执行器。对于 Sim-To-Real 迁移,需要更仔细地思考如何表示机器人电机。
- 可以通过多种方式指定。这里利用正则表达式,大致意思是“获取所有以指定文本开头的关节,然后为它们分配这些参数。”
- 这样做的好处是不必与机器人的层级结构进行强绑定。
4.3. 确定刚度和阻尼
如果事先没有刚度和阻尼值,那么如何确定合适的数值呢?简而言之,可以根据具体用例,为自定义机器人计算这些值,或者经验性地寻找这些值。
本教程不深入讲解具体调参,但先简单了解基础概念。隐式执行器使用的是 PD,也就是“比例-微分”(Proportional-Derivative)控制器。其中“比例”部分对应刚度, “微分”部分对应阻尼。
更高的刚度值意味着执行器更积极地尝试到达目标位置。但如果刚度太高,执行器可能振荡,并且难以稳定在目标位置。如果阻尼太高,关节难以快速到达目标位置。
在这里了解更多关于 Isaac Sim 中关节调参的内容。
注意
如果以前用过 Isaac Sim,可能疑惑为什么使用专门的配置类定义灯光和地平面。难道不能直接在 USD 文件中定义这些内容吗?
当然可以。这样做的目的不是重复 USD 文件准备阶段已经完成的工作,而是支持针对训练任务进行自定义配置。比如可以为行走机器人添加自定义地形,或者为感知任务训练加入特殊的随机光照。Isaac Lab 支持配置这些,且无需向机器人 USD 文件中额外添加灯光。
5. 测试机器人配置
Python 文件中的第一个类是场景配置。模板项目自带“Cartpole” 示例。下面更新该配置。
5.1. 导入机器人配置
- 打开文件
source/Reach/Reach/tasks/manager_based/reach/reach_env_cfg.py
- 导入新机器人配置。用下面这条导入语句替换原来引用
CARTPOLE_CFG的导入语句:from .ur_gripper import UR_GRIPPER_CFG
- 更新
ReachSceneCfg类。保留地平面和穹顶灯,更换机器人。确认ReachSceneCfg类看起来与下面的示例一致。注意此处引用新UR_GRIPPER_CFG。@configclass class ReachSceneCfg(InteractiveSceneCfg): """Configuration for a scene.""" # world ground = AssetBaseCfg( prim_path="/World/ground", spawn=sim_utils.GroundPlaneCfg(), init_state=AssetBaseCfg.InitialStateCfg(pos=(0.0, 0.0, -1.05)), ) # robot robot = UR_GRIPPER_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot") # lights dome_light = AssetBaseCfg( prim_path="/World/DomeLight", spawn=sim_utils.DomeLightCfg(color=(0.9, 0.9, 0.9), intensity=5000.0), ) table = AssetBaseCfg( prim_path="{ENV_REGEX_NS}/Table", spawn=sim_utils.UsdFileCfg( usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Mounts/SeattleLabTable/table_instanceable.usd", ), init_state=AssetBaseCfg.InitialStateCfg(pos=(0.55, 0.0, 0.0), rot=(0.70711, 0.0, 0.0, 0.70711)), ) # plane plane = AssetBaseCfg( prim_path="/World/GroundPlane", init_state=AssetBaseCfg.InitialStateCfg(pos=[0, 0, -1.05]), spawn=GroundPlaneCfg(), )
5.2. 思考
如果编写机器人抓取立方体的任务,还需要向场景中添加哪些资源?Isaac Lab 还提供用于控制场景生成和随机化的工具,辅助训练。如何在训练过程中使用随机化?
