AI 平台/部署

GR00T 模型真机部署指南

本指南用于帮助用户搭建完整的真机实验环境,覆盖视觉-语言-动作(VLA)模型从数据采集、训练到部署的完整流程。文档聚焦工程实践,提供可直接落地的配置建议与实现要点。

概述

GR00T 真机部署实验主要包含以下步骤:

  1. 硬件准备:确认机器人平台、传感器与算力资源就绪。
  2. 数据采集:选择合适的遥操作设备,采集至少 100 条有效 episode。
  3. 数据预处理:清洗数据、同步时间戳,并转换为 LeRobot 格式。
  4. 模型训练:使用 GR00T N1.6 进行微调。
  5. 模型评估:执行开环评估,验证模型收敛与性能。
  6. 部署准备:搭建 ZMQ Server-Client 架构。
  7. 闭环测试:在真机执行闭环控制,监控抖动与停顿问题。
  8. 问题优化:根据实测结果调整 RTC 参数与动作平滑策略。

1. 硬件与环境准备(Device Requirements)

开始前请确认机器人硬件、传感器链路与控制接口均稳定可用。

机器人平台

  • 推荐平台:支持 SDK 控制的机械臂(如 Franka、UR、Piper、SO101 等)
  • 基本要求
    • 具备实时关节状态反馈
    • 支持高频率动作执行(推荐 30 FPS)
    • 提供稳定的控制接口

多模态传感器

传感器类型 规格要求 用途
腕部相机(Wrist-mounted) 30 FPS,RGB 采集近场操作视觉信息
第三视角相机(3rd view) 30 FPS,RGB 采集全局场景信息
机器人本体状态 实时采集 关节状态(Joint States)与夹爪开合量

算力资源

  • 训练阶段:推荐使用 NVIDIA 远程 GPU 服务器(如 H100, H20 节点)以支持大 Batch Size 训练
  • 部署阶段:可使用 Jetson AGX Thor 等边缘设备进行实时推理

更多硬件推荐信息,请参考 硬件推荐指南

遥操作设备

选择合适的遥操作设备是保证数据质量的关键。

以下是常见遥操方案对比,其中,

  • 结构依赖性指遥操作端与被控机器人在关节拓扑、自由度和工作空间上的相似要求;依赖性越高,跨本体迁移难度越大。
  • 操作直观度指操作者输入与机器人动作反馈之间的一致程度;直观度越高,通常上手更快、示教误差更低。
方案类型 成本级别(参考) 结构依赖性 操作直观度 适用说明
键盘/手柄/SpaceMouse/Joylo 低:通过按键/映射控制 中:需适应按键与动作映射 入门成本低,适合作为起点或移动场景
主从臂系统(Master-Slave) 高:主从臂需相似运动学与工作空间 高:接近一对一的人机映射 适合单一机型场景,机器人 OEM 常用;可降低采集数据逼近关节限位的概率
UMI / Fast-UMI / Pika Sense 低:硬件无关动作表示,可跨机械臂复用 高:校准后 EEF 跟随较直观 适合训练通用 VLA;低自由度机械臂可能触及关节限位
VR 遥操作(VR-based) 中(头显+渲染+网络) 低:主要依赖软件集成 中:依赖沉浸式视觉反馈与追踪 方案灵活,工程集成成本较高
手套/动捕(Glove / Motion Capture) 高(商业动捕套装+数据手套) 低:通过运动学映射重定向到不同本体 高:全手/全身控制直观 适合全身控制与灵巧手任务
外骨骼(Exoskeleton) 高:通常要求关节结构一致 高:动作对应关系自然 可扩展到人形机器人多关节控制

2. 数据采集方案(Data Collection)

以下是采集时的一些要点。

时间戳同步(Timestamp Synchronization)

  • 两路相机图像采集帧率(FPS)需严格一致,且触发时机尽量同步。
  • 机械臂关节状态采集频率应高于相机采集频率,以支持后续准确下采样。
  • 采集阶段需完整记录时间戳,用于后续时序对齐。

动作表示(Action Representation)

  • 若训练目标与采集设备异构(如采集使用主从臂),采集阶段可记录关节空间 Joint States。若训练目标为任务空间模型,可在后处理阶段通过正向运动学(FK)计算末端执行器位姿(EEF Pose)。
  • 若训练目标与采集设备异构(如采集使用 UMI、部署使用 Piper),建议在采集阶段直接记录任务空间 EEF Pose

数据分布(Data Distribution)

  • 当前模型主要基于模仿学习,在已见场景中的表现通常更稳定。建议在实验初期先在受限域(limited domain)内采集并验证。
  • 完成基础流程验证后,可逐步扩大采集域,通过增加光照条件、物体位置、机械臂初始位姿等随机性提升泛化能力。

场景一致性(Scene Consistency)

  • 确保第三视角相机位姿固定,腕部相机与机械臂连接稳固。
  • 在实验初期应优先保证场景一致性,避免光照、物体位置、机械臂初始位姿等因素发生随机变化。

关节极限(Joint Limits)

  • 若采集关节空间数据,应避免接近机械臂关节极限位姿,减少逼近 Joint Limit 的样本。

3. 数据预处理(Data Preprocessing)

原始采集数据需经清洗、同步与格式转换后方可用于训练。

轨迹过滤

数据过滤建议分为两个阶段:脚本自动筛选与人工复核。

脚本筛选

  • 检查图像时间戳,剔除以下数据:
    1. 单个相机延迟过大的数据
    2. 两个相机拍照时间戳差异过大的数据
  • 检测并剔除机械臂状态数据中的异常跳变

人工筛选

通过轨迹回放并同步可视化采集图像,剔除脚本未覆盖的低质量数据:

  • 剔除相机序列与动作序列同步较差的数据
  • 剔除画面模糊的数据
  • 剔除任务执行失败的案例
  • 剔除低质量轨迹(如路径冗余、动作不连贯等)

轨迹预处理

  1. 时间戳同步:确保相机图像与机械臂关节状态在同一时间基准下对齐。
  2. 首尾裁剪:移除轨迹首尾的静止片段及无关干扰动作。

格式转换

统一转换为标准格式(如 LeRobot),以适配 GR00T:

  • 参考 数据准备指南 获取详细格式要求。
  • 使用项目提供的转换脚本,将数据转换为 GR00T LeRobot 格式。

4. VLA 模型训练(VLA Training)

训练参数配置

数据量建议

对于单任务 finetune

  • 最小数据量:建议至少准备 100 条有效 episode。若任务 domain 极小,实测 30 条数据也可获得可行结果。
  • 推荐数据量:200+ 条 episode 通常可获得更稳定的性能。

核心参数

  • 输入输出模式:推荐默认的 State-relative Action Prediction。相较 Absolute Action,该模式更易收敛,且相邻 Action Chunk 一致性更好。
  • 训练空间:关节空间与任务空间均可。对低自由度机械臂,建议优先使用关节空间以减少奇异位姿风险。
  • Action Chunk Size:默认推荐 16。若结合 RTC 缓解 Stop-and-Go问题,建议至少设置为 32。
  • Batch Size:在显存允许范围内尽量增大。

更多训练配置选项,请参考 微调指南

计算资源

  • 微调(Finetune)所需计算资源远小于预训练(Pretrain)。
  • 对于微调,单个计算节点(8 × H100 或 8 × H20)通常已足够。

效果验证

模型训练完成后,建议先执行开环验证,确认模型收敛与训练充分性,再进行闭环部署验证。

开环验证仅作为训练收敛和模型有效性的初步评估,最终效果需在机器人上进行闭环验证。详细流程和脚本用法请参见 微调指南

5. 部署与闭环控制(Deployment)

系统架构

GR00T 支持两种推理方式:

  1. 直接使用 Gr00tPolicy:适用于模型推理与机器人控制部署在同一主机的场景。
  2. ZMQ Server-Client 架构:适用于真机部署,实现本地控制端(Local Client)与远程推理端(Model Server)解耦。

对于真机部署,推荐使用 ZMQ 推理服务,主要原因如下:

  • 将计算密集型推理任务放在 GPU 服务器执行。
  • 机器人控制端仅需轻量客户端代码。
  • 避免在机器人端安装完整推理依赖。

端侧部署实现逻辑

部署代码可分为两个阶段:初始化阶段(循环外)与主控制循环(循环内)。

以下伪代码采用同步执行流程,因此可能出现 Stop-and-Go 现象。可通过异步执行结合 RTC 策略缓解,详见后续章节。

伪代码流程:

# ========== 初始化阶段 ==========
# 1. 初始化相机并测试
hand_camera = initialize_hand_camera()  # 如 OrbbecSDK
env_camera = initialize_env_camera()    # 如 RealSense
test_cameras()  # 显示预览画面,确保正常工作

# 2. 连接机械臂并测试
robot = connect_robot()  # 如 Piper SDK
robot.enable()
robot.reset_to_initial_position()
test_robot()  # 发送测试指令,确保机械臂响应

# 3. 连接 GR00T 模型服务器并测试
gr00t_client = connect_to_gr00t_server(host, port)
if not gr00t_client.ping():
    raise ConnectionError("无法连接到模型服务器")
test_model()  # 发送测试观察值,确保模型推理正常

# ========== 主控制循环 ==========
while True:
    # 1. 采集传感器数据
    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. 格式化观察值
    observation = format_observation(
        hand_image, env_image, 
        joint_states, gripper_state,
        task_description
    )
    
    # 3. 模型推理(通过 ZMQ)
    actions = gr00t_client.get_action(observation)
    
    # 4. 轨迹后处理
    actions_arm = actions["joint_states"]
    actions_arm = smooth_trajectory(actions_arm)      # 平滑
    actions_arm = check_safety_limits(actions_arm)      # 安全检查
    
    # 5. 执行动作
    for action_step in actions_arm:
        robot.execute_action(action_step)
        sleep(1.0 / 30.0)  # 30 FPS

关键实现要点

注意事项:

  • 图像格式:推荐采集 JPG 等压缩格式,以降低图像传输带宽占用。
  • 安全运行
    • 软限位(Soft Limits):在部署代码中加入关节角与末端位姿阈值检查。若预测动作超出工作空间,系统应立即报警并停止执行。
    • 急停逻辑(E-Stop):必须在上位机键盘绑定一键停机快捷键(如 Space),或配置手持物理急停开关。
  • 动作平滑:对预测动作序列执行插值与平滑处理。

更多部署细节,请参考 策略 API 指南

6. 常见问题:抖动与停顿(Common Issues)

真机部署中最常见的问题是 抖动(Jittering)停顿(Stop-and-Go)

解决抖动(Jittering)

抖动通常由两类因素引起:模型输出不一致机械臂驱动控制链路不完善。为准确定位问题,建议对两部分进行解耦分析。

诊断和解决

  1. 保存并可视化 Action Chunk
    • 保存 VLA 模型预测的全部 Action Chunk
    • 在三维空间可视化连续轨迹的 TCP(工具中心点)位置。
    • 注意:若模型输出为关节空间,需要先通过正向运动学(FK)转换至任务空间再可视化。
  2. 分析可视化结果

    情况 A:Chunk 内部抖动明显

    • 原因:模型在当前任务域(domain)未充分训练,或数据清洗不到位。
    • 解决方案:检查数据,增加该域训练数据或延长训练时长,直到开环验证通过,且保证训练和验证环境保持一致。

    情况 B:Chunk 之间抖动明显

    • 原因:相邻 Action Chunk 预测不一致。
    • 解决方案
      • 使用 State-relative Action Prediction 模式。
      • 采用 RTC(Real-Time Chunking)等策略。

    情况 C:可视化后抖动不明显

    • 原因:问题可能位于机械臂本体或驱动控制系统。
    • 解决方案:检查驱动控制算法、插值功能与硬件状态。

定量诊断指标:

除可视化观察外,可通过以下三个关键指标定量评估轨迹抖动:

指标 1:Chunk 内部平均加速度幅值

用于检测 Chunk 内部是否平滑。以下公式仅支持频率一定下的比较。

计算公式:\(a_t = pos_{t+1} – 2 \cdot pos_t + pos_{t-1}\)

def metric_intra_accel(chunks):
    """
    Args:
        chunks: numpy array, 形状为 (N_chunks, Chunk_Length, Joint_Dim)
    
    Returns:
        float: 平均加速度幅值
    """
    velocity = np.diff(chunks, axis=1)  # 一阶差分得到速度
    acceleration = np.diff(velocity, axis=1)  # 二阶差分得到加速度
    acc_magnitude = np.linalg.norm(acceleration, axis=-1)  # 计算加速度向量的 L2 范数
    return np.mean(acc_magnitude)

指标 2:Chunk 切换瞬间的位置误差(L2 Distance)

用于检测 Chunk 之间的位置连续性,比较 Chunk[i] 的最后一个执行步与 Chunk[i+1] 的第 0 步。

def metric_boundary_jump(chunks, execute_steps=None):
    """
    Args:
        chunks: numpy array, 形状为 (N_chunks, Chunk_Length, Joint_Dim)
        execute_steps: 实际执行步数,如果为 None 则使用整个 chunk 长度
    
    Returns:
        float: 平均位置跳变
    """
    chunks = np.array(chunks)
    exec_steps = execute_steps if execute_steps else chunks.shape[1]
    
    last_frame_prev = chunks[:-1, exec_steps - 1, :]  # 前一个 chunk 的最后一帧
    first_frame_curr = chunks[1:, 0, :]  # 当前 chunk 的第一帧
    jumps = np.linalg.norm(first_frame_curr - last_frame_prev, axis=-1)  # 欧几里得距离
    return np.mean(jumps)

指标 3:Chunk 切换瞬间的速度方向余弦相似度

用于检测 Chunk 之间的速度方向一致性。返回值越接近 1,表示速度方向越一致。

def metric_momentum_shift(chunks, execute_steps=None):
    """
    
    Args:
        chunks: numpy array, 形状为 (N_chunks, Chunk_Length, Joint_Dim)
        execute_steps: 实际执行步数,如果为 None 则使用整个 chunk 长度
    
    Returns:
        float: 平均余弦相似度
    """
    chunks = np.array(chunks)
    exec_steps = execute_steps if execute_steps else chunks.shape[1]
    
    # 获取前一个 Chunk 结束时的速度向量
    idx = exec_steps - 1
    v_end = chunks[:-1, idx, :] - chunks[:-1, idx - 1, :]
    
    # 获取当前 Chunk 开始时的速度向量
    v_start = chunks[1:, 1, :] - chunks[1:, 0, :]
    
    # 计算余弦相似度
    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)

解决停顿(Stop-and-Go)

问题现象

机械臂在执行连续动作过程中出现间歇性停顿,随后恢复执行,表现为周期性停顿。

问题原因

同步单步闭环控制(每次执行前都等待新预测)中,从观测采集、VLA 模型推理到转换为机械臂可执行 Action Chunk总延迟超过控制频率要求,会导致停顿。

  • 执行频率要求(同步单步闭环场景):对于 30 FPS 控制频率来说, 对应延迟需小于 33 ms。
  • 实际延迟来源:数据采集、网络传输、模型推理、数据处理等环节叠加后,总延迟常超过 33 ms。
  • 直接结果:当前动作执行结束时,下一轮预测尚未就绪,导致停顿。

解决方案

方案 1:优化推理工作流(直接但难度较高)

在同步单步闭环场景下,尝试将整个推理工作流优化到 33 ms 以内:

  • 优化网络带宽(减少数据传输时间)
  • 使用边缘推理(减少网络延迟)
  • 对 VLA 模型进行量化(加速推理)
  • 使用更小规模模型(如 ACT)

局限性:对于 VLA 模型,工作流通常难以优化至实时要求。

方案 2:使用替代算法策略(推荐)

当直接优化无法满足要求时,可采用以下算法策略:

  • Asynchronous Inference(异步推理):后台线程持续推理,主线程负责动作执行。
  • Receding Horizon(滚动时域):仅执行 Action Chunk 前若干步后重新推理。
  • Temporal Ensemble(时间集成):对多个时间步预测进行集成。
  • Real-Time Chunking(RTC,实时分块):强制当前预测前几步与上一轮未执行动作重叠。

推荐策略Asynchronous Inference + RTC 的组合通常最有效。

实时分块 (RTC, Real-Time Chunking) 详解

原理

RTC 将动作预测视为动作修复(Inpainting)问题,通过约束当前预测前几步与上一轮未执行动作重叠,保证轨迹平滑切换。

适用条件

  • RTC 目前被提出并验证为适用于 diffusion / flow-based 的 VLA 策略。
  • 需要预测更长的 Action Chunk(至少 32 步)。
  • 需要与异步推理配合使用。

实现要点

  1. 预测更长的 Action Chunk
    • 将默认 16 步提升至至少 32 步。
    • 提供更大的软融合窗口。
  2. 异步推理架构
    • 后台线程:持续执行模型推理,采集观测并准备下一批动作。
    • 主线程:执行当前动作序列。
    • 使用队列缓冲预测结果,避免阻塞。
  3. 动作融合机制
    • 通过 RTC 在重叠区域(overlap region)执行软融合。
    • 确保相邻 chunk 之间平滑过渡。

标签