接上文>>>

1.4 完整实现:ReKep关键点提议的实现细节和ReKep生成

为了使系统能够在野外执行任务并给出自由形式的任务指令,设计了一个使用大型视觉模型和视觉-语言模型的管道,用于关键点提议和ReKep生成,分别讨论如下:

1.4.1 关键点提议:最终选中DINOv2来提取特征

给定一个RGB图像

  1. 首先从DINOv2 [Dinov2: Learning robust visual features without supervision]中提取逐块特征

  2. 然后执行双线性插值,将特征上采样到原始图像大小,

  3. 为了确保提案覆盖场景中的所有相关对象,他们使用Segment Anything (SAM) 「其对应论文为:Segment anything,且此文《SAM(分割一切)——图像分割的大变革:从SAM、FastSAM、MobileSAM到SAM2》有介绍]」提取场景中的所有掩码

  4. 对于每个掩码,使用k-均值聚类算法对掩码特征进行聚类,k= 5,使用余弦相似度度量 聚类的质心用作关键点候选,通过校准的RGB-D相机投影到世界坐标R3,距离其他候选点在8厘米以内的候选点会被过滤掉

总体而言,他们发现该过程能够识别出大量细粒度和语义上有意义的对象区域

总之,对于每个平台,使用安装的RGB-D相机之一捕捉尺寸为 h × w × 3的图像,具体取决于哪台相机具有最佳的整体视图,因为所有关键点都需要在第一帧中出现以便使用所提出的方法。给定捕捉的图像
首先使用带有寄存器的DINOv2 (ViT-S14) [5, 137] 提取补丁特征
然后执行双线性插值,将特征上采样到原始图像大小,
为了确保提案覆盖场景中的所有相关对象,使用 Segment Anything (SAM) [132] 提取场景中的所有掩码
在每个掩码mi中,应用 PCA 将特征投影到三维, 发现应用 PCA 改善了聚类,因为它通常会去除与纹理相关的细节和伪影——这些对的任务没有用处
对于每个掩码j,使用k-均值聚类算法对掩码特征 进行聚类,其中k= 5,使用欧几里得距离度量。聚类的中位质心被用作关键点候选,并通过校准的RGB-D相机投影到世界坐标系R3中 请注意,还存储了哪些关键点候选来自同一个掩码,这在第1.3节描述的优化循环中的刚性假设部分会用到。超出工作空间边界的候选会被过滤掉 为了避免在小区域内出现许多杂乱的点,还使用均值漂移[138, 139] (带宽为8厘米)来过滤彼此接近的点,最后,质心被作为最终候选

打开网易新闻 查看精彩图片

  • SAM + DINOv2

  • SAM + CLIP(视觉-语言对比预训练)

  • SAM + ViT(监督预训练)

  • 仅DINOv2,自监督预训练

可以看到,得到的结果为

  1. SAM提供的对象性先验对于将关键点提议约束在场景中的物体上而不是背景上至关重要

  2. 虽然大多数视觉基础模型可以提供有用的指导,但DINOv2产生的特征更为清晰,可以更好地区分物体的细粒度区域 比如CLIP在不同物体部件之间提供了不同的特征,但这些特征不如DINOv2的清晰(颜色从一个部件到另一个部件逐渐饱和)

  3. 另一方面,ViT在物体部件之间产生的特征最不明显。物体部件,尤其是当纹理相似时

总体而言,观察结果与其他也应用DINOv2进行细粒度物体理解的工作一致

1.4.2 ReKep生成

在获得关键点候选后

  1. 将它们覆盖在原始RGB图像上,并用数字标记(After obtaining the keypoint candidates, we overlay them on the original RGB image with numerical marks)

  2. 结合任务的语言指令,然后使用视觉提示来查询GPT-4o,以生成所需阶段的数量和相应的子目标约束 和每个阶段 的路径约束 「Coupled with the language instruction of the task, we then use visual prompting to query GPT-4o [6,Gpt-4 technical report] to generate the number of required stages and the corresponding sub-goal constraints C(i)sub-goal and path constraints C(i) path for each stage i (prompts are in A.6).」

    值得注意的是,这些函数不会直接操作关键点位置的数值。相反,利用VLM的优势,通过算术运算(如关键点之间的L2距离或点积)来指定空间关系,这些运算仅在使用专门的3D跟踪器跟踪的实际关键点位置时才会实例化Notably,the functions do not directly manipulate the numerical values of the keypoint positions. Rather, we exploit the strength of VLM to specify spatial relations as arithmetic operations, such as L2 distance or dot product between keypoints, that are only instantiated when invoked with actual keypoint po-sitions tracked by a specialized 3D tracker.

  3. 此外,使用一组关键点位置进行算术运算的一个重要优势是,当提供足够的点并在相关点之间强制刚性时,它可以在完整的SO(3)中指定3D旋转,但这仅在根据任务语义需要时才会进行Furthermore, an important advantage of using arithmetic operations on a set of keypoint positions is that it can specify 3D rotations in full SO(3) when suf-ficient points are provided and rigidity between relevant points is enforced, but this is done only when needed depending on task semantics3.

    这使得VLM能够在3D笛卡尔空间中通过算术运算来推理3D旋转,有效地避免了处理替代3D旋转表示和执行数值计算的需要This enables VLM to reason about 3D rotations witharithmetic operations in 3D Cartesian space, effectively circumventing the need for dealing with alternative 3D rotation representation and the need for performing numerical computation

