Hydra 配置系统#
Isaac Lab 支持 Hydra 配置系统,以通过命令行参数修改任务的配置,这对于自动化实验和执行超参数调整非常有用。
环境的任何参数都可以通过在命令行输入中添加一个或多个形式为 env.a.b.param1=value
的元素来修改,其中 a.b.param1
反映了参数的层次结构,例如 env.actions.joint_effort.scale=10.0
。类似地,智能体的参数可以通过使用 agent
前缀来修改,例如 agent.seed=2024
。
这些命令行参数的设置方式遵循配置文件的精确结构。由于不同的 RL 框架使用不同的约定,因此参数设置方式可能会有所不同。例如,使用 rl_games 时,种子将通过 agent.params.seed
设置,而在 rsl_rl 、 skrl 和 sb3 中,则通过 agent.seed
设置。
因此,使用 hydra 参数进行训练可以使用以下语法运行:
python source/standalone/workflows/rsl_rl/train.py --task=Isaac-Cartpole-v0 --headless env.actions.joint_effort.scale=10.0 agent.seed=2024
python source/standalone/workflows/rl_games/train.py --task=Isaac-Cartpole-v0 --headless env.actions.joint_effort.scale=10.0 agent.params.seed=2024
python source/standalone/workflows/skrl/train.py --task=Isaac-Cartpole-v0 --headless env.actions.joint_effort.scale=10.0 agent.seed=2024
python source/standalone/workflows/sb3/train.py --task=Isaac-Cartpole-v0 --headless env.actions.joint_effort.scale=10.0 agent.seed=2024
上述命令将以无头模式运行任务 Isaac-Cartpole-v0
的训练脚本,并将 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) -> None:
self.enable_corruption = False
self.concatenate_terms = True
# observation groups
policy: PolicyCfg = PolicyCfg()
我们可以修改 joint_pos_rel
以计算绝对位置,而不是相对位置,使用 env.observations.policy.joint_pos_rel.func=omni.isaac.lab.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),
},
)
reset_pole_position = EventTerm(
func=mdp.reset_joints_by_offset,
mode="reset",
params={
"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"]),
"position_range": (-0.25 * math.pi, 0.25 * math.pi),
"velocity_range": (-0.25 * math.pi, 0.25 * math.pi),
},
)
@configclass
class RewardsCfg:
"""Reward terms for the MDP."""
position_range
参数可以通过 env.events.reset_cart_position.params.position_range="[-2.0, 2.0]"
进行修改。这个例子展示了两个值得注意的点:
我们设置的参数包含空格,因此必须用引号括起来。
参数是一个列表,而在 config 中它是一个元组。这是因为 Hydra 不支持元组。
修改高级参数#
在使用命令行参数修改参数时应特别小心。一些配置会根据其他参数执行中间计算。这些计算在参数被修改时不会更新。
例如,对于 Cartpole 相机深度环境的配置:
class CartpoleDepthCameraEnvCfg(CartpoleRGBCameraEnvCfg):
# camera
tiled_camera: TiledCameraCfg = TiledCameraCfg(
prim_path="/World/envs/env_.*/Camera",
offset=TiledCameraCfg.OffsetCfg(pos=(-5.0, 0.0, 2.0), rot=(1.0, 0.0, 0.0, 0.0), convention="world"),
data_types=["depth"],
spawn=sim_utils.PinholeCameraCfg(
focal_length=24.0, focus_distance=400.0, horizontal_aperture=20.955, clipping_range=(0.1, 20.0)
),
width=80,
height=80,
)
# spaces
observation_space = [tiled_camera.height, tiled_camera.width, 1]
如果用户修改了相机的宽度,即 env.tiled_camera.width=128
,那么参数 env.observation_space=[80,128,1]
也必须更新并作为输入提供。
类似地,__post_init__
方法不会随着命令行输入而更新。在 LocomotionVelocityRoughEnvCfg
中,例如,post init 更新如下:
class LocomotionVelocityRoughEnvCfg(ManagerBasedRLEnvCfg):
"""Configuration for the locomotion velocity-tracking environment."""
# 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: EventCfg = EventCfg()
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.disable_contact_processing = True
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
在这里,当修改 env.decimation
或 env.sim.dt
时,用户还需要输入更新后的 env.sim.render_interval
、env.scene.height_scanner.update_period
和 env.scene.contact_forces.update_period
。