Source code for torchrl.envs.libs.isaac_lab
# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import annotations
import torch
from torchrl.envs.libs.gym import GymWrapper
[docs]class IsaacLabWrapper(GymWrapper):
"""A wrapper for IsaacLab environments.
Args:
env (scripts_isaaclab.envs.ManagerBasedRLEnv or equivalent): the environment instance to wrap.
categorical_action_encoding (bool, optional): if ``True``, categorical
specs will be converted to the TorchRL equivalent (:class:`torchrl.data.Categorical`),
otherwise a one-hot encoding will be used (:class:`torchrl.data.OneHot`).
Defaults to ``False``.
allow_done_after_reset (bool, optional): if ``True``, it is tolerated
for envs to be ``done`` just after :meth:`reset` is called.
Defaults to ``False``.
For other arguments, see the :class:`torchrl.envs.GymWrapper` documentation.
Refer to `the Isaac Lab doc for installation instructions <https://isaac-sim.github.io/IsaacLab/main/source/setup/installation/pip_installation.html>`_.
Example:
>>> # This code block ensures that the Isaac app is started in headless mode
>>> from scripts_isaaclab.app import AppLauncher
>>> import argparse
>>> parser = argparse.ArgumentParser(description="Train an RL agent with TorchRL.")
>>> AppLauncher.add_app_launcher_args(parser)
>>> args_cli, hydra_args = parser.parse_known_args(["--headless"])
>>> app_launcher = AppLauncher(args_cli)
>>> # Imports and env
>>> import gymnasium as gym
>>> import isaaclab_tasks # noqa: F401
>>> from isaaclab_tasks.manager_based.classic.ant.ant_env_cfg import AntEnvCfg
>>> from torchrl.envs.libs.isaac_lab import IsaacLabWrapper
>>> env = gym.make("Isaac-Ant-v0", cfg=AntEnvCfg())
>>> env = IsaacLabWrapper(env)
"""
def __init__(
self,
env: isaaclab.envs.ManagerBasedRLEnv, # noqa: F821
*,
categorical_action_encoding: bool = False,
allow_done_after_reset: bool = True,
convert_actions_to_numpy: bool = False,
device: torch.device | None = None,
**kwargs,
):
if device is None:
device = torch.device("cuda:0")
super().__init__(
env,
device=device,
categorical_action_encoding=categorical_action_encoding,
allow_done_after_reset=allow_done_after_reset,
convert_actions_to_numpy=convert_actions_to_numpy,
**kwargs,
)
def seed(self, seed: int | None):
self._set_seed(seed)
def _output_transform(self, step_outputs_tuple): # noqa: F811
# IsaacLab will modify the `terminated` and `truncated` tensors
# in-place. We clone them here to make sure data doesn't inadvertently get modified.
# The variable naming follows torchrl's convention here.
observations, reward, terminated, truncated, info = step_outputs_tuple
done = terminated | truncated
reward = reward.unsqueeze(-1) # to get to (num_envs, 1)
return (
observations,
reward,
terminated.clone(),
truncated.clone(),
done.clone(),
info,
)