Skip to content

Conversation

@matthewtrepte
Copy link
Contributor

@matthewtrepte matthewtrepte commented Nov 8, 2025

Description

Initial design to support multiple visualizers with Isaac Lab 3.0

The visualizers

  • OV Visualizer
  • Newton OpenGL Visualizer
  • Newton Rerun Visualizer

Type of change

  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • 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 asset New asset feature or request isaac-sim Related to Isaac Sim team isaac-mimic Related to Isaac Mimic team infrastructure labels Nov 8, 2025
@matthewtrepte matthewtrepte changed the base branch from main to dev/newton November 8, 2025 03:13
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Nov 11, 2025

Greptile Overview

Greptile Summary

This PR introduces a multi-visualizer architecture for Isaac Lab 3.0, enabling support for Newton OpenGL, Omniverse, and Rerun visualizers through a factory pattern with scene data providers. The Newton visualizer implementation is functional, but the Rerun and Omniverse visualizers contain critical bugs.

Key Changes

  • Added abstract Visualizer base class with lifecycle methods (initialize(), step(), close(), is_running())
  • Implemented SceneDataProvider abstraction to decouple physics backends from visualizers
  • Created visualizer factory registry pattern for extensibility
  • Integrated visualizers into SimulationContext with pause/resume controls
  • Updated RL scripts to use new enable_visualizers() utility

Critical Issues Found

  • Rerun visualizer: Syntax error in config (/tmp/test.rrd unquoted), incorrect attribute access (cfg.enable_markers should be self.cfg.enable_markers)
  • Simulation context: Potential infinite loop in training pause handler (line 625-628) with no timeout mechanism
  • OV visualizer: Stub implementation missing full functionality
  • enable_visualizers(): Function doesn't create default Newton visualizer when None configured, contradicting its docstring

Architecture Strengths

  • Clean separation of concerns with abstract base classes
  • Factory pattern enables easy addition of new visualizers
  • Scene data provider abstraction supports multiple physics backends
  • Well-documented lifecycle and pause semantics

Confidence Score: 2/5

  • PR has critical runtime errors in Rerun visualizer and potential simulation hangs
  • The architecture and Newton visualizer are solid (score 4), but multiple syntax errors and logic bugs in Rerun visualizer will cause immediate runtime failures. The infinite loop in simulation context pause handling poses a reliability risk. These issues must be fixed before merging.
  • source/isaaclab/isaaclab/sim/visualizers/rerun_visualizer.py and rerun_visualizer_cfg.py require immediate fixes for syntax errors and attribute references. simulation_context.py needs timeout logic for pause handling.

Important Files Changed

File Analysis

Filename Score Overview
source/isaaclab/isaaclab/sim/visualizers/newton_visualizer.py 3/5 Functional Newton visualizer with custom viewer subclass, but silently suppresses rendering exceptions
source/isaaclab/isaaclab/sim/visualizers/rerun_visualizer.py 1/5 Contains multiple syntax errors and undefined attribute references throughout implementation
source/isaaclab/isaaclab/sim/visualizers/ov_visualizer.py 2/5 Stub implementation missing all required abstract methods from base class
source/isaaclab/isaaclab/sim/simulation_context.py 2/5 Visualizer integration with potential infinite loop in pause handling and inconsistent rendering pause behavior
source/isaaclab/isaaclab/sim/visualizers/rerun_visualizer_cfg.py 1/5 Syntax error in default value - unquoted string literal will cause NameError

Sequence Diagram