总之,在获得关键点候选后
它们被覆盖在捕获的RGB图像上,并用数字标记
然后将图像和任务指令输入到带有以下描述提示的视觉语言模型中。提示仅包含通用指令,没有图像-文本上下文示例,尽管提供了一些基于文本的示例来具体解释所提出的方法和模型的预期输出 请注意,大多数研究的任务在提供的提示中没有讨论。因此,VLM的任务是利用其内化的世界知识生成ReKep约束
在本研究中进行的实验中,使用了GPT-4o [6],因为它是实验时可用的最新模型之一 然而,由于该领域的快速进展,该流程可以直接从具有更好视觉语言推理能力的更新模型中受益 相应地,观察到不同的模型在给定相同提示时表现出不同的行为(观察到更新的模型通常需要更少的细粒度指令) 因此,他们不再致力于为本工作的任务套件开发最佳提示,而是专注于展示一个全栈管道,该管道包含一个关键组件,可以通过未来的开发实现自动化和持续改进

1.5 ReKep完整示例:针对「1.4节关键点提议和ReKep生成」

1.5.1 倒茶等任务的阶段动作及其对应的子目标约束、路径约束

以下是倒茶、折叠袖子、折叠夹克等任务的阶段目标,及其对应的子目标约束、路径约束

## 说明
假设你通过编写Python约束函数来控制机器人执行操作任务。操作任务以环境图像的形式给出,图像上覆盖了标有索引的关键点,以及文本说明。
说明以括号开头,指示机器人是单臂还是双手。对于每个给定的任务,请执行以下步骤:
- 确定任务涉及多少个阶段。抓取必须是一个独立的阶段。一些例子:
- "(单臂)从茶壶倒茶":
- 3个阶段:"抓住茶壶","将茶壶对准杯口",和"倒液体"


- "(单臂)将红色积木放在蓝色积木上":
- 3个阶段:“抓住红色积木”、“将红色积木对齐在蓝色积木上方”和“释放红色积木”


- “(双手)将袖子折叠到中间”:
- 2个阶段:“左臂抓住左袖子,右臂抓住右袖子”和“两臂将袖子折叠到中间”


- “(双手)折叠夹克”:
- 3个阶段:“左臂抓住左袖子,右臂抓住右袖子”、“两臂将袖子折叠到中间”和“一只手抓住领口(另一只手保持原位)”,以及“将领口对齐到底部”


- 对于每个阶段,写出两种约束,“子目标约束”和“路径约束”。“子目标约束”是在阶段结束时必须满足的约束,而“路径约束”是在阶段内必须满足的约束。一些例子:
- “(单臂)从茶壶倒液体”:
- "抓住茶壶"阶段:
- 子目标约束: "将末端执行器与茶壶把手对齐"
- 路径约束: 无


- "将茶壶与杯口对齐"阶段:
- 子目标约束: "茶壶嘴需要在杯口上方10厘米"
- 路径约束: "机器人正在抓住茶壶", 并且"茶壶必须保持直立以避免洒出"


- "倒液体"阶段:
- 子目标约束: "茶壶嘴需要在杯口上方5厘米", "茶壶嘴必须倾斜以倒出液体"
- 路径约束: "茶壶嘴直接在杯口上方"


- “(双手)将袖子折叠到中间”:
- "左臂抓住左袖,右臂抓住右袖"阶段:
- 子目标约束: "左臂抓住左袖", "右臂抓住右袖"
- 路径约束: 无


- "双臂将袖子折叠到中心"阶段:
- 子目标约束: "左袖与中心对齐", "右袖与中心对齐"
- 路径约束: 无

1.5.2 约束的注意事项

注意:
- 每个约束接受一个虚拟末端执行器点和一组关键点作为输入,并返回一个数值成本,当成本小于或等于零时,约束被满足。
- 对于每个阶段,你可以编写0个或多个子目标约束和0个或多个路径约束。
- 在你的约束中避免使用“if”语句。
- 在操作可变形物体(例如,衣物、毛巾)时避免使用路径约束。
- 你不需要考虑碰撞避免。专注于完成任务所需的内容。


