Skip to content

[Task Clean-up] Dexterous Part 9/9: Move the warp Direct task variants to isaaclab_tasks_experimental - #6582

Draft
hujc7 wants to merge 11 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-warp-exp
Draft

[Task Clean-up] Dexterous Part 9/9: Move the warp Direct task variants to isaaclab_tasks_experimental#6582
hujc7 wants to merge 11 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-warp-exp

Conversation

@hujc7

@hujc7 hujc7 commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Review Map

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 changes
#6414 Part 4/9: MARL-to-single-agent fix + handover/camera Direct #6413 changes
#6418 Part 5/9: Reorient manager counterparts #6413 changes
#6421 Part 6/9: Handover + camera manager counterparts #6413, #6414, #6418 changes
#6410 Part 7/9: Environment overview docs #6421 changes
#6415 Part 8/9: Benchmark success-rate utilities #6421 changes
📌 #6582 Part 9/9: Warp variants → experimental (draft; merges last) (this PR) #6413 changes
#6324 [DO-NOT-MERGE] Lumped validation reference ALL

Summary

  • Moves the warp-first implementation of the Shadow reorientation and handover Direct environments (kernels, environments, kernel behavior tests) to isaaclab_tasks_experimental, following the torch-first mainline convention: torch task logic in isaaclab_tasks, warp implementations in the experimental track.
  • The variants register under -Direct-Warp-v0 IDs and reuse the stable configurations and agents from isaaclab_tasks.core. The Allegro warp variant keeps its existing legacy registration in the experimental package.
  • The diff is largely the review-polished warp implementation from the lumped validation branch [DO-NOT-MERGE][Task Clean-up] Dexterous: lumped validation branch (series reference) #6324, relocated with import-path updates.

Stacking

Validation

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.
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-warp-exp branch from 4ec232a to 2047011 Compare July 18, 2026 11:10
hujc7 added 4 commits July 20, 2026 15:32
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.
hujc7 added a commit that referenced this pull request Jul 22, 2026
…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 |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6410?label=)
| — | — |
| 📌 #6411 Part 1/8: Newton cloner/cubric/visualizer fixes (this PR) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6411?label=)
| — | — |
| #6412 Part 2/8: OVPhysX articulation + manager runtime |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6412?label=)
| — | — |
| #6413 Part 3/8: Reorient Direct, torch |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6413?label=)
| — | — |
| #6414 Part 4/8: MARL-to-single-agent fix + handover/camera Direct |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6414?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6414/changes/6e8a63e4e028b2d43676ea30c446b9dc9068c7b5..5cb00e7cb5cc813b202521272e043007cd255194)
|
| #6418 Part 5/8: Reorient manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6418?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/79f87501ac4c81de93a71dab00dc443da62113aa..e7c9a9a3fae3a7972b0c5165ae683abffb7d0e0f)
|
| #6421 Part 6/8: Handover + camera manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6421?label=)
| #6413, #6414, #6418 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/01c9f4d8c5c35a5688b2a5bb90209e16b8f81b99..835a5815ec49b11aada1d20a76c177054505e6e7)
|
| #6415 Part 7/8: Benchmark success-rate utilities + docs |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6415?label=)
| #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) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6582?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/21dbb1769c4e30c8e9e5b0f563c2dae24c230349..83e1587cadd9712a60615ed2a3cb2d177c2ac24d)
|
| #6324 [DO-NOT-MERGE] Lumped validation reference |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6324?label=)
| 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.
hujc7 added 4 commits July 23, 2026 13:26
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.
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-warp-exp branch from 83e1587 to 167c285 Compare July 23, 2026 21:35
@github-actions github-actions Bot added the asset New asset feature or request label Jul 23, 2026
@hujc7 hujc7 changed the title [Task Clean-up] Dexterous Part 8/8: Move the warp Direct task variants to isaaclab_tasks_experimental [Task Clean-up] Dexterous Part 8/9: Move the warp Direct task variants to isaaclab_tasks_experimental Jul 23, 2026
@hujc7 hujc7 changed the title [Task Clean-up] Dexterous Part 8/9: Move the warp Direct task variants to isaaclab_tasks_experimental [Task Clean-up] Dexterous Part 9/9: Move the warp Direct task variants to isaaclab_tasks_experimental Jul 23, 2026
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.
hujc7 added a commit that referenced this pull request Jul 24, 2026
…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 |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6411?label=)
| — | merged |
| #6412 Part 2/9: OVPhysX articulation + manager runtime |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6412?label=)
| — | merged |
| 📌 #6413 Part 3/9: Reorient Direct, torch (this PR) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6413?label=)
| — |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6413/changes/f4895f0f9ee..d29afc75e71)
|
| #6414 Part 4/9: MARL-to-single-agent fix + handover/camera Direct |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6414?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6414/changes/d29afc75e71..b10a84948f8)
|
| #6418 Part 5/9: Reorient manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6418?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/d29afc75e71..707d37f8f99)
|
| #6421 Part 6/9: Handover + camera manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6421?label=)
| #6413, #6414, #6418 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/707d37f8f99..b50ac8906fc)
|
| #6410 Part 7/9: Environment overview docs |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6410?label=)
| #6421 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6410/changes/b50ac8906fc..af259c0778d)
|
| #6415 Part 8/9: Benchmark success-rate utilities |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6415?label=)
| #6421 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6415/changes/b50ac8906fc..c7f2f019d8b)
|
| #6582 Part 9/9: Warp variants → experimental (draft; merges last) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6582?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/d29afc75e71..167c28578b3)
|
| #6324 [DO-NOT-MERGE] Lumped validation reference |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6324?label=)
| 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 AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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]),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[AI Review][Pointed follow-up] The concrete annotation map is: reset_buf/goal_resetswp.array(dtype=wp.bool), successes/consecutive_successeswp.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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +125 to +131
# 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``).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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__.

Comment on lines +8 to +9
Experimental counterpart of the torch-first mainline implementation in
:mod:`isaaclab_tasks.core.handover`; see the reorient variant for the conventions.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +49 to +91
# 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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +135 to +149
# 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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +614 to +616
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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +55 to +57
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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 AntoineRichard left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment on lines +8 to +10
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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

hujc7 added a commit that referenced this pull request Jul 29, 2026
… 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 |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6411?label=)
| — | merged |
| #6412 Part 2/9: OVPhysX articulation + manager runtime |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6412?label=)
| — | merged |
| #6413 Part 3/9: Reorient Direct, torch |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6413?label=)
| — | merged |
| 📌 #6414 Part 4/9: MARL-to-single-agent fix + handover/camera Direct
(this PR) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6414?label=)
| — (on develop) | Files changed tab |
| #6418 Part 5/9: Reorient manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6418?label=)
| #6413 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6418/changes/d29afc75e71..707d37f8f99)
|
| #6421 Part 6/9: Handover + camera manager counterparts |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6421?label=)
| #6414, #6418 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6421/changes/707d37f8f99..b50ac8906fc)
|
| #6410 Part 7/9: Environment overview docs |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6410?label=)
| #6421 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6410/changes/b50ac8906fc..af259c0778d)
|
| #6415 Part 8/9: Benchmark success-rate utilities |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6415?label=)
| #6421 |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6415/changes/b50ac8906fc..c7f2f019d8b)
|
| #6582 Part 9/9: Warp variants → experimental (draft; merges last) |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6582?label=)
| — |
[changes](https://github.com/isaac-sim/IsaacLab/pull/6582/changes/d29afc75e71..167c28578b3)
|
| #6324 [DO-NOT-MERGE] Lumped validation reference |
![](https://img.shields.io/github/pulls/detail/state/isaac-sim/IsaacLab/6324?label=)
| 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants