Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Dockerfile.g1-sim
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Headless DimOS Unitree G1 simulation smoke image.
FROM python:3.12-slim

ENV UV_SYSTEM_PYTHON=1 \
PYTHONUNBUFFERED=1 \
DIMOS_INSTALL=0 \
DIMOS_USE_SYSTEM=1 \
UV_VERSION=0.8.15 \
RUN_SECONDS=20 \
BLUEPRINT=unitree-g1-sim

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
curl \
git \
libegl1 \
libgl1 \
libglib2.0-0 \
libgomp1 \
libsm6 \
libx11-6 \
libxext6 \
libxrender1 \
pkg-config \
portaudio19-dev \
&& rm -rf /var/lib/apt/lists/* \
&& curl -LsSf https://astral.sh/uv/${UV_VERSION}/install.sh | sh
ENV PATH="/root/.local/bin:${PATH}"

WORKDIR /app
COPY pyproject.toml setup.py README.md LICENSE MANIFEST.in ./
COPY dimos ./dimos
COPY scripts/g1_sim_smoke.sh ./scripts/g1_sim_smoke.sh

RUN uv pip install '.[unitree,sim]'

CMD ["bash", "scripts/g1_sim_smoke.sh"]
26 changes: 26 additions & 0 deletions cloudbuild.g1-sim.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
substitutions:
_IMAGE: dimos-g1-sim
_TAG: smoke

steps:
- name: gcr.io/cloud-builders/docker
args:
- build
- -f
- Dockerfile.g1-sim
- -t
- ${_IMAGE}:${_TAG}
- .
- name: gcr.io/cloud-builders/docker
args:
- run
- --rm
- -e
- RUN_SECONDS=10
- -e
- BLUEPRINT=unitree-g1-sim
- ${_IMAGE}:${_TAG}

timeout: 1800s
options:
logging: CLOUD_LOGGING_ONLY
63 changes: 63 additions & 0 deletions docs/platforms/humanoid/g1/sprint-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Unitree G1 simulation sprint plan

This plan is for running DimOS/DimensionalOS G1 without physical hardware, then making it easy to move the same blueprint shape onto a real G1 later.

## Sprint 0 — discovery / runnable baseline

Goal: prove the repo, CLI, and G1 simulation entrypoints are discoverable without hardware.

- Use Python 3.12 and install `dimos[unitree,sim]` for simulation.
- Confirm the CLI exposes `unitree-g1-sim`, `unitree-g1-basic-sim`, `unitree-g1-agentic-sim`, and `unitree-g1-nav-sim`.
- Prefer `--viewer none` for headless CI/smoke checks; use Rerun/native viewer for local interactive runs.
- Default smoke command:

```bash
uv venv --python 3.12
source .venv/bin/activate
uv pip install 'dimos[unitree,sim]'
dimos --simulation --viewer none run unitree-g1-sim
```

## Sprint 1 — local sim loop

Goal: make the basic humanoid simulation usable for local development.

- Run `unitree-g1-sim` first; it is the smallest perceptive G1 simulation blueprint.
- If visualizing, use `dimos --simulation --viewer rerun run unitree-g1-sim`.
- Keep `dimos status`, `dimos log`, and `dimos stop` as the standard lifecycle commands for daemon runs.
- If Rerun or the viewer crashes, reduce visual load before changing robot logic.

## Sprint 2 — navigation / command-center loop

Goal: validate the navigation stack against the simulated G1.

- Run the native navigation sim blueprint:

```bash
dimos --simulation --viewer rerun run unitree-g1-nav-sim
```

- `unitree-g1-nav-sim` connects `UnityBridgeModule`, native nav stack, `MovementManager`, and visualization.
- The blueprint rate-limits heavy visualization (`vis_throttle=0.1`) because G1 visualization can overwhelm Rerun.
- Use this sprint for path-planning, waypoints, local planner tuning, and command-center/Rerun checks.

## Sprint 3 — agentic / cloud-ready harness

Goal: package a repeatable G1 sim run for agent/MCP work and optional GCP execution.

- Agentic local command:

```bash
Comment on lines +49 to +50
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.

dimos --simulation --viewer rerun run unitree-g1-agentic-sim --daemon
dimos status
dimos mcp list-tools
dimos log -n 100
```

- For GCP, use the requested project alias/ID explicitly on every command, e.g. `gcloud ... --project YOUR_PROJECT_ID`. If a short name is only a local alias, resolve it before submitting builds.
- A practical cloud target is a Docker image that runs the same smoke command headlessly (`--viewer none`) for CI; interactive graphics/GPU should stay local or on a GPU VM with display forwarding.
- Do not require real robot networking (`ROBOT_IP`, DDS/WebRTC, sport mode) for simulation sprints.

## Real-G1 boundary

Simulation sprints do **not** perform real G1 actions. Real hardware requires the G1 doc flow: SSH/network setup, sport mode safety positioning, robot-side DimOS install, and explicit human supervision.
77 changes: 77 additions & 0 deletions scripts/g1_sim_smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail

# Headless smoke for DimOS Unitree G1 simulation entrypoints.
# Use RUN_SECONDS to limit runtime; set DIMOS_INSTALL=1 to install deps into .venv.
# Set DIMOS_USE_SYSTEM=1 inside containers where dependencies are already installed
# into the system Python.

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

: "${PYTHON_VERSION:=3.12}"
: "${RUN_SECONDS:=20}"
: "${BLUEPRINT:=unitree-g1-sim}"
: "${DIMOS_INSTALL:=0}"
: "${DIMOS_USE_SYSTEM:=0}"

if [[ "$DIMOS_USE_SYSTEM" != "1" ]]; then
if [[ ! -d .venv ]]; then
uv venv --python "$PYTHON_VERSION"
fi
# shellcheck disable=SC1091
source .venv/bin/activate

if [[ "$DIMOS_INSTALL" == "1" ]]; then
uv pip install '.[unitree,sim]'
fi
elif [[ "$DIMOS_INSTALL" == "1" ]]; then
uv pip install --system '.[unitree,sim]'
fi

python - <<'PY'
from dimos.robot.all_blueprints import all_blueprints
required = {
"unitree-g1-sim",
"unitree-g1-basic-sim",
"unitree-g1-agentic-sim",
"unitree-g1-nav-sim",
}
missing = sorted(required - set(all_blueprints))
if missing:
raise SystemExit(f"Missing G1 simulation blueprints: {missing}")
print("G1 simulation blueprints OK:", ", ".join(sorted(required)))
PY

run_limited() {
if command -v timeout >/dev/null 2>&1; then
timeout "$RUN_SECONDS" "$@"
return $?
fi
if command -v gtimeout >/dev/null 2>&1; then
gtimeout "$RUN_SECONDS" "$@"
return $?
fi
python - "$RUN_SECONDS" "$@" <<'PY'
import subprocess
import sys

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.

except subprocess.TimeoutExpired:
raise SystemExit(124)
PY
}

set +e
run_limited dimos --simulation --viewer none run "$BLUEPRINT"
status=$?
set -e

if [[ "$status" == "124" ]]; then
echo "G1 simulation smoke reached RUN_SECONDS=${RUN_SECONDS}; treating bounded run as pass."
exit 0
fi
exit "$status"