[Fix] Allow Warp environments to launch with the Kit visualizer (cherry-pick of #6111)#6139
Conversation
The experimental Warp environments read the parent settings node
"/isaaclab/visualizer", which carb returns as a dictionary of the
visualizer settings subtree, then called .split(",") on it. Requesting a
Kit visualizer (e.g. --visualizer kit) therefore crashed at construction
with: AttributeError: 'dict' object has no attribute 'split'.
Resolve the active visualizer through SimulationContext.has_active_visualizers()
and the is_rendering property, matching the stable (non-Warp) environments,
which read the "/isaaclab/visualizer/types" string and guard against
non-string values. Also drop the equivalent always-true bool() reads of the
same parent node in the manager-based and direct Warp step loops and window
setup.
Inline self.sim.has_active_visualizers() into the viewport-controller guard since the local was used only once. Correct the in-loop is_rendering comment: the property does live settings lookups and is hoisted out of the decimation loop, it is not cached.
Greptile SummaryFixes a crash (
Confidence Score: 5/5Safe to merge — all three changes are targeted, well-scoped, and directly mirror the stable environment implementations that are already in production. Each changed line replaces a broken settings lookup with a method that the stable environments have used without incident. The viewport-controller guard now correctly reads No files require special attention; both env files are straightforward one-to-one replacements of broken patterns with their proven stable counterparts. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Environment __init__] --> B{Viewport Camera Controller}
B -->|old Warp code| C["get_setting('/isaaclab/visualizer')\n→ returns dict\n→ .split() → AttributeError"]
B -->|new Warp code| D{"(has_gui OR has_active_visualizers())\nAND has_kit()"}
D -->|True| E[ViewportCameraController created]
D -->|False| F[viewport_camera_controller = None]
A --> G[step loop]
G -->|old Warp code| H["is_rendering = bool(settings.get('/isaaclab/visualizer')) OR rtx_sensors"]
G -->|new Warp code| I["is_rendering = self.sim.is_rendering\n(GUI | offscreen | rtx_sensors | visualizers | XR)"]
I --> J[decimation loop]
H --> J
J --> K{"sim_step % render_interval == 0 AND is_rendering"}
K -->|Yes| L[sim.render]
K -->|No| M[skip render]
Reviews (1): Last reviewed commit: "Address review: inline single-use visual..." | Re-trigger Greptile |
There was a problem hiding this comment.
Review Summary
This PR correctly fixes the AttributeError crash when launching Warp environments with Kit visualizer by replacing the broken string-parsing of the /isaaclab/visualizer settings node (which is actually a dict) with the same well-tested API surface used by the stable environments.
Verdict: Clean, minimal fix that brings the experimental Warp environments into alignment with the stable (ManagerBasedRLEnv, DirectRLEnv) code paths. The changes are consistent and well-scoped.
✅ What works well
- Consistent pattern adoption — All three replacements (
has_gui,is_rendering,has_active_visualizers() + has_kit()) mirror the stable environment implementations exactly. is_renderingsubsumes both old checks — The property internally covers GUI, offscreen render, RTX sensors, active visualizers, and XR, so the old_has_rtxguard and the/isaaclab/visualizerstring check are both properly replaced with a single, well-maintained property.- Good changelog fragment — Clear description referencing the relevant classes and the error message.
has_kit()guard — PreventsViewportCameraControllerfrom being instantiated in kitless Newton-only runs, which would fail at import time.
💬 Minor observations (non-blocking)
| File | Observation |
|---|---|
manager_based_env_warp.py:165 |
The stable manager_based_env.py (line 187) extracts has_visualizers = self.sim.has_active_visualizers() into a local before the condition. This PR inlines the call directly. Both are fine — just noting the stylistic divergence from the pattern this PR aims to match. |
direct_rl_env_warp.py:420 |
Comment says "is_rendering does live settings lookups" — accurate since resolve_visualizer_types() and the RTX setting are fetched live. Worth confirming this matches the stable env's comment which says "uses cached property" (stable env line 537). The behavior is identical (hoisted out of the decimation loop), but the comments now diverge on whether the property is "cached" or "live". Consider aligning the wording with the stable counterpart for consistency. |
direct_rl_env_warp.py |
The stable direct_rl_env.py also guards ViewportCameraController creation with has_active_visualizers() + has_kit() (line 169). The Warp variant does not appear to have a viewport_camera_controller at all — likely intentional for the experimental path, but worth confirming the camera controller isn't needed here. |
🧪 Testing
No new tests were added, which is acceptable for a cherry-pick of an already-reviewed fix (#6111). The changelog fragment is present. CI checks (pre-commit, build wheel, changelog fragments) are passing; installation tests are still pending.
Overall: This is a straightforward, correct fix. The observations above are stylistic / informational only — no blocking issues found. 👍
Summary
Cherry-pick of #6111 onto
release/3.0.0-beta2.Fixes a crash when launching the experimental Warp environments with a Kit visualizer (
--visualizer kit):AttributeError: 'dict' object has no attribute 'split'at environment construction. Reported by QA across ~10 manager-based Warp tasks (velocity/reach, e.g.Isaac-Velocity-Flat-Unitree-Go2-Warp-Play-v0).Root cause
The Warp environments read the parent settings node
/isaaclab/visualizer, which carb returns as a dict of the{types, explicit, disable_all, max_visible_envs}subtree thatAppLauncherwrites — then call.split(",")on it. The stable environments never do this: they read/isaaclab/visualizer/typesviaSimulationContext.has_active_visualizers()and theis_renderingproperty, which also guard against non-string values.Fix
Align the Warp environments with the stable ones:
manager_based_env_warp.py: viewport setup →has_active_visualizers()+has_kit(); in-loopis_rendering→self.sim.is_rendering.direct_rl_env_warp.py: UI-window gate →self.sim.has_gui; in-loopis_rendering→self.sim.is_rendering.See #6111 for full discussion and validation.