3. 创建自定义3D物体

创建自定义3D物体 学习卡片

任务说明

本案例目标是在 Isaac Sim 中通过 Python 脚本动态创建基本几何体(立方体、球体、圆柱体),并为每个物体设置独立的位置、颜色和物理属性(质量、碰撞刚体)。最终在视口中直接观察到三个不同颜色、不同位置、具备物理响应能力的物体。

实现方案

使用 omni.isaac.core 的 World 与 XFormPrim 接口,通过 USD 原生 API 在默认场景中创建几何体。每个物体包含:CollisionShape(碰撞体)、RigidBodyAPI(刚体物理)、VisualMaterial(颜色材质)。物理属性通过 RigidBodyAPI 的 mass 参数设置。

代码实现

"""在 Isaac Sim 中动态创建自定义 3D 物体(立方体/球体/圆柱体)"""
import omni.usd
from pxr import UsdGeom, UsdPhysics, Sdf, Gf
from omni.isaac.core import World
from omni.isaac.core.utils.stage import get_current_stage
from omni.isaac.core.prims import XFormPrim
import carb

# 初始化世界(若尚未创建)
world = World()
stage = get_current_stage()

# 定义物体参数: (名称, 类型, 位置, 颜色RGB, 质量kg)
objects_config = [
    {"name": "custom_cube", "type": "cube", "pos": (1.0, 0.0, 0.5),
     "color": (1.0, 0.2, 0.2), "mass": 2.0},
    {"name": "custom_sphere", "type": "sphere", "pos": (-1.0, 0.0, 0.5),
     "color": (0.2, 0.8, 0.2), "mass": 1.5},
    {"name": "custom_cylinder", "type": "cylinder", "pos": (0.0, 1.0, 0.5),
     "color": (0.2, 0.4, 1.0), "mass": 3.0},
]

# 创建几何体的辅助函数
def create_geometry(prim_path, geom_type):
    """在指定路径创建几何体,返回 GeomPrim"""
    if geom_type == "cube":
        return UsdGeom.Cube.Define(stage, prim_path)
    elif geom_type == "sphere":
        return UsdGeom.Sphere.Define(stage, prim_path)
    elif geom_type == "cylinder":
        return UsdGeom.Cylinder.Define(stage, prim_path)
    else:
        raise ValueError(f"Unsupported type: {geom_type}")

# 主循环:创建每个物体
for cfg in objects_config:
    prim_path = f"/World/{cfg['name']}"
    
    # 1. 创建几何体
    geom = create_geometry(prim_path, cfg["type"])
    geom_prim = geom.GetPrim()
    
    # 2. 设置位置(通过 XFormPrim 的 translate API)
    xform = XFormPrim(prim_path)
    xform.set_world_pose(position=np.array(cfg["pos"]))
    
    # 3. 添加碰撞体
    collision_api = UsdPhysics.CollisionAPI.Apply(geom_prim)
    collision_api.CreateCollisionEnabledAttr(True)
    
    # 4. 添加刚体物理属性并设置质量
    rigid_body_api = UsdPhysics.RigidBodyAPI.Apply(geom_prim)
    rigid_body_api.CreateMassAttr(cfg["mass"])
    rigid_body_api.CreateLinearVelocityAttr(Gf.Vec3f(0, 0, 0))
    
    # 5. 创建并绑定可视化材质(颜色)
    material_path = f"/World/Looks/{cfg['name']}_mat"
    material = UsdShade.Material.Define(stage, material_path)
    shader = UsdShade.Shader.Define(stage, material_path + "/Shader")
    shader.CreateIdAttr("UsdPreviewSurface")
    shader.CreateInput("diffuseColor", Sdf.ValueTypeNames.Color3f).Set(
        Gf.Vec3f(cfg["color"])
    )
    material.CreateSurfaceOutput().ConnectToSource(shader.ConnectableAPI(), "surface")
    UsdShade.MaterialBindingAPI(geom_prim).Bind(material)

# 重置世界以应用物理属性
world.reset()

print("已创建 3 个自定义物体:立方体(红)、球体(绿)、圆柱体(蓝)")
print("位置分别为: (1,0,0.5), (-1,0,0.5), (0,1,0.5)")

运行与验证

运行方式:在 Isaac Sim 的 Script Editor 中执行上述代码,或保存为 create_objects.py 后通过 ./python.sh create_objects.py 运行。

验证步骤:

  1. 视口(Viewport)中应出现三个不同颜色的物体:红色立方体在右侧、绿色球体在左侧、蓝色圆柱体在后方。
  2. 打开 Stage 面板,展开 /World,确认三个物体均带有 CollisionAPI 和 RigidBodyAPI 属性。
  3. 点击 Play 按钮运行物理模拟,三个物体应因重力下落并落到地面(若场景中有地面),或相互碰撞时产生物理响应。
  4. 在 Property 面板选中任一物体,检查 Physics 标签下 Mass 值是否与代码设置一致(立方体2.0、球体1.5、圆柱体3.0)。

判定标准:三个物体位置、颜色与代码参数完全一致;物理模拟时物体受重力影响下落且相互碰撞不穿透,即视为通过。

USD 场景层级与物理属性结构 /World (默认场景) custom_cube 位置: (1, 0, 0.5) 类型: Cube ✓ CollisionAPI ✓ RigidBodyAPI 质量: 2.0 kg 材质: 红色 (0.2, 0.2, 0.2) custom_sphere 位置: (-1, 0, 0.5) 类型: Sphere ✓ CollisionAPI ✓ RigidBodyAPI 质量: 1.5 kg 材质: 绿色 (0.2, 0.8, 0.2) custom_cylinder 位置: (0, 1, 0.5) 类型: Cylinder ✓ CollisionAPI ✓ RigidBodyAPI 质量: 3.0 kg 材质: 蓝色 (0.2, 0.4, 1.0) 物理属性已启用 质量参数 可视化材质

关键说明

代码中 world.reset() 用于将物理属性应用到刚创建的物体上,确保后续 Play 时能正确模拟。若场景中没有地面,物体将自由下落——这是验证物理属性的直观方式。所有物体均创建在 /World 根路径下,便于 Stage 面板中统一管理。