Add tutorial script and documentation for Tiled Camera View in Visualizers#5927
Add tutorial script and documentation for Tiled Camera View in Visualizers#5927matthewtrepte wants to merge 9 commits into
Conversation
There was a problem hiding this comment.
Review: Add tutorial script and documentation for Tiled Camera View in Visualizers
Thanks for adding this tutorial! The tiled camera visualizer is a valuable debugging tool, and having a dedicated how-to guide with a runnable script is a great addition. Below are my findings.
Findings
1. Missing image assets (blocking)
The RST documentation references two figures that are not included in this PR:
docs/source/_static/visualizers/tiled_camera_kit_anymal_activate.jpgdocs/source/_static/visualizers/tiled_camera_newton_kuka_wrist_activate.jpg
The docs/source/_static/visualizers/ directory exists on develop (containing newton_viz.jpg, ov_viz.jpg, rerun_viz.jpg), but these two new images are missing. The documentation build will produce broken figure references.
2. Newton config contradicts documentation and code comment (medium)
The RST documentation describes the Newton example as using an existing wrist camera sensor (/World/envs/env_.*/Robot/ee_link/palm_link/Camera), and the in-code comment at line 88 says "Edit these VisualizerCfg fields to display a different existing camera". However, the actual code configures a generated camera pattern:
visualizer_cfg.tiled_cam_prim_path = None # ← should be the sensor path for "existing" mode
visualizer_cfg.tiled_cam_target_prim_path = "/World/envs/*/Robot/ee_link/palm_link"Per the visualization docs, existing-camera mode requires tiled_cam_prim_path to be set to the Camera sensor path. Either:
- Set
tiled_cam_prim_path = "/World/envs/env_.*/Robot/ee_link/palm_link/Camera"(as described in the RST), or - Update the documentation and comment to state that Newton also uses generated cameras in this tutorial.
3. Silent sensor removal without user feedback (low)
Lines 101–104 silently nullify env_cfg.scene.wrist_camera and env_cfg.observations.wrist_image as a workaround for Dexsuite duo_camera conflicts. Users who adapt this script may be confused when their wrist camera observations disappear without explanation. Consider adding a log message:
print("[INFO]: Disabling wrist_camera sensor to avoid duplicate prim construction in this tutorial.")4. Main loop lacks graceful exit for missing visualizers (low)
In main(), if sim.visualizers is an empty list (e.g., visualizer initialization failed silently), the condition sim.visualizers and not any(...) evaluates to False indefinitely, causing an infinite loop with no way to exit except Ctrl+C. Consider adding a guard:
if not sim.visualizers:
print("[WARN]: No visualizers found. Exiting.")
env.close()
return5. v.is_running() vs v.is_closed asymmetry (nit)
In the loop exit condition:
not any(v.is_running() and not v.is_closed for v in sim.visualizers)is_running() is called as a method while is_closed is accessed as an attribute/property. If is_closed is actually a method rather than a property, this expression would never evaluate to True (a bound method is always truthy). Worth verifying the visualizer API — if it should be v.is_closed(), this would be a silent bug.
6. PR checklist items are all unchecked
All checklist items (pre-commit, changelog, CONTRIBUTORS.md, etc.) remain unchecked. The CI pre-commit check passes, so formatting appears fine. Please confirm the remaining items (changelog fragment, CONTRIBUTORS entry) before merge.
Summary
The core content is solid — clear documentation structure, good troubleshooting section, and a well-organized tutorial script. The blocking issue is the missing image assets. The Newton config inconsistency (finding #2) should also be resolved to avoid confusing users about generated vs. existing camera modes. The remaining items are minor polish.
Nice work! 🚀
Update (b5aefe4): Reviewed new commits pushed since the initial review (85d122e4 → b5aefe4a). This is a substantial improvement that addresses most of my earlier findings:
Previously raised issues — now resolved ✅
| # | Finding | Status |
|---|---|---|
| 1 | Missing image assets | ✅ Fixed — 4 new PNG screenshots added (Kit interactive/tiled views, Newton interactive/tiled views) |
| 2 | Newton config contradicts docs (generated vs existing camera) | ✅ Fixed — _make_newton_visualizer_cfg() now correctly sets tiled_cam_prim_path to an existing camera path (head_camera) and leaves tiled_cam_eye/tiled_cam_target_prim_path as None |
| 3 | Silent sensor removal workaround | ✅ Fixed — Dexsuite workaround completely removed; Newton example now uses Galbot task which has no conflict |
| 5 | is_running() vs is_closed asymmetry |
No longer applicable — loop logic unchanged but this was a nit |
Quality of the new changes
Script refactoring is well done. The monolithic _configure_visualizers() has been split into clear, focused helpers (_make_kit_visualizer_cfg, _make_newton_visualizer_cfg, _requested_visualizers with validation inlined). This makes it much easier for users to adapt configs for their own use cases.
Documentation is significantly improved. The RST rewrite provides better structure with distinct example headings, step-by-step instructions, and proper figure captions explaining what the highlighted UI elements are. The switch from Kuka-Allegro to Galbot for the Newton example is a better choice since it avoids the duo_camera workaround entirely.
Minor fabric_frame_view.py fix — downgrading the topology-change log from info to debug is sensible; this is internal noise that does not need to show up at default log levels.
Remaining items (minor)
- Finding #4 (graceful exit for missing visualizers) — still applicable but low priority
- Finding #6 (PR checklist) — items still unchecked; please confirm before merge
- The Newton config comments list
head_cameraas the active path but the RST documentation text referencesright_camera— minor inconsistency in the docs text vs actual code. (RST line: "...camera sensor located at.../right_camera" but code useshead_camera)
Overall this revision is in good shape. Nice refactoring work! 👍
Update (4c8ca27): Reviewed latest commit. This is a small but important fix correcting the camera prim paths in the Newton visualizer config:
- Comment path:
right_arm_camera_sim_view_frame/left_camera→left_arm_camera_sim_view_frame/left_camera(left camera correctly on left arm frame) - Active path:
right_arm_camera_sim_view_frame/head_camera→head_camera_sim_view_frame/head_camera(head camera correctly on head camera frame)
This resolves the doc/code inconsistency I flagged in my previous update regarding the camera path references. The paths now correctly match the actual robot prim hierarchy. ✅
Remaining items: Only finding #4 (graceful exit guard) and #6 (PR checklist) from the original review remain as minor items. LGTM otherwise. 👍
Update (12c5349): Reviewed new commits pushed since last review (4c8ca277 → 12c5349b). This batch addresses more of my earlier findings and further polishes the documentation:
Previously raised issues — now resolved ✅
| # | Finding | Status |
|---|---|---|
| 4 | Graceful exit for missing visualizers | ✅ Fixed — Script now checks if not sim.visualizers and exits cleanly with a warning message, exactly as suggested |
| 6 | PR checklist / changelog | ✅ Partially fixed — Changelog fragment added (changelog.d/mtrepte-tiled-camera-visualizer-tutorial.rst) |
Changes in this batch
Documentation (visualizer_tiled_camera.rst):
- Restructured to place figures immediately after example headings — much better flow for readers
- Simplified section headings (e.g., "Example Two: Streaming from Robot-Mounted Cameras" instead of the longer visualizer-specific variant)
- Clarified that either Kit or Newton visualizer can run either example
- Removed redundant instructions about showing/hiding the tiled camera panel (now shown once with the figure)
- Updated Newton example to reference
head_cameraconsistently (matching previous code fix) - Changed
--num_envs 64→--num_envs 25to match the "25 environments" stated in the description
Script (run_tiled_camera_visualizer.py):
- Added
from __future__ import annotations(Python best practice for forward references) - Added the graceful exit guard for missing visualizers (my finding #4)
Changelog:
- Added proper changelog fragment describing the tutorial update
Remaining items (very minor)
- Finding #6 — PR checklist boxes still appear unchecked in the PR description. The changelog fragment is now present, so this is just a cosmetic PR-description cleanup.
This revision is polished and addresses all significant findings from my earlier reviews. LGTM ✅
Update (e4b091a): Reviewed latest commit. This is a minor documentation reordering in visualization.rst — the cross-reference paragraph linking to the tiled camera tutorial (:doc:\/source/how-to/visualizer_tiled_camera`) has been moved from after the "Note, Kit tiled camera views require launching with --enable_cameras`" line to immediately after the "Camera Modes" section introduction. This improves discoverability by presenting the link to the runnable examples before the configuration details rather than after.
No functional changes, no new issues introduced. LGTM ✅
Update (5d4a6d1): Reviewed latest commit ("fix changelog frags"). This adds two per-package changelog fragments:
source/isaaclab_physx/changelog.d/mtrepte-tiled-camera-visualizer-tutorial.rst— documents the Fabric topology rebuild log-level reductionsource/isaaclab_visualizers/changelog.d/mtrepte-tiled-camera-visualizer-tutorial.rst— documents the tiled camera tutorial view synchronization update
This properly addresses finding #6 (PR checklist / changelog) from the original review by adding changelog entries to the specific packages that were modified, in addition to the existing isaaclab fragment. Good practice to have per-package changelogs matching where the code changes landed.
No functional changes, no new issues. LGTM ✅
Update (cf8cd61): Reviewed latest commit. This changes the resolution priority in prim_world_positions() (camera_view.py):
Functional change: Scene articulation state lookup is now attempted first (before FrameView/USD fallback), rather than only after the FrameView path fails. The docstring is updated accordingly to document the new priority: scene articulation → FrameView → USD XformCache.
This is a sensible improvement — when a scene is available with matching articulation data, it provides the most accurate PhysX-backed body positions and avoids the overhead of constructing a FrameView or querying USD. The previous ordering could return stale USD positions for articulated bodies in cases where FrameView construction failed but scene data was available.
New test: test_prim_world_positions_prefers_scene_articulation_state verifies that:
- Scene articulation state is correctly preferred over other resolution methods
- Environment index reordering (
[1, 0]) returns positions in the requested order
The test is well-structured with proper mocking via SimpleNamespace. No issues found.
No functional concerns with this change. LGTM ✅
Update (c4d7fb7): Reviewed merge commit from develop. This merge brings in infrastructure improvements:
- Scene partition tagging:
camera_view.pyandkit_visualizer.pynow properly tag generated cameras and viewport cameras withomni:scenePartitiontokens for RTX scene partitioning compatibility - Changelog consolidation: Individual
changelog.d/*.rstfragments consolidated intoCHANGELOG.rst; version bumped to 0.1.1 - Test import updates:
CartpoleCameraPresetsEnvCfg→CartpoleCameraEnvCfgfollowing cartpole task refactor
These are develop-branch infrastructure changes that don't affect the tutorial content. The tutorial script and documentation remain unchanged from the previous commit. No new issues introduced.
All findings from my original review have been addressed. LGTM ✅
Update (c4d7fb7): Reviewed merge commit from develop. The only PR-relevant change is in camera_view.py:
-
Scene partition tokens on generated cameras:
create_visualizer_camera()now authors anomni:scenePartitionattribute on each spawned visualizer camera prim, using the env name (e.g.env_0) derived from the prim path. This ensures generated tiled-camera prims participate correctly in RTX scene partitioning (matching the scene partition support added toKitVisualizerandIsaacRtxRendererondevelop). -
Import cleanup:
Sdf,UsdGeom, andFrameViewimports promoted from local/lazy to module-level — no functional change.
The remaining changes in this merge are from develop (cartpole refactor, visualizer changelog consolidation, kit_visualizer scene-partition additions) and are not part of this PR's authored content.
No new issues introduced. All previously raised findings remain resolved. LGTM ✅
| Kit visualizer with generated tiled cameras following Anymal-D robots. The annotated | ||
| circle and arrow should highlight the viewport selection menu used to activate the | ||
| ``Visualizer Tiled Camera`` panel. | ||
|
|
There was a problem hiding this comment.
The referenced image ../_static/visualizers/tiled_camera_kit_anymal_activate.jpg does not appear to be included in this PR. Please add the image assets or the doc build will show broken figures.
| # Edit these VisualizerCfg fields to display a different existing camera. | ||
| visualizer_cfg.tiled_cam_view = True | ||
| visualizer_cfg.tiled_cam_num = 64 | ||
| visualizer_cfg.tiled_cam_prim_path = None |
There was a problem hiding this comment.
The Newton branch here uses tiled_cam_prim_path = None with a tiled_cam_target_prim_path, which is the generated camera pattern (same as Kit). However, the RST documentation states Newton maps to an existing wrist camera sensor. Should this set tiled_cam_prim_path = "/World/envs/env_.*/Robot/ee_link/palm_link/Camera" instead to match the documented behavior?
| import gymnasium as gym | ||
| import torch | ||
|
|
||
| import isaaclab_tasks # noqa: F401 |
There was a problem hiding this comment.
Minor: list[str] return type uses PEP 604 syntax (Python 3.10+). If Isaac Lab supports 3.9, add from __future__ import annotations at the top of the file, or use typing.List[str].
Greptile SummaryThis PR adds a tutorial script (
Confidence Score: 3/5The tutorial script runs correctly as written, but the Newton section of the documentation contradicts what the code actually does, and the script ships with two hardcoded TODO workarounds that disable CUDNN and nullify a sensor. The Newton how-to text claims the demo showcases an existing wrist camera (via tiled_cam_prim_path), but the code sets that field to None and uses generated cameras instead — and then explicitly removes the wrist camera sensor through a workaround. Readers following the tutorial to learn the existing-camera pattern will be misled. The two TODO hacks are also present in tutorial code meant to be a clean, authoritative example. The Newton configuration block in run_tiled_camera_visualizer.py (lines 88–93) and the corresponding Newton section in docs/source/how-to/visualizer_tiled_camera.rst need to be brought into agreement — either the code should be updated to actually use tiled_cam_prim_path for an existing camera (and the TODO workaround resolved), or the documentation should be rewritten to accurately describe the generated-camera approach. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[run_tiled_camera_visualizer.py] --> B{--viz flag}
B -->|kit| C[KitVisualizerCfg\ntiled_cam_prim_path=None\ntiled_cam_target=.../Robot/base]
B -->|newton| D[NewtonVisualizerCfg\ntiled_cam_prim_path=None\ntiled_cam_target=.../palm_link]
C --> E[Generated cameras\nfollowing Anymal-D base]
D --> F{wrist_camera in scene?}
F -->|yes - TODO workaround| G[Remove wrist_camera\nfrom env_cfg.scene]
G --> H[Generated cameras\nfollowing palm link]
F -->|no| H
E --> I[env_cfg.sim.visualizer_cfgs]
H --> I
I --> J[launch_simulation]
J --> K[gym.make + step loop]
Reviews (1): Last reviewed commit: "Merge branch 'develop' into mtrepte/tile..." | Re-trigger Greptile |
| # Edit these VisualizerCfg fields to display a different existing camera. | ||
| visualizer_cfg.tiled_cam_view = True | ||
| visualizer_cfg.tiled_cam_num = 64 | ||
| visualizer_cfg.tiled_cam_prim_path = None | ||
| visualizer_cfg.tiled_cam_eye = (2.5, -3.0, 1.6) | ||
| visualizer_cfg.tiled_cam_target_prim_path = "/World/envs/*/Robot/ee_link/palm_link" |
There was a problem hiding this comment.
Newton config comment contradicts the actual field values
The inline comment says # Edit these VisualizerCfg fields to display a different existing camera., but the code immediately sets tiled_cam_prim_path = None. Per VisualizerCfg, None means "create generated cameras" — tiled_cam_prim_path must be set to a sensor path (e.g. "/World/envs/*/Robot/ee_link/palm_link/Camera") to use an existing camera. As a result, the Newton demo uses generated cameras following the palm link, not the wrist-mounted sensor. The companion documentation (visualizer_tiled_camera.rst, lines 59–64) further compounds this by stating "the script maps the tiled camera panel to the existing wrist camera sensor", which is incorrect. The wrist_camera sensor is also explicitly nulled out by the TODO workaround lower in _configure_visualizers, so no existing camera is present at runtime either.
| .. literalinclude:: ../../../scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py | ||
| :language: python | ||
| :emphasize-lines: 79-91 | ||
| :linenos: |
There was a problem hiding this comment.
The
emphasize-lines range stops at line 91, which is tiled_cam_prim_path = None for the Newton block. The next two Newton-specific lines — tiled_cam_eye (line 92) and tiled_cam_target_prim_path (line 93) — are configurable fields that the text asks readers to edit, but they are left un-highlighted. The range should extend to line 93 to match the Kit block's complete highlight.
| .. literalinclude:: ../../../scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py | |
| :language: python | |
| :emphasize-lines: 79-91 | |
| :linenos: | |
| .. literalinclude:: ../../../scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py | |
| :language: python | |
| :emphasize-lines: 79-93 | |
| :linenos: |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Signed-off-by: matthewtrepte <mtrepte@nvidia.com>
Description
Add tutorial script and documentation for Tiled Camera View in Visualizers
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