Nvidia Isaac Lab 8 - 在 Isaac Lab 中,训练第二个机器人 - 6. 自定义奖励函数
本节将添加用于决定策略奖励的底层数学函数。第一种方法将结合两种形式的奖励,用于衡量位置误差(即机器人距离目标位置有多远)。
1. 定义自定义奖励函数
之前的奖励管理器配置文件引用若干尚不存在的 MDP 函数。下面定义这些函数。如前所述,为清晰起见,将这些函数放在 mdp 文件夹中。
- 打开如下 Python 文件:
source/Reach/Reach/tasks/manager_based/reach/mdp/rewards.py
- 清空文件内容,将其替换为以下导入语句。
# Copyright (c) 2022-2025, The Isaac Lab Project Developers. # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause from __future__ import annotations import torch from typing import TYPE_CHECKING from isaaclab.managers import SceneEntityCfg from isaaclab.utils.math import combine_frame_transforms from isaaclab.assets import RigidObject from isaaclab.managers import SceneEntityCfg from isaaclab.utils.math import combine_frame_transforms, quat_error_magnitude, quat_mul if TYPE_CHECKING: from isaaclab.envs import ManagerBasedRLEnv
掌握 PyTorch、线性代数和三角学对于强化学习学习之旅至关重要。
2. 位置命令误差
该函数计算期望位置(来自命令)与资产本体当前位置(在世界坐标系下)之间的位置误差。通过期望位置与当前位置之差的 L2 范数计算位置误差。
什么是 L2 范数?
L2 范数,也称为欧几里得范数,是衡量空间中向量长度或大小的一种方式。
该函数如何与管理器及场景交互?
环境对象被传入 - 其中包含 Stage 上的所有机器人,因此涉及 PyTorch 的张量运算。这正是大规模并行训练特性的体现!
在前面的代码中,奖励管理器的某个奖励项引用该函数。简而言之,这里定义如何计算该奖励项,最终各项奖励被累加成最终的奖励值。
请将此代码添加到 Reach/tasks/manager_based/reach/mdp/rewards.py 文件中。
def position_command_error(env: ManagerBasedRLEnv, command_name: str, asset_cfg: SceneEntityCfg) -> torch.Tensor:
"""Penalize tracking of the position error using L2-norm.
The function computes the position error between the desired position (from the command) and the
current position of the asset's body (in world frame). The position error is computed as the L2-norm
of the difference between the desired and current positions.
"""
# extract the asset (to enable type hinting)
asset: RigidObject = env.scene[asset_cfg.name]
command = env.command_manager.get_command(command_name)
# obtain the desired and current positions
des_pos_b = command[:, :3]
des_pos_w, _ = combine_frame_transforms(asset.data.root_state_w[:, :3], asset.data.root_state_w[:, 3:7], des_pos_b)
curr_pos_w = asset.data.body_state_w[:, asset_cfg.body_ids[0], :3] # type: ignore
return torch.norm(curr_pos_w - des_pos_w, dim=1)3. 位置命令误差 Tanh
该函数计算期望位置(来自命令)与资产本体当前位置(在世界坐标系下)之间的位置误差,并且将其通过 tanh 核函数进行映射。
为什么需要第二个位置命令奖励项?
当位置误差趋近于零时,与线性误差项相比,tanh 函数产生更大的梯度。这将放大对微小错误的权重更新,从而加速向目标收敛。同时,也将输出值限制在 −1 到 1 之间。
请将此代码添加到 Reach/tasks/manager_based/reach/mdp/rewards.py 文件中。
def position_command_error_tanh(
env: ManagerBasedRLEnv, std: float, command_name: str, asset_cfg: SceneEntityCfg
) -> torch.Tensor:
"""Reward tracking of the position using the tanh kernel.
The function computes the position error between the desired position (from the command) and the
current position of the asset's body (in world frame) and maps it with a tanh kernel.
"""
# extract the asset (to enable type hinting)
asset: RigidObject = env.scene[asset_cfg.name]
command = env.command_manager.get_command(command_name)
# obtain the desired and current positions
des_pos_b = command[:, :3]
des_pos_w, _ = combine_frame_transforms(asset.data.root_state_w[:, :3], asset.data.root_state_w[:, 3:7], des_pos_b)
curr_pos_w = asset.data.body_state_w[:, asset_cfg.body_ids[0], :3] # type: ignore
distance = torch.norm(curr_pos_w - des_pos_w, dim=1)
return 1 - torch.tanh(distance / std)4. 完整的 Reward 文件
# Copyright (c) 2022-2025, The Isaac Lab Project Developers.
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
from __future__ import annotations
import torch
from typing import TYPE_CHECKING
from isaaclab.managers import SceneEntityCfg
from isaaclab.utils.math import combine_frame_transforms
from isaaclab.assets import RigidObject
from isaaclab.managers import SceneEntityCfg
from isaaclab.utils.math import combine_frame_transforms, quat_error_magnitude, quat_mul
if TYPE_CHECKING:
from isaaclab.envs import ManagerBasedRLEnv
def position_command_error(env: ManagerBasedRLEnv, command_name: str, asset_cfg: SceneEntityCfg) -> torch.Tensor:
"""Penalize tracking of the position error using L2-norm.
The function computes the position error between the desired position (from the command) and the
current position of the asset's body (in world frame). The position error is computed as the L2-norm
of the difference between the desired and current positions.
"""
# extract the asset (to enable type hinting)
asset: RigidObject = env.scene[asset_cfg.name]
command = env.command_manager.get_command(command_name)
# obtain the desired and current positions
des_pos_b = command[:, :3]
des_pos_w, _ = combine_frame_transforms(asset.data.root_state_w[:, :3], asset.data.root_state_w[:, 3:7], des_pos_b)
curr_pos_w = asset.data.body_state_w[:, asset_cfg.body_ids[0], :3] # type: ignore
return torch.norm(curr_pos_w - des_pos_w, dim=1)
def position_command_error_tanh(
env: ManagerBasedRLEnv, std: float, command_name: str, asset_cfg: SceneEntityCfg
) -> torch.Tensor:
"""Reward tracking of the position using the tanh kernel.
The function computes the position error between the desired position (from the command) and the
current position of the asset's body (in world frame) and maps it with a tanh kernel.
"""
# extract the asset (to enable type hinting)
asset: RigidObject = env.scene[asset_cfg.name]
command = env.command_manager.get_command(command_name)
# obtain the desired and current positions
des_pos_b = command[:, :3]
des_pos_w, _ = combine_frame_transforms(asset.data.root_state_w[:, :3], asset.data.root_state_w[:, 3:7], des_pos_b)
curr_pos_w = asset.data.body_state_w[:, asset_cfg.body_ids[0], :3] # type: ignore
distance = torch.norm(curr_pos_w - des_pos_w, dim=1)
return 1 - torch.tanh(distance / std)5. 配置超参数
用于 PPO 的设置和超参数
最后,替换 source/Reach/Reach/tasks/manager_based/reach/agents/skrl_ppo_cfg.yaml 中的代码。
该配置文件用于定义使用 SKRL 库中的近端策略优化(PPO)算法训练强化学习智能体时的设置和超参数。
该文件对于定制 PPO 在 Isaac Lab 中的运行方式至关重要。虽然本节不详细讨论这些配置,但下面的文件中提供相关链接,可供进一步学习。
了解 PPO 背后的直观原理。
seed: 42
# Models are instantiated using skrl's model instantiator utility
# https://skrl.readthedocs.io/en/latest/api/utils/model_instantiators.html
models:
separate: False
policy: # see gaussian_model parameters
class: GaussianMixin
clip_actions: False
clip_log_std: True
min_log_std: -20.0
max_log_std: 2.0
initial_log_std: 0.0
network:
- name: net
input: STATES
layers: [64, 64]
activations: elu
output: ACTIONS
value: # see deterministic_model parameters
class: DeterministicMixin
clip_actions: False
network:
- name: net
input: STATES
layers: [64, 64]
activations: elu
output: ONE
# Rollout memory
# https://skrl.readthedocs.io/en/latest/api/memories/random.html
memory:
class: RandomMemory
memory_size: -1 # automatically determined (same as agent:rollouts)
# PPO agent configuration (field names are from PPO_DEFAULT_CONFIG)
# https://skrl.readthedocs.io/en/latest/api/agents/ppo.html
agent:
class: PPO
rollouts: 24
learning_epochs: 5
mini_batches: 4
discount_factor: 0.99
lambda: 0.95
learning_rate: 1.0e-03
learning_rate_scheduler: KLAdaptiveLR
learning_rate_scheduler_kwargs:
kl_threshold: 0.01
state_preprocessor: RunningStandardScaler
state_preprocessor_kwargs: null
value_preprocessor: RunningStandardScaler
value_preprocessor_kwargs: null
random_timesteps: 0
learning_starts: 0
grad_norm_clip: 1.0
ratio_clip: 0.2
value_clip: 0.2
clip_predicted_values: True
entropy_loss_scale: 0.01
value_loss_scale: 1.0
kl_threshold: 0.0
rewards_shaper_scale: 1.0
time_limit_bootstrap: False
# logging and checkpoint
experiment:
directory: "reach_ur10"
experiment_name: ""
write_interval: auto
checkpoint_interval: auto
# Sequential trainer
# https://skrl.readthedocs.io/en/latest/api/trainers/sequential.html
trainer:
class: SequentialTrainer
timesteps: 24000
environment_info: log