File size: 7,101 Bytes
700dd75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# VLA Workflow: Collect, Fine-tune, Deploy

This tutorial walks through the end-to-end workflow for training and deploying a
VLA policy on the Unitree G1 with SONIC whole-body control:

1. **Collect** teleop demonstrations using the SONIC stack
2. **Fine-tune** the Isaac-GR00T N1.7 model on your collected data
3. **Deploy** the finetuned policy for autonomous inference

```text
+-----------------+     +-----------------+     +-----------------+
| 1. Collect      |     | 2. Fine-tune    |     | 3. Deploy       |
| VR teleop +     | --> | Isaac-GR00T     | --> | PolicyServer +  |
| data export     |     | N1.7            |     | SONIC           |
+-----------------+     +-----------------+     +-----------------+
```

For examples of whole-body manipulation tasks accomplished with this workflow, see the
[VLA result videos on the GEAR-SONIC project page](https://nvlabs.github.io/GEAR-SONIC/#connection-to-vla-foundation-model).

## How It Works: SONIC Latent Actions

Instead of predicting raw joint angles, the VLA predicts **SONIC latent motion
tokens** — a compact 64-dimensional representation learned by the SONIC whole-body
controller. SONIC then decodes these latents into full-body joint commands at 50 Hz.

```text
+-------------+   latent tokens   +-------------+   joint commands   +-------+
| VLA Model   | ----------------> | SONIC       | -----------------> | Robot |
| 2.5 Hz      |   64-dim x 40     | Decoder     |   50 Hz            |       |
|             |                   | C++         |                    |       |
+-------------+                   +-------------+                    +-------+
```

This means the VLA only needs to reason about *what* to do — SONIC handles the
*how*: balance, locomotion, and smooth whole-body coordination
all come for free from the pretrained controller. The result is a system that can
walk, reach, grasp, and manipulate simultaneously.

The full action space per inference step is 78-dimensional: 64-dim motion token +
7-dim left hand joints + 7-dim right hand joints.

## Step 1: Data Collection

Collect teleop demonstrations using VR whole-body teleoperation. The data exporter
records robot state, camera images, and teleop actions as a LeRobot dataset.

See the [Data Collection tutorial](data_collection.md) for full setup instructions
(camera server, VR teleop, recording controls).

**Quick start:**

```bash
python gear_sonic/scripts/launch_data_collection.py \
    --camera-host 192.168.123.164 \
    --task-prompt "pick up the soda can and place it in the bin"
```

**Output:** A LeRobot v2.1 dataset directory, e.g.:

```text
outputs/2026-04-03-14-30-00-G1-robot01/
+-- data/
|   +-- train-00000.parquet
+-- videos/
|   +-- observation.images.ego_view/
|       +-- episode_000000.mp4
+-- meta/
    +-- info.json
    +-- modality.json
    +-- episodes.jsonl
    +-- tasks.jsonl
```

```{tip}
Collect at least 50–100 demonstrations of the target task for reliable fine-tuning.
Use `--dataset-name` to append multiple sessions into the same dataset, or merge
sessions afterwards with `process_dataset.py`.
```

### Post-Process Before Fine-tuning

After collection, run the processing script to remove discarded episodes
(flagged via `x` key during recording) and clean stale SMPL frames:

```bash
source .venv_data_collection/bin/activate
python gear_sonic/scripts/process_dataset.py \
    --dataset-path outputs/2026-04-03-14-30-00-G1-robot01 \
    --output-path outputs/my_task_cleaned
```

This ensures only successful demonstrations are used for fine-tuning.

## Step 2: Fine-tuning with Isaac-GR00T

Fine-tune the GR00T N1.7 base model on your collected dataset using the
[Isaac-GR00T](https://github.com/NVIDIA/Isaac-GR00T) training pipeline.

### Prerequisites

- Clone and install [Isaac-GR00T](https://github.com/NVIDIA/Isaac-GR00T):
  ```bash
  git clone https://github.com/NVIDIA/Isaac-GR00T.git
  cd Isaac-GR00T
  uv sync --all-extras
  ```
- Multi-GPU machine (4+ GPUs recommended)
- The collected dataset accessible from the training machine

### Launch Fine-tuning

```bash
export NUM_GPUS=4
uv run python \
    gr00t/experiment/launch_finetune.py \
    --base-model-path nvidia/GR00T-N1.7-3B \
    --dataset-path /path/to/your/collected_dataset \
    --embodiment-tag UNITREE_G1_SONIC \
    --modality-config-path gr00t/configs/data/embodiment_configs.py \
    --num-gpus $NUM_GPUS \
    --output-dir /path/to/output \
    --save-total-limit 5 \
    --save-steps 5000 \
    --max-steps 20000 \
    --use-wandb \
    --global-batch-size 32 \
    --color-jitter-params brightness 0.3 contrast 0.4 saturation 0.5 hue 0.08 \
    --dataloader-num-workers 4
```

### Key Parameters

| Flag | Description |
|------|-------------|
| `--base-model-path` | HuggingFace model ID or local path to pretrained weights |
| `--dataset-path` | Path to the LeRobot dataset from Step 1 |
| `--embodiment-tag` | Must match the dataset's embodiment (`UNITREE_G1_SONIC`) |
| `--modality-config-path` | Python file defining the modality configuration |
| `--num-gpus` | Number of GPUs for distributed training |
| `--max-steps` | Total training steps (20k is a good starting point) |
| `--global-batch-size` | Total batch size across all GPUs |
| `--save-steps` | Checkpoint save interval |
| `--use-wandb` | Enable Weights & Biases logging |

### Monitoring

With `--use-wandb`, training metrics (loss, learning rate, etc.) are logged to your
W&B project. Monitor the training loss curve — it should decrease steadily and
plateau before `--max-steps`.

### Output

Checkpoints are saved to `--output-dir`:

```text
/path/to/output/
+-- checkpoint-5000/
+-- checkpoint-10000/
+-- checkpoint-15000/
+-- checkpoint-20000/
+-- config.json
+-- processor_config.json
```

Use the final checkpoint (or the best-performing one based on your evaluation) for
deployment in Step 3.

## Step 3: Deploy for Inference

Deploy the finetuned model using the Isaac-GR00T PolicyServer and the SONIC
inference stack. See the [VLA Inference tutorial](vla_inference.md) for full
details on the inference pipeline, keyboard controls, and configuration.

### Start the PolicyServer

On the GPU machine, from the Isaac-GR00T repository:

```bash
uv run python gr00t/eval/run_gr00t_server.py \
    --model-path /path/to/output/checkpoint-20000 \
    --embodiment-tag UNITREE_G1_SONIC \
    --device cuda:0 \
    --port 5550
```

### Run Inference

On the inference machine (from the GR00T-WholeBodyControl repository):

```bash
python gear_sonic/scripts/launch_inference.py \
    --policy-host <gpu_machine_ip> \
    --policy-port 5550 \
    --camera-host 192.168.123.164 \
    --prompt "pick up the soda can and place it in the bin"
```

## Summary

| Step | Where | Key Command |
|------|-------|-------------|
| Collect | GR00T-WholeBodyControl | `launch_data_collection.py` |
| Fine-tune | Isaac-GR00T | `launch_finetune.py` |
| Deploy | Both repos | `run_gr00t_server.py` + `launch_inference.py` |

For iterating on a task, repeat Steps 1–3: collect more data, fine-tune again
(or continue from an existing checkpoint), and redeploy.