导入 USD 资产#

Universal Scene Description(USD) 是 Pixar 用于描述和合成 3D 场景的开放框架。Genesis World 通过 gs.morphs.USD 导入 USD 文件(.usd、.usda、.usdc、.usdz),读取其中的几何体、材质和 UsdPhysics 关节定义。单个文件里可能是一个关节机器人、一个刚体物体,也可能是一整个包含众多实体的环境,就像 NVIDIA Isaac Sim 等类似工具导出的资产那样。

本页内容以两个可运行示例为准:

安装 {#installation}#

解析 USD 需要可选的 usd 依赖:

pip install -e ".[usd]"

它会安装 usd-core,这足以读取 USD 文件及其 UsdPreviewSurface 材质。如果资产的材质使用了其他着色器,请参阅下文的材质烘焙。

最小可运行示例#

下面的代码加载一个冰箱资产并推进仿真。首次运行时,它会从 Hugging Face 上的 Genesis World 资产仓库下载该资产:

import genesis as gs
from huggingface_hub import snapshot_download

gs.init(backend=gs.cpu)

scene = gs.Scene(show_viewer=True)
scene.add_entity(gs.morphs.Plane())

asset_path = snapshot_download(
    repo_type="dataset",
    repo_id="Genesis-Intelligence/assets",
    revision="c50bfe3e354e105b221ef4eb9a79504650709dd2",
    allow_patterns="usd/Refrigerator055/*",
    max_workers=1,
)

entities = scene.add_stage(
    morph=gs.morphs.USD(
        file=f"{asset_path}/usd/Refrigerator055/Refrigerator055.usd",
        pos=(0, 0, 0.9),
        euler=(0, 0, 180),  # extrinsic x-y-z, degrees
    ),
)

scene.build()
for _ in range(1000):
    scene.step()

add_stage 返回它创建的实体组成的 list,文件中每找到一个刚体或关节体就对应一项。冰箱是单个关节体,所以列表只有一个元素;而一个房间场景会返回很多项。每个 Genesis World 程序都相同的 initialize / scene / build / step 生命周期见 你好,Genesis World。

add_stage 与 add_entity#

USD 文件是一个 stage,其中可以包含任意数量的物理实体。Genesis World 提供两种入口:

  • scene.add_stage(morph=gs.morphs.USD(...)) 会发现并加载文件中的每一个刚体实体,并以列表形式返回。适用于完整场景,以及任何你不希望手工枚举内容的文件。

  • scene.add_entity(gs.morphs.USD(...)) 加载单个实体并直接返回它。它针对由 prim_path 指定的 prim;当 prim_path 保持为 None 时,会回退到该 stage 的默认 prim,如果文件没有声明默认 prim 则抛出异常。

两者接受相同的 gs.morphs.USD morph,因此下面列出的每个选项对两种方式都适用。

关节体与刚体#

Genesis World 把 UsdPhysics 关节解析成 dof 图。彼此之间没有关节相连的刚体会成为自由刚体;由关节连接的刚体则构成一个关节体。支持的关节类型如下:

USD schema

Genesis World 关节

自由度

UsdPhysics.RevoluteJoint

revolute

1 个旋转自由度,带限位

UsdPhysics.PrismaticJoint

prismatic

1 个平移自由度,带限位

UsdPhysics.SphericalJoint

spherical

3 个旋转自由度

UsdPhysics.FixedJoint

fixed

0(刚性连杆间焊接)

UsdPhysics.Joint(通用)

free

6(完整平移 + 旋转)

关节的根连杆是固定还是浮动,取决于资产本身的设定。可以用 morph 上的 fixed 覆盖这一行为,它只作用于根(基座)连杆:

gs.morphs.USD(file="robot.usd", fixed=True)  # weld the base to the world

examples/usd/kitchen.py 使用 fixed=False,让洗碗机这类原本固定安装的电器变成自由刚体,可以落到地面上、也能被拖动;使用 fixed=None 则保留场景中原本设定的固定/自由状态。

坐标轴与单位#

USD stage 自带 upAxis 和 metersPerUnit 元数据,Genesis World 在把资产转换到它自己的右手系、Z 轴朝上、以米为单位的世界时会遵循这些元数据。如果被引用的网格缺少这类信息,则由 morph 选项 file_meshes_are_zup 控制如何解释,其行为与其他网格格式一致。完整的坐标轴与单位处理规则见 约定,其中也包括 Genesis World 采用的、与 Blender 对齐的 Y 轴朝上 ↔ Z 轴朝上映射。

网格处理#

Genesis World 会从资产的几何体派生碰撞网格。有三个选项控制这一派生过程;examples/usd/kitchen.py 把三者都设置为尊重资产原本的设定:

scene.add_stage(
    morph=gs.morphs.USD(
        file=usd_file,
        fixed=fixed,
        convexify=False,  # Don't force convex hulls; honor the asset's per-geom MeshCollisionAPI approximation.
        decimate=True,  # Simplify collision meshes (fewer faces) for speed and stability.
        align=False,  # Keep the USD root-link frames (don't re-center to the center of mass).
    ),
    vis_mode="visual",  # Render the asset's own USD materials, not the per-collision debug colors.
)
  • convexify 用一层或多层凸包包裹每个网格(当单个凸包过于粗糙时用 coacd 做分解)。对刚体实体默认 True。设为 False 可保留资产自带的凹碰撞几何体。

  • decimate 会简化碰撞网格,使其接近 decimate_face_num 指定的面数(默认 500)。当 convexify 开启时默认 True。

  • align 会重新设定浮动基座根连杆的坐标系,使原点位于质心。默认 False。

vis_mode="collision" 会渲染碰撞几何体而非视觉网格,这是检查碰撞形状是否符合预期的最快方法。

关节动力学属性#

有些关节属性(摩擦、电枢、被动刚度与阻尼)不属于 USD 物理核心 schema,因此导出器会把它们存放在自定义属性名下。例如 Isaac Sim 会写入 physxJoint:jointFriction 和 physxLimit:angular:stiffness。Genesis World 会从一组候选属性名中读取每个属性,按顺序尝试,并使用第一个存在的属性:

gs.morphs.USD(
    file="robot.usd",
    joint_friction_attr_candidates=[
        "physxJoint:jointFriction",  # Isaac Sim
        "physics:jointFriction",
        "jointFriction",
        "friction",
    ],
)

我们的默认值已经覆盖 Isaac Sim 以及常见的社区约定,因此只有当你的导出器使用了其中都不匹配的名称时,才需要覆盖候选列表。解析出的值会填入对应的 dof 字段:

Morph 选项

填充的 dof 字段

含义

joint_friction_attr_candidates

dofs_frictionloss

关节被动摩擦

joint_armature_attr_candidates

dofs_armature

折算后的转子惯量

revolute_joint_stiffness_attr_candidates

dofs_stiffness

被动刚度(旋转关节)

revolute_joint_damping_attr_candidates

dofs_damping

被动阻尼(旋转关节)

prismatic_joint_stiffness_attr_candidates

dofs_stiffness

被动刚度(滑动关节)

prismatic_joint_damping_attr_candidates

dofs_damping

被动阻尼(滑动关节)

通过 USD PhysicsDriveAPI(physics:stiffness、physics:angular:damping)设定的 PD 控制增益会直接读入 dofs_kp 和 dofs_kv,因为它们是标准 USD 属性。

区分视觉几何体与碰撞几何体#

当资产没有通过 MeshCollisionAPI 声明碰撞几何体时,Genesis World 会根据 prim 名称推断。它用正则表达式匹配每个 prim,并把匹配结果沿子树继承下去:

gs.morphs.USD(
    file="robot.usd",
    collision_mesh_prim_patterns=[r"^([cC]ollision).*"],  # collision-only geometry
    visual_mesh_prim_patterns=[r"^([vV]isual).*"],  # visual-only geometry
)

规则按以下顺序应用:

  1. 继承。 解析器自上而下遍历 prim 层级,一旦某个 prim 匹配到模式,它的所有后代都继承这一分类。

  2. 分类。 只匹配视觉模式的 prim 仅用于视觉;只匹配碰撞模式的 prim 仅用于碰撞;两者都匹配或都不匹配的 prim 则同时用于两者。对于没有任何命名约定的纯网格资产,“都不匹配”就是默认情况。

  3. 可见性与用途。 解析器只读取可见的 prim。purpose = "guide" 的 prim 不会进入视觉表现,但仍可作为碰撞几何体。

上面的模式就是默认值,因此大多数 Isaac Sim 资产在这里无需任何配置。

材质烘焙#

usd-core 可以解析 UsdPreviewSurface 材质,这覆盖了大多数资产。基于其他着色器网络构建的材质需要 NVIDIA Omniverse Kit 才能烘焙成受支持的形式。烘焙可在 Python 3.10 和 3.11 上配合 GPU 后端使用:

pip install --extra-index-url https://pypi.nvidia.com/ omniverse-kit
export OMNI_KIT_ACCEPT_EULA=yes

OMNI_KIT_ACCEPT_EULA=yes 以非交互方式接受 Omniverse EULA,设置一次即可。如果没有 Omniverse Kit,Genesis World 只解析 UsdPreviewSurface,并在没有材质时回退到每个 prim 的 displayColor。

Note

如果看到 Baking process failed: ... 警告,常见原因有:未接受 EULA(设置 OMNI_KIT_ACCEPT_EULA=yes)、首次启动时安装依赖超时(等安装完成后重新运行程序),或多个 Python 环境之间存在过期的扩展(删除共享扩展目录,例如 Linux 上的 ~/.local/share/ov/data/ext,然后重试)。

另请参阅#