Skip to content

Commit da863b8

Browse files
committed
Add manager-based counterparts for the reorientation tasks
Rebuilt from the reviewed lump so the manager counterparts land with the review round folded in: - Sim settings come from the ShadowHandTaskCfgBase/OpenAI and Allegro task-cfg mixins instead of module-level cfg variables. - Backend scene presets declare only backend-specific fields; shared invariants live as inner-class defaults. - The command, reward, action, and reset-event declarations come from term factories in reorient_task_base; each variant states only its deltas, and the invariant termination section is shared outright. - The manager terms are named ReorientReward and ReorientTimeout; the Direct-parity contract is stated in their docstrings. - The orientation error comes from isaaclab.utils.math.quat_error_magnitude. - The superseded legacy manager env and its terms are removed. Lump review commits folded: 2c22af0, 792e400, 42675b6, 1f05f85, c6140f9, 173e9dc, 2727616, 1732493, 3659a33, ee272c9.
1 parent 21dbb17 commit da863b8

14 files changed

Lines changed: 1292 additions & 555 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Added
2+
^^^^^
3+
4+
* Added manager-based counterparts for the Allegro and Shadow cube
5+
reorientation tasks (state and OpenAI FF/LSTM observation variants), sharing
6+
the Direct tasks' scalar parameters and boolean success metrics through
7+
common MDP terms.
8+
* Added opt-in domain randomization to the manager-based Allegro environment
9+
(``enable_domain_randomization``, disabled by default; enabling requires
10+
retraining).
11+
* Added a Newton physics preset to the manager-based Allegro environment.
12+
13+
Removed
14+
^^^^^^^
15+
16+
* Removed the legacy manager-based reorientation configuration
17+
``ReorientObjectEnvCfg`` and the manager terms only it consumed
18+
(``success_bonus``, ``track_pos_l2``, ``track_orientation_inv_l2``,
19+
``max_consecutive_success``, ``object_away_from_goal``, and
20+
``object_away_from_robot``). Use the Direct-compatible manager
21+
configurations and terms instead (e.g.
22+
:class:`~isaaclab_tasks.core.reorient.mdp.ReorientReward` and
23+
:class:`~isaaclab_tasks.core.reorient.mdp.ReorientTimeout`).
24+
25+
Changed
26+
^^^^^^^
27+
28+
* **Breaking:** Changed the manager-based Allegro reorientation environment to
29+
match the Direct observation, action, reward, reset, termination, success,
30+
asset, and benchmark contracts. Existing manager checkpoints are
31+
incompatible and must be retrained.

source/isaaclab_tasks/isaaclab_tasks/core/reorient/__init__.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
This package consolidates the direct-workflow and manager-based-workflow in-hand
99
manipulation tasks, where a dexterous hand reorients an object to match a goal
1010
orientation. The shared direct base environment lives in
11-
:mod:`~isaaclab_tasks.core.reorient.reorient_direct_env` and the shared manager-based
12-
base configuration in :mod:`~isaaclab_tasks.core.reorient.reorient_manager_env_cfg`.
13-
Robot-specific tasks are organized under the ``config`` subpackage
14-
(``config/allegro_hand`` and ``config/shadow_hand``).
11+
:mod:`~isaaclab_tasks.core.reorient.reorient_direct_env`; the manager-based
12+
configurations live with their robot-specific tasks under the ``config``
13+
subpackage (``config/allegro_hand`` and ``config/shadow_hand``).
1514
1615
These environments are based on the `dexterous cube manipulation`_ environments
1716
provided in IsaacGymEnvs repository from NVIDIA. However, they contain certain

source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/allegro_hand/allegro_hand_manager_env_cfg.py

Lines changed: 242 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,260 @@
33
#
44
# SPDX-License-Identifier: BSD-3-Clause
55

6+
"""Manager-based counterpart of the Allegro Hand Direct reorientation task."""
7+
8+
import isaaclab.sim as sim_utils
9+
from isaaclab.assets import ArticulationCfg, AssetBaseCfg
10+
from isaaclab.envs import ManagerBasedRLEnvCfg
11+
from isaaclab.managers import EventTermCfg as EventTerm
12+
from isaaclab.managers import ObservationGroupCfg as ObsGroup
13+
from isaaclab.managers import ObservationTermCfg as ObsTerm
14+
from isaaclab.managers import SceneEntityCfg
15+
from isaaclab.scene import InteractiveSceneCfg
616
from isaaclab.utils.configclass import configclass
717

8-
from isaaclab_tasks.core.reorient.reorient_manager_env_cfg import ReorientObjectEnvCfg
18+
import isaaclab_tasks.core.reorient.mdp as mdp
19+
from isaaclab_tasks.core.reorient.config.allegro_hand.allegro_hand_direct_env_cfg import (
20+
GOAL_OBJECT_CFG,
21+
OBJECT_CFG,
22+
ROBOT_CFG,
23+
AllegroHandTaskCfgBase,
24+
ObjectCfg,
25+
)
26+
from isaaclab_tasks.core.reorient.reorient_task_base import (
27+
ALLEGRO_ACTUATED_JOINT_NAMES,
28+
ALLEGRO_FINGERTIP_BODY_NAMES,
29+
ReorientTerminationsCfg,
30+
reorient_goal_command,
31+
reorient_joint_action,
32+
reorient_reset_event,
33+
reorient_reward_term,
34+
)
35+
from isaaclab_tasks.utils import PresetCfg
36+
37+
38+
@configclass
39+
class AllegroCubeSceneCfg(PresetCfg):
40+
"""Backend-specific scene cloning settings matching the Direct task."""
41+
42+
@configclass
43+
class SceneCfg(InteractiveSceneCfg):
44+
"""Allegro scene shared by the backend alternatives."""
945

10-
##
11-
# Pre-defined configs
12-
##
13-
from isaaclab_assets import ALLEGRO_HAND_CFG # isort: skip
46+
num_envs = 8192
47+
env_spacing = 0.75
48+
replicate_physics = True
49+
50+
ground = AssetBaseCfg(prim_path="/World/ground", spawn=sim_utils.GroundPlaneCfg())
51+
robot: ArticulationCfg = ROBOT_CFG
52+
object: ObjectCfg = OBJECT_CFG
53+
light = AssetBaseCfg(
54+
prim_path="/World/Light",
55+
spawn=sim_utils.DomeLightCfg(intensity=2000.0, color=(0.75, 0.75, 0.75)),
56+
)
57+
58+
physx = SceneCfg(clone_in_fabric=True)
59+
newton_mjwarp = SceneCfg(clone_in_fabric=False)
60+
ovphysx = physx
61+
default = physx
62+
63+
def set_num_envs(self, num_envs: int) -> None:
64+
"""Set the environment count on every backend alternative."""
65+
for scene in (self.physx, self.newton_mjwarp, self.ovphysx, self.default):
66+
scene.num_envs = num_envs
1467

1568

1669
@configclass
17-
class AllegroCubeEnvCfg(ReorientObjectEnvCfg):
18-
def __post_init__(self):
19-
# post init of parent
20-
super().__post_init__()
70+
class CommandsCfg:
71+
"""The reorient goal command with the Allegro marker and tolerance."""
72+
73+
object_pose = reorient_goal_command(orientation_success_threshold=0.2, goal_pose_visualizer_cfg=GOAL_OBJECT_CFG)
74+
75+
76+
@configclass
77+
class ActionsCfg:
78+
"""Sixteen actuated Allegro Hand joints in Direct order."""
79+
80+
joint_pos = reorient_joint_action(ALLEGRO_ACTUATED_JOINT_NAMES)
81+
82+
83+
@configclass
84+
class ObservationsCfg:
85+
"""Full 124-dimensional state observation in Direct order."""
86+
87+
@configclass
88+
class PolicyCfg(ObsGroup):
89+
joint_pos = ObsTerm(
90+
func=mdp.joint_pos_limit_normalized,
91+
params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*", preserve_order=False)},
92+
)
93+
joint_vel = ObsTerm(
94+
func=mdp.joint_vel,
95+
scale=0.2,
96+
params={"asset_cfg": SceneEntityCfg("robot", joint_names=".*", preserve_order=False)},
97+
)
98+
object_pos = ObsTerm(func=mdp.root_pos_w, params={"asset_cfg": SceneEntityCfg("object")})
99+
object_quat = ObsTerm(
100+
func=mdp.root_quat_w,
101+
params={"asset_cfg": SceneEntityCfg("object"), "make_quat_unique": False},
102+
)
103+
object_lin_vel = ObsTerm(func=mdp.root_lin_vel_w, params={"asset_cfg": SceneEntityCfg("object")})
104+
object_ang_vel = ObsTerm(
105+
func=mdp.root_ang_vel_w,
106+
scale=0.2,
107+
params={"asset_cfg": SceneEntityCfg("object")},
108+
)
109+
goal_pose = ObsTerm(func=mdp.generated_commands, params={"command_name": "object_pose"})
110+
goal_quat_diff = ObsTerm(
111+
func=mdp.goal_quat_diff,
112+
params={"asset_cfg": SceneEntityCfg("object"), "command_name": "object_pose", "make_quat_unique": False},
113+
)
114+
fingertip_pos = ObsTerm(
115+
func=mdp.fingertip_pos,
116+
params={
117+
"asset_cfg": SceneEntityCfg("robot", body_names=ALLEGRO_FINGERTIP_BODY_NAMES, preserve_order=False)
118+
},
119+
)
120+
fingertip_quat = ObsTerm(
121+
func=mdp.fingertip_quat,
122+
params={
123+
"asset_cfg": SceneEntityCfg("robot", body_names=ALLEGRO_FINGERTIP_BODY_NAMES, preserve_order=False)
124+
},
125+
)
126+
fingertip_vel = ObsTerm(
127+
func=mdp.fingertip_vel,
128+
params={
129+
"asset_cfg": SceneEntityCfg("robot", body_names=ALLEGRO_FINGERTIP_BODY_NAMES, preserve_order=False)
130+
},
131+
)
132+
last_action = ObsTerm(func=mdp.reorient_last_action, params={"action_name": "joint_pos"})
133+
134+
def __post_init__(self):
135+
self.enable_corruption = False
136+
self.concatenate_terms = True
21137

22-
# switch robot to allegro hand
23-
self.scene.robot = ALLEGRO_HAND_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
24-
# enable clone in fabric
25-
self.scene.clone_in_fabric = True
138+
policy: PolicyCfg = PolicyCfg()
139+
140+
141+
@configclass
142+
class EventCfg:
143+
"""Reset distributions matching the Direct task, plus opt-in domain randomization.
144+
145+
The domain-randomization terms reproduce the legacy manager recipe. They are
146+
startup-mode terms and are dropped by default (see
147+
:attr:`AllegroCubeEnvCfg.enable_domain_randomization`): the Direct task has no
148+
domain randomization, and the validated benchmark thresholds were calibrated
149+
without it. Enabling them requires retraining.
150+
"""
151+
152+
# -- opt-in domain randomization (legacy manager recipe parameters)
153+
robot_physics_material = EventTerm(
154+
func=mdp.randomize_rigid_body_material,
155+
mode="startup",
156+
params={
157+
"asset_cfg": SceneEntityCfg("robot", body_names=".*"),
158+
"static_friction_range": (0.7, 1.3),
159+
"dynamic_friction_range": (0.7, 1.3),
160+
"restitution_range": (0.0, 0.0),
161+
"num_buckets": 250,
162+
},
163+
)
164+
robot_scale_mass = EventTerm(
165+
func=mdp.randomize_rigid_body_mass,
166+
mode="startup",
167+
params={
168+
"asset_cfg": SceneEntityCfg("robot", body_names=".*"),
169+
"mass_distribution_params": (0.95, 1.05),
170+
"operation": "scale",
171+
},
172+
)
173+
robot_joint_stiffness_and_damping = EventTerm(
174+
func=mdp.randomize_actuator_gains,
175+
mode="startup",
176+
params={
177+
"asset_cfg": SceneEntityCfg("robot", joint_names=".*"),
178+
"stiffness_distribution_params": (0.3, 3.0),
179+
"damping_distribution_params": (0.75, 1.5),
180+
"operation": "scale",
181+
"distribution": "log_uniform",
182+
},
183+
)
184+
object_physics_material = EventTerm(
185+
func=mdp.randomize_rigid_body_material,
186+
mode="startup",
187+
params={
188+
"asset_cfg": SceneEntityCfg("object", body_names=".*"),
189+
"static_friction_range": (0.7, 1.3),
190+
"dynamic_friction_range": (0.7, 1.3),
191+
"restitution_range": (0.0, 0.0),
192+
"num_buckets": 250,
193+
},
194+
)
195+
object_scale_mass = EventTerm(
196+
func=mdp.randomize_rigid_body_mass,
197+
mode="startup",
198+
params={
199+
"asset_cfg": SceneEntityCfg("object"),
200+
"mass_distribution_params": (0.4, 1.6),
201+
"operation": "scale",
202+
},
203+
)
204+
205+
reset_state = reorient_reset_event()
206+
207+
208+
@configclass
209+
class RewardsCfg:
210+
"""The reorient reward with the Allegro success tolerance."""
211+
212+
reorient = reorient_reward_term(success_tolerance=0.2)
213+
214+
215+
@configclass
216+
class AllegroCubeEnvCfg(AllegroHandTaskCfgBase, ManagerBasedRLEnvCfg):
217+
"""Manager-based Allegro Hand task with Direct-compatible semantics."""
218+
219+
scene: AllegroCubeSceneCfg = AllegroCubeSceneCfg()
220+
observations: ObservationsCfg = ObservationsCfg()
221+
actions: ActionsCfg = ActionsCfg()
222+
commands: CommandsCfg = CommandsCfg()
223+
rewards: RewardsCfg = RewardsCfg()
224+
# the shared termination section from isaaclab_tasks.core.reorient.reorient_task_base
225+
terminations: ReorientTerminationsCfg = ReorientTerminationsCfg()
226+
events: EventCfg = EventCfg()
227+
228+
enable_domain_randomization: bool = False
229+
"""Enable the legacy startup domain-randomization terms.
230+
231+
Disabled by default: the validated reference training runs and the benchmark
232+
thresholds were produced without domain randomization, so enabling it
233+
requires retraining and threshold recalibration.
234+
"""
235+
236+
_DOMAIN_RANDOMIZATION_TERMS = (
237+
"robot_physics_material",
238+
"robot_scale_mass",
239+
"robot_joint_stiffness_and_damping",
240+
"object_physics_material",
241+
"object_scale_mass",
242+
)
243+
244+
def __post_init__(self):
245+
self.decimation = 4
246+
self.episode_length_s = 10.0
247+
self.sim.render_interval = self.decimation
248+
self.viewer.eye = (2.0, 2.0, 2.0)
249+
if not self.enable_domain_randomization:
250+
for term_name in self._DOMAIN_RANDOMIZATION_TERMS:
251+
setattr(self.events, term_name, None)
26252

