录制仿真动画#

Isaac Lab 支持两种记录物理仿真动画的方法: 场景录制器 和 OVD 录制器 。两者都会生成可以在 Omniverse 中回放的 USD 输出,但它们在工作方式和使用场景上略有不同。

Stage Recorder 扩展监听仿真期间 USD 舞台中的所有运动和 USD 属性变化,并将它们记录为 按时间采样的数据 。生成的 USD 文件仅包含动画变化, 不包含 完整场景,其层级结构与录制时的原始舞台一致,因此可作为子图层添加,用于播放或渲染。

这种方法通过 BaseEnvWindow 内置在 Isaac Lab 的 UI 中。然而,为了记录仿真的动画,您需要禁用 Fabric ,以允许读取和写入所有更改(比如运动和 USD 属性)到 USD 场景。

OVD Recorder 旨在为更具可扩展性或自动化的工作流程而设计。它使用 OmniPVD 来捕获从播放场景中仿真的物理效果,然后直接将其“烘焙”到一个动画 USD 文件中。它支持 Fabric 功能,并可以通过 CLI 参数运行。通过在时间轴窗口中拖动来快速重播和查看动画 USD,无需进行昂贵的物理仿真操作。

备注

Omniverse 仅支持在 USD prim 上进行 物理仿真 或 动画播放 ,不可同时进行。对希望进行动画的 prim 禁用物理效果。

场景录制器#

在 Isaac Lab 中,场景记录器集成到 BaseEnvWindow 类中。这是捕捉物理仿真的最简单方式,并直接通过 UI 运行。

要记录,必须禁用 Fabric——这样才能让记录器跟踪 USD 的更改并将其写出。

场景录制器设置#

Isaac Lab 在 base_env_window.py 中使用明智的默认设置设置场景记录器。如果需要,您可以通过在 Omniverse Create 中直接使用场景记录器扩展来覆盖或检查这些设置。

在 base_env_window.py 中使用的设置
 1    def _toggle_recording_animation_fn(self, value: bool):
 2        """Toggles the animation recording."""
 3        if value:
 4            # log directory to save the recording
 5            if not hasattr(self, "animation_log_dir"):
 6                # create a new log directory
 7                log_dir = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
 8                self.animation_log_dir = os.path.join(os.getcwd(), "recordings", log_dir)
 9            # start the recording
10            _ = omni.kit.commands.execute(
11                "StartRecording",
12                target_paths=[("/World", True)],
13                live_mode=True,
14                use_frame_range=False,
15                start_frame=0,
16                end_frame=0,
17                use_preroll=False,
18                preroll_frame=0,
19                record_to="FILE",
20                fps=0,
21                apply_root_anim=False,
22                increment_name=True,
23                record_folder=self.animation_log_dir,
24                take_name="TimeSample",
25            )
26        else:
27            # stop the recording
28            _ = omni.kit.commands.execute("StopRecording")
29            # save the current stage
30            source_layer = self.stage.GetRootLayer()
31            # output the stage to a file
32            stage_usd_path = os.path.join(self.animation_log_dir, "Stage.usd")
33            source_prim_path = "/"
34            # creates empty anon layer
35            temp_layer = Sdf.Find(stage_usd_path)
36            if temp_layer is None:
37                temp_layer = Sdf.Layer.CreateNew(stage_usd_path)
38            temp_stage = Usd.Stage.Open(temp_layer)
39            # update stage data
40            UsdGeom.SetStageUpAxis(temp_stage, UsdGeom.GetStageUpAxis(self.stage))
41            UsdGeom.SetStageMetersPerUnit(temp_stage, UsdGeom.GetStageMetersPerUnit(self.stage))
42            # copy the prim
43            Sdf.CreatePrimInLayer(temp_layer, source_prim_path)
44            Sdf.CopySpec(source_layer, source_prim_path, temp_layer, source_prim_path)
45            # set the default prim
46            temp_layer.defaultPrim = Sdf.Path(source_prim_path).name
47            # remove all physics from the stage
48            for prim in temp_stage.TraverseAll():
49                # skip if the prim is an instance
50                if prim.IsInstanceable():
51                    continue
52                # if prim has articulation then disable it
53                if prim.HasAPI(UsdPhysics.ArticulationRootAPI):
54                    prim.RemoveAPI(UsdPhysics.ArticulationRootAPI)
55                    prim.RemoveAppliedSchema("PhysxArticulationAPI")
56                # if prim has rigid body then disable it
57                if prim.HasAPI(UsdPhysics.RigidBodyAPI):
58                    prim.RemoveAPI(UsdPhysics.RigidBodyAPI)
59                    prim.RemoveAppliedSchema("PhysxRigidBodyAPI")
60                # if prim is a joint type then disable it
61                if prim.IsA(UsdPhysics.Joint):
62                    prim.GetAttribute("physics:jointEnabled").Set(False)
63            # resolve paths so asset references remain valid from the new location
64            resolve_paths(source_layer.identifier, temp_layer.identifier)
65            # save the stage
66            temp_layer.Save()
67            # print the path to the saved stage
68            print("Recording completed.")
69            print(f"\tSaved recorded stage to    : {stage_usd_path}")
70            print(f"\tSaved recorded animation to: {os.path.join(self.animation_log_dir, 'TimeSample_tk001.usd')}")
71            print("\nTo play the animation, check the instructions in the following link:")
72            print(
73                "\thttps://docs.omniverse.nvidia.com/extensions/latest/ext_animation_stage-recorder.html#using-the-captured-timesamples"
74            )
75            print("\n")
76            # reset the log directory
77            self.animation_log_dir = None

示例用法#

在独立的 Isaac Lab 环境中,传递 --disable_fabric 标志:

python scripts/environments/state_machine/lift_cube_sm.py --num_envs 8 --device cpu --disable_fabric --viz kit

启动后,Isaac Lab UI 窗口将显示一个 "Record Animation" 按钮。点击开始录制。再次点击以停止。

以下文件被保存到 recordings/ 文件夹中:

  • Stage.usd — 禁用物理的原始场景

  • TimeSample_tk001.usd — 动画(时间采样)图层

回放时,打开 Isaac Sim:

uv run isaaclab -s
uv run isaaclab -s

在“Layers”面板中,插入 Stage.usd 和 TimeSample_tk001.usd 作为子图层。现在,当您点击播放按钮时,动画将开始播放。

查看 Omniverse 中的 图层教程 ,了解更多关于图层工作的信息。

OVD Recorder#

OVD 录制器 使用 OmniPVD 来记录仿真数据,并将其直接烘焙到新的 USD 场景中。这种方法更具可扩展性,更适合大规模训练场景(例如,多环境 RL)。

这不是通过用户界面控制的——整个过程是通过命令行标志启用的,并自动运行。

备注

OVD 录制器使用 OmniPVD,只能录制 PhysX 仿真。如果当前物理后端不是 PhysX(例如许多任务默认使用的 Newton),Isaac Lab 会在启动时报告错误并指出当前后端,而不会开始录制。请按下例在命令行添加 physics=isaacsim_physx ,选择 PhysX 后端。

PhysX 后端需要 Isaac Sim。如果尚未安装,在 uv run 命令中添加 --extra isaacsim ;详情见 可选依赖组 。

工作流程总结#

  1. 用户通过 CLI 运行 Isaac Lab ,启用动画录制。

  2. Isaac Lab 开始仿真

  3. OVD 数据在仿真运行时记录。

  4. 在指定的停止时间,仿真被烘烤成一个输出的 USD 文件,并关闭 IsaacLab。

  5. 最终结果是一个完全成型的、独立的 USD 动画

示例用法#

要记录动画:

uv run python scripts/tutorials/03_envs/run_cartpole_rl_env.py --anim_recording_enabled --anim_recording_start_time 1 --anim_recording_stop_time 3 physics=isaacsim_physx
uv run python scripts\tutorials\03_envs\run_cartpole_rl_env.py --anim_recording_enabled --anim_recording_start_time 1 --anim_recording_stop_time 3 physics=isaacsim_physx

备注

提供的 --anim_recording_stop_time 应大于仿真时间。

警告

当前,最终录制步骤可以从 [omni.usd] 中输出许多警告日志。这是一个已知问题,可以忽略这些警告消息。

停止时间达到后,文件将保存到:

anim_recordings/<timestamp>/baked_animation_recording.usda