1. TableSceneBuilder是场景搭建类

TableSceneBuilder 是 ManiSkill 自带的 Python 类,继承自 SceneBuilder,可以这样导入:

from mani_skill.utils.scene_builder.table import TableSceneBuilder

它负责创建桌面和地面,并提供机器人初始化逻辑。机器人本体的加载仍由环境负责;任务中的方块、目标区域、奖励和成功条件,也需要由任务环境定义。

例如,官方 PushCube-v1 使用它搭建桌面,再额外创建要推动的方块和目标圈。换一个任务,也可以复用同一套桌面布置。参见官方 PushCube 实现。

2. 基本用法:先创建场景,再初始化回合

下面是放在自定义环境类中的核心片段,用来说明调用位置。它省略了任务注册、相机、观测和成功条件等内容,不是可独立运行的完整任务脚本。

import torch
from mani_skill.envs.sapien_env import BaseEnv
from mani_skill.utils.scene_builder.table import TableSceneBuilder


class MyTableEnv(BaseEnv):
    def _load_scene(self, options: dict):
        self.table_scene = TableSceneBuilder(
            env=self,
            robot_init_qpos_noise=0.02,
        )
        self.table_scene.build()
        # 在这里继续创建任务物体,例如方块和目标标记。

    def _initialize_episode(self, env_idx: torch.Tensor, options: dict):
        with torch.device(self.device):
            self.table_scene.initialize(env_idx)
            # 在这里继续设置任务物体的初始位置等状态。

这里有两个层次:MyTableEnv 是环境类,TableSceneBuilder 是环境使用的工具类。self.table_scene 保存工具类的一个实例。

build():创建场景中的对象

build() 通常在环境的 _load_scene() 中调用,创建桌面、地面及对应的物理与视觉对象。

场景创建或重新配置时才需要进行这一步,普通回合重置不需要反复创建桌子。

initialize(env_idx):设置回合起始状态

initialize() 通常在 _initialize_episode() 中调用,设置桌面位姿,以及当前支持的机器人配置对应的初始关节状态和底座位姿。

env_idx 表示本次需要重置哪些并行环境。例如,并行运行多个环境时,可以只重置其中一部分。with torch.device(self.device) 则让块内新建张量默认使用环境所在设备。

robot_init_qpos_noise 控制机器人初始关节配置的随机扰动,不是目标物体的位置噪声,也不能把 0.02 理解成“方块随机移动2厘米”。

这两个步骤分别对应场景创建与回合初始化,完整调用流程可参考官方自定义任务教程。

3. 为什么桌面上的物体可以使用正的 z 坐标?

在本文核对的实现中,桌面表面位于 z = 0,z 轴正方向向上,位置单位为米。这是场景布置采用的约定,并不表示桌子没有高度:地面位于负的 z 高度。

假设要放置一个边长为4厘米、保持直立的方块,它的半边长就是2厘米。为了让底面落在桌面上,方块中心应放在:

half_size = 0.02
position = [0.10, -0.05, half_size]

这个位置表示:方块中心沿世界 x 正方向偏移10厘米,沿 y 负方向偏移5厘米,高于桌面2厘米。

下面的代码可以放在 _load_scene() 调用 self.table_scene.build() 之后;还需要在文件开头导入 sapien 和 actors。

import sapien
from mani_skill.utils.building import actors

# 以下语句放在 _load_scene() 方法内部。
self.cube = actors.build_cube(
    self.scene,
    half_size=0.02,
    color=[0.2, 0.6, 0.9, 1.0],
    name="example_cube",
    body_type="dynamic",
    initial_pose=sapien.Pose(p=[0.10, -0.05, 0.02]),
)

dynamic 表示方块会参与动力学运动。这里的 initial_pose 是创建时的初始位姿;如果要让方块在后续每个回合重新摆放,还应在 _initialize_episode() 中设置它的位姿。添加任务物体的方式见官方对象加载教程。

4. 世界原点具体在哪里?

世界原点是场景坐标系中的 (0, 0, 0)。由于桌面被布置在 z = 0,这个点位于桌面高度上,但不必是桌子的几何中心。

先看实际桌子的外观:下图直接使用 TableSceneBuilder 自带的桌子模型和木纹,以及 Panda 机械臂进行渲染。为便于观察调整了相机视角,未放置任务方块;
在这里插入图片描述
机械臂在这个角度会遮住原点,因此仅在这张教学图中隐藏其外观,保留底座参考点 B 的坐标。桌子的模型、纹理和位置没有改变。这是垂直朝下的透视相机视图;桌面平面与成像平面平行,方便比较桌面上的方向与距离。

最后用下面的等比例几何图查看距离,以及桌子对象原点与桌面高度的关系。
在这里插入图片描述

在本文核对的 Panda 配置中,机器人底座被放在 (-0.615, 0, 0)。因此,从底座沿世界 x 正方向移动61.5厘米,可以到达世界原点。这个说法是在帮助我们定位原点;代码中的定义顺序是先有世界坐标系,再按坐标摆放机器人。

还有一个容易混淆的地方:桌子对象自身的位姿,与桌面表面的位置不是同一件事。模型几何相对对象原点也有偏移,所以不能只读取 table.pose.p,就把它当作桌面中心。

这些数值来自TableSceneBuilder 源码中的场景布置。它们是具体实现的选择,不是所有机器人任务必须遵守的通用数值。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