Skip to content

[Task Clean-up][Manager] Dexterous Part 6/9: Add the handover and camera manager counterparts - #6421

Draft
hujc7 wants to merge 7 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-part11
Draft

[Task Clean-up][Manager] Dexterous Part 6/9: Add the handover and camera manager counterparts#6421
hujc7 wants to merge 7 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-part11

Conversation

@hujc7

@hujc7 hujc7 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

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 go stale after a branch update. Parts 7–9 are pending a rebase onto the current stack, so their ranges are omitted rather than shown wrong.
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 merged
#6418 Part 5/9: Reorient manager counterparts
📌 #6421 Part 6/9: Handover + camera manager counterparts #6418 changes
#6410 Part 7/9: Environment overview docs #6421 pending rebase
#6415 Part 8/9: Benchmark success-rate utilities #6421 pending rebase
#6582 Part 9/9: Warp variants → experimental (draft; merges last) pending rebase
#6324 [DO-NOT-MERGE] Lumped validation reference ALL

Summary

Completes manager coverage of the dexterous task families by adding manager-based counterparts
for the Shadow handover and Shadow camera reorientation tasks. Stacks on
#6418 — [Task Clean-up][Manager] Dexterous Part 5/9: Add the reorientation manager counterparts

  • 2 manager tasks added: Isaac-Handover-Shadow and Isaac-Reorient-Cube-Shadow-Camera.
  • The last 2 -Play registrations in isaaclab_tasks are removed.

1. Handover manager counterpart

The fused handover reward became a plain reward term, with success and goal-distance
bookkeeping moved to HandoverCommand, which owns the goal. It reports Metrics/success_rate as
a per-episode bit, matching the handover Direct environment. A value-parity test covers the
handover pair alongside the reorientation ones.

HandoverCommand.command builds its pose per call rather than returning a persistent buffer, so
consumers that store it across steps are not aliased to live data.

2. Camera manager counterpart

The camera task runs on PhysX by default: the RTX render modalities require Fabric cloning,
which Newton does not support, so the inherited default could not render. Newton remains
selectable with physics=newton_mjwarp for the state-only observation groups.

The feature-extractor observation term ignored its declared feature_extractor_cfg parameter
and read the environment configuration instead; it now honours the parameter.

3. Camera playback moves to play_mode

Isaac-Reorient-Cube-Shadow-Camera-Play and -Camera-Direct-Play were the last -Play
registrations left in isaaclab_tasks; every other task moved to play_mode in
#6676 — Remove the _PLAY configs. Their playback
environment count and inference feature extractor now live in play_mode overrides on the
manager and Direct camera configurations.

The override mutates the feature extractor rather than replacing it. Replacing the object
resets every field the caller does not name, which silently re-enabled the CNN in
ShadowHandCameraBenchmarkEnvCfg — a configuration whose entire purpose is to disable it.

4. Reorientation action configuration

The action term is named through a module path, so loading a task configuration no longer
imports the USD bindings.

Validation

Handover manager reaches a success rate of 0.859 against the Direct task's 0.667 over 1500
iterations at seed 42. The camera task's registered-rendering matrix and golden images are
tracked separately.

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds the manager-based counterpart for the two-hand Shadow Hand handover task (Isaac-Shadow-Handover), completing Part 11 of the dexterous task clean-up series. It introduces a new MDP term set (commands, events, observations, rewards, terminations), wires them into a HandoverManagerEnvCfg, and lands the family-wide OVPhysX acceptance test and handover configuration tests that depend on all prior parts being merged.

Confidence Score: 4/5

The change adds new files only (plus a two-line extension to init.py); no existing behavior is modified. The new env config correctly delegates scene/physics to the Direct base, and the MDP terms are consistent in frame conventions.

All newly added files follow the established lazy_export + PresetCfg pattern from the reorient task family. Frame conventions (local vs world) are consistent across commands, events, observations, and rewards. The single finding — storing two log values as zero-dim tensors while adjacent keys use .item() — is an inconsistency that could silently break a strict logging backend but does not affect training correctness.

source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/rewards.py — the dist_reward/dist_goal logging inconsistency noted above.

Important Files Changed

Filename Overview
source/isaaclab_tasks/isaaclab_tasks/core/handover/handover_manager_env_cfg.py New manager-based handover env config; delegates all scene/physics/action settings to the Direct base config via module-level _DIRECT_CFG and PresetCfg presets. Clean structure with no logic bugs found.
source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/rewards.py HandoverReward class computes sticky episode success and logs diagnostics; dist_reward and dist_goal are stored as zero-dim tensors without .item(), unlike the Metrics/* keys. Reward scaling via /step_dt is intentional and explained in comments.
source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/commands.py HandoverCommand samples fixed goal position from object default_root_pose plus offset and randomizes X/Y orientation per episode; consistent with Direct env's distribution. Goal position is correctly in local/env frame throughout.
source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/events.py reset_handover_state mirrors Direct env's reset distribution for object pose/velocity and both hands; uses env._handover_reset_actions side-channel to thread pre-reset actions into observations cleanly.
source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/observations.py All seven observation terms are frame-consistent (local/env frame for positions, world frame for velocities which are origin-invariant). object_goal returns a 24-dim block matching the Direct env layout.
source/isaaclab_tasks/isaaclab_tasks/core/handover/mdp/terminations.py Two simple termination terms: height-based fall detection and direct_timeout that exactly matches the Direct MARL boundary (>= max_episode_length - 1).
source/isaaclab_tasks/isaaclab_tasks/core/handover/init.py Registers new Isaac-Shadow-Handover manager env and adds rsl_rl_cfg_entry_point to the existing Direct registration.
source/isaaclab_tasks/test/core/test_handover_env_cfg.py New config tests verify asset reuse, pose consistency across backends, and Newton distal-joint override. Tests look correct and cover the key structural invariants.
source/isaaclab_tasks/test/core/test_dexterous_ovphysx_presets.py Family-wide OVPhysX acceptance test covering 15 dexterous variants including the new HandoverManagerEnvCfg; also tests Newton presets for allegro/handover variants.
source/isaaclab_tasks/test/benchmarking/configs.yaml Adds Isaac-Shadow-Handover benchmark row with same thresholds as the existing Direct variant (max_iterations=3000, reward>=1000, episode_length>=150).

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[ManagerBasedRLEnv\nIsaac-Shadow-Handover] --> B[HandoverManagerEnvCfg]

    B --> C[HandoverManagerSceneCfg\nPresetCfg: physx / newton_mjwarp / ovphysx]
    C --> C1[_HandoverManagerSceneCfg\nright_hand / left_hand / object]
    C1 --> C2[_DIRECT_CFG.right_robot_cfg\n_DIRECT_CFG.left_robot_cfg]

    B --> D[ActionsCfg\nEMAJointPositionToLimitsActionCfg\nright_hand + left_hand]
    B --> E[CommandsCfg\nHandoverCommand\nfixed pos + random X/Y orientation]
    B --> F[ObservationsCfg\nPolicyCfg: right 157-dim + left 157-dim]
    B --> G[EventCfg\nreset_handover_state]
    B --> H[RewardsCfg\nHandoverReward\n2x exp reward / step_dt]
    B --> I[TerminationsCfg\nobject_below_height + direct_timeout]

    G -->|env._handover_reset_actions| J[hand_action obs term]
    H -->|sticky success flag| K[Metrics/success_rate at reset]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[ManagerBasedRLEnv\nIsaac-Shadow-Handover] --> B[HandoverManagerEnvCfg]

    B --> C[HandoverManagerSceneCfg\nPresetCfg: physx / newton_mjwarp / ovphysx]
    C --> C1[_HandoverManagerSceneCfg\nright_hand / left_hand / object]
    C1 --> C2[_DIRECT_CFG.right_robot_cfg\n_DIRECT_CFG.left_robot_cfg]

    B --> D[ActionsCfg\nEMAJointPositionToLimitsActionCfg\nright_hand + left_hand]
    B --> E[CommandsCfg\nHandoverCommand\nfixed pos + random X/Y orientation]
    B --> F[ObservationsCfg\nPolicyCfg: right 157-dim + left 157-dim]
    B --> G[EventCfg\nreset_handover_state]
    B --> H[RewardsCfg\nHandoverReward\n2x exp reward / step_dt]
    B --> I[TerminationsCfg\nobject_below_height + direct_timeout]

    G -->|env._handover_reset_actions| J[hand_action obs term]
    H -->|sticky success flag| K[Metrics/success_rate at reset]
Loading

Reviews (1): Last reviewed commit: "Add the Shadow handover manager counterp..." | Re-trigger Greptile

Comment on lines +80 to +82
env.extras.setdefault("log", {})["dist_reward"] = per_agent_reward.mean()
env.extras["log"]["dist_goal"] = goal_distance.mean()
env.extras["log"]["Metrics/goal_distance"] = goal_distance.mean().item()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Mixed tensor/scalar types in extras log dict. dist_reward and dist_goal are stored as zero-dim PyTorch tensors (.mean() without .item()), while the Metrics/* keys on the very next lines use .item() to produce Python floats. A logging backend that serializes extras["log"] to JSON or passes values to a scalar summarizer will silently fail or produce unexpected output for those two keys.

Suggested change
env.extras.setdefault("log", {})["dist_reward"] = per_agent_reward.mean()
env.extras["log"]["dist_goal"] = goal_distance.mean()
env.extras["log"]["Metrics/goal_distance"] = goal_distance.mean().item()
env.extras.setdefault("log", {})["dist_reward"] = per_agent_reward.mean().item()
env.extras["log"]["dist_goal"] = goal_distance.mean().item()
env.extras["log"]["Metrics/goal_distance"] = goal_distance.mean().item()

@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch from 8cbac98 to b27cb24 Compare July 17, 2026 00:59
@hujc7 hujc7 changed the title [Task Clean-up][Manager] Dexterous Part 11/11: Add the Shadow handover manager counterpart [Task Clean-up][Manager] Dexterous Part 11: Add the handover and camera manager counterparts Jul 17, 2026
@hujc7 hujc7 changed the title [Task Clean-up][Manager] Dexterous Part 11: Add the handover and camera manager counterparts [Task Clean-up][Manager] Dexterous Part 11/11: Add the Shadow handover manager counterpart Jul 17, 2026
hujc7 added a commit that referenced this pull request Jul 17, 2026
…nager runtime (#6412)

## Summary

- Fixes OVPhysX actuator joint indices to follow the common actuator
indexing contract.
- Fixes OVPhysX initialization alongside Kit by reusing Kit's registered
PhysX schema provider.
- Fixes the OVPhysX manager to support both the declared public runtime
API and the current runtime API.
- Regression tests included. Validated by full dexterous training runs
on the OVPhysX backend; split out of the lumped validation branch #6324
(Part 2 of 11).

## Dependencies

- None.

## Series review map

Full integrated diff + training/validation evidence: the lumped
validation PR #6324
(DO-NOT-MERGE).

| Part | PR |
|---|---|
| Docs: regenerate the environment overview table |
#6410 |
| Part 1/11: Newton runtime fixes (cloner rows, cubric fallback, viz
teardown) | #6411 |
| **Part 2/11: OVPhysX runtime fixes (this PR)** |
#6412 |
| Part 3/11: success-rate metrics for the Direct reorientation tasks |
#6413 |
| Part 4/11: RSL-RL training for the handover Direct task |
#6414 |
| Part 5/11: success-rate support in the benchmark utilities |
#6415 |
| Part 6/11: renderer presets for the Direct camera task |
#6416 |
| Part 7/11: OVPhysX presets for the dexterous tasks |
#6417 |
| Part 8/11: Allegro manager counterpart |
#6418 |
| Part 9/11: Shadow + OpenAI manager counterparts |
#6419 |
| Part 10/11: Shadow camera manager counterpart |
#6420 |
| Part 11/11: Shadow handover manager counterpart |
#6421 |


---
### Exact changes in this PR

- OVPhysX backend changes + tests:
1f7a433
@hujc7 hujc7 changed the title [Task Clean-up][Manager] Dexterous Part 11/11: Add the Shadow handover manager counterpart [Task Clean-up][Manager] Dexterous Part 6/8: Add the handover and camera manager counterparts Jul 17, 2026
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch from b27cb24 to 553cd1c Compare July 18, 2026 11:10
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.
physx = _ShadowHandCameraManagerSceneCfg(clone_in_fabric=True)
newton_mjwarp = _ShadowHandCameraManagerSceneCfg(clone_in_fabric=False)
ovphysx = physx
default = newton_mjwarp

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][Important] The Manager camera task still defaults to an unsupported backend. Resolving ShadowHandCameraManagerEnvCfg() selects NewtonCfg with clone_in_fabric=False. The latest commit documents that the default RTX modalities require Fabric cloning, but its PhysX-default override was applied only to the Direct config. The new Manager and Play registrations therefore remain broken by default. Please default the Manager scene plus its sim-physics, robot, and object presets to PhysX, keep explicit newton_mjwarp selection available, and add the Manager task to the registered-camera rendering matrix so this configuration is exercised.

func=mdp.root_height_below_minimum,
params={"minimum_height": 0.24, "asset_cfg": SceneEntityCfg("object")},
)
time_out = DoneTerm(func=mdp.time_out, time_out=True)

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][Important] This timeout is one control step later than the Direct task. The generic Manager time_out returns episode_length_buf >= max_episode_length, while HandoverEnv._get_dones() uses >= max_episode_length - 1. For max_episode_length == 450, buffer value 449 terminates Direct but not Manager, changing rollout boundaries and reset observations despite this config promising Direct parity. Please add a Direct-compatible handover timeout term (or share the boundary implementation) and cover 448/449/450 explicitly.

gym.register(
id="Isaac-Reorient-Cube-Shadow-Camera-Direct",
entry_point=f"{__name__}.shadow_hand_camera_env:ShadowHandCameraEnv",
entry_point=f"{__name__}.shadow_hand_direct_camera_env:ShadowHandCameraEnv",

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][Important] The Direct camera module rename needs a deprecation shim. This PR changes the registered entry point to shadow_hand_direct_camera_env, but the previously documented shadow_hand_camera_env and shadow_hand_camera_env_cfg modules are deleted and no longer importable. That is a breaking public import-path change without the deprecation required by the repository guidelines; docs/source/overview/environments.rst also still links the old path. Please retain compatibility modules that warn and re-export the renamed symbols, and add migration guidance to the changelog before removing them in a later release.

def __post_init__(self):
self.decimation = 2
self.episode_length_s = 7.5
# simulation — mirrors the Direct cfg (guarded by the value-parity 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][Moderate] This comment claims a safeguard that is not present on this branch. There is no checked-in Direct-vs-Manager value-parity test for handover; the available dexterous test covers math helpers only. The duplicated task values have already drifted at the timeout boundary. Please either centralize the shared task constants/configuration or land the claimed parity tests in this PR. The source comment itself should describe the functional setting, not the review/test process.

# at module load (config modules import mdp; see the layering note above).
from isaaclab_tasks.core.reorient.config.shadow_hand.feature_extractor import FeatureExtractor

feature_extractor_cfg: FeatureExtractorCfg = env.cfg.feature_extractor

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][Moderate] The declared feature_extractor_cfg term parameter is silently ignored. CameraPolicyCfg supplies and rewires this parameter, but this constructor reads env.cfg.feature_extractor instead and __call__ deletes the declared argument. Consequently, configuring the observation term directly has no effect, and the later docstring claim that the term owns its copy is inaccurate. Please construct from cfg.params["feature_extractor_cfg"], or remove the parameter and all associated rewiring so there is only one explicit source of truth.

init_rot: tuple[float, float, float, float],
) -> PresetCfg:
"""Per-hand Shadow Hand preset (PhysX and Newton MJWarp variants).
"""Per-hand Shadow Hand preset (PhysX, Newton MJWarp, and OVPhysX variants).

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][Moderate] Please reduce this to durable functional documentation. This docstring is largely a tuning diary: comparisons with another backend, specific MAPPO rewards, the search history for gains, and historical asset names. Those details will age quickly and obscure the actual contract. Keep a concise description of what each actuator override controls, its units, and the backend constraint it addresses; move experiment results and rejected values to the PR or a design note. The same standard should be applied to the num_substeps benchmark anecdote below.

@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] Review summary — changes requested before showroom-quality merge.

I left six inline findings: three Important correctness/compatibility issues and three Moderate duplication/configuration/comment-quality issues. The principal blockers are the unsupported Newton default on the new Manager camera task, the one-step Direct/Manager handover timeout mismatch, and removal of documented camera module paths without a deprecation shim.

Verification performed on head ba3e66c: ./isaaclab.sh -f passed all hooks; focused dexterous-math and MARL-adapter tests passed (24 tests). I also reproduced the Manager camera default as NewtonCfg with clone_in_fabric=False, the 449/450 timeout boundary mismatch, and failure to resolve both old camera module paths. Full Isaac Sim/GPU training was not run, and the PR currently has no substantive CI result beyond the labeler.

The existing Greptile suggestion to call .item() on per-step log tensors should not be applied: zero-dimensional device tensors follow the Manager logging convention, while .item() would force a host synchronization on every environment step.

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.
@hujc7
hujc7 marked this pull request as draft July 29, 2026 06:18
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch 9 times, most recently from b70115f to 8d4e54b Compare July 31, 2026 06:04
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 31, 2026
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch from 8d4e54b to 9ed1d70 Compare July 31, 2026 11:41
hujc7 added 4 commits August 3, 2026 03:28
Manager terms that run during the initial reset had no reset_buf to read:
the attribute was only assigned in step(), which has not run yet at that
point. Allocate it alongside episode_length_buf, before the managers load.
Provide the observation, action, event, command and termination terms the
manager-based reorientation tasks need, alongside a parity test that pins
their values against the Direct environment.

Terminations evaluate success directly rather than reading the command's
metrics, which the command manager only refreshes after the termination
phase of step() has already run.
Register manager counterparts for the Allegro, Shadow and OpenAI Shadow
reorientation tasks, each configured in its own per-robot module.

Replace the single shared reorient_manager_env_cfg with those per-robot
configurations: the shared base could only describe the Allegro task, so
every Shadow variant overrode most of what it inherited.
The benchmark variant exists to measure rendering throughput rather than to
train a policy, so it belongs alongside the other contributed tasks. Keep
the released task ID working as a deprecated alias.
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch from 9ed1d70 to b95c8b8 Compare August 3, 2026 10:32
hujc7 added 3 commits August 3, 2026 03:48
The handover configuration listed the Newton actuated joints itself, which
duplicated knowledge that belongs to the robot asset and would drift the moment
the asset gained or renamed a joint.
Register Isaac-Handover-Shadow as the manager counterpart of the Direct
handover task. The fused Direct reward becomes a plain reward term, and the
command term that owns the goal also owns the success and goal-distance
bookkeeping, reporting the same per-episode success bit the Direct task does.

A value-parity test pins the shared task values against the Direct
configuration so drift on either side fails CI.
Register Isaac-Reorient-Cube-Shadow-Camera as the manager counterpart of the
Direct camera task. It defaults to PhysX: the RTX render modalities need Fabric
cloning, which Newton does not support, so the inherited default could not
render. Newton stays selectable for the state-only observation groups.

Move the camera playback settings into play_mode, removing the last two -Play
registrations in isaaclab_tasks. The override mutates the feature extractor
rather than replacing it, since replacing resets every field the caller does
not name -- which had silently re-enabled the CNN in the benchmark
configuration whose purpose is to disable it.
@hujc7
hujc7 force-pushed the jichuanh/task-cleanup-dex-part11 branch from b95c8b8 to e8c626d Compare August 3, 2026 10:50
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 documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants