Skip to content

Add Unitree G1 simulation smoke harness#2045

Open
roedefense1 wants to merge 2 commits into
dimensionalOS:mainfrom
roedefense1:g1-sim-smoke-harness
Open

Add Unitree G1 simulation smoke harness#2045
roedefense1 wants to merge 2 commits into
dimensionalOS:mainfrom
roedefense1:g1-sim-smoke-harness

Conversation

@roedefense1
Copy link
Copy Markdown

Adds a Docker/Cloud Build headless smoke harness for Unitree G1 simulation entrypoints.\n\nValidation:\n- bash -n scripts/g1_sim_smoke.sh\n- Cloud Build smoke submitted in titomic-458215 as c9f666f3-f3be-45cb-b3ca-8ce6f7329e96 (in progress at PR creation)\n\nNotes:\n- This validates simulation wiring only; it does not claim hardware validation.

@roedefense1
Copy link
Copy Markdown
Author

Cloud smoke passed.\n\nValidation:\n- bash -n scripts/g1_sim_smoke.sh\n- Cloud Build c9f666f3-f3be-45cb-b3ca-8ce6f7329e96 in titomic-458215: SUCCESS\n- Log confirms G1 sim blueprints registered and bounded headless run started DimOS, then timed out at RUN_SECONDS=10 as expected.\n\nStill simulation-only; no hardware validation claimed.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR adds a headless Docker/Cloud Build smoke harness for Unitree G1 simulation entrypoints: a Dockerfile that builds a pinned Python 3.12 + uv environment, a Cloud Build config that builds and immediately runs the image, and a shell script that validates blueprint registration and then drives dimos with a bounded timeout.

  • scripts/g1_sim_smoke.sh — validates all four G1 simulation blueprints are importable, then calls dimos --simulation --viewer none run $BLUEPRINT through a timeout-chain fallback (timeoutgtimeout → Python subprocess). Exit code 124 (bounded run) is treated as a pass.
  • Dockerfile.g1-simpython:3.12-slim base with OpenGL/audio/EGL deps; uv version is pinned via UV_VERSION=0.8.15 env var expanded in the curl command; UV_SYSTEM_PYTHON=1 drives system-level install.
  • cloudbuild.g1-sim.yaml — standard two-step build-then-run with RUN_SECONDS=10 override; no registry push since this is smoke-only.

Confidence Score: 5/5

Safe to merge; all four changed files are new additions with no impact on existing code paths.

The harness is self-contained (new files only) and the core timeout-handling logic, uv pinning, and Docker layering are all correct. The only gap found is a minor portability edge case in the Python fallback.

No files require special attention.

Important Files Changed

Filename Overview
scripts/g1_sim_smoke.sh New 77-line headless smoke harness; logic is sound with good timeout fallback chain (timeout → gtimeout → Python). The Python fallback relies on the bare python command which may be absent on some local macOS setups (both timeout utilities unavailable, venv not active).
Dockerfile.g1-sim Clean Debian slim image; uv version is correctly pinned via UV_VERSION env var and expanded in the curl command. ENV PATH is set in a separate layer after install, which is correct for Docker RUN ordering.
cloudbuild.g1-sim.yaml Standard two-step Cloud Build config (build then run); no registry push since this is a smoke-only harness. BLUEPRINT env var in the run step is redundant with the Dockerfile default but harmless.
docs/platforms/humanoid/g1/sprint-plan.md New sprint planning doc for G1 simulation and hardware onboarding; clearly scopes the simulation-only boundary and defers hardware steps.

Sequence Diagram

sequenceDiagram
    participant CB as Cloud Build
    participant D as Docker
    participant S as g1_sim_smoke.sh
    participant P as Python (blueprint check)
    participant DI as dimos CLI

    CB->>D: docker build -f Dockerfile.g1-sim
    Note over D: apt-get deps + uv install<br/>uv pip install .[unitree,sim]
    D-->>CB: image dimos-g1-sim:smoke

    CB->>D: "docker run --rm -e RUN_SECONDS=10 dimos-g1-sim:smoke"
    D->>S: bash scripts/g1_sim_smoke.sh
    S->>P: python - (heredoc blueprint check)
    P-->>S: OK / SystemExit if missing blueprints

    S->>S: run_limited() — try timeout, gtimeout, python fallback
    S->>DI: dimos --simulation --viewer none run unitree-g1-sim
    Note over DI: runs until RUN_SECONDS elapses<br/>or exits with error

    alt "exit code == 124 (timeout = bounded pass)"
        DI-->>S: 124
        S-->>CB: exit 0
    else "exit code == 0"
        DI-->>S: 0
        S-->>CB: exit 0
    else non-zero (real failure)
        DI-->>S: non-zero
        S-->>CB: exit $status (build fails)
    end
Loading

Reviews (2): Last reviewed commit: "Address G1 smoke review nits" | Re-trigger Greptile

Comment thread Dockerfile.g1-sim Outdated
pkg-config \
portaudio19-dev \
&& rm -rf /var/lib/apt/lists/* \
&& curl -LsSf https://astral.sh/uv/install.sh | sh
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 uv installer is fetched and executed in the same RUN layer without pinning a version. Any two builds that happen at different times may get different uv versions, making the image non-reproducible. Astral ships versioned releases; pinning to a specific version is straightforward and also documents the intended toolchain version.

Suggested change
&& curl -LsSf https://astral.sh/uv/install.sh | sh
&& curl -LsSf https://astral.sh/uv/install.sh | UV_VERSION=0.6.16 sh

Comment on lines +49 to +50

```bash
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 security GCP project ID leaked into version-controlled docs — openclaw-1773763209 appears to be a real, resolved project identifier. If this repository is public (or later made public), the project ID helps enumerate GCP resources and IAM policies. Consider replacing the resolved ID with a placeholder like <YOUR_GCP_PROJECT_ID> or removing the "currently resolves to" note entirely.

Comment thread scripts/g1_sim_smoke.sh
seconds = float(sys.argv[1])
cmd = sys.argv[2:]
try:
raise SystemExit(subprocess.run(cmd, timeout=seconds).returncode)
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 outer try/except only catches subprocess.TimeoutExpired; any other exception raised by subprocess.run (e.g., FileNotFoundError if dimos is not on PATH) will propagate as an uncaught exception with a Python traceback instead of a clean non-zero exit, making it harder to diagnose in CI logs.

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