Update Visualizer Integration Tests#5733
Conversation
There was a problem hiding this comment.
🔍 Isaac Lab Code Review
Thank you for this substantial PR improving the visualizer integration tests! I've conducted a thorough review focusing on test quality, Isaac Lab conventions, and potential issues.
✅ What's Working Well
-
Comprehensive Test Refactoring: The new
test_visualizer_integration.pyis significantly more robust than the previous implementation, with better structure and more thorough coverage of play/pause/resume cycles. -
Multi-Backend Testing: The parameterized tests covering both PhysX and Newton MJWarp backends are well-designed and follow pytest best practices.
-
Debug Infrastructure: The debug image capture system (
_WRITE_VIS_DEBUG_FRAMES,_save_visualizer_debug_image) is a valuable addition for diagnosing flaky tests. -
Clean Config Reorganization (new in 6055e74): The
VisualizerCfgfields are now logically grouped with section comments (Primary interactive camera, Tiled camera settings, Partial visualization, Markers, Live Plots, Internal). This improves readability significantly. -
Improved UI Naming: The Newton visualizer's ImageLogger controls renamed to "Tiled Camera View" with a dedicated
_draw_tiled_camera_view_controlsmethod provides a clearer user experience. -
Proper Test Separation (new in 6055e74): Splitting tiled camera tests into dedicated
test_*_tiled_camera_motionfunctions is a much cleaner architecture than mixing assertions in the main motion tests.
🔎 Outstanding Items
Still Open from Initial Review:
-
_WRITE_VIS_DEBUG_FRAMES = True(P1) — Should beFalsefor default CI runs to avoid writing debug PNGs to disk and PIL import dependency. -
Missing pyglet headless configuration (P1) — Newton ViewerGL tests may fail on headless CI without explicit
pyglet.options["headless"] = Truebefore AppLauncher import. -
Missing
__import__("rerun")guard (P2) — Inconsistent with the viser handling; missing rerun package will raise ImportError instead of clean skip.
📋 Changes in This Update (ed71805 → 6055e74)
| File | Change |
|---|---|
visualizer_cfg.py |
✅ Reorganized fields with section comments, improved docstrings |
newton_visualizer.py |
✅ New _draw_tiled_camera_view_controls() method, renamed section to "Tiled Camera View" |
test_visualizer_integration.py |
✅ Split tiled camera assertions into separate test_*_tiled_camera_motion test functions |
changelog.d/*.rst |
✅ Added proper changelog entry, removed .skip file |
🏁 Summary
Excellent progress! This update addresses the test organization concerns by cleanly separating tiled camera tests into dedicated functions, and improves the config documentation significantly.
Remaining blockers before merge:
- Set
_WRITE_VIS_DEBUG_FRAMES = False - Add pyglet headless configuration
- Add rerun import guard
Automated review by Isaac Lab Review Bot | Updated for commit 6055e74
Update (dbcf34b): New commits add documentation reorganization (visualization.rst moved to overview/core-concepts), typed preset CLI integration for RL scripts, teleop replay stats enhancements, FabricFrameView multi-GPU fix, and various test/changelog updates. These changes do not touch the visualizer test files — the three items flagged above remain open.
Update (004a12c): Added changelog entry (changelog.d/mtrepte-update_viz_integration_test.rst) describing tiled camera default updates. No code changes in this commit — the three items flagged above remain open.
Greptile SummaryThis PR replaces the old
Confidence Score: 3/5Two test-file issues need fixing before merging: the debug PNG write flag is enabled by default and the pyglet headless guard was dropped, both of which can cause unexpected CI failures. The debug flag being left as True will write PNG files on every CI run and adds an implicit Pillow requirement; the missing pyglet headless setup is a regression from the deleted file that the original comment explicitly called out as required for headless Newton ViewerGL. Both issues are in the test path, not production code, but can cause CI runs to fail or behave unexpectedly. source/isaaclab_visualizers/test/test_visualizer_integration.py needs the debug flag corrected and the pyglet headless setup restored; source/isaaclab/isaaclab/scene/scene_data_provider.py warrants a second look at how non-env-path cameras are handled in _walk_camera_prims. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["KitVisualizer._setup_camera_sensor_view()"] --> B{uses_camera_sensor_view?}
B -- No --> Z[return]
B -- Yes --> C{cameras_enabled?}
C -- No --> ERR[raise RuntimeError]
C -- Yes --> D[Create / resolve camera sensor]
D --> E{runtime_headless?}
E -- No --> F[_setup_camera_image_window]
E -- Yes --> G[Log: running without image panel]
H["KitVisualizer._update_camera_image_panel()"] --> I{camera_sensor is None?}
I -- Yes --> Z2[return]
I -- No --> J[Update owned camera poses]
J --> K[camera_sensor.update]
K --> L{camera_image_provider is None?}
L -- Yes --> Z3[return]
L -- No --> M[camera_rgb_batch → upload to panel]
Reviews (1): Last reviewed commit: "sync" | Re-trigger Greptile |
| "isaaclab.sim.simulation_context", | ||
| ) | ||
|
|
||
| _WRITE_VIS_DEBUG_FRAMES = True |
There was a problem hiding this comment.
Debug flag enabled in test code — contradicts PR description
The PR description states that debug image capture is "disabled by default," but _WRITE_VIS_DEBUG_FRAMES = True means every CI run will write PNG files to logs/viz_integration_captures. This also introduces a hard runtime dependency on PIL (imported inside _save_visualizer_debug_image); if Pillow is not in the test dependencies, every test that reaches frame-capture paths will raise an ImportError.
| _WRITE_VIS_DEBUG_FRAMES = True | |
| _WRITE_VIS_DEBUG_FRAMES = False | |
| """Whether to emit visualizer debug PNGs during integration tests.""" |
| from __future__ import annotations | ||
|
|
||
| import warp as wp | ||
|
|
||
| from isaaclab.app import AppLauncher | ||
|
|
||
| # launch Kit app | ||
| simulation_app = AppLauncher(headless=True, enable_cameras=True).app |
There was a problem hiding this comment.
Missing
pyglet headless configuration required for Newton ViewerGL
The deleted test_visualizer_cartpole_integration.py contained an explicit comment explaining this requirement: "Pyglet must use HeadlessWindow (EGL) before pyglet.window is imported so Newton ViewerGL can construct without an X11 display." The new file omits import pyglet; pyglet.options["headless"] = True before AppLauncher. On headless CI machines without X11/Wayland, pyglet may fall back to a crashing backend at window-construction time, causing Newton visualizer tests to fail with a display error.
| from __future__ import annotations | |
| import warp as wp | |
| from isaaclab.app import AppLauncher | |
| # launch Kit app | |
| simulation_app = AppLauncher(headless=True, enable_cameras=True).app | |
| from __future__ import annotations | |
| import warp as wp | |
| # Pyglet must use HeadlessWindow (EGL) before ``pyglet.window`` is imported so Newton | |
| # ViewerGL can construct without an X11 display (matches ``headless=True`` on NewtonVisualizerCfg). | |
| import pyglet | |
| pyglet.options["headless"] = True | |
| from isaaclab.app import AppLauncher | |
| # launch Kit app | |
| simulation_app = AppLauncher(headless=True, enable_cameras=True).app |
| if visualizer_kind == "rerun": | ||
| __import__("newton") | ||
| from isaaclab_visualizers.rerun import RerunVisualizer, RerunVisualizerCfg | ||
|
|
||
| web_port, grpc_port = _allocate_rerun_test_ports(host="127.0.0.1") |
There was a problem hiding this comment.
Missing
__import__("rerun") guard inconsistent with viser handling
For viser (line 255) the code guards with __import__("viser") before the lazy import, allowing a clean skip if the package is absent. The __import__("rerun") guard present in the deleted file was removed, so a missing rerun package now produces an ImportError from the from isaaclab_visualizers.rerun import ... line rather than a clean skip signal.
| Args: | ||
| stage: USD stage to traverse, or ``None``. | ||
|
|
||
| Returns: | ||
| Dictionary with keys ``order`` (template prim paths using ``env_%d``), | ||
| ``positions``, ``orientations`` (per-camera, per-env, with ``None`` for | ||
| absent envs), and ``num_envs``. Returns ``None`` when ``stage`` is ``None``. | ||
| """ | ||
| if stage is None: | ||
| return None | ||
|
|
There was a problem hiding this comment.
Non-env-path cameras silently assigned
world_id=0
In _walk_camera_prims, world_id is reset to 0 at the top of each iteration. Any camera prim whose path does not match _ENV_PATH_RE (e.g. /World/Camera) gets world_id=0, and the if world_id > num_envs: num_envs = world_id branch updates num_envs from -1 to 0. After num_envs += 1 the result is 1, so that global camera is placed into per_world_pos[0] — indistinguishable from an env_0 camera. Callers iterating the result by environment index will silently receive a global camera pose as if it belongs to env_0.
Description
Improve the visualizer integration test
Type of change
Screenshots
Please attach before and after screenshots of the change if applicable.
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there