枢纽
机器人Shadow Hand

UniDexGrasp:把灵巧手抓取拆成「先想好怎么抓,再执行」

Yinzhen Xu、Weikang Wan、Jialiang Zhang 等(PKU-EPIC,Peking University + 清华 + Stanford + BIGAI)。arXiv:2303.00938, CVPR 2023。 项目页 · 数据集+代码开源 · dexterous灵巧 T11

🧠 一句话心智模型:让一只 26 自由度的 ShadowHand 抓住上千种没见过的物体,不要端到端硬学——把它拆成两段:第一段像人一样「看一眼,脑子里想出好几种抓法」(生成 diverse 的抓取姿态);第二段给一个目标姿态,「照着这个目标把动作做出来」。两段各司其职,灵巧手才第一次在「通用抓取」上跑过 60% 成功率。

🎯 为什么重要:灵巧手的「通用化」关卡

平行夹爪(两指)抓取已经被攻下:GraspNet-1Billion 等工作能在上千类物体上稳定抓。但灵巧手(五指、20+ DoF)一直是块硬骨头:

核心矛盾:平行夹爪只有 7 DoF,抓法相对单一;ShadowHand 有 26 DoF——既是它灵活的来源,也是它学不动的根源。抓取姿态空间 = SO(3) 旋转 × R³ 平移 × R²² 关节角,是个高维到爆炸的混合空间。在此之前,没有任何方法能在「真实视觉输入 + 跨数百类物体」的设定下做到通用。

UniDexGrasp 是第一个在这条「真·通用灵巧抓取」赛道上跑通的 pipeline:133 类、5519 个物体实例、超过 100 万条抓取数据,最终在未见类别上仍有 66% 的成功率。

平行夹爪(成熟) 7 DoF · 抓法单一 · GraspNet 已攻下 通用抓取 ✓ 灵巧手(困难) 26 DoF(ShadowHand) · 姿态空间 SO(3)×R³×R²² · 抓法多解、要 diverse · 执行轨迹复杂 之前无通用解 UniDexGrasp ✅ 两段式通用 pipeline · 133 类 / 5519 实例 · 未见类别 66% 成功 · 首次「通用化」 突破
图 1:从平行夹爪(已成熟)到灵巧手(之前做不动),UniDexGrasp 是第一个把灵巧抓取推到「通用」级别的工作。

💡 核心思想:偷师平行夹爪的「两段式 pipeline」

平行夹爪抓取为什么能做通用?因为它把任务解耦成两段:「提议抓取姿态」+「执行」。UniDexGrasp 把同样的范式搬到灵巧手——但每一段都得解决灵巧手特有的难题。

深度点云 X₀ (物体+桌) Stage 1:抓取姿态生成(多解) GraspIPDF p(R|X₀) on SO(3) canonicalize GraspGlow p(t,q|X̃₀) NF → ContactNet 物理优化(penetration/contact) Stage 2:目标条件执行 Teacher (PPO) oracle 状态 + 课程 Student (DAgger) 仅视觉 + 本体感觉 三大创新:状态对齐 + 物体课程 + 分类辅助 SO(2) 等变 / 单物→类→多类 / PointNet 联合训
图 2:UniDexGrasp 的两段式 pipeline。Stage 1 用 IPDF(旋转)+ Glow(平移+关节)解耦建模,生成 diverse 的抓取目标;Stage 2 用「老师-学生」+ 课程学习,学会「照目标去抓」的视觉策略。

Stage 1 的关键巧思:抓取姿态 = 旋转 $R$ + 平移 $t$ + 关节角 $q$。直接用 normalizing flow 建模 $p(R, t, q | X_0)$ 会因为 SO(3) 拓扑特殊而崩。论文把它拆开:用 GraspIPDF(基于 ImplicitPDF)专管 $p(R|X_0)$,再用 GraspGlow(基于 Glow)管 $p(t, q | X_0, R)$。这一拆,既能在 SO(3) 上正确建模,又能生成多模态的抓法(CVAE 会 mode-collapse 成一种,flow 不会)。

🛠️ Stage 2 的三大创新:让「跨类通用」的视觉策略能学出来

光有一个好目标姿态还不够——第二段「照着目标抓」的视觉策略极难学。RL 直接训只会失败。论文给出三个互相配合的关键设计:

设计心智为什么必要
① 状态对齐 State Canonicalization把整个场景转到「以手初始朝向为基准」的坐标系,让策略对绕重力轴的旋转等变(SO(2) equivariant)目标条件 + 跨类设定下样本效率极低;等变让「这一圈旋转的训练数据」自动复用到「另一圈」,等价于数据增强 4 倍效果
② 物体课程 Object Curriculum3 阶段:先单物 → 单类 → 多代表类 → 全部类。循序渐进直接在 133 类上训,策略几乎学不出来(success 几乎为 0)。课程让策略先「在简单分布上学懂抓」,再慢慢加难度
③ 老师-学生蒸馏 Teacher-Student先用 PPO 训一个能看 oracle 状态(物体位姿、全点云)的老师;再用 DAgger 把它蒸馏成只看深度+本体感觉的学生真机没有 oracle 状态;但直接从视觉学 RL 几乎不可能。两段式让学生策略站在「老师已学会」的肩膀上
🔮 直觉:为什么要解耦「旋转」和「平移+关节」?
旋转 SO(3) 是个「环面」拓扑——0° 和 360° 是同一个姿态,普通 flow 在欧式空间建模会出现「不连续」和「无穷到一」映射(论文 §B.1.2 详细分析)。IPDF 用「网格 + softmax 归一化」绕开了这个拓扑难题,所以专管旋转;平移和关节角是欧式空间,Glow 直接用就行。把难的部分单独拎出来用对的工具打,这是整个 Stage 1 的灵魂。

📊 结果:未见类别 66%,全面碾压 baseline

维度数字(PDF 溯源)
数据规模1.12M 条合成抓取,覆盖 5519 物体实例 / 133 类(§4.1)。拆分:训练 3251 / 见类未见实例 754 / 未见类 1514
Stage 2 老师(状态)成功率训练集 74%,测试集见类 71%,未见类 66%(Tab.3)
Student(视觉)成功率GT 目标下 68%(train)/ 65%(见类)/ 63%(未见类);用 Stage 1 预测目标 66/59/58%(Tab.4)
vs. 基线PPO 仅 14%,DAPG(模仿)13%;比 ILAD 在 train/test 上分别高 49% / 47%(Tab.3)
消融:去掉课程 OCL成功率从 74% 暴跌到 31%(train)/ 21%(未见类)—— 课程是命脉(Tab.3)
消融:去掉状态对齐 SC74% → 59%(train)—— 等变同样关键(Tab.3)
语言引导抓取(彩蛋)接 CLIP,10 分钟微调后,「抓锤子把柄/抓瓶颈」等指令准确率 ≈90%(§4.4)
整体声明「首次」在千级物体上实现通用灵巧抓取,平均成功率 >60%,generalization gap 很小
关键洞察:单看任何一个 trick(IPDF、Glow、课程、等变、蒸馏)都不算全新,但把它们正确地组装在一起才让灵巧手第一次「通用化」。最值得记的数字:去课程 → 从 74% 跌到 31%;去等变 → 跌到 59%。说明在跨类通用设定下,RL 的样本效率是头号瓶颈,要靠课程+等变一起补

🌐 在领域中的位置

GraspIt! / 解析法(需简化假设) GraspTTA(CVAE,mode collapse) UniDexGrasp(解耦生成 + 蒸馏执行)⭐ UniDexGrasp++ / DexGraspNet / 真机迁移

UniDexGrasp 是灵巧手通用抓取的分水岭:之前的灵巧工作要么假设 oracle 几何,要么只在一两类物体上 demo。它把「跨数百类、纯视觉、目标条件」做成可复现的 pipeline,后续的 DexGraspNet 3D 数据集、UniDexGrasp++、以及诸多真机迁移工作都建立在它确立的两段式范式上。关联线索:T11 灵巧操作

❓ 常见误区

它是端到端从视觉学到抓取的吗?

不是「一个网络端到端」,而是两段式 pipeline。Stage 1 生成目标姿态(生成模型),Stage 2 是目标条件的视觉策略(RL+蒸馏)。而且 Stage 2 内部又分老师(看 oracle)和学生(看视觉)两层。这种「分而治之」恰恰是它能通用的关键。

为什么不用 diffusion 而用 normalizing flow(Glow)?

两个原因:(1) 抓取姿态的旋转部分在 SO(3) 上,diffusion 当时在 SO(3) 上建模还不成熟,IPDF 用网格归一化更直接;(2) normalizing flow 用 NLL 损失,能建模复杂多模态分布,而 CVAE 会 mode-collapse(论文 Fig.4 直观展示了 CVAE 输出全塌成一种)。后续 UniDexGrasp++ 等工作才把 diffusion 引入这一阶段。

它能直接上真机吗?

论文主实验在 IsaacGym 仿真里,但只用深度点云 + 本体感觉(不依赖 oracle 状态),是为真机迁移做的设计。论文本身把「真机迁移」作为 future work;后续工作(如 UniDexGrasp++、DexGraspNet 系列)才完成 sim-to-real。限制:只处理刚体,不处理剪刀之类的铰接物体。

「目标条件 policy」是什么意思?

策略的输入除了当前观察,还有一个「目标抓取姿态 g」(来自 Stage 1)。策略要做的不是「随便抓住」,而是「按 g 指定的方式抓」——比如抓瓶身 vs 抓瓶颈,是两种不同的 g。这让系统能配合语言指令(如「抓锤子把柄」)执行功能性抓取。