27253

28254
@configclass
29255
class AllegroCubeEnvCfg_PLAY(AllegroCubeEnvCfg):
256+
"""Reduced, deterministic play configuration."""
257+
30258
def __post_init__(self):
31-
# post init of parent
32259
super().__post_init__()
33-
# make a smaller scene for play
34-
self.scene.num_envs = 50
35-
# disable randomization for play
260+
self.scene.set_num_envs(50)
36261
self.observations.policy.enable_corruption = False
37-
# remove termination due to timeouts
38262
self.terminations.time_out = None

source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/__init__.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@
1717

1818
reorient_direct_entry = "isaaclab_tasks.core.reorient.reorient_direct_env:ReorientDirectEnv"
1919

20+
gym.register(
21+
id="Isaac-Reorient-Cube-Shadow",
22+
entry_point="isaaclab.envs:ManagerBasedRLEnv",
23+
disable_env_checker=True,
24+
kwargs={
25+
"env_cfg_entry_point": f"{__name__}.shadow_hand_manager_env_cfg:ShadowHandManagerEnvCfg",
26+
"rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_cfg.yaml",
27+
"rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:ShadowHandPPORunnerCfg",
28+
"skrl_cfg_entry_point": f"{agents.__name__}:skrl_ppo_cfg.yaml",
29+
},
30+
)
31+
2032
gym.register(
2133
id="Isaac-Reorient-Cube-Shadow-Direct",
2234
entry_point=reorient_direct_entry,
@@ -29,6 +41,29 @@
2941
},
3042
)
3143

44+
gym.register(
45+
id="Isaac-Reorient-Cube-Shadow-OpenAI-FF",
46+
entry_point="isaaclab.envs:ManagerBasedRLEnv",
47+
disable_env_checker=True,
48+
kwargs={
49+
"env_cfg_entry_point": f"{__name__}.shadow_hand_manager_env_cfg:ShadowHandOpenAIManagerEnvCfg",
50+
"rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_ff_cfg.yaml",
51+
"rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:ShadowHandAsymFFPPORunnerCfg",
52+
"skrl_cfg_entry_point": f"{agents.__name__}:skrl_ff_ppo_cfg.yaml",
53+
},
54+
)
55+
56+
gym.register(
57+
id="Isaac-Reorient-Cube-Shadow-OpenAI-LSTM",
58+
entry_point="isaaclab.envs:ManagerBasedRLEnv",
59+
disable_env_checker=True,
60+
kwargs={
61+
"env_cfg_entry_point": f"{__name__}.shadow_hand_manager_env_cfg:ShadowHandOpenAIManagerEnvCfg",
62+
"rl_games_cfg_entry_point": f"{agents.__name__}:rl_games_ppo_lstm_cfg.yaml",
63+
"rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:ShadowHandAsymLSTMPPORunnerCfg",
64+
},
65+
)
66+
3267
gym.register(
3368
id="Isaac-Reorient-Cube-Shadow-OpenAI-FF-Direct",
3469
entry_point=reorient_direct_entry,

0 commit comments

Comments
 (0)