sequenceDiagram
    participant Script as RL Script
    participant SimCtx as SimulationContext
    participant Provider as SceneDataProvider
    participant VizCfg as VisualizerCfg
    participant Viz as Visualizer
    participant Newton as NewtonManager

    Script->>SimCtx: __init__(cfg)
    SimCtx->>Provider: create NewtonSceneDataProvider()
    
    Script->>SimCtx: reset()
    SimCtx->>Newton: start_simulation()
    SimCtx->>Newton: initialize_solver()
    SimCtx->>SimCtx: initialize_visualizers()
    
    SimCtx->>VizCfg: for each cfg in visualizers
    VizCfg->>Viz: create_visualizer()
    Note over VizCfg,Viz: Factory pattern via registry
    
    SimCtx->>Provider: get_scene_data()
    Provider-->>SimCtx: {model, state, usd_stage, metadata}
    SimCtx->>Viz: initialize(scene_data)
    Viz->>Viz: validate physics backend
    Viz->>Viz: create viewer (Newton/Rerun/OV)
    
    loop Training Loop
        Script->>SimCtx: step(render=True)
        SimCtx->>Newton: step()
        SimCtx->>SimCtx: step_visualizers(dt)
        
        SimCtx->>Viz: is_running()?
        alt Visualizer closed
            SimCtx->>Viz: close()
            SimCtx->>SimCtx: remove from list
        else Visualizer paused (training)
            loop While paused
                SimCtx->>Viz: step(0.0, provider)
                SimCtx->>Viz: is_training_paused()?
            end
        else Visualizer paused (rendering)
            Note over SimCtx,Viz: Skip step, continue
        else Normal step
            SimCtx->>Provider: get_state()
            Provider->>Newton: get current state
            Provider-->>SimCtx: state
            SimCtx->>Viz: step(dt, provider)
            Viz->>Provider: get_state()
            Viz->>Viz: render frame
        end
    end
    
    Script->>SimCtx: close()
    SimCtx->>SimCtx: close_visualizers()
    SimCtx->>Viz: close()
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

14 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +368 to +369
# Frame lifecycle is now properly handled by try-finally
pass # Silently ignore to avoid log spam - the viewer will recover
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Silently suppressing exceptions can hide bugs

The pass statement after the try/finally block will hide any rendering errors. While the comment explains this is to avoid log spam, completely ignoring exceptions can make debugging difficult and hide serious issues.

Suggested change
# Frame lifecycle is now properly handled by try-finally
pass # Silently ignore to avoid log spam - the viewer will recover
except Exception as e:
# Log at debug level to avoid spam but still track issues
import omni.log
omni.log.debug(f"Rendering error in Newton visualizer: {e}")

Comment on lines 618 to 622
while visualizer.is_training_paused() and visualizer.is_running():
if isinstance(visualizer, NewtonVisualizer):
# Update state before rendering during pause
visualizer.update_state(NewtonManager._state_0)
visualizer.step(0.0) # Step with 0 dt during pause
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Potential infinite loop if visualizer hangs

The while loop blocks indefinitely if the visualizer is paused. If is_running() never returns False and the user never unpauses, this will hang the entire simulation thread. The inner step(0.0) call could also raise exceptions that aren't caught here.

Consider adding a timeout or making this non-blocking to prevent simulation hangs.

Comment on lines +625 to +626
if visualizer.is_rendering_paused():
continue
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Rendering continues when paused

When rendering is paused via is_rendering_paused(), this continue skips the visualization step but the simulation still runs. However, the visualizer's ImGui state still needs to be updated every frame (as noted in the comment on line 347 of newton_visualizer.py). This could cause the UI to become unresponsive.

The Newton visualizer's step() should probably still be called with a flag to update UI but skip rendering.

Comment on lines 569 to 575
else:
# Skip unsupported visualizer types for now
omni.log.warn(
f"Visualizer type '{type(viz_cfg).__name__}' is not yet implemented. Skipping."
)
continue

Copy link
Contributor

Choose a reason for hiding this comment

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

style: Accessing private class variable directly

The code directly accesses NewtonManager._model and NewtonManager._state_0 which are private class variables (indicated by the leading underscore). This creates tight coupling and could break if the NewtonManager implementation changes.

Consider adding public getter methods in NewtonManager like get_model() and get_state() for better encapsulation.

Comment on lines +697 to +700

# Initialize visualizers after simulation is set up (only on first reset)
if not soft and not self._visualizers:
self.initialize_visualizers()
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Check visualizer recreation behavior after cleanup

The condition if not soft and not self._visualizers means visualizers are only initialized if the list is empty. If visualizers were previously created and then closed (making the list empty again), they won't be recreated on the next reset.

Verify this matches the intended behavior for simulation resets.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

29 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile


from __future__ import annotations

from .ov_visualizer_cfg import RerunVisualizerCfg
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: incorrect import - importing RerunVisualizerCfg from ov_visualizer_cfg instead of rerun_visualizer_cfg

Suggested change
from .ov_visualizer_cfg import RerunVisualizerCfg
from .rerun_visualizer_cfg import RerunVisualizerCfg



class RerunVisualizer(Visualizer):
"""Omniverse Visualizer implementation."""
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: docstring copy-pasted from OmniverseVisualizer instead of describing Rerun visualizer

Suggested change
"""Omniverse Visualizer implementation."""
"""Rerun Visualizer implementation."""

#
# SPDX-License-Identifier: BSD-3-Clause

"""Omniverse Visualizer implementation."""
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: module docstring copy-pasted from Omniverse instead of describing Rerun

Suggested change
"""Omniverse Visualizer implementation."""
"""Rerun Visualizer implementation."""

Comment on lines 14 to 18
class OmniverseVisualizer(Visualizer):
"""Omniverse Visualizer implementation."""
def __init__(self, cfg: OVVisualizerCfg):
super().__init__(cfg)
# stub for now No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: stub visualizer missing abstract method implementations - base class requires initialize(), step(), close(), and is_running() to be implemented

Comment on lines 14 to 18
class RerunVisualizer(Visualizer):
"""Omniverse Visualizer implementation."""
def __init__(self, cfg: RerunVisualizerCfg):
super().__init__(cfg)
# stub for now No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: stub visualizer missing abstract method implementations - base class requires initialize(), step(), close(), and is_running() to be implemented

@matthewtrepte matthewtrepte changed the title [wip] Add initial cfgs for visualizers [wip] Add initial design for Visualizers Nov 12, 2025
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

30 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

30 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +631 to +633
while visualizer.is_training_paused() and visualizer.is_running():
# Step with 0 dt during pause, pass scene provider for state updates
visualizer.step(0.0, self._scene_provider)
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: This while loop will block the simulation thread indefinitely if visualizer is paused and never unpauses. If is_running() becomes false during pause, the visualizer is removed but simulation remains blocked. The inner step(0.0) call could also raise exceptions that aren't handled.

Add a timeout or make this non-blocking to prevent simulation hangs.

Comment on lines +431 to +439
def update_state(self, state) -> None:
"""Update the simulation state for visualization.
This method should be called before step() to provide the latest simulation state.
Args:
state: The Newton State object to visualize.
"""
self._state = state
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Unused method - update_state() is never called. The visualizer pulls state from scene_provider in step() (line 365). Consider removing if not needed.

Comment on lines +42 to +44
self.cfg = cfg
self._is_initialized = False
self._is_closed = False
Copy link
Contributor

Choose a reason for hiding this comment

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

style: _is_initialized and _is_closed flags must be manually set by subclasses - error-prone. Consider setting them in base class methods or document this requirement.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

30 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +1033 to +1061
def enable_visualizers(env_cfg, train_mode: bool = True) -> None:
"""Enable visualizers for an environment configuration.
If no visualizers are configured, defaults to Newton OpenGL visualizer.
If visualizers are already configured, enables them.
This is a utility function for use in scripts that want to enable visualization
based on command-line arguments.
Args:
env_cfg: Environment configuration (DirectRLEnvCfg or ManagerBasedRLEnvCfg) to modify.
train_mode: Whether to run visualizers in training mode (True) or play/inference mode (False).
Default is True.
Example:
>>> import isaaclab.sim as sim_utils
>>> if args_cli.visualize:
... sim_utils.enable_visualizers(env_cfg) # For training
... sim_utils.enable_visualizers(env_cfg, train_mode=False) # For play/inference
"""
if env_cfg.sim.visualizers :
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: docstring says function "defaults to Newton OpenGL visualizer" when no visualizers configured, but implementation only enables existing visualizers. if env_cfg.sim.visualizers is None, function does nothing instead of creating default Newton visualizer

