异构机器人数据源统一接口的设计思路:menily/toolkit 的架构笔记

0 阅读8分钟

异构机器人数据源统一接口的设计思路:menily/toolkit 的架构笔记

作者:Masashi(Menily Intelligence 创始人) 发布平台:掘金 日期:2026-04 标签:机器人 / Python / 开源项目 / AI 工具链 / 具身智能


TL;DR

这篇是关于 menily/toolkit 这个 Python 库的设计笔记——它解决的问题是:把第一人称视频、VR 手部追踪、动作捕捉(BVH/FBX)、机器人遥操作轨迹这四类完全异构的原始数据,统一转换成 VLA 模型可以直接训练的任务级示教数据格式(menily/schema v1)。

工具库开源在 github.com/MenilyIntelligence/toolkit,目前内部 alpha,PyPI 发布排在接下来几周。

关键设计决策

  • 一个核心抽象 Task + 三个 Adapter(pov / vr / mocap
  • 每个 Adapter 负责把源数据分割 + 标注 + 重采样,最终吐出同构的 Task 对象
  • Schema 验证内置,确保输出严格符合 menily/schema v1 规范
  • 对下游支持 RLDS / HuggingFace Datasets 两种输出格式
  • 设计哲学:一个文件一个任务,每个任务自包含,不依赖共享全局状态

1. 问题陈述:机器人训练数据的四种原始源,格式几乎完全不兼容

做 VLA(vision-language-action)训练数据的团队,通常会接触到这四种原始数据源:

源类型典型设备 / 来源原始格式采样率
第一人称视频(POV)智能手机、GoPro、Vision Pro 录制.mp4 / .mov24-60 fps
VR 手部追踪Quest Pro、Vision Pro、PICO 4U自定义二进制 / JSON 帧60-90 Hz
动作捕捉(MoCap)OptiTrack、Vicon、Xsens.bvh / .fbx / .c3d120-240 Hz
机器人遥操作轨迹URDF + teleop SDKHDF5 / pickle / RLDS10-30 Hz

同一个语义任务(比如"把水从杯子倒进壶里"),用四种不同方式采集时,输出的文件格式、时间戳、坐标系、关节定义完全不同。要把它们一起喂给 VLA 模型训练,需要一套统一的预处理管道。

这就是 menily/toolkit 的设计目标——一套 Python API,覆盖全部四种源,最终都落到同一份 schema 上


2. 核心抽象:Task 对象

整个工具库围绕一个类展开:

from menily.toolkit import Task

class Task:
    """
    一条任务级示教数据的内存表示。
    对应 menily/schema v1 的 TaskLevelDemoV1。
    """
    task_id: str                     # UUID
    language: LanguageField          # 指令 + paraphrase
    visual: VisualField              # 帧路径 + 内参 + 视角
    action: ActionField              # 轨迹 + 时间戳 + 夹爪
    body: BodyField                  # 机体形态 + DoF 映射
    meta: MetaField                  # source / region / time / flags
    
    def save_as(self, schema, out_dir: str) -> Path:
        """序列化为 JSON + 帧目录,符合 menily/schema v1"""
        ...
    
    def to_rlds(self) -> dict:
        """转换为 RLDS 格式(Open X-Embodiment 兼容)"""
        ...
    
    def to_hf_dataset(self) -> "datasets.Dataset":
        """转 HuggingFace Datasets 格式"""
        ...
    
    def validate(self) -> ValidationReport:
        """对照 schema v1 做字段级验证"""
        ...

关键设计:一个 Task 对象 = 一份完整的自包含示教数据。它不依赖外部配置文件、不依赖共享状态,序列化之后即可被任意下游消费。

这个抽象参考了 HuggingFace Datasets 的 DatasetDict 和 TensorFlow TFDS 的 BuilderConfig 模式——对象粒度对应语义粒度,一个 Task 就是一个任务,不是一段帧序列。


3. 三个 Adapter:把异构源转成同构 Task

3.1 toolkit.pov — 第一人称视频适配器

这是使用最多的适配器,典型调用方式:

from menily.toolkit import pov

tasks = pov.segment(
    video_path="./raw/demo_pour_water.mp4",
    language="Pour water from the blue cup into the kettle.",
    language_variants=[
        "把蓝色杯子里的水倒进水壶里",
        "Fill the kettle with water from the blue cup",
    ],
    fps=30,
    viewpoint="ego",
    body_morphology="bimanual_humanoid",
    collection_region="SEA",
)

for task in tasks:
    task.save_as(
        schema="menily.task-demo/1",
        out_dir="./processed/",
    )

内部流程:

mp4 视频
  ↓
帧采样(重采样到目标 fps,默认 30Hz)
  ↓
手部关键点检测(基于 MediaPipe / HaMeR)
  ↓
轨迹重建(关键点 → 末端执行器 6DoF 轨迹)
  ↓
任务分割(基于光流突变 + 动作能量 + 语言对齐)
  ↓
每段 → Task 对象(语言 + 视觉 + 轨迹 + meta)

核心挑战是任务分割。一段 3 分钟的 POV 视频里可能有 5 个子任务(拿起杯子、倒水、放下杯子、擦桌子、走开),分割不准确会严重伤害下游训练。我们用的是三信号加权:光流能量突变 + 关节速度零点 + 语言时间戳锚点。

3.2 toolkit.vr — VR 手部追踪适配器

针对 Quest Pro / Vision Pro 等设备的演示数据:

from menily.toolkit import vr

tasks = vr.from_quest_log(
    log_path="./raw/quest_session_20260414.json",
    language="Assemble the blue widget onto the base plate.",
    fps=60,
    viewpoint="ego",
    body_morphology="bimanual",
    calibration={
        "origin": "room_center",
        "scale_to_robot": 0.9,  # 人手 → 机器人尺寸缩放因子
    },
)

VR 数据的优势是轨迹精度极高(90Hz 原生采样,亚厘米级),劣势是视觉是虚拟场景,下游训练时需要配合 RGB 视频或仿真渲染。toolkit.vr 默认输出只含轨迹 + 虚拟场景 depth,用户需要自己接一个 RGB 渲染管道。

3.3 toolkit.mocap — 动作捕捉适配器

针对 BVH / FBX 格式:

from menily.toolkit import mocap

tasks = mocap.from_bvh(
    bvh_path="./raw/optitrack_session.bvh",
    segmentation_file="./raw/task_segments.json",  # 外部标注
    body_morphology="whole_body_humanoid",
    retarget_to="unitree_g1",   # 自动 retarget 到 Unitree G1 的 DoF 布局
)

MoCap 数据的特殊性在于需要 retargeting——动捕系统采集的是人体骨骼运动,要转成机器人的 DoF 序列。toolkit.mocap 集成了 AdaMorph 和 OmniRetarget 的 retargeting 后端作为可选依赖:

mocap.from_bvh(
    ...,
    retarget_backend="adamorph",     # or "omniretarget", "spark", "custom"
    physics_filter=True,             # 过滤物理不可行动作
)

这一部分直接复用社区已有的 retargeting 研究成果,Menily 不重复造轮子。


4. Schema 验证:内建、严格、可追溯

所有 Task.save_as() 在写磁盘之前强制做一次 schema 验证:

task.validate()
# → ValidationReport(
#     schema_version='menily.task-demo/1',
#     passed=True,
#     warnings=[
#         "language.variants is recommended but empty",
#         "body.link_lengths is recommended but missing"
#     ],
#     errors=[]
# )

字段级约束(来自 menily/schema v1):

字段约束
task_idUUID v4 格式,非空
language.instruction非空字符串,长度 5-500
language.language_codeISO 639-1 两字母代码
visual.fps正浮点数,建议 10-60
visual.viewpoint枚举:ego / third-person / overhead
action.space枚举:ee_6dof / joint_Ndof / whole_body_Mdof
action.trajectory.length必须等于 action.timestamps.length
body.morphology枚举值
body.dof_map非空字典,值为整数列表
meta.source枚举:pov_video / vr_demo / mocap / teleop / sim_generated

验证失败时可以选择三种模式:

task.save_as(schema="menily.task-demo/1", 
             out_dir="./out/",
             on_validation_error="raise")   # 默认,抛异常
             # "skip"   跳过并记录 log
             # "warn"   写警告但仍落盘

5. 和 Open X-Embodiment / RLDS 的对接

menily/schema 定位在任务级语义层,Open X-Embodiment 的 RLDS 定位在轨迹级存储层,两者组合使用的典型 pipeline:

# 从 Menily Task 导出为 RLDS
rlds_episode = task.to_rlds()
# {
#   'steps': [...],         # RLDS 标准格式
#   'episode_metadata': {
#     'language_instruction': task.language.instruction,
#     'language_variants':    task.language.variants,   # RLDS 不标准但保留
#     'body_morphology':      task.body.morphology,
#     'action_space':         task.action.space,
#   }
# }

反向也支持:

from menily.toolkit import from_rlds

tasks = from_rlds(
    rlds_path="./open_x_embodiment/bridge_dataset/",
    task_boundaries="instruction_change",   # 基于 language instruction 切任务
)

这意味着现有任何一份 RLDS 数据(包括整个 Open X-Embodiment 的 60+ 数据集)都可以通过 from_rlds() 反向转成 menily/schema 格式,补全 task-level 的语义信息。

HuggingFace Datasets 也类似:

hf_ds = task.to_hf_dataset()
hf_ds.push_to_hub("MenilyIntelligence/menily-task-demo-sample-v1")

6. 当前状态 + 后续计划

menily/toolkit 当前是 internal alpha。公开 repo 有完整的 API 定义、设计文档、测试用例,但实现部分的某些 adapter 还在完善:

适配器状态PyPI 发布
toolkit.povInternal alpha4-6 周内
toolkit.vrInternal alpha4-6 周内
toolkit.mocapDesign finalized8-10 周内
toolkit.core (Task/Schema)Stable2-3 周内

我们的第一份公开 PyPI 发布会以 toolkit.core 打头(只包含 Task / 验证 / I/O),让下游可以开始用数据结构层;三个 adapter 随后分别发包。


7. 为什么开源

这件事我在做的时候想了很久。

数据工具链这种东西本来是可以当护城河做的——我们采数据,我们用工具处理,我们卖数据给美国的 VLA 实验室,完全闭环。但这样做有两个问题:

  • 第一,schema 只有被用起来才有价值。 如果只有我们一家用,它就不是 schema,是我们的内部格式。
  • 第二,采数据这个赛道的壁垒不在"我有工具",在"我有网络"。 工具是可以开源的,数据采集网络(东南亚分布式数采工厂 + 数千个标注员)才是真正的 scale moat。

所以决定把 schema 和 toolkit 都开源,走 Apache-2.0。真正留给 Menily 自己的,是 菜单里看不到的那部分——数据采集网络 + 客户服务关系


8. 相关资源

资源链接
工具库代码github.com/MenilyIntelligence/toolkit
数据规范github.com/MenilyIntelligence/schema
研究笔记github.com/MenilyIntelligence/research
官方站点menily.ai
schema 设计详解(姊妹文)作者在 CSDN 的《VLA 任务级示教数据 schema 设计笔记》

欢迎在 GitHub Issues 提字段设计、API 设计、命名规范的建议——v1 还是草案,任何意见都会认真对待。


9. 参考文献

  1. Open X-Embodiment / RT-X Collaboration. Open X-Embodiment: Robotic Learning Datasets and RT-X Models. robotics-transformer-x.github.io
  2. OpenVLA. An Open-Source Vision-Language-Action Model. openvla.github.io
  3. Physical Intelligence. π0: A Vision-Language-Action Flow Model for General Robot Control. pi.website/blog/pi0
  4. DROID: A Large-Scale In-the-Wild Robot Manipulation Dataset. droid-dataset.github.io
  5. NVIDIA GR00T N1. arxiv.org/abs/2503.14734
  6. NVIDIA SONIC. nvlabs.github.io/GEAR-SONIC
  7. USC Ψ₀ (Psi-Zero). psi-lab.ai/Psi0
  8. AdaMorph: Cross-Morphology Retargeting. arxiv.org/abs/2601.07284
  9. OmniRetarget: Interaction-Preserving Data Generation for Humanoids. omniretarget.github.io
  10. TWIST2: Portable Full-Body Teleoperation (ICRA 2026). yanjieze.com/TWIST2

10. 关于作者 / Menily Intelligence

Masashi — Menily Intelligence 创始人。UPenn 校友。前次创业为金融数据基础设施方向。

Menily Intelligence(朔月智能)——具身 AI 任务级示教数据的基础设施公司。总部深圳,数据采集网络分布东南亚(马来西亚、菲律宾),湾区设有美国客户运营点。主要服务美国的 VLA 实验室、人形机器人团队、具身智能研究机构。

开源三仓:github.com/MenilyIntelligence — schema / toolkit / research。
联系:Masashi@Menily.AI