Skip to content

[Fix] Publish and fetch the checkpoints a task's components declare - #7485

Open
hujc7 wants to merge 4 commits into
isaac-sim:developfrom
hujc7:jichuanh/pretrained-feature-extractor-ckpt
Open

[Fix] Publish and fetch the checkpoints a task's components declare#7485
hujc7 wants to merge 4 commits into
isaac-sim:developfrom
hujc7:jichuanh/pretrained-feature-extractor-ckpt

Conversation

@hujc7

@hujc7 hujc7 commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

play --checkpoint pretrained crashed on the Shadow Hand camera tasks: the vision CNN the policy
needs was never published beside it, and nothing in the tooling knew the file existed. This PR adds
the smallest mechanism that fixes it — a component declares what it writes, and the tooling
publishes and fetches it with the policy.

The refactor that this mechanism invites is deliberately not here; it is stacked in
#7509 — Replace the pretrained checkpoint functions with CheckpointBundle.

Description

1. Declaring a checkpoint

A component declares what it writes on its own config:

@configclass
class FeatureExtractorCfg:
    checkpoint: Checkpoint = Checkpoint(name="feature_extractor", run_glob="cnn_*.pth")
    """The trained CNN, published beside the policy checkpoint."""

get_declared_checkpoints walks the resolved environment config to find every declaration, so a
task declares nothing and the component that writes the file owns its name. Each file is published
beside the policy as <policy stem>_<name><extension> and fetched with it. Checkpoint.resolve
hands the component its local file, so no component needs to know the naming convention.

Checkpoint also covers weights that already exist (url=): a frozen encoder is fetched but never
published by the checkpoint tooling.

2. Published checkpoints

Both companion pairs are trained and published, so the fix has something to fetch:

Task Backends
Isaac-Reorient-Cube-Shadow-Camera newtonmjwarp+newton, physx+rtx
Isaac-Reorient-Cube-Shadow-Camera-Direct newtonmjwarp+newton, physx+rtx

Each is a policy .pt plus its _feature_extractor.pth.

3. Verification

  • 82 tests pass across test_pretrained_checkpoint.py, test_checkpoints.py,
    test_train_and_publish_checkpoints.py, test_shadow_hand_camera_presets.py and
    test_pretrained_checkpoint_lookup.py. isaaclab -f clean.
  • The declaration tests pin discovery through nested component configs, exclusion of url weights,
    and that a published file keeps the extension the component declared.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Release backport

  • Backport this pull request to the active release branch after it merges into develop

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have added a changelog fragment under source/<pkg>/changelog.d/ for every touched package
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

@github-actions github-actions Bot added enhancement New feature or request isaac-lab Related to Isaac Lab team labels Sep 2, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 3, 2026
@hujc7

hujc7 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 3, 2026
@hujc7

hujc7 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026
play --checkpoint pretrained crashed on the Shadow Hand camera tasks: the
vision CNN the policy needs was never published beside it, and nothing in
the tooling knew the file existed.

A component now declares what it writes with a Checkpoint on its own
config. The tooling walks the resolved environment config to find every
declaration, so a task declares nothing, and publishes each file beside
the policy as <policy stem>_<name><extension>. The download path fetches
them with the policy.
@hujc7
hujc7 force-pushed the jichuanh/pretrained-feature-extractor-ckpt branch from 8a871d9 to eda9b46 Compare September 4, 2026 04:22
@hujc7 hujc7 changed the title [Fix] Provide the vision CNN checkpoint that pretrained Shadow Hand camera playback needs Publish and fetch the checkpoints a task's components declare Sep 4, 2026
@hujc7

hujc7 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026
@hujc7

hujc7 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026
"Auxiliary" ranked these files below the policy and did not generalise:
any component can declare a run artifact, and the policy is not special
among them. The discovery and path helpers, their parameter, and the
collect locals now say declared.
@hujc7
hujc7 force-pushed the jichuanh/pretrained-feature-extractor-ckpt branch from 17433c7 to b87603e Compare September 4, 2026 07:59
@hujc7 hujc7 changed the title Publish and fetch the checkpoints a task's components declare [Fix] Publish and fetch the checkpoints a task's components declare Sep 4, 2026
@hujc7

hujc7 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026
…ned-feature-extractor-ckpt

# Conflicts:
#	source/isaaclab_rl/isaaclab_rl/utils/pretrained_checkpoint.py
#	source/isaaclab_rl/test/test_pretrained_checkpoint.py
@hujc7

hujc7 commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

run-ci

@isaaclab-bot isaaclab-bot Bot added ci:run-docker Trigger the on-demand Docker and GPU CI workflow and removed ci:run-docker Trigger the on-demand Docker and GPU CI workflow labels Sep 4, 2026
@hujc7
hujc7 marked this pull request as ready for review September 5, 2026 10:17
@hujc7
hujc7 requested a review from a team September 5, 2026 10:17
@greptile-apps

greptile-apps Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces component-owned checkpoint declarations and updates training, publication, download, playback, and export paths to carry companion weights alongside policy checkpoints.

  • Adds the Checkpoint configuration and resolution abstraction.
  • Discovers run-produced checkpoint declarations from resolved environment configurations.
  • Collects, publishes, and downloads companion artifacts using policy-derived names.
  • Migrates Shadow Hand camera feature-extractor loading and the Drone ARL VAE lookup.
  • Updates playback/export entrypoints and adds checkpoint-resolution tests.
  • The current implementation still mishandles RL-Games companion lookup and permits incomplete bundles to be published and played.

Confidence Score: 3/5

This PR is not yet safe to merge because incomplete bundles remain playable and RL-Games resolves downloaded companions from the wrong directory.

Two concrete playback failures remain: RL-Games searches outside the companion's downloaded directory, and missing required companions are only warned about despite causing component initialization to fail.

