任务设计工作流

任务设计工作流#

环境定义了代理和模拟之间的接口。在最简单的情况下,环境提供代理当前的观察结果并执行代理提供的操作。在马尔可夫决策过程(MDP)的形式化中,环境还可以提供额外的信息,如当前奖励、完成标志和当前情节的信息。

虽然环境接口很容易理解,但根据任务的复杂性,其实现可能会有很大差异。在强化学习(RL)的背景下,环境的实现可以分解为几个组件,如奖励函数、观察函数、终止函数和重置函数。根据任务的复杂性和所需的模块化级别,每个组件可以以不同的方式实现。

我们为设计框架提供了两种不同的工作流:

  • 基于管理器:环境被分解为处理环境不同方面的单个组件(或管理器)(如计算观察、应用操作和应用随机化)。用户为每个组件定义配置类,环境负责协调管理器并调用它们的函数。

  • 直接:用户定义一个实现整个环境的单个类,而无需单独的管理器。该类负责计算观察、应用操作和计算奖励。

这两种工作流各有优缺点。基于管理器的工作流更具模块化,可以轻松地切换环境的不同组件。在原型环境和试验不同配置时很有用。另一方面,直接的工作流更高效,提供了更精细的控制环境逻辑的能力。在优化环境性能或实施难以分解为单独组件的复杂逻辑时很有用。

基于管理器的环境#

大多数环境实现都遵循相似的结构。环境处理输入操作,模拟步骤,计算观察和奖励,应用随机化,并重置终止的环境。受此激励,环境可以被分解为处理每一个任务的单个组件。例如,观察管理器负责计算观察,奖励管理器负责计算奖励,终止管理器负责计算终止信号。该方法称为框架中的基于管理器的环境设计。

基于管理器的环境通过将任务分解为由单独类管理的单个组件,促进了任务的模块化实现。任务的每个组件,如奖励、观察、终止都可以作为单独的配置类指定,然后传递给相应的管理器类。然后管理器负责解析配置并处理其配置中指定的内容。

不同管理器的协作由类 envs.ManagerBasedRLEnv 进行编排。它接受任务配置类的实例( envs.ManagerBasedRLEnvCfg ),其中包含任务各组件的配置。根据配置,设置场景并初始化任务。之后,通过环境,按顺序调用所有管理器执行必要的操作。

对于他们自己的任务,我们期望用户主要定义任务配置类,并使用现有的 envs.ManagerBasedRLEnv 类进行任务实现。任务配置类应继承自基类 envs.ManagerBasedRLEnvCfg ,并包含分配给不同组件的各个配置类的变量(如 ObservationCfgRewardCfg )。

使用管理器样式为Cartpole任务定义奖励函数的示例

以下类是Cartpole环境配置类的一部分。 RewardsCfg 类定义了组成奖励函数的单个项。每个奖励项由其函数实现、权重和传递给函数的其他参数来定义。用户可以定义多个奖励项和它们的权重以在奖励函数中使用。

@configclass
class RewardsCfg:
    """Reward terms for the MDP."""

    # (1) Constant running reward
    alive = RewTerm(func=mdp.is_alive, weight=1.0)
    # (2) Failure penalty
    terminating = RewTerm(func=mdp.is_terminated, weight=-2.0)
    # (3) Primary task: keep pole upright
    pole_pos = RewTerm(
        func=mdp.joint_pos_target_l2,
        weight=-1.0,
        params={"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"]), "target": 0.0},
    )
    # (4) Shaping tasks: lower cart velocity
    cart_vel = RewTerm(
        func=mdp.joint_vel_l1,
        weight=-0.01,
        params={"asset_cfg": SceneEntityCfg("robot", joint_names=["slider_to_cart"])},
    )
    # (5) Shaping tasks: lower pole angular velocity
    pole_vel = RewTerm(
        func=mdp.joint_vel_l1,
        weight=-0.005,
        params={"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"])},
    )

通过这种方法,可以轻松地通过切换一些组件来改变任务的实现方式,同时保持代码的其余部分不变。在原型环境和试验不同配置时,此灵活性非常有用。它还允许与他人轻松合作实施环境,因为贡献者可以选择使用不同的配置组合来规定自己的任务规格。

参见

我们为使用基于管理器的工作流设置环境提供了更详细的教程: 创建基于管理器的强化学习环境

直接环境#

直接样式的环境与传统的环境实现更加接近,其中一个单独的脚本直接实现奖励函数、观察函数、重置和环境的所有其他组件。这种方法不需要管理器类。相反,用户可以通过基类 envs.DirectRLEnv 的API完全自由地实现他们的任务。对于从 IsaacGymEnvsOmniIsaacGymEnvs 框架迁移的用户,这种工作流可能更为熟悉。

在使用直接样式实现的环境时,我们期望用户定义一个实现整个环境的单个类。任务类应继承自基类 envs.DirectRLEnv ,应该有相应的配置类,继承自 envs.DirectRLEnvCfg 。任务类负责设置场景,处理操作,计算奖励、观察、重置、终止信号。

使用直接样式为Cartpole任务定义奖励函数的示例

以下函数是Cartpole环境类的一部分,负责计算奖励。

def _get_rewards(self) -> torch.Tensor:
    total_reward = compute_rewards(
        self.cfg.rew_scale_alive,
        self.cfg.rew_scale_terminated,
        self.cfg.rew_scale_pole_pos,
        self.cfg.rew_scale_cart_vel,
        self.cfg.rew_scale_pole_vel,
        self.joint_pos[:, self._pole_dof_idx[0]],
        self.joint_vel[:, self._pole_dof_idx[0]],
        self.joint_pos[:, self._cart_dof_idx[0]],
        self.joint_vel[:, self._cart_dof_idx[0]],
        self.reset_terminated,
    )
    return total_reward

它调用了 compute_rewards() 函数,该函数是为了性能优势而Torch JIT编译的

@torch.jit.script
def compute_rewards(
    rew_scale_alive: float,
    rew_scale_terminated: float,
    rew_scale_pole_pos: float,
    rew_scale_cart_vel: float,
    rew_scale_pole_vel: float,
    pole_pos: torch.Tensor,
    pole_vel: torch.Tensor,
    cart_pos: torch.Tensor,
    cart_vel: torch.Tensor,
    reset_terminated: torch.Tensor,
):
    rew_alive = rew_scale_alive * (1.0 - reset_terminated.float())
    rew_termination = rew_scale_terminated * reset_terminated.float()
    rew_pole_pos = rew_scale_pole_pos * torch.sum(torch.square(pole_pos).unsqueeze(dim=1), dim=-1)
    rew_cart_vel = rew_scale_cart_vel * torch.sum(torch.abs(cart_vel).unsqueeze(dim=1), dim=-1)
    rew_pole_vel = rew_scale_pole_vel * torch.sum(torch.abs(pole_vel).unsqueeze(dim=1), dim=-1)
    total_reward = rew_alive + rew_termination + rew_pole_pos + rew_cart_vel + rew_pole_vel
    return total_reward

这种方法在环境实现中提供了更多的透明度,因为逻辑是在任务类中而不是通过使用管理器进行抽象来定义的。在实现难以分解为单独组件的复杂逻辑时,这可能是有益的。此外,直接样式的实现可能为环境带来更好的性能优势,因为它允许使用优化的框架(如 PyTorch JITWarp )实现大量逻辑。这在需要优化环境中的每个操作时可能非常有价值。

参见

我们为使用直接工作流设置RL环境提供了更详细的教程: 创建直接工作流RL环境