注册环境#

在上一个教程中,我们学习了如何创建自定义的cartpole环境。我们通过导入环境类和配置类的方式手动创建了环境的实例。

上一个教程中的环境创建
    # create environment configuration
    env_cfg = CartpoleEnvCfg()
    env_cfg.scene.num_envs = args_cli.num_envs
    # setup RL environment
    env = ManagerBasedRLEnv(cfg=env_cfg)

虽然直接,但这种方法不够可扩展,因为我们有大量的环境套件。在本教程中,我们将展示如何使用 gymnasium.register() 方法将环境注册到 gymnasium 注册表中。这使我们可以通过 gymnasium.make() 函数创建环境。

本教程中的环境创建
from omni.isaac.lab_tasks.utils import parse_env_cfg


def main():
    """Random actions agent with Isaac Lab environment."""
    # create environment configuration
    env_cfg = parse_env_cfg(
        args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
    )
    # create environment
    env = gym.make(args_cli.task, cfg=env_cfg)

代码#

本教程对应 source/standalone/environments 目录中的 random_agent.py 脚本。

random_agent.py的代码
 1# Copyright (c) 2022-2024, The Isaac Lab Project Developers.
 2# All rights reserved.
 3#
 4# SPDX-License-Identifier: BSD-3-Clause
 5
 6"""Script to an environment with random action agent."""
 7
 8"""Launch Isaac Sim Simulator first."""
 9
10import argparse
11
12from omni.isaac.lab.app import AppLauncher
13
14# add argparse arguments
15parser = argparse.ArgumentParser(description="Random agent for Isaac Lab environments.")
16parser.add_argument(
17    "--disable_fabric", action="store_true", default=False, help="Disable fabric and use USD I/O operations."
18)
19parser.add_argument("--num_envs", type=int, default=None, help="Number of environments to simulate.")
20parser.add_argument("--task", type=str, default=None, help="Name of the task.")
21# append AppLauncher cli args
22AppLauncher.add_app_launcher_args(parser)
23# parse the arguments
24args_cli = parser.parse_args()
25
26# launch omniverse app
27app_launcher = AppLauncher(args_cli)
28simulation_app = app_launcher.app
29
30"""Rest everything follows."""
31
32import gymnasium as gym
33import torch
34
35import omni.isaac.lab_tasks  # noqa: F401
36from omni.isaac.lab_tasks.utils import parse_env_cfg
37
38
39def main():
40    """Random actions agent with Isaac Lab environment."""
41    # create environment configuration
42    env_cfg = parse_env_cfg(
43        args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
44    )
45    # create environment
46    env = gym.make(args_cli.task, cfg=env_cfg)
47
48    # print info (this is vectorized environment)
49    print(f"[INFO]: Gym observation space: {env.observation_space}")
50    print(f"[INFO]: Gym action space: {env.action_space}")
51    # reset environment
52    env.reset()
53    # simulate environment
54    while simulation_app.is_running():
55        # run everything in inference mode
56        with torch.inference_mode():
57            # sample actions from -1 to 1
58            actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1
59            # apply actions
60            env.step(actions)
61
62    # close the simulator
63    env.close()
64
65
66if __name__ == "__main__":
67    # run the main function
68    main()
69    # close sim app
70    simulation_app.close()

代码解释#

envs.ManagerBasedRLEnv 类继承自 gymnasium.Env 类以遵循标准接口。然而,与传统的Gym环境不同, envs.ManagerBasedRLEnv 实现了*向量化*环境。这意味着多个环境实例同时在同一进程中运行,并且所有数据都以批处理方式返回。

同样,envs.DirectRLEnv 类也从 gymnasium.Env 类继承以用于直接工作流程。对于 envs.DirectMARLEnv ,虽然它不是从Gymnasium继承的,但可以以相同的方式注册和创建。

使用gym注册表#

要注册一个环境,我们使用 gymnasium.register() 方法。此方法接收环境名称、环境类的入口点以及环境配置类的入口点。

备注

gymnasium 注册表是一个全局注册表。因此,确保环境名称是唯一的很重要。否则,在注册环境时注册表会抛出错误。

基于管理器的环境#

对于基于管理器的环境,以下显示了在 omni.isaac.lab_tasks.manager_based.classic.cartpole 子包中注册cartpole环境的调用:

import gymnasium as gym

from . import agents

##
# Register Gym environments.
##

gym.register(
    id="Isaac-Cartpole-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_env_cfg:CartpoleEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_cfg.yaml",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:CartpolePPORunnerCfg",
        "skrl_cfg_entry_point": f"{agents.__name__}:skrl_ppo_cfg.yaml",
        "sb3_cfg_entry_point": f"{agents.__name__}:sb3_ppo_cfg.yaml",
    },
)

gym.register(
    id="Isaac-Cartpole-RGB-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_camera_env_cfg:CartpoleRGBCameraEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_camera_ppo_cfg.yaml",
    },
)

gym.register(
    id="Isaac-Cartpole-Depth-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_camera_env_cfg:CartpoleDepthCameraEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_camera_ppo_cfg.yaml",
    },
)

gym.register(
    id="Isaac-Cartpole-RGB-ResNet18-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_camera_env_cfg:CartpoleResNet18CameraEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_feature_ppo_cfg.yaml",
    },
)

gym.register(
    id="Isaac-Cartpole-RGB-TheiaTiny-v0",
    entry_point="omni.isaac.lab.envs:ManagerBasedRLEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_camera_env_cfg:CartpoleTheiaTinyCameraEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_feature_ppo_cfg.yaml",
    },
)

id 参数是环境的名称。作为约定,我们将所有的环境名称以 Isaac- 作为前缀命名,以便在注册表中更容易搜索它们。环境的名称通常后跟任务名称,然后是机器人的名称。例如,对于ANYmal C在平坦地面上的足部运动,环境称为 Isaac-Velocity-Flat-Anymal-C-v0 。版本号 v<N> 通常用于指定相同环境的不同变体。否则,环境的名称会变得太长且难以阅读。

entry_point 参数是环境类的入口点。入口点是一个 <module>:<class> 形式的字符串。对于cartpole环境,入口点是 omni.isaac.lab.envs:ManagerBasedRLEnv 。入口点用于在创建环境实例时导入环境类。

env_cfg_entry_point 参数指定了环境的默认配置。默认配置使用 omni.isaac.lab_tasks.utils.parse_env_cfg() 函数加载。然后将其传递给 gymnasium.make() 函数以创建环境实例。配置入口点可以是YAML文件或Python配置类。

直接环境#

对于基于直接的环境,环境注册遵循类似的模式。与将环境的入口点注册为 ManagerBasedRLEnv 类不同,我们将环境的入口点注册为环境的实现类。此外,我们将环境名称添加后缀 -Direct 以区分其与基于管理器的环境。

例如,以下显示了在 omni.isaac.lab_tasks.direct.cartpole 子包中注册cartpole环境的调用:

import gymnasium as gym

from . import agents

##
# Register Gym environments.
##

gym.register(
    id="Isaac-Cartpole-Direct-v0",
    entry_point=f"{__name__}.cartpole_env:CartpoleEnv",
    disable_env_checker=True,
    kwargs={
        "env_cfg_entry_point": f"{__name__}.cartpole_env:CartpoleEnvCfg",
        "rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_cfg.yaml",
        "rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:CartpolePPORunnerCfg",
        "skrl_cfg_entry_point": f"{agents.__name__}:skrl_ppo_cfg.yaml",
        "sb3_cfg_entry_point": f"{agents.__name__}:sb3_ppo_cfg.yaml",
    },
)

gym.register(

创建环境#

要将所有 omni.isaac.lab_tasks 扩展提供的环境通知 gym 注册表,我们必须在脚本开头导入模块。这将执行 __init__.py 文件,该文件遍历所有子包并注册它们各自的环境。

import omni.isaac.lab_tasks  # noqa: F401

在本教程中,任务名称从命令行中读取。任务名称用于解析默认配置以及创建环境实例。此外,其他解析的命令行参数,如环境数量、模拟设备以及是否进行渲染,用于覆盖默认配置。

    # create environment configuration
    env_cfg = parse_env_cfg(
        args_cli.task, device=args_cli.device, num_envs=args_cli.num_envs, use_fabric=not args_cli.disable_fabric
    )
    # create environment
    env = gym.make(args_cli.task, cfg=env_cfg)

一旦创建环境,其余执行将遇到标准的重置和步进。

代码执行#

现在我们已经阅读了代码,让我们运行脚本并看看结果:

./isaaclab.sh -p source/standalone/environments/random_agent.py --task Isaac-Cartpole-v0 --num_envs 32

这将打开一个与 创建基于管理器的强化学习环境 教程类似的阶段。要停止模拟,您可以关闭窗口,或在终端中按 Ctrl+C

random_agent.py 的结果

此外,您还可以通过显式设置 --device 的值将模拟设备从 GPU 更改为 CPU:

./isaaclab.sh -p source/standalone/environments/random_agent.py --task Isaac-Cartpole-v0 --num_envs 32 --device cpu

使用 --device cpu 标志,模拟将在CPU上运行。这对于调试模拟很有用。但是,与在GPU上运行相比,模拟速度会慢得多。