Add files using upload-large-folder tool
Browse files- GR00T-WholeBodyControl/.gitattributes +25 -0
- GR00T-WholeBodyControl/.gitignore +221 -0
- GR00T-WholeBodyControl/.lfsconfig +2 -0
- GR00T-WholeBodyControl/CITATION.cff +93 -0
- GR00T-WholeBodyControl/CONTRIBUTING.md +40 -0
- GR00T-WholeBodyControl/LICENSE +186 -0
- GR00T-WholeBodyControl/Makefile +16 -0
- GR00T-WholeBodyControl/README.md +459 -0
- GR00T-WholeBodyControl/SECURITY.md +10 -0
- GR00T-WholeBodyControl/check_environment.py +225 -0
- GR00T-WholeBodyControl/decoupled_wbc/pyproject.toml +93 -0
- GR00T-WholeBodyControl/docs/requirements.txt +10 -0
- GR00T-WholeBodyControl/download_from_hf.py +311 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.clang-format +85 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.cmake-format.py +20 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.editorconfig +24 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.gitattributes +9 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.gitignore +7 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/.justfile +44 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/CMakeLists.txt +245 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/deploy.sh +577 -0
- GR00T-WholeBodyControl/gear_sonic_deploy/visualize_motion.py +432 -0
- GR00T-WholeBodyControl/install_scripts/install_camera_server.sh +252 -0
- GR00T-WholeBodyControl/install_scripts/install_data_collection.sh +80 -0
- GR00T-WholeBodyControl/install_scripts/install_inference.sh +72 -0
- GR00T-WholeBodyControl/install_scripts/install_leap_sdk.sh +19 -0
- GR00T-WholeBodyControl/install_scripts/install_mujoco_sim.sh +76 -0
- GR00T-WholeBodyControl/install_scripts/install_pico.sh +191 -0
- GR00T-WholeBodyControl/install_scripts/install_ros.sh +64 -0
- GR00T-WholeBodyControl/lint.sh +45 -0
- GR00T-WholeBodyControl/motionbricks/.gitattributes +4 -0
- GR00T-WholeBodyControl/motionbricks/README.md +281 -0
- GR00T-WholeBodyControl/motionbricks/setup.py +23 -0
- GR00T-WholeBodyControl/pyproject.toml +87 -0
- GR00T-WholeBodyControl/systemd/composed_camera_server.service +66 -0
- Isaac-GR00T/.coveragerc +28 -0
- Isaac-GR00T/.dockerignore +19 -0
- Isaac-GR00T/.gitattributes +9 -0
- Isaac-GR00T/.gitignore +170 -0
- Isaac-GR00T/.gitmodules +12 -0
- Isaac-GR00T/.pre-commit-config.yaml +25 -0
- Isaac-GR00T/AGENTS.md +79 -0
- Isaac-GR00T/ATTRIBUTIONS.md +0 -0
- Isaac-GR00T/CLAUDE.md +79 -0
- Isaac-GR00T/CONTRIBUTING.md +7 -0
- Isaac-GR00T/FAQ.md +81 -0
- Isaac-GR00T/LICENSE +190 -0
- Isaac-GR00T/README.md +641 -0
- Isaac-GR00T/pyproject.toml +176 -0
- Isaac-GR00T/uv.lock +0 -0
GR00T-WholeBodyControl/.gitattributes
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Machine learning models and data files
|
| 2 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
# 3D assets and models
|
| 6 |
+
*.usd filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.usda filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.STL filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.stl filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
# Shared libraries
|
| 11 |
+
*.a filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.so* filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.deb filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
# Collect demo in sim
|
| 18 |
+
*.hdf5 filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.obj filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.dae filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.so filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.so.* filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
# Docs static assets must NOT use LFS — GitHub Pages can't serve LFS pointers
|
| 25 |
+
docs/source/_static/** filter= diff= merge=
|
GR00T-WholeBodyControl/.gitignore
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Byte-compiled / optimized / DLL files
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
|
| 6 |
+
# C extensions
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# Distribution / packaging
|
| 10 |
+
.Python
|
| 11 |
+
build/
|
| 12 |
+
develop-eggs/
|
| 13 |
+
dist/
|
| 14 |
+
downloads/
|
| 15 |
+
eggs/
|
| 16 |
+
.eggs/
|
| 17 |
+
parts/
|
| 18 |
+
sdist/
|
| 19 |
+
var/
|
| 20 |
+
wheels/
|
| 21 |
+
share/python-wheels/
|
| 22 |
+
*.egg-info/
|
| 23 |
+
.installed.cfg
|
| 24 |
+
*.egg
|
| 25 |
+
MANIFEST
|
| 26 |
+
|
| 27 |
+
# PyInstaller
|
| 28 |
+
# Usually these files are written by a python script from a template
|
| 29 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 30 |
+
*.manifest
|
| 31 |
+
*.spec
|
| 32 |
+
|
| 33 |
+
# Installer logs
|
| 34 |
+
pip-log.txt
|
| 35 |
+
pip-delete-this-directory.txt
|
| 36 |
+
|
| 37 |
+
# Unit test / coverage reports
|
| 38 |
+
htmlcov/
|
| 39 |
+
.tox/
|
| 40 |
+
.nox/
|
| 41 |
+
.coverage
|
| 42 |
+
.coverage.*
|
| 43 |
+
.cache
|
| 44 |
+
nosetests.xml
|
| 45 |
+
coverage.xml
|
| 46 |
+
*.cover
|
| 47 |
+
*.py,cover
|
| 48 |
+
.hypothesis/
|
| 49 |
+
.pytest_cache/
|
| 50 |
+
cover/
|
| 51 |
+
|
| 52 |
+
# Translations
|
| 53 |
+
*.mo
|
| 54 |
+
*.pot
|
| 55 |
+
|
| 56 |
+
# Django stuff:
|
| 57 |
+
*.log
|
| 58 |
+
local_settings.py
|
| 59 |
+
db.sqlite3
|
| 60 |
+
db.sqlite3-journal
|
| 61 |
+
|
| 62 |
+
# Flask stuff:
|
| 63 |
+
instance/
|
| 64 |
+
.webassets-cache
|
| 65 |
+
|
| 66 |
+
# Scrapy stuff:
|
| 67 |
+
.scrapy
|
| 68 |
+
|
| 69 |
+
# Sphinx documentation
|
| 70 |
+
data/
|
| 71 |
+
|
| 72 |
+
# PyBuilder
|
| 73 |
+
.pybuilder/
|
| 74 |
+
target/
|
| 75 |
+
|
| 76 |
+
# Jupyter Notebook
|
| 77 |
+
.ipynb_checkpoints
|
| 78 |
+
|
| 79 |
+
# IPython
|
| 80 |
+
profile_default/
|
| 81 |
+
ipython_config.py
|
| 82 |
+
|
| 83 |
+
# pyenv
|
| 84 |
+
# For a library or package, you might want to ignore these files since the code is
|
| 85 |
+
# intended to run in multiple environments; otherwise, check them in:
|
| 86 |
+
# .python-version
|
| 87 |
+
|
| 88 |
+
# pipenv
|
| 89 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
| 90 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 91 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 92 |
+
# install all needed dependencies.
|
| 93 |
+
#Pipfile.lock
|
| 94 |
+
|
| 95 |
+
# UV
|
| 96 |
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
| 97 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 98 |
+
# commonly ignored for libraries.
|
| 99 |
+
#uv.lock
|
| 100 |
+
|
| 101 |
+
# poetry
|
| 102 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
| 103 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 104 |
+
# commonly ignored for libraries.
|
| 105 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
| 106 |
+
#poetry.lock
|
| 107 |
+
|
| 108 |
+
# pdm
|
| 109 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
| 110 |
+
#pdm.lock
|
| 111 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
| 112 |
+
# in version control.
|
| 113 |
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
| 114 |
+
.pdm.toml
|
| 115 |
+
.pdm-python
|
| 116 |
+
.pdm-build/
|
| 117 |
+
|
| 118 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
| 119 |
+
__pypackages__/
|
| 120 |
+
|
| 121 |
+
# Celery stuff
|
| 122 |
+
celerybeat-schedule
|
| 123 |
+
celerybeat.pid
|
| 124 |
+
|
| 125 |
+
# SageMath parsed files
|
| 126 |
+
*.sage.py
|
| 127 |
+
|
| 128 |
+
# Spyder project settings
|
| 129 |
+
.spyderproject
|
| 130 |
+
.spyproject
|
| 131 |
+
|
| 132 |
+
# Rope project settings
|
| 133 |
+
.ropeproject
|
| 134 |
+
|
| 135 |
+
# mkdocs documentation
|
| 136 |
+
/site
|
| 137 |
+
|
| 138 |
+
# mypy
|
| 139 |
+
.mypy_cache/
|
| 140 |
+
.dmypy.json
|
| 141 |
+
dmypy.json
|
| 142 |
+
|
| 143 |
+
# Pyre type checker
|
| 144 |
+
.pyre/
|
| 145 |
+
|
| 146 |
+
# pytype static type analyzer
|
| 147 |
+
.pytype/
|
| 148 |
+
|
| 149 |
+
# Cython debug symbols
|
| 150 |
+
cython_debug/
|
| 151 |
+
|
| 152 |
+
# IDE
|
| 153 |
+
.idea/
|
| 154 |
+
.vscode/
|
| 155 |
+
|
| 156 |
+
# log
|
| 157 |
+
outputs/
|
| 158 |
+
|
| 159 |
+
# Ruff stuff:
|
| 160 |
+
.ruff_cache/
|
| 161 |
+
|
| 162 |
+
# PyPI configuration file
|
| 163 |
+
.pypirc
|
| 164 |
+
|
| 165 |
+
outputs/
|
| 166 |
+
|
| 167 |
+
.DS_Store
|
| 168 |
+
|
| 169 |
+
# Hugging Face upload/maintenance scripts (internal use only)
|
| 170 |
+
huggingface/
|
| 171 |
+
|
| 172 |
+
# Model checkpoints (download via download_from_hf.py)
|
| 173 |
+
*.onnx
|
| 174 |
+
*.pt
|
| 175 |
+
*.pth
|
| 176 |
+
*.ckpt
|
| 177 |
+
*.safetensors
|
| 178 |
+
*.engine
|
| 179 |
+
!decoupled_wbc/sim2mujoco/resources/robots/g1/policy/GR00T-WholeBodyControl-Balance.onnx
|
| 180 |
+
!decoupled_wbc/sim2mujoco/resources/robots/g1/policy/GR00T-WholeBodyControl-Walk.onnx
|
| 181 |
+
!motionbricks/out/**/*.ckpt
|
| 182 |
+
|
| 183 |
+
|
| 184 |
+
# Mujoco
|
| 185 |
+
MUJOCO_LOG.TXT
|
| 186 |
+
|
| 187 |
+
# IsaacDeploy
|
| 188 |
+
external_dependencies/isaac_teleop_app/isaac-deploy
|
| 189 |
+
external_dependencies/doc/
|
| 190 |
+
|
| 191 |
+
# XRoboToolkit pybind (cloned locally on aarch64 by install_pico.sh)
|
| 192 |
+
external_dependencies/XRoboToolkit-PC-Service-Pybind/
|
| 193 |
+
|
| 194 |
+
# UV
|
| 195 |
+
uv.lock
|
| 196 |
+
|
| 197 |
+
# Virtual environments (created by install_scripts/)
|
| 198 |
+
.venv_sim/
|
| 199 |
+
.venv_teleop/
|
| 200 |
+
.venv_data_collection/
|
| 201 |
+
.venv_camera/
|
| 202 |
+
.venv_inference/
|
| 203 |
+
|
| 204 |
+
# XRoboToolkit-PC-Service-Pybind
|
| 205 |
+
xrobotoolkit_sdk.cpython-*-*-*.so
|
| 206 |
+
teleop_vids/
|
| 207 |
+
*.code-workspace
|
| 208 |
+
# Motion/training data (large local datasets, not tracked in git)
|
| 209 |
+
data/
|
| 210 |
+
bones_seed_smpl/
|
| 211 |
+
sonic_release/
|
| 212 |
+
# Training output logs
|
| 213 |
+
logs_rl/
|
| 214 |
+
logs_eval/
|
| 215 |
+
|
| 216 |
+
# Model checkpoints directory
|
| 217 |
+
models/
|
| 218 |
+
|
| 219 |
+
# Downloaded from HuggingFace (hf download)
|
| 220 |
+
sample_data/
|
| 221 |
+
sonic_release/
|
GR00T-WholeBodyControl/.lfsconfig
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[lfs]
|
| 2 |
+
fetchexclude = motionbricks/out/**
|
GR00T-WholeBodyControl/CITATION.cff
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cff-version: 1.2.0
|
| 2 |
+
message: "If you use this software, please cite it as below."
|
| 3 |
+
title: "GR00T Whole-Body Control"
|
| 4 |
+
authors:
|
| 5 |
+
- family-names: "Luo"
|
| 6 |
+
given-names: "Zhengyi"
|
| 7 |
+
- family-names: "Yuan"
|
| 8 |
+
given-names: "Ye"
|
| 9 |
+
- family-names: "Wang"
|
| 10 |
+
given-names: "Tingwu"
|
| 11 |
+
- family-names: "Li"
|
| 12 |
+
given-names: "Chenran"
|
| 13 |
+
- family-names: "Chen"
|
| 14 |
+
given-names: "Sirui"
|
| 15 |
+
- family-names: "Castañeda"
|
| 16 |
+
given-names: "Fernando"
|
| 17 |
+
- family-names: "Cao"
|
| 18 |
+
given-names: "Zi-Ang"
|
| 19 |
+
- family-names: "Li"
|
| 20 |
+
given-names: "Jiefeng"
|
| 21 |
+
- family-names: "Zhu"
|
| 22 |
+
given-names: "Yuke"
|
| 23 |
+
url: "https://github.com/NVlabs/GR00T-WholeBodyControl"
|
| 24 |
+
repository-code: "https://github.com/NVlabs/GR00T-WholeBodyControl"
|
| 25 |
+
type: software
|
| 26 |
+
keywords:
|
| 27 |
+
- humanoid-robotics
|
| 28 |
+
- reinforcement-learning
|
| 29 |
+
- whole-body-control
|
| 30 |
+
- motion-tracking
|
| 31 |
+
- teleoperation
|
| 32 |
+
- robotics
|
| 33 |
+
- pytorch
|
| 34 |
+
license: Apache-2.0
|
| 35 |
+
preferred-citation:
|
| 36 |
+
type: article
|
| 37 |
+
title: "SONIC: Supersizing Motion Tracking for Natural Humanoid Whole-Body Control"
|
| 38 |
+
authors:
|
| 39 |
+
- family-names: "Luo"
|
| 40 |
+
given-names: "Zhengyi"
|
| 41 |
+
- family-names: "Yuan"
|
| 42 |
+
given-names: "Ye"
|
| 43 |
+
- family-names: "Wang"
|
| 44 |
+
given-names: "Tingwu"
|
| 45 |
+
- family-names: "Li"
|
| 46 |
+
given-names: "Chenran"
|
| 47 |
+
- family-names: "Chen"
|
| 48 |
+
given-names: "Sirui"
|
| 49 |
+
- family-names: "Castañeda"
|
| 50 |
+
given-names: "Fernando"
|
| 51 |
+
- family-names: "Cao"
|
| 52 |
+
given-names: "Zi-Ang"
|
| 53 |
+
- family-names: "Li"
|
| 54 |
+
given-names: "Jiefeng"
|
| 55 |
+
- family-names: "Minor"
|
| 56 |
+
given-names: "David"
|
| 57 |
+
- family-names: "Ben"
|
| 58 |
+
given-names: "Qingwei"
|
| 59 |
+
- family-names: "Da"
|
| 60 |
+
given-names: "Xingye"
|
| 61 |
+
- family-names: "Ding"
|
| 62 |
+
given-names: "Runyu"
|
| 63 |
+
- family-names: "Hogg"
|
| 64 |
+
given-names: "Cyrus"
|
| 65 |
+
- family-names: "Song"
|
| 66 |
+
given-names: "Lina"
|
| 67 |
+
- family-names: "Lim"
|
| 68 |
+
given-names: "Edy"
|
| 69 |
+
- family-names: "Jeong"
|
| 70 |
+
given-names: "Eugene"
|
| 71 |
+
- family-names: "He"
|
| 72 |
+
given-names: "Tairan"
|
| 73 |
+
- family-names: "Xue"
|
| 74 |
+
given-names: "Haoru"
|
| 75 |
+
- family-names: "Xiao"
|
| 76 |
+
given-names: "Wenli"
|
| 77 |
+
- family-names: "Wang"
|
| 78 |
+
given-names: "Zi"
|
| 79 |
+
- family-names: "Yuen"
|
| 80 |
+
given-names: "Simon"
|
| 81 |
+
- family-names: "Kautz"
|
| 82 |
+
given-names: "Jan"
|
| 83 |
+
- family-names: "Chang"
|
| 84 |
+
given-names: "Yan"
|
| 85 |
+
- family-names: "Iqbal"
|
| 86 |
+
given-names: "Umar"
|
| 87 |
+
- family-names: "Fan"
|
| 88 |
+
given-names: "Linxi"
|
| 89 |
+
- family-names: "Zhu"
|
| 90 |
+
given-names: "Yuke"
|
| 91 |
+
journal: "arXiv preprint"
|
| 92 |
+
year: 2025
|
| 93 |
+
url: "https://arxiv.org/abs/2511.07820"
|
GR00T-WholeBodyControl/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributing to GR00T-WholeBodyControl
|
| 2 |
+
|
| 3 |
+
We welcome contributions from the community! Here's how to get started.
|
| 4 |
+
|
| 5 |
+
## Reporting Issues
|
| 6 |
+
|
| 7 |
+
- Search [existing issues](https://github.com/NVlabs/GR00T-WholeBodyControl/issues) first
|
| 8 |
+
- Open a new issue with a clear description, error messages, and steps to reproduce
|
| 9 |
+
- Include your Python version, OS, GPU, and Isaac Lab version
|
| 10 |
+
|
| 11 |
+
## Pull Requests
|
| 12 |
+
|
| 13 |
+
1. Fork the repository
|
| 14 |
+
2. Create a feature branch (`git checkout -b my-feature`)
|
| 15 |
+
3. Make your changes
|
| 16 |
+
4. Run the pre-flight check: `python check_environment.py`
|
| 17 |
+
5. Commit and push to your fork
|
| 18 |
+
6. Open a pull request against `main`
|
| 19 |
+
|
| 20 |
+
### Guidelines
|
| 21 |
+
|
| 22 |
+
- Keep PRs focused on a single change
|
| 23 |
+
- Follow existing code style (no linter is enforced, but be consistent)
|
| 24 |
+
- Update documentation if your change affects user-facing behavior
|
| 25 |
+
- Add yourself to the PR description if you'd like credit
|
| 26 |
+
|
| 27 |
+
## Development Setup
|
| 28 |
+
|
| 29 |
+
See the [Installation Guide](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/installation_training.html)
|
| 30 |
+
for setting up the training environment.
|
| 31 |
+
|
| 32 |
+
## Questions
|
| 33 |
+
|
| 34 |
+
For questions, open a [GitHub Discussion](https://github.com/NVlabs/GR00T-WholeBodyControl/issues)
|
| 35 |
+
or contact [gear-wbc@nvidia.com](mailto:gear-wbc@nvidia.com).
|
| 36 |
+
|
| 37 |
+
## License
|
| 38 |
+
|
| 39 |
+
By contributing, you agree that your contributions will be licensed under the
|
| 40 |
+
[Apache 2.0 License](LICENSE).
|
GR00T-WholeBodyControl/LICENSE
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
================================================================================
|
| 2 |
+
DUAL LICENSE NOTICE
|
| 3 |
+
================================================================================
|
| 4 |
+
|
| 5 |
+
This repository is dual-licensed. Different components are under different terms:
|
| 6 |
+
|
| 7 |
+
1. SOURCE CODE - Apache License 2.0
|
| 8 |
+
All source code, scripts, and software components
|
| 9 |
+
|
| 10 |
+
2. MODEL WEIGHTS - NVIDIA Open Model License
|
| 11 |
+
All trained model checkpoints and weights
|
| 12 |
+
|
| 13 |
+
See below for the full text of each license.
|
| 14 |
+
|
| 15 |
+
================================================================================
|
| 16 |
+
PART 1: SOURCE CODE LICENSE (Apache License 2.0)
|
| 17 |
+
================================================================================
|
| 18 |
+
|
| 19 |
+
Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
| 20 |
+
|
| 21 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 22 |
+
you may not use this file except in compliance with the License.
|
| 23 |
+
You may obtain a copy of the License at
|
| 24 |
+
|
| 25 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 26 |
+
|
| 27 |
+
Unless required by applicable law or agreed to in writing, software
|
| 28 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 29 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 30 |
+
See the License for the specific language governing permissions and
|
| 31 |
+
limitations under the License.
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
================================================================================
|
| 35 |
+
PART 2: MODEL WEIGHTS LICENSE (NVIDIA Open Model License)
|
| 36 |
+
================================================================================
|
| 37 |
+
|
| 38 |
+
NVIDIA OPEN MODEL LICENSE AGREEMENT
|
| 39 |
+
|
| 40 |
+
Last Modified: October 24, 2025
|
| 41 |
+
|
| 42 |
+
NVIDIA Corporation and its affiliates ("NVIDIA") grants permission to use machine
|
| 43 |
+
learning models under specific conditions. Key permissions include creating
|
| 44 |
+
derivative models and distributing them, with NVIDIA retaining no ownership claims
|
| 45 |
+
over outputs generated by users.
|
| 46 |
+
|
| 47 |
+
SECTION 1: DEFINITIONS
|
| 48 |
+
|
| 49 |
+
1.1 "Derivative Model" means any modification of, or works based on or derived
|
| 50 |
+
from, the Model, excluding outputs.
|
| 51 |
+
|
| 52 |
+
1.2 "Legal Entity" means the union of the acting entity and all other entities
|
| 53 |
+
that control, are controlled by, or are under common control with that entity.
|
| 54 |
+
|
| 55 |
+
1.3 "Model" means the machine learning model, software, and any checkpoints,
|
| 56 |
+
weights, algorithms, parameters, configuration files, and documentation that NVIDIA
|
| 57 |
+
makes available under this Agreement.
|
| 58 |
+
|
| 59 |
+
1.4 "NVIDIA Cosmos Model" means a multimodal Model that is covered by this Agreement.
|
| 60 |
+
|
| 61 |
+
1.5 "Special-Purpose Model" means a Model that is limited to narrow,
|
| 62 |
+
purpose-specific tasks.
|
| 63 |
+
|
| 64 |
+
1.6 "You" or "Your" means an individual or Legal Entity exercising permissions
|
| 65 |
+
granted by this Agreement.
|
| 66 |
+
|
| 67 |
+
SECTION 2: CONDITIONS FOR USE, LICENSE GRANT, AI ETHICS AND IP OWNERSHIP
|
| 68 |
+
|
| 69 |
+
2.1 Conditions for Use. You must comply with all terms and conditions of this
|
| 70 |
+
Agreement. If You initiate copyright or patent litigation against any entity
|
| 71 |
+
(including a cross-claim or counterclaim in a lawsuit) alleging that the Model
|
| 72 |
+
constitutes direct or contributory infringement, then Your licenses under this
|
| 73 |
+
Agreement shall terminate. If You circumvent any safety guardrails or safety
|
| 74 |
+
measures built in to the Model without providing comparable alternatives, Your
|
| 75 |
+
rights under this Agreement shall terminate. NVIDIA may update this Agreement at
|
| 76 |
+
any time to comply with applicable law; Your continued use constitutes Your
|
| 77 |
+
acceptance of the updated terms.
|
| 78 |
+
|
| 79 |
+
2.2 License Grant. Subject to the terms and conditions of this Agreement, NVIDIA
|
| 80 |
+
hereby grants You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
| 81 |
+
revocable license to publicly perform, publicly display, reproduce, use, create
|
| 82 |
+
derivative works of, make, have made, sell, offer for sale, distribute and import
|
| 83 |
+
the Model.
|
| 84 |
+
|
| 85 |
+
2.3 AI Ethics. Your use of the Model must be in accordance with NVIDIA's
|
| 86 |
+
Trustworthy AI terms, which can be found at
|
| 87 |
+
https://www.nvidia.com/en-us/agreements/trustworthy-ai/terms/.
|
| 88 |
+
|
| 89 |
+
2.4 IP Ownership. NVIDIA owns the original Model and NVIDIA's Derivative Models.
|
| 90 |
+
You own Your Derivative Models. NVIDIA makes no claim of ownership to outputs. You
|
| 91 |
+
are responsible for outputs and their subsequent uses.
|
| 92 |
+
|
| 93 |
+
SECTION 3: REDISTRIBUTION
|
| 94 |
+
|
| 95 |
+
You may reproduce and distribute copies of the Model or Derivative Models thereof,
|
| 96 |
+
with or without modifications, provided that You meet the following conditions:
|
| 97 |
+
|
| 98 |
+
a. You must include a copy of this Agreement.
|
| 99 |
+
|
| 100 |
+
b. You must include the following attribution notice, which can appear in the same
|
| 101 |
+
location as other third-party notices or license information: "Licensed by NVIDIA
|
| 102 |
+
Corporation under the NVIDIA Open Model License."
|
| 103 |
+
|
| 104 |
+
c. If You are distributing a NVIDIA Cosmos Model, You must also include the phrase
|
| 105 |
+
"Built on NVIDIA Cosmos" on the applicable website, in the user interface, in a
|
| 106 |
+
blog, in an "about" page, or in product documentation.
|
| 107 |
+
|
| 108 |
+
d. You may add Your own copyright statement to Your modifications and may provide
|
| 109 |
+
additional or different license terms and conditions for use, reproduction, or
|
| 110 |
+
distribution of Your modifications or for any Derivative Models as a whole,
|
| 111 |
+
provided Your use, reproduction, and distribution otherwise complies with this
|
| 112 |
+
Agreement.
|
| 113 |
+
|
| 114 |
+
SECTION 4: SEPARATE COMPONENTS
|
| 115 |
+
|
| 116 |
+
The Model may contain components that are subject to separate legal notices or
|
| 117 |
+
governed by separate licenses (including Open Source Software Licenses), as may be
|
| 118 |
+
described in any files made available with the Model. Your use of those separate
|
| 119 |
+
components is subject to the applicable license. This Agreement shall control over
|
| 120 |
+
the separate licenses for third-party Open Source Software to the extent that the
|
| 121 |
+
separate license imposes additional restrictions. "Open Source Software License"
|
| 122 |
+
means any software license approved by the Open Source Initiative, Free Software
|
| 123 |
+
Foundation, or similar recognized organization, or a license identified by SPDX.
|
| 124 |
+
|
| 125 |
+
SECTION 5: TRADEMARKS
|
| 126 |
+
|
| 127 |
+
This Agreement does not grant permission to use the trade names, trademarks,
|
| 128 |
+
service marks, or product names of NVIDIA, except as required for reasonable and
|
| 129 |
+
customary use in describing the origin of the Model and reproducing the content of
|
| 130 |
+
the notice.
|
| 131 |
+
|
| 132 |
+
SECTION 6: DISCLAIMER OF WARRANTY
|
| 133 |
+
|
| 134 |
+
NVIDIA provides the Model on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
| 135 |
+
ANY KIND, either express or implied, including, without limitation, any warranties
|
| 136 |
+
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 137 |
+
PARTICULAR PURPOSE. You are solely responsible for reviewing the documentation
|
| 138 |
+
accompanying the Model and determining the appropriateness of using the Model, and
|
| 139 |
+
You understand that Special-Purpose Models are limited to narrow, purpose-specific
|
| 140 |
+
tasks and must not be deployed for uses that are beyond such tasks.
|
| 141 |
+
|
| 142 |
+
SECTION 7: LIMITATION OF LIABILITY
|
| 143 |
+
|
| 144 |
+
In no event and under no legal theory, whether in tort (including negligence),
|
| 145 |
+
contract, or otherwise, unless required by applicable law (such as deliberate and
|
| 146 |
+
grossly negligent acts) or agreed to in writing, will NVIDIA be liable to You for
|
| 147 |
+
damages, including any direct, indirect, special, incidental, or consequential
|
| 148 |
+
damages of any character arising as a result of this Agreement or out of the use
|
| 149 |
+
or inability to use the Model or Derivative Models or outputs (including but not
|
| 150 |
+
limited to damages for loss of goodwill, work stoppage, computer failure or
|
| 151 |
+
malfunction, or any and all other commercial damages or losses), even if NVIDIA has
|
| 152 |
+
been advised of the possibility of such damages.
|
| 153 |
+
|
| 154 |
+
SECTION 8: INDEMNITY
|
| 155 |
+
|
| 156 |
+
You will defend, indemnify and hold harmless NVIDIA and its affiliates, and their
|
| 157 |
+
respective employees, contractors, directors, officers and agents, from and against
|
| 158 |
+
any and all claims, damages, obligations, losses, liabilities, costs or debt, and
|
| 159 |
+
expenses (including but not limited to attorney's fees) arising from Your use or
|
| 160 |
+
distribution of the Model or Derivative Models or outputs.
|
| 161 |
+
|
| 162 |
+
SECTION 9: FEEDBACK
|
| 163 |
+
|
| 164 |
+
NVIDIA may use feedback You provide without restriction and without any
|
| 165 |
+
compensation to You.
|
| 166 |
+
|
| 167 |
+
SECTION 10: GOVERNING LAW
|
| 168 |
+
|
| 169 |
+
This Agreement will be governed in all respects by the laws of the United States
|
| 170 |
+
and of the State of Delaware, without regard to conflict of laws provisions. The
|
| 171 |
+
federal and state courts residing in Santa Clara County, California shall have
|
| 172 |
+
exclusive jurisdiction over any dispute arising out of this Agreement, and You
|
| 173 |
+
hereby consent to the personal jurisdiction of such courts. However, NVIDIA shall
|
| 174 |
+
have the right to seek injunctive relief in any court of competent jurisdiction.
|
| 175 |
+
|
| 176 |
+
SECTION 11: TRADE AND COMPLIANCE
|
| 177 |
+
|
| 178 |
+
You shall comply with all applicable import, export, trade, and economic sanctions
|
| 179 |
+
laws, including without limitation the Export Administration Regulations and
|
| 180 |
+
economic sanctions laws implemented by the Office of Foreign Assets Control, that
|
| 181 |
+
restrict or govern the destination, end-user and end-use of NVIDIA products,
|
| 182 |
+
technology, software, and services.
|
| 183 |
+
|
| 184 |
+
---
|
| 185 |
+
|
| 186 |
+
Version Release Date: October 24, 2025
|
GR00T-WholeBodyControl/Makefile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.PHONY : run-checks
|
| 2 |
+
run-checks :
|
| 3 |
+
isort --check .
|
| 4 |
+
black --check .
|
| 5 |
+
ruff check .
|
| 6 |
+
# mypy .
|
| 7 |
+
|
| 8 |
+
.PHONY : format
|
| 9 |
+
format :
|
| 10 |
+
isort .
|
| 11 |
+
black .
|
| 12 |
+
|
| 13 |
+
.PHONY : build
|
| 14 |
+
build :
|
| 15 |
+
rm -rf *.egg-info/
|
| 16 |
+
python -m build
|
GR00T-WholeBodyControl/README.md
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div align="center">
|
| 2 |
+
|
| 3 |
+
<img src="media/groot_wbc.png" width="800" alt="GEAR SONIC Header">
|
| 4 |
+
|
| 5 |
+
<!-- --- -->
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
</div>
|
| 9 |
+
|
| 10 |
+
<div align="center">
|
| 11 |
+
|
| 12 |
+
[](LICENSE)
|
| 13 |
+
[](https://github.com/isaac-sim/IsaacLab/releases/tag/v2.3.2)
|
| 14 |
+
[](https://nvlabs.github.io/GR00T-WholeBodyControl/)
|
| 15 |
+
[](https://nvlabs.github.io/GEAR-SONIC/demo.html)
|
| 16 |
+
|
| 17 |
+
</div>
|
| 18 |
+
|
| 19 |
+
---
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# GR00T-WholeBodyControl
|
| 25 |
+
|
| 26 |
+
This is the codebase for the **GR00T Whole-Body Control (WBC)** projects. It hosts model checkpoints and scripts for training, evaluating, and deploying advanced whole-body controllers for humanoid robots. We currently support:
|
| 27 |
+
|
| 28 |
+
- **Decoupled WBC**: the decoupled controller (RL for lower body, and IK for upper body) used in NVIDIA GR00T [N1.5](https://research.nvidia.com/labs/gear/gr00t-n1_5/) and [N1.6](https://research.nvidia.com/labs/gear/gr00t-n1_6/) models;
|
| 29 |
+
- **GEAR-SONIC Series**: our latest iteration of generalist humanoid whole-body controllers (see our [whitepaper](https://nvlabs.github.io/GEAR-SONIC/));
|
| 30 |
+
- **MotionBricks**: a real-time latent generative model for interactive motion control in animation and robotics (see the [project page](https://nvlabs.github.io/motionbricks/)).
|
| 31 |
+
|
| 32 |
+
## News
|
| 33 |
+
|
| 34 |
+
- **[2026-07-23]** **SONIC v1.1 checkpoint** — released a robot-heading-normalized SONIC controller trained with wrist-pose augmentation for 3-point teleoperation and SONIC-backed VLA execution. See the [Model Card](#model-card) and [Download Models](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/download_models.html#sonic-v11-checkpoint).
|
| 35 |
+
- **[06/16]** **Isaac Teleop Setup (CloudXR / DeviceIO, in-process)** — added bring-up docs for the in-process CloudXR path via `isaacteleop[cloudxr]`, with no separate publisher container. See [Isaac Teleop Setup](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/isaac_teleop_publisher_setup.html).
|
| 36 |
+
- **[2026-06-16]** **Low-latency teleoperation checkpoint** — released a SONIC checkpoint with 4-frame SMPL reference lookahead for more responsive whole-body teleoperation. See the [Model Card](#model-card), [Download Models](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/download_models.html#low-latency-teleoperation-checkpoint), and [VLA Inference](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vla_inference.html#low-latency-teleoperation-checkpoint).
|
| 37 |
+
- **[2026-05-07]** 🤖 **End-to-end VLA workflow on G1** — collect teleop data, fine-tune Isaac-GR00T N1.7, and deploy with SONIC whole-body control. See [Data Collection](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/data_collection.html), [VLA Workflow](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vla_workflow.html), and [VLA Inference](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vla_inference.html).
|
| 38 |
+
- **[2026-04-27]** 🧩 **MotionBricks preview** — interactive G1 demo, pretrained checkpoints (VQVAE · pose · root), synthetic training code, and motion-representation docs. See [`motionbricks/`](motionbricks/) and the [project page](https://nvlabs.github.io/motionbricks/).
|
| 39 |
+
- **[2026-04-14]** 🌐 **[Live web demo](https://nvlabs.github.io/GEAR-SONIC/demo.html)** — try SONIC interactively in your browser. Features [Kimodo](https://github.com/nv-tlabs/kimodo) text-to-motion generation.
|
| 40 |
+
- **[2026-04-10]** 🚀 Released **SONIC training code and checkpoint** on [HuggingFace](https://huggingface.co/nvidia/GEAR-SONIC). Train from scratch or finetune. **Additional embodiment support** and **VLA data collection pipeline**. See [Training Guide](https://nvlabs.github.io/GR00T-WholeBodyControl/user_guide/training.html).
|
| 41 |
+
- **[2026-03-24]** 🔧 C++ inference stack update: motor error monitoring, TTS alerts, ZMQ protocol v4, idle-mode readaptation. **ZMQ header size changed to 1280 bytes.**
|
| 42 |
+
- **[2026-03-16]** 📦 [BONES-SEED](https://huggingface.co/datasets/bones-studio/seed) open-sourced — 142K+ human motions (~288 hours) with G1 MuJoCo trajectories.
|
| 43 |
+
- **[2026-02-19]** 🎉 Released GEAR-SONIC: pretrained checkpoints, C++ inference, VR teleoperation, and documentation.
|
| 44 |
+
- **[2025-11-12]** 🏁 Initial release with Decoupled WBC for GR00T N1.5 and N1.6.
|
| 45 |
+
|
| 46 |
+
## Table of Contents
|
| 47 |
+
|
| 48 |
+
- [News](#news)
|
| 49 |
+
- [GEAR-SONIC](#gear-sonic)
|
| 50 |
+
- [Model Card](#model-card)
|
| 51 |
+
- [VR Whole-Body Teleoperation](#vr-whole-body-teleoperation)
|
| 52 |
+
- [Kinematic Planner](#kinematic-planner)
|
| 53 |
+
- [SONIC Training](#sonic-training)
|
| 54 |
+
- [TODOs](#todos)
|
| 55 |
+
- [What's Included](#whats-included)
|
| 56 |
+
- [Setup](#setup)
|
| 57 |
+
- [Documentation](#documentation)
|
| 58 |
+
- [Citation](#citation)
|
| 59 |
+
- [License](#license)
|
| 60 |
+
- [Support](#support)
|
| 61 |
+
- [MotionBricks](#motionbricks)
|
| 62 |
+
- [Decoupled WBC](#decoupled-wbc)
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
## GEAR-SONIC
|
| 66 |
+
|
| 67 |
+
<p style="font-size: 1.2em;">
|
| 68 |
+
<a href="https://nvlabs.github.io/GEAR-SONIC/"><strong>Website</strong></a> |
|
| 69 |
+
<a href="https://huggingface.co/nvidia/GEAR-SONIC"><strong>Model</strong></a> |
|
| 70 |
+
<a href="https://arxiv.org/abs/2511.07820"><strong>Paper</strong></a> |
|
| 71 |
+
<a href="https://nvlabs.github.io/GR00T-WholeBodyControl/"><strong>Docs</strong></a>
|
| 72 |
+
</p>
|
| 73 |
+
|
| 74 |
+
<div align="center">
|
| 75 |
+
<img src="docs/source/_static/sonic-preview-gif-480P.gif" width="800" >
|
| 76 |
+
|
| 77 |
+
</div>
|
| 78 |
+
|
| 79 |
+
SONIC is a humanoid behavior foundation model that gives robots a core set of motor skills learned from large-scale human motion data. Rather than building separate controllers for predefined motions, SONIC uses motion tracking as a scalable training task, enabling a single unified policy to produce natural, whole-body movement and support a wide range of behaviors — from walking and crawling to teleoperation and multi-modal control. It is designed to generalize beyond the motions it has seen during training and to serve as a foundation for higher-level planning and interaction.
|
| 80 |
+
|
| 81 |
+
In this repo, we release SONIC's training code, deployment framework, model checkpoints, and teleoperation stack for data collection.
|
| 82 |
+
|
| 83 |
+
## Model Card
|
| 84 |
+
|
| 85 |
+
SONIC provides three released Unitree G1 checkpoints. Choose the model based on its reference representation and intended deployment.
|
| 86 |
+
|
| 87 |
+
### Available Models
|
| 88 |
+
|
| 89 |
+
| Model | Hugging Face location | SMPL reference input | Intended use and comments |
|
| 90 |
+
|---|---|---|---|
|
| 91 |
+
| **Default SONIC (original release)** | Top-level `model_encoder.onnx`, `model_decoder.onnx`, and `observation_config.yaml`; training checkpoint at `sonic_release/last.pt` | 10 future frames at 20 ms spacing, approximately 200 ms of reference lookahead | Default general-purpose SONIC controller for motion tracking, planning, teleoperation, and compatibility with existing deployments. G1 and teleoperation future-reference observations use `step5`. |
|
| 92 |
+
| **Low-latency teleoperation** | [`low_latency/`](https://huggingface.co/nvidia/GEAR-SONIC/tree/main/low_latency) | 4 future frames at 20 ms spacing, approximately 80 ms of reference lookahead | Intended for more responsive whole-body teleoperation and VLA execution. G1 and teleoperation future-reference observations use `step1`. Use its encoder, decoder, and observation config together. |
|
| 93 |
+
| **SONIC v1.1** | [`sonic_v1_1/`](https://huggingface.co/nvidia/GEAR-SONIC/tree/main/sonic_v1_1) | 10 future frames at 20 ms spacing, approximately 200 ms of reference lookahead | Uses robot-heading-normalized target orientation and was trained with wrist-pose augmentation. Intended for heading-stable 3-point teleoperation and SONIC-backed VLA policies that use this controller. G1 and teleoperation future-reference observations use `step5`; this is not the low-latency model. |
|
| 94 |
+
|
| 95 |
+
All three models use the SONIC universal-token controller, produce 64-dimensional latent motion tokens, run the controller at 50 Hz, and support SMPL pose, G1 motion reference, and VR 3-point inputs. Deployment uses C++ and TensorRT; the PyTorch checkpoints support Isaac Lab evaluation and continued training.
|
| 96 |
+
|
| 97 |
+
The lookahead values describe the reference horizon presented to the controller. They are **not** measurements of total end-to-end teleoperation latency, which also includes sensing, networking, preprocessing, and inference. Model weights are covered by the [NVIDIA Open Model License](LICENSE).
|
| 98 |
+
|
| 99 |
+
### Released Files
|
| 100 |
+
|
| 101 |
+
| Model | Deployment files | PyTorch and configuration files |
|
| 102 |
+
|---|---|---|
|
| 103 |
+
| Default SONIC | `model_encoder.onnx`, `model_decoder.onnx`, `observation_config.yaml` | `sonic_release/last.pt`, `sonic_release/config.yaml` |
|
| 104 |
+
| Low-latency teleoperation | `low_latency/model_encoder.onnx`, `low_latency/model_decoder.onnx`, `low_latency/observation_config.yaml` | `low_latency/last.pt`, `low_latency/config.yaml`, `low_latency/model_config.yaml` |
|
| 105 |
+
| SONIC v1.1 | `sonic_v1_1/model_encoder.onnx`, `sonic_v1_1/model_decoder.onnx`, `sonic_v1_1/observation_config.yaml` | `sonic_v1_1/last.pt`, `sonic_v1_1/config.yaml`, `sonic_v1_1/model_config.yaml` |
|
| 106 |
+
|
| 107 |
+
### Usage
|
| 108 |
+
|
| 109 |
+
Download the default model and planner:
|
| 110 |
+
|
| 111 |
+
```bash
|
| 112 |
+
python download_from_hf.py
|
| 113 |
+
```
|
| 114 |
+
|
| 115 |
+
Download the low-latency teleoperation model and planner:
|
| 116 |
+
|
| 117 |
+
```bash
|
| 118 |
+
python download_from_hf.py --low-latency
|
| 119 |
+
```
|
| 120 |
+
|
| 121 |
+
Download SONIC v1.1 and the planner:
|
| 122 |
+
|
| 123 |
+
```bash
|
| 124 |
+
python download_from_hf.py --sonic-v1-1
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
Run the default C++ deployment stack:
|
| 128 |
+
|
| 129 |
+
```bash
|
| 130 |
+
cd gear_sonic_deploy
|
| 131 |
+
./deploy.sh --input-type zmq_manager real
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
Run the low-latency C++ deployment stack:
|
| 135 |
+
|
| 136 |
+
```bash
|
| 137 |
+
cd gear_sonic_deploy
|
| 138 |
+
./deploy.sh \
|
| 139 |
+
--cp policy/low_latency/model \
|
| 140 |
+
--obs-config policy/low_latency/observation_config.yaml \
|
| 141 |
+
--input-type zmq_manager \
|
| 142 |
+
real
|
| 143 |
+
```
|
| 144 |
+
|
| 145 |
+
Run the SONIC v1.1 C++ deployment stack:
|
| 146 |
+
|
| 147 |
+
```bash
|
| 148 |
+
cd gear_sonic_deploy
|
| 149 |
+
./deploy.sh \
|
| 150 |
+
--cp policy/sonic_v1_1/model \
|
| 151 |
+
--obs-config policy/sonic_v1_1/observation_config.yaml \
|
| 152 |
+
--input-type zmq_manager \
|
| 153 |
+
real
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
Run the default Python VLA launcher, which orchestrates the C++ controller and Python inference client:
|
| 157 |
+
|
| 158 |
+
```bash
|
| 159 |
+
python gear_sonic/scripts/launch_inference.py \
|
| 160 |
+
--camera-host 192.168.123.164 \
|
| 161 |
+
--prompt "pick up the cup"
|
| 162 |
+
```
|
| 163 |
+
|
| 164 |
+
For the low-latency model, add the matching deployment files:
|
| 165 |
+
|
| 166 |
+
```bash
|
| 167 |
+
python gear_sonic/scripts/launch_inference.py \
|
| 168 |
+
--deploy-checkpoint policy/low_latency/model \
|
| 169 |
+
--deploy-obs-config policy/low_latency/observation_config.yaml \
|
| 170 |
+
--camera-host 192.168.123.164 \
|
| 171 |
+
--prompt "pick up the cup"
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
For SONIC v1.1, use `policy/sonic_v1_1/model` and its matching
|
| 175 |
+
`policy/sonic_v1_1/observation_config.yaml` in the same launcher flags.
|
| 176 |
+
|
| 177 |
+
See [Downloading Model Checkpoints](docs/source/getting_started/download_models.md#sonic-v11-checkpoint) for Python checkpoint evaluation and additional deployment options. Test in simulation before using the checkpoint on a physical robot.
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
## VR Whole-Body Teleoperation
|
| 181 |
+
|
| 182 |
+
SONIC supports real-time whole-body teleoperation via PICO VR headset, enabling natural human-to-robot motion transfer for data collection and interactive control.
|
| 183 |
+
|
| 184 |
+
<div align="center">
|
| 185 |
+
<img src="docs/source/_static/sonic_low_latency_demo.gif" width="640" alt="SONIC Low Latency whole-body teleoperation and ground pickup">
|
| 186 |
+
</div>
|
| 187 |
+
|
| 188 |
+
<p align="center"><em><strong>SONIC Low Latency:</strong> 3-point VR teleoperation with whole-body tracking and a successful ground pickup.</em></p>
|
| 189 |
+
|
| 190 |
+
This repo can also drive the headset over Isaac Teleop / CloudXR by launching `gear_sonic/scripts/pico_manager_thread_server.py --input-source isaac-teleop`. The streamer hosts the CloudXR runtime in-process via `isaacteleop[cloudxr]` — no separate publisher container required. That path is currently documented and supported only for **G1 with a Thor backpack**. The Isaac Teleop bring-up steps are documented in [`docs/source/tutorials/isaac_teleop_publisher_setup.md`](docs/source/tutorials/isaac_teleop_publisher_setup.md).
|
| 191 |
+
|
| 192 |
+
<div align="center">
|
| 193 |
+
<table>
|
| 194 |
+
<tr>
|
| 195 |
+
<td align="center"><b>Walking</b></td>
|
| 196 |
+
<td align="center"><b>Running</b></td>
|
| 197 |
+
</tr>
|
| 198 |
+
<tr>
|
| 199 |
+
<td align="center"><img src="media/teleop_walking.gif" width="400"></td>
|
| 200 |
+
<td align="center"><img src="media/teleop_running.gif" width="400"></td>
|
| 201 |
+
</tr>
|
| 202 |
+
<tr>
|
| 203 |
+
<td align="center"><b>Sideways Movement</b></td>
|
| 204 |
+
<td align="center"><b>Kneeling</b></td>
|
| 205 |
+
</tr>
|
| 206 |
+
<tr>
|
| 207 |
+
<td align="center"><img src="media/teleop_sideways.gif" width="400"></td>
|
| 208 |
+
<td align="center"><img src="media/teleop_kneeling.gif" width="400"></td>
|
| 209 |
+
</tr>
|
| 210 |
+
<tr>
|
| 211 |
+
<td align="center"><b>Getting Up</b></td>
|
| 212 |
+
<td align="center"><b>Jumping</b></td>
|
| 213 |
+
</tr>
|
| 214 |
+
<tr>
|
| 215 |
+
<td align="center"><img src="media/teleop_getup.gif" width="400"></td>
|
| 216 |
+
<td align="center"><img src="media/teleop_jumping.gif" width="400"></td>
|
| 217 |
+
</tr>
|
| 218 |
+
<tr>
|
| 219 |
+
<td align="center"><b>Bimanual Manipulation</b></td>
|
| 220 |
+
<td align="center"><b>Object Hand-off</b></td>
|
| 221 |
+
</tr>
|
| 222 |
+
<tr>
|
| 223 |
+
<td align="center"><img src="media/teleop_bimanual.gif" width="400"></td>
|
| 224 |
+
<td align="center"><img src="media/teleop_switch_hands.gif" width="400"></td>
|
| 225 |
+
</tr>
|
| 226 |
+
</table>
|
| 227 |
+
</div>
|
| 228 |
+
|
| 229 |
+
## Kinematic Planner
|
| 230 |
+
|
| 231 |
+
SONIC includes a kinematic planner for real-time locomotion generation — choose a movement style, steer with keyboard/gamepad, and adjust speed and height on the fly.
|
| 232 |
+
|
| 233 |
+
<div align="center">
|
| 234 |
+
<table>
|
| 235 |
+
<tr>
|
| 236 |
+
<td align="center" colspan="2"><b>In-the-Wild Navigation</b></td>
|
| 237 |
+
</tr>
|
| 238 |
+
<tr>
|
| 239 |
+
<td align="center" colspan="2"><img src="media/planner/planner_in_the_wild_navigation.gif" width="800"></td>
|
| 240 |
+
</tr>
|
| 241 |
+
<tr>
|
| 242 |
+
<td align="center"><b>Run</b></td>
|
| 243 |
+
<td align="center"><b>Happy</b></td>
|
| 244 |
+
</tr>
|
| 245 |
+
<tr>
|
| 246 |
+
<td align="center"><img src="media/planner/planner_run.gif" width="400"></td>
|
| 247 |
+
<td align="center"><img src="media/planner/planner_happy.gif" width="400"></td>
|
| 248 |
+
</tr>
|
| 249 |
+
<tr>
|
| 250 |
+
<td align="center"><b>Stealth</b></td>
|
| 251 |
+
<td align="center"><b>Injured</b></td>
|
| 252 |
+
</tr>
|
| 253 |
+
<tr>
|
| 254 |
+
<td align="center"><img src="media/planner/planner_stealth.gif" width="400"></td>
|
| 255 |
+
<td align="center"><img src="media/planner/planner_injured.gif" width="400"></td>
|
| 256 |
+
</tr>
|
| 257 |
+
<tr>
|
| 258 |
+
<td align="center"><b>Kneeling</b></td>
|
| 259 |
+
<td align="center"><b>Hand Crawling</b></td>
|
| 260 |
+
</tr>
|
| 261 |
+
<tr>
|
| 262 |
+
<td align="center"><img src="media/planner/planner_kneeling.gif" width="400"></td>
|
| 263 |
+
<td align="center"><img src="media/planner/planner_hand_crawling.gif" width="400"></td>
|
| 264 |
+
</tr>
|
| 265 |
+
<tr>
|
| 266 |
+
<td align="center"><b>Elbow Crawling</b></td>
|
| 267 |
+
<td align="center"><b>Boxing</b></td>
|
| 268 |
+
</tr>
|
| 269 |
+
<tr>
|
| 270 |
+
<td align="center"><img src="media/planner/planner_elbow_crawling.gif" width="400"></td>
|
| 271 |
+
<td align="center"><img src="media/planner/planner_boxing.gif" width="400"></td>
|
| 272 |
+
</tr>
|
| 273 |
+
</table>
|
| 274 |
+
</div>
|
| 275 |
+
|
| 276 |
+
## SONIC Training
|
| 277 |
+
|
| 278 |
+
SONIC can be trained from scratch on the [Bones-SEED](https://huggingface.co/datasets/bones-studio/seed)
|
| 279 |
+
motion capture dataset (142K+ motions, ~288 hours, Unitree G1 retargeted), or finetuned
|
| 280 |
+
from the released checkpoint on [Hugging Face](https://huggingface.co/nvidia/GEAR-SONIC).
|
| 281 |
+
|
| 282 |
+
### Quick start
|
| 283 |
+
|
| 284 |
+
```bash
|
| 285 |
+
# Install training dependencies (Isaac Lab must be installed separately — see docs)
|
| 286 |
+
pip install -e "gear_sonic/[training]"
|
| 287 |
+
|
| 288 |
+
# Download checkpoint + SMPL data from Hugging Face
|
| 289 |
+
pip install huggingface_hub
|
| 290 |
+
python download_from_hf.py --training
|
| 291 |
+
|
| 292 |
+
# Download Bones-SEED G1 CSVs from huggingface.co/datasets/bones-studio/seed, then convert and filter
|
| 293 |
+
python gear_sonic/data_process/convert_soma_csv_to_motion_lib.py \
|
| 294 |
+
--input /path/to/bones_seed/g1/csv/ \
|
| 295 |
+
--output data/motion_lib_bones_seed/robot --fps 30 --fps_source 120 --individual --num_workers 16
|
| 296 |
+
python gear_sonic/data_process/filter_and_copy_bones_data.py \
|
| 297 |
+
--source data/motion_lib_bones_seed/robot --dest data/motion_lib_bones_seed/robot_filtered
|
| 298 |
+
|
| 299 |
+
# Finetune from released checkpoint (64+ GPUs recommended)
|
| 300 |
+
accelerate launch --num_processes=8 gear_sonic/train_agent_trl.py \
|
| 301 |
+
+exp=manager/universal_token/all_modes/sonic_release \
|
| 302 |
+
+checkpoint=sonic_release/last.pt \
|
| 303 |
+
num_envs=4096 headless=True \
|
| 304 |
+
++manager_env.commands.motion.motion_lib_cfg.motion_file=data/motion_lib_bones_seed/robot_filtered \
|
| 305 |
+
++manager_env.commands.motion.motion_lib_cfg.smpl_motion_file=data/smpl_filtered
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
For the full guide including multi-node training, evaluation, ONNX export, and SOMA encoder setup:
|
| 309 |
+
📖 [Installation (Training)](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/installation_training.html) |
|
| 310 |
+
[Training Guide](https://nvlabs.github.io/GR00T-WholeBodyControl/user_guide/training.html)
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
## TODOs
|
| 314 |
+
|
| 315 |
+
- [x] Release pretrained SONIC policy checkpoints
|
| 316 |
+
- [x] Open source C++ inference stack
|
| 317 |
+
- [x] Setup documentation
|
| 318 |
+
- [x] Open source teleoperation stack and demonstration scripts
|
| 319 |
+
- [x] Release training scripts and recipes for motion imitation and fine-tuning
|
| 320 |
+
- [x] Open source large-scale data collection workflows and fine-tuning VLA scripts.
|
| 321 |
+
- [x] Publish additional preprocessed large-scale human motion datasets
|
| 322 |
+
|
| 323 |
+
|
| 324 |
+
|
| 325 |
+
## What's Included
|
| 326 |
+
|
| 327 |
+
This release includes:
|
| 328 |
+
|
| 329 |
+
- **`gear_sonic_deploy`**: C++ inference stack for deploying SONIC policies on real hardware
|
| 330 |
+
- **`gear_sonic`**: Full SONIC training stack — PPO training, data processing pipeline, and configuration system for training on Bones-SEED and custom motion datasets
|
| 331 |
+
- **`motionbricks`**: Preview release of the MotionBricks real-time latent generative stack — interactive G1 demo, pretrained checkpoints, synthetic training code, and motion-representation docs
|
| 332 |
+
|
| 333 |
+
### Setup
|
| 334 |
+
|
| 335 |
+
> **Git LFS required.** This repo contains large binary assets (meshes, ONNX
|
| 336 |
+
> models). Without Git LFS, you will get small pointer files instead of actual
|
| 337 |
+
> data, causing silent failures. Install Git LFS first if you don't have it:
|
| 338 |
+
> `sudo apt install git-lfs && git lfs install`
|
| 339 |
+
>
|
| 340 |
+
> MotionBricks pretrained checkpoints are skipped by default to avoid an extra
|
| 341 |
+
> ~2.2 GiB download during normal monorepo setup. MotionBricks GIFs and meshes
|
| 342 |
+
> still download normally. Fetch the checkpoints explicitly if you plan to run
|
| 343 |
+
> the MotionBricks demo.
|
| 344 |
+
|
| 345 |
+
```bash
|
| 346 |
+
git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
|
| 347 |
+
cd GR00T-WholeBodyControl
|
| 348 |
+
git lfs pull
|
| 349 |
+
|
| 350 |
+
# Optional: fetch MotionBricks pretrained checkpoints.
|
| 351 |
+
git lfs pull --include="motionbricks/out/**" --exclude=""
|
| 352 |
+
|
| 353 |
+
# Verify your environment
|
| 354 |
+
python check_environment.py
|
| 355 |
+
```
|
| 356 |
+
|
| 357 |
+
### Which environment do I need?
|
| 358 |
+
|
| 359 |
+
| I want to... | Environment | How to install |
|
| 360 |
+
|---|---|---|
|
| 361 |
+
| **Train / finetune SONIC** | Isaac Lab's Python env | [Install Isaac Lab](https://isaac-sim.github.io/IsaacLab/main/source/setup/installation/index.html), then `pip install -e "gear_sonic/[training]"` |
|
| 362 |
+
| **Run MuJoCo simulation** | `.venv_sim` (auto-created) | `bash install_scripts/install_mujoco_sim.sh` |
|
| 363 |
+
| **VR teleoperation** | `.venv_teleop` (auto-created) | `bash install_scripts/install_pico.sh` |
|
| 364 |
+
| **Collect data** | `.venv_data_collection` (auto-created) | `bash install_scripts/install_data_collection.sh` |
|
| 365 |
+
| **Deploy on real robot** | C++ build | See [deployment docs](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/installation_deploy.html) |
|
| 366 |
+
|
| 367 |
+
Each use case has its own lightweight environment. The install scripts use `uv`
|
| 368 |
+
and create isolated venvs automatically — you don't need to manage them manually.
|
| 369 |
+
Training is the only one that requires Isaac Lab (installed separately).
|
| 370 |
+
|
| 371 |
+
## Documentation
|
| 372 |
+
|
| 373 |
+
📚 **[Full Documentation](https://nvlabs.github.io/GR00T-WholeBodyControl/)**
|
| 374 |
+
|
| 375 |
+
### Getting Started
|
| 376 |
+
- [Installation Guide](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/installation_deploy.html)
|
| 377 |
+
- [Quick Start](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/quickstart.html)
|
| 378 |
+
- [VR Teleoperation Setup](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/vr_teleop_setup.html)
|
| 379 |
+
|
| 380 |
+
### Tutorials
|
| 381 |
+
- [Keyboard Control](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/keyboard.html)
|
| 382 |
+
- [Gamepad Control](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/gamepad.html)
|
| 383 |
+
- [ZMQ Communication](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/zmq.html)
|
| 384 |
+
- [ZMQ Manager / PICO VR](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vr_wholebody_teleop.html)
|
| 385 |
+
|
| 386 |
+
### Training
|
| 387 |
+
- [Installation (Training)](https://nvlabs.github.io/GR00T-WholeBodyControl/getting_started/installation_training.html)
|
| 388 |
+
- [Training Guide](https://nvlabs.github.io/GR00T-WholeBodyControl/user_guide/training.html)
|
| 389 |
+
- [Training Data](https://nvlabs.github.io/GR00T-WholeBodyControl/user_guide/training_data.html)
|
| 390 |
+
|
| 391 |
+
### Best Practices
|
| 392 |
+
- [Teleoperation](https://nvlabs.github.io/GR00T-WholeBodyControl/user_guide/teleoperation.html)
|
| 393 |
+
|
| 394 |
+
|
| 395 |
+
|
| 396 |
+
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
---
|
| 400 |
+
|
| 401 |
+
## Citation
|
| 402 |
+
|
| 403 |
+
If you use GEAR-SONIC in your research, please cite:
|
| 404 |
+
|
| 405 |
+
```bibtex
|
| 406 |
+
@article{luo2025sonic,
|
| 407 |
+
title={SONIC: Supersizing Motion Tracking for Natural Humanoid Whole-Body Control},
|
| 408 |
+
author={Luo, Zhengyi and Yuan, Ye and Wang, Tingwu and Li, Chenran and Chen, Sirui and Casta\~neda, Fernando and Cao, Zi-Ang and Li, Jiefeng and Minor, David and Ben, Qingwei and Da, Xingye and Ding, Runyu and Hogg, Cyrus and Song, Lina and Lim, Edy and Jeong, Eugene and He, Tairan and Xue, Haoru and Xiao, Wenli and Wang, Zi and Yuen, Simon and Kautz, Jan and Chang, Yan and Iqbal, Umar and Fan, Linxi and Zhu, Yuke},
|
| 409 |
+
journal={arXiv preprint arXiv:2511.07820},
|
| 410 |
+
year={2025}
|
| 411 |
+
}
|
| 412 |
+
```
|
| 413 |
+
|
| 414 |
+
---
|
| 415 |
+
|
| 416 |
+
## License
|
| 417 |
+
|
| 418 |
+
This project uses dual licensing:
|
| 419 |
+
|
| 420 |
+
- **Source Code**: Licensed under Apache License 2.0 - applies to all code, scripts, and software components in this repository
|
| 421 |
+
- **Model Weights**: Licensed under NVIDIA Open Model License - applies to all trained model checkpoints and weights
|
| 422 |
+
|
| 423 |
+
See [LICENSE](LICENSE) for the complete dual-license text.
|
| 424 |
+
|
| 425 |
+
Please review both licenses before using this project. The NVIDIA Open Model License permits commercial use with attribution and requires compliance with NVIDIA's Trustworthy AI terms.
|
| 426 |
+
|
| 427 |
+
All required legal documents, including the Apache 2.0 license, 3rd-party attributions, and DCO language, are consolidated in the /legal folder of this repository.
|
| 428 |
+
|
| 429 |
+
---
|
| 430 |
+
|
| 431 |
+
## Support
|
| 432 |
+
|
| 433 |
+
For questions and issues, please contact the GEAR WBC team at [gear-wbc@nvidia.com](mailto:gear-wbc@nvidia.com) to provide feedback!
|
| 434 |
+
|
| 435 |
+
## MotionBricks
|
| 436 |
+
|
| 437 |
+
<p style="font-size: 1.2em;">
|
| 438 |
+
<a href="https://nvlabs.github.io/motionbricks/"><strong>Project page</strong></a> |
|
| 439 |
+
<a href="motionbricks/README.md"><strong>Subproject README</strong></a>
|
| 440 |
+
</p>
|
| 441 |
+
|
| 442 |
+
<div align="center">
|
| 443 |
+
<img src="motionbricks/assets/gifs/teaser_animation.gif" width="400">
|
| 444 |
+
<img src="motionbricks/assets/gifs/teaser_robotics.gif" width="400">
|
| 445 |
+
</div>
|
| 446 |
+
|
| 447 |
+
MotionBricks is a real-time generative framework that transforms interactive motion control for animation and robotics. It combines a large-scale latent backbone with intuitive "smart primitives" to deliver high-quality, zero-shot motion synthesis at 15,000 FPS — complementing the tracking-based GEAR-SONIC controllers in this repo.
|
| 448 |
+
|
| 449 |
+
This preview release ships an interactive G1 demo (keyboard-driven, MuJoCo viewer), pretrained checkpoints (VQVAE · pose · root), a synthetic training pipeline, and motion-representation docs. Its pretrained checkpoints are opt-in for monorepo clones; run `git lfs pull --include="motionbricks/out/**" --exclude=""` from the repo root before using the demo. A full release — fully embedded in the GEAR-SONIC pipeline — is targeted for approximately one month out. See [`motionbricks/README.md`](motionbricks/README.md) for setup, demo, and training instructions.
|
| 450 |
+
|
| 451 |
+
## Decoupled WBC
|
| 452 |
+
|
| 453 |
+
For the Decoupled WBC used in GR00T N1.5 and N1.6 models, please refer to the [Decoupled WBC documentation](docs/source/references/decoupled_wbc.md).
|
| 454 |
+
|
| 455 |
+
|
| 456 |
+
## Acknowledgments
|
| 457 |
+
We would like to acknowledge the following projects from which parts of the code in this repo are derived from:
|
| 458 |
+
- [Beyond Mimic](https://github.com/HybridRobotics/whole_body_tracking)
|
| 459 |
+
- [Isaac Lab](https://github.com/isaac-sim/IsaacLab)
|
GR00T-WholeBodyControl/SECURITY.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Security Policy
|
| 2 |
+
|
| 3 |
+
## Reporting a Vulnerability
|
| 4 |
+
|
| 5 |
+
NVIDIA is committed to the security of our products. If you believe you have
|
| 6 |
+
found a security vulnerability in this project, please report it through
|
| 7 |
+
[NVIDIA's coordinated vulnerability disclosure process](https://www.nvidia.com/en-us/security/)
|
| 8 |
+
rather than opening a public issue.
|
| 9 |
+
|
| 10 |
+
You can also email [psirt@nvidia.com](mailto:psirt@nvidia.com).
|
GR00T-WholeBodyControl/check_environment.py
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Pre-flight environment check for GR00T-WholeBodyControl.
|
| 3 |
+
|
| 4 |
+
Run this before training or deployment to verify all prerequisites are met.
|
| 5 |
+
|
| 6 |
+
Usage:
|
| 7 |
+
python check_environment.py # Check everything
|
| 8 |
+
python check_environment.py --training # Training checks only
|
| 9 |
+
python check_environment.py --deploy # Deployment checks only
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
import importlib
|
| 13 |
+
import os
|
| 14 |
+
import platform
|
| 15 |
+
import shutil
|
| 16 |
+
import subprocess
|
| 17 |
+
import sys
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def check(name, passed, msg_pass="", msg_fail=""):
|
| 21 |
+
status = "PASS" if passed else "FAIL"
|
| 22 |
+
symbol = "[+]" if passed else "[X]"
|
| 23 |
+
detail = msg_pass if passed else msg_fail
|
| 24 |
+
print(f" {symbol} {name}: {detail}" if detail else f" {symbol} {name}")
|
| 25 |
+
return passed
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
def check_python(training=False):
|
| 29 |
+
v = sys.version_info
|
| 30 |
+
version_str = f"{v.major}.{v.minor}.{v.micro}"
|
| 31 |
+
if training:
|
| 32 |
+
ok = v.major == 3 and v.minor == 11
|
| 33 |
+
return check(
|
| 34 |
+
"Python version",
|
| 35 |
+
ok,
|
| 36 |
+
msg_pass=version_str,
|
| 37 |
+
msg_fail=f"{version_str} (training requires 3.11.x — Isaac Lab requirement)",
|
| 38 |
+
)
|
| 39 |
+
else:
|
| 40 |
+
ok = v.major == 3 and v.minor >= 10
|
| 41 |
+
return check(
|
| 42 |
+
"Python version",
|
| 43 |
+
ok,
|
| 44 |
+
msg_pass=version_str,
|
| 45 |
+
msg_fail=f"{version_str} (need 3.10+)",
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def check_git_lfs():
|
| 50 |
+
lfs_installed = shutil.which("git-lfs") is not None
|
| 51 |
+
if not lfs_installed:
|
| 52 |
+
return check("Git LFS", False, msg_fail="not installed (sudo apt install git-lfs)")
|
| 53 |
+
|
| 54 |
+
# Check if LFS files are pulled (sample an actual LFS-tracked mesh file)
|
| 55 |
+
mesh_path = "gear_sonic/data/assets/robot_description/urdf/g1/meshes"
|
| 56 |
+
stl_files = [os.path.join(mesh_path, f) for f in os.listdir(mesh_path) if f.endswith(".STL")] if os.path.isdir(mesh_path) else []
|
| 57 |
+
sample_file = stl_files[0] if stl_files else "decoupled_wbc/sim2mujoco/resources/robots/g1/policy/GR00T-WholeBodyControl-Balance.onnx"
|
| 58 |
+
if os.path.exists(sample_file):
|
| 59 |
+
size = os.path.getsize(sample_file)
|
| 60 |
+
if size < 1000:
|
| 61 |
+
return check(
|
| 62 |
+
"Git LFS",
|
| 63 |
+
False,
|
| 64 |
+
msg_fail=f"{sample_file} is {size} bytes (LFS pointer — run 'git lfs pull')",
|
| 65 |
+
)
|
| 66 |
+
return check("Git LFS", True, msg_pass="installed, files pulled")
|
| 67 |
+
return check("Git LFS", True, msg_pass="installed")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def check_cuda():
|
| 71 |
+
try:
|
| 72 |
+
import torch
|
| 73 |
+
|
| 74 |
+
if torch.cuda.is_available():
|
| 75 |
+
device_name = torch.cuda.get_device_name(0)
|
| 76 |
+
cuda_version = torch.version.cuda
|
| 77 |
+
return check("CUDA", True, msg_pass=f"{device_name} (CUDA {cuda_version})")
|
| 78 |
+
else:
|
| 79 |
+
return check("CUDA", False, msg_fail="torch.cuda.is_available() = False")
|
| 80 |
+
except ImportError:
|
| 81 |
+
return check("CUDA", False, msg_fail="PyTorch not installed")
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def check_torch():
|
| 85 |
+
try:
|
| 86 |
+
import torch
|
| 87 |
+
|
| 88 |
+
return check("PyTorch", True, msg_pass=torch.__version__)
|
| 89 |
+
except ImportError:
|
| 90 |
+
return check(
|
| 91 |
+
"PyTorch",
|
| 92 |
+
False,
|
| 93 |
+
msg_fail="not installed (pip install torch)",
|
| 94 |
+
)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def check_isaaclab():
|
| 98 |
+
try:
|
| 99 |
+
import isaaclab
|
| 100 |
+
|
| 101 |
+
version = getattr(isaaclab, "__version__", "unknown")
|
| 102 |
+
return check("Isaac Lab", True, msg_pass=version)
|
| 103 |
+
except ImportError:
|
| 104 |
+
return check(
|
| 105 |
+
"Isaac Lab",
|
| 106 |
+
False,
|
| 107 |
+
msg_fail="not installed — see https://isaac-sim.github.io/IsaacLab/main/source/setup/installation/index.html",
|
| 108 |
+
)
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def check_gear_sonic():
|
| 112 |
+
try:
|
| 113 |
+
from importlib.metadata import version as get_version
|
| 114 |
+
ver = get_version("gear_sonic")
|
| 115 |
+
return check("gear_sonic", True, msg_pass=f"installed ({ver})")
|
| 116 |
+
except ImportError:
|
| 117 |
+
return check(
|
| 118 |
+
"gear_sonic",
|
| 119 |
+
False,
|
| 120 |
+
msg_fail="not installed (pip install -e 'gear_sonic/[training]')",
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
|
| 124 |
+
def check_training_deps():
|
| 125 |
+
results = []
|
| 126 |
+
for pkg, pip_name in [
|
| 127 |
+
("hydra", "hydra-core"),
|
| 128 |
+
("trl", "trl"),
|
| 129 |
+
("transformers", "transformers"),
|
| 130 |
+
("accelerate", "accelerate"),
|
| 131 |
+
("wandb", "wandb"),
|
| 132 |
+
]:
|
| 133 |
+
try:
|
| 134 |
+
mod = importlib.import_module(pkg)
|
| 135 |
+
version = getattr(mod, "__version__", "ok")
|
| 136 |
+
results.append(check(pip_name, True, msg_pass=version))
|
| 137 |
+
except ImportError:
|
| 138 |
+
results.append(
|
| 139 |
+
check(pip_name, False, msg_fail=f"not installed (pip install {pip_name})")
|
| 140 |
+
)
|
| 141 |
+
return all(results)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def check_tensorrt():
|
| 145 |
+
trt_root = os.environ.get("TensorRT_ROOT", "")
|
| 146 |
+
if not trt_root:
|
| 147 |
+
return check(
|
| 148 |
+
"TensorRT",
|
| 149 |
+
False,
|
| 150 |
+
msg_fail="TensorRT_ROOT not set (export TensorRT_ROOT=$HOME/TensorRT)",
|
| 151 |
+
)
|
| 152 |
+
if not os.path.isdir(trt_root):
|
| 153 |
+
return check("TensorRT", False, msg_fail=f"TensorRT_ROOT={trt_root} does not exist")
|
| 154 |
+
|
| 155 |
+
# Check for the library
|
| 156 |
+
lib_dir = os.path.join(trt_root, "lib")
|
| 157 |
+
if os.path.isdir(lib_dir):
|
| 158 |
+
libs = [f for f in os.listdir(lib_dir) if "nvinfer" in f and f.endswith(".so")]
|
| 159 |
+
if libs:
|
| 160 |
+
# Try to extract version from filename
|
| 161 |
+
for lib in libs:
|
| 162 |
+
if "nvinfer.so." in lib:
|
| 163 |
+
version = lib.split("nvinfer.so.")[-1]
|
| 164 |
+
return check("TensorRT", True, msg_pass=f"{version} at {trt_root}")
|
| 165 |
+
return check("TensorRT", True, msg_pass=f"found at {trt_root}")
|
| 166 |
+
|
| 167 |
+
return check("TensorRT", False, msg_fail=f"libnvinfer not found in {lib_dir}")
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
def check_disk_space():
|
| 171 |
+
stat = os.statvfs(".")
|
| 172 |
+
free_gb = (stat.f_bavail * stat.f_frsize) / (1024**3)
|
| 173 |
+
ok = free_gb > 10
|
| 174 |
+
return check(
|
| 175 |
+
"Disk space",
|
| 176 |
+
ok,
|
| 177 |
+
msg_pass=f"{free_gb:.0f} GB free",
|
| 178 |
+
msg_fail=f"{free_gb:.1f} GB free (recommend 10+ GB)",
|
| 179 |
+
)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def main():
|
| 183 |
+
mode = "all"
|
| 184 |
+
if "--training" in sys.argv:
|
| 185 |
+
mode = "training"
|
| 186 |
+
elif "--deploy" in sys.argv:
|
| 187 |
+
mode = "deploy"
|
| 188 |
+
|
| 189 |
+
print(f"GR00T-WholeBodyControl Environment Check")
|
| 190 |
+
print(f"Platform: {platform.system()} {platform.machine()}")
|
| 191 |
+
print(f"Python: {sys.executable}")
|
| 192 |
+
print()
|
| 193 |
+
|
| 194 |
+
all_pass = True
|
| 195 |
+
|
| 196 |
+
# Basic checks (always run)
|
| 197 |
+
print("Basic:")
|
| 198 |
+
all_pass &= check_python(training=(mode in ("all", "training")))
|
| 199 |
+
all_pass &= check_git_lfs()
|
| 200 |
+
all_pass &= check_cuda()
|
| 201 |
+
all_pass &= check_torch()
|
| 202 |
+
all_pass &= check_disk_space()
|
| 203 |
+
print()
|
| 204 |
+
|
| 205 |
+
if mode in ("all", "training"):
|
| 206 |
+
print("Training:")
|
| 207 |
+
all_pass &= check_isaaclab()
|
| 208 |
+
all_pass &= check_gear_sonic()
|
| 209 |
+
all_pass &= check_training_deps()
|
| 210 |
+
print()
|
| 211 |
+
|
| 212 |
+
if mode in ("all", "deploy"):
|
| 213 |
+
print("Deployment:")
|
| 214 |
+
all_pass &= check_tensorrt()
|
| 215 |
+
print()
|
| 216 |
+
|
| 217 |
+
if all_pass:
|
| 218 |
+
print("All checks passed.")
|
| 219 |
+
else:
|
| 220 |
+
print("Some checks failed. See above for details.")
|
| 221 |
+
sys.exit(1)
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
if __name__ == "__main__":
|
| 225 |
+
main()
|
GR00T-WholeBodyControl/decoupled_wbc/pyproject.toml
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=67", "wheel", "pip"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
+
[project]
|
| 6 |
+
name = "decoupled_wbc"
|
| 7 |
+
dynamic = ["version"]
|
| 8 |
+
readme = "../README.md"
|
| 9 |
+
classifiers = [
|
| 10 |
+
"Intended Audience :: Science/Research",
|
| 11 |
+
"Development Status :: 3 - Alpha",
|
| 12 |
+
"License :: OSI Approved :: Apache Software License",
|
| 13 |
+
"Programming Language :: Python :: 3",
|
| 14 |
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
| 15 |
+
]
|
| 16 |
+
authors = [
|
| 17 |
+
{name = "NVIDIA Gear Lab"}
|
| 18 |
+
]
|
| 19 |
+
requires-python = ">=3.10"
|
| 20 |
+
dependencies = [
|
| 21 |
+
"numpy==1.26.4",
|
| 22 |
+
"scipy==1.15.3",
|
| 23 |
+
"torch",
|
| 24 |
+
]
|
| 25 |
+
license = {file = "../LICENSE"}
|
| 26 |
+
|
| 27 |
+
[project.optional-dependencies]
|
| 28 |
+
# Full: all dependencies for the complete decoupled_wbc project
|
| 29 |
+
# Usage: pip install -e "decoupled_wbc[full]"
|
| 30 |
+
full = [
|
| 31 |
+
"av>=14.2",
|
| 32 |
+
"pyttsx3==2.90",
|
| 33 |
+
"matplotlib",
|
| 34 |
+
"hydra-core",
|
| 35 |
+
"ray[default]",
|
| 36 |
+
"click",
|
| 37 |
+
"gymnasium",
|
| 38 |
+
"mujoco",
|
| 39 |
+
"termcolor",
|
| 40 |
+
"flask",
|
| 41 |
+
"python-socketio>=5.13.0",
|
| 42 |
+
"flask_socketio",
|
| 43 |
+
"loguru",
|
| 44 |
+
"meshcat",
|
| 45 |
+
"meshcat-shapes",
|
| 46 |
+
"onnxruntime",
|
| 47 |
+
"rerun-sdk==0.21.0",
|
| 48 |
+
"pygame",
|
| 49 |
+
"sshkeyboard",
|
| 50 |
+
"msgpack",
|
| 51 |
+
"msgpack-numpy",
|
| 52 |
+
"pyzmq",
|
| 53 |
+
"PyQt6; platform_machine != 'aarch64'",
|
| 54 |
+
"pin",
|
| 55 |
+
"pin-pink",
|
| 56 |
+
"pyrealsense2; sys_platform != 'darwin'",
|
| 57 |
+
"pyrealsense2-macosx; sys_platform == 'darwin'",
|
| 58 |
+
"qpsolvers[osqp,quadprog]",
|
| 59 |
+
"tyro",
|
| 60 |
+
"cv-bridge",
|
| 61 |
+
"lark",
|
| 62 |
+
"lerobot @ git+https://github.com/huggingface/lerobot.git@a445d9c9da6bea99a8972daa4fe1fdd053d711d2",
|
| 63 |
+
"datasets==3.6.0",
|
| 64 |
+
"pandas",
|
| 65 |
+
"evdev; sys_platform == 'linux'",
|
| 66 |
+
"pyyaml",
|
| 67 |
+
]
|
| 68 |
+
dev = [
|
| 69 |
+
"pytest==7.4.0",
|
| 70 |
+
"build",
|
| 71 |
+
"setuptools",
|
| 72 |
+
"wheel",
|
| 73 |
+
"ruff",
|
| 74 |
+
"black",
|
| 75 |
+
"ipdb",
|
| 76 |
+
]
|
| 77 |
+
|
| 78 |
+
[project.scripts]
|
| 79 |
+
decoupled_wbc = "decoupled_wbc.control.teleop.gui.cli:cli"
|
| 80 |
+
|
| 81 |
+
[tool.setuptools.packages.find]
|
| 82 |
+
where = [".."]
|
| 83 |
+
include = ["decoupled_wbc*"]
|
| 84 |
+
|
| 85 |
+
[tool.setuptools]
|
| 86 |
+
include-package-data = true
|
| 87 |
+
|
| 88 |
+
[tool.setuptools.package-data]
|
| 89 |
+
decoupled_wbc = ["py.typed", "**/*.json", "**/*.yaml"]
|
| 90 |
+
|
| 91 |
+
[tool.setuptools.dynamic]
|
| 92 |
+
version = {attr = "decoupled_wbc.version.VERSION"}
|
| 93 |
+
|
GR00T-WholeBodyControl/docs/requirements.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Sphinx documentation build dependencies
|
| 2 |
+
sphinx>=7.0,<9.0
|
| 3 |
+
sphinx-book-theme>=1.1.0
|
| 4 |
+
myst-parser>=3.0.0
|
| 5 |
+
autodocsumm>=0.2.12
|
| 6 |
+
sphinxemoji>=0.3.1
|
| 7 |
+
sphinxcontrib-bibtex>=2.6.0
|
| 8 |
+
sphinxcontrib-video>=0.2.1
|
| 9 |
+
sphinx-copybutton>=0.5.2
|
| 10 |
+
sphinx-design>=0.6.0
|
GR00T-WholeBodyControl/download_from_hf.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Download GEAR-SONIC model checkpoints and training data from Hugging Face Hub.
|
| 4 |
+
|
| 5 |
+
Repository: https://huggingface.co/nvidia/GEAR-SONIC
|
| 6 |
+
|
| 7 |
+
Usage:
|
| 8 |
+
python download_from_hf.py # ONNX models for deployment
|
| 9 |
+
python download_from_hf.py --low-latency # Low-latency ONNX models
|
| 10 |
+
python download_from_hf.py --sonic-v1-1 # SONIC v1.1 ONNX models
|
| 11 |
+
python download_from_hf.py --training # PyTorch checkpoint + SMPL data
|
| 12 |
+
python download_from_hf.py --sample # Sample data only (quick start)
|
| 13 |
+
python download_from_hf.py --output-dir /path # custom output directory
|
| 14 |
+
python download_from_hf.py --no-planner # skip planner model
|
| 15 |
+
"""
|
| 16 |
+
|
| 17 |
+
import argparse
|
| 18 |
+
import os
|
| 19 |
+
import shutil
|
| 20 |
+
import subprocess
|
| 21 |
+
import sys
|
| 22 |
+
from pathlib import Path
|
| 23 |
+
|
| 24 |
+
REPO_ID = "nvidia/GEAR-SONIC"
|
| 25 |
+
|
| 26 |
+
# (filename in HF repo, local destination relative to output_dir)
|
| 27 |
+
POLICY_FILES = [
|
| 28 |
+
("model_encoder.onnx", "policy/release/model_encoder.onnx"),
|
| 29 |
+
("model_decoder.onnx", "policy/release/model_decoder.onnx"),
|
| 30 |
+
("observation_config.yaml", "policy/release/observation_config.yaml"),
|
| 31 |
+
]
|
| 32 |
+
|
| 33 |
+
LOW_LATENCY_POLICY_FILES = [
|
| 34 |
+
("low_latency/model_encoder.onnx", "policy/low_latency/model_encoder.onnx"),
|
| 35 |
+
("low_latency/model_decoder.onnx", "policy/low_latency/model_decoder.onnx"),
|
| 36 |
+
("low_latency/observation_config.yaml", "policy/low_latency/observation_config.yaml"),
|
| 37 |
+
]
|
| 38 |
+
|
| 39 |
+
SONIC_V1_1_POLICY_FILES = [
|
| 40 |
+
("sonic_v1_1/model_encoder.onnx", "policy/sonic_v1_1/model_encoder.onnx"),
|
| 41 |
+
("sonic_v1_1/model_decoder.onnx", "policy/sonic_v1_1/model_decoder.onnx"),
|
| 42 |
+
(
|
| 43 |
+
"sonic_v1_1/observation_config.yaml",
|
| 44 |
+
"policy/sonic_v1_1/observation_config.yaml",
|
| 45 |
+
),
|
| 46 |
+
]
|
| 47 |
+
|
| 48 |
+
PLANNER_FILE = ("planner_sonic.onnx", "planner/target_vel/V2/planner_sonic.onnx")
|
| 49 |
+
|
| 50 |
+
TRAINING_FILES = [
|
| 51 |
+
("sonic_release/last.pt", "sonic_release/last.pt"),
|
| 52 |
+
("sonic_release/config.yaml", "sonic_release/config.yaml"),
|
| 53 |
+
]
|
| 54 |
+
|
| 55 |
+
LOW_LATENCY_TRAINING_FILES = [
|
| 56 |
+
("low_latency/last.pt", "low_latency/last.pt"),
|
| 57 |
+
("low_latency/config.yaml", "low_latency/config.yaml"),
|
| 58 |
+
("low_latency/model_config.yaml", "low_latency/model_config.yaml"),
|
| 59 |
+
]
|
| 60 |
+
|
| 61 |
+
SONIC_V1_1_TRAINING_FILES = [
|
| 62 |
+
("sonic_v1_1/last.pt", "sonic_v1_1/last.pt"),
|
| 63 |
+
("sonic_v1_1/config.yaml", "sonic_v1_1/config.yaml"),
|
| 64 |
+
("sonic_v1_1/model_config.yaml", "sonic_v1_1/model_config.yaml"),
|
| 65 |
+
]
|
| 66 |
+
|
| 67 |
+
SMPL_TAR_PARTS_PREFIX = "bones_seed_smpl/bones_seed_smpl.tar.part_"
|
| 68 |
+
SMPL_TAR_PARTS = [f"{SMPL_TAR_PARTS_PREFIX}a{c}" for c in "abcdefg"]
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def parse_args():
|
| 72 |
+
parser = argparse.ArgumentParser(
|
| 73 |
+
description="Download GEAR-SONIC checkpoints from Hugging Face Hub"
|
| 74 |
+
)
|
| 75 |
+
parser.add_argument(
|
| 76 |
+
"--output-dir",
|
| 77 |
+
type=Path,
|
| 78 |
+
default=None,
|
| 79 |
+
help=(
|
| 80 |
+
"Directory to save files. "
|
| 81 |
+
"Defaults to gear_sonic_deploy/ (deploy) or repo root (training)."
|
| 82 |
+
),
|
| 83 |
+
)
|
| 84 |
+
parser.add_argument(
|
| 85 |
+
"--no-planner",
|
| 86 |
+
action="store_true",
|
| 87 |
+
help="Skip downloading the kinematic planner ONNX model",
|
| 88 |
+
)
|
| 89 |
+
parser.add_argument(
|
| 90 |
+
"--training",
|
| 91 |
+
action="store_true",
|
| 92 |
+
help="Download training checkpoint + SMPL motion data (~30 GB)",
|
| 93 |
+
)
|
| 94 |
+
variant_group = parser.add_mutually_exclusive_group()
|
| 95 |
+
variant_group.add_argument(
|
| 96 |
+
"--low-latency",
|
| 97 |
+
action="store_true",
|
| 98 |
+
help=(
|
| 99 |
+
"Download the low-latency SONIC variant. For deployment, files are "
|
| 100 |
+
"placed under gear_sonic_deploy/policy/low_latency/. With --training, "
|
| 101 |
+
"downloads low_latency/last.pt and its configs."
|
| 102 |
+
),
|
| 103 |
+
)
|
| 104 |
+
variant_group.add_argument(
|
| 105 |
+
"--sonic-v1-1",
|
| 106 |
+
dest="sonic_v1_1",
|
| 107 |
+
action="store_true",
|
| 108 |
+
help=(
|
| 109 |
+
"Download the SONIC v1.1 teleoperation variant with "
|
| 110 |
+
"robot-heading-normalized targets and "
|
| 111 |
+
"wrist-pose augmentation. For deployment, files are placed under "
|
| 112 |
+
"gear_sonic_deploy/policy/sonic_v1_1/. With --training, downloads "
|
| 113 |
+
"sonic_v1_1/last.pt and its configs."
|
| 114 |
+
),
|
| 115 |
+
)
|
| 116 |
+
parser.add_argument(
|
| 117 |
+
"--sample",
|
| 118 |
+
action="store_true",
|
| 119 |
+
help="Download sample motion data only (1 walking sequence, ~4 MB)",
|
| 120 |
+
)
|
| 121 |
+
parser.add_argument(
|
| 122 |
+
"--no-smpl",
|
| 123 |
+
action="store_true",
|
| 124 |
+
help="With --training, skip SMPL data download (checkpoint only)",
|
| 125 |
+
)
|
| 126 |
+
parser.add_argument(
|
| 127 |
+
"--token",
|
| 128 |
+
default=None,
|
| 129 |
+
help="Hugging Face token (or set HF_TOKEN env var / run `hf auth login`)",
|
| 130 |
+
)
|
| 131 |
+
return parser.parse_args()
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def _ensure_huggingface_hub():
|
| 135 |
+
try:
|
| 136 |
+
from huggingface_hub import hf_hub_download, snapshot_download
|
| 137 |
+
return hf_hub_download, snapshot_download
|
| 138 |
+
except ImportError:
|
| 139 |
+
print("huggingface_hub is not installed. Install it with:")
|
| 140 |
+
print(" pip install huggingface_hub")
|
| 141 |
+
sys.exit(1)
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def download_file(hf_hub_download, repo_id, hf_filename, local_dest, token=None):
|
| 145 |
+
"""Download hf_filename from the Hub and place it at local_dest."""
|
| 146 |
+
print(f" Downloading {hf_filename} ...", flush=True)
|
| 147 |
+
cached = hf_hub_download(
|
| 148 |
+
repo_id=repo_id,
|
| 149 |
+
filename=hf_filename,
|
| 150 |
+
token=token,
|
| 151 |
+
)
|
| 152 |
+
local_dest.parent.mkdir(parents=True, exist_ok=True)
|
| 153 |
+
shutil.copy2(cached, local_dest)
|
| 154 |
+
print(f" -> {local_dest}")
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def download_and_extract_smpl(hf_hub_download, repo_id, output_dir, token=None):
|
| 158 |
+
"""Download split tar parts and extract SMPL data."""
|
| 159 |
+
parts_dir = output_dir / "bones_seed_smpl"
|
| 160 |
+
parts_dir.mkdir(parents=True, exist_ok=True)
|
| 161 |
+
|
| 162 |
+
print(f" Downloading {len(SMPL_TAR_PARTS)} parts (~30 GB total) ...", flush=True)
|
| 163 |
+
part_paths = []
|
| 164 |
+
for hf_filename in SMPL_TAR_PARTS:
|
| 165 |
+
local_name = Path(hf_filename).name
|
| 166 |
+
local_dest = parts_dir / local_name
|
| 167 |
+
if local_dest.exists():
|
| 168 |
+
print(f" (cached) {local_name}")
|
| 169 |
+
part_paths.append(local_dest)
|
| 170 |
+
continue
|
| 171 |
+
cached = hf_hub_download(repo_id=repo_id, filename=hf_filename, token=token)
|
| 172 |
+
shutil.copy2(cached, local_dest)
|
| 173 |
+
part_paths.append(local_dest)
|
| 174 |
+
print(f" Downloaded {local_name}")
|
| 175 |
+
|
| 176 |
+
# Reassemble and extract
|
| 177 |
+
data_dir = output_dir / "data"
|
| 178 |
+
data_dir.mkdir(parents=True, exist_ok=True)
|
| 179 |
+
print(f" Extracting to {data_dir}/smpl_filtered/ ...", flush=True)
|
| 180 |
+
|
| 181 |
+
# cat parts | tar xf - -C data/
|
| 182 |
+
cat_cmd = f"cat {parts_dir}/bones_seed_smpl.tar.part_*"
|
| 183 |
+
tar_cmd = f"tar xf - -C {data_dir}"
|
| 184 |
+
result = subprocess.run(
|
| 185 |
+
f"{cat_cmd} | {tar_cmd}",
|
| 186 |
+
shell=True,
|
| 187 |
+
capture_output=True,
|
| 188 |
+
text=True,
|
| 189 |
+
)
|
| 190 |
+
if result.returncode != 0:
|
| 191 |
+
print(f" ERROR: Extraction failed: {result.stderr}")
|
| 192 |
+
sys.exit(1)
|
| 193 |
+
|
| 194 |
+
# Count extracted files
|
| 195 |
+
smpl_dir = data_dir / "smpl_filtered"
|
| 196 |
+
if smpl_dir.exists():
|
| 197 |
+
n_files = sum(1 for f in smpl_dir.iterdir() if f.suffix == ".pkl")
|
| 198 |
+
print(f" -> {smpl_dir} ({n_files} PKL files)")
|
| 199 |
+
else:
|
| 200 |
+
print(f" WARNING: Expected {smpl_dir} but directory not found")
|
| 201 |
+
|
| 202 |
+
# Clean up tar parts
|
| 203 |
+
print(" Cleaning up tar parts ...")
|
| 204 |
+
shutil.rmtree(parts_dir)
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def download_sample_data(snapshot_download, repo_id, output_dir, token=None):
|
| 208 |
+
"""Download sample motion data (1 walking sequence)."""
|
| 209 |
+
print(" Downloading sample data ...", flush=True)
|
| 210 |
+
snapshot_download(
|
| 211 |
+
repo_id=repo_id,
|
| 212 |
+
allow_patterns="sample_data/*",
|
| 213 |
+
local_dir=str(output_dir),
|
| 214 |
+
token=token,
|
| 215 |
+
)
|
| 216 |
+
sample_dir = output_dir / "sample_data"
|
| 217 |
+
if sample_dir.exists():
|
| 218 |
+
n_files = sum(1 for _ in sample_dir.rglob("*.pkl"))
|
| 219 |
+
print(f" -> {sample_dir} ({n_files} PKL files)")
|
| 220 |
+
|
| 221 |
+
|
| 222 |
+
def main():
|
| 223 |
+
args = parse_args()
|
| 224 |
+
if args.sample and (args.low_latency or args.sonic_v1_1):
|
| 225 |
+
print(
|
| 226 |
+
"ERROR: model variant flags cannot be combined with --sample",
|
| 227 |
+
file=sys.stderr,
|
| 228 |
+
)
|
| 229 |
+
sys.exit(2)
|
| 230 |
+
|
| 231 |
+
hf_hub_download, snapshot_download = _ensure_huggingface_hub()
|
| 232 |
+
if args.low_latency:
|
| 233 |
+
variant = "low_latency"
|
| 234 |
+
elif args.sonic_v1_1:
|
| 235 |
+
variant = "sonic_v1_1"
|
| 236 |
+
else:
|
| 237 |
+
variant = "default"
|
| 238 |
+
|
| 239 |
+
repo_root = Path(__file__).resolve().parent
|
| 240 |
+
|
| 241 |
+
if args.training or args.sample:
|
| 242 |
+
output_dir = args.output_dir if args.output_dir else repo_root
|
| 243 |
+
else:
|
| 244 |
+
output_dir = args.output_dir if args.output_dir else repo_root / "gear_sonic_deploy"
|
| 245 |
+
|
| 246 |
+
print("=" * 60)
|
| 247 |
+
print(" GEAR-SONIC — Hugging Face Model Downloader")
|
| 248 |
+
print(f" Repository : {REPO_ID}")
|
| 249 |
+
print(f" Output dir : {output_dir}")
|
| 250 |
+
if args.training:
|
| 251 |
+
print(f" Mode : {variant.replace('_', '-')} training checkpoint")
|
| 252 |
+
elif args.sample:
|
| 253 |
+
print(f" Mode : sample data (quick start)")
|
| 254 |
+
else:
|
| 255 |
+
print(f" Mode : {variant.replace('_', '-')} deployment (ONNX models)")
|
| 256 |
+
print("=" * 60)
|
| 257 |
+
|
| 258 |
+
if args.sample:
|
| 259 |
+
print("\n[Sample Data]")
|
| 260 |
+
download_sample_data(snapshot_download, REPO_ID, output_dir, token=args.token)
|
| 261 |
+
|
| 262 |
+
elif args.training:
|
| 263 |
+
print("\n[Checkpoint]")
|
| 264 |
+
training_files = {
|
| 265 |
+
"default": TRAINING_FILES,
|
| 266 |
+
"low_latency": LOW_LATENCY_TRAINING_FILES,
|
| 267 |
+
"sonic_v1_1": SONIC_V1_1_TRAINING_FILES,
|
| 268 |
+
}[variant]
|
| 269 |
+
for hf_filename, local_rel in training_files:
|
| 270 |
+
download_file(
|
| 271 |
+
hf_hub_download, REPO_ID, hf_filename,
|
| 272 |
+
output_dir / local_rel, token=args.token,
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
if args.low_latency:
|
| 276 |
+
print("\n[SMPL Motion Data] Skipped (not part of low-latency checkpoint download)")
|
| 277 |
+
elif not args.no_smpl:
|
| 278 |
+
print("\n[SMPL Motion Data]")
|
| 279 |
+
download_and_extract_smpl(hf_hub_download, REPO_ID, output_dir, token=args.token)
|
| 280 |
+
else:
|
| 281 |
+
print("\n[SMPL Motion Data] Skipped (--no-smpl)")
|
| 282 |
+
|
| 283 |
+
else:
|
| 284 |
+
print("\n[Policy]")
|
| 285 |
+
policy_files = {
|
| 286 |
+
"default": POLICY_FILES,
|
| 287 |
+
"low_latency": LOW_LATENCY_POLICY_FILES,
|
| 288 |
+
"sonic_v1_1": SONIC_V1_1_POLICY_FILES,
|
| 289 |
+
}[variant]
|
| 290 |
+
for hf_filename, local_rel in policy_files:
|
| 291 |
+
download_file(
|
| 292 |
+
hf_hub_download, REPO_ID, hf_filename,
|
| 293 |
+
output_dir / local_rel, token=args.token,
|
| 294 |
+
)
|
| 295 |
+
|
| 296 |
+
if not args.no_planner:
|
| 297 |
+
print("\n[Planner]")
|
| 298 |
+
hf_filename, local_rel = PLANNER_FILE
|
| 299 |
+
download_file(
|
| 300 |
+
hf_hub_download, REPO_ID, hf_filename,
|
| 301 |
+
output_dir / local_rel, token=args.token,
|
| 302 |
+
)
|
| 303 |
+
|
| 304 |
+
print("\n" + "=" * 60)
|
| 305 |
+
print(" Done! Files saved under:")
|
| 306 |
+
print(f" {output_dir}")
|
| 307 |
+
print("=" * 60)
|
| 308 |
+
|
| 309 |
+
|
| 310 |
+
if __name__ == "__main__":
|
| 311 |
+
main()
|
GR00T-WholeBodyControl/gear_sonic_deploy/.clang-format
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
Language: Cpp
|
| 3 |
+
AccessModifierOffset: 0
|
| 4 |
+
AlignAfterOpenBracket: Align
|
| 5 |
+
AlignArrayOfStructures: None
|
| 6 |
+
AlignConsecutiveAssignments: None
|
| 7 |
+
AlignConsecutiveBitFields: None
|
| 8 |
+
AlignConsecutiveDeclarations: None
|
| 9 |
+
AlignConsecutiveMacros: None
|
| 10 |
+
AlignEscapedNewlines: Right
|
| 11 |
+
AlignOperands: Align
|
| 12 |
+
AlignTrailingComments: false
|
| 13 |
+
AllowAllArgumentsOnNextLine: false
|
| 14 |
+
AllowAllParametersOfDeclarationOnNextLine: false
|
| 15 |
+
AllowShortBlocksOnASingleLine: Always
|
| 16 |
+
AllowShortCaseLabelsOnASingleLine: true
|
| 17 |
+
AllowShortEnumsOnASingleLine: true
|
| 18 |
+
AllowShortFunctionsOnASingleLine: All
|
| 19 |
+
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
|
| 20 |
+
AllowShortLambdasOnASingleLine: All
|
| 21 |
+
AllowShortLoopsOnASingleLine: true
|
| 22 |
+
AlwaysBreakAfterReturnType: None
|
| 23 |
+
AlwaysBreakBeforeMultilineStrings: false
|
| 24 |
+
AlwaysBreakTemplateDeclarations: No
|
| 25 |
+
BinPackArguments: true
|
| 26 |
+
BinPackParameters: true
|
| 27 |
+
BitFieldColonSpacing: Both
|
| 28 |
+
BreakBeforeBraces: Custom
|
| 29 |
+
BraceWrapping:
|
| 30 |
+
AfterCaseLabel: false
|
| 31 |
+
AfterClass: false
|
| 32 |
+
AfterControlStatement: Never
|
| 33 |
+
AfterEnum: false
|
| 34 |
+
AfterFunction: false
|
| 35 |
+
AfterNamespace: false
|
| 36 |
+
AfterObjCDeclaration: false
|
| 37 |
+
AfterStruct: false
|
| 38 |
+
AfterUnion: false
|
| 39 |
+
AfterExternBlock: false
|
| 40 |
+
BeforeCatch: false
|
| 41 |
+
BeforeElse: false
|
| 42 |
+
BeforeLambdaBody: false
|
| 43 |
+
BeforeWhile: false
|
| 44 |
+
IndentBraces: false
|
| 45 |
+
SplitEmptyFunction: true
|
| 46 |
+
SplitEmptyRecord: true
|
| 47 |
+
SplitEmptyNamespace: true
|
| 48 |
+
BreakAfterJavaFieldAnnotations: false
|
| 49 |
+
BreakBeforeBinaryOperators: None
|
| 50 |
+
BreakConstructorInitializers: BeforeColon
|
| 51 |
+
BreakInheritanceList: BeforeColon
|
| 52 |
+
BreakStringLiterals: true
|
| 53 |
+
ColumnLimit: 120
|
| 54 |
+
CompactNamespaces: false
|
| 55 |
+
ConstructorInitializerIndentWidth: 2
|
| 56 |
+
Cpp11BracedListStyle: true
|
| 57 |
+
EmptyLineAfterAccessModifier: Never
|
| 58 |
+
EmptyLineBeforeAccessModifier: Never
|
| 59 |
+
IndentAccessModifiers: true
|
| 60 |
+
IndentCaseLabels: true
|
| 61 |
+
IndentExternBlock: AfterExternBlock
|
| 62 |
+
IndentGotoLabels: true
|
| 63 |
+
IndentWidth: 2
|
| 64 |
+
IndentWrappedFunctionNames: false
|
| 65 |
+
KeepEmptyLinesAtTheStartOfBlocks: false
|
| 66 |
+
PackConstructorInitializers: Never
|
| 67 |
+
PointerAlignment: Left
|
| 68 |
+
ReferenceAlignment: Left
|
| 69 |
+
ReflowComments: true
|
| 70 |
+
SeparateDefinitionBlocks: Always
|
| 71 |
+
SortIncludes: false
|
| 72 |
+
SpaceBeforeAssignmentOperators: true
|
| 73 |
+
SpaceBeforeCaseColon: false
|
| 74 |
+
SpaceBeforeCpp11BracedList: true
|
| 75 |
+
SpaceBeforeCtorInitializerColon: true
|
| 76 |
+
SpaceBeforeInheritanceColon: true
|
| 77 |
+
SpaceBeforeParens: ControlStatements
|
| 78 |
+
SpaceBeforeRangeBasedForLoopColon: true
|
| 79 |
+
SpaceBeforeSquareBrackets: false
|
| 80 |
+
SpaceInEmptyBlock: false
|
| 81 |
+
SpaceInEmptyParentheses: false
|
| 82 |
+
SpacesInCStyleCastParentheses: false
|
| 83 |
+
SpacesInConditionalStatement: false
|
| 84 |
+
TabWidth: 2
|
| 85 |
+
UseTab: Never
|
GR00T-WholeBodyControl/gear_sonic_deploy/.cmake-format.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -----------------------------
|
| 2 |
+
# Options effecting formatting.
|
| 3 |
+
# -----------------------------
|
| 4 |
+
with section("format"):
|
| 5 |
+
|
| 6 |
+
# How wide to allow formatted cmake files
|
| 7 |
+
line_width = 80
|
| 8 |
+
|
| 9 |
+
# How many spaces to tab for indent
|
| 10 |
+
tab_size = 2
|
| 11 |
+
|
| 12 |
+
# If true, separate flow control names from their parentheses with a space
|
| 13 |
+
separate_ctrl_name_with_space = False
|
| 14 |
+
|
| 15 |
+
# If true, separate function names from parentheses with a space
|
| 16 |
+
separate_fn_name_with_space = False
|
| 17 |
+
|
| 18 |
+
# If a statement is wrapped to more than one line, than dangle the closing
|
| 19 |
+
# parenthesis on its own line.
|
| 20 |
+
dangle_parens = False
|
GR00T-WholeBodyControl/gear_sonic_deploy/.editorconfig
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# EditorConfig is awesome: https://EditorConfig.org
|
| 2 |
+
|
| 3 |
+
# https://github.com/jokeyrhyme/standard-editorconfig
|
| 4 |
+
|
| 5 |
+
# top-most EditorConfig file
|
| 6 |
+
root = true
|
| 7 |
+
|
| 8 |
+
[*]
|
| 9 |
+
indent_style = space
|
| 10 |
+
indent_size = 2
|
| 11 |
+
end_of_line = lf
|
| 12 |
+
charset = utf-8
|
| 13 |
+
trim_trailing_whitespace = false
|
| 14 |
+
insert_final_newline = true
|
| 15 |
+
|
| 16 |
+
[*.md]
|
| 17 |
+
indent_size = 3
|
| 18 |
+
|
| 19 |
+
[*.nix]
|
| 20 |
+
indent_size = 2
|
| 21 |
+
|
| 22 |
+
[*.py]
|
| 23 |
+
indent_size = 4
|
| 24 |
+
max_line_length = 120
|
GR00T-WholeBodyControl/gear_sonic_deploy/.gitattributes
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.a filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*so.1 filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*so.1.20.1 filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
.so filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.so.0 filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.so filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.csv filter=lfs diff=lfs merge=lfs -text
|
GR00T-WholeBodyControl/gear_sonic_deploy/.gitignore
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Ignore GitHub workflows and CI/CD files
|
| 2 |
+
.github/
|
| 3 |
+
|
| 4 |
+
build/
|
| 5 |
+
target/
|
| 6 |
+
logs/
|
| 7 |
+
*.trt
|
GR00T-WholeBodyControl/gear_sonic_deploy/.justfile
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Like GNU `make`, but `just` rustier.
|
| 2 |
+
# https://just.systems/
|
| 3 |
+
# run `just` from this directory to see available commands
|
| 4 |
+
|
| 5 |
+
alias b := build
|
| 6 |
+
alias r := run
|
| 7 |
+
alias t := test
|
| 8 |
+
alias c := clean
|
| 9 |
+
alias ch := check
|
| 10 |
+
|
| 11 |
+
# Default command when 'just' is run without arguments
|
| 12 |
+
default:
|
| 13 |
+
@just --list
|
| 14 |
+
|
| 15 |
+
# Get the number of cores
|
| 16 |
+
CORES := if os() == "macos" { `sysctl -n hw.ncpu` } else if os() == "linux" { `nproc` } else { "1" }
|
| 17 |
+
|
| 18 |
+
# Build the project
|
| 19 |
+
build *build_type='Release':
|
| 20 |
+
@mkdir -p build
|
| 21 |
+
@echo "Configuring the build system..."
|
| 22 |
+
@cd build && cmake -S .. -B . -DCMAKE_BUILD_TYPE={{build_type}} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
| 23 |
+
@echo "Building the project..."
|
| 24 |
+
@cd build && cmake --build . -j{{CORES}}
|
| 25 |
+
|
| 26 |
+
# Run a package
|
| 27 |
+
run *package='hello':
|
| 28 |
+
@./target/release/{{package}}
|
| 29 |
+
|
| 30 |
+
# Run code quality tools
|
| 31 |
+
test:
|
| 32 |
+
@echo "Running tests..."
|
| 33 |
+
|
| 34 |
+
# Remove build artifacts and non-essential files
|
| 35 |
+
clean:
|
| 36 |
+
@echo "Cleaning..."
|
| 37 |
+
@rm -rf build
|
| 38 |
+
@rm -rf target
|
| 39 |
+
|
| 40 |
+
# Run code quality tools
|
| 41 |
+
check:
|
| 42 |
+
@echo "Running code quality tools..."
|
| 43 |
+
@cppcheck --error-exitcode=1 --project=build/compile_commands.json -i build/_deps/
|
| 44 |
+
|
GR00T-WholeBodyControl/gear_sonic_deploy/CMakeLists.txt
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cmake_minimum_required(VERSION 3.14 FATAL_ERROR) # Set the minimum required
|
| 2 |
+
# version of CMake
|
| 3 |
+
|
| 4 |
+
project(
|
| 5 |
+
g1_deploy
|
| 6 |
+
VERSION 1.0.0
|
| 7 |
+
LANGUAGES CXX)
|
| 8 |
+
|
| 9 |
+
# Set C++ standard
|
| 10 |
+
set(CMAKE_CXX_STANDARD 20)
|
| 11 |
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
| 12 |
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math")
|
| 13 |
+
|
| 14 |
+
message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
|
| 15 |
+
message(STATUS "C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}")
|
| 16 |
+
message(STATUS "C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}")
|
| 17 |
+
|
| 18 |
+
# Library target
|
| 19 |
+
add_library(${PROJECT_NAME} INTERFACE)
|
| 20 |
+
|
| 21 |
+
include(CheckLanguage)
|
| 22 |
+
|
| 23 |
+
# Optional builds
|
| 24 |
+
option(BUILD_SRCS "Build sources" ON)
|
| 25 |
+
|
| 26 |
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
| 27 |
+
|
| 28 |
+
find_package(TensorRT REQUIRED)
|
| 29 |
+
find_package(Threads REQUIRED)
|
| 30 |
+
find_package(onnxruntime REQUIRED)
|
| 31 |
+
# Find CUDA Toolkit with proper environment variable support
|
| 32 |
+
if(DEFINED ENV{CUDAToolkit_ROOT})
|
| 33 |
+
set(CUDAToolkit_ROOT $ENV{CUDAToolkit_ROOT})
|
| 34 |
+
message(STATUS "🎯 Using CUDAToolkit_ROOT from environment: ${CUDAToolkit_ROOT}")
|
| 35 |
+
endif()
|
| 36 |
+
|
| 37 |
+
if(DEFINED ENV{CUDA_HOME})
|
| 38 |
+
message(STATUS "🔍 Using CUDA_HOME from environment: $ENV{CUDA_HOME}")
|
| 39 |
+
list(APPEND CMAKE_PREFIX_PATH $ENV{CUDA_HOME})
|
| 40 |
+
endif()
|
| 41 |
+
|
| 42 |
+
find_package(CUDAToolkit 10.2 QUIET)
|
| 43 |
+
|
| 44 |
+
if(CUDAToolkit_FOUND)
|
| 45 |
+
message(STATUS "✅ CUDA Toolkit found: version ${CUDAToolkit_VERSION}")
|
| 46 |
+
|
| 47 |
+
# Report CUDA architecture and paths for debugging
|
| 48 |
+
message(STATUS " CUDA Root: ${CUDAToolkit_TARGET_DIR}")
|
| 49 |
+
message(STATUS " CUDA Libraries: ${CUDAToolkit_LIBRARY_DIR}")
|
| 50 |
+
|
| 51 |
+
# For CUDA 12.6+, enable newer features if available
|
| 52 |
+
if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.6")
|
| 53 |
+
message(STATUS " 🚀 CUDA 12.6+ detected - enabling optimized features")
|
| 54 |
+
# Add any CUDA 12.6+ specific optimizations here
|
| 55 |
+
add_compile_definitions(CUDA_12_6_PLUS=1)
|
| 56 |
+
elseif(CUDAToolkit_VERSION VERSION_GREATER_EQUAL "12.0")
|
| 57 |
+
message(STATUS " 🔧 CUDA 12.x detected")
|
| 58 |
+
add_compile_definitions(CUDA_12_PLUS=1)
|
| 59 |
+
endif()
|
| 60 |
+
else()
|
| 61 |
+
# Fallback: Look for CUDA runtime libraries and headers
|
| 62 |
+
message(STATUS "🔍 CUDA Toolkit not found via find_package, searching for runtime libraries...")
|
| 63 |
+
message(STATUS " This is normal for systems with runtime-only CUDA installations")
|
| 64 |
+
|
| 65 |
+
# Debug: Show environment variables
|
| 66 |
+
if(DEFINED ENV{CUDAToolkit_ROOT})
|
| 67 |
+
message(STATUS " 🔍 Environment CUDAToolkit_ROOT: $ENV{CUDAToolkit_ROOT}")
|
| 68 |
+
endif()
|
| 69 |
+
if(DEFINED ENV{CUDA_HOME})
|
| 70 |
+
message(STATUS " 🔍 Environment CUDA_HOME: $ENV{CUDA_HOME}")
|
| 71 |
+
endif()
|
| 72 |
+
|
| 73 |
+
# Enhanced search with better path prioritization - now includes dynamic version detection
|
| 74 |
+
# First, build dynamic path lists for any CUDA versions
|
| 75 |
+
file(GLOB CUDA_SBSA_PATHS "/usr/local/cuda*/targets/sbsa-linux/lib")
|
| 76 |
+
file(GLOB CUDA_AARCH64_PATHS "/usr/local/cuda*/targets/aarch64-linux/lib")
|
| 77 |
+
file(GLOB CUDA_LIB64_PATHS "/usr/local/cuda*/lib64")
|
| 78 |
+
|
| 79 |
+
find_library(CUDA_RUNTIME_LIBRARY
|
| 80 |
+
NAMES cudart libcudart
|
| 81 |
+
HINTS
|
| 82 |
+
# Environment variable paths
|
| 83 |
+
$ENV{CUDAToolkit_ROOT}/targets/sbsa-linux/lib
|
| 84 |
+
$ENV{CUDAToolkit_ROOT}/targets/aarch64-linux/lib
|
| 85 |
+
$ENV{CUDAToolkit_ROOT}/lib64
|
| 86 |
+
$ENV{CUDAToolkit_ROOT}/lib
|
| 87 |
+
$ENV{CUDA_HOME}/targets/sbsa-linux/lib
|
| 88 |
+
$ENV{CUDA_HOME}/targets/aarch64-linux/lib
|
| 89 |
+
$ENV{CUDA_HOME}/lib64
|
| 90 |
+
$ENV{CUDA_HOME}/lib
|
| 91 |
+
PATHS
|
| 92 |
+
# Dynamic CUDA version paths (automatically found)
|
| 93 |
+
${CUDA_SBSA_PATHS}
|
| 94 |
+
${CUDA_AARCH64_PATHS}
|
| 95 |
+
${CUDA_LIB64_PATHS}
|
| 96 |
+
# Static fallback paths
|
| 97 |
+
/usr/local/cuda/targets/sbsa-linux/lib
|
| 98 |
+
/usr/local/cuda/targets/aarch64-linux/lib
|
| 99 |
+
/usr/local/cuda/lib64
|
| 100 |
+
/usr/local/cuda/lib
|
| 101 |
+
# System library paths
|
| 102 |
+
/usr/lib/aarch64-linux-gnu
|
| 103 |
+
/usr/lib/x86_64-linux-gnu
|
| 104 |
+
/usr/lib64
|
| 105 |
+
/usr/lib
|
| 106 |
+
NO_DEFAULT_PATH
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
# Build dynamic include paths for any CUDA versions
|
| 110 |
+
file(GLOB CUDA_SBSA_INCLUDE_PATHS "/usr/local/cuda*/targets/sbsa-linux/include")
|
| 111 |
+
file(GLOB CUDA_AARCH64_INCLUDE_PATHS "/usr/local/cuda*/targets/aarch64-linux/include")
|
| 112 |
+
file(GLOB CUDA_INCLUDE_PATHS "/usr/local/cuda*/include")
|
| 113 |
+
|
| 114 |
+
find_path(CUDA_INCLUDE_DIR cuda_runtime.h
|
| 115 |
+
HINTS
|
| 116 |
+
# Environment variable paths
|
| 117 |
+
$ENV{CUDAToolkit_ROOT}/targets/sbsa-linux/include
|
| 118 |
+
$ENV{CUDAToolkit_ROOT}/targets/aarch64-linux/include
|
| 119 |
+
$ENV{CUDAToolkit_ROOT}/include
|
| 120 |
+
$ENV{CUDA_HOME}/targets/sbsa-linux/include
|
| 121 |
+
$ENV{CUDA_HOME}/targets/aarch64-linux/include
|
| 122 |
+
$ENV{CUDA_HOME}/include
|
| 123 |
+
PATHS
|
| 124 |
+
# Dynamic CUDA version paths (automatically found)
|
| 125 |
+
${CUDA_SBSA_INCLUDE_PATHS}
|
| 126 |
+
${CUDA_AARCH64_INCLUDE_PATHS}
|
| 127 |
+
${CUDA_INCLUDE_PATHS}
|
| 128 |
+
# Static fallback paths
|
| 129 |
+
/usr/local/cuda/targets/sbsa-linux/include
|
| 130 |
+
/usr/local/cuda/targets/aarch64-linux/include
|
| 131 |
+
/usr/local/cuda/include
|
| 132 |
+
# System include paths
|
| 133 |
+
/usr/include
|
| 134 |
+
/usr/include/cuda
|
| 135 |
+
PATH_SUFFIXES
|
| 136 |
+
cuda
|
| 137 |
+
NO_DEFAULT_PATH
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
# Debug: Check if files exist in Jetson-specific locations
|
| 141 |
+
message(STATUS "🔍 Manually checking Jetson CUDA locations...")
|
| 142 |
+
|
| 143 |
+
# Check for libcudart with version number (as found in your system)
|
| 144 |
+
if(EXISTS "/usr/local/cuda/targets/sbsa-linux/lib/libcudart.so.12.6.77")
|
| 145 |
+
message(STATUS "✅ Found libcudart.so.12.6.77 in Jetson sbsa-linux location!")
|
| 146 |
+
set(CUDA_RUNTIME_LIBRARY "/usr/local/cuda/targets/sbsa-linux/lib/libcudart.so.12.6.77")
|
| 147 |
+
elseif(EXISTS "/usr/local/cuda/targets/sbsa-linux/lib")
|
| 148 |
+
# Check if any libcudart exists in sbsa-linux directory
|
| 149 |
+
file(GLOB CUDART_FILES "/usr/local/cuda/targets/sbsa-linux/lib/libcudart*")
|
| 150 |
+
if(CUDART_FILES)
|
| 151 |
+
list(GET CUDART_FILES 0 FIRST_CUDART)
|
| 152 |
+
message(STATUS "✅ Found CUDA runtime in sbsa-linux: ${FIRST_CUDART}")
|
| 153 |
+
set(CUDA_RUNTIME_LIBRARY ${FIRST_CUDART})
|
| 154 |
+
endif()
|
| 155 |
+
elseif(EXISTS "/usr/local/cuda/targets/aarch64-linux/lib/libcudart.so")
|
| 156 |
+
message(STATUS "✅ Found libcudart.so in Jetson aarch64-linux location!")
|
| 157 |
+
set(CUDA_RUNTIME_LIBRARY "/usr/local/cuda/targets/aarch64-linux/lib/libcudart.so")
|
| 158 |
+
elseif(EXISTS "/usr/local/cuda/lib64/libcudart.so")
|
| 159 |
+
message(STATUS "✅ Found libcudart.so in standard location!")
|
| 160 |
+
set(CUDA_RUNTIME_LIBRARY "/usr/local/cuda/lib64/libcudart.so")
|
| 161 |
+
else()
|
| 162 |
+
message(STATUS "❌ libcudart.so not found in expected locations")
|
| 163 |
+
endif()
|
| 164 |
+
|
| 165 |
+
if(EXISTS "/usr/local/cuda/targets/sbsa-linux/include/cuda_runtime.h")
|
| 166 |
+
message(STATUS "✅ Found cuda_runtime.h in Jetson sbsa-linux location!")
|
| 167 |
+
set(CUDA_INCLUDE_DIR "/usr/local/cuda/targets/sbsa-linux/include")
|
| 168 |
+
elseif(EXISTS "/usr/local/cuda/targets/aarch64-linux/include/cuda_runtime.h")
|
| 169 |
+
message(STATUS "✅ Found cuda_runtime.h in Jetson aarch64-linux location!")
|
| 170 |
+
set(CUDA_INCLUDE_DIR "/usr/local/cuda/targets/aarch64-linux/include")
|
| 171 |
+
elseif(EXISTS "/usr/local/cuda/include/cuda_runtime.h")
|
| 172 |
+
message(STATUS "✅ Found cuda_runtime.h in standard location!")
|
| 173 |
+
set(CUDA_INCLUDE_DIR "/usr/local/cuda/include")
|
| 174 |
+
else()
|
| 175 |
+
message(STATUS "❌ cuda_runtime.h not found in expected locations")
|
| 176 |
+
endif()
|
| 177 |
+
|
| 178 |
+
if(CUDA_RUNTIME_LIBRARY AND CUDA_INCLUDE_DIR)
|
| 179 |
+
message(STATUS "✅ CUDA runtime components verified")
|
| 180 |
+
|
| 181 |
+
# Try to detect CUDA version from headers
|
| 182 |
+
if(EXISTS "${CUDA_INCLUDE_DIR}/cuda.h")
|
| 183 |
+
file(STRINGS "${CUDA_INCLUDE_DIR}/cuda.h" CUDA_VERSION_DEFINES
|
| 184 |
+
REGEX "#define CUDA_VERSION ")
|
| 185 |
+
if(CUDA_VERSION_DEFINES MATCHES "#define CUDA_VERSION ([0-9]+)")
|
| 186 |
+
math(EXPR CUDA_VERSION_MAJOR "${CMAKE_MATCH_1} / 1000")
|
| 187 |
+
math(EXPR CUDA_VERSION_MINOR "(${CMAKE_MATCH_1} % 1000) / 10")
|
| 188 |
+
set(CUDA_VERSION_STRING "${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}")
|
| 189 |
+
message(STATUS " Detected CUDA version: ${CUDA_VERSION_STRING}")
|
| 190 |
+
|
| 191 |
+
# Enable version-specific features
|
| 192 |
+
if(CUDA_VERSION_MAJOR GREATER_EQUAL 12 AND CUDA_VERSION_MINOR GREATER_EQUAL 6)
|
| 193 |
+
message(STATUS " 🚀 CUDA 12.6+ detected - enabling optimized features")
|
| 194 |
+
add_compile_definitions(CUDA_12_6_PLUS=1)
|
| 195 |
+
elseif(CUDA_VERSION_MAJOR GREATER_EQUAL 12)
|
| 196 |
+
message(STATUS " 🔧 CUDA 12.x detected")
|
| 197 |
+
add_compile_definitions(CUDA_12_PLUS=1)
|
| 198 |
+
endif()
|
| 199 |
+
endif()
|
| 200 |
+
endif()
|
| 201 |
+
|
| 202 |
+
# Create imported target for compatibility with modern CMake
|
| 203 |
+
add_library(CUDA::cudart SHARED IMPORTED)
|
| 204 |
+
set_target_properties(CUDA::cudart PROPERTIES
|
| 205 |
+
IMPORTED_LOCATION "${CUDA_RUNTIME_LIBRARY}"
|
| 206 |
+
INTERFACE_INCLUDE_DIRECTORIES "${CUDA_INCLUDE_DIR}")
|
| 207 |
+
else()
|
| 208 |
+
message(STATUS "❌ CUDA components not found:")
|
| 209 |
+
if(NOT CUDA_RUNTIME_LIBRARY)
|
| 210 |
+
message(STATUS " - CUDA runtime library (libcudart) not found")
|
| 211 |
+
endif()
|
| 212 |
+
if(NOT CUDA_INCLUDE_DIR)
|
| 213 |
+
message(STATUS " - CUDA headers (cuda_runtime.h) not found")
|
| 214 |
+
endif()
|
| 215 |
+
message(FATAL_ERROR "
|
| 216 |
+
🚨 CUDA installation incomplete. Please run:
|
| 217 |
+
./scripts/install_deps.sh
|
| 218 |
+
|
| 219 |
+
💡 For Jetson systems with CUDA 12.6:
|
| 220 |
+
- Ensure JetPack SDK development components are installed
|
| 221 |
+
- Check if CUDA is installed at /usr/local/cuda-12.6/
|
| 222 |
+
- Run 'ls -la /usr/local/cuda*' to verify CUDA installation")
|
| 223 |
+
endif()
|
| 224 |
+
endif()
|
| 225 |
+
find_package(ZLIB REQUIRED)
|
| 226 |
+
|
| 227 |
+
# Use local unitree_sdk2 subfolder
|
| 228 |
+
# Disable building examples for unitree_sdk2
|
| 229 |
+
set(BUILD_EXAMPLES
|
| 230 |
+
OFF
|
| 231 |
+
CACHE BOOL "Build unitree_sdk2 examples" FORCE)
|
| 232 |
+
|
| 233 |
+
add_subdirectory(thirdparty/unitree_sdk2)
|
| 234 |
+
|
| 235 |
+
# Add unitree_sdk2 include directories
|
| 236 |
+
target_include_directories(${PROJECT_NAME}
|
| 237 |
+
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/unitree_sdk2/include)
|
| 238 |
+
|
| 239 |
+
# Link to unitree_sdk2 which includes all necessary dependencies
|
| 240 |
+
target_link_libraries(${PROJECT_NAME} INTERFACE unitree_sdk2)
|
| 241 |
+
|
| 242 |
+
# Examples
|
| 243 |
+
if(BUILD_SRCS)
|
| 244 |
+
add_subdirectory(src)
|
| 245 |
+
endif()
|
GR00T-WholeBodyControl/gear_sonic_deploy/deploy.sh
ADDED
|
@@ -0,0 +1,577 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
set -e
|
| 3 |
+
|
| 4 |
+
# ============================================================================
|
| 5 |
+
# G1 Deploy - Deployment Script
|
| 6 |
+
# ============================================================================
|
| 7 |
+
# This script handles the complete setup and deployment process for g1_deploy
|
| 8 |
+
# Following the steps from the README.md
|
| 9 |
+
#
|
| 10 |
+
# Usage: ./deploy.sh [sim|real|<interface_name>|<ip_address>]
|
| 11 |
+
# sim - Use loopback interface for simulation (MuJoCo)
|
| 12 |
+
# real - Auto-detect robot network interface (192.168.123.x)
|
| 13 |
+
# <interface_name> - Use specific interface (e.g., enP8p1s0, eth0)
|
| 14 |
+
# <ip_address> - Use interface with specific IP
|
| 15 |
+
#
|
| 16 |
+
# Default: real
|
| 17 |
+
# ============================================================================
|
| 18 |
+
|
| 19 |
+
# Colors for output
|
| 20 |
+
RED='\033[0;31m'
|
| 21 |
+
GREEN='\033[0;32m'
|
| 22 |
+
YELLOW='\033[1;33m'
|
| 23 |
+
BLUE='\033[0;34m'
|
| 24 |
+
CYAN='\033[0;36m'
|
| 25 |
+
NC='\033[0m' # No Color
|
| 26 |
+
|
| 27 |
+
# Script directory (where this script is located)
|
| 28 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 29 |
+
cd "$SCRIPT_DIR"
|
| 30 |
+
|
| 31 |
+
# ============================================================================
|
| 32 |
+
# Interface Resolution Functions
|
| 33 |
+
# ============================================================================
|
| 34 |
+
|
| 35 |
+
# Get all network interfaces and their IPs
|
| 36 |
+
# Returns lines of: interface_name:ip_address
|
| 37 |
+
get_network_interfaces() {
|
| 38 |
+
if [[ "$(uname)" == "Darwin" ]]; then
|
| 39 |
+
# macOS
|
| 40 |
+
ifconfig | awk '
|
| 41 |
+
/^[a-z]/ { iface=$1; gsub(/:$/, "", iface) }
|
| 42 |
+
/inet / { print iface ":" $2 }
|
| 43 |
+
'
|
| 44 |
+
else
|
| 45 |
+
# Linux
|
| 46 |
+
ip -4 addr show 2>/dev/null | awk '
|
| 47 |
+
/^[0-9]+:/ { gsub(/:$/, "", $2); iface=$2 }
|
| 48 |
+
/inet / { split($2, a, "/"); print iface ":" a[1] }
|
| 49 |
+
' 2>/dev/null || \
|
| 50 |
+
ifconfig 2>/dev/null | awk '
|
| 51 |
+
/^[a-z]/ { iface=$1; gsub(/:$/, "", iface) }
|
| 52 |
+
/inet / {
|
| 53 |
+
for (i=1; i<=NF; i++) {
|
| 54 |
+
if ($i == "inet") { print iface ":" $(i+1); break }
|
| 55 |
+
if ($i ~ /^addr:/) { split($i, a, ":"); print iface ":" a[2]; break }
|
| 56 |
+
}
|
| 57 |
+
}
|
| 58 |
+
'
|
| 59 |
+
fi
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
# Find interface by IP address
|
| 63 |
+
# Returns interface name or empty string
|
| 64 |
+
find_interface_by_ip() {
|
| 65 |
+
local target_ip="$1"
|
| 66 |
+
get_network_interfaces | while IFS=: read -r iface ip; do
|
| 67 |
+
if [[ "$ip" == "$target_ip" ]]; then
|
| 68 |
+
echo "$iface"
|
| 69 |
+
return 0
|
| 70 |
+
fi
|
| 71 |
+
done
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
# Find interface with IP matching a prefix
|
| 75 |
+
# Returns interface name or empty string
|
| 76 |
+
find_interface_by_ip_prefix() {
|
| 77 |
+
local prefix="$1"
|
| 78 |
+
get_network_interfaces | while IFS=: read -r iface ip; do
|
| 79 |
+
if [[ "$ip" == "$prefix"* ]]; then
|
| 80 |
+
echo "$iface"
|
| 81 |
+
return 0
|
| 82 |
+
fi
|
| 83 |
+
done
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
# Check if string is an IP address
|
| 87 |
+
is_ip_address() {
|
| 88 |
+
local input="$1"
|
| 89 |
+
if [[ "$input" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
| 90 |
+
return 0
|
| 91 |
+
fi
|
| 92 |
+
return 1
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
# Check if interface has a specific IP
|
| 96 |
+
interface_has_ip() {
|
| 97 |
+
local iface="$1"
|
| 98 |
+
local target_ip="$2"
|
| 99 |
+
get_network_interfaces | while IFS=: read -r name ip; do
|
| 100 |
+
if [[ "$name" == "$iface" ]] && [[ "$ip" == "$target_ip" ]]; then
|
| 101 |
+
echo "yes"
|
| 102 |
+
return 0
|
| 103 |
+
fi
|
| 104 |
+
done
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
# Resolve interface parameter to actual network interface name and environment type
|
| 108 |
+
# Arguments: interface - "sim", "real", or direct interface name or IP address
|
| 109 |
+
# Outputs: Sets TARGET and ENV_TYPE variables
|
| 110 |
+
resolve_interface() {
|
| 111 |
+
local interface="$1"
|
| 112 |
+
local os_type="$(uname)"
|
| 113 |
+
|
| 114 |
+
# Check if interface is an IP address
|
| 115 |
+
if is_ip_address "$interface"; then
|
| 116 |
+
if [[ "$interface" == "127.0.0.1" ]]; then
|
| 117 |
+
TARGET="$interface"
|
| 118 |
+
ENV_TYPE="sim"
|
| 119 |
+
else
|
| 120 |
+
TARGET="$interface"
|
| 121 |
+
ENV_TYPE="real"
|
| 122 |
+
fi
|
| 123 |
+
return 0
|
| 124 |
+
fi
|
| 125 |
+
|
| 126 |
+
if [[ "$interface" == "sim" ]]; then
|
| 127 |
+
local lo_interface
|
| 128 |
+
lo_interface=$(find_interface_by_ip "127.0.0.1")
|
| 129 |
+
|
| 130 |
+
if [[ -n "$lo_interface" ]]; then
|
| 131 |
+
# macOS uses lo0 instead of lo
|
| 132 |
+
if [[ "$os_type" == "Darwin" ]] && [[ "$lo_interface" == "lo" ]]; then
|
| 133 |
+
TARGET="lo0"
|
| 134 |
+
else
|
| 135 |
+
TARGET="$lo_interface"
|
| 136 |
+
fi
|
| 137 |
+
else
|
| 138 |
+
# Fallback
|
| 139 |
+
if [[ "$os_type" == "Darwin" ]]; then
|
| 140 |
+
TARGET="lo0"
|
| 141 |
+
else
|
| 142 |
+
TARGET="lo"
|
| 143 |
+
fi
|
| 144 |
+
fi
|
| 145 |
+
ENV_TYPE="sim"
|
| 146 |
+
return 0
|
| 147 |
+
|
| 148 |
+
elif [[ "$interface" == "real" ]]; then
|
| 149 |
+
# Try to find interface with 192.168.123.x IP (Unitree robot network)
|
| 150 |
+
local real_interface
|
| 151 |
+
real_interface=$(find_interface_by_ip_prefix "192.168.123.")
|
| 152 |
+
|
| 153 |
+
if [[ -n "$real_interface" ]]; then
|
| 154 |
+
TARGET="$real_interface"
|
| 155 |
+
else
|
| 156 |
+
# Fallback to common interface names
|
| 157 |
+
# Try to find any non-loopback interface
|
| 158 |
+
local fallback_interface
|
| 159 |
+
fallback_interface=$(get_network_interfaces | grep -v "127.0.0.1" | head -1 | cut -d: -f1)
|
| 160 |
+
|
| 161 |
+
if [[ -n "$fallback_interface" ]]; then
|
| 162 |
+
TARGET="$fallback_interface"
|
| 163 |
+
echo -e "${YELLOW}⚠️ Could not find 192.168.123.x interface, using: $TARGET${NC}" >&2
|
| 164 |
+
else
|
| 165 |
+
# Ultimate fallback
|
| 166 |
+
TARGET="enP8p1s0"
|
| 167 |
+
echo -e "${YELLOW}⚠️ Could not auto-detect interface, using default: $TARGET${NC}" >&2
|
| 168 |
+
fi
|
| 169 |
+
fi
|
| 170 |
+
ENV_TYPE="real"
|
| 171 |
+
return 0
|
| 172 |
+
|
| 173 |
+
else
|
| 174 |
+
# Direct interface name - check if it has 127.0.0.1 to determine env_type
|
| 175 |
+
local has_loopback
|
| 176 |
+
has_loopback=$(interface_has_ip "$interface" "127.0.0.1")
|
| 177 |
+
|
| 178 |
+
if [[ "$has_loopback" == "yes" ]]; then
|
| 179 |
+
TARGET="$interface"
|
| 180 |
+
ENV_TYPE="sim"
|
| 181 |
+
return 0
|
| 182 |
+
fi
|
| 183 |
+
|
| 184 |
+
# macOS lo interface handling
|
| 185 |
+
if [[ "$os_type" == "Darwin" ]] && [[ "$interface" == "lo" ]]; then
|
| 186 |
+
TARGET="lo0"
|
| 187 |
+
ENV_TYPE="sim"
|
| 188 |
+
return 0
|
| 189 |
+
fi
|
| 190 |
+
|
| 191 |
+
# Default to real for unknown interfaces
|
| 192 |
+
TARGET="$interface"
|
| 193 |
+
ENV_TYPE="real"
|
| 194 |
+
return 0
|
| 195 |
+
fi
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
# ============================================================================
|
| 199 |
+
# Parse Command Line Arguments
|
| 200 |
+
# ============================================================================
|
| 201 |
+
|
| 202 |
+
show_usage() {
|
| 203 |
+
echo "Usage: $0 [OPTIONS] [sim|real|<interface>]"
|
| 204 |
+
echo ""
|
| 205 |
+
echo "Options:"
|
| 206 |
+
echo " -h, --help Show this help message"
|
| 207 |
+
echo " --cp, --checkpoint PATH Set the checkpoint path (default: policy/checkpoints/example/model_step_000000)"
|
| 208 |
+
echo " --obs-config PATH Set the observation config file (default: policy/configs/example.yaml)"
|
| 209 |
+
echo " --planner PATH Set the planner model path (default: planner/example.onnx)"
|
| 210 |
+
echo " --motion-data PATH Set the motion data path (default: reference/example_motion/)"
|
| 211 |
+
echo " --input-type TYPE Set the input type (default: zmq_manager)"
|
| 212 |
+
echo " --output-type TYPE Set the output type (default: ros2)"
|
| 213 |
+
echo " --zmq-host HOST Set the ZMQ host (default: localhost)"
|
| 214 |
+
echo ""
|
| 215 |
+
echo "Interface modes:"
|
| 216 |
+
echo " sim Use loopback interface for simulation (MuJoCo)"
|
| 217 |
+
echo " real Auto-detect robot network (192.168.123.x)"
|
| 218 |
+
echo " <interface> Use specific interface (e.g., enP8p1s0, eth0)"
|
| 219 |
+
echo " <ip_address> Use interface by IP address"
|
| 220 |
+
echo ""
|
| 221 |
+
echo "Default: real"
|
| 222 |
+
echo ""
|
| 223 |
+
echo "Examples:"
|
| 224 |
+
echo " $0 sim # Run in simulation mode"
|
| 225 |
+
echo " $0 real # Auto-detect real robot interface"
|
| 226 |
+
echo " $0 enP8p1s0 # Use specific interface"
|
| 227 |
+
echo " $0 192.168.x.x # Use interface with this IP"
|
| 228 |
+
echo " $0 --cp policy/checkpoints/custom/model_step_123456 real # Use custom checkpoint"
|
| 229 |
+
echo " $0 --obs-config policy/configs/custom.yaml sim # Use custom obs config"
|
| 230 |
+
echo " $0 --planner planner/custom.onnx --input-type keyboard real # Use custom planner and input"
|
| 231 |
+
echo " $0 --motion-data reference/custom_motion/ sim # Use custom motion data"
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
# Default interface mode
|
| 235 |
+
INTERFACE_MODE="real"
|
| 236 |
+
|
| 237 |
+
# Default configuration values (can be overridden by command line)
|
| 238 |
+
CHECKPOINT_DEFAULT="policy/release/model"
|
| 239 |
+
OBS_CONFIG_DEFAULT="policy/release/observation_config.yaml"
|
| 240 |
+
PLANNER_DEFAULT="planner/target_vel/V2/planner_sonic.onnx"
|
| 241 |
+
MOTION_DATA_DEFAULT="reference/example/"
|
| 242 |
+
INPUT_TYPE_DEFAULT="manager"
|
| 243 |
+
OUTPUT_TYPE_DEFAULT="all"
|
| 244 |
+
ZMQ_HOST_DEFAULT="localhost"
|
| 245 |
+
|
| 246 |
+
# Initialize with defaults (will be set after parsing)
|
| 247 |
+
CHECKPOINT="$CHECKPOINT_DEFAULT"
|
| 248 |
+
OBS_CONFIG="$OBS_CONFIG_DEFAULT"
|
| 249 |
+
PLANNER="$PLANNER_DEFAULT"
|
| 250 |
+
MOTION_DATA="$MOTION_DATA_DEFAULT"
|
| 251 |
+
INPUT_TYPE="$INPUT_TYPE_DEFAULT"
|
| 252 |
+
OUTPUT_TYPE="$OUTPUT_TYPE_DEFAULT"
|
| 253 |
+
ZMQ_HOST="$ZMQ_HOST_DEFAULT"
|
| 254 |
+
|
| 255 |
+
# Parse arguments
|
| 256 |
+
while [[ $# -gt 0 ]]; do
|
| 257 |
+
case $1 in
|
| 258 |
+
-h|--help)
|
| 259 |
+
show_usage
|
| 260 |
+
exit 0
|
| 261 |
+
;;
|
| 262 |
+
--cp|--checkpoint)
|
| 263 |
+
if [[ -z "$2" ]]; then
|
| 264 |
+
echo -e "${RED}Error: --cp/--checkpoint requires a path argument${NC}" >&2
|
| 265 |
+
exit 1
|
| 266 |
+
fi
|
| 267 |
+
CHECKPOINT="$2"
|
| 268 |
+
shift 2
|
| 269 |
+
;;
|
| 270 |
+
--obs-config)
|
| 271 |
+
if [[ -z "$2" ]]; then
|
| 272 |
+
echo -e "${RED}Error: --obs-config requires a path argument${NC}" >&2
|
| 273 |
+
exit 1
|
| 274 |
+
fi
|
| 275 |
+
OBS_CONFIG="$2"
|
| 276 |
+
shift 2
|
| 277 |
+
;;
|
| 278 |
+
--planner)
|
| 279 |
+
if [[ -z "$2" ]]; then
|
| 280 |
+
echo -e "${RED}Error: --planner requires a path argument${NC}" >&2
|
| 281 |
+
exit 1
|
| 282 |
+
fi
|
| 283 |
+
PLANNER="$2"
|
| 284 |
+
shift 2
|
| 285 |
+
;;
|
| 286 |
+
--motion-data)
|
| 287 |
+
if [[ -z "$2" ]]; then
|
| 288 |
+
echo -e "${RED}Error: --motion-data requires a path argument${NC}" >&2
|
| 289 |
+
exit 1
|
| 290 |
+
fi
|
| 291 |
+
MOTION_DATA="$2"
|
| 292 |
+
shift 2
|
| 293 |
+
;;
|
| 294 |
+
--input-type)
|
| 295 |
+
if [[ -z "$2" ]]; then
|
| 296 |
+
echo -e "${RED}Error: --input-type requires a type argument${NC}" >&2
|
| 297 |
+
exit 1
|
| 298 |
+
fi
|
| 299 |
+
INPUT_TYPE="$2"
|
| 300 |
+
shift 2
|
| 301 |
+
;;
|
| 302 |
+
--output-type)
|
| 303 |
+
if [[ -z "$2" ]]; then
|
| 304 |
+
echo -e "${RED}Error: --output-type requires a type argument${NC}" >&2
|
| 305 |
+
exit 1
|
| 306 |
+
fi
|
| 307 |
+
OUTPUT_TYPE="$2"
|
| 308 |
+
shift 2
|
| 309 |
+
;;
|
| 310 |
+
--zmq-host)
|
| 311 |
+
if [[ -z "$2" ]]; then
|
| 312 |
+
echo -e "${RED}Error: --zmq-host requires a host argument${NC}" >&2
|
| 313 |
+
exit 1
|
| 314 |
+
fi
|
| 315 |
+
ZMQ_HOST="$2"
|
| 316 |
+
shift 2
|
| 317 |
+
;;
|
| 318 |
+
sim|real)
|
| 319 |
+
INTERFACE_MODE="$1"
|
| 320 |
+
shift
|
| 321 |
+
;;
|
| 322 |
+
*)
|
| 323 |
+
# Could be interface name or IP
|
| 324 |
+
INTERFACE_MODE="$1"
|
| 325 |
+
shift
|
| 326 |
+
;;
|
| 327 |
+
esac
|
| 328 |
+
done
|
| 329 |
+
|
| 330 |
+
# ============================================================================
|
| 331 |
+
# Display Header
|
| 332 |
+
# ============================================================================
|
| 333 |
+
|
| 334 |
+
echo -e "${CYAN}"
|
| 335 |
+
echo "╔══════════════════════════════════════════════════════════════════════╗"
|
| 336 |
+
echo "║ G1 DEPLOY LAUNCHER ║"
|
| 337 |
+
echo "╚══════════════════════════════════════════════════════════════════════╝"
|
| 338 |
+
echo -e "${NC}"
|
| 339 |
+
|
| 340 |
+
# ============================================================================
|
| 341 |
+
# Resolve Interface
|
| 342 |
+
# ============================================================================
|
| 343 |
+
|
| 344 |
+
echo -e "${BLUE}[Interface Resolution]${NC}"
|
| 345 |
+
echo "Requested mode: $INTERFACE_MODE"
|
| 346 |
+
|
| 347 |
+
resolve_interface "$INTERFACE_MODE"
|
| 348 |
+
|
| 349 |
+
echo -e "Resolved interface: ${GREEN}$TARGET${NC}"
|
| 350 |
+
echo -e "Environment type: ${GREEN}$ENV_TYPE${NC}"
|
| 351 |
+
echo ""
|
| 352 |
+
|
| 353 |
+
# ============================================================================
|
| 354 |
+
# Configuration
|
| 355 |
+
# ============================================================================
|
| 356 |
+
|
| 357 |
+
# Model checkpoint path (set via command line or default)
|
| 358 |
+
# CHECKPOINT and OBS_CONFIG are already set from argument parsing above
|
| 359 |
+
|
| 360 |
+
# Decoder and Encoder ONNX models
|
| 361 |
+
CHECKPOINT_DECODER="${CHECKPOINT}_decoder.onnx"
|
| 362 |
+
CHECKPOINT_ENCODER="${CHECKPOINT}_encoder.onnx"
|
| 363 |
+
|
| 364 |
+
# Motion data path (set via command line or default)
|
| 365 |
+
# MOTION_DATA is already set from argument parsing above
|
| 366 |
+
|
| 367 |
+
# Observation config (set via command line or default)
|
| 368 |
+
# OBS_CONFIG is already set from argument parsing above
|
| 369 |
+
|
| 370 |
+
# Planner model (set via command line or default)
|
| 371 |
+
# PLANNER is already set from argument parsing above
|
| 372 |
+
|
| 373 |
+
# Input type (set via command line or default)
|
| 374 |
+
# INPUT_TYPE is already set from argument parsing above
|
| 375 |
+
|
| 376 |
+
# Output type (set via command line or default)
|
| 377 |
+
# OUTPUT_TYPE is already set from argument parsing above
|
| 378 |
+
|
| 379 |
+
# ZMQ host (set via command line or default)
|
| 380 |
+
# ZMQ_HOST is already set from argument parsing above
|
| 381 |
+
|
| 382 |
+
# Additional flags for simulation mode
|
| 383 |
+
EXTRA_ARGS=""
|
| 384 |
+
if [[ "$ENV_TYPE" == "sim" ]]; then
|
| 385 |
+
EXTRA_ARGS="--disable-crc-check"
|
| 386 |
+
echo -e "${YELLOW}📋 Simulation mode: CRC check will be disabled${NC}"
|
| 387 |
+
echo ""
|
| 388 |
+
fi
|
| 389 |
+
|
| 390 |
+
# ============================================================================
|
| 391 |
+
# Step 1: Check Prerequisites
|
| 392 |
+
# ============================================================================
|
| 393 |
+
|
| 394 |
+
echo -e "${BLUE}[Step 1/4]${NC} Checking prerequisites..."
|
| 395 |
+
|
| 396 |
+
# Check for TensorRT
|
| 397 |
+
if [ -z "$TensorRT_ROOT" ]; then
|
| 398 |
+
echo -e "${YELLOW}⚠️ TensorRT_ROOT is not set.${NC}"
|
| 399 |
+
echo " Please ensure TensorRT is installed and add to your ~/.bashrc:"
|
| 400 |
+
echo " export TensorRT_ROOT=\$HOME/TensorRT"
|
| 401 |
+
echo ""
|
| 402 |
+
echo " Get TensorRT from: https://developer.nvidia.com/tensorrt/download/10x"
|
| 403 |
+
|
| 404 |
+
# Check if it exists in common locations
|
| 405 |
+
if [ -d "$HOME/TensorRT" ]; then
|
| 406 |
+
echo -e "${GREEN} Found TensorRT at ~/TensorRT - setting temporarily${NC}"
|
| 407 |
+
export TensorRT_ROOT="$HOME/TensorRT"
|
| 408 |
+
fi
|
| 409 |
+
fi
|
| 410 |
+
|
| 411 |
+
# Check for required model files
|
| 412 |
+
check_file() {
|
| 413 |
+
if [ ! -f "$1" ]; then
|
| 414 |
+
echo -e "${RED}❌ Missing file: $1${NC}"
|
| 415 |
+
return 1
|
| 416 |
+
else
|
| 417 |
+
echo -e "${GREEN}✅ Found: $1${NC}"
|
| 418 |
+
return 0
|
| 419 |
+
fi
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
echo ""
|
| 423 |
+
echo "Checking required model files..."
|
| 424 |
+
MISSING_FILES=0
|
| 425 |
+
|
| 426 |
+
check_file "$CHECKPOINT_DECODER" || MISSING_FILES=$((MISSING_FILES + 1))
|
| 427 |
+
check_file "$CHECKPOINT_ENCODER" || MISSING_FILES=$((MISSING_FILES + 1))
|
| 428 |
+
check_file "$OBS_CONFIG" || MISSING_FILES=$((MISSING_FILES + 1))
|
| 429 |
+
check_file "$PLANNER" || MISSING_FILES=$((MISSING_FILES + 1))
|
| 430 |
+
|
| 431 |
+
if [ -d "$MOTION_DATA" ]; then
|
| 432 |
+
echo -e "${GREEN}✅ Found: $MOTION_DATA${NC}"
|
| 433 |
+
else
|
| 434 |
+
echo -e "${RED}❌ Missing directory: $MOTION_DATA${NC}"
|
| 435 |
+
MISSING_FILES=$((MISSING_FILES + 1))
|
| 436 |
+
fi
|
| 437 |
+
|
| 438 |
+
if [ $MISSING_FILES -gt 0 ]; then
|
| 439 |
+
echo -e "${YELLOW}⚠️ Some files are missing. Make sure you have pulled the model files.${NC}"
|
| 440 |
+
echo " You may need to run: git lfs pull"
|
| 441 |
+
fi
|
| 442 |
+
|
| 443 |
+
echo ""
|
| 444 |
+
|
| 445 |
+
# ============================================================================
|
| 446 |
+
# Step 2: Install Dependencies (if needed)
|
| 447 |
+
# ============================================================================
|
| 448 |
+
|
| 449 |
+
echo -e "${BLUE}[Step 2/4]${NC} Checking/Installing dependencies..."
|
| 450 |
+
|
| 451 |
+
# Check if just is installed
|
| 452 |
+
if ! command -v just &> /dev/null; then
|
| 453 |
+
echo "Installing dependencies (just not found)..."
|
| 454 |
+
chmod +x scripts/install_deps.sh
|
| 455 |
+
./scripts/install_deps.sh
|
| 456 |
+
else
|
| 457 |
+
echo -e "${GREEN}✅ just is already installed${NC}"
|
| 458 |
+
fi
|
| 459 |
+
|
| 460 |
+
# Check if other essential tools are available
|
| 461 |
+
DEPS_OK=true
|
| 462 |
+
for cmd in cmake clang git; do
|
| 463 |
+
if ! command -v $cmd &> /dev/null; then
|
| 464 |
+
echo -e "${YELLOW}⚠️ $cmd not found, will run install_deps.sh${NC}"
|
| 465 |
+
DEPS_OK=false
|
| 466 |
+
break
|
| 467 |
+
fi
|
| 468 |
+
done
|
| 469 |
+
|
| 470 |
+
if [ "$DEPS_OK" = false ]; then
|
| 471 |
+
echo "Installing missing dependencies..."
|
| 472 |
+
chmod +x scripts/install_deps.sh
|
| 473 |
+
./scripts/install_deps.sh
|
| 474 |
+
else
|
| 475 |
+
echo -e "${GREEN}✅ All essential tools are installed${NC}"
|
| 476 |
+
fi
|
| 477 |
+
|
| 478 |
+
echo ""
|
| 479 |
+
|
| 480 |
+
# ============================================================================
|
| 481 |
+
# Step 3: Setup Environment & Build
|
| 482 |
+
# ============================================================================
|
| 483 |
+
|
| 484 |
+
echo -e "${BLUE}[Step 3/4]${NC} Setting up environment and building..."
|
| 485 |
+
|
| 486 |
+
# Source the environment setup script
|
| 487 |
+
echo "Sourcing environment setup..."
|
| 488 |
+
set +e # Temporarily allow errors (for jetson_clocks on non-Jetson systems)
|
| 489 |
+
source scripts/setup_env.sh
|
| 490 |
+
set -e # Re-enable exit on error
|
| 491 |
+
|
| 492 |
+
# Always build to ensure we have the latest version
|
| 493 |
+
echo "Building the project..."
|
| 494 |
+
just build
|
| 495 |
+
|
| 496 |
+
echo ""
|
| 497 |
+
|
| 498 |
+
# ============================================================================
|
| 499 |
+
# Step 4: Deploy
|
| 500 |
+
# ============================================================================
|
| 501 |
+
|
| 502 |
+
echo -e "${BLUE}[Step 4/4]${NC} Ready to deploy!"
|
| 503 |
+
echo ""
|
| 504 |
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════════════${NC}"
|
| 505 |
+
echo -e "${CYAN} DEPLOYMENT CONFIGURATION ${NC}"
|
| 506 |
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════════════${NC}"
|
| 507 |
+
echo ""
|
| 508 |
+
echo -e " Environment: ${GREEN}$ENV_TYPE${NC}"
|
| 509 |
+
echo -e " Network Interface: ${GREEN}$TARGET${NC}"
|
| 510 |
+
echo -e " Decoder Model: ${GREEN}$CHECKPOINT_DECODER${NC}"
|
| 511 |
+
echo -e " Encoder Model: ${GREEN}$CHECKPOINT_ENCODER${NC}"
|
| 512 |
+
echo -e " Motion Data: ${GREEN}$MOTION_DATA${NC}"
|
| 513 |
+
echo -e " Obs Config: ${GREEN}$OBS_CONFIG${NC}"
|
| 514 |
+
echo -e " Planner: ${GREEN}$PLANNER${NC}"
|
| 515 |
+
echo -e " Input Type: ${GREEN}$INPUT_TYPE${NC}"
|
| 516 |
+
echo -e " Output Type: ${GREEN}$OUTPUT_TYPE${NC}"
|
| 517 |
+
echo -e " ZMQ Host: ${GREEN}$ZMQ_HOST${NC}"
|
| 518 |
+
if [[ -n "$EXTRA_ARGS" ]]; then
|
| 519 |
+
echo -e " Extra Args: ${GREEN}$EXTRA_ARGS${NC}"
|
| 520 |
+
fi
|
| 521 |
+
echo ""
|
| 522 |
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════════════${NC}"
|
| 523 |
+
echo ""
|
| 524 |
+
echo -e "${YELLOW}The following command will be executed:${NC}"
|
| 525 |
+
echo ""
|
| 526 |
+
echo -e "${BLUE}just run g1_deploy_onnx_ref $TARGET $CHECKPOINT_DECODER $MOTION_DATA \\${NC}"
|
| 527 |
+
echo -e "${BLUE} --obs-config $OBS_CONFIG \\${NC}"
|
| 528 |
+
echo -e "${BLUE} --encoder-file $CHECKPOINT_ENCODER \\${NC}"
|
| 529 |
+
echo -e "${BLUE} --planner-file $PLANNER \\${NC}"
|
| 530 |
+
echo -e "${BLUE} --input-type $INPUT_TYPE \\${NC}"
|
| 531 |
+
echo -e "${BLUE} --output-type $OUTPUT_TYPE \\${NC}"
|
| 532 |
+
echo -e "${BLUE} --zmq-host $ZMQ_HOST${NC}"
|
| 533 |
+
if [[ -n "$EXTRA_ARGS" ]]; then
|
| 534 |
+
echo -e "${BLUE} $EXTRA_ARGS${NC}"
|
| 535 |
+
fi
|
| 536 |
+
echo ""
|
| 537 |
+
echo -e "${CYAN}═══════════════════════════════════════════════════════════════════════${NC}"
|
| 538 |
+
echo ""
|
| 539 |
+
|
| 540 |
+
# Ask for confirmation
|
| 541 |
+
if [[ "$ENV_TYPE" == "real" ]]; then
|
| 542 |
+
echo -e "${YELLOW}⚠️ WARNING: This will start the REAL robot control system!${NC}"
|
| 543 |
+
else
|
| 544 |
+
echo -e "${YELLOW}📋 This will start the simulation control system.${NC}"
|
| 545 |
+
fi
|
| 546 |
+
echo ""
|
| 547 |
+
read -p "$(echo -e ${GREEN}Proceed with deployment? [Y/n]: ${NC})" confirm
|
| 548 |
+
|
| 549 |
+
if [[ "$confirm" =~ ^[Yy]$ ]] || [[ -z "$confirm" ]]; then
|
| 550 |
+
echo ""
|
| 551 |
+
echo -e "${GREEN}🚀 Starting deployment...${NC}"
|
| 552 |
+
echo ""
|
| 553 |
+
|
| 554 |
+
# Build the command with optional extra args
|
| 555 |
+
if [[ -n "$EXTRA_ARGS" ]]; then
|
| 556 |
+
just run g1_deploy_onnx_ref "$TARGET" "$CHECKPOINT_DECODER" "$MOTION_DATA" \
|
| 557 |
+
--obs-config "$OBS_CONFIG" \
|
| 558 |
+
--encoder-file "$CHECKPOINT_ENCODER" \
|
| 559 |
+
--planner-file "$PLANNER" \
|
| 560 |
+
--input-type "$INPUT_TYPE" \
|
| 561 |
+
--output-type "$OUTPUT_TYPE" \
|
| 562 |
+
--zmq-host "$ZMQ_HOST" \
|
| 563 |
+
$EXTRA_ARGS
|
| 564 |
+
else
|
| 565 |
+
just run g1_deploy_onnx_ref "$TARGET" "$CHECKPOINT_DECODER" "$MOTION_DATA" \
|
| 566 |
+
--obs-config "$OBS_CONFIG" \
|
| 567 |
+
--encoder-file "$CHECKPOINT_ENCODER" \
|
| 568 |
+
--planner-file "$PLANNER" \
|
| 569 |
+
--input-type "$INPUT_TYPE" \
|
| 570 |
+
--output-type "$OUTPUT_TYPE" \
|
| 571 |
+
--zmq-host "$ZMQ_HOST"
|
| 572 |
+
fi
|
| 573 |
+
else
|
| 574 |
+
echo ""
|
| 575 |
+
echo -e "${YELLOW}Deployment cancelled.${NC}"
|
| 576 |
+
exit 0
|
| 577 |
+
fi
|
GR00T-WholeBodyControl/gear_sonic_deploy/visualize_motion.py
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import argparse
|
| 2 |
+
import csv
|
| 3 |
+
import os
|
| 4 |
+
import time
|
| 5 |
+
from scipy.spatial.transform import Rotation as R
|
| 6 |
+
|
| 7 |
+
import mujoco
|
| 8 |
+
import mujoco.viewer
|
| 9 |
+
import numpy as np
|
| 10 |
+
|
| 11 |
+
from lxml import etree
|
| 12 |
+
|
| 13 |
+
import zmq
|
| 14 |
+
import threading
|
| 15 |
+
import msgpack
|
| 16 |
+
|
| 17 |
+
def key_call_back(keycode):
|
| 18 |
+
global \
|
| 19 |
+
curr_start, \
|
| 20 |
+
num_motions, \
|
| 21 |
+
motion_id, \
|
| 22 |
+
motion_acc, \
|
| 23 |
+
time_step, \
|
| 24 |
+
dt, \
|
| 25 |
+
paused, \
|
| 26 |
+
data_csv_dict, \
|
| 27 |
+
frame_idx, \
|
| 28 |
+
anim_idx
|
| 29 |
+
|
| 30 |
+
try:
|
| 31 |
+
c = chr(keycode)
|
| 32 |
+
except:
|
| 33 |
+
c = ""
|
| 34 |
+
if c == "R":
|
| 35 |
+
print("Reset")
|
| 36 |
+
frame_idx = int(0)
|
| 37 |
+
elif c == " ":
|
| 38 |
+
print("Paused")
|
| 39 |
+
paused = not paused
|
| 40 |
+
elif c == ".":
|
| 41 |
+
frame_idx = frame_idx + 1
|
| 42 |
+
print("frame", frame_idx)
|
| 43 |
+
elif c == ",":
|
| 44 |
+
frame_idx = frame_idx - 1
|
| 45 |
+
print("frame", frame_idx)
|
| 46 |
+
elif c == "=":
|
| 47 |
+
anim_idx = anim_idx + 1
|
| 48 |
+
print("anim", anim_idx)
|
| 49 |
+
elif c == "-":
|
| 50 |
+
anim_idx = anim_idx - 1
|
| 51 |
+
print("anim", anim_idx)
|
| 52 |
+
else:
|
| 53 |
+
print("not mapped", c)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def load_anim_data(csv_path: str):
|
| 57 |
+
|
| 58 |
+
ret = []
|
| 59 |
+
if os.path.isdir(csv_path):
|
| 60 |
+
|
| 61 |
+
joint_pos_path = os.path.join(csv_path, "joint_pos.csv")
|
| 62 |
+
body_pos_path = os.path.join(csv_path, "body_pos.csv")
|
| 63 |
+
body_quat_path = os.path.join(csv_path, "body_quat.csv")
|
| 64 |
+
|
| 65 |
+
isaaclab_to_mujoco = [0, 3, 6, 9, 13, 17, 1, 4, 7, 10, 14, 18, 2, 5, 8,
|
| 66 |
+
11, 15, 19, 21, 23, 25, 27, 12, 16, 20, 22, 24, 26, 28]
|
| 67 |
+
|
| 68 |
+
with open(joint_pos_path, mode="r", newline="") as joint_pos_file, open(body_pos_path, mode="r", newline="") as body_pos_file, open(body_quat_path, mode="r", newline="") as body_quat_file:
|
| 69 |
+
firstRow = True
|
| 70 |
+
joint_pos_rowlist = []
|
| 71 |
+
body_pos_rowlist = []
|
| 72 |
+
body_quat_rowlist = []
|
| 73 |
+
for joint_pos_row, body_pos_row, body_quat_row in zip(joint_pos_file, body_pos_file, body_quat_file):
|
| 74 |
+
if firstRow:
|
| 75 |
+
firstRow = False
|
| 76 |
+
continue
|
| 77 |
+
|
| 78 |
+
joint_pos_row = np.array([float(x) for x in joint_pos_row.split(",")])
|
| 79 |
+
body_pos_row = np.array([float(x) for x in body_pos_row.split(",")])
|
| 80 |
+
body_quat_row = np.array([float(x) for x in body_quat_row.split(",")])
|
| 81 |
+
|
| 82 |
+
joint_pos_rowlist.append(joint_pos_row)
|
| 83 |
+
body_pos_rowlist.append(body_pos_row)
|
| 84 |
+
body_quat_rowlist.append(body_quat_row)
|
| 85 |
+
|
| 86 |
+
ret.append({
|
| 87 |
+
"dof": np.array(joint_pos_rowlist)[:, isaaclab_to_mujoco],
|
| 88 |
+
"root_rot": np.array(body_quat_rowlist)[:, [0, 1, 2, 3]], # [x, y, z, w]
|
| 89 |
+
"root_trans_offset": np.array(body_pos_rowlist)[:, :3],
|
| 90 |
+
})
|
| 91 |
+
|
| 92 |
+
else:
|
| 93 |
+
csv_data = []
|
| 94 |
+
current_rowlist = []
|
| 95 |
+
with open(csv_path, mode="r", newline="") as file:
|
| 96 |
+
|
| 97 |
+
csv_reader = csv.reader(file)
|
| 98 |
+
for row in csv_reader:
|
| 99 |
+
if len(row):
|
| 100 |
+
r = [x for x in row if x]
|
| 101 |
+
assert len(r) == 36
|
| 102 |
+
current_rowlist.append(r)
|
| 103 |
+
else:
|
| 104 |
+
csv_data.append(current_rowlist)
|
| 105 |
+
current_rowlist = []
|
| 106 |
+
|
| 107 |
+
if current_rowlist:
|
| 108 |
+
csv_data.append(current_rowlist)
|
| 109 |
+
|
| 110 |
+
for d in csv_data:
|
| 111 |
+
ret.append({
|
| 112 |
+
"dof": np.array(d)[:, 7:],
|
| 113 |
+
"root_rot": np.array(d)[:, 3:7][:, [0, 1, 2, 3]], # [x, y, z, w]
|
| 114 |
+
"root_trans_offset": np.array(d)[:, :3],
|
| 115 |
+
})
|
| 116 |
+
|
| 117 |
+
return ret
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
def receive_realtime_debug_messages(socket, data_csv_dicts, topic):
|
| 121 |
+
while True:
|
| 122 |
+
message = socket.recv()
|
| 123 |
+
|
| 124 |
+
# Remove any header or leading bytes (should be exactly 8 bytes for "g1_debug")
|
| 125 |
+
data = message.split(topic.encode())[1]
|
| 126 |
+
|
| 127 |
+
result = msgpack.unpackb(data)
|
| 128 |
+
|
| 129 |
+
data_csv_dicts[0]["root_trans_offset"][0, ...] = result["base_trans_target"]
|
| 130 |
+
data_csv_dicts[0]["root_rot"][0, ...] = result["base_quat_target"]
|
| 131 |
+
data_csv_dicts[0]["dof"][0, ...] = result["body_q_target"]
|
| 132 |
+
|
| 133 |
+
data_csv_dicts[0]["root_trans_offset_measured"][0, ...] = result["base_trans_measured"]
|
| 134 |
+
data_csv_dicts[0]["root_rot_measured"][0, ...] = result["base_quat_measured"]
|
| 135 |
+
data_csv_dicts[0]["dof_measured"][0, ...] = result["body_q_measured"]
|
| 136 |
+
|
| 137 |
+
data_csv_dicts[0]["vr_3point_position"] = np.array(result["vr_3point_position"]).reshape(3,3)
|
| 138 |
+
data_csv_dicts[0]["vr_3point_orientation"] = np.array(result["vr_3point_orientation"]).reshape(3,4)
|
| 139 |
+
data_csv_dicts[0]["vr_3point_compliance"] = np.array(result["vr_3point_compliance"]).reshape(3)
|
| 140 |
+
|
| 141 |
+
if "motor_temperature" in result:
|
| 142 |
+
temps = np.array(result["motor_temperature"])
|
| 143 |
+
# 58 values: 29 motors × 2 (winding, driver). Take max per motor.
|
| 144 |
+
data_csv_dicts[0]["motor_temperature"] = np.maximum(temps[0::2], temps[1::2]) # shape (29,)
|
| 145 |
+
|
| 146 |
+
def main(args) -> None:
|
| 147 |
+
global \
|
| 148 |
+
curr_start, \
|
| 149 |
+
num_motions, \
|
| 150 |
+
motion_id, \
|
| 151 |
+
motion_acc, \
|
| 152 |
+
time_step, \
|
| 153 |
+
dt, \
|
| 154 |
+
paused, \
|
| 155 |
+
data_csv_dict, \
|
| 156 |
+
frame_idx, \
|
| 157 |
+
anim_idx
|
| 158 |
+
|
| 159 |
+
fps = 50
|
| 160 |
+
curr_start, num_motions, motion_id, motion_acc, time_step, dt, paused, frame_idx, anim_idx = 0, 1, 0, set(), 0, 1 / fps, False, int(0), 0
|
| 161 |
+
|
| 162 |
+
def prepend_names(elem, prefix):
|
| 163 |
+
# If element has a 'name' attribute, prepend the prefix
|
| 164 |
+
if 'name' in elem.attrib:
|
| 165 |
+
elem.attrib['name'] = prefix + elem.attrib['name']
|
| 166 |
+
# Recurse for all child elements
|
| 167 |
+
for child in elem:
|
| 168 |
+
prepend_names(child, prefix)
|
| 169 |
+
|
| 170 |
+
def replace_attribute(elem, attribute, value):
|
| 171 |
+
# If element has a 'name' attribute, prepend the prefix
|
| 172 |
+
if attribute in elem.attrib:
|
| 173 |
+
elem.attrib[attribute] = value
|
| 174 |
+
# Recurse for all child elements
|
| 175 |
+
for child in elem:
|
| 176 |
+
replace_attribute(child, attribute, value)
|
| 177 |
+
|
| 178 |
+
main_scene = etree.parse('g1/scene_empty.xml')
|
| 179 |
+
robot1 = etree.parse('g1/g1_29dof_old.xml')
|
| 180 |
+
robot_asset = robot1.find('asset')
|
| 181 |
+
scene_asset = main_scene.find('asset')
|
| 182 |
+
for mesh in robot_asset.findall('mesh'):
|
| 183 |
+
# INSERT_YOUR_CODE
|
| 184 |
+
mesh.set("file", os.path.join("g1","meshes", mesh.get('file')))
|
| 185 |
+
scene_asset.append(mesh)
|
| 186 |
+
|
| 187 |
+
robot_default = robot1.find('default')
|
| 188 |
+
scene_default = main_scene.find('default')
|
| 189 |
+
for default in robot_default.findall('default'):
|
| 190 |
+
scene_default.append(default)
|
| 191 |
+
|
| 192 |
+
scene_worldbody = main_scene.find('worldbody')
|
| 193 |
+
robot1_body = robot1.find('worldbody').find('body')
|
| 194 |
+
prepend_names(robot1_body, "robot1_")
|
| 195 |
+
scene_worldbody.append(robot1_body)
|
| 196 |
+
|
| 197 |
+
robot2 = etree.parse('g1/g1_29dof_old.xml')
|
| 198 |
+
robot2_body = robot2.find('worldbody').find('body')
|
| 199 |
+
prepend_names(robot2_body, "robot2_")
|
| 200 |
+
replace_attribute(robot2_body, "rgba", "0.5 0.1 0.1 1")
|
| 201 |
+
robot2_body.set("pos", "0 -1 -10")
|
| 202 |
+
scene_worldbody.append(robot2_body)
|
| 203 |
+
|
| 204 |
+
robot3 = etree.parse('g1/g1_29dof_old.xml')
|
| 205 |
+
robot3_body = robot3.find('worldbody').find('body')
|
| 206 |
+
prepend_names(robot3_body, "robot3_")
|
| 207 |
+
replace_attribute(robot3_body, "rgba", "0.1 0.5 0.1 0.2")
|
| 208 |
+
robot3_body.set("pos", "0 -2 -10")
|
| 209 |
+
scene_worldbody.append(robot3_body)
|
| 210 |
+
|
| 211 |
+
# Robot 4: temperature visualization robot (white transparent, offset 3m to the right)
|
| 212 |
+
robot4 = etree.parse('g1/g1_29dof_old.xml')
|
| 213 |
+
robot4_body = robot4.find('worldbody').find('body')
|
| 214 |
+
prepend_names(robot4_body, "robot4_")
|
| 215 |
+
replace_attribute(robot4_body, "rgba", "0.8 0.8 0.8 0.1")
|
| 216 |
+
robot4_body.set("pos", "0 -3 -10")
|
| 217 |
+
scene_worldbody.append(robot4_body)
|
| 218 |
+
|
| 219 |
+
mj_model = mujoco.MjModel.from_xml_string(etree.tostring(main_scene, pretty_print=True, encoding="unicode"))
|
| 220 |
+
mj_data = mujoco.MjData(mj_model)
|
| 221 |
+
|
| 222 |
+
# Disable advanced visual effects for better performance
|
| 223 |
+
mj_model.vis.global_.offwidth = 1920
|
| 224 |
+
mj_model.vis.global_.offheight = 1080
|
| 225 |
+
mj_model.vis.quality.shadowsize = 0 # Disable shadows
|
| 226 |
+
mj_model.vis.quality.offsamples = 1 # Reduce anti-aliasing
|
| 227 |
+
mj_model.vis.rgba.fog = [0, 0, 0, 0] # Disable fog
|
| 228 |
+
|
| 229 |
+
# Disable advanced lighting effects
|
| 230 |
+
mj_model.vis.headlight.ambient = [0.8, 0.8, 0.8] # Increase ambient light
|
| 231 |
+
mj_model.vis.headlight.diffuse = [0.8, 0.8, 0.8] # Increase diffuse light
|
| 232 |
+
mj_model.vis.headlight.specular = [0.1, 0.1, 0.1] # Reduce specular highlights
|
| 233 |
+
|
| 234 |
+
if args.realtime_debug_url:
|
| 235 |
+
context = zmq.Context()
|
| 236 |
+
socket = context.socket(zmq.SUB)
|
| 237 |
+
socket.connect(args.realtime_debug_url)
|
| 238 |
+
socket.setsockopt(zmq.SUBSCRIBE, args.realtime_debug_topic.encode())
|
| 239 |
+
|
| 240 |
+
data_csv_dicts = [{
|
| 241 |
+
"dof": np.zeros((1,29), dtype=np.float64),
|
| 242 |
+
"root_rot": np.array([[0.0, 0.0, 0.0, 1.0]]), # [x, y, z, w]
|
| 243 |
+
"root_trans_offset": np.array([[0.0, 0.0, .9]], dtype=np.float64),
|
| 244 |
+
"dof_measured": np.zeros((1,29), dtype=np.float64),
|
| 245 |
+
"root_rot_measured": np.array([[0.0, 0.0, 0.0, 1.0]]),
|
| 246 |
+
"root_trans_offset_measured": np.array([[0.0, 0.0, 0.0]], dtype=np.float64),
|
| 247 |
+
"vr_3point_position": np.zeros((3,3), dtype=np.float64),
|
| 248 |
+
"vr_3point_orientation": np.zeros((3,4), dtype=np.float64),
|
| 249 |
+
"vr_3point_compliance": np.zeros((3), dtype=np.float64),
|
| 250 |
+
"motor_temperature": np.zeros(29, dtype=np.float64),
|
| 251 |
+
}]
|
| 252 |
+
|
| 253 |
+
threading.Thread(target=receive_realtime_debug_messages, args=(socket, data_csv_dicts, args.realtime_debug_topic)).start()
|
| 254 |
+
|
| 255 |
+
elif args.motion_dir:
|
| 256 |
+
data_csv_dicts = load_anim_data(args.motion_dir)
|
| 257 |
+
elif args.csv_path:
|
| 258 |
+
data_csv_dicts = load_anim_data(args.csv_path)
|
| 259 |
+
else:
|
| 260 |
+
raise ValueError("Either --realtime_debug_url, --motion_dir, or --csv_path must be provided")
|
| 261 |
+
|
| 262 |
+
RECORDING = False
|
| 263 |
+
mj_model.opt.timestep = dt
|
| 264 |
+
try:
|
| 265 |
+
context = mujoco.GLContext(1920, 1080)
|
| 266 |
+
context.make_current()
|
| 267 |
+
print("✓ GPU acceleration enabled")
|
| 268 |
+
except Exception as e:
|
| 269 |
+
print(f"✗ GPU acceleration not available: {e}")
|
| 270 |
+
context = None
|
| 271 |
+
|
| 272 |
+
with mujoco.viewer.launch_passive(
|
| 273 |
+
mj_model,
|
| 274 |
+
mj_data,
|
| 275 |
+
key_callback=key_call_back,
|
| 276 |
+
show_left_ui=False,
|
| 277 |
+
show_right_ui=False,
|
| 278 |
+
) as viewer:
|
| 279 |
+
# Set camera position to be further away
|
| 280 |
+
viewer.cam.distance = 15.0 # Increase distance from the scene
|
| 281 |
+
viewer.cam.azimuth = 90.0 # Set azimuth angle
|
| 282 |
+
viewer.cam.elevation = -20.0 # Set elevation angle
|
| 283 |
+
|
| 284 |
+
while viewer.is_running():
|
| 285 |
+
motion_len = data_csv_dicts[anim_idx % len(data_csv_dicts)]["dof"].shape[0]
|
| 286 |
+
step_start = time.time()
|
| 287 |
+
time_idx = frame_idx % motion_len
|
| 288 |
+
data_dict = data_csv_dicts[anim_idx % len(data_csv_dicts)]
|
| 289 |
+
mj_data.qpos[:3] = data_dict["root_trans_offset"][time_idx]
|
| 290 |
+
mj_data.qpos[3:7] = data_dict["root_rot"][time_idx]
|
| 291 |
+
mj_data.qpos[7:7+29] = data_dict["dof"][time_idx]
|
| 292 |
+
|
| 293 |
+
if "dof_measured" in data_dict:
|
| 294 |
+
mj_data.qpos[36:36+3] = data_dict["root_trans_offset_measured"][time_idx]
|
| 295 |
+
mj_data.qpos[39:39+4] = data_dict["root_rot_measured"][time_idx]
|
| 296 |
+
mj_data.qpos[43:43+29] = data_dict["dof_measured"][time_idx]
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
mj_data.qpos[43+29:43+29+3] = data_dict["root_trans_offset_measured"][time_idx]
|
| 300 |
+
mj_data.qpos[43+29+3:43+29+3+4] = data_dict["root_rot"][time_idx]
|
| 301 |
+
mj_data.qpos[43+29+3+4:43+29+3+4+29] = data_dict["dof"][time_idx]
|
| 302 |
+
|
| 303 |
+
# Robot 4: temperature visualization (copy measured state, offset 3m on y)
|
| 304 |
+
r4_base = 36 * 3 # 108
|
| 305 |
+
r4_pos = data_dict["root_trans_offset_measured"][time_idx].copy()
|
| 306 |
+
r4_pos[1] -= 1.0 # offset 1m to the right
|
| 307 |
+
mj_data.qpos[r4_base:r4_base+3] = r4_pos
|
| 308 |
+
mj_data.qpos[r4_base+3:r4_base+7] = data_dict["root_rot_measured"][time_idx]
|
| 309 |
+
mj_data.qpos[r4_base+7:r4_base+36] = data_dict["dof_measured"][time_idx]
|
| 310 |
+
|
| 311 |
+
mujoco.mj_forward(mj_model, mj_data)
|
| 312 |
+
if not paused:
|
| 313 |
+
frame_idx += 1
|
| 314 |
+
|
| 315 |
+
viewer.user_scn.ngeom = 0
|
| 316 |
+
if "vr_3point_position" in data_dict:
|
| 317 |
+
# Get root pose for transforming root-relative coordinates to world space
|
| 318 |
+
# VR 3-point data from C++ is normalized relative to root (see g1_deploy_onnx_ref.cpp)
|
| 319 |
+
root_trans = data_dict["root_trans_offset_measured"][time_idx]
|
| 320 |
+
root_quat_wxyz = data_dict["root_rot_measured"][time_idx] # [w, x, y, z] format (MuJoCo/C++ convention)
|
| 321 |
+
root_rot = R.from_quat(root_quat_wxyz, scalar_first=True)
|
| 322 |
+
|
| 323 |
+
for i in range(3):
|
| 324 |
+
# VR 3-point position is in root-relative coordinates, transform to world
|
| 325 |
+
vr_pos_root_frame = data_dict["vr_3point_position"][i]
|
| 326 |
+
# vr_pos_world = root_trans + root_rot.apply(vr_pos_root_frame)
|
| 327 |
+
vr_pos_world = vr_pos_root_frame + data_dict["root_trans_offset_measured"][time_idx]
|
| 328 |
+
|
| 329 |
+
if np.linalg.norm(data_dict["vr_3point_orientation"][i]) > 0:
|
| 330 |
+
# VR orientation is also root-relative, transform to world
|
| 331 |
+
# C++ quaternion is in [w, x, y, z] format (scalar_first=True)
|
| 332 |
+
vr_quat_root_frame = R.from_quat(data_dict["vr_3point_orientation"][i], scalar_first=True)
|
| 333 |
+
vr_rot_world = root_rot * vr_quat_root_frame # Quaternion multiplication
|
| 334 |
+
mat = vr_rot_world.as_matrix()
|
| 335 |
+
else:
|
| 336 |
+
mat = root_rot.as_matrix() # If no VR orientation, use root orientation
|
| 337 |
+
|
| 338 |
+
mujoco.mjv_initGeom(
|
| 339 |
+
viewer.user_scn.geoms[i],
|
| 340 |
+
type=mujoco.mjtGeom.mjGEOM_BOX,
|
| 341 |
+
size=[0.05, 0.01, 0.01],
|
| 342 |
+
pos=vr_pos_world,
|
| 343 |
+
mat=mat.flatten(),
|
| 344 |
+
rgba=0.5*np.array([1, 1, 0, 2])
|
| 345 |
+
)
|
| 346 |
+
viewer.user_scn.ngeom += 1
|
| 347 |
+
|
| 348 |
+
# Draw temperature indicators at each joint of the measured robot (robot2_)
|
| 349 |
+
if "motor_temperature" in data_dict:
|
| 350 |
+
# Body names for each motor joint (MuJoCo order, 29 joints)
|
| 351 |
+
motor_body_names = [
|
| 352 |
+
"left_hip_pitch_link", "left_hip_roll_link", "left_hip_yaw_link",
|
| 353 |
+
"left_knee_link", "left_ankle_pitch_link", "left_ankle_roll_link",
|
| 354 |
+
"right_hip_pitch_link", "right_hip_roll_link", "right_hip_yaw_link",
|
| 355 |
+
"right_knee_link", "right_ankle_pitch_link", "right_ankle_roll_link",
|
| 356 |
+
"waist_yaw_link", "waist_roll_link", "torso_link",
|
| 357 |
+
"left_shoulder_pitch_link", "left_shoulder_roll_link", "left_shoulder_yaw_link",
|
| 358 |
+
"left_elbow_link", "left_wrist_roll_link", "left_wrist_pitch_link",
|
| 359 |
+
"left_wrist_yaw_link", "right_shoulder_pitch_link", "right_shoulder_roll_link",
|
| 360 |
+
"right_shoulder_yaw_link", "right_elbow_link", "right_wrist_roll_link",
|
| 361 |
+
"right_wrist_pitch_link", "right_wrist_yaw_link",
|
| 362 |
+
]
|
| 363 |
+
temps = data_dict["motor_temperature"]
|
| 364 |
+
flash = (int(time.time() * 4) % 2 == 0) # 4 Hz flash toggle
|
| 365 |
+
for j in range(min(29, len(temps))):
|
| 366 |
+
t = temps[j]
|
| 367 |
+
body_name = "robot4_" + motor_body_names[j]
|
| 368 |
+
body_id = mj_model.body(body_name).id
|
| 369 |
+
pos = mj_data.xpos[body_id].copy()
|
| 370 |
+
|
| 371 |
+
# Color: green (< 50) -> yellow (50-70) -> orange (70-90) -> red (>= 90, flashing)
|
| 372 |
+
if t >= 90:
|
| 373 |
+
rgba = np.array([1.0, 0.0, 0.0, 1.0 if flash else 0.3])
|
| 374 |
+
elif t >= 70:
|
| 375 |
+
frac = (t - 70) / 20.0
|
| 376 |
+
rgba = np.array([1.0, 0.5 * (1 - frac), 0.0, 0.9])
|
| 377 |
+
elif t >= 50:
|
| 378 |
+
frac = (t - 50) / 20.0
|
| 379 |
+
rgba = np.array([frac, 1.0, 0.0, 0.8])
|
| 380 |
+
else:
|
| 381 |
+
rgba = np.array([0.0, 0.8, 0.0, 0.8])
|
| 382 |
+
|
| 383 |
+
geom_idx = viewer.user_scn.ngeom
|
| 384 |
+
if geom_idx < viewer.user_scn.maxgeom:
|
| 385 |
+
mujoco.mjv_initGeom(
|
| 386 |
+
viewer.user_scn.geoms[geom_idx],
|
| 387 |
+
type=mujoco.mjtGeom.mjGEOM_SPHERE,
|
| 388 |
+
size=[0.04, 0, 0],
|
| 389 |
+
pos=pos,
|
| 390 |
+
mat=np.eye(3).flatten(),
|
| 391 |
+
rgba=rgba,
|
| 392 |
+
)
|
| 393 |
+
viewer.user_scn.ngeom += 1
|
| 394 |
+
|
| 395 |
+
# Pick up changes to the physics state, apply perturbations, update options from GUI.
|
| 396 |
+
viewer.sync()
|
| 397 |
+
time_until_next_step = mj_model.opt.timestep - (time.time() - step_start)
|
| 398 |
+
if time_until_next_step > 0:
|
| 399 |
+
time.sleep(time_until_next_step)
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
if __name__ == "__main__":
|
| 403 |
+
parser = argparse.ArgumentParser(
|
| 404 |
+
description="Visualize retargeted motion data in MuJoCo"
|
| 405 |
+
)
|
| 406 |
+
parser.add_argument(
|
| 407 |
+
"--csv_path",
|
| 408 |
+
type=str,
|
| 409 |
+
default="",
|
| 410 |
+
help="Path to the CSV file containing retargeted motion data",
|
| 411 |
+
)
|
| 412 |
+
parser.add_argument(
|
| 413 |
+
"--motion_dir",
|
| 414 |
+
type=str,
|
| 415 |
+
default="",
|
| 416 |
+
help="Path to the CSV file containing retargeted motion data",
|
| 417 |
+
)
|
| 418 |
+
parser.add_argument(
|
| 419 |
+
"--realtime_debug_url",
|
| 420 |
+
type=str,
|
| 421 |
+
default="",
|
| 422 |
+
help="URL to receive realtime debug messages from",
|
| 423 |
+
)
|
| 424 |
+
parser.add_argument(
|
| 425 |
+
"--realtime_debug_topic",
|
| 426 |
+
type=str,
|
| 427 |
+
default="g1_debug",
|
| 428 |
+
help="Topic to receive realtime debug messages from",
|
| 429 |
+
)
|
| 430 |
+
args = parser.parse_args()
|
| 431 |
+
|
| 432 |
+
main(args)
|
GR00T-WholeBodyControl/install_scripts/install_camera_server.sh
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# install_camera_server.sh
|
| 3 |
+
# Sets up the .venv_camera venv for running the composed camera server
|
| 4 |
+
# on the robot computer.
|
| 5 |
+
#
|
| 6 |
+
# Installs gear_sonic[camera] which includes the ZMQ-based camera server
|
| 7 |
+
# framework and the depthai SDK (OAK cameras). For other camera SDKs
|
| 8 |
+
# (e.g. pyrealsense2), install them into the venv after setup.
|
| 9 |
+
#
|
| 10 |
+
# Usage: bash install_scripts/install_camera_server.sh (run from repo root)
|
| 11 |
+
|
| 12 |
+
set -euo pipefail
|
| 13 |
+
|
| 14 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 15 |
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
| 16 |
+
|
| 17 |
+
# ── 0. Print detected architecture ───────────────────────────────────────────
|
| 18 |
+
ARCH="$(uname -m)"
|
| 19 |
+
echo "[OK] Architecture: $ARCH"
|
| 20 |
+
|
| 21 |
+
# ── 1. Ensure uv is installed and available ──────────────────────────────────
|
| 22 |
+
if ! command -v uv &>/dev/null; then
|
| 23 |
+
echo "[INFO] uv not found – installing via official installer …"
|
| 24 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 25 |
+
|
| 26 |
+
if [ -f "$HOME/.local/bin/env" ]; then
|
| 27 |
+
# shellcheck disable=SC1091
|
| 28 |
+
source "$HOME/.local/bin/env"
|
| 29 |
+
elif [ -f "$HOME/.cargo/env" ]; then
|
| 30 |
+
# shellcheck disable=SC1091
|
| 31 |
+
source "$HOME/.cargo/env"
|
| 32 |
+
else
|
| 33 |
+
export PATH="$HOME/.local/bin:$PATH"
|
| 34 |
+
fi
|
| 35 |
+
|
| 36 |
+
if ! command -v uv &>/dev/null; then
|
| 37 |
+
echo "[ERROR] uv installation succeeded but binary not found on PATH."
|
| 38 |
+
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
|
| 39 |
+
exit 1
|
| 40 |
+
fi
|
| 41 |
+
fi
|
| 42 |
+
echo "[OK] uv $(uv --version)"
|
| 43 |
+
|
| 44 |
+
# ── 2. Install a uv-managed Python 3.10 ─────────────────────────────────────
|
| 45 |
+
echo "[INFO] Installing uv-managed Python 3.10 …"
|
| 46 |
+
uv python install 3.10
|
| 47 |
+
MANAGED_PY="$(uv python find --no-project 3.10)"
|
| 48 |
+
echo "[OK] Using Python: $MANAGED_PY"
|
| 49 |
+
|
| 50 |
+
# ── 3. Clean previous venv (if any) ─────────────────────────────────────────
|
| 51 |
+
cd "$REPO_ROOT"
|
| 52 |
+
echo "[INFO] Removing old .venv_camera (if present) …"
|
| 53 |
+
rm -rf .venv_camera
|
| 54 |
+
|
| 55 |
+
# ── 4. Create venv & install camera extra ────────────────────────────────────
|
| 56 |
+
echo "[INFO] Creating .venv_camera with uv-managed Python 3.10 …"
|
| 57 |
+
uv venv .venv_camera --python "$MANAGED_PY" --prompt gear_sonic_camera
|
| 58 |
+
# shellcheck disable=SC1091
|
| 59 |
+
source .venv_camera/bin/activate
|
| 60 |
+
echo "[INFO] Installing gear_sonic[camera] …"
|
| 61 |
+
uv pip install -e "gear_sonic[camera]"
|
| 62 |
+
|
| 63 |
+
echo ""
|
| 64 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 65 |
+
echo " Camera server venv setup complete!"
|
| 66 |
+
echo " depthai (OAK cameras) is included by default."
|
| 67 |
+
echo ""
|
| 68 |
+
echo " Activate the venv with:"
|
| 69 |
+
echo " source .venv_camera/bin/activate"
|
| 70 |
+
echo ""
|
| 71 |
+
echo " For other camera SDKs, install into the venv:"
|
| 72 |
+
echo " pip install pyrealsense2 # Intel RealSense"
|
| 73 |
+
echo ""
|
| 74 |
+
echo " See docs/source/tutorials/data_collection.md for full setup."
|
| 75 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 76 |
+
|
| 77 |
+
# ── 5. Optionally install the systemd service ────────────────────────────────
|
| 78 |
+
SERVICE_TEMPLATE="$REPO_ROOT/systemd/composed_camera_server.service"
|
| 79 |
+
SERVICE_NAME="composed_camera_server.service"
|
| 80 |
+
|
| 81 |
+
if [ ! -f "$SERVICE_TEMPLATE" ]; then
|
| 82 |
+
echo ""
|
| 83 |
+
echo "[WARN] systemd template not found at $SERVICE_TEMPLATE — skipping."
|
| 84 |
+
exit 0
|
| 85 |
+
fi
|
| 86 |
+
|
| 87 |
+
echo ""
|
| 88 |
+
read -rp "Install the camera server as a systemd service (auto-start on boot)? [y/N] " INSTALL_SERVICE
|
| 89 |
+
if [[ ! "$INSTALL_SERVICE" =~ ^[Yy]$ ]]; then
|
| 90 |
+
echo ""
|
| 91 |
+
echo " Skipped systemd install. You can run the camera server manually:"
|
| 92 |
+
echo " source .venv_camera/bin/activate"
|
| 93 |
+
echo " python -m gear_sonic.camera.composed_camera --ego-view-camera oak --port 5555"
|
| 94 |
+
echo ""
|
| 95 |
+
exit 0
|
| 96 |
+
fi
|
| 97 |
+
|
| 98 |
+
# Gather configuration
|
| 99 |
+
echo ""
|
| 100 |
+
echo "── Camera service configuration ──"
|
| 101 |
+
echo " Each camera needs a type and a device ID so the server knows"
|
| 102 |
+
echo " which physical camera maps to each mount position (ego, wrist, etc.)."
|
| 103 |
+
echo ""
|
| 104 |
+
|
| 105 |
+
detect_oak_cameras() {
|
| 106 |
+
"${REPO_ROOT}/.venv_camera/bin/python" -c "
|
| 107 |
+
import depthai as dai
|
| 108 |
+
devices = dai.Device.getAllAvailableDevices()
|
| 109 |
+
if not devices:
|
| 110 |
+
exit(1)
|
| 111 |
+
for i, d in enumerate(devices):
|
| 112 |
+
# Try to get actual MxID; fall back to string representation
|
| 113 |
+
mxid = None
|
| 114 |
+
for attr in ['mxid', 'getMxId']:
|
| 115 |
+
if hasattr(d, attr):
|
| 116 |
+
val = getattr(d, attr)
|
| 117 |
+
mxid = val() if callable(val) else val
|
| 118 |
+
if mxid:
|
| 119 |
+
break
|
| 120 |
+
state = d.state.name if hasattr(d, 'state') else 'N/A'
|
| 121 |
+
name = getattr(d, 'name', '')
|
| 122 |
+
if mxid and mxid != name:
|
| 123 |
+
print(f' [{i}] MxId: {mxid} port: {name} state: {state}')
|
| 124 |
+
else:
|
| 125 |
+
# MxID not available; show all useful attributes
|
| 126 |
+
print(f' [{i}] device: {d} state: {state}')
|
| 127 |
+
print(f' attributes: {[a for a in dir(d) if not a.startswith(\"_\")]}')
|
| 128 |
+
" 2>&1
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
while true; do
|
| 132 |
+
echo " Detecting connected OAK cameras …"
|
| 133 |
+
OAK_DEVICES="$(detect_oak_cameras)" && OAK_FOUND=true || OAK_FOUND=false
|
| 134 |
+
|
| 135 |
+
if $OAK_FOUND && [ -n "$OAK_DEVICES" ]; then
|
| 136 |
+
echo "$OAK_DEVICES"
|
| 137 |
+
break
|
| 138 |
+
else
|
| 139 |
+
echo " (no OAK devices detected)"
|
| 140 |
+
if [ -n "$OAK_DEVICES" ]; then
|
| 141 |
+
echo " depthai output: $OAK_DEVICES"
|
| 142 |
+
fi
|
| 143 |
+
echo ""
|
| 144 |
+
read -rp " Retry detection? [Y/n] (or 'n' to enter device IDs manually): " RETRY
|
| 145 |
+
if [[ "$RETRY" =~ ^[Nn]$ ]]; then
|
| 146 |
+
break
|
| 147 |
+
fi
|
| 148 |
+
echo ""
|
| 149 |
+
fi
|
| 150 |
+
done
|
| 151 |
+
echo ""
|
| 152 |
+
|
| 153 |
+
# Build ExecStart args incrementally
|
| 154 |
+
CAMERA_ARGS=""
|
| 155 |
+
|
| 156 |
+
# --- Ego-view camera (required) ---
|
| 157 |
+
read -rp " Ego-view camera type (oak, oak_mono, realsense, usb) [oak]: " EGO_TYPE
|
| 158 |
+
EGO_TYPE="${EGO_TYPE:-oak}"
|
| 159 |
+
read -rp " Ego-view device ID (MxID or /dev/video index): " EGO_DEVICE_ID
|
| 160 |
+
CAMERA_ARGS="--ego-view-camera ${EGO_TYPE}"
|
| 161 |
+
if [ -n "$EGO_DEVICE_ID" ]; then
|
| 162 |
+
CAMERA_ARGS="${CAMERA_ARGS} --ego-view-device-id ${EGO_DEVICE_ID}"
|
| 163 |
+
fi
|
| 164 |
+
|
| 165 |
+
# --- Left wrist camera (optional) ---
|
| 166 |
+
echo ""
|
| 167 |
+
read -rp " Add a left-wrist camera? [y/N]: " ADD_LEFT
|
| 168 |
+
if [[ "$ADD_LEFT" =~ ^[Yy]$ ]]; then
|
| 169 |
+
read -rp " Left-wrist camera type [oak]: " LEFT_TYPE
|
| 170 |
+
LEFT_TYPE="${LEFT_TYPE:-oak}"
|
| 171 |
+
read -rp " Left-wrist device ID (MxID): " LEFT_DEVICE_ID
|
| 172 |
+
CAMERA_ARGS="${CAMERA_ARGS} --left-wrist-camera ${LEFT_TYPE}"
|
| 173 |
+
if [ -n "$LEFT_DEVICE_ID" ]; then
|
| 174 |
+
CAMERA_ARGS="${CAMERA_ARGS} --left-wrist-device-id ${LEFT_DEVICE_ID}"
|
| 175 |
+
fi
|
| 176 |
+
fi
|
| 177 |
+
|
| 178 |
+
# --- Right wrist camera (optional) ---
|
| 179 |
+
echo ""
|
| 180 |
+
read -rp " Add a right-wrist camera? [y/N]: " ADD_RIGHT
|
| 181 |
+
if [[ "$ADD_RIGHT" =~ ^[Yy]$ ]]; then
|
| 182 |
+
read -rp " Right-wrist camera type [oak]: " RIGHT_TYPE
|
| 183 |
+
RIGHT_TYPE="${RIGHT_TYPE:-oak}"
|
| 184 |
+
read -rp " Right-wrist device ID (MxID): " RIGHT_DEVICE_ID
|
| 185 |
+
CAMERA_ARGS="${CAMERA_ARGS} --right-wrist-camera ${RIGHT_TYPE}"
|
| 186 |
+
if [ -n "$RIGHT_DEVICE_ID" ]; then
|
| 187 |
+
CAMERA_ARGS="${CAMERA_ARGS} --right-wrist-device-id ${RIGHT_DEVICE_ID}"
|
| 188 |
+
fi
|
| 189 |
+
fi
|
| 190 |
+
|
| 191 |
+
echo ""
|
| 192 |
+
read -rp " ZMQ port [5555]: " CFG_PORT
|
| 193 |
+
CFG_PORT="${CFG_PORT:-5555}"
|
| 194 |
+
CAMERA_ARGS="${CAMERA_ARGS} --port ${CFG_PORT}"
|
| 195 |
+
|
| 196 |
+
EXEC_START="${REPO_ROOT}/.venv_camera/bin/python -m gear_sonic.camera.composed_camera ${CAMERA_ARGS}"
|
| 197 |
+
echo ""
|
| 198 |
+
echo " ExecStart command:"
|
| 199 |
+
echo " $EXEC_START"
|
| 200 |
+
echo ""
|
| 201 |
+
read -rp " Look correct? [Y/n]: " CONFIRM
|
| 202 |
+
if [[ "$CONFIRM" =~ ^[Nn]$ ]]; then
|
| 203 |
+
echo " Aborted. Edit systemd/composed_camera_server.service manually."
|
| 204 |
+
exit 0
|
| 205 |
+
fi
|
| 206 |
+
|
| 207 |
+
# Generate unit file directly (avoids fragile sed on multi-line ExecStart)
|
| 208 |
+
TMPUNIT="$(mktemp)"
|
| 209 |
+
cat > "$TMPUNIT" <<UNIT
|
| 210 |
+
[Unit]
|
| 211 |
+
Description=SONIC Composed Camera Server (ZMQ)
|
| 212 |
+
After=network.target
|
| 213 |
+
|
| 214 |
+
[Service]
|
| 215 |
+
Type=simple
|
| 216 |
+
User=$USER
|
| 217 |
+
Environment="HOME=$HOME"
|
| 218 |
+
Environment="REPO_DIR=$REPO_ROOT"
|
| 219 |
+
WorkingDirectory=$REPO_ROOT
|
| 220 |
+
ExecStart=$EXEC_START
|
| 221 |
+
Restart=on-failure
|
| 222 |
+
RestartSec=5
|
| 223 |
+
StandardOutput=journal
|
| 224 |
+
StandardError=journal
|
| 225 |
+
|
| 226 |
+
[Install]
|
| 227 |
+
WantedBy=multi-user.target
|
| 228 |
+
UNIT
|
| 229 |
+
|
| 230 |
+
echo ""
|
| 231 |
+
echo "[INFO] Installing systemd service …"
|
| 232 |
+
sudo cp "$TMPUNIT" "/etc/systemd/system/$SERVICE_NAME"
|
| 233 |
+
rm -f "$TMPUNIT"
|
| 234 |
+
|
| 235 |
+
sudo systemctl daemon-reload
|
| 236 |
+
sudo systemctl enable "$SERVICE_NAME"
|
| 237 |
+
sudo systemctl start "$SERVICE_NAME"
|
| 238 |
+
|
| 239 |
+
echo ""
|
| 240 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 241 |
+
echo " systemd service installed and started!"
|
| 242 |
+
echo ""
|
| 243 |
+
echo " Check status:"
|
| 244 |
+
echo " sudo systemctl status $SERVICE_NAME"
|
| 245 |
+
echo ""
|
| 246 |
+
echo " View logs:"
|
| 247 |
+
echo " journalctl -u $SERVICE_NAME -f"
|
| 248 |
+
echo ""
|
| 249 |
+
echo " To reconfigure, edit and re-run this script, or:"
|
| 250 |
+
echo " sudo systemctl edit $SERVICE_NAME"
|
| 251 |
+
echo " sudo systemctl restart $SERVICE_NAME"
|
| 252 |
+
echo "══════════════════════════════════════════════════════════════"
|
GR00T-WholeBodyControl/install_scripts/install_data_collection.sh
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# install_data_collection.sh
|
| 3 |
+
# Sets up the .venv_data_collection venv for recording teleop demonstrations
|
| 4 |
+
# in LeRobot dataset format (for post-training with Isaac-GR00T).
|
| 5 |
+
#
|
| 6 |
+
# Installs gear_sonic[data_collection] which pulls in LeRobot, PyAV, OpenCV,
|
| 7 |
+
# and the other dependencies needed by run_data_exporter.py.
|
| 8 |
+
#
|
| 9 |
+
# Usage: bash install_scripts/install_data_collection.sh (run from repo root)
|
| 10 |
+
|
| 11 |
+
set -euo pipefail
|
| 12 |
+
|
| 13 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 14 |
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
| 15 |
+
|
| 16 |
+
# ── 0. System dependencies ────────────────────────────────────────────────────
|
| 17 |
+
ARCH="$(uname -m)"
|
| 18 |
+
echo "[OK] Architecture: $ARCH"
|
| 19 |
+
|
| 20 |
+
echo "[INFO] Installing system dependencies (espeak for voice feedback) …"
|
| 21 |
+
if command -v apt-get &>/dev/null; then
|
| 22 |
+
sudo apt-get install -y espeak >/dev/null 2>&1 || echo "[WARN] Could not install espeak — voice feedback will be disabled"
|
| 23 |
+
fi
|
| 24 |
+
|
| 25 |
+
# ── 1. Ensure uv is installed and available ──────────────────────────────────
|
| 26 |
+
if ! command -v uv &>/dev/null; then
|
| 27 |
+
echo "[INFO] uv not found – installing via official installer …"
|
| 28 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 29 |
+
|
| 30 |
+
# Source the uv env so it's available in this session
|
| 31 |
+
if [ -f "$HOME/.local/bin/env" ]; then
|
| 32 |
+
# shellcheck disable=SC1091
|
| 33 |
+
source "$HOME/.local/bin/env"
|
| 34 |
+
elif [ -f "$HOME/.cargo/env" ]; then
|
| 35 |
+
# shellcheck disable=SC1091
|
| 36 |
+
source "$HOME/.cargo/env"
|
| 37 |
+
else
|
| 38 |
+
export PATH="$HOME/.local/bin:$PATH"
|
| 39 |
+
fi
|
| 40 |
+
|
| 41 |
+
if ! command -v uv &>/dev/null; then
|
| 42 |
+
echo "[ERROR] uv installation succeeded but binary not found on PATH."
|
| 43 |
+
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
|
| 44 |
+
exit 1
|
| 45 |
+
fi
|
| 46 |
+
fi
|
| 47 |
+
echo "[OK] uv $(uv --version)"
|
| 48 |
+
|
| 49 |
+
# ── 2. Install a uv-managed Python 3.10 (includes dev headers / Python.h) ────
|
| 50 |
+
echo "[INFO] Installing uv-managed Python 3.10 (includes development headers) …"
|
| 51 |
+
uv python install 3.10
|
| 52 |
+
MANAGED_PY="$(uv python find --no-project 3.10)"
|
| 53 |
+
echo "[OK] Using Python: $MANAGED_PY"
|
| 54 |
+
|
| 55 |
+
# ── 3. Clean previous venv (if any) ──────────────────────────────────────────
|
| 56 |
+
cd "$REPO_ROOT"
|
| 57 |
+
echo "[INFO] Removing old .venv_data_collection (if present) …"
|
| 58 |
+
rm -rf .venv_data_collection
|
| 59 |
+
|
| 60 |
+
# ── 4. Create venv & install data_collection extra ───────────────────────────
|
| 61 |
+
echo "[INFO] Creating .venv_data_collection with uv-managed Python 3.10 …"
|
| 62 |
+
uv venv .venv_data_collection --python "$MANAGED_PY" --prompt gear_sonic_data_collection
|
| 63 |
+
# shellcheck disable=SC1091
|
| 64 |
+
source .venv_data_collection/bin/activate
|
| 65 |
+
echo "[INFO] Installing gear_sonic[data_collection] (this may take a few minutes) …"
|
| 66 |
+
# LeRobot's git repo contains LFS test artifacts that aren't needed at runtime.
|
| 67 |
+
# Skip them to avoid download failures and save bandwidth.
|
| 68 |
+
GIT_LFS_SKIP_SMUDGE=1 uv pip install -e "gear_sonic[data_collection]"
|
| 69 |
+
|
| 70 |
+
echo ""
|
| 71 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 72 |
+
echo " Setup complete! Activate the venv with:"
|
| 73 |
+
echo ""
|
| 74 |
+
echo " source .venv_data_collection/bin/activate"
|
| 75 |
+
echo ""
|
| 76 |
+
echo " You should see (gear_sonic_data_collection) in your prompt."
|
| 77 |
+
echo ""
|
| 78 |
+
echo " Then run the data exporter with:"
|
| 79 |
+
echo " python gear_sonic/scripts/run_data_exporter.py"
|
| 80 |
+
echo "══════════════════════════════════════════════════════════════"
|
GR00T-WholeBodyControl/install_scripts/install_inference.sh
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# install_inference.sh
|
| 3 |
+
# Sets up the .venv_inference venv for running VLA inference with
|
| 4 |
+
# Isaac-GR00T PolicyClient against a remote or local policy server.
|
| 5 |
+
#
|
| 6 |
+
# Installs gear_sonic[inference] which pulls in the Isaac-GR00T library,
|
| 7 |
+
# PyZMQ, msgpack, Pinocchio, and other inference dependencies.
|
| 8 |
+
#
|
| 9 |
+
# Usage: bash install_scripts/install_inference.sh (run from repo root)
|
| 10 |
+
|
| 11 |
+
set -euo pipefail
|
| 12 |
+
|
| 13 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 14 |
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
| 15 |
+
|
| 16 |
+
# ── 0. System dependencies ────────────────────────────────────────────────────
|
| 17 |
+
ARCH="$(uname -m)"
|
| 18 |
+
echo "[OK] Architecture: $ARCH"
|
| 19 |
+
|
| 20 |
+
# ── 1. Ensure uv is installed and available ──────────────────────────────────
|
| 21 |
+
if ! command -v uv &>/dev/null; then
|
| 22 |
+
echo "[INFO] uv not found – installing via official installer …"
|
| 23 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 24 |
+
|
| 25 |
+
if [ -f "$HOME/.local/bin/env" ]; then
|
| 26 |
+
# shellcheck disable=SC1091
|
| 27 |
+
source "$HOME/.local/bin/env"
|
| 28 |
+
elif [ -f "$HOME/.cargo/env" ]; then
|
| 29 |
+
# shellcheck disable=SC1091
|
| 30 |
+
source "$HOME/.cargo/env"
|
| 31 |
+
else
|
| 32 |
+
export PATH="$HOME/.local/bin:$PATH"
|
| 33 |
+
fi
|
| 34 |
+
|
| 35 |
+
if ! command -v uv &>/dev/null; then
|
| 36 |
+
echo "[ERROR] uv installation succeeded but binary not found on PATH."
|
| 37 |
+
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
|
| 38 |
+
exit 1
|
| 39 |
+
fi
|
| 40 |
+
fi
|
| 41 |
+
echo "[OK] uv $(uv --version)"
|
| 42 |
+
|
| 43 |
+
# ── 2. Install a uv-managed Python 3.10 (includes dev headers / Python.h) ────
|
| 44 |
+
echo "[INFO] Installing uv-managed Python 3.10 (includes development headers) …"
|
| 45 |
+
uv python install 3.10
|
| 46 |
+
MANAGED_PY="$(uv python find --no-project 3.10)"
|
| 47 |
+
echo "[OK] Using Python: $MANAGED_PY"
|
| 48 |
+
|
| 49 |
+
# ── 3. Clean previous venv (if any) ──────────────────────────────────────────
|
| 50 |
+
cd "$REPO_ROOT"
|
| 51 |
+
echo "[INFO] Removing old .venv_inference (if present) …"
|
| 52 |
+
rm -rf .venv_inference
|
| 53 |
+
|
| 54 |
+
# ── 4. Create venv & install inference extra ─────────────────────────────────
|
| 55 |
+
echo "[INFO] Creating .venv_inference with uv-managed Python 3.10 …"
|
| 56 |
+
uv venv .venv_inference --python "$MANAGED_PY" --prompt gear_sonic_inference
|
| 57 |
+
# shellcheck disable=SC1091
|
| 58 |
+
source .venv_inference/bin/activate
|
| 59 |
+
echo "[INFO] Installing gear_sonic[inference] (this may take a few minutes) …"
|
| 60 |
+
uv pip install -e "gear_sonic[inference]"
|
| 61 |
+
|
| 62 |
+
echo ""
|
| 63 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 64 |
+
echo " Setup complete! Activate the venv with:"
|
| 65 |
+
echo ""
|
| 66 |
+
echo " source .venv_inference/bin/activate"
|
| 67 |
+
echo ""
|
| 68 |
+
echo " You should see (gear_sonic_inference) in your prompt."
|
| 69 |
+
echo ""
|
| 70 |
+
echo " Then run VLA inference with:"
|
| 71 |
+
echo " python gear_sonic/scripts/run_vla_inference.py --help"
|
| 72 |
+
echo "══════════════════════════════════════════════════════════════"
|
GR00T-WholeBodyControl/install_scripts/install_leap_sdk.sh
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
set -e
|
| 3 |
+
|
| 4 |
+
# Install UltraLeap repository and key
|
| 5 |
+
wget -qO - https://repo.ultraleap.com/keys/apt/gpg | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/ultraleap.gpg
|
| 6 |
+
|
| 7 |
+
echo 'deb [arch=amd64] https://repo.ultraleap.com/apt stable main' | sudo tee /etc/apt/sources.list.d/ultraleap.list
|
| 8 |
+
sudo apt update
|
| 9 |
+
|
| 10 |
+
# Install UltraLeap hand tracking (auto-accept license)
|
| 11 |
+
sudo apt install -y ultraleap-hand-tracking
|
| 12 |
+
|
| 13 |
+
# Clone and install leapc-python-bindings
|
| 14 |
+
git clone https://github.com/ultraleap/leapc-python-bindings /tmp/leapc-python-bindings
|
| 15 |
+
cd /tmp/leapc-python-bindings
|
| 16 |
+
pip install -r requirements.txt
|
| 17 |
+
python -m build leapc-cffi
|
| 18 |
+
pip install leapc-cffi/dist/leapc_cffi-0.0.1.tar.gz
|
| 19 |
+
pip install -e leapc-python-api
|
GR00T-WholeBodyControl/install_scripts/install_mujoco_sim.sh
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# install_mujoco_sim.sh
|
| 3 |
+
# Minimal venv setup for running the MuJoCo simulator (run_sim_loop.py).
|
| 4 |
+
# Skips XRoboToolkit SDK and teleop dependencies that are NOT needed for sim.
|
| 5 |
+
# Based on install_pico.sh — see that script for the full teleop setup.
|
| 6 |
+
#
|
| 7 |
+
# Usage: bash install_scripts/install_mujoco_sim.sh (run from repo root)
|
| 8 |
+
|
| 9 |
+
set -euo pipefail
|
| 10 |
+
|
| 11 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 12 |
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
| 13 |
+
|
| 14 |
+
# ── 0. Print detected architecture ───────────────────────────────────────────
|
| 15 |
+
ARCH="$(uname -m)"
|
| 16 |
+
echo "[OK] Architecture: $ARCH"
|
| 17 |
+
|
| 18 |
+
# ── 1. Ensure uv is installed and available ──────────────────────────────────
|
| 19 |
+
if ! command -v uv &>/dev/null; then
|
| 20 |
+
echo "[INFO] uv not found – installing via official installer …"
|
| 21 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 22 |
+
|
| 23 |
+
# Source the uv env so it's available in this session
|
| 24 |
+
if [ -f "$HOME/.local/bin/env" ]; then
|
| 25 |
+
# shellcheck disable=SC1091
|
| 26 |
+
source "$HOME/.local/bin/env"
|
| 27 |
+
elif [ -f "$HOME/.cargo/env" ]; then
|
| 28 |
+
# shellcheck disable=SC1091
|
| 29 |
+
source "$HOME/.cargo/env"
|
| 30 |
+
else
|
| 31 |
+
export PATH="$HOME/.local/bin:$PATH"
|
| 32 |
+
fi
|
| 33 |
+
|
| 34 |
+
# Verify uv is now reachable
|
| 35 |
+
if ! command -v uv &>/dev/null; then
|
| 36 |
+
echo "[ERROR] uv installation succeeded but binary not found on PATH."
|
| 37 |
+
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
|
| 38 |
+
exit 1
|
| 39 |
+
fi
|
| 40 |
+
fi
|
| 41 |
+
echo "[OK] uv $(uv --version)"
|
| 42 |
+
|
| 43 |
+
# ── 2. Install a uv-managed Python 3.10 (includes dev headers / Python.h) ────
|
| 44 |
+
echo "[INFO] Installing uv-managed Python 3.10 (includes development headers) …"
|
| 45 |
+
uv python install 3.10
|
| 46 |
+
MANAGED_PY="$(uv python find --no-project 3.10)"
|
| 47 |
+
echo "[OK] Using Python: $MANAGED_PY"
|
| 48 |
+
|
| 49 |
+
# ── 3. Clean previous venv (if any) ──────────────────────────────────────────
|
| 50 |
+
cd "$REPO_ROOT"
|
| 51 |
+
echo "[INFO] Removing old .venv_sim (if present) …"
|
| 52 |
+
rm -rf .venv_sim
|
| 53 |
+
|
| 54 |
+
# ── 4. Create venv & install sim extra ────────────────────────────────────────
|
| 55 |
+
echo "[INFO] Creating .venv_sim with uv-managed Python 3.10 …"
|
| 56 |
+
uv venv .venv_sim --python "$MANAGED_PY" --prompt gear_sonic_sim
|
| 57 |
+
# shellcheck disable=SC1091
|
| 58 |
+
source .venv_sim/bin/activate
|
| 59 |
+
echo "[INFO] Installing gear_sonic[sim] …"
|
| 60 |
+
uv pip install -e "gear_sonic[sim]"
|
| 61 |
+
|
| 62 |
+
# ── 5. Install unitree_sdk2_python (needed by the sim ↔ WBC bridge) ──────────
|
| 63 |
+
echo "[INFO] Installing unitree_sdk2_python …"
|
| 64 |
+
uv pip install -e external_dependencies/unitree_sdk2_python
|
| 65 |
+
|
| 66 |
+
echo ""
|
| 67 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 68 |
+
echo " Setup complete! Activate the venv with:"
|
| 69 |
+
echo ""
|
| 70 |
+
echo " source .venv_sim/bin/activate"
|
| 71 |
+
echo ""
|
| 72 |
+
echo " You should see (gear_sonic_sim) in your prompt."
|
| 73 |
+
echo ""
|
| 74 |
+
echo " Then run the MuJoCo simulator with:"
|
| 75 |
+
echo " python gear_sonic/scripts/run_sim_loop.py"
|
| 76 |
+
echo "══════════════════════════════════════════════════════════════"
|
GR00T-WholeBodyControl/install_scripts/install_pico.sh
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# install_pico.sh
|
| 3 |
+
# Sets up the gear_sonic_teleop venv for PICO VR teleop on any x86_64 or arm64
|
| 4 |
+
# machine (desktop, laptop, or G1 onboard).
|
| 5 |
+
#
|
| 6 |
+
# Usage:
|
| 7 |
+
# bash install_scripts/install_pico.sh # full install
|
| 8 |
+
# SKIP_SIM_AND_UNITREE=1 bash install_scripts/install_pico.sh
|
| 9 |
+
# # publisher-only profile
|
| 10 |
+
# # (Thor/Orin used as a
|
| 11 |
+
# # headless Isaac Teleop /
|
| 12 |
+
# # CloudXR ROS publisher
|
| 13 |
+
# # — neither sim nor the
|
| 14 |
+
# # unitree DDS bindings
|
| 15 |
+
# # are on that path)
|
| 16 |
+
#
|
| 17 |
+
# Optional env vars:
|
| 18 |
+
# SKIP_SIM_AND_UNITREE=1 Skip the mujoco sim extra and unitree_sdk2_python.
|
| 19 |
+
# On aarch64 also skips the CycloneDDS C-lib build.
|
| 20 |
+
# CYCLONEDDS_HOME=<path> Override the CycloneDDS install prefix on aarch64
|
| 21 |
+
# (default: ~/cyclonedds/install). Not used on
|
| 22 |
+
# x86_64 because prebuilt cyclonedds wheels exist.
|
| 23 |
+
#
|
| 24 |
+
# Run from the repo root.
|
| 25 |
+
|
| 26 |
+
set -euo pipefail
|
| 27 |
+
|
| 28 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| 29 |
+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
| 30 |
+
|
| 31 |
+
# ── 0. Print detected architecture ───────────────────────────────────────────
|
| 32 |
+
ARCH="$(uname -m)"
|
| 33 |
+
echo "[OK] Architecture: $ARCH"
|
| 34 |
+
|
| 35 |
+
# ── 1. Ensure uv is installed and available ──────────────────────────────────
|
| 36 |
+
if ! command -v uv &>/dev/null; then
|
| 37 |
+
echo "[INFO] uv not found – installing via official installer …"
|
| 38 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 39 |
+
|
| 40 |
+
# Source the uv env so it's available in this session
|
| 41 |
+
if [ -f "$HOME/.local/bin/env" ]; then
|
| 42 |
+
# shellcheck disable=SC1091
|
| 43 |
+
source "$HOME/.local/bin/env"
|
| 44 |
+
elif [ -f "$HOME/.cargo/env" ]; then
|
| 45 |
+
# shellcheck disable=SC1091
|
| 46 |
+
source "$HOME/.cargo/env"
|
| 47 |
+
else
|
| 48 |
+
export PATH="$HOME/.local/bin:$PATH"
|
| 49 |
+
fi
|
| 50 |
+
|
| 51 |
+
# Verify uv is now reachable
|
| 52 |
+
if ! command -v uv &>/dev/null; then
|
| 53 |
+
echo "[ERROR] uv installation succeeded but binary not found on PATH."
|
| 54 |
+
echo " Please add ~/.local/bin (or ~/.cargo/bin) to your PATH and re-run."
|
| 55 |
+
exit 1
|
| 56 |
+
fi
|
| 57 |
+
fi
|
| 58 |
+
echo "[OK] uv $(uv --version)"
|
| 59 |
+
|
| 60 |
+
# ── 2. Install a uv-managed Python 3.10 (includes dev headers / Python.h) ────
|
| 61 |
+
echo "[INFO] Installing uv-managed Python 3.10 (includes development headers) …"
|
| 62 |
+
uv python install 3.10
|
| 63 |
+
MANAGED_PY="$(uv python find --no-project 3.10)"
|
| 64 |
+
echo "[OK] Using Python: $MANAGED_PY"
|
| 65 |
+
|
| 66 |
+
# ── 3. Clean previous venv (if any) ──────────────────────────────────────────
|
| 67 |
+
cd "$REPO_ROOT"
|
| 68 |
+
echo "[INFO] Removing old .venv_teleop (if present) …"
|
| 69 |
+
rm -rf .venv_teleop
|
| 70 |
+
|
| 71 |
+
# ── 4. Create venv & install teleop extra ─────────────────────────────────────
|
| 72 |
+
echo "[INFO] Creating .venv_teleop with uv-managed Python 3.10 …"
|
| 73 |
+
uv venv .venv_teleop --python "$MANAGED_PY" --prompt gear_sonic_teleop
|
| 74 |
+
# shellcheck disable=SC1091
|
| 75 |
+
source .venv_teleop/bin/activate
|
| 76 |
+
echo "[INFO] Installing gear_sonic[teleop] …"
|
| 77 |
+
uv pip install -e "gear_sonic[teleop]"
|
| 78 |
+
|
| 79 |
+
# ── 5. Install xrobotoolkit_sdk (CMake-based, not a pip package) ──────────────
|
| 80 |
+
echo "[INFO] Installing XRoboToolkit SDK …"
|
| 81 |
+
# Install cmake + pybind11 into the venv so the CMake-based build can find them.
|
| 82 |
+
# Build with --no-build-isolation so CMake inherits the venv's pybind11.
|
| 83 |
+
uv pip install cmake pybind11 setuptools
|
| 84 |
+
echo "[OK] cmake $(cmake --version | head -1)"
|
| 85 |
+
# Point CMake at pybind11's cmake config so find_package(pybind11) succeeds
|
| 86 |
+
export CMAKE_PREFIX_PATH="$(python -m pybind11 --cmakedir)"
|
| 87 |
+
echo "[OK] pybind11 cmake dir: $CMAKE_PREFIX_PATH"
|
| 88 |
+
|
| 89 |
+
# On aarch64 (Jetson Orin), build the PXREARobotSDK native lib from source
|
| 90 |
+
# because pre-built aarch64 binaries are not shipped in the repo.
|
| 91 |
+
XRT_DIR="$REPO_ROOT/external_dependencies/XRoboToolkit-PC-Service-Pybind_X86_and_ARM64"
|
| 92 |
+
if [ "$ARCH" = "aarch64" ] && [ ! -f "$XRT_DIR/lib/aarch64/libPXREARobotSDK.so" ]; then
|
| 93 |
+
echo "[INFO] Building PXREARobotSDK for aarch64 (Jetson Orin) …"
|
| 94 |
+
XRT_TMP="$XRT_DIR/tmp"
|
| 95 |
+
mkdir -p "$XRT_TMP"
|
| 96 |
+
if [ ! -d "$XRT_TMP/XRoboToolkit-PC-Service" ]; then
|
| 97 |
+
git clone -b orin https://github.com/XR-Robotics/XRoboToolkit-PC-Service.git "$XRT_TMP/XRoboToolkit-PC-Service"
|
| 98 |
+
fi
|
| 99 |
+
pushd "$XRT_TMP/XRoboToolkit-PC-Service/RoboticsService/PXREARobotSDK" > /dev/null
|
| 100 |
+
bash build.sh
|
| 101 |
+
popd > /dev/null
|
| 102 |
+
mkdir -p "$XRT_DIR/lib/aarch64" "$XRT_DIR/include/aarch64"
|
| 103 |
+
cp "$XRT_TMP/XRoboToolkit-PC-Service/RoboticsService/PXREARobotSDK/PXREARobotSDK.h" \
|
| 104 |
+
"$XRT_DIR/include/aarch64/"
|
| 105 |
+
cp -r "$XRT_TMP/XRoboToolkit-PC-Service/RoboticsService/PXREARobotSDK/nlohmann" \
|
| 106 |
+
"$XRT_DIR/include/aarch64/nlohmann/"
|
| 107 |
+
cp "$XRT_TMP/XRoboToolkit-PC-Service/RoboticsService/PXREARobotSDK/build/libPXREARobotSDK.so" \
|
| 108 |
+
"$XRT_DIR/lib/aarch64/"
|
| 109 |
+
rm -rf "$XRT_TMP"
|
| 110 |
+
echo "[OK] PXREARobotSDK aarch64 native library built and installed"
|
| 111 |
+
fi
|
| 112 |
+
|
| 113 |
+
uv pip install --no-build-isolation -e external_dependencies/XRoboToolkit-PC-Service-Pybind_X86_and_ARM64/
|
| 114 |
+
|
| 115 |
+
# ── 5c. Install isaacteleop[cloudxr] for the in-process CloudXR / DeviceIO path
|
| 116 |
+
# (--input-source isaac-teleop in pico_manager_thread_server.py).
|
| 117 |
+
# Hosted on pypi.nvidia.com (public index, no auth). Replaces the legacy
|
| 118 |
+
# multi-container path (./scripts/run_cloudxr_via_docker.sh + teleop_ros2_ref).
|
| 119 |
+
echo "[INFO] Installing isaacteleop[cloudxr]~=1.3.0 from pypi.nvidia.com …"
|
| 120 |
+
uv pip install 'isaacteleop[cloudxr]~=1.3.0' --prerelease=allow \
|
| 121 |
+
--extra-index-url https://pypi.nvidia.com
|
| 122 |
+
|
| 123 |
+
# Seed ~/cloudxr.env with the device profile CloudXRLauncher negotiates against.
|
| 124 |
+
# Skip if the file already exists.
|
| 125 |
+
if [ ! -f "$HOME/cloudxr.env" ]; then
|
| 126 |
+
echo "NV_DEVICE_PROFILE=Quest3" > "$HOME/cloudxr.env"
|
| 127 |
+
echo "[OK] Seeded $HOME/cloudxr.env with NV_DEVICE_PROFILE=Quest3"
|
| 128 |
+
else
|
| 129 |
+
echo "[OK] $HOME/cloudxr.env already exists (leaving as-is)"
|
| 130 |
+
fi
|
| 131 |
+
|
| 132 |
+
# ── 5b, 6, 7: CycloneDDS C lib (aarch64) + sim extra + unitree_sdk2_python ────
|
| 133 |
+
# Skip when:
|
| 134 |
+
# • onboard unitree-provisioned image (aarch64 + user==unitree): the image
|
| 135 |
+
# already ships CycloneDDS, sim has no display, and the on-robot deploy
|
| 136 |
+
# uses the C++ stack directly. Applies to both Orin and Thor onboards.
|
| 137 |
+
# • SKIP_SIM_AND_UNITREE=1 is set explicitly: e.g. a Thor or Orin used as a
|
| 138 |
+
# headless Isaac Teleop / CloudXR streamer — neither mujoco nor the
|
| 139 |
+
# unitree DDS bindings are on that path.
|
| 140 |
+
if { [ "$ARCH" = "aarch64" ] && [ "$(whoami)" = "unitree" ]; } \
|
| 141 |
+
|| [ "${SKIP_SIM_AND_UNITREE:-0}" = "1" ]; then
|
| 142 |
+
echo "[SKIP] Skipping CycloneDDS build, sim extra & unitree_sdk2_python"
|
| 143 |
+
else
|
| 144 |
+
# ── 5b. Build CycloneDDS C library on aarch64 (needed by the cyclonedds
|
| 145 |
+
# Python binding which unitree_sdk2_python depends on).
|
| 146 |
+
# x86_64 hosts get prebuilt cyclonedds wheels and skip this entirely.
|
| 147 |
+
# Pattern follows Unitree's own README for this exact error
|
| 148 |
+
# (https://github.com/unitreerobotics/unitree_sdk2_python#faq):
|
| 149 |
+
# per-user source checkout in $HOME, sibling install/ dir, no sudo.
|
| 150 |
+
if [ "$ARCH" = "aarch64" ]; then
|
| 151 |
+
CDDS_DIR="$HOME/cyclonedds"
|
| 152 |
+
CDDS_PREFIX="${CYCLONEDDS_HOME:-$CDDS_DIR/install}"
|
| 153 |
+
if [ ! -f "$CDDS_PREFIX/lib/libddsc.so" ]; then
|
| 154 |
+
echo "[INFO] Building CycloneDDS releases/0.10.x → $CDDS_PREFIX …"
|
| 155 |
+
# Track the releases/0.10.x maintenance branch (per Unitree's FAQ).
|
| 156 |
+
# The 0.10.2 tag is unpatched 2022 code and trips glibc FORTIFY_SOURCE
|
| 157 |
+
# in dds_create_domain on modern Ubuntu / glibc; the branch has fixes.
|
| 158 |
+
if [ ! -d "$CDDS_DIR/.git" ]; then
|
| 159 |
+
git clone -b releases/0.10.x --depth 1 \
|
| 160 |
+
https://github.com/eclipse-cyclonedds/cyclonedds.git "$CDDS_DIR"
|
| 161 |
+
fi
|
| 162 |
+
cmake -S "$CDDS_DIR" -B "$CDDS_DIR/build" \
|
| 163 |
+
-DCMAKE_INSTALL_PREFIX="$CDDS_PREFIX" \
|
| 164 |
+
-DBUILD_EXAMPLES=OFF \
|
| 165 |
+
-DBUILD_TESTING=OFF
|
| 166 |
+
cmake --build "$CDDS_DIR/build" -j"$(nproc)"
|
| 167 |
+
cmake --install "$CDDS_DIR/build"
|
| 168 |
+
echo "[OK] CycloneDDS installed at $CDDS_PREFIX"
|
| 169 |
+
else
|
| 170 |
+
echo "[OK] CycloneDDS already present at $CDDS_PREFIX (libddsc.so found)"
|
| 171 |
+
fi
|
| 172 |
+
export CYCLONEDDS_HOME="$CDDS_PREFIX"
|
| 173 |
+
fi
|
| 174 |
+
|
| 175 |
+
# ── 6. Install sim extra (for run_sim_loop.py / sim2sim testing)
|
| 176 |
+
echo "[INFO] Installing sim extra …"
|
| 177 |
+
uv pip install -e "gear_sonic[sim]"
|
| 178 |
+
|
| 179 |
+
# ── 7. Install unitree_sdk2_python (needed by the sim2sim bridge)
|
| 180 |
+
echo "[INFO] Installing unitree_sdk2_python …"
|
| 181 |
+
uv pip install -e external_dependencies/unitree_sdk2_python
|
| 182 |
+
fi
|
| 183 |
+
|
| 184 |
+
echo ""
|
| 185 |
+
echo "══════════════════════════════════════════════════════════════"
|
| 186 |
+
echo " Setup complete! Activate the venv with:"
|
| 187 |
+
echo ""
|
| 188 |
+
echo " source .venv_teleop/bin/activate"
|
| 189 |
+
echo ""
|
| 190 |
+
echo " You should see (gear_sonic_teleop) in your prompt."
|
| 191 |
+
echo "══════════════════════════════════════════════════════════════"
|
GR00T-WholeBodyControl/install_scripts/install_ros.sh
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# install_ros.sh
|
| 3 |
+
# Sets up the `teleop_ros` conda env with RoboStack ROS 2 Humble for the
|
| 4 |
+
# Isaac Teleop / CloudXR ROS bridge. Pinned to Python 3.10 to compose with
|
| 5 |
+
# .venv_teleop (created by install_pico.sh).
|
| 6 |
+
#
|
| 7 |
+
# Usage: bash install_scripts/install_ros.sh (run from repo root)
|
| 8 |
+
|
| 9 |
+
set -e
|
| 10 |
+
|
| 11 |
+
ENV_NAME="${1:-teleop_ros}"
|
| 12 |
+
PY_VERSION="3.10"
|
| 13 |
+
|
| 14 |
+
# Source conda's shell hooks so `conda activate` works in a non-interactive script.
|
| 15 |
+
source "$(conda info --base)/etc/profile.d/conda.sh"
|
| 16 |
+
|
| 17 |
+
if conda env list | awk '{print $1}' | grep -qx "$ENV_NAME"; then
|
| 18 |
+
echo "♻️ Reusing existing conda env: $ENV_NAME"
|
| 19 |
+
else
|
| 20 |
+
echo "🆕 Creating conda env '$ENV_NAME' with Python $PY_VERSION..."
|
| 21 |
+
conda create -n "$ENV_NAME" "python=$PY_VERSION" -y
|
| 22 |
+
fi
|
| 23 |
+
conda activate "$ENV_NAME"
|
| 24 |
+
|
| 25 |
+
echo "🔄 Cleaning up incomplete or cached packages..."
|
| 26 |
+
conda clean --packages --tarballs --yes
|
| 27 |
+
|
| 28 |
+
echo "🔧 Adding RoboStack and conda-forge channels to the current environment..."
|
| 29 |
+
conda config --env --add channels conda-forge
|
| 30 |
+
conda config --env --add channels robostack-staging
|
| 31 |
+
|
| 32 |
+
# Optional: remove defaults to avoid conflicts (ignore error if not present)
|
| 33 |
+
echo "⚙️ Removing 'defaults' channel if present..."
|
| 34 |
+
conda config --env --remove channels defaults || true
|
| 35 |
+
|
| 36 |
+
echo "📦 Installing ROS 2 Humble Desktop from RoboStack..."
|
| 37 |
+
# RoboStack recommends mamba over conda; conda+libmamba hits a post-link
|
| 38 |
+
# ordering bug in ros-humble-ros-workspace, and conda+classic is very slow
|
| 39 |
+
# on aarch64. Install mamba into base if it isn't already there.
|
| 40 |
+
if ! command -v mamba &>/dev/null; then
|
| 41 |
+
echo "🆕 Installing mamba into base env..."
|
| 42 |
+
conda install -n base -c conda-forge -y mamba
|
| 43 |
+
fi
|
| 44 |
+
mamba install -y ros-humble-desktop
|
| 45 |
+
|
| 46 |
+
echo "✅ Sourcing ROS environment from current conda env..."
|
| 47 |
+
source "$CONDA_PREFIX/setup.bash"
|
| 48 |
+
|
| 49 |
+
echo "🧪 Verifying rclpy import..."
|
| 50 |
+
python -c "import rclpy; print('✅ rclpy imported')"
|
| 51 |
+
|
| 52 |
+
cat <<EOF
|
| 53 |
+
|
| 54 |
+
ℹ️ Each new shell that runs gear_sonic with --input-source ros2 must compose
|
| 55 |
+
the env in this order. Add to your workflow (not auto-handled):
|
| 56 |
+
|
| 57 |
+
conda activate $ENV_NAME
|
| 58 |
+
source "\$CONDA_PREFIX/setup.bash" # ROS env (PATH, AMENT_PREFIX_PATH, ...)
|
| 59 |
+
source .venv_teleop/bin/activate # gear_sonic deps on top
|
| 60 |
+
export ROS_LOCALHOST_ONLY=1 # match the publisher container
|
| 61 |
+
|
| 62 |
+
See docs/source/tutorials/vr_wholebody_teleop.md (Isaac Teleop / CloudXR
|
| 63 |
+
alternative section) for the full env-composition rationale.
|
| 64 |
+
EOF
|
GR00T-WholeBodyControl/lint.sh
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Script to run linters the same way as in the GitLab CI pipeline
|
| 3 |
+
|
| 4 |
+
# Default mode is check only
|
| 5 |
+
FIX_MODE=false
|
| 6 |
+
|
| 7 |
+
# Parse command line arguments
|
| 8 |
+
while [[ "$#" -gt 0 ]]; do
|
| 9 |
+
case $1 in
|
| 10 |
+
--fix) FIX_MODE=true ;;
|
| 11 |
+
*) echo "Unknown parameter: $1"; exit 1 ;;
|
| 12 |
+
esac
|
| 13 |
+
shift
|
| 14 |
+
done
|
| 15 |
+
|
| 16 |
+
# Install required packages if not already installed
|
| 17 |
+
echo "Checking for required linting tools..."
|
| 18 |
+
pip install black ruff
|
| 19 |
+
|
| 20 |
+
# Set the mode message
|
| 21 |
+
if [ "$FIX_MODE" = true ]; then
|
| 22 |
+
echo "Running in FIX mode - will automatically correct issues"
|
| 23 |
+
else
|
| 24 |
+
echo "Running in CHECK mode - will only report issues"
|
| 25 |
+
fi
|
| 26 |
+
|
| 27 |
+
# Run Ruff lint checks
|
| 28 |
+
echo "Running Ruff linting checks..."
|
| 29 |
+
if [ "$FIX_MODE" = true ]; then
|
| 30 |
+
python -m ruff check --fix .
|
| 31 |
+
else
|
| 32 |
+
python -m ruff check .
|
| 33 |
+
fi
|
| 34 |
+
|
| 35 |
+
# Run Ruff import sorting and Black
|
| 36 |
+
echo "Running style checks..."
|
| 37 |
+
if [ "$FIX_MODE" = true ]; then
|
| 38 |
+
python -m ruff check --select I --fix .
|
| 39 |
+
python -m black .
|
| 40 |
+
else
|
| 41 |
+
python -m ruff check --select I .
|
| 42 |
+
python -m black --check .
|
| 43 |
+
fi
|
| 44 |
+
|
| 45 |
+
echo "Linting completed!"
|
GR00T-WholeBodyControl/motionbricks/.gitattributes
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.STL filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.stl filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.gif filter=lfs diff=lfs merge=lfs -text
|
GR00T-WholeBodyControl/motionbricks/README.md
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# MotionBricks: Scalable Real-Time Motions with Modular Latent Generative Model and Smart Primitives
|
| 2 |
+
|
| 3 |
+
<p align="center">
|
| 4 |
+
<a href="https://nvlabs.github.io/motionbricks"><img src="https://img.shields.io/badge/Project-Page-blue" alt="Project Page"></a>
|
| 5 |
+
<a href="docs/motion_representation.md"><img src="https://img.shields.io/badge/docs-online-green.svg" alt="Documentation"></a>
|
| 6 |
+
</p>
|
| 7 |
+
|
| 8 |
+
<p align="center">
|
| 9 |
+
<img src="assets/teaser_motion_bricks_three_rows.jpg" alt="MotionBricks teaser" width="100%">
|
| 10 |
+
</p>
|
| 11 |
+
|
| 12 |
+
MotionBricks is a real-time generative framework that transforms interactive motion control for animation and robotics. By combining a large-scale latent backbone with intuitive "smart primitives," it delivers high-quality, zero-shot motion synthesis at 15,000 FPS, allowing users to effortlessly build complex animations and robotic movements like assembling bricks.
|
| 13 |
+
|
| 14 |
+
## Contents
|
| 15 |
+
|
| 16 |
+
- [News & Roadmap](#news--roadmap)
|
| 17 |
+
- [Results](#results)
|
| 18 |
+
- [Setup](#setup)
|
| 19 |
+
- [Interactive Demo: Quick Start](#interactive-demo-quick-start)
|
| 20 |
+
- [Training](#training)
|
| 21 |
+
- [Motion Representation and Custom Datasets](#motion-representation-and-custom-datasets)
|
| 22 |
+
- [Related Work](#related-work)
|
| 23 |
+
- [Project Structure](#project-structure)
|
| 24 |
+
- [Known Issues](#known-issues)
|
| 25 |
+
- [Citation](#citation)
|
| 26 |
+
- [License](#license)
|
| 27 |
+
- [Contact](#contact)
|
| 28 |
+
|
| 29 |
+
## News & Roadmap
|
| 30 |
+
|
| 31 |
+
### News
|
| 32 |
+
|
| 33 |
+
- **2026-04-27** — Initial public release: interactive demo, pretrained checkpoints (VQVAE · pose · root), synthetic training code, motion-representation docs, and GIF gallery.
|
| 34 |
+
|
| 35 |
+
### Roadmap
|
| 36 |
+
|
| 37 |
+
- [ ] Full training pipeline inside [GR00T Whole-Body Control](https://github.com/NVlabs/GR00T-WholeBodyControl)'s GEAR-SONIC pipeline — targeted for approximately one month out; reproducibility experiments are already in flight.
|
| 38 |
+
|
| 39 |
+
## Results
|
| 40 |
+
|
| 41 |
+
See the [project page](https://nvlabs.github.io/motionbricks) for the full uncut demos and comparison videos. Short clips below are GIFs (muted, ~10 s each).
|
| 42 |
+
|
| 43 |
+
### Teasers
|
| 44 |
+
|
| 45 |
+
| Animation | Robotics |
|
| 46 |
+
| :---: | :---: |
|
| 47 |
+
|  |  |
|
| 48 |
+
|
| 49 |
+
### Smart Locomotion — Single Styles
|
| 50 |
+
|
| 51 |
+
| Zombie | Injured leg |
|
| 52 |
+
| :---: | :---: |
|
| 53 |
+
|  |  |
|
| 54 |
+
| **Injured torso** | **Skipping** |
|
| 55 |
+
|  |  |
|
| 56 |
+
| **Strafing** | **Crouch strafing** |
|
| 57 |
+
|  |  |
|
| 58 |
+
|
| 59 |
+
### Smart Locomotion — Mixture of Styles
|
| 60 |
+
|
| 61 |
+
| Freestyle | Idle · Walk · Jog · Run |
|
| 62 |
+
| :---: | :---: |
|
| 63 |
+
|  |  |
|
| 64 |
+
|
| 65 |
+
### Smart Objects
|
| 66 |
+
|
| 67 |
+
| Pick up sword | Falling |
|
| 68 |
+
| :---: | :---: |
|
| 69 |
+
|  |  |
|
| 70 |
+
| **Jump over bench** | **Sitting** |
|
| 71 |
+
|  |  |
|
| 72 |
+
| **Interactive authoring** | |
|
| 73 |
+
|  | |
|
| 74 |
+
|
| 75 |
+
## Setup
|
| 76 |
+
|
| 77 |
+
**Requirements:** Python 3.10+, a CUDA-capable GPU, [Git LFS](https://git-lfs.com/).
|
| 78 |
+
|
| 79 |
+
### Clone the repository
|
| 80 |
+
|
| 81 |
+
MotionBricks ships as a subproject of [GR00T Whole-Body Control](https://github.com/NVlabs/GR00T-WholeBodyControl). Clone the parent repo and `cd` into `motionbricks/`. Pretrained checkpoints, mesh assets, and gallery GIFs are tracked with Git LFS, so install LFS before cloning:
|
| 82 |
+
|
| 83 |
+
```bash
|
| 84 |
+
git lfs install
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
The parent repo skips MotionBricks pretrained checkpoints by default so a normal monorepo clone does not automatically download the extra ~2.2 GB of checkpoint files. MotionBricks GIFs and mesh assets still download normally. If you only need source code (for example, to train on your own data), clone normally:
|
| 88 |
+
|
| 89 |
+
```bash
|
| 90 |
+
git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
|
| 91 |
+
cd GR00T-WholeBodyControl/motionbricks
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
If you want the checkpoints for the interactive demo, fetch them explicitly from the repo root:
|
| 95 |
+
|
| 96 |
+
```bash
|
| 97 |
+
git clone https://github.com/NVlabs/GR00T-WholeBodyControl.git
|
| 98 |
+
cd GR00T-WholeBodyControl
|
| 99 |
+
git lfs pull --include="motionbricks/out/**" --exclude=""
|
| 100 |
+
git lfs pull --include="motionbricks/assets/skeletons/g1/meshes/**" --exclude="" # needed for interactive demo
|
| 101 |
+
cd motionbricks
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
After fetching MotionBricks checkpoints, verify that checkpoint files were downloaded (not tiny Git LFS pointer files):
|
| 105 |
+
|
| 106 |
+
```bash
|
| 107 |
+
ls -lh out/G1-clip.ckpt # ~7.5 MB
|
| 108 |
+
ls -lh out/motionbricks_vqvae/version_1/checkpoints/*.ckpt # ~273 MB
|
| 109 |
+
ls -lh out/motionbricks_pose/version_1/checkpoints/*.ckpt # ~1.6 GB
|
| 110 |
+
ls -lh out/motionbricks_root/version_1/checkpoints/*.ckpt # ~391 MB
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
If these files are unexpectedly small (around 1 KB), they are LFS pointers. From the repo root, run `git lfs pull --include="motionbricks/out/**" --exclude=""` to fetch the actual checkpoints.
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
### Install dependencies
|
| 117 |
+
|
| 118 |
+
```bash
|
| 119 |
+
# Create environment
|
| 120 |
+
conda create -n motionbricks python=3.10 -y
|
| 121 |
+
conda activate motionbricks
|
| 122 |
+
|
| 123 |
+
# Install dependencies
|
| 124 |
+
pip install -e .
|
| 125 |
+
|
| 126 |
+
# Linux only: needed for keyboard input and MuJoCo key-grab workaround
|
| 127 |
+
pip install pynput python-xlib
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
## Interactive Demo: Quick Start
|
| 131 |
+
|
| 132 |
+
```bash
|
| 133 |
+
DISPLAY=:1 python scripts/interactive_demo_g1.py
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
This launches the MuJoCo viewer with the G1 robot. Use your keyboard to control it in real time. Hold the left mouse button and drag to change the camera look-at direction.
|
| 137 |
+
|
| 138 |
+
<p align="center">
|
| 139 |
+
<img src="assets/gifs/interactive_demo.gif" alt="Interactive demo screencast" width="480">
|
| 140 |
+
</p>
|
| 141 |
+
|
| 142 |
+
### Movement Controls
|
| 143 |
+
|
| 144 |
+
| Key | Action |
|
| 145 |
+
|-----|--------|
|
| 146 |
+
| `W` | Move forward |
|
| 147 |
+
| `A` | Move left |
|
| 148 |
+
| `S` | Move backward |
|
| 149 |
+
| `D` | Move right |
|
| 150 |
+
|
| 151 |
+
The movement direction is relative to the camera. Rotate the camera by right-clicking and dragging in the MuJoCo viewer.
|
| 152 |
+
|
| 153 |
+
### Motion Styles
|
| 154 |
+
|
| 155 |
+
| Key | Style |
|
| 156 |
+
|-----|-------|
|
| 157 |
+
| `V` | Slow walk |
|
| 158 |
+
| `Z` | Hand crawling |
|
| 159 |
+
| `X` | Walk boxing |
|
| 160 |
+
| `B` | Elbow crawling |
|
| 161 |
+
| `R` | Stealth walk |
|
| 162 |
+
| `T` | Injured walk |
|
| 163 |
+
| `C` | Walk stealth (crouched) |
|
| 164 |
+
| `E` | Happy dance walk |
|
| 165 |
+
| `F` | Zombie walk |
|
| 166 |
+
| `G` | Gun walk |
|
| 167 |
+
| `Q` | Scared walk |
|
| 168 |
+
|
| 169 |
+
Note: crawling modes (`Z` hand crawling and `B` elbow crawling) currently do not support side-only directions.
|
| 170 |
+
|
| 171 |
+
Without pressing a style key, the default locomotion is: **idle** (no movement keys), **walk** (WASD pressed).
|
| 172 |
+
|
| 173 |
+
## Training
|
| 174 |
+
|
| 175 |
+
Training scripts are provided for all three model components. The scripts use synthetic data by default and load model configs from the saved checkpoints in `out/`. The full motion datasets are available at <https://bones.studio/datasets>.
|
| 176 |
+
|
| 177 |
+
**Full release status:** A full release — a model fully embedded in [GR00T whole-body control](https://github.com/NVlabs/GR00T-WholeBodyControl)'s robotics formulation, along with the complete training pipeline — is targeted for approximately one month out. Reproducibility experiments are already in flight; please check back for updates.
|
| 178 |
+
|
| 179 |
+
```bash
|
| 180 |
+
# Train the VQVAE (motion tokenizer)
|
| 181 |
+
python scripts/train_vqvae.py
|
| 182 |
+
|
| 183 |
+
# Train the pose model (requires pretrained VQVAE checkpoint)
|
| 184 |
+
python scripts/train_pose.py
|
| 185 |
+
|
| 186 |
+
# Train the root model (no VQVAE needed)
|
| 187 |
+
python scripts/train_root.py
|
| 188 |
+
```
|
| 189 |
+
|
| 190 |
+
### Dataset
|
| 191 |
+
|
| 192 |
+
The datasets used to train the pretrained checkpoints can be downloaded at <https://bones.studio/datasets>. All current training scripts default to **synthetic data** (see `motionbricks/data/synthetic_dataset.py`) so that the full training pipeline can be verified end-to-end without the real dataset.
|
| 193 |
+
|
| 194 |
+
## Motion Representation and Custom Datasets
|
| 195 |
+
|
| 196 |
+
For details on the motion feature representation, skeleton system, coordinate conventions, normalization, and feature computation pipeline, see [docs/motion_representation.md](docs/motion_representation.md).
|
| 197 |
+
|
| 198 |
+
For a step-by-step guide to training MotionBricks on your own motion data and adapting it to a new robot, see [docs/adding_your_own_dataset.md](docs/adding_your_own_dataset.md).
|
| 199 |
+
|
| 200 |
+
## Related Work
|
| 201 |
+
|
| 202 |
+
**Kimodo** — A sibling project focused on offline motion generation, complementary to MotionBricks' real-time runtime.
|
| 203 |
+
|
| 204 |
+
[Project page](https://research.nvidia.com/labs/sil/projects/kimodo/) · [GitHub](https://github.com/nv-tlabs/kimodo)
|
| 205 |
+
|
| 206 |
+
<p align="center">
|
| 207 |
+
<img src="assets/gifs/kimodo_teaser.gif" alt="Kimodo teaser" width="480">
|
| 208 |
+
</p>
|
| 209 |
+
|
| 210 |
+
**GEAR-SONIC** — Together with MotionBricks, GEAR-SONIC anchors NVIDIA's GR00T Whole-Body Control initiative.
|
| 211 |
+
|
| 212 |
+
[Project page](https://nvlabs.github.io/GEAR-SONIC/) · [GitHub](https://github.com/NVlabs/GR00T-WholeBodyControl)
|
| 213 |
+
|
| 214 |
+
<p align="center">
|
| 215 |
+
<img src="assets/gifs/sonic_teaser.gif" alt="GEAR-SONIC teaser" width="480">
|
| 216 |
+
</p>
|
| 217 |
+
|
| 218 |
+
**BONES-SEED Dataset** — MotionBricks' training corpus — 350k production-grade mocap clips from real human actors and actresses.
|
| 219 |
+
|
| 220 |
+
[Dataset page](https://huggingface.co/datasets/bones-studio/seed)
|
| 221 |
+
|
| 222 |
+
<p align="center">
|
| 223 |
+
<img src="assets/gifs/bones_seed_teaser.gif" alt="BONES-SEED teaser" width="480">
|
| 224 |
+
</p>
|
| 225 |
+
|
| 226 |
+
**SOMA Retargeter** — The Newton-based solver that retargets SOMA capture onto the G1, producing MotionBricks' training data.
|
| 227 |
+
|
| 228 |
+
[GitHub](https://github.com/NVIDIA/soma-retargeter)
|
| 229 |
+
|
| 230 |
+
<p align="center">
|
| 231 |
+
<img src="assets/gifs/soma_retargeter_teaser.gif" alt="SOMA Retargeter teaser" width="480">
|
| 232 |
+
</p>
|
| 233 |
+
|
| 234 |
+
## Project Structure
|
| 235 |
+
|
| 236 |
+
```
|
| 237 |
+
motionbricks/
|
| 238 |
+
assets/skeletons/g1/ # MuJoCo XMLs and STL meshes
|
| 239 |
+
motionbricks/ # Python package
|
| 240 |
+
scripts/
|
| 241 |
+
interactive_demo_g1.py # Interactive demo
|
| 242 |
+
train_vqvae.py # VQVAE training
|
| 243 |
+
train_pose.py # Pose model training
|
| 244 |
+
train_root.py # Root model training
|
| 245 |
+
out/ # Pre-trained checkpoints (Git LFS)
|
| 246 |
+
G1-clip.ckpt
|
| 247 |
+
motionbricks_vqvae/
|
| 248 |
+
motionbricks_pose/
|
| 249 |
+
motionbricks_root/
|
| 250 |
+
setup.py
|
| 251 |
+
```
|
| 252 |
+
|
| 253 |
+
## Known Issues
|
| 254 |
+
|
| 255 |
+
- **Linux/X11 only:** The keyboard key-grab workaround requires X11 (`python-xlib`). On Wayland, macOS, or Windows, some MuJoCo keyboard shortcuts may conflict with the controller keys. Keep the **terminal focused** (not the MuJoCo window) as a workaround.
|
| 256 |
+
- **`PYTORCH_JIT=0` disables key grabs:** Running with `PYTORCH_JIT=0` interferes with the X11 key-grab workaround. If you need `PYTORCH_JIT=0`, keep the terminal focused instead.
|
| 257 |
+
- The `pynput` package is required for keyboard input on Linux/macOS. On Windows, the `keyboard` package is used instead.
|
| 258 |
+
|
| 259 |
+
## Citation
|
| 260 |
+
|
| 261 |
+
If you use MotionBricks in your research, please cite:
|
| 262 |
+
|
| 263 |
+
```bibtex
|
| 264 |
+
@misc{wang2026motionbricksscalablerealtimemotions,
|
| 265 |
+
title={MotionBricks: Scalable Real-Time Motions with Modular Latent Generative Model and Smart Primitives},
|
| 266 |
+
author={Tingwu Wang and Olivier Dionne and Michael De Ruyter and David Minor and Davis Rempe and Kaifeng Zhao and Mathis Petrovich and Ye Yuan and Chenran Li and Zhengyi Luo and Brian Robison and Xavier Blackwell and Bernardo Antoniazzi and Xue Bin Peng and Yuke Zhu and Simon Yuen},
|
| 267 |
+
year={2026},
|
| 268 |
+
eprint={2604.24833},
|
| 269 |
+
archivePrefix={arXiv},
|
| 270 |
+
primaryClass={cs.RO},
|
| 271 |
+
url={https://arxiv.org/abs/2604.24833},
|
| 272 |
+
}
|
| 273 |
+
```
|
| 274 |
+
|
| 275 |
+
## License
|
| 276 |
+
|
| 277 |
+
Source code in this repository is licensed under **Apache 2.0**. Pretrained model weights are licensed under the **NVIDIA Open Model License**, which permits commercial use with attribution subject to the trustworthy AI requirements.
|
| 278 |
+
|
| 279 |
+
## Contact
|
| 280 |
+
|
| 281 |
+
For questions and feedback, please reach out at **`gear-wbc@nvidia.com`**.
|
GR00T-WholeBodyControl/motionbricks/setup.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from setuptools import setup, find_packages
|
| 2 |
+
|
| 3 |
+
setup(
|
| 4 |
+
name="motionbricks",
|
| 5 |
+
version="0.1.0",
|
| 6 |
+
packages=find_packages(),
|
| 7 |
+
python_requires=">=3.10",
|
| 8 |
+
install_requires=[
|
| 9 |
+
"torch>=2.0",
|
| 10 |
+
"numpy",
|
| 11 |
+
"mujoco>=3.0",
|
| 12 |
+
"scipy",
|
| 13 |
+
"hydra-core",
|
| 14 |
+
"omegaconf",
|
| 15 |
+
"pytorch-lightning",
|
| 16 |
+
"transformers",
|
| 17 |
+
"pynput",
|
| 18 |
+
"matplotlib",
|
| 19 |
+
"vector-quantize-pytorch",
|
| 20 |
+
"colorlog",
|
| 21 |
+
"adam-atan2-pytorch",
|
| 22 |
+
],
|
| 23 |
+
)
|
GR00T-WholeBodyControl/pyproject.toml
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Root pyproject.toml — tooling configuration only.
|
| 2 |
+
# To install packages, use:
|
| 3 |
+
# pip install -e decoupled_wbc/ (or decoupled_wbc[full], decoupled_wbc[dev])
|
| 4 |
+
# pip install -e gear_sonic/ (or gear_sonic[teleop], gear_sonic[sim])
|
| 5 |
+
|
| 6 |
+
[tool.black]
|
| 7 |
+
line-length = 100
|
| 8 |
+
include = '\.pyi?$'
|
| 9 |
+
exclude = '''
|
| 10 |
+
(
|
| 11 |
+
__pycache__
|
| 12 |
+
| \.git
|
| 13 |
+
| \.mypy_cache
|
| 14 |
+
| \.pytest_cache
|
| 15 |
+
| \.vscode
|
| 16 |
+
| \.venv
|
| 17 |
+
| \bdist\b
|
| 18 |
+
| \bdoc\b
|
| 19 |
+
| external_dependencies
|
| 20 |
+
| logs
|
| 21 |
+
| source
|
| 22 |
+
| /(
|
| 23 |
+
| external_dependencies/
|
| 24 |
+
)/
|
| 25 |
+
)
|
| 26 |
+
'''
|
| 27 |
+
|
| 28 |
+
[tool.isort]
|
| 29 |
+
profile = "black"
|
| 30 |
+
multi_line_output = 3
|
| 31 |
+
skip = [
|
| 32 |
+
"external_dependencies",
|
| 33 |
+
"external_dependencies/**",
|
| 34 |
+
]
|
| 35 |
+
skip_glob = [
|
| 36 |
+
"external_dependencies/*",
|
| 37 |
+
]
|
| 38 |
+
|
| 39 |
+
[tool.pyright]
|
| 40 |
+
reportPrivateImportUsage = false
|
| 41 |
+
|
| 42 |
+
[tool.ruff]
|
| 43 |
+
line-length = 115
|
| 44 |
+
target-version = "py310"
|
| 45 |
+
exclude = [
|
| 46 |
+
"gear_sonic/dexmg",
|
| 47 |
+
"external_dependencies",
|
| 48 |
+
"external_dependencies/**",
|
| 49 |
+
"./external_dependencies/**",
|
| 50 |
+
"*.ipynb",
|
| 51 |
+
]
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
[tool.ruff.lint]
|
| 55 |
+
select = ["E", "F", "I"]
|
| 56 |
+
|
| 57 |
+
[tool.ruff.lint.per-file-ignores]
|
| 58 |
+
"__init__.py" = ["F401"]
|
| 59 |
+
|
| 60 |
+
[tool.ruff.lint.isort]
|
| 61 |
+
case-sensitive = false
|
| 62 |
+
combine-as-imports = true
|
| 63 |
+
force-sort-within-sections = true
|
| 64 |
+
from-first = false
|
| 65 |
+
single-line-exclusions = ["typing"]
|
| 66 |
+
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
|
| 67 |
+
|
| 68 |
+
[tool.mypy]
|
| 69 |
+
ignore_missing_imports = true
|
| 70 |
+
no_site_packages = true
|
| 71 |
+
check_untyped_defs = true
|
| 72 |
+
exclude = [
|
| 73 |
+
"external_dependencies",
|
| 74 |
+
]
|
| 75 |
+
|
| 76 |
+
[[tool.mypy.overrides]]
|
| 77 |
+
module = "tests.*"
|
| 78 |
+
strict_optional = false
|
| 79 |
+
|
| 80 |
+
[tool.pytest.ini_options]
|
| 81 |
+
testpaths = "decoupled_wbc/tests/"
|
| 82 |
+
python_classes = [
|
| 83 |
+
"Test*",
|
| 84 |
+
"*Test"
|
| 85 |
+
]
|
| 86 |
+
log_format = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
|
| 87 |
+
log_level = "DEBUG"
|
GR00T-WholeBodyControl/systemd/composed_camera_server.service
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# systemd service for the SONIC composed camera server.
|
| 2 |
+
#
|
| 3 |
+
# Publishes JPEG-encoded camera frames over ZMQ so the data exporter
|
| 4 |
+
# (on the workstation) can subscribe and record.
|
| 5 |
+
#
|
| 6 |
+
# ── Setup ────────────────────────────────────────────────────────
|
| 7 |
+
# The install script can generate and install this automatically:
|
| 8 |
+
# bash install_scripts/install_camera_server.sh
|
| 9 |
+
#
|
| 10 |
+
# Or manually:
|
| 11 |
+
# 1. Edit USER, HOME, REPO_DIR, and the ExecStart command below.
|
| 12 |
+
# 2. Copy to systemd:
|
| 13 |
+
# sudo cp systemd/composed_camera_server.service /etc/systemd/system/
|
| 14 |
+
# 3. Enable and start:
|
| 15 |
+
# sudo systemctl daemon-reload
|
| 16 |
+
# sudo systemctl enable composed_camera_server.service
|
| 17 |
+
# sudo systemctl start composed_camera_server.service
|
| 18 |
+
# 4. Check status:
|
| 19 |
+
# sudo systemctl status composed_camera_server.service
|
| 20 |
+
# journalctl -u composed_camera_server.service -f
|
| 21 |
+
#
|
| 22 |
+
# ── Finding your device ID ───────────────────────────────────────
|
| 23 |
+
# OAK cameras:
|
| 24 |
+
# python -c "import depthai as dai; print(dai.Device.getAllAvailableDevices())"
|
| 25 |
+
# RealSense:
|
| 26 |
+
# rs-enumerate-devices --short
|
| 27 |
+
# USB:
|
| 28 |
+
# ls /dev/video* # use the index number, e.g. "0" for /dev/video0
|
| 29 |
+
# ─────────────────────────────────────────────────────────────────
|
| 30 |
+
|
| 31 |
+
[Unit]
|
| 32 |
+
Description=SONIC Composed Camera Server (ZMQ)
|
| 33 |
+
After=network.target
|
| 34 |
+
|
| 35 |
+
[Service]
|
| 36 |
+
Type=simple
|
| 37 |
+
|
| 38 |
+
# ── EDIT THESE for your robot ────────────────────────────────────
|
| 39 |
+
User=nvidia
|
| 40 |
+
Environment="HOME=/home/nvidia"
|
| 41 |
+
Environment="REPO_DIR=/home/nvidia/GR00T-WholeBodyControl"
|
| 42 |
+
# ─────────────────────────────────────────────────────────────────
|
| 43 |
+
|
| 44 |
+
WorkingDirectory=${REPO_DIR}
|
| 45 |
+
|
| 46 |
+
# Edit the ExecStart line to match your camera setup.
|
| 47 |
+
# Single ego-view OAK camera (device ID required when multiple OAK devices connected):
|
| 48 |
+
ExecStart=${REPO_DIR}/.venv_camera/bin/python -m gear_sonic.camera.composed_camera \
|
| 49 |
+
--ego-view-camera oak \
|
| 50 |
+
--ego-view-device-id YOUR_MXID_HERE \
|
| 51 |
+
--port 5555
|
| 52 |
+
|
| 53 |
+
# Multi-camera example (ego + wrist cameras):
|
| 54 |
+
# ExecStart=${REPO_DIR}/.venv_camera/bin/python -m gear_sonic.camera.composed_camera \
|
| 55 |
+
# --ego-view-camera oak --ego-view-device-id EGO_MXID \
|
| 56 |
+
# --left-wrist-camera oak --left-wrist-device-id LEFT_MXID \
|
| 57 |
+
# --right-wrist-camera oak --right-wrist-device-id RIGHT_MXID \
|
| 58 |
+
# --port 5555
|
| 59 |
+
|
| 60 |
+
Restart=on-failure
|
| 61 |
+
RestartSec=5
|
| 62 |
+
StandardOutput=journal
|
| 63 |
+
StandardError=journal
|
| 64 |
+
|
| 65 |
+
[Install]
|
| 66 |
+
WantedBy=multi-user.target
|
Isaac-GR00T/.coveragerc
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Coverage.py configuration
|
| 2 |
+
# https://coverage.readthedocs.io/en/latest/config.html
|
| 3 |
+
|
| 4 |
+
[run]
|
| 5 |
+
data_file = .coverage-data
|
| 6 |
+
disable_warnings =
|
| 7 |
+
module-not-imported
|
| 8 |
+
no-data-collected
|
| 9 |
+
parallel = True
|
| 10 |
+
|
| 11 |
+
[report]
|
| 12 |
+
exclude_lines =
|
| 13 |
+
@overload
|
| 14 |
+
def __repr__
|
| 15 |
+
if __name__ == .__main__.:
|
| 16 |
+
if TYPE_CHECKING:
|
| 17 |
+
pragma: no cover
|
| 18 |
+
raise AssertionError
|
| 19 |
+
raise NotImplementedError
|
| 20 |
+
omit =
|
| 21 |
+
*/tests/*
|
| 22 |
+
test_*.py
|
| 23 |
+
*_test.py
|
| 24 |
+
skip_empty = True
|
| 25 |
+
show_missing = True
|
| 26 |
+
|
| 27 |
+
[xml]
|
| 28 |
+
output = coverage.xml
|
Isaac-GR00T/.dockerignore
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Exclude large and unnecessary files from the Docker build context.
|
| 2 |
+
# Used when building Orin/Thor/Spark images with the repo root as build context.
|
| 3 |
+
checkpoints/
|
| 4 |
+
demo_data/
|
| 5 |
+
*.safetensors
|
| 6 |
+
*.bin
|
| 7 |
+
*.onnx
|
| 8 |
+
*.trt
|
| 9 |
+
.git/
|
| 10 |
+
.venv/
|
| 11 |
+
__pycache__/
|
| 12 |
+
*.pyc
|
| 13 |
+
*.egg-info/
|
| 14 |
+
.pytest_cache/
|
| 15 |
+
.mypy_cache/
|
| 16 |
+
.ruff_cache/
|
| 17 |
+
logs/
|
| 18 |
+
dist/
|
| 19 |
+
gr00t_trt_deployment/
|
Isaac-GR00T/.gitattributes
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
media/*.gif filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
demo_data/**/*.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
demo_data/**/*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
examples/GR00TWholeBodyControl/media/**/*.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
scripts/deployment/dgpu/wheels/*.whl filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
scripts/deployment/orin/wheels/*.whl filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
scripts/deployment/spark/wheels/*.whl filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
scripts/deployment/thor/wheels/*.whl filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
examples/RoboLab/media/**/*.mp4 filter=lfs diff=lfs merge=lfs -text
|
Isaac-GR00T/.gitignore
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Test debug artifacts
|
| 2 |
+
/debug_video_decoding/
|
| 3 |
+
|
| 4 |
+
# Finetune datasets
|
| 5 |
+
/examples/GR00T-WholeBodyControl/PhysicalAI-Robotics-GR00T-X-Embodiment-Sim/
|
| 6 |
+
/examples/LIBERO/libero_10_no_noops_1.0.0_lerobot/
|
| 7 |
+
/examples/LIBERO/libero_goal_no_noops_1.0.0_lerobot/
|
| 8 |
+
/examples/LIBERO/libero_object_no_noops_1.0.0_lerobot/
|
| 9 |
+
/examples/LIBERO/libero_spatial_no_noops_1.0.0_lerobot/
|
| 10 |
+
|
| 11 |
+
# UV lock file
|
| 12 |
+
uv.lock
|
| 13 |
+
|
| 14 |
+
# Byte-compiled / optimized / DLL files
|
| 15 |
+
__pycache__/
|
| 16 |
+
*.py[cod]
|
| 17 |
+
*$py.class
|
| 18 |
+
|
| 19 |
+
# ML / experiment outputs
|
| 20 |
+
wandb/
|
| 21 |
+
outputs/
|
| 22 |
+
logs/
|
| 23 |
+
runs/
|
| 24 |
+
out/
|
| 25 |
+
recordings/
|
| 26 |
+
plots/
|
| 27 |
+
*.npz
|
| 28 |
+
|
| 29 |
+
# C extensions
|
| 30 |
+
*.so
|
| 31 |
+
|
| 32 |
+
# Distribution / packaging
|
| 33 |
+
.Python
|
| 34 |
+
build/
|
| 35 |
+
develop-eggs/
|
| 36 |
+
dist/
|
| 37 |
+
downloads/
|
| 38 |
+
eggs/
|
| 39 |
+
.eggs/
|
| 40 |
+
sdist/
|
| 41 |
+
var/
|
| 42 |
+
wheels/
|
| 43 |
+
share/python-wheels/
|
| 44 |
+
*.egg-info/
|
| 45 |
+
.installed.cfg
|
| 46 |
+
*.egg
|
| 47 |
+
*.swp
|
| 48 |
+
*.swo
|
| 49 |
+
MANIFEST
|
| 50 |
+
|
| 51 |
+
# PyInstaller
|
| 52 |
+
*.manifest
|
| 53 |
+
*.spec
|
| 54 |
+
|
| 55 |
+
# Installer logs
|
| 56 |
+
pip-log.txt
|
| 57 |
+
pip-delete-this-directory.txt
|
| 58 |
+
|
| 59 |
+
# Unit test / coverage
|
| 60 |
+
htmlcov/
|
| 61 |
+
.tox/
|
| 62 |
+
.nox/
|
| 63 |
+
.coverage
|
| 64 |
+
.coverage.*
|
| 65 |
+
.cache
|
| 66 |
+
nosetests.xml
|
| 67 |
+
coverage.xml
|
| 68 |
+
*.cover
|
| 69 |
+
*.py,cover
|
| 70 |
+
.hypothesis/
|
| 71 |
+
.pytest_cache/
|
| 72 |
+
cover/
|
| 73 |
+
|
| 74 |
+
# Translations
|
| 75 |
+
*.mo
|
| 76 |
+
*.pot
|
| 77 |
+
|
| 78 |
+
# App / framework stuff
|
| 79 |
+
*.log
|
| 80 |
+
local_settings.py
|
| 81 |
+
db.sqlite3
|
| 82 |
+
db.sqlite3-journal
|
| 83 |
+
|
| 84 |
+
# Flask
|
| 85 |
+
instance/
|
| 86 |
+
.webassets-cache
|
| 87 |
+
|
| 88 |
+
# Jupyter Notebook
|
| 89 |
+
.ipynb_checkpoints
|
| 90 |
+
|
| 91 |
+
# IPython
|
| 92 |
+
profile_default/
|
| 93 |
+
ipython_config.py
|
| 94 |
+
|
| 95 |
+
# Environment managers
|
| 96 |
+
.pdm.toml
|
| 97 |
+
.pdm-python
|
| 98 |
+
.pdm-build/
|
| 99 |
+
__pypackages__/
|
| 100 |
+
|
| 101 |
+
# IDEs
|
| 102 |
+
.vscode/
|
| 103 |
+
.idea/
|
| 104 |
+
.cursor/
|
| 105 |
+
.cursor*
|
| 106 |
+
.claude/
|
| 107 |
+
|
| 108 |
+
# Sphinx docs
|
| 109 |
+
docs/_build/
|
| 110 |
+
|
| 111 |
+
# PyBuilder
|
| 112 |
+
.pybuilder/
|
| 113 |
+
target/
|
| 114 |
+
|
| 115 |
+
# Scrapy
|
| 116 |
+
.scrapy
|
| 117 |
+
|
| 118 |
+
# Mkdocs
|
| 119 |
+
/site
|
| 120 |
+
|
| 121 |
+
# Typing/static analysis
|
| 122 |
+
.mypy_cache/
|
| 123 |
+
.dmypy.json
|
| 124 |
+
dmypy.json
|
| 125 |
+
.pyre/
|
| 126 |
+
.pytype/
|
| 127 |
+
.ruff_cache/
|
| 128 |
+
pyrightconfig.json
|
| 129 |
+
|
| 130 |
+
# Cython
|
| 131 |
+
cython_debug/
|
| 132 |
+
|
| 133 |
+
# OS / editor junk
|
| 134 |
+
.DS_Store
|
| 135 |
+
*.code-workspace
|
| 136 |
+
|
| 137 |
+
# Virtual environments
|
| 138 |
+
.venv/
|
| 139 |
+
.venv/*
|
| 140 |
+
env/
|
| 141 |
+
venv/
|
| 142 |
+
|
| 143 |
+
# Mujoco
|
| 144 |
+
MUJOCO_LOG.TXT
|
| 145 |
+
playground/
|
| 146 |
+
|
| 147 |
+
# Shell scripts / batching
|
| 148 |
+
batch_*.sh
|
| 149 |
+
logs_*/
|
| 150 |
+
|
| 151 |
+
# Git worktrees
|
| 152 |
+
/wt
|
| 153 |
+
|
| 154 |
+
# General project data / artifacts
|
| 155 |
+
episode_data/
|
| 156 |
+
third_parties/
|
| 157 |
+
*.rdb
|
| 158 |
+
dump.rdb
|
| 159 |
+
|
| 160 |
+
# Docker
|
| 161 |
+
# Note: docker/.dockerignore is tracked — it controls the Docker build context
|
| 162 |
+
|
| 163 |
+
/examples/GR00TWholeBodyControl/media/
|
| 164 |
+
sysid_data/
|
| 165 |
+
isaac_data/
|
| 166 |
+
offline_open_loop_eval_plots/
|
| 167 |
+
|
| 168 |
+
# Generic model/data folders
|
| 169 |
+
/models
|
| 170 |
+
/data
|
Isaac-GR00T/.gitmodules
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[submodule "external_dependencies/LIBERO"]
|
| 2 |
+
path = external_dependencies/LIBERO
|
| 3 |
+
url = https://github.com/Lifelong-Robot-Learning/LIBERO.git
|
| 4 |
+
[submodule "external_dependencies/robocasa-gr1-tabletop-tasks"]
|
| 5 |
+
path = external_dependencies/robocasa-gr1-tabletop-tasks
|
| 6 |
+
url = https://github.com/robocasa/robocasa-gr1-tabletop-tasks
|
| 7 |
+
[submodule "external_dependencies/SimplerEnv"]
|
| 8 |
+
path = external_dependencies/SimplerEnv
|
| 9 |
+
url = https://github.com/squarefk/SimplerEnv.git
|
| 10 |
+
[submodule "external_dependencies/robocasa"]
|
| 11 |
+
path = external_dependencies/robocasa
|
| 12 |
+
url = https://github.com/squarefk/robocasa
|
Isaac-GR00T/.pre-commit-config.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
exclude: ^(external_dependencies/)
|
| 2 |
+
repos:
|
| 3 |
+
# Ruff: lint + autofix
|
| 4 |
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
| 5 |
+
rev: v0.12.7
|
| 6 |
+
hooks:
|
| 7 |
+
- id: ruff
|
| 8 |
+
args: [--fix]
|
| 9 |
+
- id: ruff-format
|
| 10 |
+
|
| 11 |
+
# Catch cross-platform pyproject pin drift (dGPU/Orin/Spark/Thor) at commit
|
| 12 |
+
# time; a missed mirror otherwise only surfaces at install on the unsynced
|
| 13 |
+
# platform. tomli is the 3.10 backport of stdlib tomllib (3.11+).
|
| 14 |
+
- repo: local
|
| 15 |
+
hooks:
|
| 16 |
+
- id: check-manifest-alignment
|
| 17 |
+
name: cross-platform pyproject manifest alignment
|
| 18 |
+
entry: python tools/check_manifest_alignment.py
|
| 19 |
+
language: python
|
| 20 |
+
additional_dependencies: ["tomli; python_version < '3.11'"]
|
| 21 |
+
# Mirrors MANIFESTS in tools/check_manifest_alignment.py; keep in sync when
|
| 22 |
+
# adding a platform. A miss only drops the local trigger — the unit-test
|
| 23 |
+
# live gate reads MANIFESTS directly and still fails CI on drift.
|
| 24 |
+
files: ^(pyproject\.toml|scripts/deployment/(orin|spark|thor)/pyproject\.toml|tools/(check_manifest_alignment\.py|manifest_alignment\.toml))$
|
| 25 |
+
pass_filenames: false
|
Isaac-GR00T/AGENTS.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md — Isaac GR00T N1.7
|
| 2 |
+
|
| 3 |
+
## Project overview
|
| 4 |
+
|
| 5 |
+
Isaac GR00T N1.7 is an open vision-language-action (VLA) model for generalized humanoid robot skills.
|
| 6 |
+
The repo contains the model, training pipeline, evaluation harness, and deployment tooling.
|
| 7 |
+
|
| 8 |
+
- **Language:** Python 3.12 (dGPU, Thor, DGX Spark); Python 3.10 (Orin — see deployment dir)
|
| 9 |
+
- **Package manager:** [uv](https://docs.astral.sh/uv/)
|
| 10 |
+
- **Build system:** setuptools (see `pyproject.toml`)
|
| 11 |
+
|
| 12 |
+
## Quick-start commands
|
| 13 |
+
|
| 14 |
+
```bash
|
| 15 |
+
# Install (dev mode with all extras)
|
| 16 |
+
uv sync --all-extras
|
| 17 |
+
|
| 18 |
+
# Lint and format (uses ruff via pre-commit)
|
| 19 |
+
pre-commit run --all-files
|
| 20 |
+
|
| 21 |
+
# Run CPU tests
|
| 22 |
+
python -m pytest tests/ -m "not gpu" -v --timeout=300
|
| 23 |
+
|
| 24 |
+
# Run GPU tests
|
| 25 |
+
python -m pytest tests/ -m gpu -v --timeout=300
|
| 26 |
+
|
| 27 |
+
# Build package
|
| 28 |
+
uv build
|
| 29 |
+
|
| 30 |
+
# Validate lockfile
|
| 31 |
+
uv lock --locked
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
## Code style
|
| 35 |
+
|
| 36 |
+
- Formatter: `ruff format` (double quotes, spaces, line-length 100)
|
| 37 |
+
- Linter: `ruff check` with rules E, F, I (ignores E501)
|
| 38 |
+
- Config lives in `pyproject.toml` under `[tool.ruff]`
|
| 39 |
+
- Run `pre-commit run --all-files` before committing
|
| 40 |
+
|
| 41 |
+
## Directory layout
|
| 42 |
+
|
| 43 |
+
```
|
| 44 |
+
gr00t/ # Main package
|
| 45 |
+
configs/ # Training, data, and model configs
|
| 46 |
+
data/ # Data loading, embodiment tags, dataset processing
|
| 47 |
+
eval/ # Evaluation (run_gr00t_server.py)
|
| 48 |
+
experiment/ # Training pipeline (launch_finetune.py, trainer.py)
|
| 49 |
+
model/ # Model architecture (N1.7, base, modules)
|
| 50 |
+
policy/ # Policy inference (Gr00tPolicy, server/client)
|
| 51 |
+
examples/ # Per-embodiment example configs and READMEs
|
| 52 |
+
scripts/ # Deployment, conversion, and utility scripts
|
| 53 |
+
deployment/ # Platform install scripts (dgpu, orin, thor, spark)
|
| 54 |
+
tests/ # pytest suite (markers: gpu, not gpu)
|
| 55 |
+
getting_started/ # User-facing guides and notebooks
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
## Key entry points
|
| 59 |
+
|
| 60 |
+
- **Fine-tune:** `bash examples/finetune.sh --base-model-path <path> --dataset-path <path> --embodiment-tag <tag> --output-dir <dir>`
|
| 61 |
+
- **Inference server:** `python gr00t/eval/run_gr00t_server.py --model-path <path> --embodiment-tag <tag>`
|
| 62 |
+
- **ONNX export:** `python scripts/deployment/export_onnx_n1d7.py`
|
| 63 |
+
- **TensorRT build:** `python scripts/deployment/build_trt_pipeline.py`
|
| 64 |
+
- **Benchmark:** `python scripts/deployment/benchmark_inference.py`
|
| 65 |
+
|
| 66 |
+
## Testing
|
| 67 |
+
|
| 68 |
+
- Test markers: `gpu` (requires GPU), default is CPU-safe
|
| 69 |
+
- Fixtures live in `tests/fixtures/` and `demo_data/`
|
| 70 |
+
- CI runs CPU and GPU tests in separate jobs with 300s timeout
|
| 71 |
+
|
| 72 |
+
## Deployment platforms
|
| 73 |
+
|
| 74 |
+
- **dGPU (H100, A100, RTX):** CUDA 12.8 — install via `scripts/deployment/dgpu/install_deps.sh`, container via top-level `docker/Dockerfile` (supports x86_64 and aarch64)
|
| 75 |
+
- **Jetson Orin:** CUDA 12.6 — install via `scripts/deployment/orin/install_deps.sh`, container via `scripts/deployment/orin/Dockerfile`
|
| 76 |
+
- **Jetson Thor:** CUDA 13.0 — install via `scripts/deployment/thor/install_deps.sh`, container via `scripts/deployment/thor/Dockerfile`
|
| 77 |
+
- **DGX Spark:** CUDA 13.0 — install via `scripts/deployment/spark/install_deps.sh`, container via `scripts/deployment/spark/Dockerfile`
|
| 78 |
+
|
| 79 |
+
Each Jetson/Spark platform ships an `activate_*.sh` helper (`scripts/activate_orin.sh`, `scripts/activate_spark.sh`, `scripts/activate_thor.sh`) that exports platform-specific library paths. For dGPU, the standard `source .venv/bin/activate` is sufficient.
|
Isaac-GR00T/ATTRIBUTIONS.md
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
Isaac-GR00T/CLAUDE.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# CLAUDE.md — Isaac GR00T N1.7
|
| 2 |
+
|
| 3 |
+
## Project overview
|
| 4 |
+
|
| 5 |
+
Isaac GR00T N1.7 is an open vision-language-action (VLA) model for generalized humanoid robot skills.
|
| 6 |
+
The repo contains the model, training pipeline, evaluation harness, and deployment tooling.
|
| 7 |
+
|
| 8 |
+
- **Language:** Python 3.12 (dGPU, Thor, DGX Spark); Python 3.10 (Orin — see deployment dir)
|
| 9 |
+
- **Package manager:** [uv](https://docs.astral.sh/uv/)
|
| 10 |
+
- **Build system:** setuptools (see `pyproject.toml`)
|
| 11 |
+
|
| 12 |
+
## Quick-start commands
|
| 13 |
+
|
| 14 |
+
```bash
|
| 15 |
+
# Install (dev mode with all extras)
|
| 16 |
+
uv sync --all-extras
|
| 17 |
+
|
| 18 |
+
# Lint and format (uses ruff via pre-commit)
|
| 19 |
+
pre-commit run --all-files
|
| 20 |
+
|
| 21 |
+
# Run CPU tests
|
| 22 |
+
python -m pytest tests/ -m "not gpu" -v --timeout=300
|
| 23 |
+
|
| 24 |
+
# Run GPU tests
|
| 25 |
+
python -m pytest tests/ -m gpu -v --timeout=300
|
| 26 |
+
|
| 27 |
+
# Build package
|
| 28 |
+
uv build
|
| 29 |
+
|
| 30 |
+
# Validate lockfile
|
| 31 |
+
uv lock --locked
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
## Code style
|
| 35 |
+
|
| 36 |
+
- Formatter: `ruff format` (double quotes, spaces, line-length 100)
|
| 37 |
+
- Linter: `ruff check` with rules E, F, I (ignores E501)
|
| 38 |
+
- Config lives in `pyproject.toml` under `[tool.ruff]`
|
| 39 |
+
- Run `pre-commit run --all-files` before committing
|
| 40 |
+
|
| 41 |
+
## Directory layout
|
| 42 |
+
|
| 43 |
+
```
|
| 44 |
+
gr00t/ # Main package
|
| 45 |
+
configs/ # Training, data, and model configs
|
| 46 |
+
data/ # Data loading, embodiment tags, dataset processing
|
| 47 |
+
eval/ # Evaluation (run_gr00t_server.py)
|
| 48 |
+
experiment/ # Training pipeline (launch_finetune.py, trainer.py)
|
| 49 |
+
model/ # Model architecture (N1.7, base, modules)
|
| 50 |
+
policy/ # Policy inference (Gr00tPolicy, server/client)
|
| 51 |
+
examples/ # Per-embodiment example configs and READMEs
|
| 52 |
+
scripts/ # Deployment, conversion, and utility scripts
|
| 53 |
+
deployment/ # Platform install scripts (dgpu, orin, thor, spark)
|
| 54 |
+
tests/ # pytest suite (markers: gpu, not gpu)
|
| 55 |
+
getting_started/ # User-facing guides and notebooks
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
## Key entry points
|
| 59 |
+
|
| 60 |
+
- **Fine-tune:** `bash examples/finetune.sh --base-model-path <path> --dataset-path <path> --embodiment-tag <tag> --output-dir <dir>`
|
| 61 |
+
- **Inference server:** `python gr00t/eval/run_gr00t_server.py --model-path <path> --embodiment-tag <tag>`
|
| 62 |
+
- **ONNX export:** `python scripts/deployment/export_onnx_n1d7.py`
|
| 63 |
+
- **TensorRT build:** `python scripts/deployment/build_trt_pipeline.py`
|
| 64 |
+
- **Benchmark:** `python scripts/deployment/benchmark_inference.py`
|
| 65 |
+
|
| 66 |
+
## Testing
|
| 67 |
+
|
| 68 |
+
- Test markers: `gpu` (requires GPU), default is CPU-safe
|
| 69 |
+
- Fixtures live in `tests/fixtures/` and `demo_data/`
|
| 70 |
+
- CI runs CPU and GPU tests in separate jobs with 300s timeout
|
| 71 |
+
|
| 72 |
+
## Deployment platforms
|
| 73 |
+
|
| 74 |
+
- **dGPU (H100, A100, RTX):** CUDA 12.8 — install via `scripts/deployment/dgpu/install_deps.sh`, container via top-level `docker/Dockerfile` (supports x86_64 and aarch64)
|
| 75 |
+
- **Jetson Orin:** CUDA 12.6 — install via `scripts/deployment/orin/install_deps.sh`, container via `scripts/deployment/orin/Dockerfile`
|
| 76 |
+
- **Jetson Thor:** CUDA 13.0 — install via `scripts/deployment/thor/install_deps.sh`, container via `scripts/deployment/thor/Dockerfile`
|
| 77 |
+
- **DGX Spark:** CUDA 13.0 — install via `scripts/deployment/spark/install_deps.sh`, container via `scripts/deployment/spark/Dockerfile`
|
| 78 |
+
|
| 79 |
+
Each Jetson/Spark platform ships an `activate_*.sh` helper (`scripts/activate_orin.sh`, `scripts/activate_spark.sh`, `scripts/activate_thor.sh`) that exports platform-specific library paths. For dGPU, the standard `source .venv/bin/activate` is sufficient.
|
Isaac-GR00T/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contributions
|
| 2 |
+
|
| 3 |
+
We welcome pull requests and contributions. If you encounter issues or have suggestions, please open an [Issue](https://github.com/NVIDIA/Isaac-GR00T/issues) or submit a pull request in this repository.
|
| 4 |
+
|
| 5 |
+
## Support
|
| 6 |
+
|
| 7 |
+
Now that GR00T N1.7 has reached General Availability (GA), it ships with a stable, fully validated feature set. If you encounter issues or have suggestions, please open an [Issue](https://github.com/NVIDIA/Isaac-GR00T/issues) in this repository.
|
Isaac-GR00T/FAQ.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# GR00T N1.7 FAQ
|
| 2 |
+
|
| 3 |
+
## Infrastructure & Hardware
|
| 4 |
+
|
| 5 |
+
### Is the data loader GPU-accelerated?
|
| 6 |
+
|
| 7 |
+
No, the current data loader is CPU-based. However, it has been heavily optimized for multimodal data to ensure it does not become a training bottleneck. We validated this on various configurations, including GB200, H100, and local desktops with RTX 4090 GPUs. We are actively exploring GPU-accelerated approaches for future releases.
|
| 8 |
+
|
| 9 |
+
### Is the same data loader used for both pre-training and post-training?
|
| 10 |
+
|
| 11 |
+
Yes, the data loading pipeline is unified across both training stages.
|
| 12 |
+
|
| 13 |
+
### What is the role of the Policy Remote Server in the server-client deployment?
|
| 14 |
+
|
| 15 |
+
The Policy Remote Server decouples inference from the physical robot. This allows users to run the policy on a high-compute cluster (e.g., H100s) for faster inference while the robot operates in a separate environment. It separates dependencies and enables scaling beyond the robot's onboard compute. See [Server-Client Inference](README.md#server-client-inference-for-deployment) for the architecture and setup.
|
| 16 |
+
|
| 17 |
+
## Workflow & Architecture
|
| 18 |
+
|
| 19 |
+
### Why retain only specific LLM layers (e.g., 16 layers) during fine-tuning?
|
| 20 |
+
|
| 21 |
+
This configuration was empirically tuned for the backbone (e.g., Eagle, or [Cosmos-Reason](https://huggingface.co/nvidia/Cosmos-Reason2-2B) — the reasoning VLM used as N1.7's backbone). Research suggests early layers capture grammatical structure, while middle-to-late layers are highly expressive. However, the very last layers are often over-optimized for next-token prediction; pruning or freezing them can sometimes yield better representations for vision-language-action alignment.
|
| 22 |
+
|
| 23 |
+
### How do you verify if the language model is successfully aligned with the action space?
|
| 24 |
+
|
| 25 |
+
We evaluate this end-to-end via downstream task success. We design evaluation tasks that are ambiguous without language instructions (e.g., "pick the pear" from a bowl of mixed fruit). If the robot succeeds, it confirms the model is correctly grounding language commands into physical actions.
|
| 26 |
+
|
| 27 |
+
## Data Strategy & Volume
|
| 28 |
+
|
| 29 |
+
### How much data is required for post-training on a new embodiment or task?
|
| 30 |
+
|
| 31 |
+
Data requirements depend heavily on task complexity and scene variation. Typical guidelines include:
|
| 32 |
+
|
| 33 |
+
- **Simple, fixed-location tasks (Pick & Place):** ~100 trajectories.
|
| 34 |
+
- **Complex scenes or multi-step tasks:** ~500+ trajectories.
|
| 35 |
+
- **High-DoF humanoid tasks:** ~2,000+ trajectories (e.g., shelf-picking with G1).
|
| 36 |
+
- **Fine manipulation:** ~100–500 episodes, ideally with human motion pre-training.
|
| 37 |
+
|
| 38 |
+
### What is the recommended strategy for improving success rates on hard tasks?
|
| 39 |
+
|
| 40 |
+
We recommend an iterative approach: start with ~100 teleoperated demonstrations, train a policy, and then use HG-DAgger (Human Gated Dataset Aggregation). Run the policy, intervene when it fails, and add the corrections from those trajectories to the dataset. This helps the model cover out-of-distribution states that pure behavior cloning (BC) might miss, and recover from partial failure states (e.g., a grip slipping or imprecise item placement).
|
| 41 |
+
|
| 42 |
+
### Does including real-robot data from other embodiments help if I only care about one robot?
|
| 43 |
+
|
| 44 |
+
Yes. Even if cross-embodiment generalization is not your goal, including diverse real-robot data adds visual diversity and robustness to the VLA's backbone, improving performance on your specific target robot.
|
| 45 |
+
|
| 46 |
+
### Does GR00T N1.7 support synthetic data generation via Cosmos?
|
| 47 |
+
|
| 48 |
+
While research models (like [DreamGen](https://research.nvidia.com/labs/gear/dreamgen/), a pipeline that generates synthetic robot trajectories from video world models) show promise, a robust, product-ready pipeline for generating synthetic training data via [NVIDIA Cosmos](https://www.nvidia.com/en-us/ai/cosmos/) world foundation models is currently in development and not yet part of the standard release.
|
| 49 |
+
|
| 50 |
+
## Model Capabilities
|
| 51 |
+
|
| 52 |
+
### Can the model handle lighting changes or different object colors?
|
| 53 |
+
|
| 54 |
+
VLMs can struggle with drastic appearance changes (e.g., hard shadows or significant hue shifts). While we haven't released specific lighting ablations, we strongly recommend using color jitter augmentation during training and collecting diverse data (20–50 episodes) under different lighting conditions to prevent overfitting.
|
| 55 |
+
|
| 56 |
+
### Can GR00T models perform reasoning or Visual Question Answering (VQA)?
|
| 57 |
+
|
| 58 |
+
The GR00T N1.x series is optimized specifically for action generation, not open-ended reasoning or VQA. Capabilities requiring complex semantic reasoning are targeted for future N2 (the next generation of GR00T, not yet released) releases.
|
| 59 |
+
|
| 60 |
+
### Can the model learn "retry" behaviors?
|
| 61 |
+
|
| 62 |
+
The current architecture is stateless and does not inherently "know" if a previous attempt failed. While some retry behavior may emerge from high-quality data, explicit recovery strategies are best achieved through DAgger (collecting data on recovery from failure) or Reinforcement Learning (RL), rather than pure Imitation Learning.
|
| 63 |
+
|
| 64 |
+
### Does the model distinguish between left and right arms in bimanual tasks?
|
| 65 |
+
|
| 66 |
+
Yes, provided the training data is distinct or annotated (e.g., instructions specifying "left arm" vs. "right arm"). If the dataset contains mixed, unannotated data where both arms perform identical tasks indiscriminately, the model may struggle to distinguish them.
|
| 67 |
+
|
| 68 |
+
### Is there a zero-shot cross-embodiment VLA model?
|
| 69 |
+
|
| 70 |
+
No. While cross-embodiment data improves generalization, a true "zero-shot" model (one that works perfectly on a new robot without *any* fine-tuning) does not currently exist in the open VLA landscape.
|
| 71 |
+
|
| 72 |
+
### Will differences in object shape between training and deployment cause the success rate to drop?
|
| 73 |
+
|
| 74 |
+
It depends on the degree of deviation. If the target object's shape differs drastically from the training data, performance will likely drop significantly. However, if the shape variation is minor and shares a similar grasping affordance (e.g., a slightly different bottle shape that is still grasped from the side), the model may still succeed, though with potentially lower reliability than on the original objects.
|
| 75 |
+
|
| 76 |
+
### Has the impact of large viewpoint changes (e.g., head movement) on task difficulty been studied?
|
| 77 |
+
|
| 78 |
+
Yes. Large viewpoint changes effectively change the observation distribution, which can complicate simple tasks. For example, a "simple" handover becomes complex if the robot's head moves significantly, altering the camera's perspective of its own hands.
|
| 79 |
+
|
| 80 |
+
- **Current Status:** Most public GR00T demos feature a relatively fixed head position to stabilize observations.
|
| 81 |
+
- **Mitigation:** To handle natural head movement, we recommend training with aggressive camera pose augmentation or collecting data that explicitly includes head motion to ensure the policy becomes robust to viewpoint shifts.
|
Isaac-GR00T/LICENSE
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Apache License
|
| 2 |
+
Version 2.0, January 2004
|
| 3 |
+
http://www.apache.org/licenses/
|
| 4 |
+
|
| 5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
| 6 |
+
|
| 7 |
+
1. Definitions.
|
| 8 |
+
|
| 9 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
| 10 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
| 11 |
+
|
| 12 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
| 13 |
+
the copyright owner that is granting the License.
|
| 14 |
+
|
| 15 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
| 16 |
+
other entities that control, are controlled by, or are under common
|
| 17 |
+
control with that entity. For the purposes of this definition,
|
| 18 |
+
"control" means (i) the power, direct or indirect, to cause the
|
| 19 |
+
direction or management of such entity, whether by contract or
|
| 20 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
| 21 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
| 22 |
+
|
| 23 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
| 24 |
+
exercising permissions granted by this License.
|
| 25 |
+
|
| 26 |
+
"Source" form shall mean the preferred form for making modifications,
|
| 27 |
+
including but not limited to software source code, documentation
|
| 28 |
+
source, and configuration files.
|
| 29 |
+
|
| 30 |
+
"Object" form shall mean any form resulting from mechanical
|
| 31 |
+
transformation or translation of a Source form, including but
|
| 32 |
+
not limited to compiled object code, generated documentation,
|
| 33 |
+
and conversions to other media types.
|
| 34 |
+
|
| 35 |
+
"Work" shall mean the work of authorship, whether in Source or
|
| 36 |
+
Object form, made available under the License, as indicated by a
|
| 37 |
+
copyright notice that is included in or attached to the work
|
| 38 |
+
(an example is provided in the Appendix below).
|
| 39 |
+
|
| 40 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
| 41 |
+
form, that is based on (or derived from) the Work and for which the
|
| 42 |
+
editorial revisions, annotations, elaborations, or other modifications
|
| 43 |
+
represent, as a whole, an original work of authorship. For the purposes
|
| 44 |
+
of this License, Derivative Works shall not include works that remain
|
| 45 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
| 46 |
+
the Work and Derivative Works thereof.
|
| 47 |
+
|
| 48 |
+
"Contribution" shall mean any work of authorship, including
|
| 49 |
+
the original version of the Work and any modifications or additions
|
| 50 |
+
to that Work or Derivative Works thereof, that is intentionally
|
| 51 |
+
submitted to the Licensor for inclusion in the Work by the copyright owner
|
| 52 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
| 53 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
| 54 |
+
means any form of electronic, verbal, or written communication sent
|
| 55 |
+
to the Licensor or its representatives, including but not limited to
|
| 56 |
+
communication on electronic mailing lists, source code control systems,
|
| 57 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
| 58 |
+
Licensor for the purpose of discussing and improving the Work, but
|
| 59 |
+
excluding communication that is conspicuously marked or otherwise
|
| 60 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
| 61 |
+
|
| 62 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
| 63 |
+
on behalf of whom a Contribution has been received by the Licensor and
|
| 64 |
+
subsequently incorporated within the Work.
|
| 65 |
+
|
| 66 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
| 67 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 68 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 69 |
+
copyright license to reproduce, prepare Derivative Works of,
|
| 70 |
+
publicly display, publicly perform, sublicense, and distribute the
|
| 71 |
+
Work and such Derivative Works in Source or Object form.
|
| 72 |
+
|
| 73 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
| 74 |
+
this License, each Contributor hereby grants to You a perpetual,
|
| 75 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
| 76 |
+
(except as stated in this section) patent license to make, have made,
|
| 77 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
| 78 |
+
where such license applies only to those patent claims licensable
|
| 79 |
+
by such Contributor that are necessarily infringed by their
|
| 80 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
| 81 |
+
with the Work to which such Contribution(s) was submitted. If You
|
| 82 |
+
institute patent litigation against any entity (including a
|
| 83 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
| 84 |
+
or a Contribution incorporated within the Work constitutes direct
|
| 85 |
+
or contributory patent infringement, then any patent licenses
|
| 86 |
+
granted to You under this License for that Work shall terminate
|
| 87 |
+
as of the date such litigation is filed.
|
| 88 |
+
|
| 89 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
| 90 |
+
Work or Derivative Works thereof in any medium, with or without
|
| 91 |
+
modifications, and in Source or Object form, provided that You
|
| 92 |
+
meet the following conditions:
|
| 93 |
+
|
| 94 |
+
(a) You must give any other recipients of the Work or
|
| 95 |
+
Derivative Works a copy of this License; and
|
| 96 |
+
|
| 97 |
+
(b) You must cause any modified files to carry prominent notices
|
| 98 |
+
stating that You changed the files; and
|
| 99 |
+
|
| 100 |
+
(c) You must retain, in the Source form of any Derivative Works
|
| 101 |
+
that You distribute, all copyright, patent, trademark, and
|
| 102 |
+
attribution notices from the Source form of the Work,
|
| 103 |
+
excluding those notices that do not pertain to any part of
|
| 104 |
+
the Derivative Works; and
|
| 105 |
+
|
| 106 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
| 107 |
+
distribution, then any Derivative Works that You distribute must
|
| 108 |
+
include a readable copy of the attribution notices contained
|
| 109 |
+
within such NOTICE file, excluding any notices that do not
|
| 110 |
+
pertain to any part of the Derivative Works, in at least one
|
| 111 |
+
of the following places: within a NOTICE text file distributed
|
| 112 |
+
as part of the Derivative Works; within the Source form or
|
| 113 |
+
documentation, if provided along with the Derivative Works; or,
|
| 114 |
+
within a display generated by the Derivative Works, if and
|
| 115 |
+
wherever such third-party notices normally appear. The contents
|
| 116 |
+
of the NOTICE file are for informational purposes only and
|
| 117 |
+
do not modify the License. You may add Your own attribution
|
| 118 |
+
notices within Derivative Works that You distribute, alongside
|
| 119 |
+
or as an addendum to the NOTICE text from the Work, provided
|
| 120 |
+
that such additional attribution notices cannot be construed
|
| 121 |
+
as modifying the License.
|
| 122 |
+
|
| 123 |
+
You may add Your own copyright statement to Your modifications and
|
| 124 |
+
may provide additional or different license terms and conditions
|
| 125 |
+
for use, reproduction, or distribution of Your modifications, or
|
| 126 |
+
for any such Derivative Works as a whole, provided Your use,
|
| 127 |
+
reproduction, and distribution of the Work otherwise complies with
|
| 128 |
+
the conditions stated in this License.
|
| 129 |
+
|
| 130 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
| 131 |
+
any Contribution intentionally submitted for inclusion in the Work
|
| 132 |
+
by You to the Licensor shall be under the terms and conditions of
|
| 133 |
+
this License, without any additional terms or conditions.
|
| 134 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
| 135 |
+
the terms of any separate license agreement you may have executed
|
| 136 |
+
with Licensor regarding such Contributions.
|
| 137 |
+
|
| 138 |
+
6. Trademarks. This License does not grant permission to use the trade
|
| 139 |
+
names, trademarks, service marks, or product names of the Licensor,
|
| 140 |
+
except as required for reasonable and customary use in describing the
|
| 141 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
| 142 |
+
|
| 143 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
| 144 |
+
agreed to in writing, Licensor provides the Work (and each
|
| 145 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
| 146 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
| 147 |
+
implied, including, without limitation, any warranties or conditions
|
| 148 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
| 149 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
| 150 |
+
appropriateness of using or redistributing the Work and assume any
|
| 151 |
+
risks associated with Your exercise of permissions under this License.
|
| 152 |
+
|
| 153 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
| 154 |
+
whether in tort (including negligence), contract, or otherwise,
|
| 155 |
+
unless required by applicable law (such as deliberate and grossly
|
| 156 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
| 157 |
+
liable to You for damages, including any direct, indirect, special,
|
| 158 |
+
incidental, or consequential damages of any character arising as a
|
| 159 |
+
result of this License or out of the use or inability to use the
|
| 160 |
+
Work (including but not limited to damages for loss of goodwill,
|
| 161 |
+
work stoppage, computer failure or malfunction, or any and all
|
| 162 |
+
other commercial damages or losses), even if such Contributor
|
| 163 |
+
has been advised of the possibility of such damages.
|
| 164 |
+
|
| 165 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
| 166 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
| 167 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
| 168 |
+
or other liability obligations and/or rights consistent with this
|
| 169 |
+
License. However, in accepting such obligations, You may act only
|
| 170 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
| 171 |
+
of any other Contributor, and only if You agree to indemnify,
|
| 172 |
+
defend, and hold each Contributor harmless for any liability
|
| 173 |
+
incurred by, or claims asserted against, such Contributor by reason
|
| 174 |
+
of your accepting any such warranty or additional liability.
|
| 175 |
+
|
| 176 |
+
END OF TERMS AND CONDITIONS
|
| 177 |
+
|
| 178 |
+
Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
| 179 |
+
|
| 180 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
| 181 |
+
you may not use this file except in compliance with the License.
|
| 182 |
+
You may obtain a copy of the License at
|
| 183 |
+
|
| 184 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
| 185 |
+
|
| 186 |
+
Unless required by applicable law or agreed to in writing, software
|
| 187 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
| 188 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 189 |
+
See the License for the specific language governing permissions and
|
| 190 |
+
limitations under the License.
|
Isaac-GR00T/README.md
ADDED
|
@@ -0,0 +1,641 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<div align="center">
|
| 2 |
+
|
| 3 |
+
<img src="media/header_compress.png" width="800" alt="NVIDIA Isaac GR00T N1.7 Header">
|
| 4 |
+
|
| 5 |
+
<!-- --- -->
|
| 6 |
+
|
| 7 |
+
<p style="font-size: 1.2em;">
|
| 8 |
+
<a href="https://developer.nvidia.com/isaac/gr00t"><strong>Website</strong></a> |
|
| 9 |
+
<a href="https://huggingface.co/collections/nvidia/gr00t-n17"><strong>Model</strong></a> |
|
| 10 |
+
<a href="https://huggingface.co/collections/nvidia/physical-ai"><strong>Datasets (Physical AI)</strong></a> |
|
| 11 |
+
<a href="https://arxiv.org/abs/2503.14734"><strong>Paper</strong></a> |
|
| 12 |
+
<a href="https://developer.nvidia.com/isaac"><strong>NVIDIA Isaac</strong></a> |
|
| 13 |
+
<a href="FAQ.md"><strong>FAQ</strong></a>
|
| 14 |
+
</p>
|
| 15 |
+
</div>
|
| 16 |
+
|
| 17 |
+
## Table of Contents
|
| 18 |
+
|
| 19 |
+
- [NVIDIA Isaac GR00T](#nvidia-isaac-gr00t)
|
| 20 |
+
- [What's New in GR00T N1.7](#whats-new-in-gr00t-n17)
|
| 21 |
+
- [Installation](#installation)
|
| 22 |
+
- [LeRobot Integration](#lerobot-integration)
|
| 23 |
+
- [Model Checkpoints & Embodiment Tags](#model-checkpoints--embodiment-tags)
|
| 24 |
+
- [Data Format](#data-format)
|
| 25 |
+
- [Inference](#inference)
|
| 26 |
+
- [Fine-tuning](#fine-tuning)
|
| 27 |
+
- [Evaluation](#evaluation)
|
| 28 |
+
- [Contributions](#contributions)
|
| 29 |
+
- [License](#license)
|
| 30 |
+
- [Citation](#citation)
|
| 31 |
+
|
| 32 |
+
---
|
| 33 |
+
|
| 34 |
+
## NVIDIA Isaac GR00T
|
| 35 |
+
|
| 36 |
+
<table style="width:100%; table-layout:fixed;">
|
| 37 |
+
<tr>
|
| 38 |
+
<td style="width:33.33%; text-align:center;">
|
| 39 |
+
<img src="media/unitree_g1.gif" style="max-width:100%; height:auto;">
|
| 40 |
+
</td>
|
| 41 |
+
<td style="width:33.33%; text-align:center;">
|
| 42 |
+
<img src="media/agibot_g1.gif" style="max-width:100%; height:auto;">
|
| 43 |
+
</td>
|
| 44 |
+
<td style="width:33.33%; text-align:center;">
|
| 45 |
+
<img src="media/yam.gif" style="max-width:100%; height:auto;">
|
| 46 |
+
</td>
|
| 47 |
+
</tr>
|
| 48 |
+
</table>
|
| 49 |
+
|
| 50 |
+
> We just released GR00T N1.7 General Availability, the latest version of GR00T N1 with a new VLM backbone (Cosmos-Reason2-2B / Qwen3-VL) and improved performance.
|
| 51 |
+
|
| 52 |
+
> **This is a General Availability (GA) release.** You are welcome to download the model, explore the codebase, and build on the stack, with full support and stability guarantees.
|
| 53 |
+
>
|
| 54 |
+
> **What's available:**
|
| 55 |
+
> - Pre-trained GR00T N1.7 model weights and reference code
|
| 56 |
+
> - Fine-tuning and inference with custom robot data or demonstrations
|
| 57 |
+
> - Experimentation, prototyping, and research use cases
|
| 58 |
+
> - Production deployment with commercial support
|
| 59 |
+
> - Complete benchmarks and a fully validated, stable feature set
|
| 60 |
+
> - Pull request contributions
|
| 61 |
+
>
|
| 62 |
+
> We welcome feedback - please feel free to raise issues and pull requests in this repository.
|
| 63 |
+
|
| 64 |
+
> Previous releases: [N1.6](https://github.com/NVIDIA/Isaac-GR00T/tree/n1d6) | [N1.5](https://github.com/NVIDIA/Isaac-GR00T/tree/n1d5)
|
| 65 |
+
|
| 66 |
+
NVIDIA Isaac GR00T N1.7 is an open vision-language-action (VLA) model for generalized humanoid robot skills. This cross-embodiment model takes multimodal input, including language and images, to perform manipulation tasks in diverse environments.
|
| 67 |
+
|
| 68 |
+
GR00T N1.7 is trained on a diverse mixture of robot data including bimanual, semi-humanoid and an expansive humanoid dataset. It is adaptable through post-training for specific embodiments, tasks and environments.
|
| 69 |
+
|
| 70 |
+
GR00T N1.7 is fully commercially licensable under Apache 2.0. It delivers comparable performance to N1.6, with improved generalization and language-following capabilities driven by the inclusion of 20K hours of EgoScale human video data in pretraining.
|
| 71 |
+
|
| 72 |
+
The neural network architecture of GR00T N1.7 is a combination of vision-language foundation model and diffusion transformer head that denoises continuous actions. Here is a schematic diagram of the architecture:
|
| 73 |
+
|
| 74 |
+
<div align="center">
|
| 75 |
+
<img src="media/model-architecture.png" width="800" alt="model-architecture">
|
| 76 |
+
</div>
|
| 77 |
+
|
| 78 |
+
### Workflow Overview
|
| 79 |
+
|
| 80 |
+
1. **Prepare data** — Collect robot demonstrations (video, state, action) and convert them to the [GR00T LeRobot format](#data-format). Demo datasets are included for quick testing.
|
| 81 |
+
2. **Run inference** — Try zero-shot inference with the base model on [pretrain embodiments](#embodiment-tags), or use a [finetuned checkpoint](#checkpoints) for benchmark tasks.
|
| 82 |
+
3. **Fine-tune** — Adapt the model to your robot using [`launch_finetune.py`](#fine-tuning) with your own data and modality config.
|
| 83 |
+
4. **Evaluate** — Validate with [open-loop evaluation](#open-loop-evaluation), then test in [simulation benchmarks](#benchmark-examples) or on real hardware via the [Policy API](getting_started/policy.md).
|
| 84 |
+
5. **Deploy** — Connect `Gr00tPolicy` to your robot controller, optionally accelerated with [TensorRT](scripts/deployment/README.md).
|
| 85 |
+
|
| 86 |
+
## What's New in GR00T N1.7
|
| 87 |
+
|
| 88 |
+
GR00T N1.7 builds on N1.6 with a new VLM backbone and code-level improvements.
|
| 89 |
+
|
| 90 |
+
1. **Relative EEF Action Space** — N1.7 adopts a relative end-effector action space shared across robot and human embodiments. Representing actions as deltas from the current pose (rather than absolute targets) improves generalization and is a key factor in the model's cross-embodiment performance. See [`getting_started/finetune_new_embodiment.md`](getting_started/finetune_new_embodiment.md) for guidance on configuring relative EEF for your own robot.
|
| 91 |
+
|
| 92 |
+
2. **Human Video Pretraining** — N1.7 is pretrained on 20K hours of EgoScale human video data alongside diverse robot demonstrations. Because the relative EEF action representation is consistent across both human and robot data, the model can transfer manipulation priors learned from human video directly to robot control.
|
| 93 |
+
|
| 94 |
+
### Key Changes from N1.6
|
| 95 |
+
|
| 96 |
+
Compared with N1.6, N1.7 updates the model stack, training data interface,
|
| 97 |
+
evaluation coverage, deployment flow, fine-tuning workflow, and runtime behavior.
|
| 98 |
+
|
| 99 |
+
- **New VLM backbone:** Cosmos-Reason2-2B (Qwen3-VL architecture), replacing the Eagle backbone used in N1.6. Supports flexible resolution and encodes images in their native aspect ratio without padding.
|
| 100 |
+
- **Updated model interface:** N1.7 moves to the `gr00t_n1d7` model package, expands the state/action dimensions, and increases the model action horizon.
|
| 101 |
+
- **More flexible dataset handling:** Fine-tuning can use multiple dataset paths with mixture weighting, making multi-dataset training easier to configure.
|
| 102 |
+
- **Broader benchmark coverage:** N1.7 refreshes and expands documented results across RoboCasa, RoboCasa GR1 tabletop tasks, SimplerEnv, and real G1 evaluation.
|
| 103 |
+
- **More complete deployment path:** N1.7 adds full-pipeline ONNX and TensorRT export support and improves deployment consistency across desktop GPUs and edge platforms.
|
| 104 |
+
- **More predictable runtime behavior:** Policy serving, rollout recording, evaluation, and configuration validation have been hardened so errors are easier to diagnose.
|
| 105 |
+
|
| 106 |
+
<details>
|
| 107 |
+
<summary>Detailed changes from N1.6</summary>
|
| 108 |
+
|
| 109 |
+
These are the main code, model, training, evaluation, and deployment changes
|
| 110 |
+
that distinguish the current N1.7 main branch from the N1.6 / 1D6 code path.
|
| 111 |
+
Use the [`n1d6` branch](https://github.com/NVIDIA/Isaac-GR00T/tree/n1d6) when you need
|
| 112 |
+
the N1.6 model package and runtime behavior.
|
| 113 |
+
|
| 114 |
+
- Model package changed from `gr00t_n1d6` to `gr00t_n1d7`, so codepaths and processor metadata move to the N1.7 namespace.
|
| 115 |
+
- VLM backbone changed from vendored Eagle, `nvidia/Eagle-Block2A-2B-v2`, to `nvidia/Cosmos-Reason2-2B` via Qwen3-VL.
|
| 116 |
+
- Transformers changed from `4.51.3` to `4.57.3` to support the newer Qwen3-VL stack.
|
| 117 |
+
- Model defaults changed: `select_layer` `16` to `12`, `tune_top_llm_layers` `4` to `0`, and `load_bf16` `true` to `false`.
|
| 118 |
+
- State and action dimensions expanded from `29` to `132`, and `action_horizon` expanded from `16` to `40`.
|
| 119 |
+
- Action head remains flow-matching DiT, but changes from `32` to `16` diffusion layers and adds newer N1.7 behavior options.
|
| 120 |
+
- Dataset input handling now supports multiple dataset paths and `ds_weights_alpha` for dataset mixtures.
|
| 121 |
+
- The rollout CLI flag was renamed from `--action-horizon` to `--execution-horizon` to clarify how many predicted actions are executed per policy call.
|
| 122 |
+
- Server/client transport has stronger object-dtype ndarray serialization and cleaner socket timeout behavior.
|
| 123 |
+
|
| 124 |
+
</details>
|
| 125 |
+
|
| 126 |
+
---
|
| 127 |
+
|
| 128 |
+
## Installation
|
| 129 |
+
|
| 130 |
+
### Hardware Requirements
|
| 131 |
+
|
| 132 |
+
**Inference:** 1 GPU with 16 GB+ VRAM (e.g., RTX 4090, L40, H100, Jetson AGX Thor/Orin, DGX Spark).
|
| 133 |
+
|
| 134 |
+
**Fine-tuning:** 1 or more GPUs with 40 GB+ VRAM recommended. We recommend H100 or L40 nodes for optimal performance. Other hardware (e.g., A6000) works but may require longer training time. See the [Hardware Recommendation Guide](getting_started/hardware_recommendation.md) for detailed specs.
|
| 135 |
+
|
| 136 |
+
**CUDA / Python per platform:** dGPU on CUDA 12.8 with Python 3.12; Jetson Orin on CUDA 12.6 with Python 3.10; Jetson Thor and DGX Spark on CUDA 13.0 with Python 3.12. The per-platform install scripts and Dockerfiles live under `scripts/deployment/`; see the [Deployment & Inference Guide](scripts/deployment/README.md) for the full matrix.
|
| 137 |
+
|
| 138 |
+
### Clone the Repository
|
| 139 |
+
|
| 140 |
+
GR00T relies on submodules for certain dependencies. Include them when cloning:
|
| 141 |
+
|
| 142 |
+
**Note:** `git-lfs` is **required** to download parquet data files in `demo_data/`. Install it before cloning: `sudo apt install git-lfs && git lfs install`.
|
| 143 |
+
```sh
|
| 144 |
+
git clone --recurse-submodules https://github.com/NVIDIA/Isaac-GR00T
|
| 145 |
+
cd Isaac-GR00T
|
| 146 |
+
```
|
| 147 |
+
|
| 148 |
+
If you've already cloned without submodules, initialize them separately:
|
| 149 |
+
|
| 150 |
+
```sh
|
| 151 |
+
git submodule update --init --recursive
|
| 152 |
+
```
|
| 153 |
+
|
| 154 |
+
### Set Up the Environment
|
| 155 |
+
|
| 156 |
+
GR00T uses [uv](https://github.com/astral-sh/uv) for fast, reproducible dependency management. Install uv first:
|
| 157 |
+
|
| 158 |
+
```sh
|
| 159 |
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
#### dGPU (x86_64) — Default
|
| 163 |
+
|
| 164 |
+
Install FFmpeg (required by `torchcodec`, the only supported video backend):
|
| 165 |
+
```sh
|
| 166 |
+
sudo apt-get update && sudo apt-get install -y ffmpeg
|
| 167 |
+
```
|
| 168 |
+
> **FFmpeg version:** `torchcodec==0.8.0` supports **FFmpeg 4-7 only**. On Ubuntu 25.10+/26.04 the `ffmpeg` package is version 8, which `torchcodec` cannot load (`RuntimeError: Could not load libtorchcodec ... We support versions 4, 5, 6 and 7`). On those distros install an FFmpeg<8 runtime instead, e.g. `conda install -c conda-forge 'ffmpeg<8'`, and make sure its libraries are on `LD_LIBRARY_PATH`.
|
| 169 |
+
|
| 170 |
+
Create the environment and install GR00T:
|
| 171 |
+
```sh
|
| 172 |
+
uv sync --python 3.12
|
| 173 |
+
```
|
| 174 |
+
GPU dependencies (flash-attn, TensorRT, etc.) are included in the default install.
|
| 175 |
+
|
| 176 |
+
Verify the installation:
|
| 177 |
+
```sh
|
| 178 |
+
uv run python -c "import gr00t; print('GR00T installed successfully')"
|
| 179 |
+
```
|
| 180 |
+
|
| 181 |
+
> **Hugging Face access (required):** GR00T's VLM backbone is [`nvidia/Cosmos-Reason2-2B`](https://huggingface.co/nvidia/Cosmos-Reason2-2B), a **gated** model that every GR00T checkpoint (including the base `nvidia/GR00T-N1.7-3B`) loads on first use. Before running inference or finetuning, request access on the model page and authenticate:
|
| 182 |
+
> ```sh
|
| 183 |
+
> uv run huggingface-cli login # or: export HF_TOKEN=<your_token>
|
| 184 |
+
> ```
|
| 185 |
+
> Without access, model loading fails with a `GatedRepoError` / `401 Client Error`.
|
| 186 |
+
|
| 187 |
+
> **`flash-attn` message on every `uv run`:** You may see `Installing flash-attn...` each time you run `uv run`. This is a known `uv` behavior with URL-pinned wheel sources — `uv` re-validates the cached wheel against the source URL on each invocation. It is **not** rebuilding from source; the wheel is already cached locally and the operation takes 2-3 seconds. This affects platforms that use URL-pinned flash-attn wheels (x86_64 and aarch64).
|
| 188 |
+
> To suppress it, remove the `flash-attn` entries under `[tool.uv.sources]` in your local `pyproject.toml` after the initial install. But that will break `uv lock` and cause flash-attn to build from source on next lock regeneration.
|
| 189 |
+
|
| 190 |
+
<details>
|
| 191 |
+
<summary><strong>Alternative: pip install (without uv)</strong></summary>
|
| 192 |
+
|
| 193 |
+
If you prefer pip/conda over uv, create a Python 3.12 virtualenv and install:
|
| 194 |
+
```sh
|
| 195 |
+
python3.12 -m venv .venv && source .venv/bin/activate
|
| 196 |
+
pip install -e .
|
| 197 |
+
```
|
| 198 |
+
Note: GPU dependencies (flash-attn, TensorRT) may require manual installation with pip. The `uv` workflow handles these automatically.
|
| 199 |
+
</details>
|
| 200 |
+
|
| 201 |
+
> **If fine-tuning fails with `CUDA_HOME is unset`:** Run `bash scripts/deployment/dgpu/install_deps.sh` once to configure CUDA paths, or manually `export CUDA_HOME=/usr/local/cuda`.
|
| 202 |
+
|
| 203 |
+
> **CUDA 13.x Users (Thor, Spark, and other CUDA 13+ platforms):** PyTorch 2.7 pins Triton to 3.3.1, which does not recognize CUDA major version 13+. This causes a `RuntimeError` in Triton's `ptx_get_version()`. Run `scripts/patch_triton_cuda13.sh` to fix:
|
| 204 |
+
> ```sh
|
| 205 |
+
> uv run bash scripts/patch_triton_cuda13.sh
|
| 206 |
+
> ```
|
| 207 |
+
|
| 208 |
+
> **GB300 (sm_103) Users:** Triton 3.3.1 (pinned by PyTorch 2.7) does not support the GB300 GPU architecture (sm_103). `torch.compile` will fail on GB300. Use PyTorch eager mode or TensorRT inference instead. Triton 3.5.1+ adds sm_103 support but is not yet compatible with the pinned PyTorch version.
|
| 209 |
+
|
| 210 |
+
> **Video Backend:** GR00T uses [`torchcodec`](https://github.com/pytorch/torchcodec) as its sole video decoding backend. Backends such as `decord` and `pyav` are no longer supported. `torchcodec` 0.8.0 requires **FFmpeg 4-7** (FFmpeg 8 is not supported — see the FFmpeg version note above) and supports H.264 on all platforms; AV1 decoding is not guaranteed (convert AV1 datasets to H.264 with `examples/SimplerEnv/convert_av1_to_h264.py`). On aarch64 platforms (Thor, Orin), `torchcodec` is built from source during `install_deps.sh` because pre-built wheels are not available — if you encounter a `NotImplementedError`, ensure the build completed successfully.
|
| 211 |
+
|
| 212 |
+
<details>
|
| 213 |
+
<summary><strong>DGX Spark</strong> (tested with DGX Spark GB10)</summary>
|
| 214 |
+
|
| 215 |
+
```bash
|
| 216 |
+
bash scripts/deployment/spark/install_deps.sh
|
| 217 |
+
source .venv/bin/activate
|
| 218 |
+
source scripts/activate_spark.sh
|
| 219 |
+
```
|
| 220 |
+
|
| 221 |
+
See the [Spark setup guide](scripts/deployment/README.md#dgx-spark-setup) for Docker and bare metal details.
|
| 222 |
+
</details>
|
| 223 |
+
|
| 224 |
+
<details>
|
| 225 |
+
<summary><strong>Jetson AGX Thor</strong> (tested with JetPack 7.1)</summary>
|
| 226 |
+
|
| 227 |
+
> **flash-attn on older systems (e.g., Ubuntu 20.04 with glibc < 2.35):** The pre-built `flash-attn` wheel may fail with `ImportError: glibc_compat.so: cannot open shared object file`. To fix this, build from source:
|
| 228 |
+
> ```sh
|
| 229 |
+
> uv pip install flash-attn==2.7.4.post1 --no-binary flash-attn --no-cache
|
| 230 |
+
> ```
|
| 231 |
+
> This compiles locally (~10-30 minutes) and avoids the glibc compatibility issue.
|
| 232 |
+
|
| 233 |
+
```bash
|
| 234 |
+
bash scripts/deployment/thor/install_deps.sh
|
| 235 |
+
source .venv/bin/activate
|
| 236 |
+
source scripts/activate_thor.sh
|
| 237 |
+
```
|
| 238 |
+
|
| 239 |
+
See the [Thor setup guide](scripts/deployment/README.md#jetson-thor-setup) for Docker and bare metal details.
|
| 240 |
+
</details>
|
| 241 |
+
|
| 242 |
+
<details>
|
| 243 |
+
<summary><strong>Jetson Orin</strong> (tested with JetPack 6.2)</summary>
|
| 244 |
+
|
| 245 |
+
```bash
|
| 246 |
+
bash scripts/deployment/orin/install_deps.sh
|
| 247 |
+
source .venv/bin/activate
|
| 248 |
+
source scripts/activate_orin.sh
|
| 249 |
+
```
|
| 250 |
+
|
| 251 |
+
See the [Orin setup guide](scripts/deployment/README.md#jetson-orin-setup) for Docker and bare metal details.
|
| 252 |
+
</details>
|
| 253 |
+
|
| 254 |
+
> ⚠️ **aarch64 users (Spark / Thor / Orin):** After running `install_deps.sh`, always
|
| 255 |
+
> activate the venv with `source .venv/bin/activate && source scripts/activate_<platform>.sh`
|
| 256 |
+
> (`activate_spark.sh`, `activate_thor.sh`, or `activate_orin.sh`) and run the example
|
| 257 |
+
> commands in this guide with **plain `python`** / `torchrun`, not `uv run python` /
|
| 258 |
+
> `uv run torchrun`. The latter will re-sync against the root `pyproject.toml` (which targets
|
| 259 |
+
> x86_64 Python 3.12) and destroy the platform-specific environment. See the
|
| 260 |
+
> [Deployment & Inference Guide](scripts/deployment/README.md#platform-specific-setup) for
|
| 261 |
+
> per-platform Docker and bare-metal setup.
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
For a containerized setup that avoids system-level dependency conflicts, see our [Docker Setup Guide](docker/README.md). The recommended container workflow is to start the image first, then clone or pull the repo inside the running container so your checkout uses the image's prebuilt dependency environment.
|
| 265 |
+
|
| 266 |
+
---
|
| 267 |
+
|
| 268 |
+
## LeRobot Integration
|
| 269 |
+
|
| 270 |
+
GR00T N1.7 is also available through Hugging Face LeRobot via the `groot` policy type. Use the [LeRobot GR00T documentation](https://github.com/huggingface/lerobot/blob/main/docs/source/groot.mdx) for LeRobot-native training, evaluation, and rollout workflows. Use this repository for the reference GR00T implementation, model internals, deployment tooling, and benchmark-specific examples.
|
| 271 |
+
|
| 272 |
+
---
|
| 273 |
+
|
| 274 |
+
## Model Checkpoints & Embodiment Tags
|
| 275 |
+
|
| 276 |
+
### Checkpoints
|
| 277 |
+
|
| 278 |
+
| Checkpoint | Type | Embodiment Tag | Description |
|
| 279 |
+
|------------|------|---------------|-------------|
|
| 280 |
+
| [`nvidia/GR00T-N1.7-3B`](https://huggingface.co/nvidia/GR00T-N1.7-3B) | Base | See [pretrain tags](getting_started/policy.md#--embodiment-tag) | Base model (3B params) — zero-shot inference on pretrain embodiments, or finetune for new tasks |
|
| 281 |
+
| [`nvidia/GR00T-N1.7-LIBERO`](https://huggingface.co/nvidia/GR00T-N1.7-LIBERO) | Finetuned | `LIBERO_PANDA` | Finetuned on [LIBERO](https://libero-project.github.io/) benchmark (Franka Panda) |
|
| 282 |
+
| [`nvidia/GR00T-N1.7-DROID`](https://huggingface.co/nvidia/GR00T-N1.7-DROID) | Finetuned | `OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT` | Finetuned on [DROID](https://droid-dataset.github.io/) dataset |
|
| 283 |
+
| [`nvidia/GR00T-N1.7-SimplerEnv-Bridge`](https://huggingface.co/nvidia/GR00T-N1.7-SimplerEnv-Bridge) | Finetuned | `SIMPLER_ENV_WIDOWX` | Finetuned on SimplerEnv Bridge (WidowX) |
|
| 284 |
+
| [`nvidia/GR00T-N1.7-SimplerEnv-Fractal`](https://huggingface.co/nvidia/GR00T-N1.7-SimplerEnv-Fractal) | Finetuned | `SIMPLER_ENV_GOOGLE` | Finetuned on SimplerEnv Fractal (Google Robot) |
|
| 285 |
+
|
| 286 |
+
### Embodiment Tags
|
| 287 |
+
|
| 288 |
+
Every inference or finetuning command requires an `--embodiment-tag`. The tag determines which modality config (state/action keys, normalization) the model uses. Tags are **case-insensitive**.
|
| 289 |
+
|
| 290 |
+
For the full list of pretrain and posttrain tags, see the [Policy API Guide — Embodiment Tags](getting_started/policy.md#--embodiment-tag).
|
| 291 |
+
|
| 292 |
+
---
|
| 293 |
+
|
| 294 |
+
## Data Format
|
| 295 |
+
|
| 296 |
+
GR00T uses a flavor of the [LeRobot v2 dataset format](https://github.com/huggingface/lerobot) with an additional `meta/modality.json` file that describes state/action/video structure. A dataset looks like:
|
| 297 |
+
|
| 298 |
+
```
|
| 299 |
+
my_dataset/
|
| 300 |
+
meta/
|
| 301 |
+
info.json # dataset metadata
|
| 302 |
+
episodes.jsonl # episode index and lengths
|
| 303 |
+
tasks.jsonl # language task descriptions
|
| 304 |
+
modality.json # state/action/video key mapping (GR00T-specific)
|
| 305 |
+
data/chunk-000/ # parquet files (state, action per timestep)
|
| 306 |
+
videos/chunk-000/ # mp4 video files per episode
|
| 307 |
+
```
|
| 308 |
+
|
| 309 |
+
The `modality.json` maps how the concatenated state/action arrays split into named fields (e.g., `x`, `y`, `z`, `gripper`) and which video keys are available. This is what the embodiment tag uses to interpret the data.
|
| 310 |
+
|
| 311 |
+
**Included demo datasets** (ready to use, no download needed):
|
| 312 |
+
|
| 313 |
+
| Dataset | Robot | Embodiment Tag | Use Case |
|
| 314 |
+
|---------|-------|---------------|----------|
|
| 315 |
+
| `demo_data/droid_sample` | DROID (3 episodes) | `OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT` | Zero-shot or finetuned inference (DROID) |
|
| 316 |
+
| `demo_data/libero_demo` | LIBERO Panda (5 episodes) | `LIBERO_PANDA` | Inference with finetuned checkpoint |
|
| 317 |
+
| `demo_data/simplerenv_bridge_sample` | WidowX (SimplerEnv Bridge) | `SIMPLER_ENV_WIDOWX` | Inference with finetuned SimplerEnv Bridge checkpoint |
|
| 318 |
+
| `demo_data/simplerenv_fractal_sample` | Google Robot (SimplerEnv Fractal) | `SIMPLER_ENV_GOOGLE` | Inference with finetuned SimplerEnv Fractal checkpoint |
|
| 319 |
+
| `demo_data/cube_to_bowl_5` | SO100 arm (5 episodes) | `NEW_EMBODIMENT` | Fine-tuning custom embodiment example |
|
| 320 |
+
| `demo_data/cube_to_bowl_5_with_mask` | SO100 arm + per-frame masks | `NEW_EMBODIMENT` | [Mask-guided background suppression](examples/mask-guided-background-suppression/README.md) example |
|
| 321 |
+
|
| 322 |
+
> To generate more DROID episodes: `python scripts/download_droid_sample.py --num-episodes 10`
|
| 323 |
+
|
| 324 |
+
**Using your own data:** Convert your demonstrations to the format above. If coming from LeRobot v3, use the conversion helper in its own environment:
|
| 325 |
+
```bash
|
| 326 |
+
cd scripts/lerobot_conversion
|
| 327 |
+
uv venv
|
| 328 |
+
source .venv/bin/activate
|
| 329 |
+
uv pip install -e . --verbose
|
| 330 |
+
python convert_v3_to_v2.py --repo-id <DATASET_REPO_ID>
|
| 331 |
+
```
|
| 332 |
+
See the full [Data Preparation Guide](getting_started/data_preparation.md) for schema details and examples.
|
| 333 |
+
|
| 334 |
+
---
|
| 335 |
+
|
| 336 |
+
## Inference
|
| 337 |
+
|
| 338 |
+
> **Prefer an interactive walkthrough?** The [`getting_started/GR00T_inference.ipynb`](getting_started/GR00T_inference.ipynb) notebook steps through loading the model and predicting actions from observations on a sample dataset.
|
| 339 |
+
|
| 340 |
+
### Zero-Shot Inference (Base Model)
|
| 341 |
+
|
| 342 |
+
The included `demo_data/droid_sample` dataset works with the base model out of the box — no finetuning or checkpoint download needed:
|
| 343 |
+
|
| 344 |
+
```bash
|
| 345 |
+
uv run python scripts/deployment/standalone_inference_script.py \
|
| 346 |
+
--model-path nvidia/GR00T-N1.7-3B \
|
| 347 |
+
--dataset-path demo_data/droid_sample \
|
| 348 |
+
--embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \
|
| 349 |
+
--traj-ids 1 2 \
|
| 350 |
+
--inference-mode pytorch \
|
| 351 |
+
--execution-horizon 8
|
| 352 |
+
```
|
| 353 |
+
|
| 354 |
+
This runs open-loop inference on 2 DROID episodes, comparing predicted actions against ground truth. The base model downloads automatically from HuggingFace on first run (~6 GB).
|
| 355 |
+
|
| 356 |
+
> **Note:** The base model loads the gated `nvidia/Cosmos-Reason2-2B` backbone, so this command requires Hugging Face access (see [Set Up the Environment](#set-up-the-environment)). Without it the run fails with a `GatedRepoError`.
|
| 357 |
+
|
| 358 |
+
### Finetuned Inference
|
| 359 |
+
|
| 360 |
+
For posttrain embodiments, use a finetuned checkpoint. Most finetuned checkpoints (e.g., DROID, SimplerEnv) have a flat file structure and can be passed directly as a HuggingFace model ID — no manual download needed:
|
| 361 |
+
|
| 362 |
+
```bash
|
| 363 |
+
uv run python scripts/deployment/standalone_inference_script.py \
|
| 364 |
+
--model-path nvidia/GR00T-N1.7-DROID \
|
| 365 |
+
--dataset-path demo_data/droid_sample \
|
| 366 |
+
--embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \
|
| 367 |
+
--traj-ids 1 2 \
|
| 368 |
+
--inference-mode pytorch \
|
| 369 |
+
--execution-horizon 8
|
| 370 |
+
```
|
| 371 |
+
|
| 372 |
+
Some checkpoints (e.g., LIBERO) use a nested folder structure with model files under a subfolder. HuggingFace does not support nested repo paths in `--model-path`, so you must download first:
|
| 373 |
+
|
| 374 |
+
```bash
|
| 375 |
+
uv run hf download nvidia/GR00T-N1.7-LIBERO \
|
| 376 |
+
--include "libero_10/config.json" "libero_10/embodiment_id.json" \
|
| 377 |
+
"libero_10/model-*.safetensors" "libero_10/model.safetensors.index.json" \
|
| 378 |
+
"libero_10/processor_config.json" "libero_10/statistics.json" \
|
| 379 |
+
--local-dir checkpoints/GR00T-N1.7-LIBERO
|
| 380 |
+
```
|
| 381 |
+
|
| 382 |
+
```bash
|
| 383 |
+
uv run python scripts/deployment/standalone_inference_script.py \
|
| 384 |
+
--model-path checkpoints/GR00T-N1.7-LIBERO/libero_10 \
|
| 385 |
+
--dataset-path demo_data/libero_demo \
|
| 386 |
+
--embodiment-tag LIBERO_PANDA \
|
| 387 |
+
--traj-ids 0 1 2 \
|
| 388 |
+
--inference-mode pytorch \
|
| 389 |
+
--execution-horizon 8
|
| 390 |
+
```
|
| 391 |
+
|
| 392 |
+
### Server-Client Inference (for Deployment)
|
| 393 |
+
|
| 394 |
+
For real-world deployment or simulation evaluation, use the server-client architecture. The policy runs on a GPU server; a lightweight client sends observations and receives actions over ZMQ.
|
| 395 |
+
|
| 396 |
+
**Terminal 1 — Start the policy server:**
|
| 397 |
+
```bash
|
| 398 |
+
uv run python gr00t/eval/run_gr00t_server.py \
|
| 399 |
+
--model-path nvidia/GR00T-N1.7-3B \
|
| 400 |
+
--embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \
|
| 401 |
+
--device cuda:0
|
| 402 |
+
```
|
| 403 |
+
|
| 404 |
+
**Terminal 2 — Run open-loop evaluation as a client:**
|
| 405 |
+
```bash
|
| 406 |
+
uv run python gr00t/eval/open_loop_eval.py \
|
| 407 |
+
--dataset-path demo_data/droid_sample \
|
| 408 |
+
--embodiment-tag OXE_DROID_RELATIVE_EEF_RELATIVE_JOINT \
|
| 409 |
+
--host 127.0.0.1 \
|
| 410 |
+
--port 5555 \
|
| 411 |
+
--traj-ids 1 2 \
|
| 412 |
+
--execution-horizon 8
|
| 413 |
+
```
|
| 414 |
+
|
| 415 |
+
> **Tip:** If you get `ZMQError: Address already in use`, the default port 5555 is occupied. Use `--port <other_port>`.
|
| 416 |
+
|
| 417 |
+
For connecting to a real robot (e.g., DROID hardware), see [examples/DROID/README.md](examples/DROID/README.md). For faster inference with TensorRT, see the [Deployment & Inference Guide](scripts/deployment/README.md).
|
| 418 |
+
|
| 419 |
+
See the complete [Policy API Guide](getting_started/policy.md) for documentation on observation/action formats, batched inference, and troubleshooting.
|
| 420 |
+
|
| 421 |
+
---
|
| 422 |
+
|
| 423 |
+
## Fine-tuning
|
| 424 |
+
|
| 425 |
+
### Reproducing Benchmark Results
|
| 426 |
+
|
| 427 |
+
Each benchmark has a self-contained README with dataset download, finetune, and evaluation commands:
|
| 428 |
+
|
| 429 |
+
| Benchmark | Embodiment | Guide |
|
| 430 |
+
|-----------|-----------|-------|
|
| 431 |
+
| LIBERO | `LIBERO_PANDA` | [examples/LIBERO/README.md](examples/LIBERO/README.md) |
|
| 432 |
+
| SimplerEnv (Fractal) | `SIMPLER_ENV_GOOGLE` | [examples/SimplerEnv/README.md](examples/SimplerEnv/README.md) |
|
| 433 |
+
| SimplerEnv (Bridge) | `SIMPLER_ENV_WIDOWX` | [examples/SimplerEnv/README.md](examples/SimplerEnv/README.md) |
|
| 434 |
+
| SO100 | `NEW_EMBODIMENT` | [examples/SO100/README.md](examples/SO100/README.md) |
|
| 435 |
+
|
| 436 |
+
### Humanoid Whole-Body Control (SONIC)
|
| 437 |
+
|
| 438 |
+
GR00T N1.7 supports whole-body humanoid control via the `UNITREE_G1_SONIC` embodiment tag and the [GEAR-SONIC](https://github.com/NVlabs/GR00T-WholeBodyControl) controller. In this workflow, the VLA predicts compact latent action tokens that a learned whole-body controller decodes into full-body joint commands — including legs, arms, and hands. A single policy produces language-conditioned, coordinated manipulation and locomotion end-to-end. SONIC supports whole-body coordination with precise hand and foot placements.
|
| 439 |
+
|
| 440 |
+
The complete collect → finetune → deploy workflow is documented in the [GR00T-WholeBodyControl repository](https://github.com/NVlabs/GR00T-WholeBodyControl):
|
| 441 |
+
|
| 442 |
+
- [Data collection](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/data_collection.html) — VR teleoperation with SONIC for demonstration recording
|
| 443 |
+
- [VLA Workflow](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vla_workflow.html) — finetuning Isaac-GR00T N1.7 on collected data and deploying the policy
|
| 444 |
+
- [VLA Inference](https://nvlabs.github.io/GR00T-WholeBodyControl/tutorials/vla_inference.html) — running the PolicyServer + SONIC decoder for real-time control
|
| 445 |
+
|
| 446 |
+
> **Note:** The `UNITREE_G1` embodiment tag is compatible with the [decoupled WBC](https://github.com/NVlabs/GR00T-WholeBodyControl/tree/main/decoupled_wbc) controller, but the end-to-end collect-finetune-deploy workflow is only supported for GEAR-SONIC (`UNITREE_G1_SONIC`).
|
| 447 |
+
|
| 448 |
+
### Fine-tune on Your Own Robot ("NEW_EMBODIMENT")
|
| 449 |
+
|
| 450 |
+
To finetune GR00T on your own robot data and configuration, follow the detailed tutorial at [`getting_started/finetune_new_embodiment.md`](getting_started/finetune_new_embodiment.md).
|
| 451 |
+
|
| 452 |
+
Ensure your input data follows the [GR00T LeRobot format](#data-format), and specify your modality configuration via `--modality-config-path`.
|
| 453 |
+
|
| 454 |
+
**Single GPU:**
|
| 455 |
+
```bash
|
| 456 |
+
CUDA_VISIBLE_DEVICES=0 uv run python \
|
| 457 |
+
gr00t/experiment/launch_finetune.py \
|
| 458 |
+
--base-model-path nvidia/GR00T-N1.7-3B \
|
| 459 |
+
--dataset-path demo_data/cube_to_bowl_5 \
|
| 460 |
+
--embodiment-tag NEW_EMBODIMENT \
|
| 461 |
+
--modality-config-path examples/SO100/so100_config.py \
|
| 462 |
+
--num-gpus 1 \
|
| 463 |
+
--output-dir /tmp/test_finetune \
|
| 464 |
+
--max-steps 2000 \
|
| 465 |
+
--global-batch-size 32 \
|
| 466 |
+
--dataloader-num-workers 4
|
| 467 |
+
```
|
| 468 |
+
|
| 469 |
+
**Multi-GPU (e.g., 8xH100):**
|
| 470 |
+
```bash
|
| 471 |
+
uv run torchrun --nproc_per_node=8 --master_port=29500 \
|
| 472 |
+
gr00t/experiment/launch_finetune.py \
|
| 473 |
+
--base-model-path nvidia/GR00T-N1.7-3B \
|
| 474 |
+
--dataset-path demo_data/cube_to_bowl_5 \
|
| 475 |
+
--embodiment-tag NEW_EMBODIMENT \
|
| 476 |
+
--modality-config-path examples/SO100/so100_config.py \
|
| 477 |
+
--num-gpus 8 \
|
| 478 |
+
--output-dir /tmp/test_finetune_8gpu \
|
| 479 |
+
--max-steps 2000 \
|
| 480 |
+
--global-batch-size 32 \
|
| 481 |
+
--dataloader-num-workers 4
|
| 482 |
+
```
|
| 483 |
+
|
| 484 |
+
Replace `demo_data/cube_to_bowl_5` and `examples/SO100/so100_config.py` with your own dataset and modality config. See [`examples/SO100`](examples/SO100/README.md) for a complete walkthrough.
|
| 485 |
+
|
| 486 |
+
> **Note:** Use `uv run torchrun` (not bare `torchrun`) to ensure the correct virtual environment is used. Add `--use-wandb` to enable Weights & Biases logging. For more extensive configuration, use `gr00t/experiment/launch_train.py`.
|
| 487 |
+
|
| 488 |
+
### Training Tips
|
| 489 |
+
|
| 490 |
+
- Maximize batch size for your hardware and train for a few thousand steps.
|
| 491 |
+
- Users may observe 5-6% variance between runs due to non-deterministic image augmentations. Keep this in mind when comparing to reported benchmarks.
|
| 492 |
+
- **`--state_dropout_prob`** (model config default: 0.8; finetune CLI default: 0.2; see `gr00t/configs/finetune_config.py`): Randomly drops state inputs during training to improve generalization and reduce state-dependency. The shipped benchmark scripts override the CLI default per suite: LIBERO 10-Long uses 0.2 (the CLI default), SimplerEnv Bridge uses 0.8, SimplerEnv Fractal uses 0.5. If your task relies heavily on proprioceptive state, lower this value.
|
| 493 |
+
|
| 494 |
+
---
|
| 495 |
+
|
| 496 |
+
## Evaluation
|
| 497 |
+
|
| 498 |
+
### Open-Loop Evaluation
|
| 499 |
+
|
| 500 |
+
Compare predicted actions against ground truth from your dataset:
|
| 501 |
+
|
| 502 |
+
```bash
|
| 503 |
+
uv run python gr00t/eval/open_loop_eval.py \
|
| 504 |
+
--dataset-path <DATASET_PATH> \
|
| 505 |
+
--embodiment-tag NEW_EMBODIMENT \
|
| 506 |
+
--model-path <CHECKPOINT_PATH> \
|
| 507 |
+
--traj-ids 0 \
|
| 508 |
+
--execution-horizon 16
|
| 509 |
+
```
|
| 510 |
+
|
| 511 |
+
This generates a visualization at `/tmp/open_loop_eval/traj_{traj_id}.jpeg` with ground truth vs. predicted actions and MSE metrics. Use `--save-plot-path <dir>` to save plots to a custom location.
|
| 512 |
+
|
| 513 |
+
### Closed-Loop Evaluation
|
| 514 |
+
|
| 515 |
+
Test your model in simulation or on real hardware using the server-client architecture:
|
| 516 |
+
|
| 517 |
+
```bash
|
| 518 |
+
# Start the policy server
|
| 519 |
+
uv run python gr00t/eval/run_gr00t_server.py \
|
| 520 |
+
--embodiment-tag NEW_EMBODIMENT \
|
| 521 |
+
--model-path <CHECKPOINT_PATH> \
|
| 522 |
+
--device cuda:0 \
|
| 523 |
+
--host 0.0.0.0 --port 5555
|
| 524 |
+
```
|
| 525 |
+
|
| 526 |
+
```python
|
| 527 |
+
from gr00t.policy.server_client import PolicyClient
|
| 528 |
+
|
| 529 |
+
policy = PolicyClient(host="localhost", port=5555)
|
| 530 |
+
env = YourEnvironment()
|
| 531 |
+
obs, info = env.reset()
|
| 532 |
+
action, info = policy.get_action(obs)
|
| 533 |
+
obs, reward, done, truncated, info = env.step(action)
|
| 534 |
+
```
|
| 535 |
+
|
| 536 |
+
**Debugging with ReplayPolicy:** To verify your environment setup without a trained model, start the server with `--dataset-path <DATASET_PATH>` (omit `--model-path`) to replay recorded actions from the dataset.
|
| 537 |
+
|
| 538 |
+
See the complete [Policy API Guide](getting_started/policy.md) for observation/action formats, batched inference, and troubleshooting.
|
| 539 |
+
|
| 540 |
+
### Benchmark Examples
|
| 541 |
+
|
| 542 |
+
We support evaluation on public benchmarks using a server-client architecture. The policy server reuses the project root's uv environment; simulation clients have individual setup scripts.
|
| 543 |
+
|
| 544 |
+
You can use [the verification script](scripts/eval/check_sim_eval_ready.py) to verify that all dependencies are properly configured.
|
| 545 |
+
|
| 546 |
+
#### One-Time Simulation Environment Setup
|
| 547 |
+
|
| 548 |
+
Each simulation benchmark needs a one-time environment setup before its first run. First install the shared system libraries:
|
| 549 |
+
|
| 550 |
+
```bash
|
| 551 |
+
sudo apt update
|
| 552 |
+
sudo apt install libegl1-mesa-dev libglu1-mesa
|
| 553 |
+
```
|
| 554 |
+
|
| 555 |
+
Then run the benchmark's own `setup_*.sh` script, linked from each simulation benchmark's README (LIBERO, SimplerEnv, robocasa, and robocasa-gr1). This only needs to run once per benchmark; afterward you just launch the server and client. The real-hardware/custom-embodiment workflows (DROID, RoboLab, SO100) have no simulation setup script; follow their own READMEs instead.
|
| 556 |
+
|
| 557 |
+
**Zero-shot** (evaluate with the base model, no finetuning):
|
| 558 |
+
- [DROID](examples/DROID/README.md) — real-world DROID robot (also available as the finetuned `nvidia/GR00T-N1.7-DROID` checkpoint; `examples/DROID/README.md` covers both paths)
|
| 559 |
+
|
| 560 |
+
**Finetuned** (evaluate with finetuned checkpoints):
|
| 561 |
+
- [DROID](examples/DROID/README.md) — real-world DROID robot via `nvidia/GR00T-N1.7-DROID`
|
| 562 |
+
- [RoboLab](examples/RoboLab/README.md) — RoboLab simulation tasks via `nvidia/GR00T-N1.7-DROID`
|
| 563 |
+
- [LIBERO](examples/LIBERO/README.md) — LIBERO benchmark (Franka Panda)
|
| 564 |
+
- [SimplerEnv](examples/SimplerEnv/README.md) — Google Robot (Fractal) and WidowX (Bridge)
|
| 565 |
+
- [SO100](examples/SO100/README.md) — SO100 custom embodiment workflow
|
| 566 |
+
|
| 567 |
+
<details>
|
| 568 |
+
<summary><strong>Adding a New Sim Benchmark</strong></summary>
|
| 569 |
+
|
| 570 |
+
Each sim benchmark registers its environments under a gym env_name with the format `{prefix}/{task_name}` (e.g., `libero_sim/LIVING_ROOM_SCENE2_put_soup_in_basket`). The evaluation framework uses the prefix to look up the corresponding `EmbodimentTag` via a mapping in [`gr00t/eval/sim/env_utils.py`](gr00t/eval/sim/env_utils.py).
|
| 571 |
+
|
| 572 |
+
> **Important:** The env_name prefix and the `EmbodimentTag` **name** are often different. For example, the prefix `libero_sim` maps to `EmbodimentTag.LIBERO_PANDA` (whose value happens to be `"libero_sim"`). Do not assume the prefix matches the tag name.
|
| 573 |
+
|
| 574 |
+
To add a new benchmark:
|
| 575 |
+
|
| 576 |
+
1. Add an entry to `ENV_PREFIX_TO_EMBODIMENT_TAG` in `gr00t/eval/sim/env_utils.py`:
|
| 577 |
+
```python
|
| 578 |
+
ENV_PREFIX_TO_EMBODIMENT_TAG = {
|
| 579 |
+
...
|
| 580 |
+
"my_new_benchmark": EmbodimentTag.MY_ROBOT,
|
| 581 |
+
}
|
| 582 |
+
```
|
| 583 |
+
2. If the benchmark has multiple env_name prefixes (e.g., `my_benchmark_v1`, `my_benchmark_v2`), all related prefixes **must** map to the same `EmbodimentTag`.
|
| 584 |
+
3. Add corresponding test cases in `tests/gr00t/eval/sim/test_env_utils.py` and update the `test_all_known_prefixes_present` test.
|
| 585 |
+
</details>
|
| 586 |
+
|
| 587 |
+
|
| 588 |
+
|
| 589 |
+
## Running Tests
|
| 590 |
+
|
| 591 |
+
Install the development dependencies before running the test suite:
|
| 592 |
+
```bash
|
| 593 |
+
uv sync --python 3.12 --extra dev
|
| 594 |
+
uv run python -m pytest
|
| 595 |
+
```
|
| 596 |
+
|
| 597 |
+
Use targeted test paths for faster local checks, and reserve GPU-marked tests for machines with the required CUDA hardware.
|
| 598 |
+
|
| 599 |
+
---
|
| 600 |
+
|
| 601 |
+
## Contributions
|
| 602 |
+
|
| 603 |
+
We welcome issues and pull requests. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to contribute and for support details now that GR00T N1.7 has reached General Availability (GA).
|
| 604 |
+
|
| 605 |
+
## License
|
| 606 |
+
|
| 607 |
+
- **Code:** Apache 2.0 — see [LICENSE](LICENSE)
|
| 608 |
+
- **Model weights:** [NVIDIA Open Model License](https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-open-model-license/)
|
| 609 |
+
|
| 610 |
+
```
|
| 611 |
+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
| 612 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 613 |
+
#
|
| 614 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 615 |
+
# you may not use this file except in compliance with the License.
|
| 616 |
+
# You may obtain a copy of the License at
|
| 617 |
+
#
|
| 618 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 619 |
+
#
|
| 620 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 621 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 622 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 623 |
+
# See the License for the specific language governing permissions and
|
| 624 |
+
# limitations under the License.
|
| 625 |
+
```
|
| 626 |
+
|
| 627 |
+
|
| 628 |
+
## Citation
|
| 629 |
+
|
| 630 |
+
[Paper Site](https://research.nvidia.com/labs/lpr/publication/gr00tn1_2025/)
|
| 631 |
+
```bibtex
|
| 632 |
+
@inproceedings{gr00tn1_2025,
|
| 633 |
+
archivePrefix = {arxiv},
|
| 634 |
+
eprint = {2503.14734},
|
| 635 |
+
title = {{GR00T} {N1}: An Open Foundation Model for Generalist Humanoid Robots},
|
| 636 |
+
author = {NVIDIA and Johan Bjorck and Fernando Castañeda, Nikita Cherniadev and Xingye Da and Runyu Ding and Linxi "Jim" Fan and Yu Fang and Dieter Fox and Fengyuan Hu and Spencer Huang and Joel Jang and Zhenyu Jiang and Jan Kautz and Kaushil Kundalia and Lawrence Lao and Zhiqi Li and Zongyu Lin and Kevin Lin and Guilin Liu and Edith Llontop and Loic Magne and Ajay Mandlekar and Avnish Narayan and Soroush Nasiriany and Scott Reed and You Liang Tan and Guanzhi Wang and Zu Wang and Jing Wang and Qi Wang and Jiannan Xiang and Yuqi Xie and Yinzhen Xu and Zhenjia Xu and Seonghyeon Ye and Zhiding Yu and Ao Zhang and Hao Zhang and Yizhou Zhao and Ruijie Zheng and Yuke Zhu},
|
| 637 |
+
month = {March},
|
| 638 |
+
year = {2025},
|
| 639 |
+
booktitle = {ArXiv Preprint},
|
| 640 |
+
}
|
| 641 |
+
```
|
Isaac-GR00T/pyproject.toml
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Default platform pyproject.toml (x86, GB200, and any non-Jetson GPU)
|
| 2 |
+
|
| 3 |
+
[build-system]
|
| 4 |
+
requires = ["setuptools>=67", "wheel", "pip"]
|
| 5 |
+
build-backend = "setuptools.build_meta"
|
| 6 |
+
|
| 7 |
+
[project]
|
| 8 |
+
name = "gr00t"
|
| 9 |
+
version = "0.1.0"
|
| 10 |
+
requires-python = ">=3.12,<3.13"
|
| 11 |
+
dependencies = [
|
| 12 |
+
"albumentations==1.4.18",
|
| 13 |
+
"huggingface-hub[cli]",
|
| 14 |
+
"opencv-python-headless>=4.5,<4.13",
|
| 15 |
+
"diffusers==0.35.1",
|
| 16 |
+
"dm-tree",
|
| 17 |
+
"lmdb==1.7.5",
|
| 18 |
+
"msgpack==1.1.0",
|
| 19 |
+
"msgpack-numpy==0.4.8",
|
| 20 |
+
"pandas==2.2.3",
|
| 21 |
+
"peft==0.17.1",
|
| 22 |
+
"termcolor==3.2.0",
|
| 23 |
+
"torch==2.9.0",
|
| 24 |
+
"torchvision==0.24.0",
|
| 25 |
+
"transformers==4.57.3",
|
| 26 |
+
"tyro==0.9.17",
|
| 27 |
+
"click==8.1.8",
|
| 28 |
+
"datasets==3.6.0",
|
| 29 |
+
"cryptography>=46.0.7",
|
| 30 |
+
"einops==0.8.1",
|
| 31 |
+
"gitpython==3.1.50",
|
| 32 |
+
"jsonlines==4.0.0",
|
| 33 |
+
"gymnasium==1.2.2",
|
| 34 |
+
"matplotlib==3.10.1",
|
| 35 |
+
"numpy==1.26.4",
|
| 36 |
+
"omegaconf==2.3.0",
|
| 37 |
+
"scipy==1.15.3",
|
| 38 |
+
# torchcodec 0.8.0 pairs with torch 2.9 and supports FFmpeg 4-7. It does NOT
|
| 39 |
+
# support FFmpeg 8 (the default on Ubuntu 25.10+/26.04); on those distros
|
| 40 |
+
# install an FFmpeg<8 runtime. x86_64: PyPI wheel; aarch64 Linux: prebuilt
|
| 41 |
+
# wheel in scripts/deployment/dgpu/wheels/ (no aarch64 wheel published on PyPI).
|
| 42 |
+
"torchcodec==0.8.0; platform_machine == 'x86_64'",
|
| 43 |
+
"torchcodec==0.8.0; platform_machine == 'aarch64' and sys_platform == 'linux'",
|
| 44 |
+
"wandb==0.23.0",
|
| 45 |
+
"pyzmq==27.0.1",
|
| 46 |
+
# deepspeed publishes wheels only for x86_64 Linux.
|
| 47 |
+
"deepspeed==0.17.6; sys_platform == 'linux' and platform_machine == 'x86_64'",
|
| 48 |
+
# triton is needed on aarch64 (GB200) but ships with torch on x86_64
|
| 49 |
+
"triton==3.5.0; sys_platform == 'linux' and platform_machine == 'aarch64'",
|
| 50 |
+
# flash-attn wheels are sourced from `[tool.uv.sources]` below (official cp312 wheels for x86_64 and aarch64).
|
| 51 |
+
"flash-attn==2.8.3; sys_platform == 'linux' and (platform_machine == 'x86_64' or platform_machine == 'aarch64')",
|
| 52 |
+
"onnx>=1.20.0",
|
| 53 |
+
"onnxscript",
|
| 54 |
+
# cu12 wheels only exist for x86_64; Blackwell / aarch64 requires cu13.
|
| 55 |
+
"tensorrt-cu12>=10.15.1.29; platform_machine == 'x86_64'",
|
| 56 |
+
"tensorrt-cu13>=10.15.1.29; platform_machine == 'aarch64'",
|
| 57 |
+
"tensorrt-cu12-libs>=10.15.1.29; platform_machine == 'x86_64'",
|
| 58 |
+
"tensorrt-cu13-libs>=10.15.1.29; platform_machine == 'aarch64'",
|
| 59 |
+
]
|
| 60 |
+
|
| 61 |
+
[project.optional-dependencies]
|
| 62 |
+
dev = [
|
| 63 |
+
"boto3",
|
| 64 |
+
"ruff",
|
| 65 |
+
"ipython",
|
| 66 |
+
"pip-licenses",
|
| 67 |
+
"pytest",
|
| 68 |
+
"pytest-cov",
|
| 69 |
+
"pytest-timeout",
|
| 70 |
+
"pytest-xdist",
|
| 71 |
+
"build",
|
| 72 |
+
"pre-commit",
|
| 73 |
+
# `tomllib` is 3.11+ stdlib; provide `tomli` for the 3.10 fallback.
|
| 74 |
+
"tomli; python_version < '3.11'",
|
| 75 |
+
]
|
| 76 |
+
|
| 77 |
+
[tool.setuptools.packages.find]
|
| 78 |
+
where = ["."]
|
| 79 |
+
include = ["gr00t*"]
|
| 80 |
+
|
| 81 |
+
[tool.uv]
|
| 82 |
+
required-environments = [
|
| 83 |
+
"sys_platform == 'linux' and platform_machine == 'x86_64'",
|
| 84 |
+
"sys_platform == 'linux' and platform_machine == 'aarch64'",
|
| 85 |
+
]
|
| 86 |
+
|
| 87 |
+
[tool.uv.sources]
|
| 88 |
+
torch = [
|
| 89 |
+
{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" },
|
| 90 |
+
]
|
| 91 |
+
torchvision = [
|
| 92 |
+
{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" },
|
| 93 |
+
]
|
| 94 |
+
triton = [
|
| 95 |
+
{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" },
|
| 96 |
+
]
|
| 97 |
+
flash-attn = [
|
| 98 |
+
{ url = "https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.9cxx11abiTRUE-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64'" },
|
| 99 |
+
{ url = "https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.9cxx11abiTRUE-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64'" },
|
| 100 |
+
]
|
| 101 |
+
torchcodec = [
|
| 102 |
+
{ path = "scripts/deployment/dgpu/wheels/torchcodec-0.8.0-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64'" },
|
| 103 |
+
]
|
| 104 |
+
tensorrt-cu12-libs = [
|
| 105 |
+
{ index = "nvidia-pypi", marker = "platform_machine == 'x86_64'" },
|
| 106 |
+
]
|
| 107 |
+
tensorrt-cu13-libs = [
|
| 108 |
+
{ index = "nvidia-pypi", marker = "platform_machine == 'aarch64'" },
|
| 109 |
+
]
|
| 110 |
+
|
| 111 |
+
[tool.uv.extra-build-dependencies]
|
| 112 |
+
flash-attn = ["torch==2.9.0", "numpy==1.26.4", "triton==3.5.0"]
|
| 113 |
+
|
| 114 |
+
[tool.pytest.ini_options]
|
| 115 |
+
pythonpath = [".", "tests"]
|
| 116 |
+
addopts = "--import-mode=importlib"
|
| 117 |
+
markers = [
|
| 118 |
+
"gpu: tests that require a GPU",
|
| 119 |
+
"edge_device: tests that run on edge device runners (Orin, Thor, DGX Spark)",
|
| 120 |
+
"multigpu: tests that require multiple GPUs and use all visible GPUs",
|
| 121 |
+
"serial: run in the CPU job's serial phase instead of under pytest-xdist -n auto (e.g. it forks torch-importing subprocesses that oversubscribe the box and time out under full fan-out)",
|
| 122 |
+
]
|
| 123 |
+
# Include fixture setup/teardown in JUnit <testcase time="..."> so duration
|
| 124 |
+
# reports (ci/print_duration_summary.py) and TestRun.duration in testdb
|
| 125 |
+
# reflect real wall-clock time. With the default ("call"), expensive
|
| 126 |
+
# session/module/class-scoped fixtures (e.g. NFS->local model staging,
|
| 127 |
+
# Gr00tPolicy load) are invisible and tests look misleadingly fast.
|
| 128 |
+
junit_duration_report = "total"
|
| 129 |
+
|
| 130 |
+
[tool.ruff]
|
| 131 |
+
line-length = 100
|
| 132 |
+
target-version = "py312"
|
| 133 |
+
src = ["gr00t"]
|
| 134 |
+
exclude = [
|
| 135 |
+
"__pycache__",
|
| 136 |
+
".git",
|
| 137 |
+
".mypy_cache",
|
| 138 |
+
".pytest_cache",
|
| 139 |
+
".vscode",
|
| 140 |
+
".venv",
|
| 141 |
+
"dist",
|
| 142 |
+
"logs",
|
| 143 |
+
"*.ipynb",
|
| 144 |
+
"external_dependencies",
|
| 145 |
+
]
|
| 146 |
+
|
| 147 |
+
[tool.ruff.format]
|
| 148 |
+
quote-style = "double"
|
| 149 |
+
indent-style = "space"
|
| 150 |
+
docstring-code-format = true
|
| 151 |
+
|
| 152 |
+
[tool.ruff.lint]
|
| 153 |
+
select = ["E", "F", "I"]
|
| 154 |
+
ignore = ["E501"]
|
| 155 |
+
|
| 156 |
+
[tool.ruff.lint.per-file-ignores]
|
| 157 |
+
"__init__.py" = ["F401"]
|
| 158 |
+
|
| 159 |
+
[tool.ruff.lint.isort]
|
| 160 |
+
case-sensitive = false
|
| 161 |
+
combine-as-imports = true
|
| 162 |
+
force-sort-within-sections = true
|
| 163 |
+
force-wrap-aliases = false
|
| 164 |
+
split-on-trailing-comma = false
|
| 165 |
+
lines-after-imports = 2
|
| 166 |
+
section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
|
| 167 |
+
|
| 168 |
+
[[tool.uv.index]]
|
| 169 |
+
name = "nvidia-pypi"
|
| 170 |
+
url = "https://pypi.nvidia.com"
|
| 171 |
+
explicit = true
|
| 172 |
+
|
| 173 |
+
[[tool.uv.index]]
|
| 174 |
+
name = "pytorch-cu128"
|
| 175 |
+
url = "https://download.pytorch.org/whl/cu128"
|
| 176 |
+
explicit = true
|
Isaac-GR00T/uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|