3. 创建自定义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 运行。
验证步骤:
- 视口(Viewport)中应出现三个不同颜色的物体:红色立方体在右侧、绿色球体在左侧、蓝色圆柱体在后方。
- 打开 Stage 面板,展开
/World,确认三个物体均带有CollisionAPI和RigidBodyAPI属性。 - 点击 Play 按钮运行物理模拟,三个物体应因重力下落并落到地面(若场景中有地面),或相互碰撞时产生物理响应。
- 在 Property 面板选中任一物体,检查
Physics标签下 Mass 值是否与代码设置一致(立方体2.0、球体1.5、圆柱体3.0)。
判定标准:三个物体位置、颜色与代码参数完全一致;物理模拟时物体受重力影响下落且相互碰撞不穿透,即视为通过。
关键说明
代码中 world.reset() 用于将物理属性应用到刚创建的物体上,确保后续 Play 时能正确模拟。若场景中没有地面,物体将自由下落——这是验证物理属性的直观方式。所有物体均创建在 /World 根路径下,便于 Stage 面板中统一管理。