Fix OVRTX scene-camera black frames from unscoped render-var lookups - #7943
matthewtrepte wants to merge 2 commits into
Conversation
OVRTX 0.4 keys frame.render_vars by source name; 0.5+ keys it by the authored RenderVar prim path. The version-compat shim correctly detected this switch, but the static prim-path table it fell back to still used the pre-per-camera-scoping "/Render/Vars/<name>" path. OVRTX 0.5+ actually authors each camera's render vars under its own scope, "/RenderCamera_<id>/Vars/<name>" (see render_scope_name in build_render_product_as_string, which already remaps correctly for authoring). The read side never applied that same remapping, so every frame.render_vars.get() silently returned None and the output buffer stayed at its zero-initialized (black) state. Fixed by resolving each render-var key from the owning camera's render_scope_name (now stored on OVRTXCameraRenderData) via a new resolve_render_var_key() helper, instead of indexing the unscoped global RENDER_VAR_FRAME_KEYS table. Verified against test_rendering_cartpole_kitless.py [ovstage-ovphysx-ovrtx_renderer-static]: before the fix it raised "render vars missing from the OVRTX frame"; after the fix it produces real (non-black) images matching the golden reference at SSIM 0.997, just outside the pixel-diff tolerance (likely minor rendering-noise drift, not a content bug). Not caused by and unrelated to newton-physics/newton#4256 -- this code path is OVPhysX + kitless OVRTX rendering and does not touch Newton physics.
|
| def _render_var_key(self, render_data: OVRTXCameraRenderData, source: str) -> str: | ||
| """Return *render_data*'s camera's ``frame.render_vars`` key for a render-var source name.""" | ||
| return resolve_render_var_key(source, render_data.render_scope_name) |
There was a problem hiding this comment.
On OVRTX 0.5+, the renderer contract tests now fail before processing a frame. Their OVRTXCameraRenderData fixture bypasses __init__ and does not define render_scope_name, but this code now accesses that attribute for every frame lookup, causing an AttributeError. The fixture and its frame keys need a camera scope so the new scoped lookup behavior is covered.
There was a problem hiding this comment.
Isaac Lab Review Bot
Replaces import-time render-var keys with per-camera key resolution using each camera’s authored render scope, addressing OVRTX 0.5+ black frames caused by unscoped lookups. The proposed unknown-source finding is not actionable for the changed consumers because every supplied source is a fixed, known entry from the existing render-var mapping.
- Design and architecture: The camera scope is captured consistently in the legacy, ovstage, and additional-camera registration paths, while version-specific key behavior remains centralized in
ovrtx_compat. The read-side remapping mirrors the render-product authoring convention; this creates a non-blocking maintenance dependency between the compatibility helper andbuild_render_product_as_string. - API: The existing
RENDER_VAR_FRAME_KEYSsymbol is retained, and the newresolve_render_var_key()interface is documented with modern typing and a Google-style docstring. A package changelog fragment documents the user-visible fix. - Implementation: The RGB, HDR, depth, albedo, normals, motion-vector, semantic, instance-segmentation, and segmentation metadata lookup paths all resolve keys through the owning camera’s scope. All changed call sites pass fixed source names already represented by
render_var_prim_paths_by_source(), so the fallback for an unknown source does not establish a concrete failure in this patch.
No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.
Automated review; human maintainers own approval decisions.
_make_ovrtx_camera_render_data() built OVRTXCameraRenderData via __new__, bypassing __init__, so it never got the new render_scope_name attribute added for the black-frame fix -- three pre-existing tests crashed with AttributeError. Give the helper a render_scope_name parameter and set it. Also add a regression test that a camera with a known render_scope_name reads its own scoped render-var key (not the unscoped fallback), plus unit tests for resolve_render_var_key's OVRTX 0.4 and 0.5+ branches. Previously nothing exercised the actual per-camera scoping the fix introduces, so a regression there could pass CI while reintroducing the black-frame bug.
|
run-ci |
There was a problem hiding this comment.
The functional fix looks correct. Please also update the PR description to preserve the distinction noted inline: #7860 made Isaac Lab author per-camera scopes for every OVRTX version; the OVRTX 0.5-specific behavior is that frame.render_vars is keyed by those authored prim paths.
|
|
||
| * Fixed :class:`~isaaclab_ov.renderers.ovrtx_renderer.OVRTXRenderer` producing all-black frames | ||
| for scene camera sensors on OVRTX 0.5+. Render-var lookups used a fixed, unscoped | ||
| ``"/Render/Vars/<name>"`` key, but OVRTX 0.5+ authors each camera's render vars under its own |
| 0.5 keys it by the authored RenderVar prim path. :data:`RENDER_VAR_FRAME_KEYS` gives the | ||
| *single-camera* (unscoped) form of that path (``"/Render/Vars/LdrColor"``) for callers | ||
| that do not have a specific camera's render scope. OVRTX 0.5+ actually authors render | ||
| vars under a *per-camera* scope (``"/RenderCamera_<id>/Vars/LdrColor"``, see |
There was a problem hiding this comment.
same conclusion about OVRTX version here
|
|
||
|
|
||
| def test_ovrtx_process_frame_reads_the_camera_scoped_key(monkeypatch: pytest.MonkeyPatch): | ||
| """OVRTX 0.5+ authors each camera's render vars under its own scope; frame reads for a |
There was a problem hiding this comment.
same conclusion about OVRTX version here
There was a problem hiding this comment.
question: are these version changes intentional? this patch does not touch any dependencies.
|
thanks for this fix @matthewtrepte - I dropped some comments about docstrings and descriptions and I checked the backport toggle since this would have landed on release branch too. |
Description
OVRTX 0.4 keys frame.render_vars by source name; 0.5+ keys it by the authored RenderVar prim path. The version-compat shim correctly detected this switch, but the static prim-path table it fell back to still used the pre-per-camera-scoping "/Render/Vars/" path. OVRTX 0.5+ actually authors each camera's render vars under its own scope, "/RenderCamera_/Vars/" (see render_scope_name in build_render_product_as_string, which already remaps correctly for authoring). The read side never applied that same remapping, so every frame.render_vars.get() silently returned None and the output buffer stayed at its zero-initialized (black) state.
Fixed by resolving each render-var key from the owning camera's render_scope_name (now stored on OVRTXCameraRenderData) via a new resolve_render_var_key() helper, instead of indexing the unscoped global RENDER_VAR_FRAME_KEYS table.
Verified against test_rendering_cartpole_kitless.py [ovstage-ovphysx-ovrtx_renderer-static]: before the fix it raised "render vars missing from the OVRTX frame"; after the fix it produces real (non-black) images matching the golden reference at SSIM 0.997, just outside the pixel-diff tolerance (likely minor rendering-noise drift, not a content bug).
Type of change
Release backport
developScreenshots
Please attach before and after screenshots of the change if applicable.
Checklist
Docker and GPU tests run on demand. Push the commits you want tested, then
comment
run-cion the pull request.pre-commitchecks with./isaaclab.sh --formatsource/<pkg>/changelog.d/for every touched package (do not editCHANGELOG.rstor bumpextension.toml— CI handles that)CONTRIBUTORS.mdor my name already exists there