Timsty commited on
Commit
c26f879
·
verified ·
1 Parent(s): b516ae9

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. GR00T-WholeBodyControl/.gitattributes +25 -0
  2. GR00T-WholeBodyControl/.gitignore +221 -0
  3. GR00T-WholeBodyControl/.lfsconfig +2 -0
  4. GR00T-WholeBodyControl/CITATION.cff +93 -0
  5. GR00T-WholeBodyControl/CONTRIBUTING.md +40 -0
  6. GR00T-WholeBodyControl/LICENSE +186 -0
  7. GR00T-WholeBodyControl/Makefile +16 -0
  8. GR00T-WholeBodyControl/README.md +459 -0
  9. GR00T-WholeBodyControl/SECURITY.md +10 -0
  10. GR00T-WholeBodyControl/check_environment.py +225 -0
  11. GR00T-WholeBodyControl/decoupled_wbc/pyproject.toml +93 -0
  12. GR00T-WholeBodyControl/docs/requirements.txt +10 -0
  13. GR00T-WholeBodyControl/download_from_hf.py +311 -0
  14. GR00T-WholeBodyControl/gear_sonic_deploy/.clang-format +85 -0
  15. GR00T-WholeBodyControl/gear_sonic_deploy/.cmake-format.py +20 -0
  16. GR00T-WholeBodyControl/gear_sonic_deploy/.editorconfig +24 -0
  17. GR00T-WholeBodyControl/gear_sonic_deploy/.gitattributes +9 -0
  18. GR00T-WholeBodyControl/gear_sonic_deploy/.gitignore +7 -0
  19. GR00T-WholeBodyControl/gear_sonic_deploy/.justfile +44 -0
  20. GR00T-WholeBodyControl/gear_sonic_deploy/CMakeLists.txt +245 -0
  21. GR00T-WholeBodyControl/gear_sonic_deploy/deploy.sh +577 -0
  22. GR00T-WholeBodyControl/gear_sonic_deploy/visualize_motion.py +432 -0
  23. GR00T-WholeBodyControl/install_scripts/install_camera_server.sh +252 -0
  24. GR00T-WholeBodyControl/install_scripts/install_data_collection.sh +80 -0
  25. GR00T-WholeBodyControl/install_scripts/install_inference.sh +72 -0
  26. GR00T-WholeBodyControl/install_scripts/install_leap_sdk.sh +19 -0
  27. GR00T-WholeBodyControl/install_scripts/install_mujoco_sim.sh +76 -0
  28. GR00T-WholeBodyControl/install_scripts/install_pico.sh +191 -0
  29. GR00T-WholeBodyControl/install_scripts/install_ros.sh +64 -0
  30. GR00T-WholeBodyControl/lint.sh +45 -0
  31. GR00T-WholeBodyControl/motionbricks/.gitattributes +4 -0
  32. GR00T-WholeBodyControl/motionbricks/README.md +281 -0
  33. GR00T-WholeBodyControl/motionbricks/setup.py +23 -0
  34. GR00T-WholeBodyControl/pyproject.toml +87 -0
  35. GR00T-WholeBodyControl/systemd/composed_camera_server.service +66 -0
  36. Isaac-GR00T/.coveragerc +28 -0
  37. Isaac-GR00T/.dockerignore +19 -0
  38. Isaac-GR00T/.gitattributes +9 -0
  39. Isaac-GR00T/.gitignore +170 -0
  40. Isaac-GR00T/.gitmodules +12 -0
  41. Isaac-GR00T/.pre-commit-config.yaml +25 -0
  42. Isaac-GR00T/AGENTS.md +79 -0
  43. Isaac-GR00T/ATTRIBUTIONS.md +0 -0
  44. Isaac-GR00T/CLAUDE.md +79 -0
  45. Isaac-GR00T/CONTRIBUTING.md +7 -0
  46. Isaac-GR00T/FAQ.md +81 -0
  47. Isaac-GR00T/LICENSE +190 -0
  48. Isaac-GR00T/README.md +641 -0
  49. Isaac-GR00T/pyproject.toml +176 -0
  50. 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](https://img.shields.io/badge/License-Apache%202.0-76B900.svg)](LICENSE)
13
+ [![IsaacLab](https://img.shields.io/badge/IsaacLab-2.3.2-orange.svg)](https://github.com/isaac-sim/IsaacLab/releases/tag/v2.3.2)
14
+ [![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-76B900.svg)](https://nvlabs.github.io/GR00T-WholeBodyControl/)
15
+ [![Demo](https://img.shields.io/badge/Live%20Demo-GEAR--SONIC-blue.svg)](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
+ | ![Animation teaser](assets/gifs/teaser_animation.gif) | ![Robotics teaser](assets/gifs/teaser_robotics.gif) |
48
+
49
+ ### Smart Locomotion — Single Styles
50
+
51
+ | Zombie | Injured leg |
52
+ | :---: | :---: |
53
+ | ![Zombie](assets/gifs/loco_zombie.gif) | ![Injured leg](assets/gifs/loco_injured_leg.gif) |
54
+ | **Injured torso** | **Skipping** |
55
+ | ![Injured torso](assets/gifs/loco_injured_torso.gif) | ![Skipping](assets/gifs/loco_skipping.gif) |
56
+ | **Strafing** | **Crouch strafing** |
57
+ | ![Strafing](assets/gifs/loco_strafing.gif) | ![Crouch strafing](assets/gifs/loco_crouch_strafing.gif) |
58
+
59
+ ### Smart Locomotion — Mixture of Styles
60
+
61
+ | Freestyle | Idle · Walk · Jog · Run |
62
+ | :---: | :---: |
63
+ | ![Freestyle](assets/gifs/loco_freestyle.gif) | ![Idle / walk / jog / run](assets/gifs/loco_idle_walk_jog_run.gif) |
64
+
65
+ ### Smart Objects
66
+
67
+ | Pick up sword | Falling |
68
+ | :---: | :---: |
69
+ | ![Pick up sword](assets/gifs/obj_pickup_sword.gif) | ![Falling](assets/gifs/obj_falling.gif) |
70
+ | **Jump over bench** | **Sitting** |
71
+ | ![Jump over bench](assets/gifs/obj_jump_bench.gif) | ![Sitting](assets/gifs/obj_sitting.gif) |
72
+ | **Interactive authoring** | |
73
+ | ![Interactive authoring](assets/gifs/obj_interactive_authoring.gif) | |
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&lt;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