Nvidia Isaac Lab 8 - 在 Isaac Lab 中,训练第二个机器人 - 4. 配置管理器

回到马尔可夫决策过程框架,将其应用到当前的问题上。


1. 检查代码

打开文件 /Reach/tasks/manager_based/reach/reach_env_cfg.py

在此为任务配置各个管理器。首先,搭建包括机器人、地面和光源的环境。

将用到两类函数:

  1. 内建 MDP 函数
    • Isaac Lab 自带,涵盖通用参数,比如 mdp.joint_pos_rel
    • 如需了解用于创建观测项的内置 MDP 函数,请参阅此文档
  1. 自定义函数
    • 在 Isaac Lab 管理器工作流中,常见做法是创建 mdp 文件夹存放自定义函数。

下面先实现定义管理器的主类,然后填充自定义 MDP 函数。


2. 动作

动作定义 Agent 能做什么。在本场景中,即移动机器人的全部 6 个旋转关节。本示例将利用内置的 JointPositionActionCfg 类。关节名称取自 USD 文件中的机器人关节。无需为这些关节提供 Prim 路径,它们将被自动定位。

提示:也可以使用正则表达式定义关节名称。如果机器人的关节命名方式类似,例如 joint_1joint_2 等,只需使用 joint_.* 即可全部选中。此处为清晰起见,使用显式名称。

替换 reach_env_cfg.py 中的该类:

@configclass
class ActionsCfg:
    """Action specifications for the MDP."""

    arm_action: ActionTerm = mdp.JointPositionActionCfg(
        asset_name="robot", 
        joint_names=["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"], 
        scale=1, 
        use_default_offset=True, 
        debug_vis=True
    )

3. 命令

命令与动作很相似,也确实相关。命令是更高层次的任务说明,描述的是要实现什么,而不是如何实现(动作)。命令是目标,动作是实现目标的手段。

向 reach_env_cfg.py 中添加该类:

@configclass
class CommandsCfg:
    """Command terms for the MDP."""

    ee_pose = mdp.UniformPoseCommandCfg(
        asset_name="robot",
        body_name="ee_link", # This is the body in the USD file
        resampling_time_range=(4.0, 4.0),
        debug_vis=True,
# These are essentially ranges of poses that can be commanded for the end of the robot during training
        ranges=mdp.UniformPoseCommandCfg.Ranges(
            pos_x=(0.35, 0.65),
            pos_y=(-0.2, 0.2),
            pos_z=(0.15, 0.5),
            roll=(0.0, 0.0),
            pitch=(math.pi / 2, math.pi / 2),
            yaw=(-3.14, 3.14),
        ),
    )

4. 观测

观测是从环境中采集的测量数据,用于评估任务。在本例中,包括:

利用观测,可以评估运动是否平滑,以及机器人是否接近其目标位置。

观测可以分组,在本例中,仅保留与策略相关的观测。

最后,self.enable_corruption = True 允许为观测添加噪声“扰动”。下面的代码将噪声作为参数添加到 joint_pos 和 joint_vel 这两个观测项中。噪声有助于模拟真实世界的传感器噪声,增强策略的鲁棒性,防止过拟合纯净数据。

替换 reach_env_cfg.py 中的该类:

@configclass
class ObservationsCfg:
    """Observation specifications for the MDP."""

    @configclass
    class PolicyCfg(ObsGroup):
        """Observations for policy group."""

        # observation terms (order preserved)
        joint_pos = ObsTerm(func=mdp.joint_pos_rel, noise=Unoise(n_min=-0.01, n_max=0.01))
        joint_vel = ObsTerm(func=mdp.joint_vel_rel, noise=Unoise(n_min=-0.01, n_max=0.01))
        pose_command = ObsTerm(func=mdp.generated_commands, params={"command_name": "ee_pose"})
        actions = ObsTerm(func=mdp.last_action)

        def __post_init__(self):
            self.enable_corruption = True
            self.concatenate_terms = True

    # observation groups
    policy: PolicyCfg = PolicyCfg()

5. 终止条件

训练回合结束的定义是什么?是任务成功,还是已知某些需要提前中止以避免浪费时间的情形?此处使用简单的超时机制,在达到一定时间后停止任务。该时长的具体数值将由后续设置的回合长度提供。

替换 reach_env_cfg.py 中的该类:

@configclass
class TerminationsCfg:
    """Termination terms for the MDP."""

    time_out = DoneTerm(func=mdp.time_out, time_out=True)

5.1. 思考

如果任务更复杂,那么使用哪种终止条件?

示例:将特定位姿,或与其他物体发生碰撞,或速度过高视为终止条件。


6. 事件

本项目只处理“重置”事件。重置事件发生在训练回合结束时。通过配置 EventTerm,调用函数以一定的随机性重置关节。

本例使用内置的 mdp.reset_joints_by_scale 函数,该函数通过按给定范围缩放默认位置和速度的方式,重置机器人关节。

替换 reach_env_cfg.py 中的该类:

@configclass
class EventCfg:
    """Configuration for events."""

    reset_robot_joints = EventTerm(
        func=mdp.reset_joints_by_scale,
        mode="reset",
        params={
            "position_range": (0.75, 1.25),
            "velocity_range": (0.0, 0.0),
        },
    )

7. 奖励

奖励是最具挑战的关键方面之一。该如何定义奖励函数呢?本示例使用多个奖励函数帮助完成该任务。

该类包含很多代码,下面逐一拆解:

替换 reach_env_cfg.py 中的该类:

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

    # task terms
    end_effector_position_tracking = RewTerm(
        func=mdp.position_command_error,
        weight=-0.2,
        params={"asset_cfg": SceneEntityCfg("robot", body_names=["ee_link"]), "command_name": "ee_pose"},
    )
    end_effector_position_tracking_fine_grained = RewTerm(
        func=mdp.position_command_error_tanh,
        weight=0.1,
        params={"asset_cfg": SceneEntityCfg("robot", body_names=["ee_link"]), "std": 0.1, "command_name": "ee_pose"},
    )

    # action penalty
    action_rate = RewTerm(func=mdp.action_rate_l2, weight=-0.0001)
    joint_vel = RewTerm(
        func=mdp.joint_vel_l2,
        weight=-0.0001,
        params={"asset_cfg": SceneEntityCfg("robot")},
    )

注意,其中一些函数,比如 mdp.orientation_command_error ,不是内置函数,因此需要自定义这些函数。

另外请记住,Isaac Lab 负责根据配置数据,计算给定状态下的奖励。


8. 课程

课程(Curriculum)提供进一步配置更详细训练指令的方法。

向 reach_env_cfg.py 中添加该类:

@configclass
class CurriculumCfg:
    """Curriculum terms for the MDP."""

    action_rate = CurrTerm(
        func=mdp.modify_reward_weight, params={"term_name": "action_rate", "weight": -0.005, "num_steps": 4500}
    )

    joint_vel = CurrTerm(
        func=mdp.modify_reward_weight, params={"term_name": "joint_vel", "weight": -0.001, "num_steps": 4500}
    )