Nvidia Isaac Lab 8 - 在 Isaac Lab 中,训练第二个机器人 - 4. 配置管理器
回到马尔可夫决策过程框架,将其应用到当前的问题上。
1. 检查代码
打开文件 /Reach/tasks/manager_based/reach/reach_env_cfg.py。
在此为任务配置各个管理器。首先,搭建包括机器人、地面和光源的环境。
将用到两类函数:
- 内建 MDP 函数
- Isaac Lab 自带,涵盖通用参数,比如
mdp.joint_pos_rel。
- 如需了解用于创建观测项的内置 MDP 函数,请参阅此文档。
- Isaac Lab 自带,涵盖通用参数,比如
- 自定义函数
- 在 Isaac Lab 管理器工作流中,常见做法是创建
mdp文件夹存放自定义函数。
- 在 Isaac Lab 管理器工作流中,常见做法是创建
下面先实现定义管理器的主类,然后填充自定义 MDP 函数。
2. 动作
动作定义 Agent 能做什么。在本场景中,即移动机器人的全部 6 个旋转关节。本示例将利用内置的 JointPositionActionCfg 类。关节名称取自 USD 文件中的机器人关节。无需为这些关节提供 Prim 路径,它们将被自动定位。
提示:也可以使用正则表达式定义关节名称。如果机器人的关节命名方式类似,例如 joint_1、joint_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}
)