Suggested change
def enable_visualizers(env_cfg, train_mode: bool = True) -> None:
"""Enable visualizers for an environment configuration.
If no visualizers are configured, defaults to Newton OpenGL visualizer.
If visualizers are already configured, enables them.
This is a utility function for use in scripts that want to enable visualization
based on command-line arguments.
Args:
env_cfg: Environment configuration (DirectRLEnvCfg or ManagerBasedRLEnvCfg) to modify.
train_mode: Whether to run visualizers in training mode (True) or play/inference mode (False).
Default is True.
Example:
>>> import isaaclab.sim as sim_utils
>>> if args_cli.visualize:
... sim_utils.enable_visualizers(env_cfg) # For training
... sim_utils.enable_visualizers(env_cfg, train_mode=False) # For play/inference
"""
if env_cfg.sim.visualizers :
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
if env_cfg.sim.visualizers:
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
else:
# Default to Newton OpenGL visualizer if none configured
from .visualizers import NewtonVisualizerCfg
env_cfg.sim.visualizers = NewtonVisualizerCfg(enabled=True, train_mode=train_mode)

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

31 files reviewed, 8 comments

Edit Code Review Agent Settings | Greptile

Args:
markers: VisualizationMarkers instance to log each frame.
"""
if self._visualize_markers:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: _visualize_markers attribute undefined - should be _enable_markers

Suggested change
if self._visualize_markers:
if self._enable_markers:

Args:
plots: Dictionary mapping plot names to LivePlot instances.
"""
if self._visualize_plots:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: _visualize_plots attribute undefined - should be _enable_live_plots

Suggested change
if self._visualize_plots:
if self._enable_live_plots:

- Optimize batch logging for large marker counts
- Add color/material support for better visual distinction
"""
if not self._visualize_markers or len(self._registered_markers) == 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: _visualize_markers attribute undefined - should be _enable_markers

Suggested change
if not self._visualize_markers or len(self._registered_markers) == 0:
if not self._enable_markers or len(self._registered_markers) == 0:

- Maintain proper timeline synchronization
- Support different plot types (line, bar, etc.)
"""
if not self._visualize_plots or len(self._registered_plots) == 0:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: _visualize_plots attribute undefined - should be _enable_live_plots

Suggested change
if not self._visualize_plots or len(self._registered_plots) == 0:
if not self._enable_live_plots or len(self._registered_plots) == 0:

keep_scalar_history: bool = True
"""Keep scalar/plot history in timeline."""

record_to_rrd: str | None = test.rrd
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: syntax error - test.rrd is not quoted and will cause NameError

Suggested change
record_to_rrd: str | None = test.rrd
record_to_rrd: str | None = None

self._viewer.log_state(self._state)

# Actively log markers (if enabled)
if self.cfg.visualize_markers:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: cfg.visualize_markers attribute doesn't exist in RerunVisualizerCfg - should use cfg.enable_markers

Suggested change
if self.cfg.visualize_markers:
if self.cfg.enable_markers:

self._viewer.log_markers()

# Actively log plot data (if enabled)
if self.cfg.visualize_plots:
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: cfg.visualize_plots attribute doesn't exist in RerunVisualizerCfg - should use cfg.enable_live_plots

Suggested change
if self.cfg.visualize_plots:
if self.cfg.enable_live_plots:

Comment on lines +86 to +100
physics_backend = self._metadata.get("physics_backend", "unknown")
metadata_text += f"**Physics Backend:** {physics_backend}\n"

# Environment info
num_envs = self._metadata.get("num_envs", 0)
metadata_text += f"**Total Environments:** {num_envs}\n"

if self._env_indices is not None:
metadata_text += f"**Visualized Environments:** {len(self._env_indices)} (indices: {self._env_indices[:5]}...)\n"
else:
metadata_text += f"**Visualized Environments:** All ({num_envs})\n"

# Physics backend info
physics_backend = self._metadata.get("physics_backend", "unknown")
metadata_text += f"**Physics:** {physics_backend}\n"
Copy link
Contributor

Choose a reason for hiding this comment

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

style: duplicate physics_backend logging - already logged on line 87 as "Physics Backend", then again on line 100 as "Physics"

Suggested change
physics_backend = self._metadata.get("physics_backend", "unknown")
metadata_text += f"**Physics Backend:** {physics_backend}\n"
# Environment info
num_envs = self._metadata.get("num_envs", 0)
metadata_text += f"**Total Environments:** {num_envs}\n"
if self._env_indices is not None:
metadata_text += f"**Visualized Environments:** {len(self._env_indices)} (indices: {self._env_indices[:5]}...)\n"
else:
metadata_text += f"**Visualized Environments:** All ({num_envs})\n"
# Physics backend info
physics_backend = self._metadata.get("physics_backend", "unknown")
metadata_text += f"**Physics:** {physics_backend}\n"
# Physics info
physics_backend = self._metadata.get("physics_backend", "unknown")
metadata_text += f"**Physics Backend:** {physics_backend}\n"
# Environment info
num_envs = self._metadata.get("num_envs", 0)
metadata_text += f"**Total Environments:** {num_envs}\n"
if self._env_indices is not None:
metadata_text += f"**Visualized Environments:** {len(self._env_indices)} (indices: {self._env_indices[:5]}...)\n"
else:
metadata_text += f"**Visualized Environments:** All ({num_envs})\n"

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

31 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +1053 to +1061
if env_cfg.sim.visualizers :
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: function doesn't create default visualizer when env_cfg.sim.visualizers is None, contradicting docstring on line 1036 which says "defaults to Newton OpenGL visualizer"

the implementation only enables existing visualizers but never creates a default one

Suggested change
if env_cfg.sim.visualizers :
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
if env_cfg.sim.visualizers:
# Enable configured visualizer(s)
if isinstance(env_cfg.sim.visualizers, list):
for viz_cfg in env_cfg.sim.visualizers:
viz_cfg.enabled = True
viz_cfg.train_mode = train_mode
else:
env_cfg.sim.visualizers.enabled = True
env_cfg.sim.visualizers.train_mode = train_mode
else:
# Default to Newton OpenGL visualizer if none configured
from .visualizers import NewtonVisualizerCfg
env_cfg.sim.visualizers = NewtonVisualizerCfg(enabled=True, train_mode=train_mode)

keep_scalar_history: bool = True
"""Keep scalar/plot history in timeline."""

record_to_rrd: str | None = "/tmp/test.rrd"
Copy link
Contributor

Choose a reason for hiding this comment

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

syntax: unquoted string causes NameError at runtime - /tmp/test.rrd is not a valid Python identifier

Suggested change
record_to_rrd: str | None = "/tmp/test.rrd"
record_to_rrd: str | None = "/tmp/test.rrd"

Comment on lines +395 to +396
if self.cfg.enable_markers:
self._viewer.log_markers()
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: cfg.enable_markers doesn't exist in RerunVisualizerCfg - should use self.cfg.enable_markers which is correctly defined

Suggested change
if self.cfg.enable_markers:
self._viewer.log_markers()
# Actively log markers (if enabled)
if self.cfg.enable_markers:
self._viewer.log_markers()

Comment on lines +398 to +400
# Actively log plot data (if enabled)
if self.cfg.enable_live_plots:
self._viewer.log_plot_data()
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: cfg.enable_live_plots doesn't exist - should use self.cfg.enable_live_plots

Suggested change
# Actively log plot data (if enabled)
if self.cfg.enable_live_plots:
self._viewer.log_plot_data()
# Actively log plot data (if enabled)
if self.cfg.enable_live_plots:
self._viewer.log_plot_data()

Comment on lines +625 to +628
# Handle training pause - block until resumed
while visualizer.is_training_paused() and visualizer.is_running():
# Step with 0 dt during pause, pass scene provider for state updates
visualizer.step(0.0, self._scene_provider)
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: infinite loop blocks simulation if visualizer never unpauses - no timeout or escape mechanism

if is_running() returns False during the loop, the visualizer is removed but the loop continues blocking the simulation thread

Suggested change
# Handle training pause - block until resumed
while visualizer.is_training_paused() and visualizer.is_running():
# Step with 0 dt during pause, pass scene provider for state updates
visualizer.step(0.0, self._scene_provider)
# Handle training pause with timeout
pause_start_time = time.time()
max_pause_duration = 300 # 5 minutes timeout
while visualizer.is_training_paused() and visualizer.is_running():
if time.time() - pause_start_time > max_pause_duration:
omni.log.warn(f"Visualizer pause timeout after {max_pause_duration}s, resuming simulation")
break
# Step with 0 dt during pause, pass scene provider for state updates
visualizer.step(0.0, self._scene_provider)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asset New asset feature or request documentation Improvements or additions to documentation infrastructure isaac-mimic Related to Isaac Mimic team isaac-sim Related to Isaac Sim team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant