Unverified Commit 34227828 authored by rebeccazhang0707's avatar rebeccazhang0707 Committed by GitHub

Adds surface gripper support in manager-based workflow (#3174)

# Description

<!--
Thank you for your interest in sending a pull request. Please make sure
to check the contribution guidelines.

Link:
https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html
-->

We only have a surface gripper sample with direct workflow, whereas in
manager-based workflow it is not supported yet.
- Add surface gripper as an asset instance to the scene (CPU only)
- Add SurfaceGripperAction and SurfaceGripperActionCfg
- Add two TaskEnvs for testing: 

1. Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0  
2. Isaac-Stack-Cube-UR10-Short-Suction-IK-Rel-v0

You can test recording demos by:
`./isaaclab.sh -p scripts/tools/record_demos.py --task
Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0 --teleop_device keyboard
--device cpu`

<!-- As a practice, it is recommended to open an issue to have
discussions on the proposed pull request.
This makes it easier for the community to keep track of what is being
developed or added, and if a given feature
is demanded by more than one party. -->

## Type of change

<!-- As you go through the list, delete the ones that are not
applicable. -->

- New feature (non-breaking change which adds functionality)

## Screenshot
<img width="1386" height="273" alt="environments_surface_gripper"
src="https://github.com/user-attachments/assets/4c1cb5a4-4325-4861-b20c-9204e98e7dff"
/>




## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [ ] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->

---------
Signed-off-by: 's avatarrebeccazhang0707 <168459200+rebeccazhang0707@users.noreply.github.com>
Signed-off-by: 's avatarKelly Guo <kellyg@nvidia.com>
Co-authored-by: 's avatarKelly Guo <kellyg@nvidia.com>
parent 73aa877d
......@@ -3,7 +3,7 @@
Available Environments
======================
The following lists comprises of all the RL tasks implementations that are available in Isaac Lab.
The following lists comprises of all the RL or IL tasks implementations that are available in Isaac Lab.
While we try to keep this list up-to-date, you can always get the latest list of environments by
running the following command:
......@@ -116,6 +116,10 @@ for the lift-cube environment:
| | | Blueprint env used for the NVIDIA Isaac GR00T blueprint for synthetic |
| | |stack-cube-bp-link| | manipulation motion generation |
+----------------------+---------------------------+-----------------------------------------------------------------------------+
| |surface-gripper| | |long-suction-link| | Stack three cubes (bottom to top: blue, red, green) |
| | | with the UR10 arm and long surface gripper |
| | |short-suction-link| | or short surface gripper. |
+----------------------+---------------------------+-----------------------------------------------------------------------------+
| |cabi-franka| | |cabi-franka-link| | Grasp the handle of a cabinet's drawer and open it with the Franka robot |
| | | |
| | |franka-direct-link| | |
......@@ -148,6 +152,7 @@ for the lift-cube environment:
.. |cube-shadow| image:: ../_static/tasks/manipulation/shadow_cube.jpg
.. |stack-cube| image:: ../_static/tasks/manipulation/franka_stack.jpg
.. |gr1_pick_place| image:: ../_static/tasks/manipulation/gr-1_pick_place.jpg
.. |surface-gripper| image:: ../_static/tasks/manipulation/ur10_stack_surface_gripper.jpg
.. |gr1_pp_waist| image:: ../_static/tasks/manipulation/gr-1_pick_place_waist.jpg
.. |reach-franka-link| replace:: `Isaac-Reach-Franka-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/reach/config/franka/joint_pos_env_cfg.py>`__
......@@ -163,6 +168,8 @@ for the lift-cube environment:
.. |stack-cube-link| replace:: `Isaac-Stack-Cube-Franka-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_joint_pos_env_cfg.py>`__
.. |stack-cube-bp-link| replace:: `Isaac-Stack-Cube-Franka-IK-Rel-Blueprint-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_blueprint_env_cfg.py>`__
.. |gr1_pick_place-link| replace:: `Isaac-PickPlace-GR1T2-Abs-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_env_cfg.py>`__
.. |long-suction-link| replace:: `Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/ur10_gripper/stack_ik_rel_env_cfg.py>`__
.. |short-suction-link| replace:: `Isaac-Stack-Cube-UR10-Short-Suction-IK-Rel-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/ur10_gripper/stack_ik_rel_env_cfg.py>`__
.. |gr1_pp_waist-link| replace:: `Isaac-PickPlace-GR1T2-WaistEnabled-Abs-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_waist_enabled_env_cfg.py>`__
.. |cube-shadow-link| replace:: `Isaac-Repose-Cube-Shadow-Direct-v0 <https://github.com/isaac-sim/IsaacLab/blob/main/source/isaaclab_tasks/isaaclab_tasks/direct/shadow_hand/shadow_hand_env_cfg.py>`__
......@@ -939,6 +946,14 @@ inferencing, including reading from an already trained checkpoint and disabling
-
- Manager Based
-
* - Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0
-
- Manager Based
-
* - Isaac-Stack-Cube-UR10-Short-Suction-IK-Rel-v0
-
- Manager Based
-
* - Isaac-Velocity-Flat-Anymal-B-v0
- Isaac-Velocity-Flat-Anymal-B-Play-v0
- Manager Based
......
......@@ -87,7 +87,7 @@ class PickAndPlaceEnvCfg(DirectRLEnvCfg):
# Surface Gripper, the prim_expr need to point to a unique surface gripper per environment.
gripper = SurfaceGripperCfg(
prim_expr="/World/envs/env_.*/Robot/picker_head/SurfaceGripper",
prim_path="/World/envs/env_.*/Robot/picker_head/SurfaceGripper",
max_grip_distance=0.1,
shear_force_limit=500.0,
coaxial_force_limit=500.0,
......
......@@ -72,7 +72,7 @@ def design_scene():
# Surface Gripper: Next we define the surface gripper config
surface_gripper_cfg = SurfaceGripperCfg()
# We need to tell the View which prim to use for the surface gripper
surface_gripper_cfg.prim_expr = "/World/Origin.*/Robot/picker_head/SurfaceGripper"
surface_gripper_cfg.prim_path = "/World/Origin.*/Robot/picker_head/SurfaceGripper"
# We can then set different parameters for the surface gripper, note that if these parameters are not set,
# the View will try to read them from the prim.
surface_gripper_cfg.max_grip_distance = 0.1 # [m] (Maximum distance at which the gripper can grasp an object)
......
[package]
# Note: Semantic Versioning is used: https://semver.org/
version = "0.45.11"
version = "0.45.12"
# Description
title = "Isaac Lab framework for Robot Learning"
......
Changelog
---------
0.45.12 (2025-09-05)
~~~~~~~~~~~~~~~~~~~~
Added
^^^^^
* Added :class:`~isaaclab.envs.mdp.actions.SurfaceGripperBinaryAction` for supporting surface grippers in Manager-Based workflows.
Changed
^^^^^^^
* Added AssetBase inheritance for :class:`~isaaclab.assets.surface_gripper.SurfaceGripper`
0.45.11 (2025-09-04)
~~~~~~~~~~~~~~~~~~~~
......
......@@ -9,6 +9,7 @@ import torch
import warnings
from typing import TYPE_CHECKING
import omni.log
from isaacsim.core.utils.extensions import enable_extension
from isaacsim.core.version import get_version
......@@ -18,7 +19,7 @@ from isaaclab.assets import AssetBase
if TYPE_CHECKING:
from isaacsim.robot.surface_gripper import GripperView
from .surface_gripper_cfg import SurfaceGripperCfg
from .surface_gripper_cfg import SurfaceGripperCfg
class SurfaceGripper(AssetBase):
......@@ -246,7 +247,7 @@ class SurfaceGripper(AssetBase):
Raises:
ValueError: If the simulation backend is not CPU.
RuntimeError: If the Simulation Context is not initialized.
RuntimeError: If the Simulation Context is not initialized or if gripper prims are not found.
Note:
The SurfaceGripper is only supported on CPU for now. Please set the simulation backend to run on CPU.
......@@ -262,8 +263,35 @@ class SurfaceGripper(AssetBase):
"SurfaceGripper is only supported on CPU for now. Please set the simulation backend to run on CPU. Use"
" `--device cpu` to run the simulation on CPU."
)
# obtain the first prim in the regex expression (all others are assumed to be a copy of this)
template_prim = sim_utils.find_first_matching_prim(self._cfg.prim_path)
if template_prim is None:
raise RuntimeError(f"Failed to find prim for expression: '{self._cfg.prim_path}'.")
template_prim_path = template_prim.GetPath().pathString
# find surface gripper prims
gripper_prims = sim_utils.get_all_matching_child_prims(
template_prim_path, predicate=lambda prim: prim.GetTypeName() == "IsaacSurfaceGripper"
)
if len(gripper_prims) == 0:
raise RuntimeError(
f"Failed to find a surface gripper when resolving '{self._cfg.prim_path}'."
" Please ensure that the prim has type 'IsaacSurfaceGripper'."
)
if len(gripper_prims) > 1:
raise RuntimeError(
f"Failed to find a single surface gripper when resolving '{self._cfg.prim_path}'."
f" Found multiple '{gripper_prims}' under '{template_prim_path}'."
" Please ensure that there is only one surface gripper in the prim path tree."
)
# resolve gripper prim back into regex expression
gripper_prim_path = gripper_prims[0].GetPath().pathString
gripper_prim_path_expr = self._cfg.prim_path + gripper_prim_path[len(template_prim_path) :]
# Count number of environments
self._prim_expr = self._cfg.prim_expr
self._prim_expr = gripper_prim_path_expr
env_prim_path_expr = self._prim_expr.rsplit("/", 1)[0]
self._parent_prims = sim_utils.find_matching_prims(env_prim_path_expr)
self._num_envs = len(self._parent_prims)
......@@ -287,6 +315,10 @@ class SurfaceGripper(AssetBase):
retry_interval=self._retry_interval.clone(),
)
# log information about the surface gripper
omni.log.info(f"Surface gripper initialized at: {self._cfg.prim_path} with root '{gripper_prim_path_expr}'.")
omni.log.info(f"Number of instances: {self._num_envs}")
# Reset grippers
self.reset()
......
......@@ -7,12 +7,15 @@ from dataclasses import MISSING
from isaaclab.utils import configclass
from ..asset_base_cfg import AssetBaseCfg
from .surface_gripper import SurfaceGripper
@configclass
class SurfaceGripperCfg:
class SurfaceGripperCfg(AssetBaseCfg):
"""Configuration parameters for a surface gripper actuator."""
prim_expr: str = MISSING
prim_path: str = MISSING
"""The expression to find the grippers in the stage."""
max_grip_distance: float | None = None
......@@ -26,3 +29,5 @@ class SurfaceGripperCfg:
retry_interval: float | None = None
"""The amount of time the gripper will spend trying to grasp an object."""
class_type: type = SurfaceGripper
......@@ -9,7 +9,14 @@ from isaaclab.controllers import DifferentialIKControllerCfg, OperationalSpaceCo
from isaaclab.managers.action_manager import ActionTerm, ActionTermCfg
from isaaclab.utils import configclass
from . import binary_joint_actions, joint_actions, joint_actions_to_limits, non_holonomic_actions, task_space_actions
from . import (
binary_joint_actions,
joint_actions,
joint_actions_to_limits,
non_holonomic_actions,
surface_gripper_actions,
task_space_actions,
)
##
# Joint actions.
......@@ -310,3 +317,25 @@ class OperationalSpaceControllerActionCfg(ActionTermCfg):
Note: Functional only when ``nullspace_control`` is set to ``"position"`` within the
``OperationalSpaceControllerCfg``.
"""
##
# Surface Gripper actions.
##
@configclass
class SurfaceGripperBinaryActionCfg(ActionTermCfg):
"""Configuration for the binary surface gripper action term.
See :class:`SurfaceGripperBinaryAction` for more details.
"""
asset_name: str = MISSING
"""Name of the surface gripper asset in the scene."""
open_command: float = -1.0
"""The command value to open the gripper. Defaults to -1.0."""
close_command: float = 1.0
"""The command value to close the gripper. Defaults to 1.0."""
class_type: type[ActionTerm] = surface_gripper_actions.SurfaceGripperBinaryAction
# Copyright (c) 2022-2025, 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 __future__ import annotations
import torch
from collections.abc import Sequence
from typing import TYPE_CHECKING
import omni.log
from isaaclab.assets.surface_gripper import SurfaceGripper
from isaaclab.managers.action_manager import ActionTerm
if TYPE_CHECKING:
from isaaclab.envs import ManagerBasedEnv
from . import actions_cfg
class SurfaceGripperBinaryAction(ActionTerm):
"""Surface gripper binary action.
This action term maps a binary action to the *open* or *close* surface gripper configurations.
The surface gripper behavior is as follows:
- [-1, -0.3] --> Gripper is Opening
- [-0.3, 0.3] --> Gripper is Idle (do nothing)
- [0.3, 1] --> Gripper is Closing
Based on above, we follow the following convention for the binary action:
1. Open action: 1 (bool) or positive values (float).
2. Close action: 0 (bool) or negative values (float).
The action term is specifically designed for surface grippers, which use a different
interface than joint-based grippers.
"""
cfg: actions_cfg.SurfaceGripperBinaryActionCfg
"""The configuration of the action term."""
_asset: SurfaceGripper
"""The surface gripper asset on which the action term is applied."""
def __init__(self, cfg: actions_cfg.SurfaceGripperBinaryActionCfg, env: ManagerBasedEnv) -> None:
# initialize the action term
super().__init__(cfg, env)
# log the resolved asset name for debugging
omni.log.info(
f"Resolved surface gripper asset for the action term {self.__class__.__name__}: {self.cfg.asset_name}"
)
# create tensors for raw and processed actions
self._raw_actions = torch.zeros(self.num_envs, 1, device=self.device)
self._processed_actions = torch.zeros(self.num_envs, 1, device=self.device)
# parse open command
self._open_command = torch.tensor(self.cfg.open_command, device=self.device)
# parse close command
self._close_command = torch.tensor(self.cfg.close_command, device=self.device)
"""
Properties.
"""
@property
def action_dim(self) -> int:
return 1
@property
def raw_actions(self) -> torch.Tensor:
return self._raw_actions
@property
def processed_actions(self) -> torch.Tensor:
return self._processed_actions
"""
Operations.
"""
def process_actions(self, actions: torch.Tensor):
# store the raw actions
self._raw_actions[:] = actions
# compute the binary mask
if actions.dtype == torch.bool:
# true: close, false: open
binary_mask = actions == 0
else:
# true: close, false: open
binary_mask = actions < 0
# compute the command
self._processed_actions = torch.where(binary_mask, self._close_command, self._open_command)
def apply_actions(self):
"""Apply the processed actions to the surface gripper."""
self._asset.set_grippers_command(self._processed_actions.view(-1))
self._asset.write_data_to_sim()
def reset(self, env_ids: Sequence[int] | None = None) -> None:
if env_ids is None:
self._raw_actions[:] = 0.0
else:
self._raw_actions[env_ids] = 0.0
......@@ -554,9 +554,9 @@ class InteractiveScene:
rigid_object.write_root_pose_to_sim(root_pose, env_ids=env_ids)
rigid_object.write_root_velocity_to_sim(root_velocity, env_ids=env_ids)
# surface grippers
for asset_name, gripper in self._surface_grippers.items():
for asset_name, surface_gripper in self._surface_grippers.items():
asset_state = state["gripper"][asset_name]
gripper.write_gripper_state_to_sim(asset_state, env_ids=env_ids)
surface_gripper.set_grippers_command(asset_state)
# write data to simulation to make sure initial state is set
# this propagates the joint targets to the simulation
......@@ -643,6 +643,10 @@ class InteractiveScene:
asset_state["root_pose"][:, :3] -= self.env_origins
asset_state["root_velocity"] = rigid_object.data.root_vel_w.clone()
state["rigid_object"][asset_name] = asset_state
# surface grippers
state["gripper"] = dict()
for asset_name, gripper in self._surface_grippers.items():
state["gripper"][asset_name] = gripper.state.clone()
return state
"""
......@@ -749,7 +753,8 @@ class InteractiveScene:
asset_paths = sim_utils.find_matching_prim_paths(rigid_object_cfg.prim_path)
self._global_prim_paths += asset_paths
elif isinstance(asset_cfg, SurfaceGripperCfg):
pass
# add surface grippers to scene
self._surface_grippers[asset_name] = asset_cfg.class_type(asset_cfg)
elif isinstance(asset_cfg, SensorBaseCfg):
# Update target frame path(s)' regex name space for FrameTransformer
if isinstance(asset_cfg, FrameTransformerCfg):
......
......@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: BSD-3-Clause
"""Configuration for the Universal Robots.
The following configuration parameters are available:
......@@ -21,7 +22,6 @@ from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR, ISAACLAB_NUCLEUS_DIR
# Configuration
##
UR10_CFG = ArticulationCfg(
spawn=sim_utils.UsdFileCfg(
usd_path=f"{ISAACLAB_NUCLEUS_DIR}/Robots/UniversalRobots/UR10/ur10_instanceable.usd",
......@@ -102,3 +102,23 @@ UR10e_CFG = ArticulationCfg(
)
"""Configuration of UR-10 arm using implicit actuator models."""
UR10_LONG_SUCTION_CFG = UR10_CFG.copy()
UR10_LONG_SUCTION_CFG.spawn.usd_path = f"{ISAAC_NUCLEUS_DIR}/Robots/UniversalRobots/ur10/ur10.usd"
UR10_LONG_SUCTION_CFG.spawn.variants = {"Gripper": "Long_Suction"}
UR10_LONG_SUCTION_CFG.spawn.rigid_props.disable_gravity = True
UR10_LONG_SUCTION_CFG.init_state.joint_pos = {
"shoulder_pan_joint": 0.0,
"shoulder_lift_joint": -1.5707,
"elbow_joint": 1.5707,
"wrist_1_joint": -1.5707,
"wrist_2_joint": 1.5707,
"wrist_3_joint": 0.0,
}
"""Configuration of UR10 arm with long suction gripper."""
UR10_SHORT_SUCTION_CFG = UR10_LONG_SUCTION_CFG.copy()
UR10_SHORT_SUCTION_CFG.spawn.variants = {"Gripper": "Short_Suction"}
"""Configuration of UR10 arm with short suction gripper."""
[package]
# Note: Semantic Versioning is used: https://semver.org/
version = "0.10.48"
version = "0.10.49"
# Description
title = "Isaac Lab Environments"
......
Changelog
---------
0.10.49 (2025-09-05)
~~~~~~~~~~~~~~~~~~~~
Added
^^^^^
* Added suction gripper stacking environments with UR10 that can be used with teleoperation.
0.10.48 (2025-09-03)
~~~~~~~~~~~~~~~~~~~~
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
import gymnasium as gym
from . import stack_ik_rel_env_cfg
##
# Register Gym environments.
##
##
# Inverse Kinematics - Relative Pose Control
##
gym.register(
id="Isaac-Stack-Cube-UR10-Long-Suction-IK-Rel-v0",
entry_point="isaaclab.envs:ManagerBasedRLEnv",
kwargs={
"env_cfg_entry_point": stack_ik_rel_env_cfg.UR10LongSuctionCubeStackEnvCfg,
},
disable_env_checker=True,
)
gym.register(
id="Isaac-Stack-Cube-UR10-Short-Suction-IK-Rel-v0",
entry_point="isaaclab.envs:ManagerBasedRLEnv",
kwargs={
"env_cfg_entry_point": stack_ik_rel_env_cfg.UR10ShortSuctionCubeStackEnvCfg,
},
disable_env_checker=True,
)
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2022-2025, 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 isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg
from isaaclab.devices.device_base import DevicesCfg
from isaaclab.devices.keyboard import Se3KeyboardCfg
from isaaclab.devices.spacemouse import Se3SpaceMouseCfg
from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg
from isaaclab.utils import configclass
from . import stack_joint_pos_env_cfg
@configclass
class UR10LongSuctionCubeStackEnvCfg(stack_joint_pos_env_cfg.UR10LongSuctionCubeStackEnvCfg):
def __post_init__(self):
# post init of parent
super().__post_init__()
# Set actions for the specific robot type (UR10 LONG SUCTION)
self.actions.arm_action = DifferentialInverseKinematicsActionCfg(
asset_name="robot",
joint_names=[".*_joint"],
body_name="ee_link",
controller=DifferentialIKControllerCfg(command_type="pose", use_relative_mode=True, ik_method="dls"),
scale=1.0,
body_offset=DifferentialInverseKinematicsActionCfg.OffsetCfg(pos=[0.0, 0.0, -0.22]),
)
self.teleop_devices = DevicesCfg(
devices={
"keyboard": Se3KeyboardCfg(
pos_sensitivity=0.02,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
"spacemouse": Se3SpaceMouseCfg(
pos_sensitivity=0.05,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
}
)
@configclass
class UR10ShortSuctionCubeStackEnvCfg(stack_joint_pos_env_cfg.UR10ShortSuctionCubeStackEnvCfg):
def __post_init__(self):
# post init of parent
super().__post_init__()
# Set actions for the specific robot type (UR10 SHORT SUCTION)
self.actions.arm_action = DifferentialInverseKinematicsActionCfg(
asset_name="robot",
joint_names=[".*_joint"],
body_name="ee_link",
controller=DifferentialIKControllerCfg(command_type="pose", use_relative_mode=True, ik_method="dls"),
scale=1.0,
body_offset=DifferentialInverseKinematicsActionCfg.OffsetCfg(pos=[0.0, 0.0, -0.159]),
)
self.teleop_devices = DevicesCfg(
devices={
"keyboard": Se3KeyboardCfg(
pos_sensitivity=0.02,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
"spacemouse": Se3SpaceMouseCfg(
pos_sensitivity=0.05,
rot_sensitivity=0.05,
sim_device=self.sim.device,
),
}
)
# Copyright (c) 2022-2025, 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 isaaclab.assets import RigidObjectCfg, SurfaceGripperCfg
from isaaclab.envs.mdp.actions.actions_cfg import SurfaceGripperBinaryActionCfg
from isaaclab.managers import EventTermCfg as EventTerm
from isaaclab.managers import SceneEntityCfg
from isaaclab.sensors import FrameTransformerCfg
from isaaclab.sensors.frame_transformer.frame_transformer_cfg import OffsetCfg
from isaaclab.sim.schemas.schemas_cfg import RigidBodyPropertiesCfg
from isaaclab.sim.spawners.from_files.from_files_cfg import UsdFileCfg
from isaaclab.utils import configclass
from isaaclab.utils.assets import ISAAC_NUCLEUS_DIR
from isaaclab_tasks.manager_based.manipulation.stack import mdp
from isaaclab_tasks.manager_based.manipulation.stack.mdp import franka_stack_events
from isaaclab_tasks.manager_based.manipulation.stack.stack_env_cfg import StackEnvCfg
from isaaclab_assets.robots.universal_robots import ( # isort: skip
UR10_LONG_SUCTION_CFG,
UR10_SHORT_SUCTION_CFG,
)
##
# Pre-defined configs
##
from isaaclab.markers.config import FRAME_MARKER_CFG # isort: skip
@configclass
class EventCfgLongSuction:
"""Configuration for events."""
init_franka_arm_pose = EventTerm(
func=franka_stack_events.set_default_joint_pose,
mode="reset",
params={
"default_pose": [0.0, -1.5707, 1.5707, -1.5707, -1.5707, 0.0],
},
)
randomize_franka_joint_state = EventTerm(
func=franka_stack_events.randomize_joint_by_gaussian_offset,
mode="reset",
params={
"mean": 0.0,
"std": 0.02,
"asset_cfg": SceneEntityCfg("robot"),
},
)
randomize_cube_positions = EventTerm(
func=franka_stack_events.randomize_object_pose,
mode="reset",
params={
"pose_range": {"x": (0.4, 0.6), "y": (-0.10, 0.10), "z": (0.0203, 0.0203), "yaw": (-1.0, 1.0, 0)},
"min_separation": 0.1,
"asset_cfgs": [SceneEntityCfg("cube_1"), SceneEntityCfg("cube_2"), SceneEntityCfg("cube_3")],
},
)
@configclass
class UR10CubeStackEnvCfg(StackEnvCfg):
# Rigid body properties of each cube
cube_properties = RigidBodyPropertiesCfg(
solver_position_iteration_count=16,
solver_velocity_iteration_count=1,
max_angular_velocity=1000.0,
max_linear_velocity=1000.0,
max_depenetration_velocity=5.0,
disable_gravity=False,
)
cube_scale = (1.0, 1.0, 1.0)
# Listens to the required transforms
marker_cfg = FRAME_MARKER_CFG.copy()
marker_cfg.markers["frame"].scale = (0.1, 0.1, 0.1)
marker_cfg.prim_path = "/Visuals/FrameTransformer"
def __post_init__(self):
# post init of parent
super().__post_init__()
# Set events
self.events = EventCfgLongSuction()
# Set actions for the specific robot type (ur10)
self.actions.arm_action = mdp.JointPositionActionCfg(
asset_name="robot", joint_names=[".*_joint"], scale=0.5, use_default_offset=True
)
# Set surface gripper action
self.actions.gripper_action = SurfaceGripperBinaryActionCfg(
asset_name="surface_gripper",
open_command=-1.0,
close_command=1.0,
)
# Set each stacking cube deterministically
self.scene.cube_1 = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Cube_1",
init_state=RigidObjectCfg.InitialStateCfg(pos=[0.4, 0.0, 0.0203], rot=[1, 0, 0, 0]),
spawn=UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/blue_block.usd",
scale=self.cube_scale,
rigid_props=self.cube_properties,
),
)
self.scene.cube_2 = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Cube_2",
init_state=RigidObjectCfg.InitialStateCfg(pos=[0.55, 0.05, 0.0203], rot=[1, 0, 0, 0]),
spawn=UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/red_block.usd",
scale=self.cube_scale,
rigid_props=self.cube_properties,
),
)
self.scene.cube_3 = RigidObjectCfg(
prim_path="{ENV_REGEX_NS}/Cube_3",
init_state=RigidObjectCfg.InitialStateCfg(pos=[0.60, -0.1, 0.0203], rot=[1, 0, 0, 0]),
spawn=UsdFileCfg(
usd_path=f"{ISAAC_NUCLEUS_DIR}/Props/Blocks/green_block.usd",
scale=self.cube_scale,
rigid_props=self.cube_properties,
),
)
self.decimation = 5
self.episode_length_s = 30.0
# simulation settings
self.sim.dt = 0.01 # 100Hz
self.sim.render_interval = 5
@configclass
class UR10LongSuctionCubeStackEnvCfg(UR10CubeStackEnvCfg):
def __post_init__(self):
# post init of parent
super().__post_init__()
# Set events
self.events = EventCfgLongSuction()
# Set UR10 as robot
self.scene.robot = UR10_LONG_SUCTION_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
# Set surface gripper: Ensure the SurfaceGripper prim has the required attributes
self.scene.surface_gripper = SurfaceGripperCfg(
prim_path="{ENV_REGEX_NS}/Robot/ee_link/SurfaceGripper",
max_grip_distance=0.05,
shear_force_limit=5000.0,
coaxial_force_limit=5000.0,
retry_interval=0.05,
)
self.scene.ee_frame = FrameTransformerCfg(
prim_path="{ENV_REGEX_NS}/Robot/base_link",
debug_vis=True,
visualizer_cfg=self.marker_cfg,
target_frames=[
FrameTransformerCfg.FrameCfg(
prim_path="{ENV_REGEX_NS}/Robot/ee_link",
name="end_effector",
offset=OffsetCfg(
pos=[0.22, 0.0, 0.0],
),
),
],
)
@configclass
class UR10ShortSuctionCubeStackEnvCfg(UR10CubeStackEnvCfg):
def __post_init__(self):
# post init of parent
super().__post_init__()
# Set UR10 as robot
self.scene.robot = UR10_SHORT_SUCTION_CFG.replace(prim_path="{ENV_REGEX_NS}/Robot")
# Set surface gripper: Ensure the SurfaceGripper prim has the required attributes
self.scene.surface_gripper = SurfaceGripperCfg(
prim_path="{ENV_REGEX_NS}/Robot/ee_link/SurfaceGripper",
max_grip_distance=0.05,
shear_force_limit=5000.0,
coaxial_force_limit=5000.0,
retry_interval=0.05,
)
self.scene.ee_frame = FrameTransformerCfg(
prim_path="{ENV_REGEX_NS}/Robot/base_link",
debug_vis=True,
visualizer_cfg=self.marker_cfg,
target_frames=[
FrameTransformerCfg.FrameCfg(
prim_path="{ENV_REGEX_NS}/Robot/ee_link",
name="end_effector",
offset=OffsetCfg(
pos=[0.1585, 0.0, 0.0],
),
),
],
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment