|
Download Isaac-GR00T/getting_started/real_world_deployment.md from Timsty/groot_deployment: direct link, hf CLI and curl.
- Browser
- Download file 22.3 kB
-
https://huggingface.co/Timsty/groot_deployment/resolve/main/Isaac-GR00T/getting_started/real_world_deployment.md
- Command line
-
hf download hf://Timsty/groot_deployment/Isaac-GR00T/getting_started/real_world_deployment.md
-
curl -L -o real_world_deployment.md https://huggingface.co/Timsty/groot_deployment/resolve/main/Isaac-GR00T/getting_started/real_world_deployment.md
22.3 kB
| # 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 | |
| ``` | |