[Task Clean-up] Dexterous Part 9/9: Move the warp Direct task variants to isaaclab_tasks_experimental - #6582
[Task Clean-up] Dexterous Part 9/9: Move the warp Direct task variants to isaaclab_tasks_experimental#6582hujc7 wants to merge 11 commits into
Conversation
Add a behavioral Metrics/success_rate signal (goal-reach streaks per episode) and threshold-independent episode orientation-error diagnostics to the Direct reorientation environments, with the shared helpers in isaaclab_tasks.core.utils and torch math tests. The task logic is torch-first per the mainline convention; success gates task health while reward stays diagnostic. Also fix hand resets that could initialize joints below their lower position limits.
Fold the reviewed lump changes that belong to this part's content: - Share per-family sim settings through task-cfg base mixins. - Deduplicate backend scene presets via inner-class defaults and nest single-consumer helper cfgs in the shadow-hand Direct cfg. - Compute the orientation error through isaaclab.utils.math.quat_error_magnitude and delete the local direct_reorient_rotation_distance primitive. - Rename direct_reorient_reward to reorient_reward: shared symbols carry no paradigm prefix. Source commits on the lump branch: 2c22af0, 792e400, 42675b6, c6140f9, 173e9dc.
4ec232a to
2047011
Compare
Part 3 share of the lump readability round (cdaadac): the Direct cfg files keep only task values; asset and marker cfgs, name lists, backend presets, and noise cfgs move to shadow_hand_common and allegro_hand_common, task geometry to reorient_common, and reorient_task_base is removed. The Shadow Direct files carry the workflow marker in their names.
The shadow_hand_env_cfg -> shadow_hand_direct_env_cfg rename landed at this layer while two consumers kept importing the removed module name, so the part tree no longer stood alone (caught by arm-ci kitless rendering collection). Pin the camera cfg import to shadow_hand_direct_env_cfg and the handover robot cfg import to shadow_hand_common, matching the final tree.
The rename round updated the camera gym-registration entry-point strings to shadow_hand_direct_camera_env* at this layer, but the camera modules here still carry their pre-rename names, so every registry-driven cfg load failed at import (isaaclab_tasks suites, forbidden-imports test, registered-tasks rendering). Point the registrations back at the modules that exist at this layer.
…isualizer teardown (#6411) ## Review Map - **Exact changes**: a stacked PR's page shows the cumulative diff of its dependency chain; the link pins the commit range that is the PR's own contribution. - Links pin specific SHAs and can go stale after a branch update — the table on #6324 is refreshed first. | PR | Status | Depends on | Exact changes | |---|---|---|---| | #6410 [Docs] Environment overview regen |  | — | — | | 📌 #6411 Part 1/8: Newton cloner/cubric/visualizer fixes (this PR) |  | — | — | | #6412 Part 2/8: OVPhysX articulation + manager runtime |  | — | — | | #6413 Part 3/8: Reorient Direct, torch |  | — | — | | #6414 Part 4/8: MARL-to-single-agent fix + handover/camera Direct |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6414/changes/6e8a63e4e028b2d43676ea30c446b9dc9068c7b5..5cb00e7cb5cc813b202521272e043007cd255194) | | #6418 Part 5/8: Reorient manager counterparts |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/79f87501ac4c81de93a71dab00dc443da62113aa..e7c9a9a3fae3a7972b0c5165ae683abffb7d0e0f) | | #6421 Part 6/8: Handover + camera manager counterparts |  | #6413, #6414, #6418 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/01c9f4d8c5c35a5688b2a5bb90209e16b8f81b99..835a5815ec49b11aada1d20a76c177054505e6e7) | | #6415 Part 7/8: Benchmark success-rate utilities + docs |  | #6413, #6414, #6418, #6421 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6415/changes/e1abb6b1790ccc57af42551eebccf743633f1f13..d6348539aa8032d9668c20a8fea462c5d88d3af9) | | #6582 Part 8/8: Warp variants → experimental (draft; merges last) |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/21dbb1769c4e30c8e9e5b0f563c2dae24c230349..83e1587cadd9712a60615ed2a3cb2d177c2ac24d) | | #6324 [DO-NOT-MERGE] Lumped validation reference |  | ALL | — | ## Summary - Fixes Newton cloner label rows, the cubric IAdapter version audit (exact-match fallback to the CPU hierarchy path), and visualizer teardown. - Retains an in-tree `ignore_paths` workaround for custom-frequency USD traversal; it becomes redundant once the Newton pin advance (#6584) merges — this PR then only needs a rebase. ## Stacking - Independent; based on `develop`. ## Review history - Approved. The Newton pin + MuJoCo overrides were split out to #6584 via revert commits (2026-07-17) so this PR's CI runs against develop's pins.
Applies the P3-owned share of the lump review-response commits: - Default the dexterous tasks to newton_mjwarp (from 3f9ce324). - Drop solver defaults matching the backend + inline the scene preset via preset() instead of a wrapper class (from 29e189bf). - Simplify the Direct reorientation reward computation (from bfb73735). - Source the actuated-joint and fingertip body-name lists from the robot assets instead of the config module (from 34676102). Deferred to their owning layers: the core/utils relocation (S17) lands at the manager layer where reorient/mdp/events.py is introduced, and the handover default/preset changes land with the handover part.
Move the warp implementation of the Shadow reorientation and handover Direct environments (kernels, environments, kernel behavior tests) from the mainline task package to isaaclab_tasks_experimental, following the torch-first mainline convention. The variants register under -Direct-Warp-v0 IDs and reuse the stable configurations and agents. The Allegro warp variant keeps its existing legacy registration.
Mirror the mainline rename (reorient_reward) in the experimental warp package: the launcher is family-scoped, not paradigm-scoped, and the package already lives under direct/. Pure rename; no behavioral change.
83e1587 to
167c285
Compare
The vision env renders through the Isaac RTX tiled camera, whose render products require the Fabric cloning path. The Newton backend disables Fabric cloning, so under Newton the rgb annotator has no render products at num_envs > 1 and the default RGB/depth/semantic render fails with "Annotator rgb is not attached to any render products". The shared PhysicsCfg/RobotCfg/ObjectCfg now default to Newton, so the camera env inherited a Newton default it cannot render with. Override the camera env's backend PresetCfgs to default to PhysX in __post_init__; Newton stays selectable via physics=newton_mjwarp for the depth-only Newton-warp-renderer benchmark path.
…eorientation Direct tasks (#6413) ## Review Map - **Exact changes**: a stacked PR's page shows the cumulative diff of its dependency chain; the link pins the commit range that is the PR's own contribution. - Links pin specific SHAs and can go stale after a branch update — the table on #6324 is refreshed first. | PR | Status | Depends on | Exact changes | |---|---|---|---| | #6411 Part 1/9: Newton cloner/cubric/visualizer fixes |  | — | merged | | #6412 Part 2/9: OVPhysX articulation + manager runtime |  | — | merged | | 📌 #6413 Part 3/9: Reorient Direct, torch (this PR) |  | — | [changes](https://github.com/isaac-sim/IsaacLab/pull/6413/changes/f4895f0f9ee..d29afc75e71) | | #6414 Part 4/9: MARL-to-single-agent fix + handover/camera Direct |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6414/changes/d29afc75e71..b10a84948f8) | | #6418 Part 5/9: Reorient manager counterparts |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/d29afc75e71..707d37f8f99) | | #6421 Part 6/9: Handover + camera manager counterparts |  | #6413, #6414, #6418 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/707d37f8f99..b50ac8906fc) | | #6410 Part 7/9: Environment overview docs |  | #6421 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6410/changes/b50ac8906fc..af259c0778d) | | #6415 Part 8/9: Benchmark success-rate utilities |  | #6421 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6415/changes/b50ac8906fc..c7f2f019d8b) | | #6582 Part 9/9: Warp variants → experimental (draft; merges last) |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/d29afc75e71..167c28578b3) | | #6324 [DO-NOT-MERGE] Lumped validation reference |  | ALL | — | ## Summary - Adds a behavioral `Metrics/success_rate` signal (goal-reach streaks per episode) and threshold-independent episode orientation-error diagnostics to the Direct reorientation environments; success gates task health, reward stays diagnostic. - Task logic is **torch-first** per the mainline convention (plain torch buffers; `.torch` accessors only at the core-lib boundary). This supersedes the earlier warp-first revision of this PR; the warp implementation moved to `isaaclab_tasks_experimental` (#6582). - Lands shared helpers in `isaaclab_tasks.core.utils` (`EpisodeErrorRecorder`, `sample_joint_positions_within_limits`) with torch math tests; fixes hand resets below lower joint limits. ## Stacking - First stack PR; based on `develop`. ## Validation - Kit-free torch math + utils tests green; Direct state training on Newton: success rate 0.85–1.00, reward ≈3600–3900 at 2000 iterations, frame-verified policy video. Full integrated evidence: #6324. ## Review history - The earlier warp-era review rounds on this PR are superseded by the torch restack (2026-07-16); the warp implementation and its review-polished kernels live on in #6582.
AntoineRichard
left a comment
There was a problem hiding this comment.
[AI Review] Requesting changes. The current Part 9 head is not merge-ready: the new Gym registrations and environment modules contain stale imports, and the camera PhysX-default override is ineffective under the current PresetCfg resolution rules. The kernel tests are useful and pass on CPU/CUDA in CI, but they do not instantiate the registered environments; the current isaaclab_tasks [3/3] CI shard is red on the three Shadow Warp config loads.
Before re-review, please also tighten the source comments to durable functional constraints, remove hot-loop duplication/conversions called out inline, use concrete Warp array annotations on public launchers, and add an isaaclab_tasks changelog fragment for the camera-default change.
| entry_point=reorient_warp_entry, | ||
| disable_env_checker=True, | ||
| kwargs={ | ||
| "env_cfg_entry_point": f"{stable_shadow}.shadow_hand_env_cfg:ShadowHandEnvCfg", |
There was a problem hiding this comment.
[AI Review] Blocking: shadow_hand_env_cfg.py no longer exists. All three Shadow Warp registrations in this file use this stale module name, and the current isaaclab_tasks [3/3] CI shard fails exactly these three config loads. Point them to shadow_hand_direct_env_cfg, then add a registry/config-load test covering every new ID so a successful kernel-only suite cannot mask broken entry points.
| from isaaclab.sim.spawners.from_files import GroundPlaneCfg, spawn_ground_plane | ||
| from isaaclab.utils.math import sample_uniform | ||
|
|
||
| from isaaclab_tasks.core.reorient.reorient_task_base import GOAL_MARKER_POSITION, IN_HAND_POS_OFFSET |
There was a problem hiding this comment.
[AI Review] Blocking: reorient_task_base was removed; these constants now live in reorient_common. The TYPE_CHECKING import below also still names the removed shadow_hand_env_cfg instead of shadow_hand_direct_env_cfg. Once the registration strings are fixed, importing this environment will fail here, so please update both stale references and add an environment-entry import smoke test.
| from isaaclab.utils.math import sample_uniform | ||
|
|
||
| from isaaclab_tasks.core.handover.handover_env_cfg import HandoverEnvCfg | ||
| from isaaclab_tasks.core.handover.handover_task_base import GOAL_POSITION_OFFSET |
There was a problem hiding this comment.
[AI Review] Blocking: handover_task_base.py does not exist in this head, and GOAL_POSITION_OFFSET has no current definition. This makes the new handover entry point fail on import. Please put the goal definition at a genuine shared boundary (configuration or a small common module used by both torch and Warp implementations) rather than restoring a single-consumer “task base,” and cover the registered entry point with a smoke test.
There was a problem hiding this comment.
[AI Review][Pointed follow-up] The stable implementation currently hard-codes the goal at handover_env.py:73-77. That is the concrete duplication to remove: define one environment-frame GOAL_POSITION in handover_env_cfg.py or a handover_common.py, then make both HandoverEnv and HandoverWarpEnv consume it. Do not recreate the deleted handover_task_base.py solely to satisfy this import.
| # for the depth-only Newton-warp-renderer benchmark path (``presets=newton_renderer``). | ||
| super().__post_init__() | ||
| for backend_cfg in (self.sim.physics, self.robot_cfg, self.object_cfg): | ||
| backend_cfg.default = backend_cfg.physx |
There was a problem hiding this comment.
[AI Review] Blocking: assigning default on these PresetCfg instances does not change preset resolution. _preset_fields() explicitly prefers the class attribute, so the inherited class-level Newton defaults still win and the camera remains Newton-default. Define camera-specific preset types or declarative preset(...) fields whose class-level default is PhysX, and add a collect_presets(ShadowHandCameraEnvCfg()) assertion for physics, robot, and object defaults. The preceding seven-line rationale should also become one functional sentence, e.g. “Isaac RTX tiled cameras require the PhysX Fabric cloning path”; benchmark CLI history belongs in tests/docs, not this method.
There was a problem hiding this comment.
[AI Review][Pointed follow-up] The exact precedence rule is in _preset_fields(): getattr(type(preset_obj), field_name) wins over the instance field. The existing regression test_collect_fields_prefers_class_attr_over_instance codifies that behavior. Add the new camera-specific assertion beside the shadow_hand_camera_presets fixture, checking that sim.physics.default, robot_cfg.default, and object_cfg.default resolve to their PhysX alternatives.
| # the goal-reset flags, success counts, and moving average update in place. | ||
| # passing the time-out flags alone is exact here: the kernel ORs in the | ||
| # fallen-object condition itself, and that is this env's only other reset | ||
| reorient_reward( |
There was a problem hiding this comment.
[AI Review] The comment immediately above says reward reuses the success flags and orientation distances computed in _get_dones, but this call passes object/goal quaternions and reorient_reward_kernel recomputes _rotation_distance and the tolerance comparison. This is both misleading documentation and duplicate GPU hot-loop work. Pass success_flags and orientation_error_buf into the reward path, matching the torch implementation, and remove the redundant quaternion evaluation.
There was a problem hiding this comment.
[AI Review][Pointed follow-up] The stable torch path shows the intended API: ReorientDirectEnv._get_rewards() passes _success_flags and _orientation_error_buf into reorient_reward. By contrast, the Warp kernel recomputes both at reorient_kernels.py:283-288. Concretely, replace the object/target quaternion plus tolerance inputs with goal_reached: wp.array(dtype=wp.bool) and rotation_distance: wp.array(dtype=wp.float32), then use those values for the reset, bonus, and inverse-error reward.
| ema_actuation_kernel, | ||
| dim=(self.num_envs, self._actuated_dof_ids_wp.shape[0]), | ||
| inputs=[ | ||
| wp.from_torch(self.actions[agent]), |
There was a problem hiding this comment.
[AI Review] The initialization comment claims the hot loop launches kernels without conversions, but wp.from_torch(self.actions[agent]) is created here and again in _hand_proprio_obs for both agents every step. Use persistent per-agent action tensors, copy incoming actions into them in _pre_physics_step, and cache their Warp views once, as the reorientation variant already does.
| self.right_hand.write_joint_position_to_sim_index(position=dof_pos, env_ids=env_ids) | ||
| self.right_hand.write_joint_velocity_to_sim_index(velocity=dof_vel, env_ids=env_ids) | ||
|
|
||
| # reset left hand |
There was a problem hiding this comment.
[AI Review] The left-hand reset block duplicates the right-hand block above almost statement-for-statement. Please extract a _reset_hand(hand, prev_targets, curr_targets, env_ids) helper (or iterate a per-agent state map). This is exactly the kind of copied lifecycle code that drifts during follow-up fixes and is avoidable within this PR.
|
|
||
|
|
||
| def reorient_reward( | ||
| reset_buf: wp.array, |
There was a problem hiding this comment.
[AI Review] This public launcher uses generic wp.array annotations for every array argument, contrary to the repository requirement to annotate Warp arrays with concrete dimensionality and dtype. Please specify the actual contracts here (wp.bool, wp.float32, wp.vec3f, wp.quatf, and 2D float actions) and on the return type. compute_cube_keypoints() has the same issue.
There was a problem hiding this comment.
[AI Review][Pointed follow-up] The concrete annotation map is: reset_buf/goal_resets → wp.array(dtype=wp.bool), successes/consecutive_successes → wp.array(dtype=wp.float32), positions/origins → wp.array(dtype=wp.vec3f), quaternions → wp.array(dtype=wp.quatf), actions → wp.array2d(dtype=wp.float32), and the return → wp.array(dtype=wp.float32). For compute_cube_keypoints, use wp.array2d(dtype=wp.float32) for poses and wp.array2d(dtype=wp.vec3f) for keypoints. This makes the public launcher contract match the typed kernel signatures instead of discarding their information.
|
|
||
| """Warp kernels and device math for the reorientation task family. | ||
|
|
||
| This is the family's math root: the experimental Direct environments and the |
There was a problem hiding this comment.
[AI Review] Please reduce this module docstring to the module’s functional purpose. The long “math root”/step-order narrative is maintenance-heavy, and it claims manager terms consume these kernels even though the current tree only imports them from the experimental environments/tests. Keep execution contracts beside the relevant launcher; remove historical validation and aspirational dependency narration.
|
|
||
| """Warp kernels for the handover task family. | ||
|
|
||
| This is the family's math root: the experimental Direct environment launches |
There was a problem hiding this comment.
[AI Review] This “math root” and “reverse dependency never exists” prose is architectural narration rather than a functional kernel contract. A concise module description plus precise function-level frame/unit comments is enough. In particular, retain useful invariants such as world-frame versus environment-frame positions, but remove commentary about how the codebase is intended to be organized.
AntoineRichard
left a comment
There was a problem hiding this comment.
[AI Review][Comment cleanup] Follow-up pass covering every comment/docstring block that violates the requested standard. Each inline note identifies the exact narration, restatement, stale claim, or hard-coded dimensional prose to remove or rewrite. Comments that encode coordinate frames, zero-copy lifetime, unavailable-sensor behavior, sticky state, or synchronization constraints are intentionally left untouched.
| # The vision env renders through the Isaac RTX tiled camera, whose render | ||
| # products require the Fabric cloning path. The Newton backend disables Fabric | ||
| # cloning (see the base env's ``clone_in_fabric`` scene preset), so under Newton | ||
| # the ``rgb`` annotator has no render products for ``num_envs > 1`` and the | ||
| # default RGB/depth/semantic render fails. Default the vision env to PhysX so it | ||
| # renders out of the box; Newton stays selectable via ``physics=newton_mjwarp`` | ||
| # for the depth-only Newton-warp-renderer benchmark path (``presets=newton_renderer``). |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Replace this seven-line narrative with one durable functional constraint: # Isaac RTX tiled cameras require the PhysX Fabric cloning path. The failure history, num_envs scenario, CLI spelling, and benchmark path belong in the regression test or user documentation, not in __post_init__.
| Experimental counterpart of the torch-first mainline implementation in | ||
| :mod:`isaaclab_tasks.core.handover`; see the reorient variant for the conventions. |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Make this module docstring self-contained. “See the reorient variant for the conventions” forces readers to inspect an unrelated module and does not describe a functional contract. A single sentence such as Warp Direct environment for the Shadow handover task. is sufficient.
| # buffers for position targets | ||
| self.right_hand_prev_targets = torch.zeros( | ||
| (self.num_envs, self.num_hand_dofs), dtype=torch.float, device=self.device | ||
| ) | ||
| self.right_hand_curr_targets = torch.zeros( | ||
| (self.num_envs, self.num_hand_dofs), dtype=torch.float, device=self.device | ||
| ) | ||
| self.left_hand_prev_targets = torch.zeros( | ||
| (self.num_envs, self.num_hand_dofs), dtype=torch.float, device=self.device | ||
| ) | ||
| self.left_hand_curr_targets = torch.zeros( | ||
| (self.num_envs, self.num_hand_dofs), dtype=torch.float, device=self.device | ||
| ) | ||
|
|
||
| # list of actuated joints | ||
| self.actuated_dof_indices, _ = self.right_hand.find_joints(cfg.actuated_joint_names) | ||
| if len(self.actuated_dof_indices) != len(cfg.actuated_joint_names): | ||
| raise ValueError( | ||
| f"Expected {len(cfg.actuated_joint_names)} actuated joints, found {len(self.actuated_dof_indices)}." | ||
| ) | ||
|
|
||
| # finger bodies | ||
| self.finger_bodies, _ = self.right_hand.find_bodies(self.cfg.fingertip_body_names) | ||
| if len(self.finger_bodies) != len(self.cfg.fingertip_body_names): | ||
| raise ValueError( | ||
| f"Expected {len(self.cfg.fingertip_body_names)} fingertip bodies, found {len(self.finger_bodies)}." | ||
| ) | ||
| self.num_fingertips = len(self.finger_bodies) | ||
|
|
||
| # joint limits | ||
| joint_pos_limits = self.right_hand.data.joint_limits.torch.to(self.device) | ||
| self.hand_dof_lower_limits = joint_pos_limits[..., 0] | ||
| self.hand_dof_upper_limits = joint_pos_limits[..., 1] | ||
|
|
||
| # default goal positions | ||
| self.goal_rot = torch.zeros((self.num_envs, 4), dtype=torch.float, device=self.device) | ||
| self.goal_rot[:, 3] = 1.0 # identity quaternion in (x, y, z, w) layout | ||
| self.goal_pos = torch.zeros((self.num_envs, 3), dtype=torch.float, device=self.device) | ||
| # goal = object default position + shared offset (mirrors HandoverCommand.__init__) | ||
| self.goal_pos[:, :] = self.object.data.default_root_pose.torch[:, :3].to(self.device) + torch.tensor( | ||
| GOAL_POSITION_OFFSET, dtype=torch.float, device=self.device | ||
| ) | ||
| # initialize goal marker |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Remove the labels on lines 49, 63, 70, 78, 83, and 91; each merely repeats the immediately following variable lookup/allocation. Also drop the historical mirrors HandoverCommand.__init__ clause on line 87. Once the goal definition is moved to a shared config/common boundary, its name should carry that relationship; if a comment remains, document only the coordinate frame or invariant.
| self._success_flags = torch.empty(self.num_envs, dtype=torch.bool, device=self.device) | ||
| self._goal_distance_buf = torch.empty(self.num_envs, dtype=torch.float32, device=self.device) | ||
| self._reward_buf = torch.empty(self.num_envs, dtype=torch.float32, device=self.device) | ||
| # cached Warp views of the buffers above; the hot loop launches kernels without conversions |
There was a problem hiding this comment.
[AI Review][Comment cleanup] This comment is factually incorrect: action views are still created with wp.from_torch(...) in _apply_hand_action and _hand_proprio_obs every step. After introducing persistent per-agent action buffers, rewrite this narrowly as # Cache Warp views of persistent Torch buffers. Until then, remove it rather than claiming a property the implementation does not have.
| # add hand, in-hand object, and goal object | ||
| self.right_hand = Articulation(self.cfg.right_robot_cfg) | ||
| self.left_hand = Articulation(self.cfg.left_robot_cfg) | ||
| self.object = RigidObject(self.cfg.object_cfg) | ||
| # add ground plane | ||
| spawn_ground_plane(prim_path="/World/ground", cfg=GroundPlaneCfg()) | ||
| src, dest = "/World/envs/env_0", "/World/envs/env_{}" | ||
| pos = cloner.grid_transforms(self.scene.num_envs, self.scene.cfg.env_spacing, device=self.device)[0] | ||
| plan = cloner.ClonePlan.from_env_0(src, dest, self.scene.num_envs, self.device, pos) | ||
| cloner.replicate(plan, stage=self.scene.stage) | ||
| # add articulation to scene - we must register to scene to randomize with EventManager | ||
| self.scene.articulations["right_robot"] = self.right_hand | ||
| self.scene.articulations["left_robot"] = self.left_hand | ||
| self.scene.rigid_objects["object"] = self.object | ||
| # add lights |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Remove # add hand..., # add ground plane, and # add lights; they only narrate the next constructor/call. Keep the EventManager constraint on line 145, but tighten it to the functional reason: # Register assets with the scene for EventManager randomization.
| Launched over ``(num_envs, obs_dim)``: each thread walks a branch ladder over the | ||
| segment boundaries and writes one output column, so warps (32 consecutive columns) | ||
| stay branch-uniform except at segment boundaries. |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Keep the launch shape, but remove the speculative warp-uniformity explanation. The branch behavior is an implementation/performance claim without a benchmark or enforced invariant and makes this already-long observation docstring harder to scan.
| Launched over ``(num_envs, obs_dim)``: each thread walks a branch ladder over the | ||
| segment boundaries and writes one output column, so warps (32 consecutive columns) | ||
| stay branch-uniform except at segment boundaries. |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Keep the launch shape and output layout, but remove the warp-uniformity narrative. It is an implementation/performance claim rather than the kernel’s functional contract and duplicates the same prose in full_obs_kernel.
| reward: wp.array(dtype=wp.float32), | ||
| ): | ||
| i = wp.tid() | ||
| # Direct handover reward: exponential falloff with object-goal distance |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Remove this line; handover_reward_kernel, goal_distance, and the immediately following exponential expression already state exactly what it says.
| device=device, | ||
| ) | ||
| torch.testing.assert_close(dist, _rotation_distance_ref(q1, q2), atol=1e-4, rtol=1e-4) | ||
| # identical quaternions have zero distance |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Remove this comment. The test inputs (q1, q1.clone()), assertion, and test name make the zero-distance case self-explanatory.
| buffers=buffers, | ||
| **params, | ||
| ) | ||
| # torch reference |
There was a problem hiding this comment.
[AI Review][Comment cleanup] Remove this generic label. The _ref variable names and subsequent assertions already distinguish the Torch reference computation from the Warp result.
AntoineRichard
left a comment
There was a problem hiding this comment.
[AI Review][Pointed follow-up] Three additional places where the review should name the exact missing coverage or ownership boundary, rather than leaving the fixer to infer it.
| Added | ||
| ^^^^^ | ||
|
|
||
| * Added warp-first Direct variants of the Shadow cube reorientation and handover |
There was a problem hiding this comment.
[AI Review][Pointed follow-up] Part 9 also changes source/isaaclab_tasks/.../shadow_hand_camera_env_cfg.py, but this is the only fragment added by the Part 9 commit range. The inherited source/isaaclab_tasks/changelog.d/task-cleanup-dex-part03.minor.rst belongs to Part 3 and does not mention the camera default; after the stack is rebased, Part 9 will touch isaaclab_tasks with no fragment. Either move commit 386272f2 to its owning stable-task PR or add a separate source/isaaclab_tasks/changelog.d/<slug>.rst Fixed entry for the camera backend default.
| Kit-free: imports only torch/warp and the kernel module. Every kernel is | ||
| checked against an independent torch reference implementation on randomized | ||
| inputs, on CPU and CUDA. |
There was a problem hiding this comment.
[AI Review][Pointed follow-up] Keep these kernel tests Kit-free, but add a separate registration smoke test because these 44 cases never load an env_cfg_entry_point or import either environment class. The current CI failure proves the gap: parameterize the four new Gym IDs, resolve each config entry point, and import its environment entry point. That test would fail on all five stale references currently present (shadow_hand_env_cfg ×3, reorient_task_base, and handover_task_base) while preserving this file’s focused kernel contract.
| self.episode_length_buf_warp, | ||
| self._orientation_error.minimum_error, | ||
| self.time_out_flags, | ||
| self._orientation_error._has_sample, |
There was a problem hiding this comment.
[AI Review][Pointed follow-up] This reaches into EpisodeErrorRecorder._has_sample, a private field owned by isaaclab_tasks.core.utils, and makes the experimental kernel depend on that class’s internal storage layout. EpisodeErrorRecorder.update() is the public boundary and also owns shape/finite-value semantics. Expose an explicit Warp-compatible recorder API/buffer contract, or keep Warp-owned minimum/sample buffers in this environment and pass summarized values to the recorder at reset; do not bind a kernel output directly to another class’s private attribute.
… and enable handover Direct RSL-RL (#6414) ## Review Map - **Exact changes**: a stacked PR's page shows the cumulative diff of its dependency chain; the link pins the commit range that is the PR's own contribution. This PR (#6414) is now rebased directly onto `develop`, so its own **Files changed** tab is its contribution. - Links pin specific SHAs and can go stale after a branch update — the table on #6324 is refreshed first. | PR | Status | Depends on | Exact changes | |---|---|---|---| | #6411 Part 1/9: Newton cloner/cubric/visualizer fixes |  | — | merged | | #6412 Part 2/9: OVPhysX articulation + manager runtime |  | — | merged | | #6413 Part 3/9: Reorient Direct, torch |  | — | merged | | 📌 #6414 Part 4/9: MARL-to-single-agent fix + handover/camera Direct (this PR) |  | — (on develop) | Files changed tab | | #6418 Part 5/9: Reorient manager counterparts |  | #6413 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/d29afc75e71..707d37f8f99) | | #6421 Part 6/9: Handover + camera manager counterparts |  | #6414, #6418 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/707d37f8f99..b50ac8906fc) | | #6410 Part 7/9: Environment overview docs |  | #6421 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6410/changes/b50ac8906fc..af259c0778d) | | #6415 Part 8/9: Benchmark success-rate utilities |  | #6421 | [changes](https://github.com/isaac-sim/IsaacLab/pull/6415/changes/b50ac8906fc..c7f2f019d8b) | | #6582 Part 9/9: Warp variants → experimental (draft; merges last) |  | — | [changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/d29afc75e71..167c28578b3) | | #6324 [DO-NOT-MERGE] Lumped validation reference |  | ALL | — | ## Summary Converts the two-hand Shadow Hand **handover** task from multi-agent (MARL) to **single-agent** (enabling RSL-RL training), fixes the underlying MARL→single-agent observation bridge, and consolidates the shared Shadow Hand definitions into the asset. - **MARL → single-agent bridge (general, broader than this task).** Single-agent RL libraries train `DirectMARLEnv` tasks via `multi_agent_to_single_agent`; the bridge dropped the latest observations from the public buffer. Fixed generally — RSL-RL observations read from the env-owned `obs_buf`, stored by `reset` like `step` on all env bases (`DirectRLEnv`, `DirectMARLEnv`, the experimental warp base). Every MARL task + single-agent runner benefits; handover is the first consumer. - **Handover Direct → single-agent + RSL-RL.** Single-agent conversion, RSL-RL runner config, shared identity in `handover_common`, success-rate reward metrics, and a fix for its Newton construction failure (see below). - **Shadow Hand Newton robot → the asset.** Moved the Newton (MJWarp) robot cfg into `isaaclab_assets` as `SHADOW_HAND_NEWTON_CFG` (beside `SHADOW_HAND_CFG`); reorient and handover consume it as **siblings** (neither imports the other). Reorient uses the default gains; handover overrides only the finger stiffness/damping to `20/2` for its catch. - **Shadow camera cleanup.** Renamed the camera Direct modules to `shadow_hand_direct_camera_env[_cfg]`; moved cube-keypoint math to the shared, unit-tested `reorient/mdp/observations.py` (replacing the per-env `compute_keypoints` shim); and added OVPhysX physics presets to the handover and camera Direct environments. The camera env config is otherwise unchanged from develop. ### Behavior changes **Reorient-on-Newton is unchanged.** The Newton hand definition moves **verbatim** into `SHADOW_HAND_NEWTON_CFG` — same joint expressions, effort limits, gains, friction and armature — so its config diff vs `develop` is purely the move, and the Direct env config has no diff at all. Handover changes in three ways: - Its **default physics backend moves from PhysX to Newton** (MJWarp), matching the reorientation tasks. Pass `physics=physx` for the previous backend. - Its `distal_passive` actuator group is **removed**. It targeted `robot0_(FF|MF|RF|LF)J0` — joints that **do not exist** on the Newton asset (its fingers are numbered `J1`–`J4`/`J5`), so constructing the environment raised `No joints found for actuator group`. The `fingers` group already drives those joints, and the comment justifying the group (USD-baked `stiffness=286/damping=57`) does not apply to this asset, which authors no drive stiffness at all. - Two orientation fixes: the goal orientation was initialized to a 180-degree rotation instead of identity, and the Newton root rotation replaced the asset's baked rotation instead of composing with it, leaving both palms rotated 90 degrees. Two pre-existing discrepancies were found while verifying against the asset and are left for a follow-up, since each is a behavior change needing its own validation: the config sets `armature=2e-3` where the asset authors `0.0002`, and the per-finger `J1`/`J2` pair is coupled by a fixed tendon that the MJWarp solver currently skips — the actuator gains are what hold that pair together today, which is why the `J4` knuckle-abduction joints cannot simply be added to the driven set. ## Notes - Rebased onto **latest develop**; clean 3-commit history: `Add single-agent flattening for MARL Direct environments` / `Convert Shadow Hand handover to single-agent Direct with RSL-RL` / `Clean up Shadow reorient/camera tasks and consolidate the Newton hand`. ## Validation - Kit-free suite green: handover, keypoint math, the MARL adapter, and new checks pinning the RSL-RL wrapper observation contract (verified to fail against the previous implementation). - Camera Direct reaches training takeoff under `rsl_rl` (frame-verified videos); its env config now matches develop's established vision env. - **Reorient-on-Newton vs `develop`** (`rsl_rl`, 2048 envs, 1500 iterations, 4 runs per config): this branch spans 524–664 reward, `develop` spans 654–822 — overlapping distributions whose per-config spreads (140–168) exceed the gap between them. The move is additionally verified at the config level: the Newton robot configuration is character-for-character identical to `develop`'s. - **Handover-on-Newton** trains end-to-end on this branch (reward 1314), which the `develop` config cannot do at all — it fails during construction. Full evidence: #6324.
Review Map
Summary
isaaclab_tasks_experimental, following the torch-first mainline convention: torch task logic inisaaclab_tasks, warp implementations in the experimental track.-Direct-Warp-v0IDs and reuse the stable configurations and agents fromisaaclab_tasks.core. The Allegro warp variant keeps its existing legacy registration in the experimental package.Stacking
DirectRLEnvWarp) and the performance focus for the experimental variants are follow-on scope, out of this series.Validation