|
9 | 9 | from isaaclab_physx.physics import PhysxCfg |
10 | 10 |
|
11 | 11 | import isaaclab.sim as sim_utils |
12 | | -import isaaclab.utils.math as math_utils |
13 | | -from isaaclab.assets import ArticulationCfg, RigidObjectCfg |
| 12 | +from isaaclab.assets import RigidObjectCfg |
| 13 | +from isaaclab.assets.articulation import ArticulationCfg |
14 | 14 | from isaaclab.envs import DirectMARLEnvCfg |
15 | 15 | from isaaclab.markers import VisualizationMarkersCfg |
16 | 16 | from isaaclab.physics import PhysxAutoCfg |
17 | 17 | from isaaclab.scene import InteractiveSceneCfg |
18 | 18 | from isaaclab.sim import SimulationCfg |
19 | 19 | from isaaclab.sim.spawners.materials import RigidBodyMaterialBaseCfg |
| 20 | +from isaaclab.utils import math as math_utils |
20 | 21 | from isaaclab.utils.configclass import configclass |
21 | | - |
22 | | -from isaaclab_tasks.core.handover.handover_common import ( |
23 | | - ACTUATED_JOINT_NAMES, |
24 | | - FINGERTIP_BODY_NAMES, |
25 | | - GOAL_MARKER_CFG, |
26 | | - OBJECT_RADIUS, |
| 22 | +from isaaclab.visualizers import VisualizerCfg |
| 23 | + |
| 24 | +from isaaclab_tasks.core.handover.handover_common import GOAL_MARKER_CFG, OBJECT_RADIUS |
| 25 | +from isaaclab_tasks.utils import PresetCfg |
| 26 | + |
| 27 | +from isaaclab_assets.robots.shadow_hand import ( |
| 28 | + FINGERTIP_NAMES, |
| 29 | + JOINT_NAMES, |
| 30 | + SHADOW_HAND_NEWTON_CFG, |
| 31 | + SHADOW_HAND_PHYSX_CFG, |
| 32 | + TENDON_NAMES, |
| 33 | + TENDON_POSITION_LIMITS, |
27 | 34 | ) |
28 | | -from isaaclab_tasks.utils import PresetCfg, preset |
29 | | - |
30 | | -from isaaclab_assets.robots.shadow_hand import SHADOW_HAND_CFG, SHADOW_HAND_NEWTON_CFG |
31 | 35 |
|
32 | 36 |
|
33 | | -def _shadow_hand_cfg( |
| 37 | +def _hand_cfg( |
| 38 | + base: ArticulationCfg, |
34 | 39 | prim_path: str, |
35 | 40 | init_pos: tuple[float, float, float], |
36 | 41 | init_rot: tuple[float, float, float, float], |
37 | | -) -> PresetCfg: |
38 | | - """Build the per-hand Shadow Hand preset for each supported backend. |
| 42 | +) -> ArticulationCfg: |
| 43 | + """Place one engine's Shadow Hand at this task's pose for one hand. |
| 44 | +
|
| 45 | + The catch needs more joint authority than reorientation, but the hand's gains belong to the |
| 46 | + hand, so both tasks take them as the asset configuration supplies them. This task used to raise |
| 47 | + every actuator to stiffness 20 / damping 2, which also drove the tendon-coupled joints -- they |
| 48 | + take no position command, and MEASURED, giving them one costs the tendon most of its travel: |
| 49 | + 11.1 rad falls to 1.0 rad. |
39 | 50 |
|
40 | 51 | Args: |
| 52 | + base: The hand on the engine's asset variant. |
41 | 53 | prim_path: Scene path the hand spawns at. |
42 | 54 | init_pos: Spawn position [m]. |
43 | 55 | init_rot: Spawn orientation as ``(w, x, y, z)``. |
44 | 56 |
|
45 | 57 | Returns: |
46 | | - A preset carrying the PhysX, Newton MJWarp and OvPhysX variants, each at |
47 | | - *prim_path* with the given pose. The two hands differ only in these arguments. |
| 58 | + That configuration at *prim_path* with the given pose. |
48 | 59 | """ |
49 | | - physx_cfg = SHADOW_HAND_CFG.replace(prim_path=prim_path).replace( |
50 | | - init_state=ArticulationCfg.InitialStateCfg(pos=init_pos, rot=init_rot, joint_pos={".*": 0.0}) |
51 | | - ) |
52 | | - # Newton's importer bakes the asset's root orientation into the root joint (see the note on |
53 | | - # SHADOW_HAND_NEWTON_CFG.init_state), so the task rotation must compose with it rather than |
54 | | - # replace it — replacing leaves both palms rotated 90 degrees. |
55 | | - newton_rot = tuple( |
| 60 | + # The asset's own spawn rotation is shared by both engines, so the per-hand rotation COMPOSES |
| 61 | + # with it rather than replacing it -- replacing leaves both palms turned 90 degrees. See |
| 62 | + # SHADOW_HAND_PHYSX_CFG's init_state for why the asset carries that rotation. |
| 63 | + hand_rot = tuple( |
56 | 64 | math_utils.quat_mul( |
57 | 65 | torch.tensor(init_rot, dtype=torch.float64), |
58 | | - torch.tensor(SHADOW_HAND_NEWTON_CFG.init_state.rot, dtype=torch.float64), |
| 66 | + torch.tensor(base.init_state.rot, dtype=torch.float64), |
59 | 67 | ).tolist() |
60 | 68 | ) |
61 | | - newton_mjwarp_cfg = SHADOW_HAND_NEWTON_CFG.replace( |
62 | | - prim_path=prim_path, |
63 | | - init_state=SHADOW_HAND_NEWTON_CFG.init_state.replace(pos=init_pos, rot=newton_rot), |
64 | | - actuators={ |
65 | | - **SHADOW_HAND_NEWTON_CFG.actuators, |
66 | | - "fingers": SHADOW_HAND_NEWTON_CFG.actuators["fingers"].replace(stiffness=20.0, damping=2.0), |
67 | | - }, |
68 | | - ) |
69 | | - ovphysx_cfg = SHADOW_HAND_CFG.replace( |
| 69 | + return base.replace( |
70 | 70 | prim_path=prim_path, |
71 | | - # OVPhysX does not expose the fixed-tendon runtime API, so spawn without tendon overrides. |
72 | | - spawn=SHADOW_HAND_CFG.spawn.replace(fixed_tendons_props=None), |
73 | | - init_state=SHADOW_HAND_CFG.init_state.replace(pos=init_pos, rot=init_rot), |
74 | | - ) |
75 | | - return preset( |
76 | | - default=newton_mjwarp_cfg, |
77 | | - physx=physx_cfg, |
78 | | - isaacsim_physx=physx_cfg, |
79 | | - newton_mjwarp=newton_mjwarp_cfg, |
80 | | - ovphysx=ovphysx_cfg, |
| 71 | + init_state=base.init_state.replace(pos=init_pos, rot=hand_rot), |
81 | 72 | ) |
82 | 73 |
|
83 | 74 |
|
84 | | -# Per-hand presets shared by the Direct environment and the manager scene. |
85 | | -RIGHT_HAND_CFG = _shadow_hand_cfg( |
86 | | - prim_path="{ENV_REGEX_NS}/RightRobot", |
87 | | - init_pos=(0.0, 0.0, 0.5), |
88 | | - init_rot=(0.0, 0.0, 0.0, 1.0), |
89 | | -) |
90 | | -LEFT_HAND_CFG = _shadow_hand_cfg( |
91 | | - prim_path="{ENV_REGEX_NS}/LeftRobot", |
92 | | - init_pos=(0.0, -1.0, 0.5), |
93 | | - init_rot=(0.0, 0.0, 1.0, 0.0), |
94 | | -) |
| 75 | +# Per-hand poses. The rotations are composed with the asset's own; they are unchanged from the |
| 76 | +# previous Newton asset, which the two assets being identical geometry makes valid. |
| 77 | +_RIGHT_POSE = ("{ENV_REGEX_NS}/RightRobot", (0.0, 0.0, 0.5), (0.0, 0.0, 0.0, 1.0)) |
| 78 | +_LEFT_POSE = ("{ENV_REGEX_NS}/LeftRobot", (0.0, -1.0, 0.5), (0.0, 0.0, 1.0, 0.0)) |
| 79 | + |
| 80 | + |
| 81 | +@configclass |
| 82 | +class RightHandCfg(PresetCfg): |
| 83 | + """The right hand on every engine; only the asset's physics variant differs.""" |
| 84 | + |
| 85 | + newton_mjwarp = _hand_cfg(SHADOW_HAND_NEWTON_CFG, *_RIGHT_POSE) |
| 86 | + isaacsim_physx = _hand_cfg(SHADOW_HAND_PHYSX_CFG, *_RIGHT_POSE) |
| 87 | + physx = isaacsim_physx |
| 88 | + ovphysx = isaacsim_physx |
| 89 | + default = newton_mjwarp |
| 90 | + |
| 91 | + |
| 92 | +@configclass |
| 93 | +class LeftHandCfg(PresetCfg): |
| 94 | + """The left hand on every engine; only the asset's physics variant differs.""" |
| 95 | + |
| 96 | + newton_mjwarp = _hand_cfg(SHADOW_HAND_NEWTON_CFG, *_LEFT_POSE) |
| 97 | + isaacsim_physx = _hand_cfg(SHADOW_HAND_PHYSX_CFG, *_LEFT_POSE) |
| 98 | + physx = isaacsim_physx |
| 99 | + ovphysx = isaacsim_physx |
| 100 | + default = newton_mjwarp |
95 | 101 |
|
96 | 102 |
|
97 | 103 | BALL_CFG = RigidObjectCfg( |
@@ -169,13 +175,18 @@ class HandoverEnvCfg(DirectMARLEnvCfg): |
169 | 175 | render_interval=decimation, |
170 | 176 | physics_material=RigidBodyMaterialBaseCfg(static_friction=1.0, dynamic_friction=1.0), |
171 | 177 | physics=PhysicsCfg(), |
| 178 | + # Frame both hands and the object between them. Without this the visualizer looks at the |
| 179 | + # origin from its default 4 m away, which renders the pair a few pixels wide. |
| 180 | + default_visualizer_cfg=VisualizerCfg(eye=(1.15, -1.65, 1.15), lookat=(0.0, -0.5, 0.55), focal_length=35.0), |
172 | 181 | ) |
173 | 182 |
|
174 | 183 | # robot |
175 | | - right_robot_cfg: PresetCfg = RIGHT_HAND_CFG |
176 | | - left_robot_cfg: PresetCfg = LEFT_HAND_CFG |
177 | | - actuated_joint_names = ACTUATED_JOINT_NAMES |
178 | | - fingertip_body_names = FINGERTIP_BODY_NAMES |
| 184 | + right_robot_cfg: RightHandCfg = RightHandCfg() |
| 185 | + left_robot_cfg: LeftHandCfg = LeftHandCfg() |
| 186 | + actuated_joint_names = JOINT_NAMES |
| 187 | + actuated_tendon_names = TENDON_NAMES |
| 188 | + actuated_tendon_position_limits = TENDON_POSITION_LIMITS |
| 189 | + fingertip_body_names = FINGERTIP_NAMES |
179 | 190 |
|
180 | 191 | # in-hand object |
181 | 192 | object_cfg: RigidObjectCfg = BALL_CFG |
|
0 commit comments