异构机器人数据源统一接口的设计思路: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 / .mov | 24-60 fps |
| VR 手部追踪 | Quest Pro、Vision Pro、PICO 4U | 自定义二进制 / JSON 帧 | 60-90 Hz |
| 动作捕捉(MoCap) | OptiTrack、Vicon、Xsens | .bvh / .fbx / .c3d | 120-240 Hz |
| 机器人遥操作轨迹 | URDF + teleop SDK | HDF5 / pickle / RLDS | 10-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_id | UUID v4 格式,非空 |
language.instruction | 非空字符串,长度 5-500 |
language.language_code | ISO 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.pov | Internal alpha | 4-6 周内 |
toolkit.vr | Internal alpha | 4-6 周内 |
toolkit.mocap | Design finalized | 8-10 周内 |
toolkit.core (Task/Schema) | Stable | 2-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. 参考文献
- Open X-Embodiment / RT-X Collaboration. Open X-Embodiment: Robotic Learning Datasets and RT-X Models.
robotics-transformer-x.github.io - OpenVLA. An Open-Source Vision-Language-Action Model.
openvla.github.io - Physical Intelligence. π0: A Vision-Language-Action Flow Model for General Robot Control.
pi.website/blog/pi0 - DROID: A Large-Scale In-the-Wild Robot Manipulation Dataset.
droid-dataset.github.io - NVIDIA GR00T N1. arxiv.org/abs/2503.14734
- NVIDIA SONIC. nvlabs.github.io/GEAR-SONIC
- USC Ψ₀ (Psi-Zero). psi-lab.ai/Psi0
- AdaMorph: Cross-Morphology Retargeting. arxiv.org/abs/2601.07284
- OmniRetarget: Interaction-Preserving Data Generation for Humanoids. omniretarget.github.io
- 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