Skip to content

[Bug Report] Inconsistent Behavior and Frame Rate for loading USD Asset with Physics via GUI and Standalone Python #5144

@ganzh6880

Description

@ganzh6880

Describe the bug

When loading the same pre-saved scene with physics settings:

  • Using the GUI:

    • Initial FPS starts around 15–17 FPS
    • After assets settle (a few minutes), FPS improves to ~55–60 FPS
  • Using a standalone Python script to load the exact same scene:

    • FPS remains consistently low at ~6–8 FPS
    • No improvement over time, even after assets have fully settled

This suggests a discrepancy between how the GUI and standalone script handle simulation stepping, rendering, or physics initialization.


Steps to reproduce

  1. Open Isaac Sim GUI

  2. Load the pre-saved scene with physics settings

  3. Press play and observe:

    • Initial FPS (~15–17)
    • FPS after settling (~55–60)
  4. Run the standalone Python script:

#!/usr/bin/env python3
# Copyright (c) 2022-2026, The Isaac Lab Project Developers
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause

"""
Standalone scene loader for Isaac Lab.

Creates:
1. Default ground plane
2. Dome light
3. A user-specified USD asset

Example:
    ./isaaclab.sh -p scripts/interactive-search/scripts/load_usd_asset_standalone.py \
      --usd_path scripts/bedroom1/export_scene.blend/export_scene.usdc
"""

from __future__ import annotations

import argparse
from pathlib import Path

from isaaclab.app import AppLauncher


def _resolve_usd_path(path_str: str) -> str:
    """Resolve local file paths and keep non-local (e.g. Nucleus) paths unchanged."""
    if not path_str:
        return path_str
    candidate = Path(path_str).expanduser()
    if candidate.exists():
        return str(candidate.resolve())
    return path_str


parser = argparse.ArgumentParser(description="Spawn a ground plane, a light, and a USD asset in Isaac Lab.")
parser.add_argument(
    "--usd_path",
    type=str,
    default="scripts/bedroom1/export_scene.blend/export_scene.usdc",
    help="Path to USD/USDC to load (local path or Nucleus path).",
)
parser.add_argument(
    "--asset_prim_path",
    type=str,
    default="/World/Asset",
    help="Prim path for the spawned USD asset.",
)
parser.add_argument(
    "--asset_pos",
    type=float,
    nargs=3,
    default=(0.0, 0.0, 0.0),
    metavar=("X", "Y", "Z"),
    help="World position for the spawned asset (meters).",
)
parser.add_argument(
    "--asset_rot",
    type=float,
    nargs=4,
    default=(1.0, 0.0, 0.0, 0.0),
    metavar=("W", "X", "Y", "Z"),
    help="World orientation quaternion for the spawned asset (w, x, y, z).",
)
parser.add_argument("--light_intensity", type=float, default=3000.0, help="Dome light intensity.")
parser.add_argument("--physics_dt", type=float, default=1.0 / 120.0, help="Physics time-step.")
parser.add_argument("--rendering_dt", type=float, default=1.0 / 60.0, help="Rendering time-step.")

# append AppLauncher cli args
AppLauncher.add_app_launcher_args(parser)
args_cli = parser.parse_args()

# launch omniverse app
app_launcher = AppLauncher(args_cli)
simulation_app = app_launcher.app

"""Rest everything follows."""

import isaaclab.sim as sim_utils
from isaaclab.assets import AssetBaseCfg


def main() -> None:
    usd_path = _resolve_usd_path(args_cli.usd_path)

    # Initialize simulation.
    sim_cfg = sim_utils.SimulationCfg(
        device=args_cli.device,
        dt=args_cli.physics_dt,
        render_interval=max(1, round(args_cli.rendering_dt / args_cli.physics_dt)),
    )
    sim = sim_utils.SimulationContext(sim_cfg)
    sim.set_camera_view(eye=[4.0, 4.0, 3.0], target=[0.0, 0.0, 0.5])

    # Spawn default ground plane.
    ground_cfg = sim_utils.GroundPlaneCfg()
    ground = AssetBaseCfg(prim_path="/World/defaultGroundPlane", spawn=ground_cfg)
    ground.spawn.func(ground.prim_path, ground.spawn)

    # Spawn dome light.
    light_cfg = sim_utils.DomeLightCfg(intensity=args_cli.light_intensity, color=(0.75, 0.75, 0.75))
    light = AssetBaseCfg(prim_path="/World/Light", spawn=light_cfg)
    light.spawn.func(light.prim_path, light.spawn)

    # Spawn USD asset.
    asset_cfg = AssetBaseCfg(
        prim_path=args_cli.asset_prim_path,
        init_state=AssetBaseCfg.InitialStateCfg(pos=tuple(args_cli.asset_pos), rot=tuple(args_cli.asset_rot)),
        spawn=sim_utils.UsdFileCfg(usd_path=usd_path),
    )
    asset_cfg.spawn.func(
        asset_cfg.prim_path,
        asset_cfg.spawn,
        translation=asset_cfg.init_state.pos,
        orientation=asset_cfg.init_state.rot,
    )

    sim.reset()
    print("[INFO] Scene ready.")
    print(f"[INFO] Loaded USD: {usd_path}")
    print(f"[INFO] Prim path: {args_cli.asset_prim_path}")

    while simulation_app.is_running():
        sim.step()


if __name__ == "__main__":
    main()
    simulation_app.close()

<!-- Failed to upload "export_scene_real_last_physics.zip" -->

  1. Observe FPS:
    • Stays at ~6–8 FPS consistently
    • No improvement after waiting for scene to settle

System Info

  • Commit: main (latest)
  • Isaac Sim Version: 5.1.0
  • Isaac Lab Version: 2.3.2 (Docker)
  • OS: Ubuntu 24.04
  • GPU: RTX 4090 x2
  • CUDA: 12.6
  • GPU Driver: 560.35.03

Additional context

  • The scene is identical in both cases (same saved USD and physics settings).

  • The GUI version clearly shows a warm-up / settling phase where performance improves significantly.

  • The standalone script does not exhibit this behavior, suggesting possible differences in:

    • Simulation stepping loop
    • Rendering pipeline
    • GPU utilization / device selection
    • Physics solver warm-up or async behavior
  • Docker environment is used (IsaacLab 2.3.2

), unsure if this contributes.

Attachments (to be included):

  • 2x screenshots: GUI (initial low FPS)
  • 2x screenshots: GUI (after settling high FPS)
  • 1x screenshot: standalone script FPS
  • 1x screenshot: GUI loading scene/assets
  • Standalone script (see placeholder above)

Checklist

  • I have checked that there is no similar issue in the repo (required)
  • I have checked that the issue is not in running Isaac Sim itself and is related to the repo

Acceptance Criteria

  • Explanation for why GUI and standalone script show significantly different FPS behavior
  • Identification of missing configuration / steps in standalone script (if expected behavior)
  • Fix or guidance to achieve comparable FPS (~55–60 FPS after settling) in standalone mode
Image Image Image Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions