Skip to content

[Task Clean-up][Manager][Camera] Dexterous Part 10/11: Add the Shadow camera manager counterpart - #6420

Closed
hujc7 wants to merge 8 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-part10
Closed

[Task Clean-up][Manager][Camera] Dexterous Part 10/11: Add the Shadow camera manager counterpart#6420
hujc7 wants to merge 8 commits into
isaac-sim:developfrom
hujc7:jichuanh/task-cleanup-dex-part10

Conversation

@hujc7

@hujc7 hujc7 commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds the manager-based counterpart for the Shadow Hand camera reorientation task (Play variant, benchmark row, rendering-correctness row, CI-rendered golden images for both camera tasks).
  • Carries the camera enablement deferred from Part 6 per review: the shared validation helper, the Warp cube-keypoint implementation with parity tests (the module-level compute_keypoints is deprecated in favor of feature_extractor.compute_cube_keypoints), and the camera observation terms in the task mdp package.
  • The benchmark row gates on episode length and duration only: the camera reward scale plateaus near 300 against the copied 1000 gate, and camera threshold recalibration is a tracked follow-up. The consumer-less manager Benchmark registration was dropped per review.
  • Validated by full camera manager training and rendering-correctness runs; split out of the lumped validation branch [DO-NOT-MERGE][Task Clean-up] Dexterous: lumped validation branch (series reference) #6324 (Part 10 of 11).

Dependencies

Review updates (2026-07-09)

  • The camera manager reads fingertip names and the force-torque scale from the constants module instead of instantiating the Direct cfg; the cube-keypoint feature path writes into a pre-allocated buffer.

Review updates (2026-07-11)

  • Synced with lump head d3cddae: the camera manager benchmark row gains an interim reward gate (150) that catches pipeline breakage below the truncated-run plateau (~174-290); success gates stay off until a full-budget manager run calibrates them. The camera observation terms and feature extractor pick up the Warp kernel conversion, and the camera env drops its redundant fingertip force-sensor update. The keypoint parity test file is dropped; the consolidated kernel behavior suite ships with Part 11 ([Task Clean-up][Manager] Dexterous Part 6/9: Add the handover and camera manager counterparts #6421).

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 #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 (this PR) #6420
Part 11/11: Shadow handover manager counterpart #6421

Builds on: #6413, #6416. This PR's own commits relative to each parent branch:

Manager-based counterpart for the Shadow Hand camera reorientation
task with Play and Benchmark variants, registered with the rendering
correctness suite and reference golden images for both the Direct and
manager camera tasks.

Validated by full camera manager training and rendering-correctness
runs on RTX.
@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 Shadow Hand camera reorientation task, completing parity with the existing Direct variant. It introduces ShadowHandCameraManagerEnvCfg (plus Play and Benchmark variants), three new gym registrations, a benchmark row, render-correctness test registration, and golden images for both the Direct and manager camera tasks.

  • New shadow_hand_camera_manager_env_cfg.py: Wires a _ShadowHandCameraManagerSceneCfg (camera + joint-wrench sensors) together with asymmetric actor/critic observations (CameraPolicyCfg / CameraCriticCfg) that mirror the Direct task's 191-dim / 214-dim observation spaces, sharing the same FeatureExtractorCfg instance via __post_init__.
  • __init__.py additions: Registers Isaac-Reorient-Cube-Shadow-Camera, -Play, and -Benchmark for ManagerBasedRLEnv, and also back-fills the missing rsl_rl_cfg_entry_point on the existing Isaac-Reorient-Cube-Shadow-OpenAI-LSTM-Direct entry.
  • Test/benchmark additions: The training env is registered in the render-correctness suite with the same flaky(max_runs=3, min_passes=1) marks as the Direct camera task, and benchmark thresholds match the Direct task's values.

Confidence Score: 4/5

Safe to merge once the dependency chain (Parts 3, 6, 8, 9) lands; the new config code is structurally consistent with the Direct camera task it mirrors.

The new manager env cfg correctly reuses Direct task dynamics and wires asymmetric actor/critic observations. Two style-level concerns exist: validate_config hardcodes the three scene preset attribute names rather than discovering them dynamically, and a full ShadowHandCameraEnvCfg() is instantiated at module import time just to read two constants. Neither represents a functional defect in the changed code; the PR was validated end-to-end with full training runs.

shadow_hand_camera_manager_env_cfg.py — the validate_config method and the module-level config instantiation are worth a second look.

Important Files Changed

Filename Overview
source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/shadow_hand_camera_manager_env_cfg.py New manager-based camera env config reusing Direct task's dynamics and observations; structurally sound with a minor coupling concern in validate_config and module-level instantiation.
source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/init.py Adds gym registrations for three camera manager variants (training, play, benchmark) and fills in missing rsl_rl runner for the existing LSTM-Direct env; consistent with existing patterns.
source/isaaclab_tasks/test/benchmarking/configs.yaml Adds benchmark row for Isaac-Reorient-Cube-Shadow-Camera with thresholds identical to the Direct camera task; consistent with the series pattern.
source/isaaclab_tasks/test/core/test_rendering_registered_tasks.py Registers Isaac-Reorient-Cube-Shadow-Camera in the render-correctness suite with the same flaky-retry marks as the Direct camera task; no logic changes to the test harness.

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class ShadowHandManagerEnvCfg {
        +scene: _ShadowHandManagerSceneCfg
        +observations: FullStateObsCfg
    }
    class ShadowHandCameraManagerEnvCfg {
        +scene: ShadowHandCameraManagerSceneCfg
        +observations: CameraObservationsCfg
        +feature_extractor: FeatureExtractorCfg
        +validate_config()
        +__post_init__()
    }
    class ShadowHandCameraManagerPlayEnvCfg {
        +scene: ShadowHandCameraManagerPlaySceneCfg
        +feature_extractor: FeatureExtractorCfg(train=False, load_checkpoint=True)
    }
    class ShadowHandCameraManagerBenchmarkEnvCfg {
        +feature_extractor: FeatureExtractorCfg(enabled=False)
    }
    class CameraObservationsCfg {
        +policy: CameraPolicyCfg
        +critic: CameraCriticCfg
    }
    class CameraPolicyCfg {
        +camera_features: ObsTerm(ShadowHandCameraFeatures)
        +goal_keypoints: ObsTerm
        +last_action: ObsTerm
        --object_pos/quat/vel set to None
    }
    class CameraCriticCfg {
        +fingertip_wrench: ObsTerm
        +last_action: ObsTerm
        +camera_features: ObsTerm(cached)
    }
    class _ShadowHandCameraManagerSceneCfg {
        +ground = None
        +tiled_camera: ShadowHandTiledCameraCfg
        +joint_wrench: JointWrenchSensorCfg
    }

    ShadowHandManagerEnvCfg <|-- ShadowHandCameraManagerEnvCfg
    ShadowHandCameraManagerEnvCfg <|-- ShadowHandCameraManagerPlayEnvCfg
    ShadowHandCameraManagerEnvCfg <|-- ShadowHandCameraManagerBenchmarkEnvCfg
    ShadowHandCameraManagerEnvCfg *-- CameraObservationsCfg
    CameraObservationsCfg *-- CameraPolicyCfg
    CameraObservationsCfg *-- CameraCriticCfg
    ShadowHandCameraManagerEnvCfg *-- _ShadowHandCameraManagerSceneCfg
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"}}}%%
classDiagram
    class ShadowHandManagerEnvCfg {
        +scene: _ShadowHandManagerSceneCfg
        +observations: FullStateObsCfg
    }
    class ShadowHandCameraManagerEnvCfg {
        +scene: ShadowHandCameraManagerSceneCfg
        +observations: CameraObservationsCfg
        +feature_extractor: FeatureExtractorCfg
        +validate_config()
        +__post_init__()
    }
    class ShadowHandCameraManagerPlayEnvCfg {
        +scene: ShadowHandCameraManagerPlaySceneCfg
        +feature_extractor: FeatureExtractorCfg(train=False, load_checkpoint=True)
    }
    class ShadowHandCameraManagerBenchmarkEnvCfg {
        +feature_extractor: FeatureExtractorCfg(enabled=False)
    }
    class CameraObservationsCfg {
        +policy: CameraPolicyCfg
        +critic: CameraCriticCfg
    }
    class CameraPolicyCfg {
        +camera_features: ObsTerm(ShadowHandCameraFeatures)
        +goal_keypoints: ObsTerm
        +last_action: ObsTerm
        --object_pos/quat/vel set to None
    }
    class CameraCriticCfg {
        +fingertip_wrench: ObsTerm
        +last_action: ObsTerm
        +camera_features: ObsTerm(cached)
    }
    class _ShadowHandCameraManagerSceneCfg {
        +ground = None
        +tiled_camera: ShadowHandTiledCameraCfg
        +joint_wrench: JointWrenchSensorCfg
    }

    ShadowHandManagerEnvCfg <|-- ShadowHandCameraManagerEnvCfg
    ShadowHandCameraManagerEnvCfg <|-- ShadowHandCameraManagerPlayEnvCfg
    ShadowHandCameraManagerEnvCfg <|-- ShadowHandCameraManagerBenchmarkEnvCfg
    ShadowHandCameraManagerEnvCfg *-- CameraObservationsCfg
    CameraObservationsCfg *-- CameraPolicyCfg
    CameraObservationsCfg *-- CameraCriticCfg
    ShadowHandCameraManagerEnvCfg *-- _ShadowHandCameraManagerSceneCfg
Loading

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

Comment on lines +37 to +38
_DIRECT_CAMERA_CFG = ShadowHandCameraEnvCfg()
_FINGERTIP_BODY_NAMES = _DIRECT_CAMERA_CFG.fingertip_body_names

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 Module-level config instantiation to read two constants

ShadowHandCameraEnvCfg() is instantiated at import time solely to read fingertip_body_names and force_torque_obs_scale. Since both values are defined directly on ShadowHandEnvCfg (the parent class) as class-level fields, they can be retrieved without creating a full env config object. The current approach works but adds unnecessary initialization cost on every import of this module, and any future side effect added to ShadowHandCameraEnvCfg.__post_init__ would silently fire at import time.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +143 to +152
self.observations.policy.camera_features.params["feature_extractor_cfg"] = self.feature_extractor

def validate_config(self):
"""Check every unresolved scene alternative or the selected camera pipeline."""
if isinstance(self.scene, PresetCfg):
scenes = (self.scene.physx, self.scene.newton_mjwarp, self.scene.ovphysx)
else:
scenes = (self.scene,)
for scene in scenes:
validate_shadow_hand_camera_settings(scene.tiled_camera, self.feature_extractor)

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 validate_config hardcodes preset attribute names

The three backend names physx, newton_mjwarp, and ovphysx are accessed by string-literal attribute lookup. All concrete subclasses in this PR define those three attributes, so this is safe today. However, any future subclass that overrides scene with a PresetCfg that omits or renames one of these backends will hit an AttributeError from PresetCfg.__getattr__ (which only handles known legacy aliases). Iterating via dataclasses.fields() and filtering out default and underscore-prefixed entries would make the validation self-describing and forward-compatible.

hujc7 added 6 commits July 9, 2026 04:30
Carries the camera enablement deferred from the renderer-preset part
(shared validation helper, Warp cube-keypoint function with parity
tests and deprecation shim, manager observation terms in the mdp
package), drops the consumer-less manager Benchmark registration, and
removes the camera benchmark row's unreachable reward gate.
CI's RTX output differs from locally rendered frames beyond the color
gate; use the frames CI itself rendered as the references.
The camera manager reads the fingertip names and force-torque scale
from the constants module instead of instantiating the Direct cfg, and
the cube-keypoint feature path writes into a pre-allocated buffer.
The camera manager reads the fingertip names and force-torque scale
from the constants module instead of instantiating the Direct cfg, and
the cube-keypoint feature path writes into a pre-allocated buffer.
The camera manager reads the fingertip names and force-torque scale
from the constants module instead of instantiating the Direct cfg, and
the cube-keypoint feature path writes into a pre-allocated buffer.
The camera manager row gains an interim reward gate (150) that
catches pipeline breakage well below the truncated manager plateau
(~174-290); success gates stay off until a full-budget manager run
calibrates them. The camera observation terms and feature extractor
pick up the Warp kernel conversion, the camera env drops its
redundant fingertip force-sensor update (the base Direct env's Warp
observation build owns the refresh), and the keypoint parity test
file is dropped in favor of the consolidated kernel behavior suite
that ships with Part 11.
The camera Direct and manager configurations define their scalars as
per-paradigm literals; the cube-keypoint helpers now come from the
family kernel module reorient_kernels (the feature-extractor
re-export keeps the deprecated shim working).
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 commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as part of the series restructure: the Shadow camera manager counterpart now lives in #6421 (Part 6/8). The full series layout is tracked in the Review Map at the top of #6324.

@hujc7 hujc7 closed this Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant