Skip to content

Fix Newton model not built for sensors added in _setup_scene()#5051

Open
nblauch wants to merge 1 commit intoisaac-sim:developfrom
nblauch:nick/v3.0.0-beta
Open

Fix Newton model not built for sensors added in _setup_scene()#5051
nblauch wants to merge 1 commit intoisaac-sim:developfrom
nblauch:nick/v3.0.0-beta

Conversation

@nblauch
Copy link

@nblauch nblauch commented Mar 18, 2026

InteractiveScene.init() resolves renderer requirements from sensors declared in the scene config, but DirectRLEnv environments add sensors programmatically in _setup_scene() after the scene is constructed. This means PhysxSceneDataProvider is never told it needs a Newton model, so get_newton_model() returns None and Newton-based renderers/visualizers get a black screen.

Add _update_scene_data_requirements_from_sensors() to DirectRLEnv which re-scans all scene sensors after _setup_scene() and merges their renderer requirements into the simulation context before the provider is constructed.

Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
List any dependencies that are required for this change.

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Screenshots

Please attach before and after screenshots of the change if applicable.

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 updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

InteractiveScene.__init__() resolves renderer requirements from sensors
declared in the scene config, but DirectRLEnv environments add sensors
programmatically in _setup_scene() after the scene is constructed.
This means PhysxSceneDataProvider is never told it needs a Newton model,
so get_newton_model() returns None and Newton-based renderers/visualizers
get a black screen.

Add _update_scene_data_requirements_from_sensors() to DirectRLEnv which
re-scans all scene sensors after _setup_scene() and merges their renderer
requirements into the simulation context before the provider is constructed.
@nblauch nblauch requested a review from kellyguo11 as a code owner March 18, 2026 00:45
@github-actions github-actions bot added the isaac-lab Related to Isaac Lab team label Mar 18, 2026
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 18, 2026

Greptile Summary

This PR fixes a bug in DirectRLEnv where sensors added programmatically inside _setup_scene() were invisible to the renderer-requirements resolution that happens during InteractiveScene.__init__(), causing PhysxSceneDataProvider to never build a Newton model and Newton-based renderers/visualizers to produce a black screen.

The fix adds _update_scene_data_requirements_from_sensors(), which re-scans all scene sensors after _setup_scene() returns and merges their requirements (via OR aggregation) into sim._scene_data_requirements before SceneDataProvider is constructed at sim.reset().

Key points:

  • The core requirement-update logic is sound — aggregate_requirements correctly ORs the current and new sensor requirements, preserving any visualizer requirements already set.
  • The method accesses self.scene._sensor_renderer_types(), a protected (single-underscore) method on InteractiveScene, creating fragile cross-class coupling. A public API would be more stable.
  • The visualizer_clone_fn / prebuilt Newton-model artifact fast path is resolved in InteractiveScene.__init__() — before _setup_scene() runs — so it is still computed without knowledge of programmatically added sensors. The provider falls back to building the Newton model from USD, which may be correct but is worth verifying for all backends.
  • Module-level imports for aggregate_requirements and resolve_scene_data_requirements are deferred into the method body, inconsistent with the rest of the file.
  • The PR checklist items (pre-commit checks, tests, changelog) are all unchecked.

Confidence Score: 3/5

  • Merge with caution — the core requirement-update fix is correct, but the prebuilt Newton-model artifact path may still be incomplete for programmatic sensors, and no tests were added to verify the fix.
  • The fix correctly patches sim._scene_data_requirements before SceneDataProvider is constructed, addressing the described Newton-model-is-None bug. However, the prebuilt artifact fast path (resolved from visualizer_clone_fn in InteractiveScene.__init__()) is not updated with the new sensor requirements, which could leave the provider without a valid prebuilt artifact when programmatic sensors require a Newton model. Whether this causes a correctness regression (vs. just a performance regression) depends on the SceneDataProvider fallback behavior, which is untested by this PR. Additionally, the PR checklist items (pre-commit, tests, changelog) are all unchecked.
  • source/isaaclab/isaaclab/envs/direct_rl_env.py — specifically the interaction between the new method and the prebuilt artifact path in InteractiveScene.__init__().

Important Files Changed

Filename Overview
source/isaaclab/isaaclab/envs/direct_rl_env.py Adds _update_scene_data_requirements_from_sensors() to re-scan all scene sensors after _setup_scene() and merge their renderer requirements into the simulation context, fixing Newton model not being built for programmatically added sensors. Concerns: accesses InteractiveScene._sensor_renderer_types() (private by convention), uses deferred imports, and the prebuilt Newton-model artifact fast path is still resolved before programmatic sensors are registered.

Sequence Diagram

sequenceDiagram
    participant DRL as DirectRLEnv.__init__
    participant IS as InteractiveScene.__init__
    participant Sim as SimulationContext
    participant SDP as SceneDataProvider

    DRL->>IS: InteractiveScene(cfg.scene)
    IS->>IS: _add_entities_from_cfg()
    IS->>IS: _sensor_renderer_types() → [] (no programmatic sensors yet)
    IS->>Sim: update_scene_data_requirements(requirements)<br/>requires_newton_model=False
    IS->>IS: resolve_visualizer_clone_fn(requirements)<br/>→ None (no Newton model needed)
    IS->>IS: clone_environments() [artifact NOT prebuilt]
    IS-->>DRL: scene ready

    DRL->>DRL: _setup_scene() [programmatic sensors added here]

    Note over DRL,Sim: NEW fix — re-scan after _setup_scene()
    DRL->>IS: _sensor_renderer_types() → [newton_warp, ...]
    DRL->>Sim: get_scene_data_requirements() → current_req
    DRL->>DRL: aggregate_requirements([current_req, sensor_req])
    DRL->>Sim: update_scene_data_requirements(merged)<br/>requires_newton_model=True ✓

    DRL->>Sim: reset()
    Sim->>SDP: SceneDataProvider(stage, sim)
    SDP->>Sim: get_scene_data_requirements() → requires_newton_model=True
    SDP->>SDP: build Newton model ✓
    SDP->>Sim: get_scene_data_visualizer_prebuilt_artifact() → None<br/>(artifact was not prebuilt — fallback to USD rebuild)
Loading

Last reviewed commit: "Fix Newton model not..."

resolve_scene_data_requirements,
)

renderer_types = self.scene._sensor_renderer_types()
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Accessing protected method across class boundary

self.scene._sensor_renderer_types() calls a name-prefixed protected method on InteractiveScene from outside that class. This creates tight coupling to an implementation detail: any internal refactor of InteractiveScene (e.g., renaming the method, changing its return type, or merging it into another helper) would silently break this fix with no IDE/type-checker warning.

Consider exposing a public sensor_renderer_types() method on InteractiveScene, or a dedicated public helper such as scene.get_renderer_requirements() that returns the already-resolved SceneDataRequirement. That way the contract is stable and tested independently.

Comment on lines +677 to +680
from isaaclab.physics.scene_data_requirements import (
aggregate_requirements,
resolve_scene_data_requirements,
)
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Deferred imports should be at module level

aggregate_requirements and resolve_scene_data_requirements are imported inside the method body. The rest of the file follows the standard pattern of top-level imports. Importing inside a method hides the dependency from tools (linters, type-checkers, dependency scanners) and adds a small repeated cost if the method is ever called more than once.

Suggested change
from isaaclab.physics.scene_data_requirements import (
aggregate_requirements,
resolve_scene_data_requirements,
)
from isaaclab.physics.scene_data_requirements import (
aggregate_requirements,
resolve_scene_data_requirements,
)
renderer_types = self.scene._sensor_renderer_types()

Prefer moving the two imports to the module-level import block at the top of the file alongside the other isaaclab.* imports.

Comment on lines +666 to +689
def _update_scene_data_requirements_from_sensors(self):
"""Re-scan scene sensors and update simulation context requirements.

``InteractiveScene.__init__()`` resolves renderer requirements from
sensors declared in the scene *config*, but sensors added
programmatically in :meth:`_setup_scene` (the standard ``DirectRLEnv``
pattern) are missed. This method re-scans all scene sensors after
``_setup_scene()`` returns and merges their renderer requirements into
the simulation context so that ``PhysxSceneDataProvider`` (constructed
later) knows whether it needs to build a Newton model.
"""
from isaaclab.physics.scene_data_requirements import (
aggregate_requirements,
resolve_scene_data_requirements,
)

renderer_types = self.scene._sensor_renderer_types()
if not renderer_types:
return
sensor_req = resolve_scene_data_requirements(visualizer_types=[], renderer_types=renderer_types)
current_req = self.sim.get_scene_data_requirements()
merged = aggregate_requirements([current_req, sensor_req])
if merged != current_req:
self.sim.update_scene_data_requirements(merged)
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Prebuilt visualizer artifact optimization bypassed for programmatic sensors

Inside InteractiveScene.__init__(), the visualizer_clone_fn (and thus the Newton-model prebuilt artifact fast path) is resolved from _sensor_renderer_types() before _setup_scene() runs:

# Inside InteractiveScene.__init__() — sensors from _setup_scene() not yet registered
requirements = resolve_scene_data_requirements(
    visualizer_types=requested_viz_types,
    renderer_types=self._sensor_renderer_types(),  # empty for programmatic sensors
)
self.sim.update_scene_data_requirements(requirements)
visualizer_clone_fn = cloner.resolve_visualizer_clone_fn(
    requirements=requirements, ...
)

This means visualizer_clone_fn is None (or is resolved without requires_newton_model=True) when sensors are added only in _setup_scene(). As a result, set_scene_data_visualizer_prebuilt_artifact is never called with a valid Newton-model artifact, so sim.get_scene_data_visualizer_prebuilt_artifact() returns None.

The new _update_scene_data_requirements_from_sensors() correctly patches sim._scene_data_requirements, ensuring SceneDataProvider is told it needs a Newton model. Whether the provider can build the Newton model correctly from USD when the prebuilt artifact is missing (the fallback path) depends on the SceneDataProvider implementation. If that fallback is always valid, the fix is sufficient. If SceneDataProvider relies on the artifact to correctly wire the multi-env Newton model during initialization, the fix would address the symptom (wrong requirements) but the artifact gap could still cause a black screen in certain backends.

It is worth verifying that SceneDataProvider behaves identically (not just "slightly slower") when get_scene_data_visualizer_prebuilt_artifact() returns None and requires_newton_model=True.

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