Files Needing Attention: source/isaaclab_rl/isaaclab_rl/utils/pretrained_checkpoint.py, source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rl_games.py, scripts/tools/train_and_publish_checkpoints.py

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/utils/checkpoints.py Adds component checkpoint discovery primitives and local/remote resolution, but does not enforce its source-selection invariant.
source/isaaclab_rl/isaaclab_rl/utils/pretrained_checkpoint.py Adds companion discovery and fetching, but continues after a required declared artifact is unavailable.
scripts/tools/train_and_publish_checkpoints.py Collects and uploads declared artifacts, while allowing policies to be published without their required companions.
source/isaaclab_rl/isaaclab_rl/entrypoints/backends/play_rl_games.py Passes the environment configuration for companion retrieval but derives a log directory above the downloaded companion.
source/isaaclab_tasks/isaaclab_tasks/core/reorient/config/shadow_hand/feature_extractor.py Declares and resolves the Shadow Hand feature-extractor checkpoint through the new abstraction.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  C[Component Checkpoint declaration] --> D[Discover from environment config]
  D --> T[Training run writes artifact]
  T --> K[Collect policy and companion]
  K --> P[Publish beside policy]
  P --> F[Fetch into checkpoint cache]
  F --> L[Pass policy directory as log_dir]
  L --> R[Component resolves companion]
Loading

Reviews (1): Last reviewed commit: "Merge remote-tracking branch 'upstream/d..." | Re-trigger Greptile

if args_cli.checkpoint == "pretrained":
backend_names = get_pretrained_checkpoint_backend_names(env_cfg)
resume_path = get_published_pretrained_checkpoint("rl_games", train_task_name, *backend_names)
resume_path = get_published_pretrained_checkpoint("rl_games", train_task_name, env_cfg=env_cfg)

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.

P1 Wrong RL-Games companion directory

When an RL-Games task declares a companion checkpoint, the policy and companion are downloaded beside each other. The RL-Games play path then sets log_dir to the policy's grandparent, so the component searches one directory above the downloaded companion and raises FileNotFoundError. As a result, pretrained playback fails for RL-Games tasks that need companion weights.

Comment on lines 342 to +343
except FileNotFoundError:
# the asset server reports a checkpoint that was never published and a server it
# cannot reach the same way, so both are covered by the same message
backends = (
""
if physics_backend is None
else f" with the '{physics_backend}' physics and '{render_backend}' render backends"
)
print(
"A pre-trained checkpoint is currently unavailable for this task.\n"
f" The asset server does not provide '{ov_path}'.\n"
f" Either no checkpoint is published for task '{task_name}'{backends}, or the asset"
" server could not be reached.\n"
" Train the task, or pass --checkpoint <path> to use a checkpoint of your own."
)
return None
print(f"[WARNING]: The asset server does not provide the {checkpoint.name} checkpoint '{declared_path}'.")

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.

P1 Incomplete bundles remain usable

When a declared companion is missing, this code only warns and still returns the policy. Publication likewise skips an uncollected companion without failing the job. Camera play requires the feature extractor and raises FileNotFoundError when it is absent, so an incomplete publication is reported as successful and --checkpoint pretrained later crashes instead of rejecting the unusable bundle.

Comment on lines +39 to +44
"""Published location of pre-existing weights."""

@property
def is_run_artifact(self) -> bool:
"""Whether this run produces the file, as opposed to fetching a published one."""
return self.run_glob is not None

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 Checkpoint sources aren't validated

Checkpoint requires exactly one of run_glob and url, but the configuration class does not validate that invariant. Setting both silently ignores the URL, while setting neither eventually passes None to retrieval or extension handling. This makes malformed component declarations fail later with unrelated errors instead of a direct configuration diagnostic.

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

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.

Isaac Lab Review Bot

The component-owned Checkpoint declaration and environment-config discovery provide a focused mechanism for publishing and fetching companion artifacts. However, the new cache layout does not match the existing log_dir derivation for RL-Games and skrl, so those consumers cannot resolve fetched companion checkpoints.

  • Design and architecture: Artifact ownership remains localized to component configs, and discovery avoids task-level duplication. The cache-to-consumer contract needs correction: RL-Games and skrl move two directory levels up from the returned policy path, while companions remain in the policy’s immediate cache directory.
  • API: The keyword-only env_cfg addition preserves the existing positional backend arguments, and the migrated play, demo, and export callers consistently pass the resolved environment config. The new Checkpoint type is exported through the package typing surface. No compatibility break is established by the accepted finding.
  • Implementation: Companion discovery, naming, collection, publication, and retrieval are connected across the tooling. Fix the RL-Games and skrl playback/export paths so env_cfg.log_dir points to the directory containing the fetched companion, or arrange the cache layout to match those workflows’ existing two-level path convention.

Minor fixes needed. Posted 1 actionable finding inline.

Automated review; human maintainers own approval decisions.

print(f"Fetching pre-trained checkpoint : {ov_path}")
# one cache directory per published checkpoint: play treats it as the run log directory and
# writes videos, exported policies, and additional checkpoints into it
download_dir = os.path.join(

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.

🟡 Warning · Design Architecture — Companion cache dir misses rl_games/skrl log_dir

Companions are fetched into .pretrained_checkpoints/<workflow>/<stem>/, and the new docstring promises a component reading its log directory finds them. That holds for rsl_rl and sb3, but play_rl_games.py (line 149) and play_skrl.py (line 209), plus their LEAPP exporters, derive log_dir = dirname(dirname(resume_path)) = .pretrained_checkpoints/<workflow>, one level above the companion, so Checkpoint.resolve(log_dir) raises. Mirror each workflow's native nesting or use the download directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant