Isaac Lab 动画录制实战:Stage Recorder 与 OVD Recorder 双通道生成可回放 USD 动画
【免费下载链接】IsaacLabUnified framework for robot learning built on NVIDIA Isaac Sim项目地址: https://gitcode.com/GitHub_Trending/is/IsaacLab
Isaac Lab 提供了两套将物理仿真结果导出为 USD 动画的机制:Stage Recorder(UI 驱动,监听舞台上所有运动与 USD 属性变化并记录为时间采样数据)和OVD Recorder(CLI 驱动,基于 OmniPVD 抓取仿真状态并烘焙成自包含的动画 USD)。本文基于仓库中 动画录制指南 与相关源码实现,完整讲解两种方式的适用场景、命令行参数、产物结构与回放步骤,并给出源码级的实现依据,帮助你在视觉调试、数据审查、多环境训练复盘等场景下选择合适的录制方案。
两种录制方式的定位差异
Isaac Lab 的两种动画录制方案都生成可在 Omniverse 中回放的 USD 输出,但工作机制与使用方式完全不同:
| 维度 | Stage Recorder | OVD Recorder |
|---|---|---|
| 实现机制 | 监听舞台上所有运动与 USD 属性变化,记录为时间采样数据(time-sampled data) | 使用 OmniPVD(omni.physx.pvd)抓取播放舞台中的物理仿真状态,**烘焙(bake)**进动画 USD |
| 输出结构 | 只捕获动画变化的层,不复制完整场景,层级与原舞台一致,可作为子层(sublayer)叠加回放 | 输出完全烘焙、自包含的单个 USD 动画文件 |
| Fabric 要求 | 必须禁用Fabric,以便读写舞台上所有 USD 变更 | Fabric 开启状态下即可工作 |
| 触发方式 | UI 中 "Record Animation" 按钮手动启停 | CLI 参数自动启用,到达停止时间后自动烘焙并退出 |
| 适用场景 | 少量环境的可视化捕捉、交互式调试 | 大规模、自动化工作流(如多环境 RL 训练) |
| 底层入口 | BaseEnvWindow | app_launcher.py + physx_manager.py |
从源码结构看,两者的实现分处不同包:Stage Recorder 集成在核心包isaaclab的环境 UI 层;OVD Recorder 的 CLI 参数解析在isaaclab的AppLauncher中,而真正读取 OVD 文件并烘焙 USD 的逻辑位于 PhysX 后端包isaaclab_physx的physx_manager.py中,这与 OVD Recorder 依赖omni.physx.pvd扩展的事实相吻合。
关键前提:Omniverse 中物理与动画互斥
一个必须牢记的平台限制:Omniverse 对同一个 USD prim 只支持物理仿真或动画回放二者之一,不能同时存在。因此想回放某个 prim 的动画,必须先在其上禁用物理。Isaac Lab 在 Stage Recorder 停止录制时已自动处理了这一点(见下文“物理 API 剥离”),使用 OVD Recorder 时若回放报错,也应首先检查目标 prim 是否仍携带物理 API。
Stage Recorder:通过 UI 录制时间采样动画
Stage Recorder 是 Omniverse 的官方扩展,Isaac Lab 将其集成进 BaseEnvWindow 类。这是最直观的可视化捕捉方式:启动带 UI 的仿真后,窗口中会出现 "Record Animation" 按钮,点击开始、再次点击停止。
前提条件:禁用 Fabric
Stage Recorder 要求禁用 Fabric才能跟踪并写出 USD 变更。在 Isaac Lab 的独立环境中,通过--disable_fabric启动参数即可满足该条件:
python scripts/environments/state_machine/lift_cube_sm.py --num_envs 8 --device cpu --disable_fabric --viz kit从源码看,Fabric 状态直接影响 UI 按钮的可用性。在 base_env_window.py 中,"Record Animation" 状态按钮的enabled属性被设置为not self.env.sim.get_setting("/isaaclab/fabric_enabled")——也就是说,当 Fabric 开启时按钮直接处于禁用状态,这与文档中“必须禁用 Fabric 才能录制”的要求一致,也解释了按钮 tooltip 中 "Only effective if fabric is disabled" 的提示。
源码视角:录制开关到底做了什么
Stage Recorder 的启停逻辑集中在 BaseEnvWindow._toggle_recording_animation_fn 中,这一方法也是文档所引用的默认配置来源(base_env_window.py内已内置合理默认值,如需调整可在 Omniverse Create 中直接打开 Stage Recorder 扩展检查):
- 开始录制(value=True):创建一个带时间戳的日志目录
recordings/<YYYY-MM-DD_HH-MM-SS>/(以当前工作目录为基准),然后执行 Kit 命令StartRecording,关键参数包括:target_paths=[("/World", True)]:只录制/World子树;record_to="FILE"、live_mode=True、use_frame_range=False:实时录制到文件、不限帧区间;take_name="TimeSample"、increment_name=True:动画层的命名前缀,自动递增生成TimeSample_tk001.usd等文件。
- 停止录制(value=False):执行
StopRecording后,将当前舞台另存为Stage.usd,并在导出过程中剥离所有物理 API——对每个非实例化的 prim,若带有UsdPhysics.ArticulationRootAPI或UsdPhysics.RigidBodyAPI,则移除该 API 及PhysxArticulationAPI/PhysxRigidBodyAPI应用;若 prim 是UsdPhysics.Joint,则将physics:jointEnabled设为False。最后通过resolve_paths解决资产引用路径,保证 USD 资产引用在新位置仍然有效。
这正是前述“物理与动画互斥”限制的自动化处理:导出的Stage.usd天生就是一个无物理、可直接回放的舞台。
产物与回放步骤
停止录制后,recordings/目录下会保存两个文件:
Stage.usd—— 原始舞台的快照(物理已剥离);TimeSample_tk001.usd—— 时间采样动画层(只含动画变化,层级与原舞台一致)。
回放方式:打开 Isaac Sim(Linux 下./isaaclab.sh -s,Windows 下isaaclab.bat -s,入口脚本为 isaaclab.sh),在Layers 面板中将Stage.usd与TimeSample_tk001.usd都作为 sublayer 插入,按下播放键即可回放动画。停止录制时程序也会在终端打印两个产物路径及 Omniverse 官方 Stage Recorder 文档中 "Using the captured timesamples" 一节的链接,便于核对。
OVD Recorder:CLI 驱动的自动化烘焙录制
OVD Recorder 面向更可扩展、可自动化的工作流:它通过 OmniPVD 记录仿真过程中的物理状态,并在指定时刻将其烘焙为一个自包含的动画 USD 文件。整个过程不依赖 UI,全部由 CLI 参数控制,非常适合大规模训练场景(如多环境 RL)的批量复盘。
工作流程
文档给出的标准流程为:
- 用户通过 CLI 参数启动 Isaac Lab 并启用动画录制;
- Isaac Lab 启动仿真;
- 仿真运行期间持续记录 OVD 数据;
- 到达指定停止时间后,仿真被烘焙成输出的 USD 文件,Isaac Lab 随即关闭;
- 最终得到一个完全烘焙、自包含的 USD 动画,可在时间轴窗口中直接拖动回放,无需再运行昂贵的物理仿真。
CLI 参数与默认值
参数定义位于 AppLauncher 的命令行解析中,共三个:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
--anim_recording_enabled | store_true | 关 | 启用从 Isaac Lab PhysX 仿真中录制时间采样 USD 动画 |
--anim_recording_start_time | float | 0 | 动画录制开始播放的时刻,不设置则从仿真开始录制 |
--anim_recording_stop_time | float | 10 | 动画录制停止播放的时刻;若进程在到达停止时间前被关闭,则不会产出录制结果 |
示例命令(来自文档):
python scripts/tutorials/03_envs/run_cartpole_rl_env.py --anim_recording_enabled --anim_recording_start_time 1 --anim_recording_stop_time 3源码视角:参数校验与扩展启用
参数并非直接生效,而是经过两步解析(均在 app_launcher.py 中):
- _resolve_anim_recording_settings:若启用了录制,首先检查无头模式(headless)下不支持动画录制并抛出
ValueError;随后向sys.argv追加--enable omni.physx.pvd,即在 Kit 启动时加载 OVD 捕获所需的扩展。 - _set_animation_recording_settings:校验
anim_recording_start_time必须小于anim_recording_stop_time(否则抛出带具体数值的ValueError),然后把三个设置写入 settings 体系:/isaaclab/anim_recording/enabled(bool)/isaaclab/anim_recording/start_time(float)/isaaclab/anim_recording/stop_time(float)
这些 settings 供后续仿真流程读取,从而在停止时刻触发烘焙。
烘焙链路:从 OVD 到 USD
OVD 数据最终由 PhysX 后端消费。在 physx_manager.py 中,PhysXManager通过from omni.physxpvd.bindings import _physxPvd获取 PVD 接口(_physxPvd.acquire_physx_pvd_interface());当检测到 OVD 文件且 PVD 可用时,调用ovd_to_usd_over_with_layer_creation将 OVD 数据转换为baked_animation_recording.usda,并对生成文件做起始时间修正(_update_usda_start_time)。
产物与已知注意事项
达到停止时间后,录制文件保存至:
anim_recordings/<timestamp>/baked_animation_recording.usda两点使用注意(文档原文提示):
--anim_recording_stop_time应大于仿真实际运行时长,否则录制窗口可能覆盖不到你想留存的仿真阶段;- 最终录制步骤可能输出大量来自
omni.usd的 warning 日志,这是已知问题,可以安全忽略。
如何选择与落地要点
综合两种方式的特点,选择建议如下:
- 需要人工挑选录制时机、只录少量环境、希望产物与原舞台层级严格对应:用 Stage Recorder。注意必须带
--disable_fabric启动,回放时需手动把Stage.usd与TimeSample_tk001.usd插为子层。 - 需要无人值守、可脚本化批量产出、或训练环境数量较大:用 OVD Recorder。注意必须非无头运行(源码中 headless 会直接抛错)、停止时间大于仿真时长,并接受产物为单个烘焙 USD(无需再组装舞台层)。
两种方式共同的底层约束是 Omniverse 的“物理与动画互斥”规则:Stage Recorder 在导出Stage.usd时已自动移除ArticulationRootAPI、RigidBodyAPI、PhysxArticulationAPI、PhysxRigidBodyAPI并禁用关节(见 base_env_window.py#L349-L364),而使用 OVD 产物或其他外部录制结果回放时,若出现回放失败,应检查目标 prim 上的物理 API 是否已移除。
参考文件汇总:
- 文档:动画录制指南
- Stage Recorder 实现:base_env_window.py、录制启停与物理剥离
- OVD Recorder CLI 与设置解析:app_launcher.py 参数定义、扩展启用、settings 写入与校验
- OVD 烘焙:physx_manager.py
- 示例脚本:lift_cube_sm.py、run_cartpole_rl_env.py
【免费下载链接】IsaacLabUnified framework for robot learning built on NVIDIA Isaac Sim项目地址: https://gitcode.com/GitHub_Trending/is/IsaacLab
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考