- 约束的输入如下:
- `end_effector `: np.array of shape `(3,) ` 表示末端执行器的位置。
- `keypoints `: np.array of shape `(K, 3) ` 表示关键点的位置。
- 在每个函数内部,你可以使用原生Python函数和NumPy函数。
- 对于抓取阶段,你应该只编写一个将末端执行器与关键点关联的子目标约束。不需要路径约束。
- 对于非抓取阶段,不应参考末端执行器的位置。
- 为了移动一个关键点,其关联的物体必须在前一个阶段之一被抓取。
- 机器人一次只能抓取一个物体。
- 抓取必须是独立于其他阶段的阶段。
- 您可以使用两个关键点形成一个向量,该向量可用于指定旋转(通过指定向量与固定轴之间的角度)。
- 您可以使用多个关键点来指定一个表面或体积。
- 您也可以使用多个关键点的中心来指定一个位置。
- 单个折叠动作应包括两个阶段:一个抓取和一个放置

1.5.3 将ReKep生成转化成Python代码

其对应的代码如下

Structure your output in a single python code block as follows for single-arm robot:
```python
# Your explanation of how many stages are involved in the task and what each stage is about.
# ...
num_stages = ?
### stage 1 sub-goal constraints (if any)
def stage1_subgoal_constraint1(end_effector, keypoints):
"""Put your explanation here."""
...
return cost
# Add more sub-goal constraints if needed
### stage 1 path constraints (if any)
def stage1_path_constraint1(end_effector, keypoints):
"""Put your explanation here."""
...
return cost
# Add more path constraints if needed
# repeat for more stages
...
```
Structure your output in a single python code block as follows for bimanual robot:
```python
# Your explanation of how many stages are involved in the task and what each stage is about.
# ...
num_stages = ?
### left-arm stage 1 sub-goal constraints (if any)
def left_stage1_subgoal_constraint1(end_effector, keypoints):
"""Put your explanation here."""
...
return cost
### right-arm stage 1 sub-goal constraints (if any)
def right_stage1_subgoal_constraint1(end_effector, keypoints):
"""Put your explanation here."""
...
return cost
# Add more sub-goal constraints if needed
### left stage 1 path constraints (if any)
def left_stage1_path_constraint1(end_effector, keypoints):
"""Put your explanation here."""
...
return cost
### right stage 1 path constraints (if any)
def right_stage1_path_constraint1(end_effector, keypoints):


"""Put your explanation here."""
...
return cost
# Add more path constraints if needed
# repeat for more stages
...
```
## Query
Query Task: "[INSTRUCTION]"
Query Image: [IMAGE WITH KEYPOINTS

以上代码对应的翻译如下

将您的输出结构化为如下所示的单臂机器人单个python代码块:
``` python
# 您对任务涉及的阶段数量及每个阶段内容的解释。
# ...
num_stages = ?
### 阶段1子目标约束(如果有)
def stage1_subgoal_constraint1(end_effector, keypoints):
"""在这里放置你的解释。"""
...
返回成本
# 如果需要,添加更多子目标约束
### 阶段1路径约束(如果有的话)
def stage1_path_constraint1(end_effector, keypoints):
"""在这里放置你的解释。"""
...
返回成本
# 如果需要,添加更多路径约束
# 重复更多阶段
...
```
将你的输出结构化为如下的双手机器人代码块:
``` python
# 您对任务涉及的阶段数量及每个阶段内容的解释。
# ...
num_stages = ?
### 左臂阶段1子目标约束(如果有的话)
def left_stage1_subgoal_constraint1(end_effector, keypoints):
"""在这里放置你的解释。"""
...
返回成本
### 右臂阶段1子目标约束(如果有的话)
def right_stage1_subgoal_constraint1(end_effector, keypoints):
"""在这里放置你的解释。"""
...
返回成本
# 如果需要,添加更多子目标约束
### 左臂阶段1路径约束(如果有的话)
def left_stage1_path_constraint1(end_effector, keypoints):
"""在这里放置你的解释。"""
...
返回成本
### 右臂阶段1路径约束(如果有的话)
def right_stage1_path_constraint1(end_effector, keypoints)


"""在这里放置你的解释。"""
...
返回成本
# 如果需要,添加更多路径约束
# 重复更多阶段
...
```
## 查询
查询任务: "[指令]"
查询图像: [带有关键点的图像]

除了以上,更多机器人相关见七月在线的《大模型机器人二次开发线下营》

↓↓↓扫码了解课程↓↓↓

课程咨询可找苏苏老师VX:julyedukefu008或七月在线其他老师