Skip to content

Fix/rheo dockerfile - #231

Open
hermixbr wants to merge 6 commits into
isaac-for-healthcare:mainfrom
hermixbr:fix/rheo-dockerfile
Open

Fix/rheo dockerfile#231
hermixbr wants to merge 6 commits into
isaac-for-healthcare:mainfrom
hermixbr:fix/rheo-dockerfile

Conversation

@hermixbr

Copy link
Copy Markdown

Fixes #ISSUE_NUMBER

Description

@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR overhauls the Rheo Docker build pipeline for RTX 50-series (Blackwell) GPU stability and fixes several runtime issues: it replaces the monolithic isaaclab.sh -i install with staged, version-pinned pip calls; strips the PyPI warp-lang that shadows the Kit-bundled Warp; defaults the container to HEADLESS=1; and adds blackwell_render.py to inject conservative Kit flags and render settings before SimulationApp starts.

  • Dockerfile.x86: Staged IsaacLab pip installs with explicit version pins; warp-lang scrub after all pip steps; pkg-config/libfreetype6/libpng added for matplotlib build.
  • blackwell_render.py + task files: New utility injects Blackwell-safe Kit args into sys.argv and replaces hard-coded quality render settings (DLAA, translucency, ray-tracing) in all four task configs with performance-mode overrides, enabled by default for all hardware with an opt-out env-var.
  • register_and_patch.py: Adds a builtins.open monkey-patch to auto-create missing Lightwheel SDK cache subdirectories; adds _skip_eager_arena_registry to prevent premature IsaacLab imports during asset registration.
  • run_docker.sh: Adds bash re-exec guard, pre-creates Lightwheel cache dirs on the host, and handles Blackwell-aware DISPLAY unsetting with graceful xhost fallback.

Confidence Score: 3/5

The builtins.open monkey-patch in register_and_patch.py will crash with TypeError for any open(bytes_path) call after it is installed — a global side-effect that could surface in any third-party library used at runtime.

The _patch_lightwheel_cache_writes function replaces builtins.open process-wide but does not handle bytes file arguments: os.fspath(b'/path') returns bytes, and the subsequent str_marker in bytes_path raises TypeError. This breaks all code that legitimately passes a bytes path to open() after the patch is active, including any C-extension or third-party package that does so.

workflows/rheo/scripts/simulation/register_and_patch.py (bytes-path branch of the builtins.open patch) and workflows/rheo/scripts/utils/blackwell_render.py (_merge_kit_arg_values substring conflict).

Important Files Changed

Filename Overview
workflows/rheo/docker/Dockerfile.x86 Major overhaul of the IsaacLab install pipeline — staged pip installs with explicit version pins, warp-lang stripping, and Blackwell HEADLESS default. GR00T block still overwrites several base-pinned packages (pre-existing, flagged in prior review).
workflows/rheo/scripts/simulation/register_and_patch.py Adds _patch_lightwheel_cache_writes() which monkey-patches builtins.open globally — the bytes-path branch will raise TypeError for any open(b'path') call after the patch is applied.
workflows/rheo/scripts/utils/blackwell_render.py New utility providing Kit flags and render-cfg overrides for RTX 50-series Blackwell GPUs. Enabled by default for all users; _merge_kit_arg_values uses substring matching that can produce duplicate conflicting flags.
workflows/rheo/docker/run_docker.sh Added bash re-exec guard, Lightwheel SDK cache dir pre-creation, and Blackwell-aware DISPLAY/HEADLESS handling with graceful xhost fallback.
workflows/rheo/scripts/simulation/tasks/g1_observe_object_task.py Replaces explicit quality render settings (DLAA, translucency, fractionalCutoutOpacity) with apply_blackwell_safe_render_cfg, which applies performance-mode rendering to all hardware by default.
workflows/rheo/scripts/simulation/examples/utils.py Adds multi-camera video recording helpers (create_video_writer_if_requested, maybe_record_video_frame, record_available_cameras) for observe/policy runners.
workflows/rheo/scripts/simulation/examples/video_runner_cli.py New file adding --save_video, --video_dir, --video_fps, and --video_env_id CLI arguments for MP4 recording.
workflows/rheo/scripts/simulation/rl/rlinf_ext/init.py Updated AppLauncher call to conditionally pass Blackwell-safe kit_args, with correct fallback when the patch is disabled.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Host as Host (run_docker.sh)
    participant Docker as Docker Container
    participant Kit as Isaac Sim Kit Python
    participant Reg as register_and_patch.py
    participant App as SimulationApp

    Host->>Host: "mkdir -p ~/.cache/lightwheel_sdk/object/*"
    Host->>Host: "Blackwell: unset DISPLAY (HEADLESS=1)"
    Host->>Docker: docker run (mounts host cache)

    Note over Docker: ENV HEADLESS=1, PYTHONPATH includes workflows/rheo

    Docker->>Reg: import register_and_patch → register_workflow_cli()
    Reg->>Kit: ensure_blackwell_safe_kit_args() injects --kit_args into sys.argv

    Docker->>App: SimulationAppContext(args_cli) starts Kit
    App-->>Docker: Kit initialized with Blackwell flags

    Docker->>Reg: register_workflow_assets()
    Reg->>Reg: _skip_eager_arena_registry() patches AssetRegistry temporarily
    Reg->>Reg: _patch_lightwheel_cache_writes() patches builtins.open
    Reg->>Reg: import asset modules (no eager Arena registry load)

    Docker->>App: "gym.make(env_name, cfg=env_cfg)"
    App->>App: apply_blackwell_safe_render_cfg(sim.render)
    Note over App: performance mode, translucency off, shadows off

    Docker->>App: env.step() loop + optional video recording
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant Host as Host (run_docker.sh)
    participant Docker as Docker Container
    participant Kit as Isaac Sim Kit Python
    participant Reg as register_and_patch.py
    participant App as SimulationApp

    Host->>Host: "mkdir -p ~/.cache/lightwheel_sdk/object/*"
    Host->>Host: "Blackwell: unset DISPLAY (HEADLESS=1)"
    Host->>Docker: docker run (mounts host cache)

    Note over Docker: ENV HEADLESS=1, PYTHONPATH includes workflows/rheo

    Docker->>Reg: import register_and_patch → register_workflow_cli()
    Reg->>Kit: ensure_blackwell_safe_kit_args() injects --kit_args into sys.argv

    Docker->>App: SimulationAppContext(args_cli) starts Kit
    App-->>Docker: Kit initialized with Blackwell flags

    Docker->>Reg: register_workflow_assets()
    Reg->>Reg: _skip_eager_arena_registry() patches AssetRegistry temporarily
    Reg->>Reg: _patch_lightwheel_cache_writes() patches builtins.open
    Reg->>Reg: import asset modules (no eager Arena registry load)

    Docker->>App: "gym.make(env_name, cfg=env_cfg)"
    App->>App: apply_blackwell_safe_render_cfg(sim.render)
    Note over App: performance mode, translucency off, shadows off

    Docker->>App: env.step() loop + optional video recording
Loading

Reviews (4): Last reviewed commit: "Dockerfile" | Re-trigger Greptile

hidapi==0.14.0.post2 \
starlette==0.49.1 \
"pyglet<2"
RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary "onnx>=1.18.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 onnx version overwritten by GR00T block

This PR newly installs onnx>=1.18.0 here, but when INSTALL_GROOT=true the GR00T block later runs pip install ... onnx==1.17.0 (line 219), which downgrades it. Any code that depends on onnx 1.18+ APIs (or the onnxruntime install assuming onnx 1.18+) would fail at runtime with that build configuration.

Comment on lines +89 to +95
RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary \
prettytable==3.3.0 \
gymnasium==1.2.1 \
pillow==11.3.0 \
hidapi==0.14.0.post2 \
starlette==0.49.1 \
"pyglet<2"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 gymnasium pinned to 1.2.1 here, overwritten to 1.0.0 by GR00T block

This PR explicitly pins gymnasium==1.2.1, but when INSTALL_GROOT=true the GR00T stage installs gymnasium==1.0.0 (line 208), which pip will downgrade to. Gymnasium 1.0.0 has API differences from 1.2.x; if any IsaacLab extension depends on 1.2-era APIs, it would fail silently with a wrong-version import at runtime. matplotlib is similarly pinned to 3.10.3 here and then overwritten to 3.10.0 in the GR00T block.

Comment thread workflows/rheo/docker/Dockerfile.x86 Outdated
starlette==0.49.1 \
"pyglet<2"
RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary "onnx>=1.18.0"
RUN ${ISAACLAB_PATH}/isaaclab.sh -p -m pip install --no-build-isolation --prefer-binary warp-lang

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 warp-lang has no version pin

Every other package in the surrounding block is version-pinned, but warp-lang floats. A breaking release from NVIDIA (Warp has had API changes across minor versions) would silently produce a different image with no indication in the Dockerfile. Consider pinning to the specific version you validated against.

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!

Comment on lines +111 to +112
"protobuf>=4.25.8,!=5.26.0" \
"packaging<24"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 protobuf base requirement overwritten by GR00T block

This PR newly adds "protobuf>=4.25.8,!=5.26.0" to the base section (protobuf 4.x is required by isaaclab/tensorboard). When INSTALL_GROOT=true, the GR00T block later runs pip install ... protobuf==3.20.3 (line 229), which downgrades to a 3.x release that does not satisfy >=4.25.8. Any isaaclab component that relies on protobuf 4.x binary APIs will fail at runtime in GR00T builds. This follows the same pattern as the onnx/gymnasium version conflicts noted in previous review threads.

Diego Vieira (SiDi) added 2 commits June 25, 2026 10:20
Mitigate RTX 50-series crashes via Kit args, conservative render presets,
and headless DISPLAY handling; add --save_video to observe/policy runners.
Comment on lines +62 to +66
def _open_with_lightwheel_cache_dirs(file, *args, **kwargs):
if isinstance(file, (str, bytes, os.PathLike)):
path = os.fspath(file)
marker = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}"
if marker in path:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0 open(bytes_path) raises TypeError after this patch is applied

os.fspath(file) returns bytes when file is a bytes object, but marker is always a str. The expression marker in path raises TypeError: a bytes-like object is required, not 'str' in Python 3 when path is bytes. Because this replaces builtins.open globally, any third-party library that legitimately calls open(b"/some/path") after this patch is installed will crash with an unhandled TypeError instead of opening the file.

Suggested change
def _open_with_lightwheel_cache_dirs(file, *args, **kwargs):
if isinstance(file, (str, bytes, os.PathLike)):
path = os.fspath(file)
marker = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}"
if marker in path:
def _open_with_lightwheel_cache_dirs(file, *args, **kwargs):
if isinstance(file, (str, bytes, os.PathLike)):
path = os.fspath(file)
marker_str = f"{os.sep}.cache{os.sep}lightwheel_sdk{os.sep}object{os.sep}"
marker = marker_str.encode() if isinstance(path, bytes) else marker_str
if marker in path:

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant