Hydra 配置系统#
通过 Hydra 覆盖参数,可在命令行修改任务和智能体设置,无需编辑 Python。
环境设置使用 env.<path>=<value>,例如 env.actions.joint_effort.scale=10.0;训练设置使用 agent 前缀,例如 agent.seed=2024。
路径遵循各强化学习库的配置结构。例如,RL-Games 使用 agent.params.seed,RSL-RL、skrl 和 SB3 使用 agent.seed。
例如:
uv run isaaclab train --rl_library rsl_rl --task=Isaac-Cartpole env.actions.joint_effort.scale=10.0 agent.seed=2024
uv run --extra rl-games isaaclab train --rl_library rl_games --task=Isaac-Cartpole env.actions.joint_effort.scale=10.0 agent.params.seed=2024
uv run --extra skrl isaaclab train --rl_library skrl --task=Isaac-Cartpole env.actions.joint_effort.scale=10.0 agent.seed=2024
uv run --extra sb3 isaaclab train --rl_library sb3 --task=Isaac-Cartpole env.actions.joint_effort.scale=10.0 agent.seed=2024
上述命令训练 Isaac-Cartpole 任务,不选择可视化器,并将 env.actions.joint_effort.scale 设为 10.0、 agent.seed 设为 2024。
备注
为了保持向后兼容性,并提供更友好的用户体验,我们保留了旧的 cli 参数形式 --param ,例如 --num_envs 、 --seed 、 --max_iterations 。这些参数优先于 hydra 参数,并将覆盖由 hydra 参数设置的值。
修改高级参数#
可调用对象#
使用 module:attribute_name 选择函数或类。例如,在 Cartpole 中:
class ObservationsCfg:
"""Observation specifications for the MDP."""
@configclass
class PolicyCfg(ObsGroup):
"""Observations for policy group."""
# observation terms (order preserved)
joint_pos_rel = ObsTerm(func=mdp.joint_pos_rel)
joint_vel_rel = ObsTerm(func=mdp.joint_vel_rel)
def __post_init__(self):
self.enable_corruption = False
self.concatenate_terms = True
# observation groups
policy: PolicyCfg = PolicyCfg()
我们可以修改 joint_pos_rel 以计算绝对位置,而不是相对位置,使用 env.observations.policy.joint_pos_rel.func=isaaclab.envs.mdp:joint_pos 。
将参数设置为 None#
要将参数设置为 None,请使用 null 关键字,这是 Hydra 中的一个特殊关键字,会自动转换为 None。在上面的示例中,我们还可以通过将 env.observations.policy.joint_pos_rel=null 设置为 None 来禁用 joint_pos_rel 观测。
字典#
字典中的元素作为配置层级中的参数处理。例如,在 Cartpole 环境中:
reset_cart_position = EventTerm(
func=mdp.reset_joints_by_offset,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("robot", joint_names=["slider_to_cart"]),
"position_range": (-1.0, 1.0),
"velocity_range": (-0.5, 0.5),
},
)
position_range 参数可以通过 env.events.reset_cart_position.params.position_range="[-2.0, 2.0]" 进行修改。这个例子展示了两个值得注意的点:
该值包含空格,因此必须用引号括起,供 shell 正确解析。
参数是一个列表,而在 config 中它是一个元组。这是因为 Hydra 不支持元组。
修改高级参数#
覆盖参数不会重新计算此前已由其他设置推导出的值。除非环境会在运行时重新计算,否则也需更新这些依赖值。
例如,Cartpole 相机环境的配置:
class CartpoleCameraEnvCfg(PresetCfg):
"""Cartpole camera environment with a selectable camera data type.
The selector also picks the matching tiled camera preset and its rendering backend through
:attr:`CartpoleCameraSceneCfg.tiled_camera`.
"""
@configclass
class BaseCartpoleCameraEnvCfg(CartpoleEnvCfg):
"""Camera variant of :class:`CartpoleEnvCfg`; only the fields that differ are overridden."""
write_image_to_file = False
frame_stack: int = 2
"""Number of frames to stack along the channel dimension.
Values less than two disable stacking.
"""
# spaces: single-frame channels + default spatial size. At env init, height/width
# are replaced with the tiled camera size and channels are expanded by frame_stack.
# Only the channel count must stay in sync with the camera data type (presets set this).
observation_space = [3, 96, 96]
配置声明单帧通道数和默认空间尺寸。环境初始化时, CartpoleCameraEnv 根据解析后的相机重新构建 observation_space :默认 frame_stack=2 会扩展通道数,高度和宽度来自 scene.tiled_camera 。因此,仅设置 env.scene.tiled_camera.width=128 env.scene.tiled_camera.height=128 ,就会得到有效的堆叠形状 [6,128,128] ,无需同时覆盖 env.observation_space 。 observation_space 中的通道数仍必须匹配相机数据类型(例如 presets=depth 对应 [1, ...] );预设已完成这一设置。
类体中的赋值在导入时只求值一次, 不会 随后续 Hydra 覆盖自动更新,除非运行时代码显式重新构建依赖值,正如这个相机环境所做的那样。
类似地, __post_init__ 方法不会随着命令行输入而更新。在 LocomotionVelocityRoughEnvCfg 中,例如,post init 更新如下:
class LocomotionVelocityRoughEnvCfg(ManagerBasedRLEnvCfg):
"""Configuration for the locomotion velocity-tracking environment."""
# Simulation settings
sim: SimulationCfg = SimulationCfg(physics=RoughPhysicsCfg())
# Scene settings
scene: MySceneCfg = MySceneCfg(num_envs=4096, env_spacing=2.5)
# Basic settings
observations: ObservationsCfg = ObservationsCfg()
actions: ActionsCfg = ActionsCfg()
commands: CommandsCfg = CommandsCfg()
# MDP settings
rewards: RewardsCfg = RewardsCfg()
terminations: TerminationsCfg = TerminationsCfg()
events: EventsCfg = EventsCfg()
curriculum: CurriculumCfg = CurriculumCfg()
def __post_init__(self):
"""Post initialization."""
# general settings
self.decimation = 4
self.episode_length_s = 20.0
# simulation settings
self.sim.dt = 0.005
self.sim.render_interval = self.decimation
self.sim.physics_material = self.scene.terrain.physics_material
# update sensor update periods
# we tick all the sensors based on the smallest update period (physics update period)
if self.scene.height_scanner is not None:
self.scene.height_scanner.update_period = self.decimation * self.sim.dt
if self.scene.contact_forces is not None:
self.scene.contact_forces.update_period = self.sim.dt
# check if terrain levels curriculum is enabled - if so, enable curriculum for terrain generator
# this generates terrains with increasing difficulty and is useful for training
if getattr(self.curriculum, "terrain_levels", None) is not None:
if self.scene.terrain.terrain_generator is not None:
self.scene.terrain.terrain_generator.curriculum = True
else:
if self.scene.terrain.terrain_generator is not None:
self.scene.terrain.terrain_generator.curriculum = False
def play_mode(self):
"""Play-mode overrides shared by the velocity-tracking environments."""
super().play_mode()
# spawn the robot randomly in the grid (instead of their terrain levels)
self.scene.terrain.max_init_terrain_level = None
# reduce the number of terrains to save memory
if self.scene.terrain.terrain_generator is not None:
self.scene.terrain.terrain_generator.num_rows = 5
self.scene.terrain.terrain_generator.num_cols = 5
self.scene.terrain.terrain_generator.curriculum = False
# remove random pushing events
self.events.base_external_force_torque = None
self.events.push_robot = None
在这里,当修改 env.decimation 或 env.sim.dt 时,用户还需要输入更新后的 env.sim.render_interval 、 env.scene.height_scanner.update_period 和 env.scene.contact_forces.update_period 。
自定义配置验证#
Configclass 对象可以定义 validate_config() 方法,在所有字段解析后执行领域相关验证。预设解析和 MISSING 字段检查成功后会自动调用该钩子,使你能尽早发现无效参数组合,并提供明确的错误信息。
例如,Franka 到达任务配置会验证 Newton IK 动作预设是否与 Newton 物理配置配合使用:
def validate_config(self) -> None:
"""Validate the selected controller and physics backend."""
if self.observations.policy.ee_target_error is not None and not isinstance(
self.actions.arm_action, mdp.JointPositionActionCfg
):
raise ValueError("The 'hold' preset requires the Franka joint-position action.")
if isinstance(self.actions.arm_action, NewtonInverseKinematicsActionCfg) and not isinstance(
self.sim.physics, NewtonCfg
):
raise ValueError("The 'newton_ik' action preset requires a Newton physics preset.")
执行时机:
先检查所有
MISSING字段;仍有缺失时抛出TypeError。只有此后,才在 顶层 配置对象上调用
validate_config()。该钩子应抛出
ValueError,并给出明确说明和迁移建议。
常见验证内容:
独立选择的控制器、物理配置和渲染器之间的兼容性
渲染器、相机数据类型和特征提取器的兼容性
仅靠字段类型无法表达的数值关系或限制
预设系统#
若想从使用者角度了解如何选择物理、渲染和任务变体,请先阅读 后端与预设 。本节介绍完整的预设定义和解析行为。
预设系统允许通过一个命令行参数替换整个配置部分,或单个标量值。无需逐字段覆盖,只需选择命名预设,即可 完全替换 对应配置部分(不合并字段)。
预设通过继承 PresetCfg ,或使用便捷工厂 preset() 声明。系统自动从嵌套配置中递归发现全部预设,包括字典字段内的预设(例如 actuators )。
覆盖顺序#
实际优先级从低到高为:
默认值 :未解析的
PresetCfg回退到各自的default字段。带类型和领域选择 :
physics=newton_mjwarp选择物理配置,presets=rgb将任务特有名称广播到所有匹配配置。路径选择 :
env.sim.physics=newton_kamino定位一个具体的PresetCfg,并在该路径上优先生效。回放模式修改 :回放命令请求时,将环境的
play_mode()修改应用到解析后的配置。标量覆盖 :
env.sim.dt=0.001对单个字段具有最终决定权。
如果多个广播名称在同一有效路径上选择不同选项,解析会失败,而不是静默选择其中一个。
使用 PresetCfg 定义预设#
创建 PresetCfg 子类,将每个字段定义为一个命名选项。没有命令行覆盖时,使用 default 字段指定的配置:
from isaaclab.sim import SimulationCfg
from isaaclab.utils import configclass
from isaaclab_newton.physics import NewtonCfg
from isaaclab_physx.physics import PhysxCfg
from isaaclab_tasks.utils import PresetCfg
@configclass
class PhysicsPresetsCfg(PresetCfg):
isaacsim_physx: PhysxCfg = PhysxCfg()
default: PhysxCfg = isaacsim_physx
newton_mjwarp: NewtonCfg = NewtonCfg()
@configclass
class MyEnvCfg:
sim: SimulationCfg = SimulationCfg(physics=PhysicsPresetsCfg())
物理由 SimulationCfg 管理,因此预设配置路径是 env.sim.physics 。选择后端时优先使用带类型选择器:
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole physics=newton_mjwarp
只有明确希望替换这一个预设节点、而不选择其他匹配的任务预设时,才使用路径形式 env.sim.physics=newton_mjwarp 。
将 default 字段设为 None ,可定义默认关闭、只有显式选择才启用的可选功能:
@configclass
class CameraSettingsCfg:
width: int = 64
height: int = 64
@configclass
class CameraPresetCfg(PresetCfg):
default = None
small: CameraSettingsCfg = CameraSettingsCfg()
large: CameraSettingsCfg = CameraSettingsCfg(width=256, height=256)
@configclass
class SceneCfg:
camera: CameraPresetCfg = CameraPresetCfg()
此处 env.scene.camera 默认解析为 None 。使用该配置的已注册任务可以通过路径选择器 env.scene.camera=large 启用大相机。
后端与求解器预设#
物理后端选择使用同一预设系统。任务可以定义 PresetCfg ,各条目替换完整物理配置:
Cartpole 任务中的定义是一个持续维护的示例:
class CartpolePhysicsCfg(PresetCfg):
"""Physics backend presets for the cartpole environments."""
isaacsim_physx: PhysxCfg = PhysxCfg()
ovphysx: OvPhysxCfg = OvPhysxCfg()
physx: PhysxAutoCfg = PhysxAutoCfg(isaacsim_physx=isaacsim_physx, ovphysx=ovphysx)
newton_mjwarp: NewtonCfg = NewtonCfg(
solver_cfg=MJWarpSolverCfg(
njmax=5,
nconmax=3,
cone="pyramidal",
impratio=1,
integrator="implicitfast",
),
num_substeps=1,
debug_mode=False,
use_cuda_graph=True,
)
newton_kamino: NewtonCfg = NewtonCfg(
solver_cfg=KaminoPADMMSolverCfg(sparse_jacobian=True),
debug_mode=False,
use_cuda_graph=True,
)
default: NewtonCfg = newton_mjwarp
newton_mjwarp 和 newton_kamino 均选择 Newton 物理后端,因为两者都是 NewtonCfg 对象。区别在于求解器配置: newton_mjwarp 使用 MJWarpSolverCfg , newton_kamino 使用 KaminoPADMMSolverCfg 。
因此,Kamino 是求解器预设,不是独立的 Isaac Lab 后端。预设解析后,仍使用同一套 Newton 资产、传感器、渲染器和可视化器。它是基于近端交替方向乘子法(P-ADMM)的约束刚性多体动力学求解器。
备注
Kamino 要求资产具有兼容的模型结构。能够使用 MuJoCo-Warp 或 PhysX 预设的资产,可能仍需调整模型结构,才能使用 physics=newton_kamino。
# Preferred: select and validate a physics preset by type
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole physics=newton_kamino
# Advanced: replace only the physics config at this path
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole env.sim.physics=newton_kamino
后端支持范围取决于具体任务,并会随验证进展变化,以任务的 --help 输出为准。向未列出该预设的任务传入 physics=newton_kamino 会失败,不会自动为该任务添加 Kamino 配置。
通过 preset() 定义内联预设#
对于不值得单独定义完整子类的简单值(标量、列表),使用 preset() 工厂。它根据关键字参数动态创建 PresetCfg 实例:
from isaaclab_tasks.utils.hydra import preset
# Scalar preset -- no boilerplate subclass
self.scene.robot.actuators["legs"].armature = preset(
default=0.0, isaacsim_physx=0.0, newton_mjwarp=0.01, physx=0.0
)
这会创建与 PresetCfg 子类相同的字段,default 参数必填。
preset() 适用于任意值类型,包括标量、列表,甚至配置实例:
# Resolution preset on a camera config field
width = preset(default=64, res128=128, res256=256)
# List preset for camera data types
@configclass
class DataTypeCfg(PresetCfg):
default: list = ["rgb"]
depth: list = ["depth"]
albedo: list = ["albedo"]
定义可以写在一行时,使用 preset() 。选项较复杂、需要类型注解和多行排版时,使用 PresetCfg 子类。
预设系统会发现配置树中任意位置的 preset() 值,包括 actuators 等字典字段内部:
# Select MJWarp physics and all matching dependent alternatives
uv run isaaclab train --rl_library rsl_rl \
--task IsaacContrib-Velocity-Rough-AnymalC physics=newton_mjwarp
带类型的 physics= 选择器按所选名称进行广播解析,因此具有相同名称的任务选项(例如这里的电枢惯量值)也会更新。它还验证该名称确实解析出了物理配置;自由形式的 presets= 选择器不提供这一类型检查。
带类型的预设选择器#
预设命令行层识别三种 key=value 参数(不带前导短横线),可附加到任意训练或回放脚本命令后:
参数 |
作用 |
|---|---|
|
用于选择 |
|
用于选择 |
|
广播:应用到配置树中每个匹配的 |
带类型选择器采用与 presets= 相同的广播解析。因此 physics=newton_mjwarp 也可以更新具有相同名称的依赖任务预设,例如执行器或事件设置。但它们并不等价:带类型选择器必须解析出至少一个声明类型的配置,否则报错。后端选择使用 physics= 和 renderer= ,任务特有模式使用 presets= 。
常见物理预设名称 (仅当任务列出时可用):
名称 |
后端 |
|---|---|
|
明确的 Isaac Sim PhysX 配置 |
|
在已配置的选项中自动选择 PhysX 系列后端 |
|
使用 MuJoCo-Warp 求解器的 Newton 物理配置 |
|
使用 Kamino 求解器的 Newton 物理后端(部分任务支持,见 后端与求解器预设) |
|
受支持的不依赖 Kit 的任务所用的明确 OvPhysX 配置 |
常见渲染器预设名称 (由 MultiBackendRendererCfg 提供时):
名称 |
渲染器 |
|---|---|
|
明确的 Isaac Sim RTX 渲染器 |
|
在已配置的选项中自动选择 RTX 系列渲染器 |
|
Newton Warp 渲染器 |
|
受支持的不依赖 Kit 的任务所用的明确 OVRTX 渲染器 |
隐含的 default 字段由任务决定,并有意不在 --help 中列出。不要根据这些惯用名称推断任务默认后端,应查看帮助输出或配置。 physics=physx 和 renderer=rtx 等自动选择需显式启用,并非通用默认值。
领域预设(观测模式、相机配置等)取决于任务。向训练命令传入 --task=<task-name> --help ,可查看按选择器类型分组的全部可用任务预设。
对于强化学习任务,预设解析将已注册的环境和智能体配置组合为同级根节点。因此,库的规范 <library>_cfg_entry_point 可以返回根级 PresetCfg ,包含与环境相同名称的选项。 presets=resnet18 这样的广播会在一次解析中,在两个根节点上都选择 resnet18 :
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole-Camera presets=resnet18
这是使依赖环境的策略形状(例如特征提取器或动作空间输出头)与所选环境保持一致的推荐方式,无需预设专属的注册条目,也无需改写 --agent 。
独立的训练方案仍通过显式选择智能体来指定。任务可以为对称性、循环网络、蒸馏或其他算法选择不同智能体,而不改变环境预设。
该模型不使用预设专属的智能体入口,也不在注册表端维护预设到智能体的映射。应使用规范入口,并通过 presets= 选择变体。对于旧版 SKRL 运行,如果其清单或目录以配置键后缀而非 agent.class 表示算法,请显式传入检查点路径,不要使用自动 latest 或 best 发现。
备注
旧别名 newton → newton_mjwarp 和 kamino → newton_kamino 仍可使用,但会发出 FutureWarning 。渲染器别名 isaacsim_rtx_renderer → isaacsim_rtx 和 ovrtx_renderer → ovrtx 也如此。请优先使用规范名称。
使用预设#
带类型选择器 — 选择物理和渲染器后端的推荐形式:
# Switch to Newton MuJoCo-Warp physics
uv run isaaclab train --rl_library rsl_rl \
--task IsaacContrib-Velocity-Rough-AnymalC physics=newton_mjwarp
# Switch to Newton renderer for camera environments
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole-Camera-Direct renderer=newton_renderer
# Combine typed selectors with a task-specific observation preset
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole-Camera-Direct \
physics=newton_mjwarp renderer=newton_renderer presets=rgb
路径预设 — 为一个配置路径选择具体预设:
# Replace only this task's physics preset node
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole env.sim.physics=newton_kamino
领域预设 — 在所有存在该名称的位置广播任务特有选项:
# Keep the observation pipeline and camera data type in sync
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole-Camera presets=depth
多个领域预设 — 应用多个互不冲突的任务选项:
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Lift-KukaAllegro-Camera presets=duo_camera,rgb128
KukaAllegro 的 -Camera 任务默认使用单相机,以及与之匹配的 RSL-RL CNN actor。 presets=duo_camera 同时切换相机组合和 actor 输入;critic 继续使用状态观测。
组合使用 — 带类型选择器、领域预设和标量覆盖:
uv run isaaclab train --rl_library rsl_rl \
--task Isaac-Cartpole-Camera \
physics=newton_mjwarp renderer=newton_renderer presets=rgb \
env.sim.dt=0.002
全局预设冲突检测#
如果两个全局预设都匹配同一配置路径,会抛出错误,尽早暴露歧义:
ValueError: Conflicting global presets: 'foo' and 'bar'
both define preset for 'env.events'
实际示例#
ANYmal-C 运动环境展示了 PresetCfg 与 preset() 的配合使用:
class AnymalCRoughEnvCfg(LocomotionVelocityRoughEnvCfg):
def __post_init__(self):
super().__post_init__()
# scene
self.scene.robot = replace(ANYMAL_C_CFG, prim_path="{ENV_REGEX_NS}/Robot")
基础速度配置还为物理和质心随机化事件定义了 newton_mjwarp 选项,MJWarp 会禁用该事件。显式设置 physics=newton_mjwarp ,会解析物理配置及具有同名的所有有效依赖选项:禁用该事件,并将 ANYmal-C 执行器电枢惯量设为 0.01 。带类型选择器还会验证确实选中了物理预设。
uv run isaaclab train --rl_library rsl_rl \
--task IsaacContrib-Velocity-Rough-AnymalC physics=newton_mjwarp
不提供选择器时,各 PresetCfg 独立使用自己的 default ;默认选项的名称不会广播到其他预设节点。
总结#
覆盖类型 |
语法 |
作用 |
|---|---|---|
标量 |
|
修改单个字段 |
路径预设 |
|
替换整个配置部分 |
领域预设 |
|
在所有匹配位置应用任务特有名称 |
带类型的物理选择器 |
|
选择物理变体,更新匹配的依赖预设,并要求类型匹配 |
带类型的渲染器选择器 |
|
选择渲染器变体,并要求类型匹配 |
组合使用 |
|
带类型选择器 + 领域预设 + 标量覆盖 |