File size: 22,315 Bytes
b6a9d87 | 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 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 | # GR00T Real-World Deployment Guide
This guide covers building an end-to-end real-world VLA pipeline—from data collection and training to deployment—with practical engineering recommendations.
## Overview
A typical GR00T real-world deployment workflow includes:
1. **[Hardware Preparation](#1-hardware-and-environment-preparation-device-requirements)**: Verify that the robot platform, sensors, and compute resources are ready.
2. **[Data Collection](#2-data-collection)**: Choose an appropriate teleoperation setup and collect at least 100 valid episodes.
3. **[Data Preprocessing](#3-data-preprocessing)**: Clean data, align timestamps, and convert to LeRobot format.
4. **[Model Training](#4-vla-model-training)**: Fine-tune GR00T N1.*.
5. **[Model Evaluation](#validation)**: Run open-loop evaluation to validate convergence and model quality.
6. **[Deployment Setup](#5-deployment-and-closed-loop-control)**: Build a ZMQ Server-Client architecture.
7. **[Closed-Loop Testing](#5-deployment-and-closed-loop-control)**: Run closed-loop control on real hardware and monitor jittering and stop-and-go behavior.
8. **[Optimization](#6-common-issues-jittering-and-stop-and-go)**: Tune RTC parameters and trajectory smoothing strategies based on real-world performance.
## 1. Hardware and Environment Preparation (Device Requirements)
Ensure your robot hardware, sensor pipeline, and control interfaces are stable and available.
### Robot Platform
- **Recommended platforms**: Robotic arms with SDK-level control support (e.g., Franka, UR, Piper, SO101).
- **Basic requirements**:
- Real-time joint state feedback.
- High-frequency action execution (30 FPS recommended).
- Stable control interface.
> **30 FPS vs inference rate:** The 30 FPS here (and for the cameras below) is the robot's **action-execution** and **camera-capture** rate — not the model **inference** rate. The policy returns a multi-step action *chunk* per inference, so a ~10 Hz inference rate can drive 30 FPS execution via action chunking + asynchronous inference. See the [inference-frequency guidance](hardware_recommendation.md#key-insights) for what each platform sustains.
### Multimodal Sensors
| Sensor Type | Specification | Purpose |
|-------------|---------------|---------|
| **Wrist-mounted camera** | 30 FPS, RGB | Capture close-range manipulation visuals |
| **Third-person camera (3rd view)** | 30 FPS, RGB | Capture global scene context |
| **Robot proprioceptive state** | Real-time acquisition | Joint states and gripper state |
### Compute Resources
- **Training phase**: NVIDIA GPU servers (e.g., H100 or H20) are recommended for larger batch sizes.
- **Deployment phase**: Edge hardware such as Jetson AGX Thor supports on-device inference.
> For details, see the [hardware recommendation guide](hardware_recommendation.md).
### Teleoperation Devices
Teleoperation device selection is critical for data quality.
### Teleoperation Device Comparison
In the table below:
- **Embodiment dependency**: how similar the teleoperation device and target robot must be in joint topology, degrees of freedom (DoF), and workspace. Higher dependency implies harder cross-embodiment transfer.
- **Operational intuition**: how naturally operator inputs map to robot motion. Higher intuition means faster onboarding and lower demonstration error.
| Device Type | Cost Level (Reference) | Embodiment Dependency | Operational Intuition | Notes |
|-------------|------------------------|-----------------------|-----------------------|-------|
| **Keyboard/Gamepad/SpaceMouse/Joylo** | Low | Low: command mapping via keys/controls | Medium: requires adaptation to key-motion mapping | Low entry cost; a good starting point and useful in mobile scenarios |
| **Master-Slave arm systems** | Medium | High: master/slave arms usually require similar kinematics and workspace | High: near one-to-one human-robot mapping | Suitable for single-robot setups; commonly used by robot OEMs; can reduce the risk of reaching joint limits during demonstrations |
| **UMI / Fast-UMI / Pika Sense** | Medium | Low: hardware-agnostic action representation reusable across arms | High: after calibration, end-effector (EEF) following is intuitive | Suitable for training general VLA models; low-DoF arms may still hit joint limits |
| **VR-based teleoperation** | Medium (headset + rendering + network) | Low: mainly depends on software integration | Medium: depends on immersive visual feedback and tracking quality | A flexible solution, but with higher integration overhead |
| **Glove / Motion Capture** | High (commercial mocap suite + data gloves) | Low: retarget through kinematic mapping to different embodiments | High: intuitive full-hand/full-body control | Suitable for full-body control and dexterous-hand tasks |
| **Exoskeleton** | High | High: usually requires matched joint structure | High: natural action correspondence | Extendable to multi-joint humanoid control |
## 2. Data Collection
Key considerations for data collection:
### Timestamp Synchronization
- The FPS of both camera streams should be strictly matched, and capture triggers should be as synchronized as possible.
- Joint state sampling frequency should exceed camera FPS to enable accurate downsampling.
- Record full timestamps during collection for downstream temporal alignment.
### Action Representation
- If training and collection use the same embodiment (e.g., master-slave arms), log joint-space `Joint States` during collection. For task-space models, compute EEF pose via forward kinematics (FK) in post-processing.
- If embodiments differ (e.g., collect with UMI, deploy on Piper), directly record task-space EEF pose during collection.
### Data Distribution
- Current imitation-learning-based models perform more reliably in previously seen scenarios. In early-stage experiments, start with data collection and validation in a limited domain.
- After pipeline validation, gradually expand the domain by varying lighting, object placement, and initial robot poses to improve generalization.
### Scene Consistency
- Keep third-person camera extrinsics fixed and ensure a rigid wrist-camera mount.
- In early experiments, prioritize scene consistency; avoid varying lighting, object placement, or initial robot poses.
### Joint Limits
- If collecting joint-space data, avoid operating near joint limits to reduce the number of samples in those regions.
## 3. Data Preprocessing
Raw data must be cleaned, synchronized, and converted before training.
### Trajectory Filtering
Data filtering is recommended in two stages: script-based filtering and manual review.
#### Script Filtering
- Check image timestamps and remove samples with:
1. Excessive latency in a single camera stream.
2. Excessive timestamp difference between the two camera streams.
- Detect and remove abnormal jumps in robot state sequences.
#### Manual Filtering
Replay trajectories with synchronized visualization to catch issues missed by scripts:
- Remove samples with poor synchronization between image and action sequences.
- Remove blurry frames.
- Remove failed task executions.
- Remove low-quality trajectories (e.g., redundant paths, discontinuous actions).
### Trajectory Preprocessing
1. Timestamp alignment: align camera frames and robot joint states to a shared time base.
2. Head-tail trimming: remove idle segments at the start and end of trajectories.
3. Split long trajectories (several minutes) into multiple subtasks.
### Format Conversion
Convert all data to a standard format (e.g., LeRobot) for GR00T compatibility:
- See the [data preparation guide](data_preparation.md) for format requirements.
- Use the provided conversion scripts to convert data to GR00T LeRobot format.
## 4. VLA Model Training
### Training Parameter Configuration
**Dataset size recommendations**
For single-task `finetune`:
- **Minimum data size**: Prepare at least **100 valid episodes**. For very narrow task domains, ~30 episodes may suffice. A capture frequency of 20–50 Hz is recommended for manipulation tasks.
- **Episode length**: No hard limit, but each episode must contain a complete action cycle with idle frames removed. Split overly long episodes into subtasks.
- **Recommended data size**: 200+ episodes usually provide more stable performance.
**Core parameters**
- **Input/output mode**: Default to `State-relative Action Prediction`. Compared with `Absolute Action`, it converges more easily and improves inter-chunk consistency.
- **Training space**: Both joint space and task space are valid. For low-DoF arms, joint space is often preferred to reduce singularity-related risks.
- **Action Chunk Size**: Default is 16. If combined with RTC to mitigate stop-and-go, set it to at least 32.
- **Batch Size**: Increase the batch size as much as GPU memory allows.
> For additional training options, see the [fine-tuning guide](finetune_new_embodiment.md).
**Compute resources**
- Fine-tuning requires significantly less compute than pretraining.
- You can start on a **single GPU** (40 GB+ VRAM). See the [hardware recommendation guide](hardware_recommendation.md#fine-tuning-hardware) for the minimum and quick-start configurations.
- A single compute node (8 x H100 or 8 x H20) is a **production-scale** setup for faster convergence on larger datasets — not a minimum requirement.
### Validation
After training, run open-loop validation to confirm convergence, then proceed to closed-loop deployment validation.
> Open-loop validation is only a preliminary check. Final performance must be verified with closed-loop testing on real robots. For details, see the [fine-tuning guide](finetune_new_embodiment.md).
## 5. Deployment and Closed-Loop Control
### System Architecture
GR00T supports two inference modes:
1. **Direct `Gr00tPolicy` usage**: Suitable when model inference and robot control run on the same machine.
2. **ZMQ Server-Client architecture**: Suitable for real-world deployment and decouples local robot control (`Local Client`) from remote inference (`Model Server`).
For real-world deployment, **ZMQ inference service** is recommended:
- Move compute-intensive inference to GPU servers.
- Keep robot-side control code lightweight.
- Avoid installing the full inference dependency stack on the robot side.
### On-Device Deployment Logic
Deployment code has two phases: **initialization** and the **main control loop**.
The pseudo-code below uses a synchronous workflow, which may cause stop-and-go. See later sections for mitigation via asynchronous execution + RTC.
**Pseudo-code workflow:**
```python
# ========== Initialization ==========
# 1. Initialize and test cameras
hand_camera = initialize_hand_camera() # e.g., OrbbecSDK
env_camera = initialize_env_camera() # e.g., RealSense
test_cameras() # Show preview and verify normal operation
# 2. Connect and test robot
robot = connect_robot() # e.g., Piper SDK
robot.enable()
robot.reset_to_initial_position()
test_robot() # Send test command and verify robot response
# 3. Connect and test GR00T model server
gr00t_client = connect_to_gr00t_server(host, port)
if not gr00t_client.ping():
raise ConnectionError("Failed to connect to model server")
test_model() # Send test observation and verify inference
# ========== Main control loop ==========
while True:
# 1. Acquire sensor data
hand_image = hand_camera.get_frame()
env_image = env_camera.get_frame()
joint_states = robot.get_joint_states()
gripper_state = robot.get_gripper_state()
# 2. Format observation
observation = format_observation(
hand_image,
env_image,
joint_states,
gripper_state,
task_description,
)
# 3. Model inference (via ZMQ)
actions = gr00t_client.get_action(observation)
# 4. Trajectory post-processing
actions_arm = actions["joint_states"]
actions_arm = smooth_trajectory(actions_arm) # smoothing
actions_arm = check_safety_limits(actions_arm) # safety checks
# 5. Execute actions
for action_step in actions_arm:
robot.execute_action(action_step)
sleep(1.0 / 30.0) # 30 FPS
```
### Key Implementation Notes
**Important notes:**
- **Image format**: Use compressed formats such as JPG to reduce transmission bandwidth.
- **Safe operation**:
- **Soft Limits**: Add joint-angle and EEF pose range checks. If a predicted action exceeds workspace bounds, raise an alarm and stop immediately.
- **E-Stop logic**: Bind an emergency stop hotkey (e.g., Space) on the control PC, or use a physical E-Stop switch.
- **Action smoothing**: Apply interpolation and smoothing to predicted action sequences.
> For more deployment details, see the [policy API guide](policy.md).
## 6. Common Issues: Jittering and Stop-and-Go
The most common issues in real-world deployment are **jittering** and **stop-and-go**.
### Fixing Jittering
**Jittering** here refers to visible shaking or vibration of the end-effector or joints during task execution.
Jittering typically originates from **inconsistent model outputs** or **insufficient robot-side control quality**. Analyze these two components separately to localize the issue. The suggestions below are general guidelines and may not apply to every robot platform or control stack — always verify against your own hardware and environment.
```mermaid
flowchart TD
A[Jittering observed] --> B[Save & visualize action chunks in 3D]
B --> C{Where is the jitter?}
C -->|Inside each chunk| D[Case A: Model undertrained or poor data quality]
C -->|Between consecutive chunks| E[Case B: Inconsistent chunk predictions]
C -->|Chunks look smooth| F[Case C: Robot hardware / low-level control issue]
D --> D1[Add more data, train longer, check train/eval consistency]
E --> E1[Use state-relative actions + RTC chunking strategy]
F --> F1[Check drive control, interpolation, hardware status]
```
**Diagnosis and mitigation**
1. **Save and visualize Action Chunks**
- Save all predicted `Action Chunks`.
- Visualize continuous TCP (tool center point) trajectories in 3D.
- **Note**: Convert joint-space outputs to task space via FK before visualization.
2. **Analyze visualization results**
**Case A: Significant jitter inside each chunk**
- **Cause**: The model is undertrained, or data quality is insufficient.
- **Solution**: Improve data quality, add more training data, or train longer. Keep training and validation environments consistent.
**Case B: Significant jitter between chunks**
- **Cause**: Inconsistent adjacent `Action Chunk` predictions.
- **Solution**:
- Use `State-relative Action Prediction`. Predicting actions relative to the current state produces a more uniform output distribution, making the network easier to train.
- Use RTC (`Real-Time Chunking`) or similar strategies.
**Case C: Little jitter after visualization**
- **Cause**: Likely a robot hardware or low-level control issue.
- **Solution**: Check drive control, interpolation, and hardware status.
**Quantitative diagnostic metrics**
Trajectory jitter can also be quantified using these three metrics:
**Metric 1: Mean intra-chunk acceleration magnitude**
Measures intra-chunk smoothness. Only valid under fixed sampling frequency.
Formula: $a_t = pos_{t+1} - 2 \cdot pos_t + pos_{t-1}$
```python
def metric_intra_accel(chunks):
"""
Args:
chunks: numpy array with shape (N_chunks, Chunk_Length, Joint_Dim)
Returns:
float: Mean acceleration magnitude
"""
velocity = np.diff(chunks, axis=1) # first-order difference
acceleration = np.diff(velocity, axis=1) # second-order difference
acc_magnitude = np.linalg.norm(acceleration, axis=-1) # L2 norm per step
return np.mean(acc_magnitude)
```
**Metric 2: Position jump at chunk boundary (L2 distance)**
Measures position continuity between chunks by comparing the last executed step of `Chunk[i]` with step 0 of `Chunk[i+1]`.
```python
def metric_boundary_jump(chunks, execute_steps=None):
"""
Args:
chunks: numpy array with shape (N_chunks, Chunk_Length, Joint_Dim)
execute_steps: number of executed steps per chunk; if None, use full chunk length
Returns:
float: Mean position jump
"""
chunks = np.array(chunks)
exec_steps = chunks.shape[1] if execute_steps is None else execute_steps
last_frame_prev = chunks[:-1, exec_steps - 1, :] # last frame of previous chunk
first_frame_curr = chunks[1:, 0, :] # first frame of current chunk
jumps = np.linalg.norm(first_frame_curr - last_frame_prev, axis=-1) # Euclidean distance
return np.mean(jumps)
```
**Metric 3: Cosine similarity of velocity direction at chunk boundary**
Measures velocity-direction consistency between chunks. Values closer to 1 indicate better consistency.
```python
def metric_momentum_shift(chunks, execute_steps=None):
"""
Args:
chunks: numpy array with shape (N_chunks, Chunk_Length, Joint_Dim)
execute_steps: number of executed steps per chunk; if None, use full chunk length
Returns:
float: Mean cosine similarity
"""
chunks = np.array(chunks)
exec_steps = chunks.shape[1] if execute_steps is None else execute_steps
# velocity at the end of previous chunk
idx = exec_steps - 1
if idx < 1:
raise ValueError("execute_steps must be >= 2 to compute end velocity")
v_end = chunks[:-1, idx, :] - chunks[:-1, idx - 1, :]
# velocity at the start of current chunk
v_start = chunks[1:, 1, :] - chunks[1:, 0, :]
# cosine similarity
dot_product = np.sum(v_end * v_start, axis=-1)
norm_prev = np.linalg.norm(v_end, axis=-1)
norm_curr = np.linalg.norm(v_start, axis=-1)
epsilon = 1e-8
cosine_sim = dot_product / (norm_prev * norm_curr + epsilon)
return np.mean(cosine_sim)
```
### Fixing Stop-and-Go
Stop-and-Go here refers to a behavior in which the robot intermittently pauses during motion, producing periodic stop-and-go behavior.
#### Root Cause
In **synchronous single-step closed-loop** control, stop-and-go occurs when the **end-to-end latency** (observation capture → VLA inference → action conversion) exceeds control-frequency requirements.
- **Control-frequency requirement**: At 30 FPS, latency must stay below ~33 ms.
- **Typical latency sources**: Data capture, network transfer, model inference, and post-processing often exceed 33 ms combined.
- **Consequence**: The next prediction is not ready when the current action finishes, causing pauses.
#### Solutions
**Option 1: Optimize the inference pipeline (direct but difficult)**
Reduce full workflow latency below 33 ms:
- Optimize network bandwidth (reduce transfer time).
- Use edge inference (reduce network latency).
- Quantize the VLA model (speed up inference).
- Use a smaller model (e.g., ACT).
**Limitation**: For VLA models, meeting strict real-time requirements through optimization alone is often impractical.
**Option 2: Use algorithmic scheduling strategies (recommended)**
When direct optimization is insufficient, use one or more of the following:
- **Asynchronous Inference**: A background thread runs inference while the main thread executes actions.
- **Receding Horizon**: Execute only the first few steps of each `Action Chunk` before triggering a new inference.
- **Temporal Ensemble**: Aggregate predictions across multiple timesteps.
- **Real-Time Chunking (RTC)**: Overlap the start of the current prediction with unexecuted steps from the previous one.
**Recommended strategy**: `Asynchronous Inference + RTC` is usually the most effective.
> **RTC status (experimental):** Asynchronous inference is supported today. RTC is currently only a low-level model primitive: `action_head.get_action(..., options={"rtc_overlap_steps": ..., "rtc_frozen_steps": ..., "rtc_ramp_rate": ...})` with the previous action fed back in (`gr00t/model/gr00t_n1d7/gr00t_n1d7.py`). It is **not wired into `Gr00tPolicy` or the server-client path** (there `options` is currently unused), and it has no tests or ready-made example — so the RTC steps below require manual integration.
#### Real-Time Chunking (RTC) Details
**Principle**
RTC treats action prediction as an inpainting problem: overlapping the start of the new prediction with unexecuted steps from the previous one ensures smooth transitions.
**Applicability**
- Validated for **diffusion / flow-based** VLA policies.
- Requires `Action Chunk` length ≥ 32 steps.
- Should be combined with asynchronous inference.
**Implementation essentials**
1. **Predict longer Action Chunks**:
- Increase from the default 16 steps to at least 32.
- Provide a larger soft fusion window.
2. **Asynchronous inference architecture**:
- **Background thread**: Continuously infer, capture observations, and prepare action batches.
- **Main thread**: Execute the current action sequence.
- Buffer predictions in a queue to avoid blocking.
3. **Action fusion mechanism**:
- Use RTC for soft fusion in the overlap region.
- Ensure smooth transitions between adjacent chunks.
**Pseudocode: Async Inference + RTC**
In the RTC (Real-Time Chunking) framework, two key parameters control how adjacent action chunks overlap and transition:
- **`overlap`**: The number of action steps retained from the previous prediction to constrain the current one, ensuring temporal consistency between consecutive chunks.
- **`frozen`**: The number of steps that remain completely frozen (i.e., not updated by the new prediction), typically set to match the inference latency.
Below is a simplified async inference + RTC loop. Note that official RTC support for GR00T is coming soon; the current implementation may require manual adaptation.
```
actions = policy.infer(obs) # blocking first call
loop:
for i in range(action_horizon):
if i == action_horizon - overlap - 1:
future = async policy.infer(new_obs) # non-blocking
robot.execute(actions[i])
if i == action_horizon - frozen - 1:
actions = future.get() # swap in next chunk
break # discard frozen tail
```
|