Skip to content

[OVPHYSX] Improve USD integration to avoid disk dumps #5324

@AntoineRichard

Description

@AntoineRichard

Summary

Replace the disk-based USD export in `OvPhysxManager` with an in-memory transfer. Currently the USD stage is exported to a temp file and reloaded — this disk round-trip is unnecessary overhead.

Current Flow

  1. `stage.Export(tmp_path)` — write USD to disk
  2. `physx.add_usd(tmp_path)` — read USD from disk

Desired Flow

  1. `stage.ExportToString()` — serialize to string in memory
  2. `physx.add_usd_from_string(string)` — load directly from memory

OVPhysX Blocker for @marcodiiga

Add `physx.add_usd_from_string()` (or `add_usd_from_bytes()`) to the ovphysx Python API. The C++ side likely already parses USD from a buffer — this just needs a Python binding.

IsaacLab-Side Changes

~10 lines in `ovphysx_manager.py` — replace file export/load with string export/load, remove temp file cleanup.

Spec

Full design spec: `docs/superpowers/specs/2026-04-20-ovphysx-usd-integration-design.md`

Parent issue: #5315


📋 Full Design Spec (click to expand)

OVPhysX USD Integration Improvement — Design Spec

Issue: #5324 — [OVPHYSX] Improve USD integration to avoid disk dumps
Date: 2026-04-20
Status: Draft

Summary

Currently, OvPhysxManager exports the USD stage to a temporary file on disk and then loads it back into the ovphysx PhysX instance. This disk round-trip is unnecessary overhead and introduces temp file management complexity. The goal is to pass the USD stage directly to ovphysx without writing to disk.

Current Problem

From OvPhysxManager._warmup_and_load():

  1. The in-memory USD stage is exported to a temp .usda file via stage.Export()
  2. ovphysx loads the file via physx.add_usd(temp_path)
  3. The temp file persists until process exit

Issues:

  • Performance: Disk I/O is slow for large scenes (many environments, complex assets)
  • Reliability: Temp file may not be cleaned up on crash
  • Containerization: Some container environments have limited temp storage
  • Security: USD file on disk may contain sensitive scene data

Desired State

Pass the USD stage directly to ovphysx via an in-memory API, eliminating the disk round-trip entirely.

Approach Options

Option A: In-memory USD string (ovphysx API addition)

Add an ovphysx API that accepts a USD string/bytes instead of a file path:

# Current
physx.add_usd("/tmp/exported_scene.usda")

# Proposed
usd_string = stage.ExportToString()
physx.add_usd_from_string(usd_string)

Or using flatbuffers/binary format:

usd_bytes = stage.Flatten().ExportToString()  # or binary format
physx.add_usd_from_bytes(usd_bytes)

Option B: Shared memory / file descriptor

Use a file descriptor or shared memory segment instead of a named file:

import io
buffer = io.BytesIO()
stage.Export(buffer)  # if pxr supports stream export
physx.add_usd_from_fd(buffer.fileno())

Risk: USD's Export() may only support file paths, not streams.

Option C: Direct scene graph transfer

Instead of going through USD serialization at all, transfer the scene graph directly:

  • Iterate prims in the USD stage
  • Call ovphysx APIs to create physics objects directly
  • Skip serialization entirely

Risk: High complexity, essentially reimplementing USD loading in Python.

Recommendation

Option A (in-memory USD string) is the cleanest. It requires @marcodiiga to add add_usd_from_string() or similar to the ovphysx Python API. The IsaacLab side change is minimal (replace stage.Export(path) + physx.add_usd(path) with stage.ExportToString() + physx.add_usd_from_string(string)).

Blocker for @marcodiiga: Add an in-memory USD loading API to ovphysx. The C++ side likely already parses USD from a buffer — this just needs a Python binding that passes the buffer directly instead of reading from a file path.

Implementation Steps

  1. @marcodiiga adds physx.add_usd_from_string() to ovphysx wheel
  2. Update OvPhysxManager._warmup_and_load():
    • Replace stage.Export(tmp_path) with stage.ExportToString()
    • Replace physx.add_usd(tmp_path) with physx.add_usd_from_string(usd_string)
    • Remove temp file creation and cleanup
  3. Remove the atexit temp file cleanup handler

Dependencies

Estimated Scope

  • IsaacLab-side changes: ~10 lines in ovphysx_manager.py
  • ovphysx-side: new Python binding for in-memory USD loading

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions