4. 导入外部3D模型
任务说明
本案例目标是在 Isaac Sim 中导入外部机器人模型(URDF 或 USD 格式),并通过代码调整模型的位置与缩放,使其正确显示在仿真场景中。我们将使用 Isaac Sim 自带的 omni.isaac.urdf 扩展来解析 URDF 文件,或直接使用 usd 接口加载 USD 文件,随后将导入的模型添加到 Stage 中并设置其 transform。
实现方案
我们提供两个独立函数:import_urdf 用于导入 URDF 模型,import_usd 用于导入 USD 模型。两者均返回导入模型的 Prim 路径,并支持通过参数指定位置(position)和缩放(scale)。核心逻辑是:先创建或获取 Stage,然后调用对应导入接口,最后通过 UsdGeom.Xformable 设置平移与缩放属性。
代码实现
# 文件: import_model.py
# 依赖: isaacsim 2023.1+ / omni.isaac.urdf
from omni.isaac.core.utils.stage import get_current_stage
from omni.isaac.urdf import _urdf
import omni.usd
from pxr import UsdGeom, Gf
def import_urdf(urdf_path: str, prim_path: str,
position=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0)):
"""
导入 URDF 模型并设置位置与缩放。
:param urdf_path: URDF 文件路径
:param prim_path: 目标 Prim 路径,如 "/World/robot"
:param position: 平移 (x, y, z)
:param scale: 缩放 (sx, sy, sz)
:return: 导入后的 Prim 路径
"""
urdf_interface = _urdf.acquire_urdf_interface()
# 设置解析参数:使用 meters 单位,不合并固定关节
result = urdf_interface.parse_urdf(
urdf_path=urdf_path,
path=prim_path,
merge_fixed_joints=False,
fix_base=False,
make_default_prim=True,
self_collision=False
)
if not result.success:
raise RuntimeError(f"URDF 导入失败: {result.status_message}")
# 设置位置与缩放
stage = get_current_stage()
prim = stage.GetPrimAtPath(prim_path)
if not prim.IsValid():
raise RuntimeError(f"Prim 无效: {prim_path}")
xform = UsdGeom.Xformable(prim)
xform.ClearXformOpOrder()
# 先平移,再缩放(顺序影响最终结果)
xform.AddTranslateOp().Set(Gf.Vec3d(*position))
xform.AddScaleOp().Set(Gf.Vec3f(*scale))
return prim_path
def import_usd(usd_path: str, prim_path: str,
position=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0)):
"""
导入 USD 模型并设置位置与缩放。
:param usd_path: USD 文件路径
:param prim_path: 目标 Prim 路径,如 "/World/robot"
:param position: 平移 (x, y, z)
:param scale: 缩放 (sx, sy, sz)
:return: 导入后的 Prim 路径
"""
# 将 USD 文件作为子层引用添加到当前 Stage
success = omni.usd.get_context().get_stage().GetRootLayer().subLayerPaths.append(usd_path)
if not success:
# 若 subLayer 方式失败,则使用引用方式
stage = get_current_stage()
prim = stage.DefinePrim(prim_path, "Xform")
prim.GetReferences().AddReference(usd_path)
else:
# subLayer 方式下,需要找到实际模型根节点
# 这里假设 USD 文件根节点即为模型根节点
stage = get_current_stage()
prim = stage.GetPrimAtPath("/" + usd_path.split("/")[-1].split(".")[0])
if not prim.IsValid():
# 若找不到,则使用目标路径
prim = stage.GetPrimAtPath(prim_path)
if not prim.IsValid():
raise RuntimeError(f"USD 导入失败: {usd_path}")
# 设置位置与缩放
xform = UsdGeom.Xformable(prim)
xform.ClearXformOpOrder()
xform.AddTranslateOp().Set(Gf.Vec3d(*position))
xform.AddScaleOp().Set(Gf.Vec3f(*scale))
return prim.GetPath().pathString
# 使用示例(在 Isaac Sim 的 Python 脚本中执行)
if __name__ == "__main__":
# 示例 1: 导入 URDF
# robot_path = import_urdf("/path/to/robot.urdf", "/World/robot",
# position=(1.0, 0.0, 0.5), scale=(0.01, 0.01, 0.01))
# print(f"URDF 模型已导入: {robot_path}")
# 示例 2: 导入 USD
# robot_path = import_usd("/path/to/robot.usd", "/World/robot",
# position=(0.0, 0.0, 0.0), scale=(1.0, 1.0, 1.0))
# print(f"USD 模型已导入: {robot_path}")
pass
落地与验证
运行方式:在 Isaac Sim 的 Script Editor 中执行上述代码,或保存为 .py 文件后通过 ./python.sh import_model.py 运行。需要提前在 Omniverse 环境中安装 omni.isaac.urdf 扩展。
验证方法:执行导入后,在 Viewport 中观察模型是否出现在指定位置且大小符合预期。同时可通过以下代码检查 Transform 属性:
from pxr import UsdGeom
stage = get_current_stage()
prim = stage.GetPrimAtPath("/World/robot")
xform = UsdGeom.Xformable(prim)
# 读取并打印平移与缩放值
for op in xform.GetOrderedXformOps():
print(f"Op: {op.GetOpType()}, Value: {op.Get()}")
判定标准:若 Viewport 中模型位置与代码中 position 参数一致,且模型尺寸相对原始文件按 scale 参数正确缩放,则视为导入成功。对于 URDF 文件,若模型单位是毫米而场景使用米,需设置 scale=(0.001, 0.001, 0.001) 进行单位换算。