Skip to content

Commit 96316fd

Browse files
Merge pull request #35 from WATonomous/add-rl-lift-and-cabinet-task
Add RL Lift and Cabinet Task
2 parents d031c65 + 2259612 commit 96316fd

21 files changed

Lines changed: 1221 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
"""Manipulation environments to open drawers in a cabinet."""
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
2+
# All rights reserved.
3+
#
4+
# SPDX-License-Identifier: BSD-3-Clause
5+
6+
7+
from dataclasses import MISSING
8+
9+
import isaaclab.sim as sim_utils
10+
from isaaclab.actuators import ImplicitActuatorCfg
11+
from isaaclab.assets import ArticulationCfg, AssetBaseCfg
12+
from isaaclab.envs import ManagerBasedRLEnvCfg
13+
from isaaclab.managers import EventTermCfg as EventTerm
14+
from isaaclab.managers import ObservationGroupCfg as ObsGroup
15+
from isaaclab.managers import ObservationTermCfg as ObsTerm
16+
from isaaclab.managers import RewardTermCfg as RewTerm
17+
from isaaclab.managers import SceneEntityCfg
18+
from isaaclab.managers import TerminationTermCfg as DoneTerm
19+
from isaaclab.scene import InteractiveSceneCfg
20+
from isaaclab.sensors import FrameTransformerCfg
21+
from isaaclab.sensors.frame_transformer import OffsetCfg
22+
from isaaclab.utils import configclass
23+
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
24+
25+
from . import mdp
26+
27+
##
28+
# Pre-defined configs
29+
##
30+
from isaaclab.markers.config import FRAME_MARKER_CFG # isort: skip
31+
32+
33+
FRAME_MARKER_SMALL_CFG = FRAME_MARKER_CFG.copy()
34+
FRAME_MARKER_SMALL_CFG.markers["frame"].scale = (0.10, 0.10, 0.10)
35+
36+
37+
##
38+
# Scene definition
39+
##
40+
41+
42+
@configclass
43+
class CabinetSceneCfg(InteractiveSceneCfg):
44+
"""Configuration for the cabinet scene with a robot and a cabinet.
45+
46+
This is the abstract base implementation, the exact scene is defined in the derived classes
47+
which need to set the robot and end-effector frames
48+
"""
49+
50+
# robots, Will be populated by agent env cfg
51+
robot: ArticulationCfg = MISSING
52+
# End-effector, Will be populated by agent env cfg
53+
ee_frame: FrameTransformerCfg = MISSING
54+
55+
cabinet = ArticulationCfg(
56+
prim_path="{ENV_REGEX_NS}/Cabinet",
57+
spawn=sim_utils.UsdFileCfg(
58+
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Sektion_Cabinet/sektion_cabinet_instanceable.usd",
59+
activate_contact_sensors=False,
60+
),
61+
init_state=ArticulationCfg.InitialStateCfg(
62+
pos=(0.8, 0, 0.4),
63+
rot=(0.0, 0.0, 0.0, 1.0),
64+
joint_pos={
65+
"door_left_joint": 0.0,
66+
"door_right_joint": 0.0,
67+
"drawer_bottom_joint": 0.0,
68+
"drawer_top_joint": 0.0,
69+
},
70+
),
71+
actuators={
72+
"drawers": ImplicitActuatorCfg(
73+
joint_names_expr=["drawer_top_joint", "drawer_bottom_joint"],
74+
effort_limit_sim=87.0,
75+
stiffness=10.0,
76+
damping=1.0,
77+
),
78+
"doors": ImplicitActuatorCfg(
79+
joint_names_expr=["door_left_joint", "door_right_joint"],
80+
effort_limit_sim=87.0,
81+
stiffness=10.0,
82+
damping=2.5,
83+
),
84+
},
85+
)
86+
87+
# Frame definitions for the cabinet.
88+
cabinet_frame = FrameTransformerCfg(
89+
prim_path="{ENV_REGEX_NS}/Cabinet/sektion",
90+
debug_vis=True,
91+
visualizer_cfg=FRAME_MARKER_SMALL_CFG.replace(prim_path="/Visuals/CabinetFrameTransformer"),
92+
target_frames=[
93+
FrameTransformerCfg.FrameCfg(
94+
prim_path="{ENV_REGEX_NS}/Cabinet/drawer_handle_top",
95+
name="drawer_handle_top",
96+
offset=OffsetCfg(
97+
pos=(0.305, 0.0, 0.01),
98+
rot=(0.5, 0.5, -0.5, -0.5), # align with end-effector frame
99+
),
100+
),
101+
],
102+
)
103+
104+
# plane
105+
plane = AssetBaseCfg(
106+
prim_path="/World/GroundPlane",
107+
init_state=AssetBaseCfg.InitialStateCfg(),
108+
spawn=sim_utils.GroundPlaneCfg(),
109+
collision_group=-1,
110+
)
111+
112+
# lights
113+
light = AssetBaseCfg(
114+
prim_path="/World/light",
115+
spawn=sim_utils.DomeLightCfg(color=(0.75, 0.75, 0.75), intensity=3000.0),
116+
)
117+
118+
119+
##
120+
# MDP settings
121+
##
122+
123+
124+
@configclass
125+
class ActionsCfg:
126+
"""Action specifications for the MDP."""
127+
128+
arm_action: mdp.JointPositionActionCfg = MISSING
129+
gripper_action: mdp.BinaryJointPositionActionCfg = MISSING
130+
131+
132+
@configclass
133+
class ObservationsCfg:
134+
"""Observation specifications for the MDP."""
135+
136+
@configclass
137+
class PolicyCfg(ObsGroup):
138+
"""Observations for policy group."""
139+
140+
joint_pos = ObsTerm(func=mdp.joint_pos_rel)
141+
joint_vel = ObsTerm(func=mdp.joint_vel_rel)
142+
cabinet_joint_pos = ObsTerm(
143+
func=mdp.joint_pos_rel,
144+
params={"asset_cfg": SceneEntityCfg("cabinet", joint_names=["drawer_top_joint"])},
145+
)
146+
cabinet_joint_vel = ObsTerm(
147+
func=mdp.joint_vel_rel,
148+
params={"asset_cfg": SceneEntityCfg("cabinet", joint_names=["drawer_top_joint"])},
149+
)
150+
rel_ee_drawer_distance = ObsTerm(func=mdp.rel_ee_drawer_distance)
151+
152+
actions = ObsTerm(func=mdp.last_action)
153+
154+
def __post_init__(self):
155+
self.enable_corruption = True
156+
self.concatenate_terms = True
157+
158+
# observation groups
159+
policy: PolicyCfg = PolicyCfg()
160+
161+
162+
@configclass
163+
class EventCfg:
164+
"""Configuration for events."""
165+
166+
robot_physics_material = EventTerm(
167+
func=mdp.randomize_rigid_body_material,
168+
mode="startup",
169+
params={
170+
"asset_cfg": SceneEntityCfg("robot", body_names=".*"),
171+
"static_friction_range": (0.8, 1.25),
172+
"dynamic_friction_range": (0.8, 1.25),
173+
"restitution_range": (0.0, 0.0),
174+
"num_buckets": 16,
175+
},
176+
)
177+
178+
cabinet_physics_material = EventTerm(
179+
func=mdp.randomize_rigid_body_material,
180+
mode="startup",
181+
params={
182+
"asset_cfg": SceneEntityCfg("cabinet", body_names="drawer_handle_top"),
183+
"static_friction_range": (1.0, 1.25),
184+
"dynamic_friction_range": (1.25, 1.5),
185+
"restitution_range": (0.0, 0.0),
186+
"num_buckets": 16,
187+
},
188+
)
189+
190+
reset_all = EventTerm(func=mdp.reset_scene_to_default, mode="reset")
191+
192+
reset_robot_joints = EventTerm(
193+
func=mdp.reset_joints_by_offset,
194+
mode="reset",
195+
params={
196+
"position_range": (-0.1, 0.1),
197+
"velocity_range": (0.0, 0.0),
198+
},
199+
)
200+
201+
202+
@configclass
203+
class RewardsCfg:
204+
"""Reward terms for the MDP."""
205+
206+
# 1. Approach the handle
207+
approach_ee_handle = RewTerm(func=mdp.approach_ee_handle, weight=2.0, params={"threshold": 0.2})
208+
align_ee_handle = RewTerm(func=mdp.align_ee_handle, weight=0.5)
209+
210+
# 2. Grasp the handle
211+
approach_gripper_handle = RewTerm(func=mdp.approach_gripper_handle, weight=5.0, params={"offset": MISSING})
212+
align_grasp_around_handle = RewTerm(func=mdp.align_grasp_around_handle, weight=0.125)
213+
grasp_handle = RewTerm(
214+
func=mdp.grasp_handle,
215+
weight=0.5,
216+
params={
217+
"threshold": 0.03,
218+
"open_joint_pos": MISSING,
219+
"asset_cfg": SceneEntityCfg("robot", joint_names=MISSING),
220+
},
221+
)
222+
223+
# 3. Open the drawer
224+
open_drawer_bonus = RewTerm(
225+
func=mdp.open_drawer_bonus,
226+
weight=7.5,
227+
params={"asset_cfg": SceneEntityCfg("cabinet", joint_names=["drawer_top_joint"])},
228+
)
229+
multi_stage_open_drawer = RewTerm(
230+
func=mdp.multi_stage_open_drawer,
231+
weight=1.0,
232+
params={"asset_cfg": SceneEntityCfg("cabinet", joint_names=["drawer_top_joint"])},
233+
)
234+
235+
# 4. Penalize actions for cosmetic reasons
236+
action_rate_l2 = RewTerm(func=mdp.action_rate_l2, weight=-1e-2)
237+
joint_vel = RewTerm(func=mdp.joint_vel_l2, weight=-0.0001)
238+
239+
240+
@configclass
241+
class TerminationsCfg:
242+
"""Termination terms for the MDP."""
243+
244+
time_out = DoneTerm(func=mdp.time_out, time_out=True)
245+
246+
247+
##
248+
# Environment configuration
249+
##
250+
251+
252+
@configclass
253+
class CabinetEnvCfg(ManagerBasedRLEnvCfg):
254+
"""Configuration for the cabinet environment."""
255+
256+
# Scene settings
257+
scene: CabinetSceneCfg = CabinetSceneCfg(num_envs=4096, env_spacing=2.0)
258+
# Basic settings
259+
observations: ObservationsCfg = ObservationsCfg()
260+
actions: ActionsCfg = ActionsCfg()
261+
# MDP settings
262+
rewards: RewardsCfg = RewardsCfg()
263+
terminations: TerminationsCfg = TerminationsCfg()
264+
events: EventCfg = EventCfg()
265+
266+
def __post_init__(self):
267+
"""Post initialization."""
268+
# general settings
269+
self.decimation = 1
270+
self.episode_length_s = 8.0
271+
self.viewer.eye = (-2.0, 2.0, 2.0)
272+
self.viewer.lookat = (0.8, 0.0, 0.5)
273+
# simulation settings
274+
self.sim.dt = 1 / 60 # 60Hz
275+
self.sim.render_interval = self.decimation
276+
self.sim.physx.bounce_threshold_velocity = 0.2
277+
self.sim.physx.bounce_threshold_velocity = 0.01
278+
self.sim.physx.friction_correlation_distance = 0.00625
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import gymnasium as gym
2+
3+
from . import agents
4+
5+
gym.register(
6+
id="Isaac-Open-Drawer-Humanoid-Arm-v0",
7+
entry_point="isaaclab.envs:ManagerBasedRLEnv",
8+
disable_env_checker=True,
9+
kwargs={
10+
"env_cfg_entry_point": f"{__name__}.joint_pos_env_cfg:HumanoidArmCabinetEnvCfg",
11+
"rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:HumanoidArmCabinetPPORunnerCfg",
12+
},
13+
)
14+
15+
gym.register(
16+
id="Isaac-Open-Drawer-Humanoid-Arm-Play-v0",
17+
entry_point="isaaclab.envs:ManagerBasedRLEnv",
18+
disable_env_checker=True,
19+
kwargs={
20+
"env_cfg_entry_point": f"{__name__}.joint_pos_env_cfg:HumanoidArmCabinetEnvCfg_PLAY",
21+
"rsl_rl_cfg_entry_point": f"{agents.__name__}.rsl_rl_ppo_cfg:HumanoidArmCabinetPPORunnerCfg",
22+
},
23+
)

