4. 机器人模型导入:URDF与USD格式转换、使用Import功能导入机器人、关节与链接的层级结构、配置机器人初始位姿

好,我们进入第四章。这一章要解决一个很实际的问题——怎么把机器人模型弄进Isaac Sim里。

你手头可能有URDF文件,也可能有STEP或STP的CAD模型。但Isaac Sim原生用的是USD格式。所以,核心就两个事:格式转换,以及导入后的配置。

我个人习惯先把URDF吃透,因为ROS生态里URDF太常见了。你想想看,一个机械臂、一台AGV,甚至人形机器人,URDF几乎是标配。但Isaac Sim不直接吃URDF,它要的是USD。怎么办?两种路子:要么用内置的Import功能直接转,要么用官方提供的urdf_importer脚本。

4.1 URDF与USD:到底差在哪?

先搞清楚这两个格式的本质区别,不然你后面遇到问题会懵。

特性 URDF USD (Universal Scene Description)
出身 ROS社区,纯文本XML Pixar,好莱坞级3D场景描述
核心能力 描述运动学树(关节+连杆) 描述整个虚拟世界(灯光、材质、物理、动画)
几何支持 简单几何体(box, cylinder, mesh) 任意复杂网格、NURBS、点云
物理属性 通过<inertial>和<collision>定义 通过PhysicsSchema、ArticulationSchema定义
扩展性 弱,需要xacro预处理 强,支持层叠、继承、引用

说白了,URDF是“机器人专用格式”,而USD是“全能格式”。Isaac Sim选择USD,是因为它要同时处理机器人、环境、传感器、灯光——一个URDF根本装不下这么多东西。

核心认知:URDF描述的是机器人的“骨架”和“皮肤”,USD描述的是整个“舞台”。导入过程就是把骨架和皮肤搬到舞台上,并告诉舞台“这个家伙有物理属性,能动”。

4.2 使用Import功能导入机器人

Isaac Sim的Import功能藏在菜单栏 File -> Import 里。但别急着点,先做准备工作。

4.2.1 准备工作:检查URDF文件

我曾经遇到过一个问题:导入后机器人直接趴在地上,关节乱飞。查了半天,发现URDF里<origin>标签写错了,导致连杆原点偏移。所以,导入前我建议你先用ROS自带的check_urdf工具扫一遍:

# 终端执行
check_urdf my_robot.urdf

这个命令会输出机器人的关节树,如果有语法错误或缺失的mesh路径,它会直接报错。嗯,这一步能省掉你后面80%的排查时间。

4.2.2 正式导入:两种方式

方式一:GUI菜单导入

  1. 打开Isaac Sim,新建一个空Stage。
  2. 点击 File -> Import,选择你的URDF文件。
  3. 在弹出的对话框中,勾选 Fix Base Link(如果你的机器人是固定基座)。
  4. 点击 Import,等待几秒钟。

导入成功后,你会在Stage面板里看到一堆以_joint和_link结尾的Prim。这就是USD格式的机器人了。

方式二:Python脚本导入

如果你需要批量处理,或者想把导入流程自动化,用脚本更靠谱:

import omni.kit.commands
import carb

# 设置URDF路径
urdf_path = "/path/to/your/robot.urdf"

# 执行导入
omni.kit.commands.execute(
    "URDFImportCommand",
    urdf_path=urdf_path,
    import_as="articulation",  # 导入为关节体
    fix_base=True,             # 固定基座
    merge_fixed_joints=False   # 不合并固定关节
)

print("URDF导入完成")

我的经验:导入时merge_fixed_joints这个参数要小心。如果设为True,所有固定关节(比如法兰盘和末端工具之间的关节)会被合并成一个刚体,这会丢失关节信息。我一般设为False,保持关节树完整。

4.3 关节与链接的层级结构

导入完成后,你需要在Stage面板里理解这个层级。说白了,这就是一个树状结构,根节点是机器人本体,下面挂着一堆关节和连杆。

举个例子,一个六轴机械臂的层级大概长这样:

/World
    /robot_name                (ArticulationRoot)
        /base_link             (RigidBody)
            /base_link_visual  (Mesh)
            /base_link_collision (Mesh)
            /joint_1           (Joint)
                /link_1        (RigidBody)
                    /link_1_visual (Mesh)
                    /joint_2   (Joint)
                        /link_2 (RigidBody)
                            ...

这里有几个关键点:

  • ArticulationRoot:整个机器人的根节点,Isaac Sim用它来识别这是一个“可动机构”。
  • RigidBody:每个连杆都是一个刚体,包含质量、惯性、碰撞形状。
  • Joint:关节,定义了父子连杆之间的相对运动(旋转、平移)。
  • Mesh:视觉和碰撞网格,挂在对应的连杆下面。

避坑指南:我曾经导入一个AGV模型,发现轮子不转。检查层级发现,轮子的关节被错误地挂在了base_link下面,而不是ArticulationRoot下面。Isaac Sim要求所有关节必须直接或间接挂在ArticulationRoot下,否则物理引擎不认。导入后一定要检查根节点类型是不是ArticulationRoot。

4.4 配置机器人初始位姿

机器人导入后,默认位姿是URDF里定义的<origin>。但很多时候,你需要调整它的初始位置和姿态,比如把机器人放在工作台面上,或者让机械臂处于一个“准备姿态”。

4.4.1 通过Transform组件调整

最简单的方法:在Stage面板选中ArticulationRoot节点,在Property面板里找到Transform组件,直接修改Translate和Rotate值。

但注意,这里有个坑:如果你直接修改ArticulationRoot的Transform,物理引擎可能会把整个机器人“瞬移”过去,导致穿模。我建议先暂停仿真,调整好位姿,再启动仿真。

4.4.2 通过Python脚本设置初始关节角度

更专业的做法是,在仿真开始前,把机器人的关节设置到目标角度。比如,让六轴机械臂的J1和J2转到特定位置:

import omni.physx as physx
from pxr import UsdPhysics, Gf

# 获取机器人根节点
robot_prim = stage.GetPrimAtPath("/World/robot_name")

# 获取关节API
articulation = UsdPhysics.ArticulationRootAPI(robot_prim)

# 设置关节目标位置(弧度)
joint_paths = [
    "/World/robot_name/base_link/joint_1",
    "/World/robot_name/base_link/joint_2"
]
joint_angles = [0.5, -0.3]  # 单位:弧度

for path, angle in zip(joint_paths, joint_angles):
    joint_prim = stage.GetPrimAtPath(path)
    joint_api = UsdPhysics.JointAPI(joint_prim)
    # 设置驱动目标
    joint_api.GetTargetPositionAttr().Set(angle)

# 更新物理场景
physx.update_physics_stage()

我的习惯:我会在导入脚本的最后,加一段位姿配置代码。这样每次重新导入,机器人都会自动摆到预设位置,省得手动拖拽。你想想看,如果每次调试都要手动调整,那效率太低了。

4.5 本章知识结构图

下面这张图总结了URDF导入Isaac Sim的完整流程和关键节点:

URDF导入Isaac Sim流程与层级结构 URDF导入Isaac Sim:流程与层级结构 URDF文件 Mesh文件(.stl/.obj) 材质/纹理文件 Isaac Sim Import功能 / Python脚本 USD Stage:ArticulationRoot → RigidBody → Joint → Mesh ArticulationRoot(根节点) RigidBody(连杆+物理属性) Joint(关节+驱动参数) 配置初始位姿:Transform / 关节角度 / 物理属性 可仿真的机器人模型 关键检查点:根节点类型、关节层级、物理属性、Mesh路径

4.6 常见问题与避坑

  • 导入后机器人是透明的?——检查Mesh路径。URDF里的<mesh filename>必须是路径,或者相对于URDF文件的路径。我遇到过相对路径写错,导致Isaac Sim找不到Mesh文件。
  • 关节不动?——检查ArticulationRoot是否设置正确。如果根节点是Xform而不是ArticulationRoot,物理引擎不会驱动机器人。
  • 机器人掉出地面?——初始位姿的Z值设得太低了。把Translate的Z值抬高,让机器人刚好接触地面。
  • 导入报错“Failed to parse URDF”?——URDF文件里有中文注释或特殊字符。把URDF用UTF-8 without BOM编码保存。

我曾经踩过的坑:有一次导入一个协作机器人,URDF里用了<gazebo>标签来定义传动比。Isaac Sim的Import功能不解析<gazebo>标签,导致关节驱动参数丢失。解决办法是:在URDF里直接用<transmission>和<joint>标签定义驱动,或者导入后用Python脚本手动设置关节驱动参数。