Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
6e8a63e
Add success-rate metrics to the reorientation Direct tasks
hujc7 Jul 17, 2026
392e7d9
Add RSL-RL training and torch metrics to handover and camera Direct
hujc7 Jul 17, 2026
d4d1290
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 17, 2026
37f9ee6
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 17, 2026
b27cb24
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 17, 2026
df070af
Add success-rate support to the benchmark utilities and refresh docs
hujc7 Jul 17, 2026
a468ed0
Expand the changelog fragment with preset and deprecation entries
hujc7 Jul 17, 2026
bad1f69
Apply dexterous lump review updates to the handover layer
hujc7 Jul 18, 2026
21dbb17
Apply dexterous lump review updates to the Direct layer
hujc7 Jul 18, 2026
c5195e8
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 18, 2026
e07f9b9
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 18, 2026
553cd1c
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 18, 2026
0b20fad
Merge the rebuilt handover and camera manager base
hujc7 Jul 18, 2026
98867b3
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 18, 2026
b0296cc
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 18, 2026
f86d21c
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 18, 2026
27d79fe
Merge the rebuilt handover and camera manager base
hujc7 Jul 18, 2026
970a1cf
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 18, 2026
1b5c99c
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 18, 2026
372cc6b
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 18, 2026
920be95
Merge the rebuilt handover and camera manager base
hujc7 Jul 18, 2026
da863b8
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 18, 2026
e52279c
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 19, 2026
216eb96
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 19, 2026
4504125
Merge the rebuilt handover and camera manager base
hujc7 Jul 19, 2026
79f8750
Split identity into common modules and mark the Direct filenames
hujc7 Jul 20, 2026
dbe4bcd
Merge branch 'jichuanh/task-cleanup-dex-part03' into jichuanh/task-cl…
hujc7 Jul 20, 2026
957322a
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 20, 2026
01c9f4d
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 20, 2026
fcc7037
Adopt the common identity modules in the camera and handover tasks
hujc7 Jul 20, 2026
e1abb6b
Add manager-based counterparts for handover and camera tasks
hujc7 Jul 20, 2026
d2ee4fc
Merge the rebuilt handover and camera manager base
hujc7 Jul 20, 2026
7ea6b37
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
a3e8045
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
35b8408
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
36f2aa3
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
7fb203f
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
b97fabb
Merge remote-tracking branch 'upstream/develop' into jichuanh/task-cl…
hujc7 Jul 21, 2026
2d61229
Fix stale shadow-hand imports at this layer
hujc7 Jul 22, 2026
28daaf9
Fix stale shadow-hand imports at this layer
hujc7 Jul 22, 2026
a7f6a53
Merge branch 'jichuanh/task-cleanup-dex-part03' into jichuanh/task-cl…
hujc7 Jul 22, 2026
e7c9a9a
Merge branch 'jichuanh/task-cleanup-dex-part03' into jichuanh/task-cl…
hujc7 Jul 22, 2026
f570605
Merge branch 'jichuanh/task-cleanup-dex-part04' into jichuanh/task-cl…
hujc7 Jul 22, 2026
2abd525
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 22, 2026
2e11422
Merge branch 'jichuanh/task-cleanup-dex-part11' into jichuanh/task-cl…
hujc7 Jul 22, 2026
9987bb6
Fix stale camera helper import in rendering test utils
hujc7 Jul 22, 2026
eb345f3
Merge branch 'jichuanh/task-cleanup-dex-part04' into jichuanh/task-cl…
hujc7 Jul 22, 2026
213f88f
Merge branch 'jichuanh/task-cleanup-dex-part11' into jichuanh/task-cl…
hujc7 Jul 22, 2026
2c38c32
Fix leaked camera registration modules at this layer
hujc7 Jul 22, 2026
ddcd71e
Merge branch 'jichuanh/task-cleanup-dex-part03' into jichuanh/task-cl…
hujc7 Jul 22, 2026
6a43af9
Merge branch 'jichuanh/task-cleanup-dex-part03' into jichuanh/task-cl…
hujc7 Jul 22, 2026
9024129
Merge branch 'jichuanh/task-cleanup-dex-part04' into jichuanh/task-cl…
hujc7 Jul 22, 2026
538a3e9
Merge branch 'jichuanh/task-cleanup-dex-part08' into jichuanh/task-cl…
hujc7 Jul 22, 2026
9b79c13
Merge branch 'jichuanh/task-cleanup-dex-part11' into jichuanh/task-cl…
hujc7 Jul 22, 2026
5cb00e7
Re-pin camera registrations to this layer's renamed modules
hujc7 Jul 22, 2026
835a581
Merge branch 'jichuanh/task-cleanup-dex-part04' into jichuanh/task-cl…
hujc7 Jul 22, 2026
d634853
Merge branch 'jichuanh/task-cleanup-dex-part11' into jichuanh/task-cl…
hujc7 Jul 22, 2026
0618f81
Fold dexterous lump review fixes into the reorient Direct layer
hujc7 Jul 23, 2026
60ff05a
Merge commit '0618f81af3add3e610802c560fdba6c6710e8b3a' into restack/…
hujc7 Jul 23, 2026
8f13d3f
Fold handover review fixes into the handover Direct layer
hujc7 Jul 23, 2026
d29afc7
Add isaaclab_assets changelog fragment for the name-list additions
hujc7 Jul 23, 2026
b10a849
Merge commit 'd29afc75e715a6874e27b4bee1a591e8d1963065' into restack/…
hujc7 Jul 23, 2026
30597db
Add manager-based counterparts for the reorientation tasks
hujc7 Jul 20, 2026
707d37f
Fold dexterous lump review fixes into the reorient manager layer
hujc7 Jul 23, 2026
020f21a
Merge commit 'b10a84948f8c476b830c1855e651fd5504f5e073' into restack/…
hujc7 Jul 23, 2026
b50ac89
Fold dexterous lump review fixes into the handover/camera manager layer
hujc7 Jul 23, 2026
a9ace29
Merge commit 'b50ac8906fc4f18f88514b0b01f534e7083b5119' into restack/…
hujc7 Jul 23, 2026
0c1f18f
Add warp-first Direct variants of dexterous tasks to experimental
hujc7 Jul 17, 2026
167c285
Drop the direct_ prefix from the warp reorient reward launcher
hujc7 Jul 18, 2026
5af12e0
Fix dexterous shadow-hand source links and ovphysx doc row
hujc7 Jul 23, 2026
c7f2f01
Move dexterous environment docs out of the benchmark PR
hujc7 Jul 23, 2026
af259c0
Update environment overview for the dexterous series
hujc7 Jul 23, 2026
6c356e6
u:P7
hujc7 Jul 23, 2026
1c2e62f
u:docs
hujc7 Jul 23, 2026
951bac7
Default Shadow camera env to PhysX for RTX rendering
hujc7 Jul 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 42 additions & 15 deletions docs/source/overview/environments.rst
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ for the lift-cube environment:
| | |allegro-direct-link| | | ``ovphysx`` (direct only) |
+-------------------------+------------------------------+-----------------------------------------------------------------------------+------------------------------+
| |cube-shadow| | |cube-shadow-link| | In-hand reorientation of a cube using Shadow hand | **physics=** ``physx``, |
| | | | ``newton_mjwarp`` |
| | |cube-shadow-ff-link| | | |
| | | | ``newton_mjwarp``, |
| | |cube-shadow-ff-link| | | ``ovphysx`` |
| | | | |
| | |cube-shadow-lstm-link| | | |
+-------------------------+------------------------------+-----------------------------------------------------------------------------+------------------------------+
Expand Down Expand Up @@ -355,10 +355,10 @@ for the lift-cube environment:
.. |kuka-allegro-reorient-link| replace:: :isaaclab-source:`Isaac-Reorient-KukaAllegro <source/isaaclab_tasks/isaaclab_tasks/core/dexsuite/config/kuka_allegro/dexsuite_kuka_allegro_env_cfg.py>`
.. |ka-lift-cam-link| replace:: :isaaclab-source:`Isaac-Lift-KukaAllegro-Camera <source/isaaclab_tasks/isaaclab_tasks/core/dexsuite/config/kuka_allegro/dexsuite_kuka_allegro_camera_env_cfg.py>`
.. |ka-reorient-cam-link| replace:: :isaaclab-source:`Isaac-Reorient-KukaAllegro-Camera <source/isaaclab_tasks/isaaclab_tasks/core/dexsuite/config/kuka_allegro/dexsuite_kuka_allegro_camera_env_cfg.py>`
.. |cube-shadow-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_env_cfg.py>`
.. |cube-shadow-ff-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-OpenAI-FF-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_env_cfg.py>`
.. |cube-shadow-lstm-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-OpenAI-LSTM-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_env_cfg.py>`
.. |cube-shadow-vis-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-Camera-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_env.py>`
.. |cube-shadow-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_direct_env_cfg.py>`
.. |cube-shadow-ff-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-OpenAI-FF-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_direct_env_cfg.py>`
.. |cube-shadow-lstm-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-OpenAI-LSTM-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_direct_env_cfg.py>`
.. |cube-shadow-vis-link| replace:: :isaaclab-source:`Isaac-Reorient-Cube-Shadow-Camera-Direct <source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_direct_camera_env.py>`
.. |agibot_place_mug-link| replace:: :isaaclab-source:`IsaacContrib-Place-Mug-Agibot-Left-Arm-RmpFlow <source/isaaclab_tasks/isaaclab_tasks/contrib/place/config/agibot/place_upright_mug_rmp_rel_env_cfg.py>`
.. |agibot_place_toy-link| replace:: :isaaclab-source:`IsaacContrib-Place-Toy2Box-Agibot-Right-Arm-RmpFlow <source/isaaclab_tasks/isaaclab_tasks/contrib/place/config/agibot/place_toy2box_rmp_rel_env_cfg.py>`
.. |reach_openarm_bi-link| replace:: :isaaclab-source:`IsaacContrib-Reach-OpenArmBi <source/isaaclab_tasks/isaaclab_tasks/contrib/reach/config/openarm/bimanual/joint_pos_env_cfg.py>`
Expand Down Expand Up @@ -1054,7 +1054,7 @@ inferencing, including reading from an already trained checkpoint and disabling
- Isaac-Reorient-Cube-Allegro-Play
- Manager Based
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
-
- **physics=** ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Allegro-Direct
-
- Direct
Expand All @@ -1065,28 +1065,50 @@ inferencing, including reading from an already trained checkpoint and disabling
- Direct
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
-
* - Isaac-Reorient-Cube-Shadow
-
- Manager Based
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Shadow-Camera
- Isaac-Reorient-Cube-Shadow-Camera-Play
- Manager Based
- **rl_games** (PPO), **rsl_rl** (PPO)
- | **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
| **renderer=** ``isaacsim_rtx``, ``newton_renderer``, ``ovrtx``, ``rtx``
| **presets=** ``albedo``, ``depth``, ``full``, ``rgb``, ``rgb_depth``, ``semantic_segmentation``, ``simple_shading_constant_diffuse``, ``simple_shading_diffuse_mdl``, ``simple_shading_full_mdl``
* - Isaac-Reorient-Cube-Shadow-Camera-Direct
- Isaac-Reorient-Cube-Shadow-Camera-Direct-Play
- Direct
- **rl_games** (PPO), **rsl_rl** (PPO)
- | **physics=** ``newton_kamino``, ``newton_mjwarp``, ``physx``
- | **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
| **renderer=** ``isaacsim_rtx``, ``newton_renderer``, ``ovrtx``, ``rtx``
| **presets=** ``albedo``, ``depth``, ``full``, ``rgb``, ``semantic_segmentation``, ``simple_shading_constant_diffuse``, ``simple_shading_diffuse_mdl``, ``simple_shading_full_mdl``
| **presets=** ``albedo``, ``depth``, ``full``, ``rgb``, ``rgb_depth``, ``semantic_segmentation``, ``simple_shading_constant_diffuse``, ``simple_shading_diffuse_mdl``, ``simple_shading_full_mdl``
* - Isaac-Reorient-Cube-Shadow-Direct
-
- Direct
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``physx``
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Shadow-OpenAI-FF
-
- Manager Based
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Shadow-OpenAI-FF-Direct
-
- Direct
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``physx``
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Shadow-OpenAI-LSTM
-
- Manager Based
- **rl_games** (PPO), **rsl_rl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Cube-Shadow-OpenAI-LSTM-Direct
-
- Direct
- **rl_games** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``physx``
- **rl_games** (PPO), **rsl_rl** (PPO)
- **physics=** ``newton_kamino``, ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Reorient-Franka
- Isaac-Reorient-Franka-Play
- Manager Based
Expand All @@ -1106,11 +1128,16 @@ inferencing, including reading from an already trained checkpoint and disabling
- | **physics=** ``newton_mjwarp``, ``physx``
| **renderer=** ``isaacsim_rtx``, ``newton_renderer``, ``ovrtx``, ``rtx``
| **presets=** ``albedo128``, ``albedo256``, ``albedo64``, ``cube``, ``depth128``, ``depth256``, ``depth64``, ``duo_camera``, ``raycaster_depth128``, ``raycaster_depth256``, ``raycaster_depth64``, ``rgb128``, ``rgb256``, ``rgb64``, ``semantic_segmentation128``, ``semantic_segmentation256``, ``semantic_segmentation64``, ``shapes``, ``simple_shading_constant_diffuse128``, ``simple_shading_constant_diffuse256``, ``simple_shading_constant_diffuse64``, ``simple_shading_diffuse_mdl128``, ``simple_shading_diffuse_mdl256``, ``simple_shading_diffuse_mdl64``, ``simple_shading_full_mdl128``, ``simple_shading_full_mdl256``, ``simple_shading_full_mdl64``, ``single_camera``
* - Isaac-Shadow-Handover
-
- Manager Based
- **rsl_rl** (PPO)
- **physics=** ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Shadow-Handover-Direct
-
- Direct
- **rl_games** (PPO), **skrl** (PPO, IPPO, MAPPO)
- **physics=** ``newton_mjwarp``, ``physx``
- **rl_games** (PPO), **rsl_rl** (PPO), **skrl** (PPO, IPPO, MAPPO)
- **physics=** ``newton_mjwarp``, ``ovphysx``, ``physx``
* - Isaac-Velocity-Flat-AnymalB-Warp-v0
- Isaac-Velocity-Flat-AnymalB-Warp-Play-v0
- Manager Based
Expand Down
7 changes: 7 additions & 0 deletions source/isaaclab/changelog.d/dexterous-env-convergence.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Fixed
^^^^^

* Fixed :meth:`~isaaclab.envs.DirectRLEnv.reset` to store the observation buffer
like :meth:`~isaaclab.envs.DirectRLEnv.step` already does, and exposed the
latest observations on the multi-agent-to-single-agent adapter through the
same public buffer.
4 changes: 3 additions & 1 deletion source/isaaclab/isaaclab/envs/direct_rl_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,9 @@ def reset(self, seed: int | None = None, options: dict[str, Any] | None = None)
self.sim.render()

# return observations
return self._get_observations(), self.extras
# store the buffer like step() does, so consumers can read the latest observations
self.obs_buf = self._get_observations()
return self.obs_buf, self.extras

def step(self, action: torch.Tensor) -> VecEnvStepReturn:
"""Execute one time-step of the environment's dynamics.
Expand Down
50 changes: 26 additions & 24 deletions source/isaaclab/isaaclab/envs/utils/marl.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,22 +81,34 @@ def __init__(self, env: DirectMARLEnv) -> None:
)
self.action_space = gym.vector.utils.batch_space(self.single_action_space, self.num_envs)

def reset(self, seed: int | None = None, options: dict[str, Any] | None = None) -> tuple[VecEnvObs, dict]:
obs, extras = self.env.reset(seed, options)
@property
def episode_length_buf(self) -> torch.Tensor:
"""Episode lengths from the wrapped multi-agent environment."""
return self.env.episode_length_buf

# use environment state as observation
if self._state_as_observation:
obs = {"policy": self.env.state()}
# concatenate agents' observations
@episode_length_buf.setter
def episode_length_buf(self, value: torch.Tensor) -> None:
self.env.episode_length_buf = value

@property
def obs_buf(self) -> VecEnvObs:
"""Latest observations from the wrapped multi-agent environment."""
return self._convert_observations(self.env.obs_dict)

def _convert_observations(self, obs: dict[AgentID, ObsType]) -> VecEnvObs:
"""Convert multi-agent observations to the single-agent policy observation."""
# FIXME: This implementation assumes the spaces are fundamental ones. Fix it to support composite spaces
else:
obs = {
"policy": torch.cat(
[obs[agent].reshape(self.num_envs, -1) for agent in self.env.possible_agents], dim=-1
)
}
if self._state_as_observation:
return {"policy": self.env.state()}
return {
"policy": torch.cat(
[obs[agent].reshape(self.num_envs, -1) for agent in self.env.possible_agents], dim=-1
)
}

return obs, extras
def reset(self, seed: int | None = None, options: dict[str, Any] | None = None) -> tuple[VecEnvObs, dict]:
obs, extras = self.env.reset(seed, options)
return self._convert_observations(obs), extras

def step(self, action: torch.Tensor) -> VecEnvStepReturn:
# split single-agent actions to build the multi-agent ones
Expand All @@ -111,17 +123,7 @@ def step(self, action: torch.Tensor) -> VecEnvStepReturn:
# step the environment
obs, rewards, terminated, time_outs, extras = self.env.step(_actions)

# use environment state as observation
if self._state_as_observation:
obs = {"policy": self.env.state()}
# concatenate agents' observations
# FIXME: This implementation assumes the spaces are fundamental ones. Fix it to support composite spaces
else:
obs = {
"policy": torch.cat(
[obs[agent].reshape(self.num_envs, -1) for agent in self.env.possible_agents], dim=-1
)
}
obs = self._convert_observations(obs)

# process environment outputs to return single-agent data
rewards = sum(rewards.values())
Expand Down
5 changes: 5 additions & 0 deletions source/isaaclab/test/cli/test_install_command_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ def test_core_submodules_starts_with_isaaclab(self):
"isaaclab must be first so dependents resolve against the local copy"
)

def test_core_submodules_install_contrib_before_tasks(self):
assert CORE_ISAACLAB_SUBMODULES.index("isaaclab_contrib") < CORE_ISAACLAB_SUBMODULES.index("isaaclab_tasks"), (
"isaaclab_contrib must be installed before isaaclab_tasks so its declared local dependency resolves"
)

def test_core_submodules_contains_expected_packages(self):
expected = {
"isaaclab",
Expand Down
82 changes: 82 additions & 0 deletions source/isaaclab/test/envs/test_marl_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

from types import SimpleNamespace

import gymnasium as gym
import torch

from isaaclab.envs.utils.marl import multi_agent_to_single_agent


class _FakeMultiAgentEnv:
possible_agents = ["agent_0", "agent_1"]
observation_spaces = {
"agent_0": gym.spaces.Box(low=-1.0, high=1.0, shape=(2,)),
"agent_1": gym.spaces.Box(low=-1.0, high=1.0, shape=(1,)),
}
action_spaces = {
"agent_0": gym.spaces.Box(low=-1.0, high=1.0, shape=(1,)),
"agent_1": gym.spaces.Box(low=-1.0, high=1.0, shape=(1,)),
}
render_mode = None

def __init__(self):
self.unwrapped = self
self.cfg = SimpleNamespace(state_space=2)
self.state_space = gym.spaces.Box(low=-1.0, high=1.0, shape=(2,))
self.sim = object()
self.scene = SimpleNamespace(num_envs=2)
self.episode_length_buf = torch.tensor([1, 2])
self.obs_dict = {
"agent_0": torch.tensor([[1.0, 2.0], [3.0, 4.0]]),
"agent_1": torch.tensor([[5.0], [6.0]]),
}

def reset(self, seed=None, options=None):
return self.obs_dict, {}

def state(self):
return torch.tensor([[7.0, 8.0], [9.0, 10.0]])

def close(self):
pass


def test_multi_agent_to_single_agent_reset_concatenates_agents():
"""The adapter reset should concatenate the agents' observations."""
env = multi_agent_to_single_agent(_FakeMultiAgentEnv())

observations, _ = env.reset()

torch.testing.assert_close(observations["policy"], torch.tensor([[1.0, 2.0, 5.0], [3.0, 4.0, 6.0]]))


def test_multi_agent_to_single_agent_reset_can_use_state():
"""The adapter reset should support the state-as-observation mode."""
env = multi_agent_to_single_agent(_FakeMultiAgentEnv(), state_as_observation=True)

observations, _ = env.reset()

torch.testing.assert_close(observations["policy"], torch.tensor([[7.0, 8.0], [9.0, 10.0]]))


def test_multi_agent_to_single_agent_forwards_episode_lengths():
"""RSL-RL episode randomization should update the wrapped environment buffer."""
source_env = _FakeMultiAgentEnv()
env = multi_agent_to_single_agent(source_env)
episode_lengths = torch.tensor([3, 4])

env.episode_length_buf = episode_lengths

assert env.episode_length_buf is episode_lengths
assert source_env.episode_length_buf is episode_lengths


def test_multi_agent_to_single_agent_exposes_latest_observations():
"""The public observation buffer should reflect the wrapped environment's buffer."""
env = multi_agent_to_single_agent(_FakeMultiAgentEnv())

torch.testing.assert_close(env.obs_buf["policy"], torch.tensor([[1.0, 2.0, 5.0], [3.0, 4.0, 6.0]]))
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Added
^^^^^

* Added the dexterous-hand actuated-joint and fingertip body-name lists
(:obj:`~isaaclab_assets.robots.shadow_hand.SHADOW_ACTUATED_JOINT_NAMES`,
:obj:`~isaaclab_assets.robots.shadow_hand.SHADOW_FINGERTIP_BODY_NAMES`,
:obj:`~isaaclab_assets.robots.allegro.ALLEGRO_ACTUATED_JOINT_NAMES`,
:obj:`~isaaclab_assets.robots.allegro.ALLEGRO_FINGERTIP_BODY_NAMES`) to the
robot asset modules so tasks can reference them from a single source.
29 changes: 29 additions & 0 deletions source/isaaclab_assets/isaaclab_assets/robots/allegro.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,32 @@
soft_joint_pos_limit_factor=1.0,
)
"""Configuration of Allegro Hand robot."""


ALLEGRO_FINGERTIP_BODY_NAMES: list[str] = [
"index_link_3",
"middle_link_3",
"ring_link_3",
"thumb_link_3",
]
"""Allegro Hand fingertip body names."""

ALLEGRO_ACTUATED_JOINT_NAMES: list[str] = [
"index_joint_0",
"middle_joint_0",
"ring_joint_0",
"thumb_joint_0",
"index_joint_1",
"index_joint_2",
"index_joint_3",
"middle_joint_1",
"middle_joint_2",
"middle_joint_3",
"ring_joint_1",
"ring_joint_2",
"ring_joint_3",
"thumb_joint_1",
"thumb_joint_2",
"thumb_joint_3",
]
"""Allegro Hand actuated joint names, in the Direct task's actuation order."""
34 changes: 34 additions & 0 deletions source/isaaclab_assets/isaaclab_assets/robots/shadow_hand.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,37 @@
soft_joint_pos_limit_factor=1.0,
)
"""Configuration of Shadow Hand robot."""


SHADOW_FINGERTIP_BODY_NAMES: list[str] = [
"robot0_ffdistal",
"robot0_mfdistal",
"robot0_rfdistal",
"robot0_lfdistal",
"robot0_thdistal",
]
"""Shadow Hand fingertip body names (identical on every backend asset)."""

SHADOW_ACTUATED_JOINT_NAMES: list[str] = [
"robot0_WRJ1",
"robot0_WRJ0",
"robot0_FFJ3",
"robot0_FFJ2",
"robot0_FFJ1",
"robot0_MFJ3",
"robot0_MFJ2",
"robot0_MFJ1",
"robot0_RFJ3",
"robot0_RFJ2",
"robot0_RFJ1",
"robot0_LFJ4",
"robot0_LFJ3",
"robot0_LFJ2",
"robot0_LFJ1",
"robot0_THJ4",
"robot0_THJ3",
"robot0_THJ2",
"robot0_THJ1",
"robot0_THJ0",
]
"""Shadow Hand actuated joint names, in the Direct task's actuation order."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Fixed
^^^^^

* Fixed :meth:`~isaaclab_experimental.envs.DirectRLEnvWarp.step` and
:meth:`~isaaclab_experimental.envs.DirectRLEnvWarp.reset` to store the returned
observation dictionary in ``obs_buf``, which
:meth:`~isaaclab_rl.rsl_rl.RslRlVecEnvWrapper.get_observations` now reads.
Loading