Python API Reference#
High-level Python API for the ovphysx library.
Stream-Ordered Execution Model#
All operations in this API are stream-ordered, meaning they execute in submission order as if on a single queue. This provides sequential consistency:
Operations appear to complete in submission order
Writes from operation N are visible to operation N+1
You don’t need explicit synchronization between dependent operations
Independent operations may execute concurrently internally for performance
Example (no explicit waits needed between dependent operations):
usd_handle, _ = physx.add_usd("scene.usda") # Returns immediately
physx.step(dt, time) # Sees the USD load (stream-ordered)
binding = physx.create_tensor_binding(...) # Sees step results
binding.read(output) # Reads current state
Use wait_op() when:
Before accessing results outside the stream (e.g., reading data on CPU/GPU)
To ensure operations complete before program exit
For explicit synchronization points in your application
Thread Safety#
Multiple PhysX instances: fully thread-safe
Single instance: NOT thread-safe. Use external synchronization if calling from multiple threads
- class ovphysx.api.PhysX(
- settings: dict[str, bool | int | float | str] | None = None,
- ignore_version_mismatch: bool = False,
- device: str | int | None = None,
- gpu_index: int = 0,
Bases:
objectHigh-level wrapper around the C API using ctypes.
- add_usd(usd_path: str, path_prefix: str = '') tuple[int, int]#
Add USD file to stage (async, returns immediately).
- Parameters:
usd_path – Path to USD file
path_prefix – Optional prefix for all paths in USD
- Returns:
Tuple of (usd_handle, op_index). The usd_handle is used for remove_usd(). op_index can be used with wait_op() if you need explicit synchronization.
Examples
# Simple usage (stream-ordered) usd_handle, _ = physx.add_usd(“scene.usda”) physx.step(dt, time) # Automatically waits for USD to load
# Explicit synchronization (if needed before non-stream operations) usd_handle, op = physx.add_usd(“scene.usda”) physx.wait_op(op) # Ensure load completes before external access
- Preconditions:
usd_path must exist and be readable.
- Side effects:
Enqueues stage load and allocates runtime resources.
- Ownership/Lifetime:
The returned usd_handle is owned by this instance until remove_usd/reset.
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises RuntimeError on load or enqueue failure.
- clone(source_path: str, target_paths: list[str]) int#
Clone a USD prim hierarchy to create multiple Fabric-based copies (asynchronous, returns immediately).
Creates physics-optimized clones in Fabric for high-performance simulation. The source prim must exist in the loaded USD stage and have physics properties. Due to stream-ordered execution, subsequent operations automatically see the result of clone.
- Parameters:
source_path – USD path of the source prim hierarchy to clone (e.g., “/World/env0”)
target_paths – List of USD paths for the cloned hierarchies (e.g., [“/World/env1”, “/World/env2”])
- Returns:
op_index (can be used with wait_op() for explicit synchronization)
- Raises:
ValueError – If source_path is empty, target_paths is empty, or any target path matches source path
RuntimeError – If clone fails to queue or if no USD scene is loaded
- Preconditions:
A USD stage is loaded and source_path exists.
target_paths are unique and do not already exist.
- Side effects:
Creates cloned runtime prims that immediately participate in simulation.
- Ownership/Lifetime:
Clones remain valid until reset/remove_usd.
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises ValueError for invalid inputs.
Raises RuntimeError on enqueue or internal failure.
- create_tensor_binding(
- pattern: str | None = None,
- prim_paths: list[str] | None = None,
- tensor_type: int = ovphysx._bindings.OVPHYSX_TENSOR_RIGID_BODY_POSE_F32,
Create tensor binding for bulk physics data access (synchronous).
A tensor binding connects USD prims (by pattern or explicit paths) to a tensor type, enabling efficient bulk read/write of physics data.
- Parameters:
pattern – USD path glob pattern (e.g., “/World/robot*”, “/World/env[N]/robot”). Mutually exclusive with
prim_paths.prim_paths – Explicit list of prim paths. Mutually exclusive with
pattern.tensor_type – Tensor type enum value (
OVPHYSX_TENSOR_*).
- Returns:
TensorBinding object for reading/writing tensor data.
- Raises:
ValueError – If neither
patternnorprim_pathsis provided, or both are.RuntimeError – If binding creation fails.
Examples:
# Read all robot poses by pattern with physx.create_tensor_binding( "/World/robot*", tensor_type=OVPHYSX_TENSOR_RIGID_BODY_POSE_F32 ) as binding: poses = np.zeros(binding.shape, dtype=np.float32) binding.read(poses) # Set joint position targets for specific articulations binding = physx.create_tensor_binding( prim_paths=["/World/env1/robot", "/World/env2/robot"], tensor_type=OVPHYSX_TENSOR_ARTICULATION_DOF_POSITION_TARGET_F32, ) targets = np.zeros(binding.shape, dtype=np.float32) binding.write(targets) binding.destroy()
- Preconditions:
Exactly one of
patternorprim_pathsmust be provided.A USD stage is loaded.
- Side effects:
Allocates native binding resources.
- Ownership/Lifetime:
Returned TensorBinding owns native resources until
destroy().
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises
ValueErrorfor invalid arguments.Raises
RuntimeErroron creation failure.
- get_setting(key: str) str | None#
Get a Carbonite setting value.
- Parameters:
key – Setting path (e.g., “/physics/physxDispatcher”)
- Preconditions:
key must be a valid setting path.
- Side effects:
None.
- Ownership/Lifetime:
Returns a new Python string on success.
- Threading:
Safe to call from any thread.
- Errors:
Returns None if the lookup fails.
- get_stage_id() int#
Return the attached USD stage id.
- Preconditions:
Instance must be valid.
- Side effects:
None.
- Ownership/Lifetime:
Returned ID is owned by the runtime and may change after stage reload.
- Threading:
Do not call concurrently with stage mutation without external sync.
- Errors:
Returns -1 if the query fails.
- release() None#
Release PhysX instance.
- Preconditions:
Instance is valid and not in use by other threads.
- Side effects:
Releases native resources and unregisters the instance.
- Ownership/Lifetime:
The instance becomes unusable after release.
- Threading:
Do not call concurrently with other operations on this instance.
- Errors:
Errors during cleanup are suppressed for robustness.
- remove_usd(usd_handle: int) int#
Remove USD file from stage (async, returns immediately).
- Parameters:
usd_handle – Handle from add_usd()
- Returns:
op_index (can be used with wait_op() for explicit synchronization)
Example
# Simple usage (stream-ordered) physx.remove_usd(usd_handle) physx.step(dt, time) # Automatically waits for removal
- Preconditions:
usd_handle must be valid for this instance.
- Side effects:
Removes USD data from the runtime stage when complete.
- Ownership/Lifetime:
usd_handle becomes invalid after completion.
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises RuntimeError on failure.
- reset() int#
Reset stage to empty (async, invalidates all usd_handles).
- Returns:
op_index (can be used with wait_op() for explicit synchronization)
Example
# Simple usage (stream-ordered) physx.reset() usd_handle, _ = physx.add_usd(“new_scene.usda”) # Automatically waits for reset
- Preconditions:
Instance must be valid.
- Side effects:
Clears the runtime stage and invalidates all USD handles.
- Ownership/Lifetime:
All previously returned usd_handles become invalid after completion.
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises RuntimeError on failure.
- set_setting(key: str, value: bool | int | float | str) None#
Set a Carbonite setting at runtime.
- Parameters:
key – Setting path (e.g., “/physics/physxDispatcher”)
value – Setting value (bool, int, float, or str)
- Preconditions:
key must be a valid setting path.
- Side effects:
Updates a process-global setting affecting all instances.
- Ownership/Lifetime:
Values are copied to native strings during the call.
- Threading:
Safe to call from any thread; avoid concurrent configuration changes.
- Errors:
Raises RuntimeError on failure.
- step(dt: float, sim_time: float) int#
Initiate physics step (async, returns op_index).
- Parameters:
dt – Delta time for this step
sim_time – Current simulation time
- Returns:
op_index (can be used with wait_op() for explicit synchronization)
Examples
# Simple usage (stream-ordered) physx.step(0.016, 0.0) binding.read(output) # Automatically waits for step
# Explicit wait (if accessing results outside stream) op = physx.step(0.016, 0.0) physx.wait_op(op) # Ensure step completes before external GPU work
- Preconditions:
A USD stage is loaded if physics content is expected.
- Side effects:
Advances simulation time and mutates physics state.
- Ownership/Lifetime:
Returned op_index is single-use and must be waited once if needed.
- Threading:
Do not call concurrently on the same instance without external sync.
- Errors:
Raises RuntimeError on failure to enqueue.
- wait_all(timeout_ns: int | None = None) None#
Wait for all pending operations (convenience wrapper for wait_op(ALL)).
- Parameters:
timeout_ns – Timeout in nanoseconds (None = infinite, 0 = poll)
- Preconditions:
Instance must be valid.
- Side effects:
Blocks until all pending ops complete or timeout.
- Threading:
Safe to call if no other thread is waiting on specific op_indices.
- Errors:
Raises RuntimeError on failure.
Raises TimeoutError if timeout expired (e.g., when polling with timeout_ns=0 and operations are not ready).
- wait_op(op_index: int, timeout_ns: int | None = None) None#
Wait for operation(s) to complete.
- Parameters:
op_index – Operation index to wait for, or OVPHYSX_OP_INDEX_ALL for all ops
timeout_ns – Timeout in nanoseconds (None = infinite, 0 = poll)
- Raises:
RuntimeError – If operation failed
TimeoutError – If timeout expired (e.g., when polling with timeout_ns=0 and the operation is not ready)
- Preconditions:
op_index must be valid and not previously consumed.
- Side effects:
Consumes op_index on successful wait.
- Ownership/Lifetime:
Error strings returned by the API are destroyed internally.
- Threading:
Do not wait on the same op_index from multiple threads.
- warmup_gpu() None#
Explicitly initialize GPU buffers (synchronous).
In GPU mode, PhysX DirectGPU buffers need one simulation step to initialize. This is normally done automatically on the first tensor read (auto-warmup).
Call this function explicitly if you want to: - Control exactly when the warmup latency occurs - Avoid a latency spike on the first tensor read - Verify GPU initialization succeeded before starting your main loop
This function is idempotent - calling it multiple times has no effect after the first successful call. In CPU mode, this is a no-op.
- Raises:
RuntimeError – If GPU warmup fails.
- Preconditions:
Instance is configured for GPU mode.
- Side effects:
Advances simulation by a minimal timestep on first call.
- Ownership/Lifetime:
No ownership changes; affects current stage state.
- Threading:
Do not call concurrently with other operations on this instance.
- class ovphysx.api.TensorBinding(
- sdk,
- handle: int,
- tensor_type: int,
- ndim: int,
- shape: tuple,
Bases:
objectTensor binding for bulk physics data access via DLPack.
A tensor binding connects a USD prim pattern to a tensor type, enabling efficient bulk read/write of physics data (poses, velocities, joint positions, etc.).
This is a synchronous API - operations complete before returning.
Usage patterns:
Context manager (auto-cleanup):
with physx.create_tensor_binding("/World/robot*", OVPHYSX_TENSOR_RIGID_BODY_POSE_F32) as binding: poses = np.zeros(binding.shape, dtype=np.float32) binding.read(poses) # ... modify poses ... binding.write(poses) # Auto-destroyed here
Manual (explicit cleanup):
binding = physx.create_tensor_binding("/World/robot*", OVPHYSX_TENSOR_RIGID_BODY_POSE_F32) poses = np.zeros(binding.shape, dtype=np.float32) binding.read(poses) binding.destroy()
- property count: int#
Get number of entities (first dimension of shape).
- destroy() None#
Release binding resources.
Safe to call multiple times. Called automatically on garbage collection or when exiting a context manager.
- Preconditions:
Binding must not be in use by other threads.
- Side effects:
Releases native resources and invalidates the binding.
- Ownership/Lifetime:
After destruction, the binding cannot be used.
- Threading:
Serialized per binding via an internal lock.
- Errors:
RuntimeError if destruction fails.
- property handle: int#
Get the binding handle.
- property ndim: int#
Get the number of dimensions (2 or 3).
- read(tensor) None#
Read simulation data into a user-provided tensor (synchronous).
The tensor must have matching shape and dtype (float32). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.
- Parameters:
tensor – DLPack-compatible tensor with pre-allocated storage matching self.shape. Must be float32 on matching device (CPU or GPU).
- Preconditions:
This binding is not destroyed.
tensor has matching shape, dtype (float32), and device.
- Side effects:
Blocks until data is available and writes into the provided tensor.
- Ownership/Lifetime:
Caller owns tensor storage and must keep it alive for the duration of the call.
- Threading:
Serialized per binding via an internal lock.
- Errors:
RuntimeError if read fails (shape mismatch, device mismatch, etc.).
- property shape: tuple#
Get tensor shape as tuple.
- Returns:
(N, C) where N=count, C=components (e.g., 7 for pose, 6 for velocity) - 3D tensors: (N, L, C) where L=links for articulation link data
- Return type:
2D tensors
- property tensor_type: int#
Get the tensor type enum value.
- write(tensor, indices=None, mask=None) None#
Write data from a user-provided tensor into the simulation (synchronous).
The tensor must have matching shape and dtype (float32). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.
- Parameters:
tensor – DLPack-compatible tensor with data to write, shape matching self.shape. Must be float32 on matching device (CPU or GPU).
indices – Optional int32 tensor of indices for partial update. If provided, only the rows at the given indices are written. The tensor argument must still be full shape [N, …] matching the binding spec; only the selected rows are applied. Shape of indices: [K] where K <= N.
mask –
Optional bool/uint8 tensor for masked update. If provided, only elements where mask[i] != 0 are written. Shape: [N] matching the binding’s first dimension. When mask is provided, tensor must be full shape [N, …]. If both mask and indices are provided, mask takes precedence and indices are ignored (with a warning).
Note: there is no corresponding
read(..., mask=...); reads always return the full [N,…] tensor and callers can index the result themselves. This write-only mask design matches other RL physics APIs such as Newton’s selectionAPI, where masks selectively apply actions but observations are always returned in full.
- Preconditions:
This binding is not destroyed.
tensor matches shape, dtype (float32), and device.
indices (if provided) is int32 and within bounds.
mask (if provided) is bool/uint8 with shape [N] on matching device.
- Side effects:
Updates simulation state for the bound entities.
- Ownership/Lifetime:
Caller owns tensor/indices/mask storage and must keep it alive for the call.
- Threading:
Serialized per binding via an internal lock.
- Errors:
RuntimeError if write fails (shape mismatch, device mismatch, etc.).
- ovphysx.api.disable_python_logging() None#
Stop routing native log messages to Python’s logging module.
If
enable_python_logging()was not called, this is a no-op.
- ovphysx.api.enable_default_log_output(enable: bool = True) None#
Enable or disable Carbonite’s built-in console log output.
By default, Carbonite logs to the console. When custom callbacks are registered (or
enable_python_logging()is active), both the built-in console output and the callbacks receive messages, which may cause duplicate output.Call with
Falseto suppress the built-in console output while keeping callbacks active. Call withTrueto re-enable it.This is independent of callback registration and the global log level.
- Parameters:
enable –
Trueto enable (default),Falseto disable.
- ovphysx.api.enable_python_logging(logger_name: str = 'ovphysx') None#
Route native log messages to Python’s logging module.
Registers a C-level callback that forwards every message (at or above the global log level) to
logging.getLogger(logger_name)at the corresponding Python log level.Call
disable_python_logging()to stop forwarding.- Parameters:
logger_name – Name of the Python logger to route to (default: “ovphysx”).
- ovphysx.api.get_log_level() int#
Get the current global log level threshold.
- Returns:
The current log level (int matching ovphysx_log_level_t constants).
- ovphysx.api.set_log_level(level: int) None#
Set the global log level threshold.
Messages below this level are suppressed for all outputs (console and registered callbacks). Callable at any time, including before instance creation.
- Parameters:
level – Log level threshold (OVPHYSX_LOG_NONE through OVPHYSX_LOG_VERBOSE). Default: OVPHYSX_LOG_WARNING.
- Raises:
ValueError – If level is out of range. No state change is applied.