2. 加载机器人模型

任务目标

本案例演示在 Isaac Sim 中从 URDF 或 MJCF 格式加载机器人模型(以 Franka Panda 和 Cartpole 为例),并将其放置到仿真环境中。完成本案例后,你将能够在 Isaac Sim 的 Stage 中实例化外部机器人模型,并确认其已正确生成。

环境与依赖

  • Isaac Sim 2023.1.0 或更新版本(自带 omni.isaac.urdf 与 omni.isaac.mjcf 扩展)
  • Python 3.7+(Isaac Sim 内置)
  • 无需额外安装第三方库

实现代码

以下代码创建两个独立函数,分别从 URDF 和 MJCF 格式加载模型,并在仿真场景中生成对应的 Actor。代码可直接在 Isaac Sim 的 Python Script Editor 中运行。

from omni.isaac.urdf import _urdf
from omni.isaac.mjcf import _mjcf
from omni.isaac.core.utils.stage import add_reference_to_stage
from omni.isaac.core.world import World
import carb

def load_franka_from_urdf(urdf_path: str, position=[0.0, 0.0, 0.0]):
    """从URDF文件加载Franka机器人到当前Stage"""
    # 获取URDF扩展接口
    urdf_interface = _urdf.acquire_urdf_interface()
    
    # 设置导入配置
    import_config = urdf_interface.UrdfImportConfig()
    import_config.urdf_path = urdf_path
    import_config.fix_base = True  # 固定底座
    import_config.make_default_prim = False
    
    # 执行导入
    result = urdf_interface.import_urdf(import_config)
    if not result.valid:
        carb.log_error(f"URDF导入失败: {result.message}")
        return None
    
    # 获取生成的prim路径并设置位置
    prim_path = result.prim_path
    from pxr import UsdGeom
    stage = World.instance().stage
    prim = stage.GetPrimAtPath(prim_path)
    if prim.IsValid():
        xform = UsdGeom.Xformable(prim)
        xform.ClearXformOpOrder()
        xform.AddTranslateOp().Set(tuple(position))
    
    return prim_path

def load_cartpole_from_mjcf(mjcf_path: str, position=[0.0, 0.0, 0.0]):
    """从MJCF文件加载Cartpole到当前Stage"""
    # 获取MJCF扩展接口
    mjcf_interface = _mjcf.acquire_mjcf_interface()
    
    # 设置导入配置
    import_config = mjcf_interface.MjcfImportConfig()
    import_config.mjcf_path = mjcf_path
    import_config.fix_base = True
    
    # 执行导入
    result = mjcf_interface.import_mjcf(import_config)
    if not result.valid:
        carb.log_error(f"MJCF导入失败: {result.message}")
        return None
    
    prim_path = result.prim_path
    
    # 设置位置
    from pxr import UsdGeom
    stage = World.instance().stage
    prim = stage.GetPrimAtPath(prim_path)
    if prim.IsValid():
        xform = UsdGeom.Xformable(prim)
        xform.ClearXformOpOrder()
        xform.AddTranslateOp().Set(tuple(position))
    
    return prim_path

# ===== 使用示例 =====
if __name__ == "__main__":
    # 初始化World(必须)
    world = World()
    
    # 方式1:从URDF加载Franka(需提供本地URDF文件路径)
    # franka_prim = load_franka_from_urdf("/path/to/franka.urdf", [0.5, 0, 0])
    
    # 方式2:从MJCF加载Cartpole(需提供本地MJCF文件路径)
    # cartpole_prim = load_cartpole_from_mjcf("/path/to/cartpole.xml", [-0.5, 0, 0])
    
    # 方式3:使用Isaac Sim内置资产(无需外部文件)
    # 加载内置Franka(来自Isaac Sim资产库)
    franka_asset_path = "/Isaac/Robots/Franka/franka_alt.usd"
    franka_prim = add_reference_to_stage(
        usd_path=franka_asset_path, 
        prim_path="/World/Franka"
    )
    
    # 加载内置Cartpole(来自Isaac Sim资产库)
    cartpole_asset_path = "/Isaac/Robots/Cartpole/cartpole.usd"
    cartpole_prim = add_reference_to_stage(
        usd_path=cartpole_asset_path,
        prim_path="/World/Cartpole"
    )
    
    # 设置位置
    from pxr import UsdGeom, Gf
    stage = world.stage
    
    for prim_path, pos in [("/World/Franka", (0.5, 0, 0)), 
                           ("/World/Cartpole", (-0.5, 0, 0))]:
        prim = stage.GetPrimAtPath(prim_path)
        if prim.IsValid():
            xform = UsdGeom.Xformable(prim)
            xform.ClearXformOpOrder()
            xform.AddTranslateOp().Set(Gf.Vec3d(*pos))
    
    print("模型加载完成。在Viewport中查看结果。")
    print(f"Franka prim: {franka_prim}")
    print(f"Cartpole prim: {cartpole_prim}")

运行与验证

  1. 打开 Isaac Sim,进入 Window → Python Script Editor。
  2. 将上述代码粘贴到编辑器中,点击 Run。
  3. 若使用外部 URDF/MJCF 文件,请将代码中注释的路径替换为实际文件路径,并取消注释对应行。
  4. 运行后,在 Viewport 中应能看到 Franka 机械臂和 Cartpole 模型出现在指定位置。

通过条件

  • Viewport 中可见两个机器人模型,且位置与代码中设置的坐标一致(Franka 在 x=0.5 处,Cartpole 在 x=-0.5 处)。
  • Console 窗口无报错信息,并输出两个 prim 路径。
  • 在 Stage 面板中展开 /World,能看到 Franka 和 Cartpole 两个子节点。

常见问题

  • URDF 导入失败:确认 URDF 文件中的 mesh 路径为路径或相对 URDF 文件的正确相对路径。
  • 模型位置未生效:确保在设置 Transform 前已调用 World() 初始化,且 Stage 已加载。
  • 内置资产路径错误:不同 Isaac Sim 版本的资产路径可能略有差异,可在 Content 面板中搜索 franka 或 cartpole 确认实际路径。