Skip to content

Commit 2644c1e

Browse files
matthewtreptebdilinilahuidongcgreptile-apps[bot]pbarejko
authored
Sync video recorder's (--video) renderer backend with the active visualizer (--visualizer) (#5474)
# Description <!-- Thank you for your interest in sending a pull request. Please make sure to check the contribution guidelines. Link: https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html 💡 Please try to keep PRs small and focused. Large PRs are harder to review and merge. --> Extending Brian's original PR: Sync video recorder's (--video) renderer backend with the active visualizer (--visualizer) Change enable cross recording support for Renderers and Visualizers Also fixes https://nvbugs/6121118 <!-- As a practice, it is recommended to open an issue to have discussions on the proposed pull request. This makes it easier for the community to keep track of what is being developed or added, and if a given feature is demanded by more than one party. --> ## Type of change <!-- As you go through the list, delete the ones that are not applicable. --> - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) ## Screenshots Please attach before and after screenshots of the change if applicable. <!-- Example: | Before | After | | ------ | ----- | | _gif/png before_ | _gif/png after_ | To upload images to a PR -- simply drag and drop an image while in edit mode and it should upload the image directly. You can then paste that source into the above before/after sections. --> ## Checklist - [ ] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [ ] I have run the [`pre-commit` checks](https://pre-commit.com/) 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 <!-- As you go through the checklist above, you can mark something as done by putting an x character in it For example, - [x] I have done this task - [ ] I have not done this task --> --------- Signed-off-by: bdilinila <148156773+bdilinila@users.noreply.github.com> Signed-off-by: Kelly Guo <kellyg@nvidia.com> Signed-off-by: matthewtrepte <mtrepte@nvidia.com> Co-authored-by: Brian Dilinila <bdilinila@nvidia.com> Co-authored-by: HuiDong Chen <huidongc@nvidia.com> Co-authored-by: bdilinila <148156773+bdilinila@users.noreply.github.com> Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> Co-authored-by: Piotr Barejko <pbarejko@nvidia.com> Co-authored-by: myurasov-nv <168484206+myurasov-nv@users.noreply.github.com> Co-authored-by: Pascal Roth <57946385+pascal-roth@users.noreply.github.com> Co-authored-by: Antoine Richard <antoiner@nvidia.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: ClemensSchwarke <clemens.schwarke@gmail.com> Co-authored-by: rwiltz <165190220+rwiltz@users.noreply.github.com> Co-authored-by: Kelly Guo <kellyg@nvidia.com> Co-authored-by: Kelly Guo <kelly@nvidia.com> Co-authored-by: ooctipus <zhengyuz@nvidia.com> Co-authored-by: hougantc-nvda <127865892+hougantc-nvda@users.noreply.github.com> Co-authored-by: Piotr Barejko <piotrbarejko@protonmail.com>
1 parent 9ffafbb commit 2644c1e

20 files changed

Lines changed: 712 additions & 94 deletions

apps/isaaclab.python.headless.rendering.kit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ keywords = ["experience", "app", "isaaclab", "python", "camera", "minimal"]
1717
[dependencies]
1818
# Isaac Lab minimal app
1919
"isaaclab.python.headless" = {}
20+
"isaacsim.core.rendering_manager" = {}
2021
"omni.replicator.core" = {}
2122

2223
# Rendering

docs/source/features/visualization.rst

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,96 @@ Also, there is a CLI arg ``--max_visible_envs`` that overrides ``VisualizerCfg.m
185185
- any
186186
- Run headless; ``--headless`` takes precedence.
187187

188+
Video Recording
189+
---------------
190+
191+
Video recording is enabled with the ``--video`` flag. When combined with ``--visualizer``,
192+
the visualizer selection also determines which backend captures the video frames:
193+
194+
- ``--visualizer kit`` enables ``--video`` capture through the Isaac RTX renderer (Omniverse Replicator).
195+
- ``--visualizer newton`` enables ``--video`` capture through the Newton OpenGL renderer.
196+
- ``--visualizer rerun`` does not produce ``--video`` clips; it records Rerun ``.rrd`` data for replay
197+
through the Rerun visualizer.
198+
- ``--visualizer viser`` does not currently provide a ``--video`` recording backend.
199+
200+
When both Kit and Newton visualizers are active, Isaac Lab records a single ``--video`` stream and
201+
Kit takes precedence. To record from the renderer/physics stack instead of the active visualizer,
202+
set ``VideoRecorderCfg.backend_source = "renderer"`` in the task configuration.
203+
204+
.. list-table:: ``--video`` compatibility: visualizer × renderer preset
205+
:header-rows: 1
206+
:widths: 28 36 36
207+
208+
* - Renderer preset
209+
- ``--visualizer kit --video``
210+
- ``--visualizer newton --video``
211+
* - ``isaacsim_rtx_renderer``
212+
- ✅ Kit RTX captures video *(default, no change)*
213+
- ✅ Newton GL captures video *(overrides RTX backend)*
214+
* - ``newton_renderer``
215+
- ✅ Kit RTX captures video *(overrides Newton backend)*
216+
- ✅ Newton GL captures video *(default, no change)*
217+
* - ``ovrtx_renderer``
218+
- ❌ **Raises an error** — see note below
219+
- ✅ Newton GL captures video; ovrtx provides camera sensor data
220+
221+
.. note::
222+
223+
``--visualizer kit`` combined with ``ovrtx_renderer`` raises a ``ValueError`` at startup.
224+
Both Kit (Isaac Sim) and ovrtx ship conflicting RTX hydra libraries compiled against
225+
different USD namespaces (``pxrInternal_v0_25_11`` vs ``ovInternal_v0_25_11``), which
226+
causes a dynamic-linker crash when loaded into the same process.
227+
Use ``--visualizer newton`` instead — it is compatible with all renderer presets.
228+
229+
**Record video with the ovrtx renderer preset**
230+
231+
.. code-block:: bash
232+
233+
./isaaclab.sh -p scripts/benchmarks/benchmark_rsl_rl.py \
234+
--task=Isaac-Repose-Cube-Shadow-Vision-Direct-v0 \
235+
--enable_cameras \
236+
--visualizer newton \
237+
--video \
238+
--video_length=300 \
239+
--video_interval=2000 \
240+
--max_iterations=5 \
241+
--num_envs=1024 \
242+
--benchmark_backend=summary \
243+
"presets=newton,ovrtx_renderer,rgb"
244+
245+
**Record video with the Isaac RTX renderer preset using the Newton video backend**
246+
247+
.. code-block:: bash
248+
249+
./isaaclab.sh -p scripts/benchmarks/benchmark_rsl_rl.py \
250+
--task=Isaac-Repose-Cube-Shadow-Vision-Direct-v0 \
251+
--enable_cameras \
252+
--visualizer newton \
253+
--video \
254+
--video_length=300 \
255+
--video_interval=2000 \
256+
--max_iterations=5 \
257+
--num_envs=1024 \
258+
--benchmark_backend=summary \
259+
"presets=physx,isaacsim_rtx_renderer,rgb"
260+
261+
**Record video with the Isaac RTX renderer preset using the Kit video backend**
262+
263+
.. code-block:: bash
264+
265+
./isaaclab.sh -p scripts/benchmarks/benchmark_rsl_rl.py \
266+
--task=Isaac-Repose-Cube-Shadow-Vision-Direct-v0 \
267+
--enable_cameras \
268+
--visualizer kit \
269+
--video \
270+
--video_length=300 \
271+
--video_interval=2000 \
272+
--max_iterations=5 \
273+
--num_envs=1024 \
274+
--benchmark_backend=summary \
275+
"presets=physx,isaacsim_rtx_renderer,rgb"
276+
277+
188278
Visualizer Backends
189279
-------------------
190280

docs/source/how-to/record_video.rst

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ Recording video clips during training
33

44
Isaac Lab supports recording video clips during training using the
55
`gymnasium.wrappers.RecordVideo <https://gymnasium.farama.org/main/_modules/gymnasium/wrappers/record_video/>`_ class.
6-
When the ``--video`` flag is enabled, Isaac Lab captures a perspective view of the scene. The backend
7-
is chosen automatically from the active physics and renderer stack: an Isaac Sim Kit camera or a
8-
Newton GL headless viewer.
6+
When the ``--video`` flag is enabled, Isaac Lab captures a perspective view of the scene. If a Kit or
7+
Newton visualizer is active, that visualizer selects the video backend by default. Otherwise, the
8+
backend is chosen automatically from the active physics and renderer stack: an Isaac Sim Kit camera or
9+
a Newton GL headless viewer.
910

1011
This feature can be enabled by installing ``ffmpeg`` and using the following command line arguments with the training
1112
script:
@@ -32,8 +33,8 @@ Overview
3233

3334
The video recording feature is implemented using the ``VideoRecorder`` class. This class is responsible for resolving the video backend from the scene, capturing the video frames, and saving them to a file.
3435

35-
* ``VideoRecorderCfg`` (``isaaclab.envs.utils.video_recorder_cfg``) holds resolution and world-space
36-
perspective parameters ``camera_position`` and ``camera_target`` (defaults to a diagonal view of the
36+
* ``VideoRecorderCfg`` (``isaaclab.envs.utils.video_recorder_cfg``) holds resolution, backend source,
37+
and world-space perspective parameters ``eye`` and ``lookat`` (defaults to a diagonal view of the
3738
scene).
3839
* ``VideoRecorder`` (``isaaclab.envs.utils.video_recorder``) picks a video backend from the scene
3940
(Kit vs Newton GL), builds the matching low-level capture object, and returns RGB frames via
@@ -47,12 +48,12 @@ The video recording feature is implemented using the ``VideoRecorder`` class. Th
4748
Configuration: ``VideoRecorderCfg``
4849
------------------------------------
4950

50-
The dataclass lives in ``isaaclab.envs.utils.video_recorder_cfg``. Fields ``camera_position`` and
51-
``camera_target`` are the perspective ``eye`` and ``lookat`` points in meters.
51+
The dataclass lives in ``isaaclab.envs.utils.video_recorder_cfg``. Fields ``eye`` and ``lookat`` are
52+
the perspective camera position and target in meters.
5253

5354
.. literalinclude:: ../../../source/isaaclab/isaaclab/envs/utils/video_recorder_cfg.py
5455
:language: python
55-
:lines: 20-48
56+
:lines: 20-58
5657

5758

5859
Task framing: ``ViewerCfg``
@@ -72,11 +73,20 @@ Backend selection: Kit vs Newton GL
7273
-------------------------------------
7374

7475
``VideoRecorder`` resolves the implementation from the live :class:`~isaaclab.scene.InteractiveScene`.
75-
If the user provides the PhysX physics (``presets=physx,...``) or Isaac RTX (``presets=isaac_rtx_renderer,...``) in the sensor stack, the Kit path is selected (``omni.replicator`` on
76-
``/OmniverseKit_Persp``). The Newton GL path is selected when Newton physics is active (``presets=newton,...``) or the Newton
77-
Warp renderer (``presets=newton_renderer,...``) appears in the sensor stack - and neither PhysX nor Isaac RTX is present to claim the
78-
Kit path. OVRTX (``presets=ovrtx_renderer,...`` from ``isaaclab_ov``) can pair with IsaacSim or Newton physics; in that case the video backend is
79-
selected via the physics preset. If both Kit and Newton GL signals are present (e.g., ``presets=physx,isaac_rtx_renderer,...`` or ``presets=newton,newton_renderer,...``), the Kit path is chosen.
76+
With the default ``VideoRecorderCfg.backend_source = "visualizer"``, an active ``--visualizer kit``
77+
selects the Kit path (``omni.replicator`` on ``/OmniverseKit_Persp``), and an active
78+
``--visualizer newton`` selects the Newton GL path. If both visualizers are active, Kit takes
79+
precedence and only one ``--video`` stream is recorded. Rerun records ``.rrd`` replay data through
80+
the Rerun visualizer rather than producing ``--video`` clips, and Viser does not currently provide a
81+
``--video`` recording backend.
82+
83+
Set ``VideoRecorderCfg.backend_source = "renderer"`` to ignore active visualizers and choose from the
84+
physics/renderer stack instead. In that mode, PhysX physics (``presets=physx,...``) or Isaac RTX
85+
(``presets=isaac_rtx_renderer,...``) selects the Kit path. Newton physics (``presets=newton,...``) or
86+
the Newton Warp renderer (``presets=newton_renderer,...``) selects the Newton GL path when no Kit
87+
signal is present. OVRTX (``presets=ovrtx_renderer,...`` from ``isaaclab_ov``) can pair with IsaacSim
88+
or Newton physics; in that case the video backend is selected via the physics preset. If both Kit and
89+
Newton GL signals are present, the Kit path is chosen.
8090

8191
.. literalinclude:: ../../../source/isaaclab/isaaclab/envs/utils/video_recorder.py
8292
:language: python
@@ -87,8 +97,8 @@ Construction and dispatch
8797
--------------------------
8898

8999
When ``env_render_mode`` is ``"rgb_array"`` (as when wrappers or scripts request RGB frames for
90-
video), the recorder instantiates the backend-specific helper and passes through ``camera_position``,
91-
``camera_target``, and window size.
100+
video), the recorder instantiates the backend-specific helper and passes through ``eye``, ``lookat``,
101+
and window size.
92102

93103
.. literalinclude:: ../../../source/isaaclab/isaaclab/envs/utils/video_recorder.py
94104
:language: python
@@ -98,18 +108,19 @@ video), the recorder instantiates the backend-specific helper and passes through
98108
Customising the camera view
99109
----------------------------
100110

101-
When ``--video`` is passed, the recording camera uses the same
102-
position and look-at target as the interactive viewer. The defaults come from
111+
When ``--video`` is passed, the recording camera uses the same configured
112+
position and look-at target as the active Kit or Newton visualizer when that visualizer drives backend
113+
selection. Otherwise, the defaults come from
103114
:class:`~isaaclab.envs.common.ViewerCfg`:
104115

105116
* ``eye = (7.5, 7.5, 7.5)`` — camera position in world space (metres)
106117
* ``lookat = (0.0, 0.0, 0.0)`` — camera look-at target in world space (metres)
107118
* Resolution ``1280x720``
108119

109-
To change the recording angle, override the ``viewer`` field in your task's environment config.
110-
The RL base classes automatically copy ``eye`` and ``lookat`` into ``VideoRecorderCfg`` before
111-
recording starts (when ``origin_type`` is ``"world"``), so the video clip uses the same viewpoint
112-
as the interactive viewport:
120+
To change the recording angle without a visualizer, override the ``viewer`` field in your task's
121+
environment config. The RL base classes automatically copy ``eye`` and ``lookat`` into
122+
``VideoRecorderCfg`` before recording starts (when ``origin_type`` is ``"world"``), so the video clip
123+
uses the same configured viewpoint as the interactive viewport:
113124

114125
.. code-block:: python
115126
@@ -144,6 +155,12 @@ Summary
144155
* - ``newton,...,ovrtx_renderer,...`` (OVRTX + Newton physics)
145156
- Newton GL (``"newton_gl"``)
146157
- ``newton.viewer.ViewerGL`` on the SDP Newton model
158+
* - ``--visualizer kit`` with default ``backend_source``
159+
- Kit (``"kit"``)
160+
- Visualizer ``eye`` / ``lookat`` copied to ``/OmniverseKit_Persp`` + Replicator RGB
161+
* - ``--visualizer newton`` with default ``backend_source``
162+
- Newton GL (``"newton_gl"``)
163+
- Visualizer ``eye`` / ``lookat`` initially, then live Newton viewer camera sync per frame
147164

148165

149166
See also
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Added
2+
^^^^^
3+
4+
* Added backend-agnostic :class:`~isaaclab.markers.VisualizationMarkers` support for
5+
marker-capable Kit, Newton, Rerun, and Viser visualizers.

source/isaaclab/isaaclab/envs/direct_marl_env.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ def _init_sim(self, render_mode: str | None = None, **kwargs):
176176
if self.cfg.video_recorder is not None:
177177
self.cfg.video_recorder.env_render_mode = render_mode
178178
vr = self.cfg.video_recorder
179-
vr.camera_position = tuple(float(x) for x in self.cfg.viewer.eye)
180-
vr.camera_target = tuple(float(x) for x in self.cfg.viewer.lookat)
179+
vr.eye = tuple(float(x) for x in self.cfg.viewer.eye)
180+
vr.lookat = tuple(float(x) for x in self.cfg.viewer.lookat)
181181
self.video_recorder: VideoRecorder = self.cfg.video_recorder.class_type(self.cfg.video_recorder, self.scene)
182182
else:
183183
self.video_recorder = None

source/isaaclab/isaaclab/envs/direct_rl_env.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ def _init_sim(self, render_mode: str | None = None, **kwargs):
182182
self.cfg.video_recorder.env_render_mode = render_mode
183183
# Perspective --video uses same eye/lookat as task viewer (Kit persp + Newton GL).
184184
vr = self.cfg.video_recorder
185-
vr.camera_position = tuple(float(x) for x in self.cfg.viewer.eye)
186-
vr.camera_target = tuple(float(x) for x in self.cfg.viewer.lookat)
185+
vr.eye = tuple(float(x) for x in self.cfg.viewer.eye)
186+
vr.lookat = tuple(float(x) for x in self.cfg.viewer.lookat)
187187
self.video_recorder: VideoRecorder = self.cfg.video_recorder.class_type(self.cfg.video_recorder, self.scene)
188188
else:
189189
self.video_recorder = None

source/isaaclab/isaaclab/envs/manager_based_env.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ def _init_sim(self):
195195
# Instantiate the video recorder before sim.reset() so that any fallback Camera
196196
# (used for state-based envs without an observation camera) is spawned into the USD
197197
# stage and registered for the PHYSICS_READY callback before physics initialises.
198-
# env_render_mode and camera_position/camera_target are forwarded by subclasses (e.g. ManagerBasedRLEnv)
198+
# env_render_mode and eye/lookat are forwarded by subclasses (e.g. ManagerBasedRLEnv)
199199
# into cfg.video_recorder before calling super().__init__().
200200
if self.cfg.video_recorder is not None:
201201
self.video_recorder: VideoRecorder = self.cfg.video_recorder.class_type(self.cfg.video_recorder, self.scene)

source/isaaclab/isaaclab/envs/manager_based_rl_env.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ def __init__(self, cfg: ManagerBasedRLEnvCfg, render_mode: str | None = None, **
8181
# (env_render_mode="rgb_array") and the perspective view matches the task viewport.
8282
if cfg.video_recorder is not None:
8383
cfg.video_recorder.env_render_mode = render_mode
84-
cfg.video_recorder.camera_position = tuple(float(x) for x in cfg.viewer.eye)
85-
cfg.video_recorder.camera_target = tuple(float(x) for x in cfg.viewer.lookat)
84+
cfg.video_recorder.eye = tuple(float(x) for x in cfg.viewer.eye)
85+
cfg.video_recorder.lookat = tuple(float(x) for x in cfg.viewer.lookat)
8686

8787
# initialize the base class to setup the scene.
8888
super().__init__(cfg=cfg)

0 commit comments

Comments
 (0)