Skip to content

[Test] Quadrupeds: relax import order (depends on #5826 + #5771)#5828

Draft
hujc7 wants to merge 14 commits into
isaac-sim:developfrom
hujc7:jichuanh/relax-quadrupeds-import-order
Draft

[Test] Quadrupeds: relax import order (depends on #5826 + #5771)#5828
hujc7 wants to merge 14 commits into
isaac-sim:developfrom
hujc7:jichuanh/relax-quadrupeds-import-order

Conversation

@hujc7
Copy link
Copy Markdown
Collaborator

@hujc7 hujc7 commented May 28, 2026

1. Summary

  • Demonstrates that PR 5826's producer-side pxr deferral, applied on top of PR 5771's resolve_backend_and_visualizer helper, lets the demo script keep imports at module top — the canonical IsaacLab idiom
  • The deferred-imports-inside-design_scene() workaround in PR 5771 is no longer needed
  • 1 demo script touched (8 lines moved)

2. Branch composition

This branch chains three sets of changes for review-as-one. Diff order against develop:

  1. PR [Fix] Defer pxr loading in SimulationContext and AssetBase #5826 commits (80b86a01070, 33d40434df5): producer-side pxr deferral in source/isaaclab/isaaclab/assets/asset_base.py and source/isaaclab/isaaclab/sim/simulation_context.py.
  2. PR Support Demo Scripts With Multiple Backends #5771 commits (merged at 6c292c1802b): YizeWang's scripts/demos/demo_helper.py and scripts/demos/quadrupeds.py with resolve_backend_and_visualizer.
  3. This branch's commit 690f2805f09: lift the deferred imports back to module top in scripts/demos/quadrupeds.py.

3. Mechanism

After (1), from isaaclab.assets import Articulation, from isaaclab.sim import SimulationContext, and import isaaclab.sim as sim_utils all keep sys.modules free of pxr/omni/carb/isaacsim until a runtime touch (e.g. sim_utils.SimulationContext.instance()).

(3) takes advantage of this: the 7 deferred imports inside design_scene() and 1 inside main() move back to module top, ordered after args_cli = parser.parse_args() to match the existing """Parse CLI first so we can decide whether to launch Isaac Sim Kit.""" block.

resolve_backend_and_visualizer from PR 5771 still gates the conditional AppLauncher launch inside the with block; the script's behavior under --physics newton_mjwarp --visualizer newton (no Kit) is unchanged.

4. Verification

Ran the script end-to-end (step-capped, headless) for all four backend combinations from the docstring:

Combo Outcome
--physics newton_mjwarp --visualizer newton (kit-less) [INFO]: Setup complete, sim stepped, rc=0
--physics newton_mjwarp --visualizer kit rc=0
--physics physx --visualizer newton rc=0
--physics physx --visualizer kit rc=0

Plus an assert "pxr" not in sys.modules immediately after the module-top asset imports — passed in every case.

5. Out of scope

  • This PR does not propose merging on its own. It chains 5826 and 5771 into a reviewable single state so reviewers can see the end shape if both land.
  • If PR 5771 merges first, the relaxation here becomes a one-commit follow-up on top of 5826.
  • If PR 5826 merges first, the relaxation here can be folded into PR 5771's branch directly.

6. Test plan

  • ./isaaclab.sh -f clean
  • End-to-end run of quadrupeds.py across all 4 backend combinations
  • Existing demo / tutorial tests still green on PhysX backend
  • Existing Newton kitless demo tests still green

Yize Wang and others added 14 commits May 26, 2026 00:52
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Signed-off-by: Yize Wang <yizew@nvidia.com>
Importing AssetBase / BaseArticulation forced pxr (USD) and downstream
omni.* extensions to load at module-import time. That ordering broke
conditional AppLauncher() patterns: any user script doing
`from isaaclab.assets import Articulation` at module top loaded pxr
before Kit, and Kit's later USD extension registration then failed with
a cascade of "extension class wrapper for base class pxr...::TfNotice
has not been created yet" errors and a SEGV.

Three changes:

* asset_base.py: move `from pxr import Usd` under TYPE_CHECKING; drop
  module-top `from isaaclab.sim.simulation_context import SimulationContext`
  and `from isaaclab.sim.utils.stage import get_current_stage`. Call sites
  use `sim_utils.SimulationContext.instance()` and
  `sim_utils.get_current_stage()` via the already-lazy isaaclab.sim
  package, so pxr is loaded on first runtime access instead of at import.
* base_articulation.py: defer `from ...sim import SimulationContext` to
  the body of __init__ (its only use site).

`from isaaclab.assets import Articulation` no longer adds pxr / omni /
carb / isaacsim to sys.modules. A full smoke test that imports asset
classes at module top, then launches AppLauncher, then constructs an
Articulation now succeeds end-to-end.
Pushes the pxr deferral down to the producer module. simulation_context.py
no longer does `from pxr import Gf, Usd, UsdGeom, UsdPhysics, UsdUtils` at
module top; instead `__init__` does a local `from pxr import UsdUtils` and
`_init_usd_physics_scene` does a local `from pxr import Gf, UsdGeom,
UsdPhysics`. The `Usd` annotation on `_predicate(prim: Usd.Prim)` stays
typed via the existing `from __future__ import annotations` (already at
line 6) + a TYPE_CHECKING import.

stage_utils, create_new_stage, and close_stage are reached via
sim_utils.X / a function-local `from isaaclab.sim.utils import stage`
so simulation_context.py's module-top imports no longer transitively
load pxr through stage.py either.

With this in place, `from isaaclab.sim import SimulationContext` is
pxr-free at module top, which means the earlier
`base_articulation.py:__init__`-local `from ...sim import SimulationContext`
workaround is no longer needed -- reverted to the original module-top form.
…pts-with-helper' into jichuanh/relax-quadrupeds-import-order
With the producer-side pxr deferral from this branch's preceding commits
(asset_base and SimulationContext), `from isaaclab.assets import Articulation`
and `import isaaclab.sim as sim_utils` no longer load pxr at module-import
time. The deferred-imports-inside-design_scene workaround is no longer
needed -- imports return to module top matching every other IsaacLab demo
script's canonical "Launch first / Rest everything follows" idiom, just
with the launch gated by the helper.

Moved 7 import lines from `design_scene()` body and 1 from `main()` body
back to module top (after CLI parse). Behavior unchanged across all four
backend combinations from the docstring; verified by running the script
end-to-end (--headless, step-capped) on newton+newton (kit-less),
newton+kit, physx+newton, and physx+kit.
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label May 28, 2026
@hujc7 hujc7 changed the title [Demo] Quadrupeds: relax import order (depends on #5826 + #5771) [Test] Quadrupeds: relax import order (depends on #5826 + #5771) May 28, 2026
Copy link
Copy Markdown

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

Choose a reason for hiding this comment

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

Code Review Summary

This PR demonstrates the combined effect of PRs #5826 and #5771, enabling module-top imports in demo scripts by deferring pxr loading until runtime. The approach is architecturally sound and maintains backward compatibility.


🔬 Architecture & Design

Design Assessment: The pxr deferral pattern is the correct approach for enabling kit-less workflows. Moving pxr imports to TYPE_CHECKING blocks and accessing them through sim_utils (which uses lazy module loading) cleanly separates import-time from runtime dependencies.

Cross-Module Impact: Well-contained. The changes to asset_base.py and simulation_context.py use the existing sim_utils namespace, so call sites remain unchanged. No API breaks.

File Placement: demo_helper.py in scripts/demos/ is appropriate for demo-specific utilities. The helper is not part of the core isaaclab package, which is correct—it's demo infrastructure.


🔍 Implementation Findings

🟡 Warning: scripts/demos/quadrupeds.py:193 — Timestep changed without documentation

The physics timestep changed from dt=0.01 to dt=0.005. This halves the timestep (doubling simulation accuracy but also computational cost). If intentional for Newton backend compatibility, please document in the PR description or add a comment explaining the choice.

# Current (PR):
sim_cfg = sim_utils.SimulationCfg(dt=0.005, device=args_cli.device, ...)

# Base (develop):
sim = sim_utils.SimulationContext(sim_utils.SimulationCfg(dt=0.01))

🔵 Improvement: scripts/demos/demo_helper.py:75 — Defensive check for visualizer attribute access

The has_no_alive_visualizer_window function accesses v.is_closed as an attribute, but if this were a method call that fails, it would raise an exception. Consider whether is_closed could ever be undefined on a visualizer object:

def has_no_alive_visualizer_window(sim) -> bool:
    visualizers = sim.visualizers or ()
    return not any(v.is_running() and not v.is_closed for v in visualizers)

If is_closed is guaranteed by the BaseVisualizer interface, this is fine. Otherwise, consider getattr(v, 'is_closed', True) as a defensive fallback.

🔵 Improvement: scripts/demos/quadrupeds.py:139 — Type annotations loosened

The run_simulator signature changed from typed parameters to generic ones:

# Before:
def run_simulator(sim: sim_utils.SimulationContext, entities: dict[str, Articulation], origins: torch.Tensor):

# After:
def run_simulator(sim, entities: dict, origins):

While acceptable for a demo script, keeping the type hints aids IDE support and documentation. Consider preserving them if the interface is stable.


🧪 Test Coverage

Coverage Assessment: This PR is a demonstration/refactoring change rather than a new feature. The core logic changes in asset_base.py and simulation_context.py are internal import restructuring that doesn't change runtime behavior.

Verification: The PR author's manual verification matrix (4 backend combinations + assert \"pxr\" not in sys.modules) is appropriate validation for import-order changes, which are difficult to unit test.

Recommendation: No additional tests required for this PR. The deferred import pattern is exercised by existing tests that use Articulation and SimulationContext.


✅ Summary

Aspect Status
Architecture ✅ Sound pxr deferral approach
API Compatibility ✅ No breaking changes
Code Quality ✅ Clean with minor suggestions
Test Coverage ✅ Adequate for refactoring PR
Documentation ⚠️ dt change needs explanation

Verdict: Minor fixes needed (clarify dt change)

The pxr deferral mechanism is well-implemented and achieves the stated goal of allowing module-top imports without forcing Kit initialization. Once the timestep change is documented, this is ready to proceed.


Automated review by IsaacLab Review Bot 🤖

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