跳转至

第 3 章 环境抽象与任务配置

一个强化学习任务,最终要落到"环境"这个对象上:它每一步吃什么观测、吐什么动作、怎么算奖励、何时终止、随机化什么。Isaac Lab 提供两条写环境的路线——继承 DirectRLEnv 自己写方法,或用 ManagerBasedRLEnv 声明一组 term 配置。本章讲清两条路线的边界与选用判据,展开后者"五大 term 体系"的组织方式,落到动作空间与执行频率的关系,最后用一个 Direct 与一个 Manager-Based 的最小任务把结构走通。

1. 两条环境抽象路线

两条路线都实现 Gymnasium 风格的 env 接口(reset() / step() 返回 obs、reward、terminated、truncated、info),差别只在"逻辑写在哪":

路线 基类 任务逻辑的载体 适用
Direct DirectRLEnv / DirectRLEnvCfg 子类里重写 _pre_physics_step、_apply_action、_get_observations、_get_rewards、_get_dones 等方法 单机器人、逻辑直白、想一眼看到全部计算
Manager-Based ManagerBasedRLEnv / ManagerBasedRLEnvCfg 一组声明式 term 配置,交给各个 manager 调度 多实体、多观测组、奖励/事件项多,需可组合与复用

选用判据可粗化为一句:任务结构复杂、需要拼装大量观测/奖励/随机化项并跨任务复用时,走 Manager-Based;任务紧凑、逻辑就是几行、要的是可读的"一个类看到底"时,走 Direct。 内置任务两条路线都有——Isaac-Cartpole-Direct-v0 是 Direct 的样板,Isaac-Lift-*、Isaac-Velocity-* 是 Manager-Based 的样板。

Direct 路线的骨架(方法签名,运行环境 Isaac Lab 3.0.0):

class CartpoleEnv(DirectRLEnv):
    cfg: CartpoleEnvCfg

    def _setup_scene(self):
        # 建机器人、加到场景、克隆环境、配置 articulation root
        ...

    def _pre_physics_step(self, actions: torch.Tensor):
        # 每仿真步一次:把策略动作转成要下发的目标(在 decimation 前)
        self.actions = self.cfg.action_scale * actions

    def _apply_action(self):
        # 每策略步一次:把目标写入执行器
        self._robot.set_joint_position_target(self.actions)

    def _get_observations(self) -> dict:
        joint_pos = self._robot.data.joint_pos
        return {"policy": torch.cat([joint_pos, self._robot.data.joint_vel], dim=1)}

    def _get_rewards(self) -> torch.Tensor: ...
    def _get_dones(self) -> tuple[torch.Tensor, torch.Tensor]: ...

_get_dones 返回 (terminated, time_out) 两个布尔张量,分别对应"真终止"与"超时截断"——这也是 Manager-Based 里 termination term 用 time_out=True 标记的语义。

判据:结构复杂走 Manager-Based,紧凑逻辑走 Direct

多实体、多观测组、奖励与随机化项需要拼装复用时用 Manager-Based;任务就是几行、要一个类看到底时用 Direct。

2. 五大 term 体系

Manager-Based 环境把任务逻辑拆进若干 manager,每个 manager 吃一组 term。核心五类是 observation / action / reward / termination / event,另有 command(指令生成)、curriculum(课程)、recorder(记录)三个扩展 manager。

一个 manager 的配置就是一个 @configclass 容器,容器里每个属性是一个 term(下面的 ObsGroup/ObsTerm/RewTerm/DoneTerm/EventTerm 是任务代码对 ObservationGroupCfg/ObservationTermCfg/RewardTermCfg/TerminationTermCfg/EventTermCfg 的惯用别名,经 from isaaclab.managers import ... as ... 引入):

@configclass
class ObservationsCfg:
    @configclass
    class PolicyCfg(ObsGroup):                    # 观测分组
        joint_pos = ObsTerm(func=mdp.joint_pos_rel)
        joint_vel = ObsTerm(func=mdp.joint_vel_rel)
        last_action = ObsTerm(func=mdp.last_action)
    policy: PolicyCfg = PolicyCfg()              # 交给策略的组
    critic: CriticCfg = ...                       # (可选)只给价值网络用的特权组


@configclass
class ActionsCfg:
    joint_pos = mdp.actions.JointPositionActionCfg(   # 动作 term 直接是 ActionCfg
        asset_name="robot", joint_names=[".*"], scale=0.25, use_default_offset=True
    )


@configclass
class RewardsCfg:
    alive = RewTerm(func=mdp.is_alive, weight=1.0)
    joint_torques = RewTerm(func=mdp.joint_torques_l2, weight=-1e-4)   # 惩罚项权重取负


@configclass
class TerminationsCfg:
    time_out = DoneTerm(func=mdp.time_out, time_out=True)
    tipped = DoneTerm(func=mdp.bad_orientation, params={"limit_angle": 0.6})  # 真终止(姿态超限)


@configclass
class EventCfg:
    physics = EventTermCfg(func=mdp.randomize_rigid_body_mass, mode="startup")

各 term 的公共约定:

  • 观测按组聚合:policy 组进策略网络,critic 组可携带特权信息(真值质量、摩擦等)只给训练期的价值网络,部署时不占用观测维度。这是 Manager-Based 相较 Direct 的一个结构性便利。
  • 奖励 = weight × func 返回值:约定奖励函数返回每环境标量,weight 为负即惩罚;求和由 reward manager 完成。
  • 终止分两类:time_out=True 标记"超时截断"(价值需要 bootstrap),否则是"真终止"(回合结束,不 bootstrap)。
  • event 的 mode:"startup" 只在初始化跑一次,"reset" 在每次环境重置跑,"interval" 按固定周期跑——域随机化就落在这里(第 6 章展开)。

观测噪声不是独立 manager,而是挂在 ObsTerm 的噪声配置字段(UniformNoiseCfg/GaussianNoiseCfg)与 modifiers(如历史堆叠 HistoryBufferCfg、缩放)上,因此可逐项开关——训练期加噪、评估期把整组噪声置零即可对照。

Manager-Based 环境把任务逻辑拆进 manager,每个 manager 吃一组 term:

flowchart LR
    env["ManagerBasedRLEnv"]
    env --> om["observation manager<br/>观测项 → policy 组"]
    env --> am["action manager<br/>动作项 → 关节目标"]
    env --> rm["reward manager<br/>奖励项求和"]
    env --> tm["termination manager<br/>真终止 / 超时"]
    env --> em["event manager<br/>reset 与随机化"]
    env -.-> cmd["command manager"]
    env -.-> cur["curriculum manager"]
    env -.-> rec["recorder manager"]

3. 动作空间与执行频率

动作 term 决定策略输出如何映射到机器人。常见几类(均在 isaaclab.envs.mdp.actions):

动作配置 语义 输出维度
JointPositionActionCfg 关节位置目标(经执行器 PD 跟踪) 关节数
JointVelocityActionCfg / JointEffortActionCfg 关节速度 / 力矩直发 关节数
TaskSpaceActionCfg 末端位姿增量,走 IK 6 或 7
NonHolonomicActionCfg 非完整轮式(左右轮速度) 2

关节位置动作有两个常用缩放项:scale 把网络输出的 [-1,1] 乘成关节角增量,use_default_offset=True 让目标叠加在配置的默认关节角上(即"相对目标"而非"绝对目标")。另有一组按关节行程重缩放的变体(mdp.actions 下的 joint_actions_to_limits 模块),省去自己 clip。

执行频率由两个参数配比决定,都写在场景配置里:

  • sim.dt:物理步长(如 1/60 或 1/120)。
  • decimation:每 sim.dt 步一次控制更新、多少个物理步才更新一次动作。例如 decimation=10 表示动作每 10 个物理步刷新一次,策略有效频率 = 1 / (decimation · sim.dt)。

这个比值是第 4 章"仿真步长与策略频率之比"的配置入口;动作平滑与观测/执行延迟的随机化则归第 6 章(域随机化)与第 9 章(sim-to-real)。

坑:decimation 改的是控制频率

策略频率 = 物理频率 / decimation;调它等于改控制周期,观测与奖励的时间含义随之变化,不能只当作性能开关。

4. 最小任务示例

两个内置任务把上面两条路线各钉一遍:

Direct:Isaac-Cartpole-Direct-v0。一个 DirectRLEnvCfg 声明场景与物理,一个 CartpoleEnv(DirectRLEnv) 用方法体重写观测/奖励/终止。第 1 章的自检正是跑它。

Manager-Based:Isaac-Lift-Cube-Franka-v0 / Isaac-Velocity-*。任务入口 gym.register 把环境配置与各 RL 库的配置一起登记(详见第 5 章):

gym.register(
    id="Isaac-Cartpole-Direct-v0",
    entry_point="...cartpole_direct_env:CartpoleEnv",
    kwargs={"env_cfg_entry_point": "...cartpole_direct_env_cfg:CartpoleEnvCfg",
            "rsl_rl_cfg_entry_point": "...rsl_rl_ppo_cfg:CartpoleDirectPPORunnerCfg"},
)

lift 场景配置里的 SceneCfg(num_envs=4096, env_spacing=3, replicate_physics=True) 直接体现第 2 章的复用线:一套 term 配置模板 + num_envs 克隆出 4096 个并行环境。replicate_physics=True 让物理状态张量连续排布以利 GPU 访存(第 4 章展开)。

5. 要点

  • 两条路线都满足 Gymnasium 接口;Direct 用方法体重写、适合紧凑任务,Manager-Based 用声明式 term、适合多实体/可组合任务,选型按"逻辑写在方法里还是配置里"决策。
  • 五大 term 体系 = observation / action / reward / termination / event 五个 manager(外加 command / curriculum / recorder);每个 term 是 func + params + 组内 weight。
  • 观测按 policy / critic 分组,critic 可带只供训练的特权信息;噪声挂在 ObsTerm.noise 与 modifiers 上,逐项可关。
  • 终止区分 time_out=True(超时截断,价值需 bootstrap)与真终止;奖励约定"返回标量、weight 求和、负权重即惩罚"。
  • 动作空间分关节位置/速度/力矩、任务空间、非完整轮式;scale 与 use_default_offset 决定"相对目标"语义。
  • 执行频率由 sim.dt 与 decimation 配比决定,策略频率 = 1/(decimation·sim.dt);这是连接建模与训练性能的关键旋钮。

参考文献与延伸阅读

  • Isaac Lab. 文档入口. 文档
  • Gymnasium. 环境接口文档. 文档
  • Isaac Sim. 文档入口. 文档