autonomy/simulation/Humanoid_Wato/HumanoidRL/HumanoidRLPackage/HumanoidRLSetup/tasks/cabinet/config/HumanoidRLEnv/agents/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
from isaaclab.utils import configclass
2+
from isaaclab_rl.rsl_rl import (
3+
RslRlOnPolicyRunnerCfg,
4+
RslRlPpoActorCriticCfg,
5+
RslRlPpoAlgorithmCfg,
6+
)
7+
8+
9+
@configclass
10+
class HumanoidArmCabinetPPORunnerCfg(RslRlOnPolicyRunnerCfg):
11+
num_steps_per_env = 96
12+
max_iterations = 400
13+
save_interval = 50
14+
experiment_name = "cabinet_humanoid_arm"
15+
empirical_normalization = False
16+
policy = RslRlPpoActorCriticCfg(
17+
init_noise_std=1.0,
18+
actor_obs_normalization=False,
19+
critic_obs_normalization=False,
20+
actor_hidden_dims=[256, 128, 64],
21+
critic_hidden_dims=[256, 128, 64],
22+
activation="elu",
23+
)
24+
algorithm = RslRlPpoAlgorithmCfg(
25+
value_loss_coef=1.0,
26+
use_clipped_value_loss=True,
27+
clip_param=0.2,
28+
entropy_coef=1e-3,
29+
num_learning_epochs=5,
30+
num_mini_batches=4,
31+
learning_rate=5.0e-4,
32+
schedule="adaptive",
33+
gamma=0.99,
34+
lam=0.95,
35+
desired_kl=0.02,
36+
max_grad_norm=1.0,
37+
)

0 commit comments

Comments
 (0)