Skip to content

Add a task discovery API for backend combinations - #7046

Draft
AntoineRichard wants to merge 1 commit into
isaac-sim:developfrom
AntoineRichard:antoiner/task-discovery-api
Draft

Add a task discovery API for backend combinations#7046
AntoineRichard wants to merge 1 commit into
isaac-sim:developfrom
AntoineRichard:antoiner/task-discovery-api

Conversation

@AntoineRichard

Copy link
Copy Markdown
Collaborator

Description

The Gym registry is currently walked in two places that answer two different questions:

  • tools/environ_docs.py reads what a task declares. That is what the environments.rst tables publish.
  • Nothing reports what actually resolves.

The gap is not theoretical. A combination can be documented while being impossible to run — that is how the AnymalC-Direct rows advertised presets the task does not have (fixed by hand in #6914). Because CI never runs update_environments_rst.py --check, nothing catches that class of drift.

This adds tools/task_discovery.py:

discover_tasks(resolve=False)   # what each task declares - fast
discover_tasks(resolve=True)    # build each combination + run the runtime validator

Resolved mode is the useful part: the cross product is not all legal. OVRTX is kitless and cannot share a process with Kit physics, so isaacsim_physx + ovrtx is declared yet unusable. Discovering that costs one config resolution; discovering it on a GPU costs a whole benchmark run.

Automatic selectors are reported separately

physics=physx (PhysxAutoCfg) resolves to OvPhysX kitless and to Isaac Sim PhysX under Kit. renderer=rtx (_AutoRtxRendererCfg) behaves the same way. A selector and the backend it resolves to are therefore the same run, which is why the tables already say:

physics=physx is also a valid automatic selector [...] The tables list only concrete backends so that each row identifies the runtimes it supports.

That knowledge currently lives in three places — the docs prose, the filtering inside environ_docs, and a downstream benchmark dispatcher — and they have already drifted apart. DiscoveredTask.selectors exposes it as data instead:

concrete = tuple(n for n in t.declared["renderer"] if n not in t.selectors.get("renderer", ()))

Detected by config type, not by name, so adding a selector upstream needs no edit here. Currently finds physx on 50 tasks and rtx on 7.

Whether a selector is redundant depends on how the caller launches, so discovery reports both and leaves the policy to the caller.

Equivalence with the current docs walk

resolve=False was compared against collect_environment_doc_rows() across the whole registry:

task_discovery = 127   environ_docs = 127
only in task_discovery: []
only in environ_docs  : []
field mismatches      : 0     (RL libraries, physics, renderer, domain presets)

The one apparent RL-library difference is environ_docs' own RL_LIBRARY_OVERRIDES table, applied downstream where it belongs.

Scope, and what is deliberately not here

This lands the module only. Nothing in-repo consumes it yet — that is intentional, so the equivalence above can be reviewed on its own before working doc generation is touched. Planned follow-ups in this PR:

  1. collect_environment_doc_rows() delegates to discover_tasks(resolve=False), keeping apply_rl_library_overrides and _physics_names_for_docs where they are, with update_environments_rst.py --check proving environments.rst is byte-identical.
  2. A CLI, and optionally a --check mode that reports declared-but-unresolvable combinations so CI can fail on doc drift.

Two things I would like reviewer input on:

  • _selector_names loads the env config a second time (once via enumerate_task_presets, once via collect_presets), roughly doubling declared-mode cost. Reusing a single walk means duplicating _bucket_variants_by_target; exposing the walked configs from preset_cli would be cleaner but widens this PR.
  • Home. tools/ matches environ_docs.py, but if this should be a supported API for out-of-tree consumers, source/isaaclab_tasks/isaaclab_tasks/utils/ may be the better place.

Type of change

  • New feature (non-breaking change which adds functionality)

Checklist

  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have added tests that prove my fix is effective or that my feature works
  • I have added a changelog fragment under source/isaaclab/changelog.d/
  • Consumer wiring (see Scope) — follow-up commits in this PR

@github-actions github-actions Bot added isaac-lab Related to Isaac Lab team infrastructure labels Aug 12, 2026
`enumerate_task_presets` reports what a task declares, bucketed by
selector target. It cannot say whether a declared combination works, and
the two differ: OVRTX is kitless and cannot share a process with Kit
physics, so `isaacsim_physx + ovrtx` is declared yet unusable, and a task
can advertise a backend it has no configuration for. Finding that out on
a GPU costs a whole run; finding it here costs one config load.

`resolve` builds the config and runs the runtime validator, returning the
configs the selection resolved to rather than a bare yes/no. That richer
return answers a second question for free: `physics=physx` resolves to
`PhysxAutoCfg`, which picks a concrete backend at launch, so an alias and
the backend it selects are the same run. `is_selector` reads that off the
resolved config instead of comparing against the names `physx` and `rtx`.

Costs roughly 0.1s for the first combination of a task and 0.017s
thereafter, about 13s across the registry.
@AntoineRichard
AntoineRichard force-pushed the antoiner/task-discovery-api branch from 6e8cf32 to 88f9da7 Compare August 13, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

infrastructure isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant