2. 认识USD与Omniverse
好,我们正式开始第二讲。说实话,很多刚接触Isaac Sim的朋友,第一反应都是「我直接把模型拖进去不就行了?」——嗯,确实能拖,但后面大概率会出各种奇怪的问题。材质丢了、坐标飞了、动画不动了……这些坑我几乎都踩过。
问题的根源,往往在于不理解USD。USD不是一种简单的文件格式,它是一整套场景描述与协作的体系。今天我们就把它讲透。
2.1 USD到底是什么?
USD的全称是Universal Scene Description,通用场景描述。它由皮克斯开发,最初是为了解决大型动画电影中多工具、多部门协作的难题。后来NVIDIA把它拿过来,作为Omniverse和Isaac Sim的底层数据标准。
你可以把USD理解成一种「场景的乐高系统」。每个模型、材质、灯光、动画都是一个独立的乐高块,它们通过USD组合成一个完整的仿真场景。而且这些块可以来自不同的软件——Maya、Blender、CAD、UE5,都能转成USD。
核心要点:USD不是单一文件,而是一个场景描述框架。它定义了「场景里有什么」「它们长什么样」「它们怎么动」以及「它们之间怎么组合」。
我个人习惯把USD比作「场景的JSON」。它不存储几何体的顶点数据本身(那是.usda或.usdc干的事),而是存储场景的结构、引用关系和属性覆盖。真正的大块数据,比如高精网格或纹理,通常以外部文件的形式被USD引用。
2.2 Stage与Layer:场景的骨架与层次
这两个概念是USD的基石。搞懂了它们,你就搞懂了USD的一半。
Stage(舞台)
Stage就是你的整个仿真场景。它包含所有物体、灯光、相机、物理属性、时间轴。在Isaac Sim里,你打开一个USD文件,其实就是加载了一个Stage。
Stage有一个根节点(Root Prim),下面挂载各种子节点。每个节点我们叫它Prim(基元)。Prim可以是一个机器人、一个传感器、一个平面,甚至一个空组。
小技巧:在Isaac Sim的Stage窗口中,你可以看到完整的Prim树形结构。我建议你养成习惯,每次导入模型后先看一眼Stage树,确认层级是否合理。我曾经遇到过CAD导出的模型,一个螺丝钉被拆成200多个独立Prim,仿真时物理引擎直接崩溃——就是因为Stage层级太扁平,没有合理分组。
Layer(层)
Layer是USD最强大的设计之一。它允许你把场景拆成多个「层」,每一层可以独立编辑、独立版本管理,最后叠加在一起形成最终的Stage。
举个例子:
- 基础层(Base Layer):放静态环境,比如地面、墙壁、传送带。
- 模型层(Model Layer):放机器人模型,引用自外部USD文件。
- 布局层(Layout Layer):调整机器人的位置和朝向。
- 物理层(Physics Layer):添加碰撞体、关节、刚体属性。
- 动画层(Animation Layer):录制或导入运动轨迹。
这些层按顺序叠加,后面的层会覆盖前面的层。如果你在布局层把机器人移动了1米,它不会影响基础层的地面——这就是Layer的「非破坏性编辑」特性。
| 概念 | 类比 | 关键特性 |
|---|---|---|
| Stage | 最终合成的电影 | 包含所有层叠加后的完整场景 |
| Layer | 电影的不同音轨/字幕轨 | 独立编辑、可叠加、可覆盖 |
| Prim | 电影里的一个演员或道具 | 有类型、属性、变换、关系 |
| Composition Arc | 导演的剪辑指令 | 定义层如何组合(引用、继承、变体等) |
注意:Layer的叠加顺序非常重要。如果你把物理层放在基础层下面,物理属性可能被基础层的默认值覆盖掉,导致碰撞体失效。我踩过这个坑——调试了整整一个下午,才发现是Layer顺序搞反了。
2.3 Omniverse Nucleus:团队的场景数据库
讲完了USD的文件结构,我们聊聊怎么存、怎么分享这些文件。这就是Nucleus登场的地方。
Nucleus本质上是一个协作式场景数据库。它运行在一台服务器(可以是本地工作站、云端或DGX Station)上,提供USD文件的存储、版本管理、实时同步和访问控制。
你想想看,如果团队里有5个人同时修改同一个仿真场景——A在调机器人位置,B在改材质,C在加传感器——没有Nucleus的话,大家只能互相传文件,然后祈祷不要覆盖别人的修改。有了Nucleus,每个人在自己的Layer上工作,Nucleus负责合并和冲突检测。
Nucleus的核心能力
- USD原生存储:直接存储.usd、.usda、.usdc文件,保留所有Layer和引用关系。
- 版本控制:每次保存都会生成一个新版本,可以随时回退。比Git更适合大文件。
- 实时同步(Live Sync):多用户同时编辑时,Nucleus会推送增量更新。你在Isaac Sim里能看到别人正在移动的物体实时变化。
- 权限管理:可以设置谁可以读、谁可以写、谁可以创建新版本。
- 连接器生态:Maya、Blender、UE5、CAD等软件都可以通过Connector直接读写Nucleus上的USD文件。
我的建议:即使你是一个人做仿真,我也推荐你搭建一个Nucleus服务器(哪怕就在本机)。原因很简单——版本管理。你改了一个模型,发现改坏了,想回到昨天那个版本。没有Nucleus的话,你只能祈祷自己记得备份。有了Nucleus,一键回退。我吃过这个亏,所以现在所有项目都跑在Nucleus上。
2.4 知识结构图:USD与Omniverse核心概念
下面这张图梳理了本章的核心逻辑。你可以把它当作一个思维导图来理解。
2.5 实际工作流:从文件到仿真场景
理论讲完了,我们看看实际中怎么用。下面是一个典型的USD场景导入流程:
- 准备USD资产:从CAD或DCC工具导出为USD格式。注意导出设置——单位、轴朝向、材质路径都要统一。
- 上传到Nucleus:把USD文件及其依赖的纹理、网格文件,一起上传到Nucleus服务器的指定项目目录。
- 创建Stage:在Isaac Sim中新建一个Stage,通过「Reference」或「Payload」方式引用Nucleus上的USD文件。
- 分层编辑:创建独立的Layer用于位置调整、物理属性添加、传感器配置等。每个Layer单独保存。
- 验证与迭代:运行仿真,检查物理行为、视觉表现。发现问题后,只修改对应的Layer,不影响其他部分。
关键原则:尽量保持「一个Layer只做一件事」。环境层只放环境,机器人层只放机器人,物理层只放物理属性。这样后期调试和团队协作都会轻松很多。
2.6 避坑指南
最后分享几个我实际项目中遇到的坑,希望能帮你少走弯路:
- 路径问题:USD文件中的引用路径,尽量使用相对路径或Nucleus的omniverse://协议。路径换台机器就崩了。
- 单位不一致:CAD导出的模型经常是毫米单位,而Isaac Sim默认用米。导入时一定要做单位转换,否则一个机器人可能变成摩天大楼。
- Layer污染:不要在基础层上直接修改模型位置。应该新建一个布局层来做这件事。否则后续想恢复原始位置就麻烦了。
- 版本号爆炸:Nucleus每次保存都会生成新版本。建议养成习惯,每次保存时写一句注释,说明改了哪里。不然一周后你面对几十个版本,根本分不清哪个是哪个。
嗯,这一章的内容就到这里。USD的概念确实有点抽象,但一旦你理解了Stage、Layer和Nucleus这三者的关系,后面的实操就会顺畅很多。记住一句话:Stage是结果,Layer是过程,Nucleus是底座。