diff --git a/docs/source/api/lab/isaaclab.devices.rst b/docs/source/api/lab/isaaclab.devices.rst index 5f04c4733cf..a24bf33e8f1 100644 --- a/docs/source/api/lab/isaaclab.devices.rst +++ b/docs/source/api/lab/isaaclab.devices.rst @@ -18,16 +18,15 @@ HaplyDevice OpenXRDevice ManusVive - isaaclab.devices.openxr.retargeters.GripperRetargeter - isaaclab.devices.openxr.retargeters.Se3AbsRetargeter - isaaclab.devices.openxr.retargeters.Se3RelRetargeter - isaaclab.devices.openxr.retargeters.GR1T2Retargeter + isaaclab.devices.retargeters.GripperRetargeter + isaaclab.devices.retargeters.Se3AbsRetargeter + isaaclab.devices.retargeters.Se3RelRetargeter .. rubric:: Modules .. autosummary:: - isaaclab.devices.openxr.retargeters + isaaclab.devices.retargeters Device Base ----------- @@ -116,25 +115,19 @@ Manus + Vive Retargeters ----------- -.. autoclass:: isaaclab.devices.openxr.retargeters.GripperRetargeter +.. autoclass:: isaaclab.devices.retargeters.GripperRetargeter :members: :inherited-members: :show-inheritance: :noindex: -.. autoclass:: isaaclab.devices.openxr.retargeters.Se3AbsRetargeter +.. autoclass:: isaaclab.devices.retargeters.Se3AbsRetargeter :members: :inherited-members: :show-inheritance: :noindex: -.. autoclass:: isaaclab.devices.openxr.retargeters.Se3RelRetargeter - :members: - :inherited-members: - :show-inheritance: - :noindex: - -.. autoclass:: isaaclab.devices.openxr.retargeters.GR1T2Retargeter +.. autoclass:: isaaclab.devices.retargeters.Se3RelRetargeter :members: :inherited-members: :show-inheritance: diff --git a/docs/source/how-to/cloudxr_teleoperation.rst b/docs/source/how-to/cloudxr_teleoperation.rst index d05e1656f40..638d6d6982e 100644 --- a/docs/source/how-to/cloudxr_teleoperation.rst +++ b/docs/source/how-to/cloudxr_teleoperation.rst @@ -680,33 +680,21 @@ the OpenXRDevice during initialization. Isaac Lab provides three main retargeters for hand tracking: -.. dropdown:: Se3RelRetargeter (:class:`isaaclab.devices.openxr.retargeters.Se3RelRetargeter`) +.. dropdown:: Se3RelRetargeter (:class:`isaaclab.devices.retargeters.Se3RelRetargeter`) * Generates incremental robot commands from relative hand movements * Best for precise manipulation tasks -.. dropdown:: Se3AbsRetargeter (:class:`isaaclab.devices.openxr.retargeters.Se3AbsRetargeter`) +.. dropdown:: Se3AbsRetargeter (:class:`isaaclab.devices.retargeters.Se3AbsRetargeter`) * Maps hand position directly to robot end-effector position * Enables 1:1 spatial control -.. dropdown:: GripperRetargeter (:class:`isaaclab.devices.openxr.retargeters.GripperRetargeter`) +.. dropdown:: GripperRetargeter (:class:`isaaclab.devices.retargeters.GripperRetargeter`) * Controls gripper state based on thumb-index finger distance * Used alongside position retargeters for full robot control -.. dropdown:: GR1T2Retargeter (:class:`isaaclab.devices.openxr.retargeters.GR1T2Retargeter`) - - * Retargets OpenXR hand tracking data to GR1T2 hand end-effector commands - * Handles both left and right hands, converting hand poses to joint angles for the GR1T2 robot's hands - * Supports visualization of tracked hand joints - -.. dropdown:: UnitreeG1Retargeter (:class:`isaaclab.devices.openxr.retargeters.UnitreeG1Retargeter`) - - * Retargets OpenXR hand tracking data to Unitree G1 using Inspire 5-finger hand end-effector commands - * Handles both left and right hands, converting hand poses to joint angles for the G1 robot's hands - * Supports visualization of tracked hand joints - Retargeters can be combined to control different robot functions simultaneously. Using Retargeters with Hand Tracking @@ -717,7 +705,7 @@ Here's an example of setting up hand tracking: .. code-block:: python from isaaclab.devices import OpenXRDevice, OpenXRDeviceCfg - from isaaclab.devices.openxr.retargeters import Se3AbsRetargeter, GripperRetargeter + from isaaclab.devices.retargeters import Se3AbsRetargeter, GripperRetargeter # Create retargeters position_retargeter = Se3AbsRetargeter( @@ -796,7 +784,7 @@ XR-based teleoperation can be integrated with Isaac Lab's environment configurat from isaaclab.envs import ManagerBasedEnvCfg from isaaclab.devices import DevicesCfg, OpenXRDeviceCfg from isaaclab.devices.openxr import XrCfg - from isaaclab.devices.openxr.retargeters import Se3AbsRetargeterCfg, GripperRetargeterCfg + from isaaclab.devices.retargeters import Se3AbsRetargeterCfg, GripperRetargeterCfg @configclass class MyEnvironmentCfg(ManagerBasedEnvCfg): diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/__init__.py b/source/isaaclab/isaaclab/devices/openxr/retargeters/__init__.py index d4e12bd40ed..06d5d319d77 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/__init__.py +++ b/source/isaaclab/isaaclab/devices/openxr/retargeters/__init__.py @@ -2,23 +2,20 @@ # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause -"""Retargeters for mapping input device data to robot commands.""" -from .humanoid.fourier.gr1t2_retargeter import GR1T2Retargeter, GR1T2RetargeterCfg -from .humanoid.unitree.g1_lower_body_standing import G1LowerBodyStandingRetargeter, G1LowerBodyStandingRetargeterCfg -from .humanoid.unitree.g1_motion_controller_locomotion import ( - G1LowerBodyStandingMotionControllerRetargeter, - G1LowerBodyStandingMotionControllerRetargeterCfg, -) -from .humanoid.unitree.inspire.g1_upper_body_retargeter import UnitreeG1Retargeter, UnitreeG1RetargeterCfg -from .humanoid.unitree.trihand.g1_upper_body_motion_ctrl_retargeter import ( - G1TriHandUpperBodyMotionControllerRetargeter, - G1TriHandUpperBodyMotionControllerRetargeterCfg, -) -from .humanoid.unitree.trihand.g1_upper_body_retargeter import ( - G1TriHandUpperBodyRetargeter, - G1TriHandUpperBodyRetargeterCfg, +""" +Backward compatibility shim for retargeters. + +.. warning:: + This module is deprecated. Please use :mod:`isaaclab.devices.retargeters` instead. +""" + +import warnings + +from isaaclab.devices.retargeters import * # noqa: F401, F403 + +warnings.warn( + "isaaclab.devices.openxr.retargeters has moved to isaaclab.devices.retargeters. Please update your imports.", + DeprecationWarning, + stacklevel=2, ) -from .manipulator.gripper_retargeter import GripperRetargeter, GripperRetargeterCfg -from .manipulator.se3_abs_retargeter import Se3AbsRetargeter, Se3AbsRetargeterCfg -from .manipulator.se3_rel_retargeter import Se3RelRetargeter, Se3RelRetargeterCfg diff --git a/source/isaaclab/isaaclab/devices/retargeters/__init__.py b/source/isaaclab/isaaclab/devices/retargeters/__init__.py new file mode 100644 index 00000000000..1d1a0d3e93a --- /dev/null +++ b/source/isaaclab/isaaclab/devices/retargeters/__init__.py @@ -0,0 +1,21 @@ +# 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 +"""Retargeters for mapping input device data to robot commands.""" + +from .dex.dex_hand_retargeter import ( + DexBiManualRetargeter, + DexBiManualRetargeterCfg, + DexHandRetargeter, + DexHandRetargeterCfg, +) +from .dex.dex_motion_controller import DexMotionController, DexMotionControllerCfg +from .locomotion.locomotion_fixed_root_cmd_retargeter import ( + LocomotionFixedRootCmdRetargeter, + LocomotionFixedRootCmdRetargeterCfg, +) +from .locomotion.locomotion_root_cmd_retargeter import LocomotionRootCmdRetargeter, LocomotionRootCmdRetargeterCfg +from .manipulator.gripper_retargeter import GripperRetargeter, GripperRetargeterCfg +from .manipulator.se3_abs_retargeter import Se3AbsRetargeter, Se3AbsRetargeterCfg +from .manipulator.se3_rel_retargeter import Se3RelRetargeter, Se3RelRetargeterCfg diff --git a/source/isaaclab/isaaclab/devices/retargeters/dex/__init__.py b/source/isaaclab/isaaclab/devices/retargeters/dex/__init__.py new file mode 100644 index 00000000000..7e1ea406a2f --- /dev/null +++ b/source/isaaclab/isaaclab/devices/retargeters/dex/__init__.py @@ -0,0 +1,7 @@ +# 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 .dex_hand_retargeter import DexHandRetargeter, DexHandRetargeterCfg +from .dex_motion_controller import DexMotionController, DexMotionControllerCfg diff --git a/source/isaaclab/isaaclab/devices/retargeters/dex/dex_hand_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/dex/dex_hand_retargeter.py new file mode 100644 index 00000000000..e50e638da33 --- /dev/null +++ b/source/isaaclab/isaaclab/devices/retargeters/dex/dex_hand_retargeter.py @@ -0,0 +1,292 @@ +# 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 contextlib +import numpy as np +import torch +import yaml +from dataclasses import MISSING, dataclass +from scipy.spatial.transform import Rotation as R + +import isaaclab.sim as sim_utils +from isaaclab.devices.device_base import DeviceBase +from isaaclab.devices.retargeter_base import RetargeterBase, RetargeterCfg +from isaaclab.markers import VisualizationMarkers, VisualizationMarkersCfg +from isaaclab.utils.assets import retrieve_file_path + +# Helper to import dex_retargeting which might not be available on all platforms +with contextlib.suppress(ImportError): + from dex_retargeting.retargeting_config import RetargetingConfig + + +class DexHandRetargeter(RetargeterBase): + """Generic retargeter for dexterous hands using the dex_retargeting library. + + This class wraps the dex_retargeting library to retarget OpenXR hand tracking data + to robot hand joint angles. It supports configuration via YAML files and URDFs. + """ + + def __init__(self, cfg: DexHandRetargeterCfg): + """Initialize the retargeter. + + Args: + cfg: Configuration for the retargeter. + """ + super().__init__(cfg) + + # Check if dex_retargeting is available + if "dex_retargeting" not in globals() and "RetargetingConfig" not in globals(): + raise ImportError("The 'dex_retargeting' package is required but not installed.") + + self._sim_device = cfg.sim_device + self._hand_joint_names = cfg.hand_joint_names + self._target = cfg.target + + # Setup paths + self._prepare_configs(cfg) + + # Initialize dex retargeting optimizer + self._dex_hand = RetargetingConfig.load_from_file(cfg.hand_retargeting_config).build() + + # Cache joint names from optimizer + self._dof_names = self._dex_hand.optimizer.robot.dof_joint_names + + # Store transforms + self._handtracking2baselink = np.array(cfg.handtracking_to_baselink_frame_transform).reshape(3, 3) + + # Map OpenXR joints (26) to Dex-retargeting (21) + # Indices: [Wrist, Thumb(4), Index(4), Middle(4), Ring(4), Pinky(4)] + # OpenXR: Wrist(1), Thumb(4), Index(5), Middle(5), Ring(5), Pinky(5) + # Note: We skip the metacarpal for non-thumb fingers in OpenXR if needed, + # but here we use the standard mapping from existing utils. + self._hand_joints_index = [1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 22, 23, 24, 25] + + # Visualization + self._enable_visualization = cfg.enable_visualization + self._num_open_xr_hand_joints = cfg.num_open_xr_hand_joints + if self._enable_visualization: + marker_cfg = VisualizationMarkersCfg( + prim_path=f"/Visuals/dex_hand_markers_{self._target.name}", + markers={ + "joint": sim_utils.SphereCfg( + radius=0.005, + visual_material=sim_utils.PreviewSurfaceCfg(diffuse_color=(1.0, 0.0, 0.0)), + ), + }, + ) + self._markers = VisualizationMarkers(marker_cfg) + + def retarget(self, data: dict) -> torch.Tensor: + """Process input data and return retargeted joint angles. + + Args: + data: Dictionary mapping tracking targets to joint data dictionaries. + + Returns: + torch.Tensor: Tensor of hand joint angles. + """ + hand_poses = data.get(self._target) + + # Visualization + if self._enable_visualization and hand_poses: + # Visualize the raw tracked points + joints_position = np.array([pose[:3] for pose in hand_poses.values()]) + self._markers.visualize( + translations=torch.tensor(joints_position, device=self._sim_device, dtype=torch.float32) + ) + + # Compute + q = self._compute_hand(hand_poses, self._dex_hand, self._handtracking2baselink) + + # Map to output vector based on configured joint names + retargeted_joints = np.zeros(len(self._hand_joint_names)) + + for i, name in enumerate(self._dof_names): + if name in self._hand_joint_names: + idx = self._hand_joint_names.index(name) + retargeted_joints[idx] = q[i] + + return torch.tensor(retargeted_joints, dtype=torch.float32, device=self._sim_device) + + def get_requirements(self) -> list[RetargeterBase.Requirement]: + return [RetargeterBase.Requirement.HAND_TRACKING] + + # -- Internal Helpers -- + + def _prepare_configs(self, cfg: DexHandRetargeterCfg): + """Downloads URDFs if needed and updates YAML config files.""" + # Retrieve URDF (downloads if URL, returns path if local) + local_urdf = retrieve_file_path(cfg.hand_urdf, force_download=True) + + # Update YAML + self._update_yaml(cfg.hand_retargeting_config, local_urdf) + + def _update_yaml(self, yaml_path: str, urdf_path: str): + """Updates the 'urdf_path' field in the retargeting YAML config.""" + try: + with open(yaml_path) as f: + config = yaml.safe_load(f) + + if "retargeting" in config: + config["retargeting"]["urdf_path"] = urdf_path + with open(yaml_path, "w") as f: + yaml.dump(config, f) + except Exception as e: + print(f"[DexHandRetargeter] Error updating YAML {yaml_path}: {e}") + + def _compute_hand(self, poses: dict | None, retargeting: RetargetingConfig, op2mano: np.ndarray) -> np.ndarray: + """Computes retargeting for a single hand.""" + if poses is None: + return np.zeros(len(retargeting.optimizer.robot.dof_joint_names)) + + # 1. Extract positions for relevant joints + hand_joints = list(poses.values()) + joint_pos = np.zeros((21, 3)) + for i, idx in enumerate(self._hand_joints_index): + joint_pos[i] = hand_joints[idx][:3] + + # 2. Transform to canonical frame + # Center at wrist (index 0 of our subset, which maps to OpenXR 'wrist' at index 1) + joint_pos = joint_pos - joint_pos[0:1, :] + + # Apply wrist rotation alignment (OpenXR w,x,y,z -> Scipy x,y,z,w) + wrist_pose = poses.get("wrist") + if wrist_pose is None: + return np.zeros(len(retargeting.optimizer.robot.dof_joint_names)) + xr_wrist_quat = wrist_pose[3:] + wrist_rot = R.from_quat([xr_wrist_quat[1], xr_wrist_quat[2], xr_wrist_quat[3], xr_wrist_quat[0]]).as_matrix() + + target_pos = joint_pos @ wrist_rot @ op2mano + + # 3. Compute reference value for optimizer + indices = retargeting.optimizer.target_link_human_indices + if retargeting.optimizer.retargeting_type == "POSITION": + ref_value = target_pos[indices, :] + else: + origin_indices = indices[0, :] + task_indices = indices[1, :] + ref_value = target_pos[task_indices, :] - target_pos[origin_indices, :] + + # 4. Run optimizer + with torch.enable_grad(), torch.inference_mode(False): + return retargeting.retarget(ref_value) + + +@dataclass(kw_only=True) +class DexHandRetargeterCfg(RetargeterCfg): + """Configuration for the generic dexterous hand retargeter.""" + + retargeter_type: type[RetargeterBase] = DexHandRetargeter + + # Target Hand + target: DeviceBase.TrackingTarget = MISSING + + # Joint Names + hand_joint_names: list[str] = MISSING + + # Config Paths + hand_retargeting_config: str = MISSING + hand_urdf: str = MISSING + + # Transforms (3x3 matrix flattened to 9 elements) + # Default: G1/Inspire coordinate frame + handtracking_to_baselink_frame_transform: tuple[float, ...] = (0, 0, 1, 1, 0, 0, 0, 1, 0) + + enable_visualization: bool = False + num_open_xr_hand_joints: int = 26 + + +class DexBiManualRetargeter(RetargeterBase): + """Wrapper around two DexHandRetargeters to support bimanual retargeting with custom joint ordering. + + This class instantiates two :class:`DexHandRetargeter` instances (one for each hand) and combines + their outputs into a single vector ordered according to `target_joint_names`. + """ + + def __init__(self, cfg: DexBiManualRetargeterCfg): + """Initialize the retargeter. + + Args: + cfg: Configuration for the retargeter. + """ + super().__init__(cfg) + self._sim_device = cfg.sim_device + + # Initialize individual retargeters + self._left_retargeter = DexHandRetargeter(cfg.left_hand_cfg) + self._right_retargeter = DexHandRetargeter(cfg.right_hand_cfg) + + self._target_joint_names = cfg.target_joint_names + + # Prepare index mapping for fast runtime reordering + self._left_indices = [] + self._right_indices = [] + self._output_indices_left = [] + self._output_indices_right = [] + + left_joints = cfg.left_hand_cfg.hand_joint_names + right_joints = cfg.right_hand_cfg.hand_joint_names + + for i, name in enumerate(self._target_joint_names): + if name in left_joints: + self._output_indices_left.append(i) + self._left_indices.append(left_joints.index(name)) + elif name in right_joints: + self._output_indices_right.append(i) + self._right_indices.append(right_joints.index(name)) + else: + pass + + # Convert to tensors for advanced indexing + self._left_src_idx = torch.tensor(self._left_indices, device=self._sim_device, dtype=torch.long) + self._left_dst_idx = torch.tensor(self._output_indices_left, device=self._sim_device, dtype=torch.long) + + self._right_src_idx = torch.tensor(self._right_indices, device=self._sim_device, dtype=torch.long) + self._right_dst_idx = torch.tensor(self._output_indices_right, device=self._sim_device, dtype=torch.long) + + def retarget(self, data: dict) -> torch.Tensor: + """Process input data and return retargeted joint angles. + + Args: + data: Dictionary mapping tracking targets to joint data dictionaries. + + Returns: + torch.Tensor: Tensor of combined hand joint angles. + """ + left_out = self._left_retargeter.retarget(data) + right_out = self._right_retargeter.retarget(data) + + # Create output buffer + combined = torch.zeros(len(self._target_joint_names), device=self._sim_device, dtype=torch.float32) + + if len(self._left_dst_idx) > 0: + combined[self._left_dst_idx] = left_out[self._left_src_idx] + + if len(self._right_dst_idx) > 0: + combined[self._right_dst_idx] = right_out[self._right_src_idx] + + return combined + + def get_requirements(self) -> list[RetargeterBase.Requirement]: + reqs = set() + reqs.update(self._left_retargeter.get_requirements()) + reqs.update(self._right_retargeter.get_requirements()) + return list(reqs) + + +@dataclass(kw_only=True) +class DexBiManualRetargeterCfg(RetargeterCfg): + """Configuration for the bimanual dexterous hand retargeter.""" + + retargeter_type: type[RetargeterBase] = DexBiManualRetargeter + + # Configurations for individual hands + left_hand_cfg: DexHandRetargeterCfg = MISSING + right_hand_cfg: DexHandRetargeterCfg = MISSING + + # Combined joint names for the output + target_joint_names: list[str] = MISSING diff --git a/source/isaaclab/isaaclab/devices/retargeters/dex/dex_motion_controller.py b/source/isaaclab/isaaclab/devices/retargeters/dex/dex_motion_controller.py new file mode 100644 index 00000000000..2232e2f5e27 --- /dev/null +++ b/source/isaaclab/isaaclab/devices/retargeters/dex/dex_motion_controller.py @@ -0,0 +1,127 @@ +# 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 numpy as np +import torch +from dataclasses import MISSING, dataclass + +from isaaclab.devices.device_base import DeviceBase +from isaaclab.devices.retargeter_base import RetargeterBase, RetargeterCfg + + +class DexMotionController(RetargeterBase): + """Retargeter that maps motion controller inputs to robot hand joint angles. + + This class implements simple logic to map button presses and trigger/joystick inputs + to finger joint angles. It is specifically designed for the G1/Inspire hands mapping logic. + """ + + def __init__(self, cfg: DexMotionControllerCfg): + """Initialize the retargeter. + + Args: + cfg: Configuration for the retargeter. + """ + super().__init__(cfg) + self._sim_device = cfg.sim_device + self._hand_joint_names = cfg.hand_joint_names + self._target = cfg.target + self._is_left = self._target == DeviceBase.TrackingTarget.CONTROLLER_LEFT + + # Visualization not implemented for this simple mapper yet, but cfg supports it + self._enable_visualization = cfg.enable_visualization + + def retarget(self, data: dict) -> torch.Tensor: + """Process input data and return retargeted joint angles. + + Args: + data: Dictionary mapping tracking targets to controller data. + + Returns: + torch.Tensor: Tensor of hand joint angles. + """ + controller_data = data.get(self._target, np.array([])) + + # Map controller inputs to hand joints + # Returns 7 joints: [ThumbRot, Thumb1, Thumb2, Index1, Index2, Middle1, Middle2] + joints = self._map_to_hand_joints(controller_data, is_left=self._is_left) + + if self._is_left: + # Negate left hand joints for proper mirroring + joints = -joints + + # The internal map returns 7 DOFs. We assume the hand_joint_names provided + # correspond to these 7 DOFs in order, or we return them as is if names match count. + # Internal Order: + # 0: Thumb Rotation + # 1: Thumb Middle/Proximal + # 2: Thumb Distal + # 3: Index Proximal + # 4: Index Distal + # 5: Middle Proximal + # 6: Middle Distal + + # If the user provided specific joint names, we might need to map, but + # for this simple controller we return the 7-dof vector. + # Note: The previous implementation hardcoded a specific interleaving for two hands. + # Here we return the single hand 7-dof vector. + + return torch.tensor(joints, dtype=torch.float32, device=self._sim_device) + + def get_requirements(self) -> list[RetargeterBase.Requirement]: + return [RetargeterBase.Requirement.MOTION_CONTROLLER] + + def _map_to_hand_joints(self, controller_data: np.ndarray, is_left: bool) -> np.ndarray: + """Map controller inputs to hand joint angles.""" + hand_joints = np.zeros(7) + + if len(controller_data) <= DeviceBase.MotionControllerDataRowIndex.INPUTS.value: + return hand_joints + + inputs = controller_data[DeviceBase.MotionControllerDataRowIndex.INPUTS.value] + if len(inputs) < len(DeviceBase.MotionControllerInputIndex): + return hand_joints + + trigger = inputs[DeviceBase.MotionControllerInputIndex.TRIGGER.value] + squeeze = inputs[DeviceBase.MotionControllerInputIndex.SQUEEZE.value] + + thumb_button = max(trigger, squeeze) + thumb_angle = -thumb_button + + thumb_rotation = 0.5 * trigger - 0.5 * squeeze + if not is_left: + thumb_rotation = -thumb_rotation + + hand_joints[0] = thumb_rotation + hand_joints[1] = thumb_angle * 0.4 + hand_joints[2] = thumb_angle * 0.7 + + index_angle = trigger * 1.0 + hand_joints[3] = index_angle + hand_joints[4] = index_angle + + middle_angle = squeeze * 1.0 + hand_joints[5] = middle_angle + hand_joints[6] = middle_angle + + return hand_joints + + +@dataclass(kw_only=True) +class DexMotionControllerCfg(RetargeterCfg): + """Configuration for the dexterous motion controller retargeter.""" + + retargeter_type: type[RetargeterBase] = DexMotionController + + # Target + target: DeviceBase.TrackingTarget = MISSING + + # Configuration + hand_joint_names: list[str] = MISSING + hand_urdf: str = MISSING # Added as requested parameter + + enable_visualization: bool = False diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/gr1_t2_dex_retargeting_utils.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/fourier/gr1_t2_dex_retargeting_utils.py similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/gr1_t2_dex_retargeting_utils.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/fourier/gr1_t2_dex_retargeting_utils.py diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/gr1t2_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/fourier/gr1t2_retargeter.py similarity index 92% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/gr1t2_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/fourier/gr1t2_retargeter.py index a352580c2e9..a96277b2719 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/gr1t2_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/humanoid/fourier/gr1t2_retargeter.py @@ -8,6 +8,7 @@ import contextlib import numpy as np import torch +import warnings from dataclasses import dataclass import isaaclab.sim as sim_utils @@ -22,10 +23,10 @@ class GR1T2Retargeter(RetargeterBase): - """Retargets OpenXR hand tracking data to GR1T2 hand end-effector commands. + """Retargets hand tracking data to GR1T2 hand end-effector commands. - This retargeter maps hand tracking data from OpenXR to joint commands for the GR1T2 robot's hands. - It handles both left and right hands, converting poses of the hands in OpenXR format joint angles for the GR1T2 robot's hands. + This retargeter maps hand tracking data to joint commands for the GR1T2 robot's hands. + It handles both left and right hands, converting poses of the hands in the tracking format to joint angles for the GR1T2 robot's hands. """ def __init__( @@ -40,6 +41,12 @@ def __init__( device: PyTorch device for computations hand_joint_names: List of robot hand joint names """ + warnings.warn( + "The 'GR1T2Retargeter' class is deprecated and will be removed in a future release. " + "Please use 'isaaclab.devices.retargeters.DexHandRetargeter' instead.", + DeprecationWarning, + stacklevel=2, + ) super().__init__(cfg) self._hand_joint_names = cfg.hand_joint_names @@ -118,7 +125,7 @@ def _retarget_abs(self, wrist: np.ndarray) -> np.ndarray: """Handle absolute pose retargeting. Args: - wrist: Wrist pose data from OpenXR + wrist: Wrist pose data Returns: Retargeted wrist pose in USD control frame diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/g1_dex_retargeting_utils.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/inspire/g1_dex_retargeting_utils.py similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/g1_dex_retargeting_utils.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/inspire/g1_dex_retargeting_utils.py diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py similarity index 96% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py index 74fa7518e90..ceff9ca2507 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/inspire/g1_upper_body_retargeter.py @@ -8,6 +8,7 @@ import contextlib import numpy as np import torch +import warnings from dataclasses import dataclass import isaaclab.sim as sim_utils @@ -40,6 +41,12 @@ def __init__( device: PyTorch device for computations hand_joint_names: List of robot hand joint names """ + warnings.warn( + "The 'UnitreeG1Retargeter' class is deprecated and will be removed in a future release. " + "Please use 'isaaclab.devices.retargeters.DexHandRetargeter' instead.", + DeprecationWarning, + stacklevel=2, + ) super().__init__(cfg) self._hand_joint_names = cfg.hand_joint_names diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_dex_retargeting_utils.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_dex_retargeting_utils.py similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_dex_retargeting_utils.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_dex_retargeting_utils.py diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py similarity index 96% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py index 49481da6d6f..a5dc68b20af 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_motion_ctrl_retargeter.py @@ -7,6 +7,7 @@ import numpy as np import torch +import warnings from dataclasses import dataclass import isaaclab.sim as sim_utils @@ -27,6 +28,12 @@ class G1TriHandUpperBodyMotionControllerRetargeter(RetargeterBase): def __init__(self, cfg: G1TriHandUpperBodyMotionControllerRetargeterCfg): """Initialize the retargeter.""" + warnings.warn( + "The 'G1TriHandUpperBodyMotionControllerRetargeter' class is deprecated and will be removed in a future" + " release. Please use 'isaaclab.devices.retargeters.DexMotionController' instead.", + DeprecationWarning, + stacklevel=2, + ) super().__init__(cfg) self._sim_device = cfg.sim_device self._hand_joint_names = cfg.hand_joint_names diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py similarity index 96% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py index 8e432aa59fe..fbaf3aa3c66 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/humanoid/unitree/trihand/g1_upper_body_retargeter.py @@ -8,6 +8,7 @@ import contextlib import numpy as np import torch +import warnings from dataclasses import dataclass import isaaclab.sim as sim_utils @@ -38,6 +39,12 @@ def __init__( Args: cfg: Configuration for the retargeter. """ + warnings.warn( + "The 'G1TriHandUpperBodyRetargeter' class is deprecated and will be removed in a future release. " + "Please use 'isaaclab.devices.retargeters.DexHandRetargeter' instead.", + DeprecationWarning, + stacklevel=2, + ) super().__init__(cfg) # Store device name for runtime retrieval diff --git a/source/isaaclab/isaaclab/devices/retargeters/locomotion/__init__.py b/source/isaaclab/isaaclab/devices/retargeters/locomotion/__init__.py new file mode 100644 index 00000000000..61529bcb89b --- /dev/null +++ b/source/isaaclab/isaaclab/devices/retargeters/locomotion/__init__.py @@ -0,0 +1,7 @@ +# 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 .locomotion_fixed_root_cmd_retargeter import LocomotionFixedRootCmdRetargeter, LocomotionFixedRootCmdRetargeterCfg +from .locomotion_root_cmd_retargeter import LocomotionRootCmdRetargeter, LocomotionRootCmdRetargeterCfg diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_lower_body_standing.py b/source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_fixed_root_cmd_retargeter.py similarity index 55% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_lower_body_standing.py rename to source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_fixed_root_cmd_retargeter.py index 3c7f4309b05..f54a0aa9686 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_lower_body_standing.py +++ b/source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_fixed_root_cmd_retargeter.py @@ -11,15 +11,20 @@ from isaaclab.devices.retargeter_base import RetargeterBase, RetargeterCfg -class G1LowerBodyStandingRetargeter(RetargeterBase): - """Provides lower body standing commands for the G1 robot.""" +class LocomotionFixedRootCmdRetargeter(RetargeterBase): + """Provides fixed root commands (velocity zero, fixed hip height). - def __init__(self, cfg: G1LowerBodyStandingRetargeterCfg): + Useful for standing still or when motion controllers are not available but the pipeline expects + locomotion commands. + """ + + def __init__(self, cfg: LocomotionFixedRootCmdRetargeterCfg): """Initialize the retargeter.""" super().__init__(cfg) self.cfg = cfg def retarget(self, data: dict) -> torch.Tensor: + # Returns [vel_x, vel_y, rot_vel_z, hip_height] return torch.tensor([0.0, 0.0, 0.0, self.cfg.hip_height], device=self.cfg.sim_device) def get_requirements(self) -> list[RetargeterBase.Requirement]: @@ -28,9 +33,10 @@ def get_requirements(self) -> list[RetargeterBase.Requirement]: @dataclass -class G1LowerBodyStandingRetargeterCfg(RetargeterCfg): - """Configuration for the G1 lower body standing retargeter.""" +class LocomotionFixedRootCmdRetargeterCfg(RetargeterCfg): + """Configuration for the fixed locomotion root command retargeter.""" hip_height: float = 0.72 - """Height of the G1 robot hip in meters. The value is a fixed height suitable for G1 to do tabletop manipulation.""" - retargeter_type: type[RetargeterBase] = G1LowerBodyStandingRetargeter + """Height of the robot hip in meters.""" + + retargeter_type: type[RetargeterBase] = LocomotionFixedRootCmdRetargeter diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_motion_controller_locomotion.py b/source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_root_cmd_retargeter.py similarity index 76% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_motion_controller_locomotion.py rename to source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_root_cmd_retargeter.py index a3dd950e882..e660a431608 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/g1_motion_controller_locomotion.py +++ b/source/isaaclab/isaaclab/devices/retargeters/locomotion/locomotion_root_cmd_retargeter.py @@ -13,14 +13,20 @@ from isaaclab.sim import SimulationContext -class G1LowerBodyStandingMotionControllerRetargeter(RetargeterBase): - """Provides lower body standing commands for the G1 robot.""" +class LocomotionRootCmdRetargeter(RetargeterBase): + """Provides root velocity and hip height commands for locomotion. - def __init__(self, cfg: G1LowerBodyStandingMotionControllerRetargeterCfg): + This retargeter maps motion controller thumbsticks to: + - Linear velocity (X, Y) + - Angular velocity (Z) + - Hip height adjustment + """ + + def __init__(self, cfg: LocomotionRootCmdRetargeterCfg): """Initialize the retargeter.""" super().__init__(cfg) self.cfg = cfg - self._hip_height = cfg.hip_height + self._hip_height = cfg.initial_hip_height def retarget(self, data: dict) -> torch.Tensor: left_thumbstick_x = 0.0 @@ -51,7 +57,7 @@ def retarget(self, data: dict) -> torch.Tensor: right_thumbstick_x = right_inputs[DeviceBase.MotionControllerInputIndex.THUMBSTICK_X.value] right_thumbstick_y = right_inputs[DeviceBase.MotionControllerInputIndex.THUMBSTICK_Y.value] - # Thumbstick values are in the range of [-1, 1], so we need to scale them to the range of [-movement_scale, movement_scale] + # Thumbstick values are in the range of [-1, 1], so we need to scale them left_thumbstick_x = left_thumbstick_x * self.cfg.movement_scale left_thumbstick_y = left_thumbstick_y * self.cfg.movement_scale @@ -60,6 +66,10 @@ def retarget(self, data: dict) -> torch.Tensor: self._hip_height -= right_thumbstick_y * dt * self.cfg.rotation_scale self._hip_height = max(0.4, min(1.0, self._hip_height)) + # Returns [vel_x, vel_y, rot_vel_z, hip_height] + # Note: left_thumbstick_y is forward/backward, so it maps to X velocity (negated because up is +1) + # left_thumbstick_x is left/right, so it maps to Y velocity (negated because right is +1) + # right_thumbstick_x is rotation, so it maps to Z angular velocity (negated) return torch.tensor( [-left_thumbstick_y, -left_thumbstick_x, -right_thumbstick_x, self._hip_height], device=self.cfg.sim_device, @@ -71,15 +81,16 @@ def get_requirements(self) -> list[RetargeterBase.Requirement]: @dataclass -class G1LowerBodyStandingMotionControllerRetargeterCfg(RetargeterCfg): - """Configuration for the G1 lower body standing retargeter.""" +class LocomotionRootCmdRetargeterCfg(RetargeterCfg): + """Configuration for the locomotion root command retargeter.""" - hip_height: float = 0.72 - """Height of the G1 robot hip in meters. The value is a fixed height suitable for G1 to do tabletop manipulation.""" + initial_hip_height: float = 0.72 + """Initial height of the robot hip in meters.""" movement_scale: float = 0.5 """Scale the movement of the robot to the range of [-movement_scale, movement_scale].""" rotation_scale: float = 0.35 """Scale the rotation of the robot to the range of [-rotation_scale, rotation_scale].""" - retargeter_type: type[RetargeterBase] = G1LowerBodyStandingMotionControllerRetargeter + + retargeter_type: type[RetargeterBase] = LocomotionRootCmdRetargeter diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/__init__.py b/source/isaaclab/isaaclab/devices/retargeters/manipulator/__init__.py similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/__init__.py rename to source/isaaclab/isaaclab/devices/retargeters/manipulator/__init__.py diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/gripper_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/manipulator/gripper_retargeter.py similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/gripper_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/manipulator/gripper_retargeter.py diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_abs_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_abs_retargeter.py similarity index 69% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_abs_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_abs_retargeter.py index fd82ab07556..c7b28c27cd4 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_abs_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_abs_retargeter.py @@ -16,7 +16,7 @@ class Se3AbsRetargeter(RetargeterBase): - """Retargets OpenXR hand tracking data to end-effector commands using absolute positioning. + """Retargets hand tracking data to end-effector commands using absolute positioning. This retargeter maps hand joint poses directly to robot end-effector positions and orientations, rather than using relative movements. It can either: @@ -43,9 +43,15 @@ def __init__( device: The device to place the returned tensor on ('cpu' or 'cuda') """ super().__init__(cfg) - if cfg.bound_hand not in [DeviceBase.TrackingTarget.HAND_LEFT, DeviceBase.TrackingTarget.HAND_RIGHT]: + if cfg.bound_hand not in [ + DeviceBase.TrackingTarget.HAND_LEFT, + DeviceBase.TrackingTarget.HAND_RIGHT, + DeviceBase.TrackingTarget.CONTROLLER_LEFT, + DeviceBase.TrackingTarget.CONTROLLER_RIGHT, + ]: raise ValueError( - "bound_hand must be either DeviceBase.TrackingTarget.HAND_LEFT or DeviceBase.TrackingTarget.HAND_RIGHT" + "bound_hand must be one of [HAND_LEFT, HAND_RIGHT, CONTROLLER_LEFT, CONTROLLER_RIGHT], got" + f" {cfg.bound_hand}" ) self.bound_hand = cfg.bound_hand @@ -53,6 +59,11 @@ def __init__( self._use_wrist_rotation = cfg.use_wrist_rotation self._use_wrist_position = cfg.use_wrist_position + # Store offsets + self._target_offset_pos = np.array(cfg.target_offset_pos) + # Convert w,x,y,z (Isaac Lab) to x,y,z,w (scipy) + self._target_offset_rot = np.array([*cfg.target_offset_rot[1:], cfg.target_offset_rot[0]]) + # Initialize visualization if enabled self._enable_visualization = cfg.enable_visualization if cfg.enable_visualization: @@ -68,17 +79,32 @@ def retarget(self, data: dict) -> torch.Tensor: Args: data: Dictionary mapping tracking targets to joint data dictionaries. - The joint names are defined in isaaclab.devices.openxr.common.HAND_JOINT_NAMES + The joint names are defined in isaaclab.devices.openxr.common.HAND_JOINT_NAMES (if using OpenXR) Returns: torch.Tensor: 7D tensor containing position (xyz) and orientation (quaternion) for the robot end-effector """ # Extract key joint poses from the bound hand - hand_data = data[self.bound_hand] - thumb_tip = hand_data.get("thumb_tip") - index_tip = hand_data.get("index_tip") - wrist = hand_data.get("wrist") + hand_data = data.get(self.bound_hand) + + if hand_data is None: + wrist = np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]) + thumb_tip = None + index_tip = None + elif isinstance(hand_data, np.ndarray): + # Motion Controller Data: [Pose, Inputs] + if len(hand_data) > 0: + wrist = hand_data[0] + else: + wrist = np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]) + thumb_tip = None + index_tip = None + else: + # Hand Tracking Data: Dict + thumb_tip = hand_data.get("thumb_tip") + index_tip = hand_data.get("index_tip") + wrist = hand_data.get("wrist") ee_command_np = self._retarget_abs(thumb_tip, index_tip, wrist) @@ -88,16 +114,23 @@ def retarget(self, data: dict) -> torch.Tensor: return ee_command def get_requirements(self) -> list[RetargeterBase.Requirement]: + if self.bound_hand in [ + DeviceBase.TrackingTarget.CONTROLLER_LEFT, + DeviceBase.TrackingTarget.CONTROLLER_RIGHT, + ]: + return [RetargeterBase.Requirement.MOTION_CONTROLLER] return [RetargeterBase.Requirement.HAND_TRACKING] - def _retarget_abs(self, thumb_tip: np.ndarray, index_tip: np.ndarray, wrist: np.ndarray) -> np.ndarray: + def _retarget_abs( + self, thumb_tip: np.ndarray | None, index_tip: np.ndarray | None, wrist: np.ndarray + ) -> np.ndarray: """Handle absolute pose retargeting. Args: thumb_tip: 7D array containing position (xyz) and orientation (quaternion) - for the thumb tip + for the thumb tip. Can be None. index_tip: 7D array containing position (xyz) and orientation (quaternion) - for the index tip + for the index tip. Can be None. wrist: 7D array containing position (xyz) and orientation (quaternion) for the wrist @@ -107,13 +140,13 @@ def _retarget_abs(self, thumb_tip: np.ndarray, index_tip: np.ndarray, wrist: np. """ # Get position - if self._use_wrist_position: + if self._use_wrist_position or thumb_tip is None or index_tip is None: position = wrist[:3] else: position = (thumb_tip[:3] + index_tip[:3]) / 2 # Get rotation - if self._use_wrist_rotation: + if self._use_wrist_rotation or thumb_tip is None or index_tip is None: # wrist is w,x,y,z but scipy expects x,y,z,w base_rot = Rotation.from_quat([*wrist[4:], wrist[3]]) else: @@ -126,8 +159,13 @@ def _retarget_abs(self, thumb_tip: np.ndarray, index_tip: np.ndarray, wrist: np. slerp = Slerp(key_times, Rotation.concatenate([r0, r1])) base_rot = slerp([0.5])[0] - # Apply additional x-axis rotation to align with pinch gesture - final_rot = base_rot * Rotation.from_euler("x", 90, degrees=True) + # Apply offset rotation + # (previously hardcoded as base_rot * Rotation.from_euler("x", 90, degrees=True)) + offset_rot = Rotation.from_quat(self._target_offset_rot) + final_rot = base_rot * offset_rot + + # Apply position offset in the wrist frame (rotated by base_rot) + position = position + base_rot.apply(self._target_offset_pos) if self._zero_out_xy_rotation: z, y, x = final_rot.as_euler("ZYX") @@ -166,6 +204,12 @@ class Se3AbsRetargeterCfg(RetargeterCfg): zero_out_xy_rotation: bool = True use_wrist_rotation: bool = False use_wrist_position: bool = True + + # Default offset corresponds to Rotation.from_euler("x", 90, degrees=True) + # quaternion (w, x, y, z) to maintain backward compatibility + target_offset_rot: tuple[float, float, float, float] = (0.7071068, 0.7071068, 0.0, 0.0) + target_offset_pos: tuple[float, float, float] = (0.0, 0.0, 0.0) + enable_visualization: bool = False bound_hand: DeviceBase.TrackingTarget = DeviceBase.TrackingTarget.HAND_RIGHT retargeter_type: type[RetargeterBase] = Se3AbsRetargeter diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_rel_retargeter.py b/source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_rel_retargeter.py similarity index 98% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_rel_retargeter.py rename to source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_rel_retargeter.py index 5c70e9ea61a..7662f45dff0 100644 --- a/source/isaaclab/isaaclab/devices/openxr/retargeters/manipulator/se3_rel_retargeter.py +++ b/source/isaaclab/isaaclab/devices/retargeters/manipulator/se3_rel_retargeter.py @@ -16,7 +16,7 @@ class Se3RelRetargeter(RetargeterBase): - """Retargets OpenXR hand tracking data to end-effector commands using relative positioning. + """Retargets hand tracking data to end-effector commands using relative positioning. This retargeter calculates delta poses between consecutive hand joint poses to generate incremental robot movements. It can either: @@ -90,7 +90,7 @@ def retarget(self, data: dict) -> torch.Tensor: Args: data: Dictionary mapping tracking targets to joint data dictionaries. - The joint names are defined in isaaclab.devices.openxr.common.HAND_JOINT_NAMES + The joint names are defined in isaaclab.devices.openxr.common.HAND_JOINT_NAMES (if using OpenXR) Returns: torch.Tensor: 6D tensor containing position (xyz) and rotation vector (rx,ry,rz) diff --git a/source/isaaclab/setup.py b/source/isaaclab/setup.py index 75fe5b9a3e7..e837c6be6f0 100644 --- a/source/isaaclab/setup.py +++ b/source/isaaclab/setup.py @@ -53,7 +53,7 @@ # required by isaaclab.isaaclab.controllers.pink_ik f"pin-pink==3.1.0 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})", f"daqp==0.7.2 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS_ARM})", - # required by isaaclab.devices.openxr.retargeters.humanoid.fourier.gr1_t2_dex_retargeting_utils + # required by isaaclab.devices.retargeters.dex.dex_hand_retargeter f"dex-retargeting==0.4.6 ; platform_system == 'Linux' and ({SUPPORTED_ARCHS})", ] diff --git a/source/isaaclab/test/devices/test_device_constructors.py b/source/isaaclab/test/devices/test_device_constructors.py index 83a2c9ddeba..4163628f69f 100644 --- a/source/isaaclab/test/devices/test_device_constructors.py +++ b/source/isaaclab/test/devices/test_device_constructors.py @@ -40,7 +40,7 @@ Se3SpaceMouseCfg, ) from isaaclab.devices.openxr import XrCfg -from isaaclab.devices.openxr.retargeters import GripperRetargeterCfg, Se3AbsRetargeterCfg +from isaaclab.devices.retargeters import GripperRetargeterCfg, Se3AbsRetargeterCfg # Import teleop device factory for testing from isaaclab.devices.teleop_device_factory import create_teleop_device diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/data/configs/dex-retargeting/g1_hand_left_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/configs/dex_retargeting/g1_hand_left_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/data/configs/dex-retargeting/g1_hand_left_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/configs/dex_retargeting/g1_hand_left_dexpilot.yml diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/data/configs/dex-retargeting/g1_hand_right_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/configs/dex_retargeting/g1_hand_right_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/trihand/data/configs/dex-retargeting/g1_hand_right_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/configs/dex_retargeting/g1_hand_right_dexpilot.yml diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/fixed_base_upper_body_ik_g1_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/fixed_base_upper_body_ik_g1_env_cfg.py index e3ace99b520..6c3dd6fa85a 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/fixed_base_upper_body_ik_g1_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/fixed_base_upper_body_ik_g1_env_cfg.py @@ -4,16 +4,16 @@ # SPDX-License-Identifier: BSD-3-Clause +import os + from isaaclab_assets.robots.unitree import G1_29DOF_CFG import isaaclab.envs.mdp as base_mdp import isaaclab.sim as sim_utils from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg -from isaaclab.devices.device_base import DevicesCfg +from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr import OpenXRDeviceCfg, XrCfg -from isaaclab.devices.openxr.retargeters.humanoid.unitree.trihand.g1_upper_body_retargeter import ( - G1TriHandUpperBodyRetargeterCfg, -) +from isaaclab.devices.retargeters import DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs import ManagerBasedRLEnvCfg from isaaclab.managers import ObservationGroupCfg as ObsGroup from isaaclab.managers import ObservationTermCfg as ObsTerm @@ -196,16 +196,53 @@ def __post_init__(self): # Retrieve local paths for the URDF and mesh files. Will be cached for call after the first time. self.actions.upper_body_ik.controller.urdf_path = retrieve_file_path(urdf_omniverse_path) + # Re-order hand joint names to grouping by hand (Left then Right) + original_hand_joints = self.actions.upper_body_ik.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "left" in j] + right_hand_joints = [j for j in original_hand_joints if "right" in j] + self.actions.upper_body_ik.hand_joint_names = left_hand_joints + right_hand_joints + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - G1TriHandUpperBodyRetargeterCfg( + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(0.7071, 0.0, 0.7071, 0.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.7071, 0.0, -0.7071), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # OpenXR hand tracking has 26 joints per hand + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "configs/dex_retargeting/g1_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, enable_visualization=True, # OpenXR hand tracking has 26 joints per hand - num_open_xr_hand_joints=2 * 26, + num_open_xr_hand_joints=26, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "configs/dex_retargeting/g1_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), ), ], sim_device=self.sim.device, diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/locomanipulation_g1_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/locomanipulation_g1_env_cfg.py index e460c12d662..8676c7db051 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/locomanipulation_g1_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/locomanipulation/pick_place/locomanipulation_g1_env_cfg.py @@ -3,24 +3,23 @@ # # SPDX-License-Identifier: BSD-3-Clause +import os + from isaaclab_assets.robots.unitree import G1_29DOF_CFG import isaaclab.envs.mdp as base_mdp import isaaclab.sim as sim_utils from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg -from isaaclab.devices.device_base import DevicesCfg +from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr import OpenXRDeviceCfg, XrCfg -from isaaclab.devices.openxr.retargeters.humanoid.unitree.g1_lower_body_standing import G1LowerBodyStandingRetargeterCfg -from isaaclab.devices.openxr.retargeters.humanoid.unitree.g1_motion_controller_locomotion import ( - G1LowerBodyStandingMotionControllerRetargeterCfg, -) -from isaaclab.devices.openxr.retargeters.humanoid.unitree.trihand.g1_upper_body_motion_ctrl_retargeter import ( - G1TriHandUpperBodyMotionControllerRetargeterCfg, -) -from isaaclab.devices.openxr.retargeters.humanoid.unitree.trihand.g1_upper_body_retargeter import ( - G1TriHandUpperBodyRetargeterCfg, -) from isaaclab.devices.openxr.xr_cfg import XrAnchorRotationMode +from isaaclab.devices.retargeters import ( + DexBiManualRetargeterCfg, + DexHandRetargeterCfg, + DexMotionControllerCfg, + Se3AbsRetargeterCfg, +) +from isaaclab.devices.retargeters.locomotion import LocomotionFixedRootCmdRetargeterCfg, LocomotionRootCmdRetargeterCfg from isaaclab.envs import ManagerBasedRLEnvCfg from isaaclab.managers import ObservationGroupCfg as ObsGroup from isaaclab.managers import ObservationTermCfg as ObsTerm @@ -213,6 +212,11 @@ def __post_init__(self): # Retrieve local paths for the URDF and mesh files. Will be cached for call after the first time. self.actions.upper_body_ik.controller.urdf_path = retrieve_file_path(urdf_omniverse_path) + # Extract hand joint names for each hand + original_hand_joints = self.actions.upper_body_ik.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "left" in j] + right_hand_joints = [j for j in original_hand_joints if "right" in j] + self.xr.anchor_prim_path = "/World/envs/env_0/Robot/pelvis" self.xr.fixed_anchor_height = True # Ensure XR anchor rotation follows the robot pelvis (yaw only), with smoothing for comfort @@ -222,14 +226,51 @@ def __post_init__(self): devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - G1TriHandUpperBodyRetargeterCfg( - enable_visualization=True, - # OpenXR hand tracking has 26 joints per hand - num_open_xr_hand_joints=2 * 26, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(0.7071, 0.0, 0.7071, 0.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.7071, 0.0, -0.7071), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, ), - G1LowerBodyStandingRetargeterCfg( + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, + sim_device=self.sim.device, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "configs/dex_retargeting/g1_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "configs/dex_retargeting/g1_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), + ), + LocomotionFixedRootCmdRetargeterCfg( sim_device=self.sim.device, ), ], @@ -238,12 +279,37 @@ def __post_init__(self): ), "motion_controllers": OpenXRDeviceCfg( retargeters=[ - G1TriHandUpperBodyMotionControllerRetargeterCfg( - enable_visualization=True, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.CONTROLLER_LEFT, + # Offset equivalent to (0, -75, 90) Euler (XYZ) + target_offset_rot=(0.5358, -0.4619, 0.5358, 0.4619), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.CONTROLLER_RIGHT, + # Offset equivalent to (0, -75, 90) Euler (XYZ) but mirrored for right hand? + target_offset_rot=(0.5358, -0.4619, 0.5358, 0.4619), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + DexMotionControllerCfg( + target=DeviceBase.TrackingTarget.CONTROLLER_LEFT, + hand_joint_names=left_hand_joints, + sim_device=self.sim.device, + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_left_hand.urdf", + ), + DexMotionControllerCfg( + target=DeviceBase.TrackingTarget.CONTROLLER_RIGHT, + hand_joint_names=right_hand_joints, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Controllers/LocomanipulationAssets/unitree_g1_dexpilot_asset/G1_right_hand.urdf", ), - G1LowerBodyStandingMotionControllerRetargeterCfg( + LocomotionRootCmdRetargeterCfg( sim_device=self.sim.device, ), ], diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/data/configs/dex-retargeting/fourier_hand_left_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/fourier_hand_left_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/data/configs/dex-retargeting/fourier_hand_left_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/fourier_hand_left_dexpilot.yml diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/data/configs/dex-retargeting/fourier_hand_right_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/fourier_hand_right_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/fourier/data/configs/dex-retargeting/fourier_hand_right_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/fourier_hand_right_dexpilot.yml diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/data/configs/dex-retargeting/unitree_hand_left_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/unitree_hand_left_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/data/configs/dex-retargeting/unitree_hand_left_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/unitree_hand_left_dexpilot.yml diff --git a/source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/data/configs/dex-retargeting/unitree_hand_right_dexpilot.yml b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/unitree_hand_right_dexpilot.yml similarity index 100% rename from source/isaaclab/isaaclab/devices/openxr/retargeters/humanoid/unitree/inspire/data/configs/dex-retargeting/unitree_hand_right_dexpilot.yml rename to source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/config/dex_retargeting/unitree_hand_right_dexpilot.yml diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/exhaustpipe_gr1t2_pink_ik_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/exhaustpipe_gr1t2_pink_ik_env_cfg.py index 01feeab1cc2..96fa83332ca 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/exhaustpipe_gr1t2_pink_ik_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/exhaustpipe_gr1t2_pink_ik_env_cfg.py @@ -3,16 +3,20 @@ # # SPDX-License-Identifier: BSD-3-Clause +import os + import carb from pink.tasks import DampingTask, FrameTask import isaaclab.controllers.utils as ControllerUtils from isaaclab.controllers.pink_ik import NullSpacePostureTask, PinkIKControllerCfg from isaaclab.devices import DevicesCfg +from isaaclab.devices.device_base import DeviceBase from isaaclab.devices.openxr import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters import GR1T2RetargeterCfg +from isaaclab.devices.retargeters import DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs.mdp.actions.pink_actions_cfg import PinkInverseKinematicsActionCfg from isaaclab.utils import configclass +from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR from isaaclab_tasks.manager_based.manipulation.pick_place.exhaustpipe_gr1t2_base_env_cfg import ( ExhaustPipeGR1T2BaseEnvCfg, @@ -134,16 +138,53 @@ def __post_init__(self): self.actions.gr1_action.controller.urdf_path = temp_urdf_output_path self.actions.gr1_action.controller.mesh_path = temp_urdf_meshes_output_path + # Re-order hand joint names to grouping by hand (Left then Right) + original_hand_joints = self.actions.gr1_action.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "L_" in j] + right_hand_joints = [j for j in original_hand_joints if "R_" in j] + self.actions.gr1_action.hand_joint_names = left_hand_joints + right_hand_joints + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - GR1T2RetargeterCfg( + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(1.0, 0.0, 0.0, 0.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.0, 0.0, 1.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, enable_visualization=True, # number of joints in both hands - num_open_xr_hand_joints=2 * self.NUM_OPENXR_HAND_JOINTS, + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, sim_device=self.sim.device, - hand_joint_names=self.actions.gr1_action.hand_joint_names, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), ), ], sim_device=self.sim.device, diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/nutpour_gr1t2_pink_ik_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/nutpour_gr1t2_pink_ik_env_cfg.py index 6dcdd9a1e8f..fac7c23d10f 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/nutpour_gr1t2_pink_ik_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/nutpour_gr1t2_pink_ik_env_cfg.py @@ -3,16 +3,20 @@ # # SPDX-License-Identifier: BSD-3-Clause +import os + import carb from pink.tasks import DampingTask, FrameTask import isaaclab.controllers.utils as ControllerUtils from isaaclab.controllers.pink_ik import NullSpacePostureTask, PinkIKControllerCfg from isaaclab.devices import DevicesCfg +from isaaclab.devices.device_base import DeviceBase from isaaclab.devices.openxr import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters import GR1T2RetargeterCfg +from isaaclab.devices.retargeters import DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs.mdp.actions.pink_actions_cfg import PinkInverseKinematicsActionCfg from isaaclab.utils import configclass +from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR from isaaclab_tasks.manager_based.manipulation.pick_place.nutpour_gr1t2_base_env_cfg import NutPourGR1T2BaseEnvCfg @@ -132,16 +136,53 @@ def __post_init__(self): self.actions.gr1_action.controller.urdf_path = temp_urdf_output_path self.actions.gr1_action.controller.mesh_path = temp_urdf_meshes_output_path + # Re-order hand joint names to grouping by hand (Left then Right) + original_hand_joints = self.actions.gr1_action.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "L_" in j] + right_hand_joints = [j for j in original_hand_joints if "R_" in j] + self.actions.gr1_action.hand_joint_names = left_hand_joints + right_hand_joints + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - GR1T2RetargeterCfg( + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(1.0, 0.0, 0.0, 0.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.0, 0.0, 1.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=2 * 26, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), + DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, enable_visualization=True, # number of joints in both hands - num_open_xr_hand_joints=2 * self.NUM_OPENXR_HAND_JOINTS, + num_open_xr_hand_joints=2 * 26, sim_device=self.sim.device, - hand_joint_names=self.actions.gr1_action.hand_joint_names, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), ), ], sim_device=self.sim.device, diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_env_cfg.py index 4b073b35a3f..0b055b03205 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_env_cfg.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause +import os import tempfile import torch @@ -14,9 +15,9 @@ import isaaclab.sim as sim_utils from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg from isaaclab.controllers.pink_ik import NullSpacePostureTask, PinkIKControllerCfg -from isaaclab.devices.device_base import DevicesCfg +from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr import ManusViveCfg, OpenXRDeviceCfg, XrCfg -from isaaclab.devices.openxr.retargeters.humanoid.fourier.gr1t2_retargeter import GR1T2RetargeterCfg +from isaaclab.devices.retargeters import DexBiManualRetargeterCfg, DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs import ManagerBasedRLEnvCfg from isaaclab.envs.mdp.actions.pink_actions_cfg import PinkInverseKinematicsActionCfg from isaaclab.managers import EventTermCfg as EventTerm @@ -384,16 +385,60 @@ def __post_init__(self): self.actions.upper_body_ik.controller.urdf_path = temp_urdf_output_path self.actions.upper_body_ik.controller.mesh_path = temp_urdf_meshes_output_path + # Extract hand joint names for each hand + original_hand_joints = self.actions.upper_body_ik.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "L_" in j] + right_hand_joints = [j for j in original_hand_joints if "R_" in j] + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - GR1T2RetargeterCfg( - enable_visualization=True, - # number of joints in both hands - num_open_xr_hand_joints=2 * self.NUM_OPENXR_HAND_JOINTS, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(1.0, 0.0, 0.0, 0.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.0, 0.0, 1.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), ), ], sim_device=self.sim.device, @@ -401,15 +446,53 @@ def __post_init__(self): ), "manusvive": ManusViveCfg( retargeters=[ - GR1T2RetargeterCfg( - enable_visualization=True, - num_open_xr_hand_joints=2 * 26, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(1.0, 0.0, 0.0, 0.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.0, 0.0, 1.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, + sim_device=self.sim.device, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), ), ], sim_device=self.sim.device, xr_cfg=self.xr, ), - } + }, ) diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_waist_enabled_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_waist_enabled_env_cfg.py index 30b17e89493..4aa2897c949 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_waist_enabled_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_gr1t2_waist_enabled_env_cfg.py @@ -3,14 +3,16 @@ # # SPDX-License-Identifier: BSD-3-Clause +import os import tempfile import isaaclab.controllers.utils as ControllerUtils -from isaaclab.devices.device_base import DevicesCfg +from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr import OpenXRDeviceCfg, XrCfg -from isaaclab.devices.openxr.retargeters.humanoid.fourier.gr1t2_retargeter import GR1T2RetargeterCfg +from isaaclab.devices.retargeters import DexBiManualRetargeterCfg, DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs import ManagerBasedRLEnvCfg from isaaclab.utils import configclass +from isaaclab.utils.assets import ISAACLAB_NUCLEUS_DIR from .pickplace_gr1t2_env_cfg import ActionsCfg, EventCfg, ObjectTableSceneCfg, ObservationsCfg, TerminationsCfg @@ -68,16 +70,60 @@ def __post_init__(self): self.actions.upper_body_ik.controller.urdf_path = temp_urdf_output_path self.actions.upper_body_ik.controller.mesh_path = temp_urdf_meshes_output_path + # Extract hand joint names for each hand + original_hand_joints = self.actions.upper_body_ik.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "L_" in j] + right_hand_joints = [j for j in original_hand_joints if "R_" in j] + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - GR1T2RetargeterCfg( - enable_visualization=True, - # number of joints in both hands - num_open_xr_hand_joints=2 * self.NUM_OPENXR_HAND_JOINTS, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(1.0, 0.0, 0.0, 0.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.0, 0.0, 1.0), + zero_out_xy_rotation=False, + use_wrist_rotation=True, + use_wrist_position=True, + sim_device=self.sim.device, + ), + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, sim_device=self.sim.device, - hand_joint_names=self.actions.upper_body_ik.hand_joint_names, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/fourier_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/GR1T2_assets/GR1_T2_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, -1, 0, -1, 0, 0, 0, 0, -1), + ), ), ], sim_device=self.sim.device, diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_unitree_g1_inspire_hand_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_unitree_g1_inspire_hand_env_cfg.py index a557911498a..9f7b13fd83a 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_unitree_g1_inspire_hand_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/pick_place/pickplace_unitree_g1_inspire_hand_env_cfg.py @@ -2,6 +2,7 @@ # All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause +import os import tempfile import torch @@ -13,9 +14,9 @@ import isaaclab.sim as sim_utils from isaaclab.assets import ArticulationCfg, AssetBaseCfg, RigidObjectCfg from isaaclab.controllers.pink_ik import NullSpacePostureTask, PinkIKControllerCfg -from isaaclab.devices.device_base import DevicesCfg +from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr import ManusViveCfg, OpenXRDeviceCfg, XrCfg -from isaaclab.devices.openxr.retargeters.humanoid.unitree.inspire.g1_upper_body_retargeter import UnitreeG1RetargeterCfg +from isaaclab.devices.retargeters import DexBiManualRetargeterCfg, DexHandRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs import ManagerBasedRLEnvCfg from isaaclab.envs.mdp.actions.pink_actions_cfg import PinkInverseKinematicsActionCfg from isaaclab.managers import EventTermCfg as EventTerm @@ -376,18 +377,60 @@ def __post_init__(self): self.actions.pink_ik_cfg.controller.urdf_path = temp_urdf_output_path self.actions.pink_ik_cfg.controller.mesh_path = temp_urdf_meshes_output_path + # Extract hand joint names for each hand + original_hand_joints = self.actions.pink_ik_cfg.hand_joint_names + left_hand_joints = [j for j in original_hand_joints if "L_" in j] + right_hand_joints = [j for j in original_hand_joints if "R_" in j] + self.teleop_devices = DevicesCfg( devices={ "handtracking": OpenXRDeviceCfg( retargeters=[ - UnitreeG1RetargeterCfg( - enable_visualization=True, - # number of joints in both hands - num_open_xr_hand_joints=2 * 26, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(0.7071, 0.0, 0.7071, 0.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.7071, 0.0, -0.7071), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, sim_device=self.sim.device, - # Please confirm that self.actions.pink_ik_cfg.hand_joint_names is consistent with robot.joint_names[-24:] - # The order of the joints does matter as it will be used for converting pink_ik actions to final control actions in IsaacLab. - hand_joint_names=self.actions.pink_ik_cfg.hand_joint_names, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + # Please confirm that self.actions.pink_ik_cfg.hand_joint_names is consistent with robot.joint_names[-24:] + # The order of the joints does matter as it will be used for converting pink_ik actions to final control actions in IsaacLab. + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/unitree_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/G1_inspire_assets/retarget_inspire_white_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + # number of joints in both hands + num_open_xr_hand_joints=self.NUM_OPENXR_HAND_JOINTS, + sim_device=self.sim.device, + # Please confirm that self.actions.pink_ik_cfg.hand_joint_names is consistent with robot.joint_names[-24:] + # The order of the joints does matter as it will be used for converting pink_ik actions to final control actions in IsaacLab. + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/unitree_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/G1_inspire_assets/retarget_inspire_white_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), ), ], sim_device=self.sim.device, @@ -395,11 +438,45 @@ def __post_init__(self): ), "manusvive": ManusViveCfg( retargeters=[ - UnitreeG1RetargeterCfg( - enable_visualization=True, - num_open_xr_hand_joints=2 * 26, + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_LEFT, + target_offset_rot=(0.7071, 0.0, 0.7071, 0.0), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + Se3AbsRetargeterCfg( + bound_hand=DeviceBase.TrackingTarget.HAND_RIGHT, + target_offset_rot=(0.0, 0.7071, 0.0, -0.7071), + zero_out_xy_rotation=False, + sim_device=self.sim.device, + ), + DexBiManualRetargeterCfg( + target_joint_names=original_hand_joints, sim_device=self.sim.device, - hand_joint_names=self.actions.pink_ik_cfg.hand_joint_names, + left_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_LEFT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=left_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/unitree_hand_left_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/G1_inspire_assets/retarget_inspire_white_left_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), + right_hand_cfg=DexHandRetargeterCfg( + target=DeviceBase.TrackingTarget.HAND_RIGHT, + enable_visualization=True, + num_open_xr_hand_joints=26, + sim_device=self.sim.device, + hand_joint_names=right_hand_joints, + hand_retargeting_config=os.path.join( + os.path.dirname(__file__), "config/dex_retargeting/unitree_hand_right_dexpilot.yml" + ), + hand_urdf=f"{ISAACLAB_NUCLEUS_DIR}/Mimic/G1_inspire_assets/retarget_inspire_white_right_hand.urdf", + handtracking_to_baselink_frame_transform=(0, 0, 1, 1, 0, 0, 0, 1, 0), + ), ), ], sim_device=self.sim.device, diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_abs_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_abs_env_cfg.py index add822599ad..c248ee6898b 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_abs_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_abs_env_cfg.py @@ -6,8 +6,8 @@ from isaaclab.controllers.differential_ik_cfg import DifferentialIKControllerCfg from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.openxr.openxr_device import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg -from isaaclab.devices.openxr.retargeters.manipulator.se3_abs_retargeter import Se3AbsRetargeterCfg +from isaaclab.devices.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg +from isaaclab.devices.retargeters.manipulator.se3_abs_retargeter import Se3AbsRetargeterCfg from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg from isaaclab.utils import configclass diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg.py index a543d7fe124..ae08a4372c5 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg.py @@ -7,8 +7,8 @@ from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.keyboard import Se3KeyboardCfg from isaaclab.devices.openxr.openxr_device import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg -from isaaclab.devices.openxr.retargeters.manipulator.se3_rel_retargeter import Se3RelRetargeterCfg +from isaaclab.devices.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg +from isaaclab.devices.retargeters.manipulator.se3_rel_retargeter import Se3RelRetargeterCfg from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg from isaaclab.utils import configclass diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg_skillgen.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg_skillgen.py index 10da599d3d9..5a4dbece564 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg_skillgen.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/franka/stack_ik_rel_env_cfg_skillgen.py @@ -7,8 +7,8 @@ from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.keyboard import Se3KeyboardCfg from isaaclab.devices.openxr.openxr_device import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg -from isaaclab.devices.openxr.retargeters.manipulator.se3_rel_retargeter import Se3RelRetargeterCfg +from isaaclab.devices.retargeters.manipulator.gripper_retargeter import GripperRetargeterCfg +from isaaclab.devices.retargeters.manipulator.se3_rel_retargeter import Se3RelRetargeterCfg from isaaclab.envs.mdp.actions.actions_cfg import DifferentialInverseKinematicsActionCfg from isaaclab.managers import ObservationGroupCfg as ObsGroup from isaaclab.managers import ObservationTermCfg as ObsTerm diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py index ff8df74a196..c5f5b02daeb 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_joint_pos_env_cfg.py @@ -8,7 +8,7 @@ from isaaclab.devices import DevicesCfg from isaaclab.devices.device_base import DeviceBase from isaaclab.devices.openxr.openxr_device import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters import GripperRetargeterCfg, Se3AbsRetargeterCfg +from isaaclab.devices.retargeters import GripperRetargeterCfg, Se3AbsRetargeterCfg from isaaclab.envs.mdp.actions.actions_cfg import SurfaceGripperBinaryActionCfg from isaaclab.managers import EventTermCfg as EventTerm from isaaclab.managers import ObservationGroupCfg as ObsGroup diff --git a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_rmp_rel_env_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_rmp_rel_env_cfg.py index a1c61cb87fb..febdbc45255 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_rmp_rel_env_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/manager_based/manipulation/stack/config/galbot/stack_rmp_rel_env_cfg.py @@ -10,7 +10,7 @@ from isaaclab.devices.device_base import DeviceBase, DevicesCfg from isaaclab.devices.keyboard import Se3KeyboardCfg from isaaclab.devices.openxr.openxr_device import OpenXRDeviceCfg -from isaaclab.devices.openxr.retargeters import GripperRetargeterCfg, Se3RelRetargeterCfg +from isaaclab.devices.retargeters import GripperRetargeterCfg, Se3RelRetargeterCfg from isaaclab.devices.spacemouse import Se3SpaceMouseCfg from isaaclab.envs.mdp.actions.rmpflow_actions_cfg import RMPFlowActionCfg from isaaclab.sensors import CameraCfg, FrameTransformerCfg