Skip to content

Add tutorial script and documentation for Tiled Camera View in Visualizers#5927

Open
matthewtrepte wants to merge 9 commits into
isaac-sim:developfrom
matthewtrepte:mtrepte/tiled_cam_tut
Open

Add tutorial script and documentation for Tiled Camera View in Visualizers#5927
matthewtrepte wants to merge 9 commits into
isaac-sim:developfrom
matthewtrepte:mtrepte/tiled_cam_tut

Conversation

@matthewtrepte
Copy link
Copy Markdown
Contributor

@matthewtrepte matthewtrepte commented Jun 2, 2026

Description

Add tutorial script and documentation for Tiled Camera View in Visualizers

Type of change

  • New feature (non-breaking change which adds functionality)
  • 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

@github-actions github-actions Bot added documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team labels Jun 2, 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.

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.jpg
  • docs/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()
    return

5. 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 (85d122e4b5aefe4a). 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_camera as the active path but the RST documentation text references right_camera — minor inconsistency in the docs text vs actual code. (RST line: "...camera sensor located at .../right_camera" but code uses head_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_cameraleft_arm_camera_sim_view_frame/left_camera (left camera correctly on left arm frame)
  • Active path: right_arm_camera_sim_view_frame/head_camerahead_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 (4c8ca27712c5349b). 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_camera consistently (matching previous code fix)
  • Changed --num_envs 64--num_envs 25 to 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 reduction
  • source/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.py and kit_visualizer.py now properly tag generated cameras and viewport cameras with omni:scenePartition tokens for RTX scene partitioning compatibility
  • Changelog consolidation: Individual changelog.d/*.rst fragments consolidated into CHANGELOG.rst; version bumped to 0.1.1
  • Test import updates: CartpoleCameraPresetsEnvCfgCartpoleCameraEnvCfg following 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 an omni:scenePartition attribute 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 to KitVisualizer and IsaacRtxRenderer on develop).

  • Import cleanup: Sdf, UsdGeom, and FrameView imports 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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 2, 2026

Greptile Summary

This PR adds a tutorial script (run_tiled_camera_visualizer.py) and accompanying how-to documentation for the tiled camera panel in the Kit and Newton visualizers, plus a cross-reference link in the existing visualization overview page.

  • New tutorial script demonstrates Kit (generated cameras following Anymal-D base) and Newton (generated cameras following Kuka palm link) tiled camera configs, with two TODO workarounds that disable CUDNN and remove the Dexsuite wrist camera sensor.
  • New how-to doc (visualizer_tiled_camera.rst) describes both use cases, but the Newton section incorrectly states the demo uses an existing wrist-mounted camera when the code actually generates cameras (tiled_cam_prim_path = None); the emphasize-lines range also misses the last two Newton config lines.

Confidence Score: 3/5

The 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

Filename Overview
scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py New tutorial script for tiled camera visualizer; Newton config sets tiled_cam_prim_path=None (generated cameras) while comment and docs claim it uses an existing wrist camera — a logic mismatch. Contains two TODO workarounds that disable CUDNN and remove a wrist camera sensor.
docs/source/how-to/visualizer_tiled_camera.rst New how-to page documenting tiled camera use; Newton section incorrectly describes behavior as 'existing wrist camera' when the script uses generated cameras; emphasize-lines range misses two Newton config lines (92-93).
docs/source/how-to/index.rst Adds 'Using Visualizers' toctree section linking to the new visualizer_tiled_camera guide; straightforward and correct.
docs/source/overview/core-concepts/visualization.rst Adds a cross-reference link to the new how-to guide in the tiled camera section; two lines added, no issues.

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]
Loading

Reviews (1): Last reviewed commit: "Merge branch 'develop' into mtrepte/tile..." | Re-trigger Greptile

Comment on lines +88 to +93
# 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"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 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.

Comment on lines +23 to +26
.. literalinclude:: ../../../scripts/tutorials/07_visualizers/run_tiled_camera_visualizer.py
:language: python
:emphasize-lines: 79-91
:linenos:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 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.

Suggested change
.. 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!

@matthewtrepte matthewtrepte requested a review from Toni-SM as a code owner June 3, 2026 00:38
Signed-off-by: matthewtrepte <mtrepte@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant