style: format visual evidence files #165
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy Visual Report to GitHub Pages | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: pages | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| - name: Install system dependencies (OSMesa for headless rendering) | |
| run: sudo apt-get update && sudo apt-get install -y libosmesa6-dev | |
| - name: Install package with demo + WBC dependencies | |
| run: uv pip install --system -e ".[demo,wbc]" | |
| - name: Install unitree SDK, CPU PyTorch, and lerobot | |
| run: | | |
| # unitree-sdk2py is installed directly from the fork (not a pyproject | |
| # extra — PyPI rejects packages with git-based direct references). | |
| uv pip install --system "unitree-sdk2py @ git+https://github.com/MiaoDX-fork-and-pruning/unitree_sdk2_python_uv.git" | |
| uv pip install --system torch --index-url https://download.pytorch.org/whl/cpu | |
| uv pip install --system lerobot | |
| uv pip install --system loguru pygame scipy pyyaml | |
| - name: Cache HuggingFace models | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/huggingface/hub | |
| key: hf-models-${{ runner.os }}-v1 | |
| - name: Run MuJoCo grasp example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/mujoco/grasp.py --report --output-dir ./harness_output | |
| - name: Run G1 WBC reach example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/g1/wbc_reach.py --report --output-dir ./harness_output | |
| - name: Run LeRobot G1 locomotion example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/g1/lerobot_locomotion.py --report --output-dir ./harness_output | |
| - name: Run native LeRobot G1 (GR00T) example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/g1/lerobot_native.py --controller groot --report --output-dir ./harness_output | |
| - name: Run native LeRobot G1 (SONIC) example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/g1/lerobot_native.py --controller sonic --report --output-dir ./harness_output | |
| - name: Run SONIC planner example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/sonic/locomotion.py --report --assert-success --output-dir ./harness_output | |
| - name: Run SONIC motion tracking example | |
| env: | |
| MUJOCO_GL: osmesa | |
| run: python examples/demos/sonic/tracking.py --report --assert-success --output-dir ./harness_output | |
| - name: Build static pages (landing) | |
| run: | | |
| mkdir -p _site | |
| cp .github/pages/index.html _site/index.html | |
| - name: Build demo reports | |
| run: | | |
| # --- Demo 1: Simple Grasp (with Meshcat 3D) --- | |
| # The report's iframe src values are relative to the harness output | |
| # root (e.g. mujoco_grasp/trial_001/<cp>/meshcat_scene.html), so the | |
| # deployed checkpoint assets must preserve that nesting under | |
| # _site/grasp/ or the 3D scenes 404. | |
| mkdir -p _site/grasp | |
| cp harness_output/report.html _site/grasp/index.html | |
| for cp_dir in harness_output/mujoco_grasp/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| dest="_site/grasp/mujoco_grasp/trial_001/${cp_name}" | |
| mkdir -p "$dest" | |
| cp "${cp_dir}"*_rgb.png "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"*_depth_viz.png "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"meshcat_scene.html "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "$dest/" 2>/dev/null || true | |
| done | |
| cp harness_output/mujoco_grasp/trial_001/autonomous_report.json _site/grasp/ 2>/dev/null || true | |
| cp harness_output/mujoco_grasp/trial_001/alarms.json _site/grasp/ 2>/dev/null || true | |
| cp harness_output/mujoco_grasp/trial_001/phase_manifest.json _site/grasp/ 2>/dev/null || true | |
| # --- Demo 2: G1 WBC Reach --- | |
| # As with the grasp demo, the report references meshcat scenes by | |
| # their output-relative path (g1_wbc_reach/trial_001/<cp>/...), so the | |
| # deployed assets keep that nesting under _site/g1-reach/. | |
| mkdir -p _site/g1-reach | |
| cp harness_output/g1_wbc_reach_report.html _site/g1-reach/index.html | |
| for cp_dir in harness_output/g1_wbc_reach/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| dest="_site/g1-reach/g1_wbc_reach/trial_001/${cp_name}" | |
| mkdir -p "$dest" | |
| cp "${cp_dir}"*_rgb.png "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"*_depth_viz.png "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"meshcat_scene.html "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "$dest/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "$dest/" 2>/dev/null || true | |
| done | |
| # --- Demo 3: LeRobot G1 Locomotion --- | |
| mkdir -p _site/g1-loco | |
| cp harness_output/lerobot_g1_report.html _site/g1-loco/index.html | |
| for cp_dir in harness_output/lerobot_g1/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| mkdir -p "_site/g1-loco/${cp_name}" | |
| cp "${cp_dir}"*_rgb.png "_site/g1-loco/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "_site/g1-loco/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "_site/g1-loco/${cp_name}/" 2>/dev/null || true | |
| done | |
| # --- Demo 4a: Native LeRobot G1 (GR00T) --- | |
| mkdir -p _site/g1-native-groot | |
| cp harness_output/lerobot_g1_native_groot_report.html _site/g1-native-groot/index.html | |
| for cp_dir in harness_output/lerobot_g1_native_groot/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| mkdir -p "_site/g1-native-groot/${cp_name}" | |
| cp "${cp_dir}"*_rgb.png "_site/g1-native-groot/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "_site/g1-native-groot/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "_site/g1-native-groot/${cp_name}/" 2>/dev/null || true | |
| done | |
| # --- Demo 4b: Native LeRobot G1 (SONIC) --- | |
| mkdir -p _site/g1-native-sonic | |
| cp harness_output/lerobot_g1_native_sonic_report.html _site/g1-native-sonic/index.html | |
| for cp_dir in harness_output/lerobot_g1_native_sonic/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| mkdir -p "_site/g1-native-sonic/${cp_name}" | |
| cp "${cp_dir}"*_rgb.png "_site/g1-native-sonic/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "_site/g1-native-sonic/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "_site/g1-native-sonic/${cp_name}/" 2>/dev/null || true | |
| done | |
| # --- Demo 5: SONIC Planner --- | |
| mkdir -p _site/sonic-planner | |
| cp harness_output/sonic_locomotion_report.html _site/sonic-planner/index.html | |
| for cp_dir in harness_output/sonic_locomotion/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| mkdir -p "_site/sonic-planner/${cp_name}" | |
| cp "${cp_dir}"*_rgb.png "_site/sonic-planner/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "_site/sonic-planner/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "_site/sonic-planner/${cp_name}/" 2>/dev/null || true | |
| done | |
| # --- Demo 6: SONIC Motion Tracking --- | |
| mkdir -p _site/sonic | |
| cp harness_output/sonic_tracking_report.html _site/sonic/index.html | |
| for cp_dir in harness_output/sonic_tracking/trial_001/*/; do | |
| cp_name=$(basename "$cp_dir") | |
| mkdir -p "_site/sonic/${cp_name}" | |
| cp "${cp_dir}"*_rgb.png "_site/sonic/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"metadata.json "_site/sonic/${cp_name}/" 2>/dev/null || true | |
| cp "${cp_dir}"state.json "_site/sonic/${cp_name}/" 2>/dev/null || true | |
| done | |
| - name: Upload Pages artifact | |
| if: always() | |
| uses: actions/upload-pages-artifact@v3 | |
| with: | |
| path: _site | |
| - name: Upload site content for downstream workflows | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: site-content | |
| path: _site | |
| deploy: | |
| needs: build | |
| if: ${{ !cancelled() }} | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v4 |