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):

Listing 1 Stream-ordered operation sequence#
 physx.attach_ovstage(stage, read_ordinal=initial_ordinal)
 # After the application authors later ovstage edits:
 physx.update_from_ovstage(from_ordinal, to_ordinal)
 physx.step(dt)                               # Sees the drained stage edits
 binding = physx.create_tensor_binding(
     "/World/Cube", tensor_type=TensorType.RIGID_BODY_POSE
 )  # 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#

  • PhysX instances share the underlying omni.physx runtime. Serialize simulation, stage mutation, and binding creation across instances.

  • A single instance is NOT thread-safe. Use external synchronization if calling from multiple threads.

  • ctypes releases the GIL during native calls, so concurrent step() and TensorBinding.read() / write() from different threads is a data race. See the developer guide threading section for the recommended pattern.

Core Classes#

class ovphysx.api.PhysX(
config: PhysXConfig | None = None,
ignore_version_mismatch: bool = False,
active_cuda_gpus: str | None = None,
)#

Bases: object

High-level wrapper around the C API using ctypes.

attach_ovstage(stage, read_ordinal: int = 1) None#

Attach an ovstage Stage as the orchestration data surface.

Attach performs the initial scene parse at read_ordinal. After the producer authors later ovstage edits, call update_from_ovstage() with only those subsequent ordinals. Tensor bindings remain available as a perf escape hatch.

Parameters:
  • stage – An ovstage.Stage or a raw ovstage_instance_t* handle.

  • read_ordinal – Caller-owned sealed ovstage ordinal the initial scene parse reads at. The application owns ordinal advancement; defaults to 1 (read from the first sealed ordinal).

Preconditions:
  • Instance must be valid.

  • Not already attached to a Stage.

Lifetime:
  • stage must outlive the attachment because ovphysx captures and dereferences its native pointer until detach. This wrapper holds a reference to stage for the duration of the attachment, so a Stage created inline (attach_ovstage(ovstage.Stage(...))) stays alive; the reference is dropped by detach_ovstage() and release().

Errors:
  • Raises RuntimeError if already attached, stage is null, or the runtime attach fails. Instance remains unattached on failure.

clone(
source_path: str,
target_paths: list[str],
parent_transforms: list[tuple[float, float, float, float, float, float, float]] | None = None,
env_ids: list[int] | None = None,
) int#

Clone a prim hierarchy to create multiple runtime physics copies.

Creates physics-optimized clones in the runtime representation for high-performance simulation, backed by the PhysX SDK replicator so cloned articulations are real articulations. The source prim must exist in the loaded stage and have physics properties. Replication executes inline. The returned operation index is already complete, so subsequent operations see the clone immediately and wait_op() returns immediately.

This is the clone entrypoint for both standalone callers and callers that populate the scene through an ovstage Stage attached via attach_ovstage(). Replication runs in the internal representation only (USD untouched).

Cross-environment collision filtering can optionally use PhysX environment ids, controlled by the /ovphysx/clone/useEnvIds setting (default: on). When enabled and the scene runs GPU dynamics + GPU broadphase, each cloned environment gets a distinct environment id so copies in different environments do not collide. The source environment is included: its bodies are created holding environment id 0 (assigned as the attach parses them; clones get 1..N), so co-located clones (parent_transforms=None) are collision-isolated from the source as well. Like all carbonite settings it is per-process (shared by every ovphysx instance in the process), so set it consistently before attaching.

When one logical environment is assembled from SEVERAL clone calls (e.g. an IsaacLab ClonePlan cloning one source row at a time: first /env0/Robot to every environment, then /env0/Object), pass env_ids so objects that share an environment share an environment id – with env_ids=None each call numbers its copies afresh, so /env1/Robot and /env1/Object cloned by different calls would land on different ids and never collide with each other:

env_ids = [0, 1]  # same ids in every call -> same logical environments
physx.clone("/env0/Robot",  ["/env1/Robot",  "/env2/Robot"],  transforms_r, env_ids)
physx.clone("/env0/Object", ["/env1/Object", "/env2/Object"], transforms_o, env_ids)
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”])

  • parent_transforms – Optional list of (px, py, pz, qx, qy, qz, qw) transforms giving the world pose of each copy’s parent. Position followed by quaternion rotation (imaginary-first, matching tensor API convention). Identity rotation = (0, 0, 0, 1). Must have the same length as target_paths. Each cloned body keeps its pose relative to the source’s parent, so a copy’s world pose is transform * inverse(source_parent) * source_body – for a source authored at the origin this places each body exactly at the transform. Pass None to co-locate every copy on the source.

  • env_ids – Optional logical environment id per target (list of int, same length as target_paths, each 0 <= id < 0x00FFFFFF – PhysX supports at most 1<<24 environments and the runtime id is env_ids[i] + 1). Stable across calls: the same id always maps to the same runtime environment, so clones from different calls that share an id collide with each other and stay isolated from every other environment (engages under GPU dynamics + GPU broadphase, like all env-id filtering). Pass None for automatic per-call numbering (each call’s copies get fresh ids past every previous call’s).

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 cloning fails, if no ovstage is attached, if target_paths contains duplicate or overlapping entries, or if clone() is called after the first step(), step_sync(), or step_n_sync(). The after-step rejection applies in CPU and GPU mode. GPU warmup is also rejected; hard CPU mode treats warmup_gpu() as a no-op.

Preconditions:
Side effects:
  • Creates live PhysX objects keyed by the target paths. No USD or runtime-stage prims are authored.

Ownership/Lifetime:
  • Clones remain valid until reset_stage().

Threading:
  • Do not call concurrently on the same instance without external sync.

Errors:
  • Raises ValueError for invalid inputs.

  • Raises RuntimeError on internal failure, including duplicate-target and after-step/after-warmup ordering violations.

create_contact_binding(
sensor_patterns: list[str],
filter_patterns: list[str] | None = None,
filters_per_sensor: int = 0,
max_contact_data_count: int = 0,
) ContactBinding#

Create a contact binding for reading aggregate and detailed contact tensors.

Returns DLPack-compatible tensors of net forces [S, 3] or force matrices [S, F, 3]. Detailed contact and friction data are exposed as flat [C, ...] buffers plus [S, F] count/start-index tensors via ContactBinding.read_contact_data() and ContactBinding.read_friction_data().

A sensor is a set of rigid body prims matched by a USD prim path pattern. A filter is a second set of bodies whose contacts with each sensor you want to measure. No extra USD schema is needed beyond the rigid bodies themselves.

The binding must be created before the first simulation step whose contacts you want to observe. Call read_net_forces() or read_force_matrix() after PhysxSDK.step(). Before the first step, both return all-zeros tensors.

Result tensor shapes after step:
  • net forces: [S, 3] where S = matched sensor count

  • force matrix: [S, F, 3] where F = matched filter count per sensor

  • detailed data: flat [C, 1] or [C, 3] buffers indexed by counts and start_indices with shape [S, F]

Use ContactBinding.sensor_paths and ContactBinding.filter_paths to map rows and columns back to resolved USD prim paths.

Example:

cb = sdk.create_contact_binding(
    sensor_patterns=["/World/robot_0/ee"],
    filter_patterns=["/World/obstacles/box"],
    filters_per_sensor=1,
    max_contact_data_count=256,
)
# After sdk.step():
forces = torch.zeros(cb.sensor_count, 3, device="cuda")
cb.read_net_forces(forces)
Parameters:
  • sensor_patterns – USD prim path patterns for sensor bodies.

  • filter_patterns – Flat list of USD prim path patterns for filters. Total length must equal len(sensor_patterns) * filters_per_sensor. Pass None with filters_per_sensor=0 to get contacts with all bodies.

  • filters_per_sensor – Number of filter patterns per sensor (same for all sensors).

  • max_contact_data_count – Max raw contact pairs to track in the native backend; also caps the detailed contact/friction flat-buffer reads. Detailed reads require this value and filters_per_sensor to be positive.

create_sdf_view(
pattern: str,
max_query_points: int,
) SdfView#

Create an SDF shape view for evaluating signed distance fields.

Requires a GPU instance; CPU SDF evaluation is not yet implemented.

Parameters:
  • pattern – USD glob pattern matching SDF collision shapes.

  • max_query_points – Number of query points per shape per call. Query tensors passed to SdfView.evaluate must have Q equal to this.

Returns:

SdfView with count == number of matched shapes.

Example:

sdf = physx.create_sdf_view("/World/Mesh*", max_query_points=64)
# Query/output tensors must be on the CUDA device (SDF eval is GPU-only).
pts = torch.zeros((sdf.count, 64, 3), dtype=torch.float32, device="cuda")
out = torch.zeros((sdf.count, 64, 4), dtype=torch.float32, device="cuda")
sdf.evaluate(pts, out)
sdf.destroy()
create_tensor_binding(
pattern: str = None,
prim_paths: list[str] = None,
tensor_type: int = TensorType.RIGID_BODY_POSE,
*,
raise_if_empty: bool = False,
) TensorBinding#

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 (TensorType.*).

  • raise_if_empty – If True, raise ValueError when the binding matches zero prims. The default keeps empty bindings valid; prefer it for optional or broad queries and check binding.count.

Returns:

TensorBinding object for reading/writing tensor data.

Raises:
  • ValueError – If neither pattern nor prim_paths is provided, both are, or raise_if_empty is true and no prims match.

  • RuntimeError – If binding creation fails.

Examples:

# Read all robot poses by pattern. Optional broad queries can be empty.
with sdk.create_tensor_binding(
    "/World/robot*", tensor_type=TensorType.RIGID_BODY_POSE
) as binding:
    if binding.count:
        poses = np.zeros(binding.shape, dtype=np.dtype(str(binding.dtype)))
        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=TensorType.ARTICULATION_DOF_POSITION_TARGET,
)
targets = np.zeros(binding.shape, dtype=np.dtype(str(binding.dtype)))
binding.write(targets)
binding.destroy()
Preconditions:
  • Exactly one of pattern or prim_paths must be provided.

  • A USD stage is loaded.

Side effects:
  • Allocates native binding resources.

Ownership/Lifetime:
  • Returned TensorBinding owns native resources until destroy().

  • Use binding.shape and binding.dtype (or binding.spec) to allocate compatible buffers; most tensor types are float32, but some types such as RIGID_BODY_DISABLE_SIMULATION are not.

  • The binding is tied to the current stage topology. Reuse it across steps, but do not keep it across reset_stage(), removing USD data that contains bound objects, or replacing/reparsing the stage so bound objects are destroyed and recreated. Destroy cached bindings before those lifecycle operations when practical; if a stale binding survives, only destroy it. Create replacements after the operation completes.

Diagnostics:
  • Pattern bindings can intentionally match zero prims, so expected TensorAPI no-match diagnostics are quieted on the simulation view used to create that binding.

  • Explicit prim_paths keep the default error-level no-match diagnostics for typo detection. To detect partial misses programmatically, compare the requested prim_paths with the resolved binding.prim_paths returned after creation.

Threading:
  • Do not create bindings concurrently with stage mutation.

Errors:
  • Raises ValueError for invalid arguments.

  • Raises RuntimeError on creation failure.

detach_ovstage() None#

Detach the currently-attached ovstage Stage.

Idempotent — calling on an unattached instance is a no-op success. Clears registered interests and output-buffer registrations, so a subsequent attach_ovstage() to a different Stage starts clean. After detach, stage-dependent calls such as update_from_ovstage() and step() fail until a Stage is attached again. Detach invalidates the stage’s tensor, contact, and SDF views. Do not read, write, or evaluate existing bindings or SDF views; destroy them and create replacements after calling attach_ovstage() and realizing a stage again.

Errors:
  • Raises RuntimeError on internal failures.

get_config_bool(key: int) bool#

Get a boolean config value.

Parameters:

key – Boolean config key (e.g., ovphysx.ConfigBool.DISABLE_CONTACT_PROCESSING).

Returns:

Current boolean value.

get_config_float(key: int) float#

Get a float config value.

Parameters:

key – Float config key.

Returns:

Current float value.

get_config_int32(key: int) int#

Get an int32 config value.

Parameters:

key – Int32 config key (e.g., ovphysx.ConfigInt32.NUM_THREADS).

Returns:

Current int32 value.

get_config_string(key: int) str | None#

Get a string config value.

Parameters:

key – String config key from ovphysx.ConfigString.

Returns:

Current string value, or None if not found.

get_contact_report(
include_friction_anchors: bool = False,
copy: bool = False,
) dict#

Get per-contact-point event data for the current simulation step.

Use this for custom contact sensors, collision debugging, or per-point force analysis. For aggregate force tensors (net forces or force matrices between sensor/filter body sets), use create_contact_binding() instead.

Warning

With the default copy=False, the returned headers, points, and anchors are zero-copy ctypes views into internal C buffers that are valid only until the next step() or step_sync() call. After the next step the buffers may be reallocated or reused; accessing the views is undefined behavior (silent data corruption or segfault). Python cannot detect this dangling state.

Pass copy=True to get Python-owned lists of dicts that are safe to retain across simulation steps. This is the recommended mode for RL training loops or any code that holds contact data beyond a single step.

Parameters:
  • include_friction_anchors – If True, also return friction anchor data (position and impulse at each friction anchor point).

  • copy – If True, return Python-owned list[dict] for each section (safe to hold across steps). If False (default), return zero-copy ctypes array views (faster but valid only until the next step()/step_sync()).

Returns a dict with:
  • headers: contact event headers describing each contact pair (actors, colliders, event type). When copy=False, a ctypes array of ContactEventHeader; when copy=True, a list[dict] with the same field names. Length is num_headers.

  • num_headers (int): Number of contact event headers.

  • points: per-contact-point data (position, normal, impulse, separation). When copy=False, a ctypes array of ContactPoint; when copy=True, a list[dict]. Length is num_points.

  • num_points (int): Number of contact point entries.

  • anchors (only if include_friction_anchors=True): friction anchor data. When copy=False, a ctypes array of FrictionAnchor; when copy=True, a list[dict]. Length is num_anchors.

  • num_anchors (int, only if include_friction_anchors=True): Number of friction anchors.

Example (safe across steps, copy=True):

report = physx.get_contact_report(copy=True)
physx.step_sync(dt)  # next step — report still valid
for h in report["headers"]:
    print(h["actor0"], h["numContactData"])
for p in report["points"]:
    print(p["position"], p["normal"], p["impulse"])

Example (zero-copy, copy=False):

report = physx.get_contact_report()
for i in range(report["num_headers"]):
    h = report["headers"][i]
    print(h.actor0, h.numContactData)
# Do NOT call step() before finishing access to report.

Prims must have PhysxContactReportAPI applied in the USD stage for contacts to be reported.

Raises:

RuntimeError – If the call fails.

get_object_type(prim_path: str) int#

Classify a USD prim by TensorAPI object type.

Unresolved paths return INVALID. Raises RuntimeError for invalid input (empty path, embedded NUL byte) or if no stage is attached.

Returns:

One of RIGID_BODY, ARTICULATION, ARTICULATION_LINK, ARTICULATION_ROOT_LINK, ARTICULATION_JOINT, or INVALID.

Return type:

ObjectType

property handle: int#

The raw ovphysx_handle_t for this instance (read-only).

Use this when passing the handle to C/C++ code that calls the ovphysx C API directly.

Raises:

RuntimeError – If the instance has been released.

overlap(
geometry_type: SceneQueryGeometryType,
mode: SceneQueryMode = SceneQueryMode.ALL,
**kwargs,
) list[dict]#

Test geometry overlap against objects in the scene.

For overlap queries, location fields (normal, position, distance, face_index, material) are zeroed – only object identity is populated.

Parameters:
  • geometry_typeSceneQueryGeometryType.

  • modeSceneQueryMode (ANY or ALL).

  • **kwargs – Geometry parameters (same as sweep()).

Returns:

List of hit dicts (same format as raycast()).

Raises:

ValueError – If mode is CLOSEST.

query_shared_dictionary(query: int) int#

Return the opaque pointer to the shared ovstage path dictionary backing a query.

This is NOT an ovphysx-private dictionary: it is the process-shared ovstage dictionary the attached Stage uses, the same one that interned the query’s tokens / prim lists, so a group’s attribute token / prim_list handle resolve through an ovstage.PathDictionary(stage) as well. Returns 0 if unavailable.

raycast(
origin: tuple | list,
direction: tuple | list,
distance: float,
mode: SceneQueryMode = SceneQueryMode.CLOSEST,
both_sides: bool = False,
) list[dict]#

Cast a ray and return hits.

Parameters:
  • origin – Ray origin [x, y, z].

  • direction – Normalized ray direction [x, y, z].

  • distance – Maximum ray length (>= 0).

  • modeSceneQueryMode (CLOSEST, ANY, or ALL).

  • both_sides – If True, test both sides of mesh triangles.

Returns:

List of hit dicts. Each dict contains collision, rigid_body, proto_index, normal, position, distance, face_index, material. For ANY mode, hit fields are zeroed.

read(
object_type: SimObjectType,
attribute_names: list[str],
scope: ObjectScope = ObjectScope.ALL,
) ReadResult#

Read physics output (ADR-0007) for one simulated type as column groups.

Mirrors the ovstage read idiom: open a query over object_type in scope, read the named attribute_names (e.g. ["position", "orientation"]), and return a context-managed ReadResult whose groups is one ReadGroup per typed column. The read is ovstage-native — attach an ovstage Stage first.

Use it as a context manager: the query + read session stay open for the with block so each group’s interned prim_list / attribute handles are valid — feed them straight into the ovstage write path (stage.query_from_path_list(group.prim_list)) for a no-repack write-back. Group tensors are NumPy copies, safe to keep past the block.

This is the physics → app direction. To avoid physics consuming its own output, write the data back into ovstage at ordinals that are never passed to update_from_ovstage(). See the ovstage Integration guide for the ordinal-coupling principle.

Parameters:
  • object_type – Simulated type to read (SimObjectType).

  • attribute_names – Semantic attribute names to read.

  • scopeALL or ACTIVE (active is single-frame).

Returns:

A ReadResult context manager. result.groups is empty if no objects matched.

Raises:

RuntimeError – on a native error (e.g. no ovstage attached).

read_tokens(
object_type: SimObjectType,
attribute_tokens: list[int],
scope: ObjectScope = ObjectScope.ALL,
) ReadResult#

Token form of read().

Identical to read() but the attributes are given as interned attribute tokens (e.g. those from fetch_query_result()) instead of strings, so a token can be fed straight back in with no token→string→name round-trip. Both forms build the same ovx_string_or_token_t array under the hood.

Parameters:
  • object_type – Simulated type to read (SimObjectType).

  • attribute_tokens – Interned attribute tokens to read.

  • scopeALL or ACTIVE (active is single-frame).

Returns:

A ReadResult context manager (see read()).

Raises:

RuntimeError – on a native error (e.g. no ovstage attached).

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:
  • All tensor bindings and contact bindings created by this instance are automatically released.

  • 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.

reset_stage() int#

Reset stage to empty (async).

Returns:

op_index (can be used with wait_op() for explicit synchronization)

Example

# Simple usage (stream-ordered) physx.reset_stage() physx.wait_all()

Preconditions:
  • Instance must be valid.

Side effects:
  • Clears the runtime stage.

  • Detaches any attached ovstage Stage (the C runtime calls detach_ovstage internally). Callers must re-attach with attach_ovstage() before any further update_from_ovstage().

Ownership/Lifetime:
  • All TensorBinding, ContactBinding, and SdfView objects for the previous stage become invalid. Destroy cached bindings and SDF views before reset when practical; if a stale handle survives, only destroy it. Create replacement bindings and SDF views after the reset completes.

Threading:
  • Do not call concurrently on the same instance without external sync.

Errors:
  • Raises RuntimeError on failure.

set_config(
entry: ovphysx._bindings.ovphysx_config_entry_t,
) None#

Set a typed global config entry at runtime (process-global).

Prefer the typed setters (set_config_bool(), set_config_int32(), set_config_float()) for a cleaner API.

Parameters:

entry – Typed config entry (ovphysx_config_entry_t).

set_config_bool(key: int, value: bool) None#

Set a boolean config value at runtime (process-global).

Parameters:
  • key – Boolean config key (e.g., ConfigBool.DISABLE_CONTACT_PROCESSING).

  • value – Boolean value.

set_config_float(key: int, value: float) None#

Set a float config value at runtime (process-global).

Parameters:
  • key – Float config key.

  • value – Float value.

set_config_int32(key: int, value: int) None#

Set an int32 config value at runtime (process-global).

Parameters:
  • key – Int32 config key (e.g., ConfigInt32.NUM_THREADS).

  • value – Int32 value.

static set_cpu_mode(cpu_only: bool) None#

Force process-wide CPU-only mode.

Call before the first PhysX instance is ever created to guarantee that CUDA is never touched. The call requires no active instances. Once set to True successfully, the mode cannot be reversed for this process.

When True: no CUDA driver is touched; all PhysX scenes use CPU dynamics regardless of their USD physxScene:enableGPUDynamics settings.

Raises:

RuntimeError – If any PhysX instances are currently active, or if attempting to set False after True has been applied (CPU-only mode is sticky as soon as enabling it succeeds).

step(dt: float) int#

Initiate physics step (async, returns op_index).

Simulation time is tracked internally; each step advances it by dt.

Parameters:

dt – Delta time for this step [s].

Returns:

op_index (can be used with wait_op() for explicit synchronization)

Examples

# Simple usage (stream-ordered) physx.step(0.016) binding.read(output) # Automatically waits for step

# Explicit wait (if accessing results outside stream) op = physx.step(0.016) 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.

step_n_sync(n: int, dt: float) None#

Run N steps in a single C call, saving (N-1) ctypes round-trips.

Equivalent to calling step_sync(dt) n times, but with only one Python-to-C transition. Simulation time is tracked internally and advanced by n * dt.

Parameters:
  • n – Number of steps to run (must be >= 1).

  • dt – Duration of each step [s].

Raises:

RuntimeError – If any step fails.

step_sync(dt: float) None#

Step simulation and wait for completion in a single call.

Faster than step() + wait_op() for performance-critical applications like RL training that always wait immediately. Simulation time is tracked internally and advanced by dt.

Parameters:

dt – Delta time [s] for this step.

Raises:

RuntimeError – If the step or wait fails.

sweep(
geometry_type: SceneQueryGeometryType,
direction: tuple | list,
distance: float,
mode: SceneQueryMode = SceneQueryMode.CLOSEST,
both_sides: bool = False,
**kwargs,
) list[dict]#

Sweep a geometry shape along a direction and return hits.

Parameters:
  • geometry_typeSceneQueryGeometryType.

  • direction – Normalized sweep direction [x, y, z].

  • distance – Maximum sweep distance (>= 0).

  • modeSceneQueryMode.

  • both_sides – If True, test both sides of mesh triangles.

  • **kwargs

    Geometry parameters:

    • SPHERE: radius, position

    • BOX: half_extent, position, rotation (xyzw quaternion)

    • SHAPE: prim_path (USD prim path string)

Returns:

List of hit dicts (same format as raycast()).

update_articulations_kinematic() None#

Update articulation link poses from current joint positions.

This performs a synchronous articulation forward-kinematics update without running a normal simulation step, collision detection, or contact generation. Call it after writing articulation DOF positions and before reading articulation link pose tensors when fresh link poses are needed in the same frame.

In GPU mode, the first kinematic update after loading USD may perform the same automatic DirectGPU warmup step used by tensor reads/writes.

Raises:

RuntimeError – If the update fails.

update_from_ovstage(from_ordinal: int, to_ordinal: int) None#

Apply committed ovstage edits over the closed range [from_ordinal, to_ordinal].

The application that writes to ovstage owns the ordinal range and calls this after sealing the writes. population.apply_usd_changes() waits for population work but does not seal its ordinal; complete stage.advance_write_floor(ordinal).wait() before this call. ovphysx forwards the range (as ovstage’s own ovstage_ordinal_range_t) to the runtime ovstage change feed and applies the resulting deltas to the simulation.

The initial read_ordinal was already parsed by attach_ovstage(). Normal incremental updates pass only later ordinals; including the initial ordinal replays the initial scene changes rather than only the new delta.

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:
  • Consumes each completed or failed operation reached before success or timeout.

Threading:
  • Serialize all calls on the same instance externally.

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 OP_INDEX_ALL for all ops

  • timeout_ns – Timeout in nanoseconds (None = infinite, 0 = poll)

Raises:
  • RuntimeError – If an operation failed or op_index is invalid or already consumed.

  • 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 each completed or failed operation reached up to op_index.

  • An operation still pending when the wait times out is not consumed.

  • An index completed by internal stream synchronization may be acknowledged once; that acknowledgement consumes it.

Ownership/Lifetime:
  • Wait-result storage is released internally.

  • Error strings are borrowed and remain valid until the next API call on the same thread.

Threading:
  • Serialize calls on one PhysX instance externally.

  • Do not wait on the same op_index from multiple threads.

Examples:

# Blocking wait (default)
physx.wait_op(op_index)

# Non-blocking poll
try:
    physx.wait_op(op_index, timeout_ns=0)
except TimeoutError:
    pass  # operation not yet complete
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,
dtype: DLDataType | None = None,
)#

Bases: object

Tensor 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.). The shape, ndim, and dtype metadata come from ovphysx_get_tensor_binding_spec(). Use them to allocate compatible buffers instead of assuming every tensor type is float32.

This is a synchronous API - operations complete before returning. Bindings are tied to the currently realized physics objects. Reuse them across simulation steps, but do not keep them across reset_stage(), removing USD data that contains bound objects, or replacing/reparsing the stage so bound objects are destroyed and recreated. Destroy cached bindings before those lifecycle operations when practical; if a stale binding survives, only destroy it. Create replacement bindings after the operation completes.

Usage patterns:

  • Context manager (auto-cleanup):

    with sdk.create_tensor_binding("/World/robot*", tensor_type=TensorType.RIGID_BODY_POSE) as binding:
        poses = np.zeros(binding.shape, dtype=np.dtype(str(binding.dtype)))
        binding.read(poses)
        poses[:, 2] += 0.1  # raise z position
        binding.write(poses)
    # Auto-destroyed here
    
  • Manual (explicit cleanup):

    binding = sdk.create_tensor_binding("/World/robot*", tensor_type=TensorType.RIGID_BODY_POSE)
    poses = np.zeros(binding.shape, dtype=np.dtype(str(binding.dtype)))
    binding.read(poses)
    binding.destroy()
    
property body_count: int#

Number of links.

property body_names: list[str]#

List of body/link names.

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 dof_count: int#

Number of degrees of freedom (DOFs). 0 if not an articulation binding.

property dof_names: list[str]#

List of DOF names (one per DOF).

property dtype: DLDataType#

Get the required DLPack dtype for tensors passed to this binding.

Most bindings use float32. Index bindings (deformable element indices) use int32; bool bindings (DISABLE_SIMULATION) use uint8. See dtype_name for a compact string form.

property dtype_name: str#

Get the required tensor dtype as a short string such as float32, int32, or uint8.

property fixed_tendon_count: int#

Number of fixed tendons per articulation (0 if none).

Use to decide whether to allocate buffers for fixed tendon property tensors (types 80-85) and to skip tendon code paths when T=0.

property handle: int#

Get the binding handle.

property is_fixed_base: bool#

Whether the articulation has a fixed base.

property joint_count: int#

Number of joints per articulation.

property joint_names: list[str]#

List of joint names.

property ndim: int#

Get the number of dimensions reported by ovphysx_get_tensor_binding_spec().

property prim_paths: list[str]#

Resolved USD prim paths in tensor row order.

Rigid-body bindings return one path per rigid-body tensor row. Articulation bindings return one root prim path per articulation row. For per-articulation link names, use body_names.

read(tensor) None#

Read simulation data into a user-provided tensor (synchronous).

The tensor must have matching shape and dtype (shape and dtype). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.

When called repeatedly with the same buffer object, an internal cache skips DLPack acquisition and attribute chain lookups, giving near-raw-C-call overhead. The numpy writeable guard is preserved on the fast path. Callers that want this fast path should reuse the same tensor object with unchanged backing storage across calls. Calling numpy.ndarray.resize() or torch.Tensor.resize_() between calls is safe (a staleness guard detects the pointer change and rebuilds the cache) but defeats the purpose of caching.

Parameters:

tensor – DLPack-compatible tensor with pre-allocated storage matching self.shape. Must use self.dtype. CPU/CUDA device mismatches are staged when CUDA is available; cross-GPU mismatches and CUDA tensors in process-wide CPU-only mode are rejected.

Preconditions:
  • This binding is not destroyed.

  • tensor has matching shape and dtype and uses a supported 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.

  • Do not mutate the tensor’s backing storage (resize(), set_(), etc.) between cached calls. For numpy and torch tensors, a staleness guard detects common mutations and falls back to the slow path; other types rely on the caller honouring this contract.

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 reported by ovphysx_get_tensor_binding_spec().

Returns:

Tensor dimensions for this binding. Scalar-property bindings use (N,). Flat state tensors use (N, C). Articulation and deformable mesh tensors use (N, L, C).

sleep(indices=None) None#

Force rigid bodies in this binding to sleep.

Mirrors PhysX SDK PxRigidDynamic::putToSleep. Symmetric counterpart to wake_up(). Bodies that have RIGID_BODY_DISABLE_SIMULATION set are silently skipped.

Only valid on a rigid-body binding. Articulation bindings raise.

Parameters:

indices – Optional int32 DLPack-compatible tensor of indices into this binding. If None, every body in the binding is put to sleep.

Errors:

RuntimeError if the binding is destroyed, is not a rigid-body binding, has been invalidated by a stage change, or the engine call fails.

property spatial_tendon_count: int#

Number of spatial tendons per articulation (0 if none).

Use to decide whether to allocate buffers for spatial tendon property tensors (types 90-93) and to skip tendon code paths when T=0.

property spec: TensorBindingSpec#

Get a Python-owned tensor spec snapshot for this binding.

property tensor_type: int#

Get the tensor type enum value.

wake_up(indices=None) None#

Wake rigid bodies in this binding.

Mirrors PhysX SDK PxRigidDynamic::wakeUp. Bodies that still have RIGID_BODY_DISABLE_SIMULATION set are silently skipped (the engine refuses to wake disabled actors).

Typical pair: clear the disable flag on an actor (re-add it to simulation in a sleep state) and then call this so the actor is active for the next step().

Only valid on a rigid-body binding. Articulation bindings raise.

Parameters:

indices – Optional int32 DLPack-compatible tensor of indices into this binding. If None, every body in the binding is woken.

Errors:

RuntimeError if the binding is destroyed, is not a rigid-body binding, has been invalidated by a stage change, or the engine wake call fails.

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 (shape and dtype). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.

When called repeatedly with the same buffer object and no indices/mask, an internal cache skips DLPack acquisition and attribute chain lookups, giving near-raw-C-call overhead. Callers that want this fast path should reuse the same tensor object with unchanged backing storage across calls; see read() for the full contract.

Parameters:
  • tensor – DLPack-compatible tensor with data to write, shape matching self.shape. Must use self.dtype. CPU/CUDA device mismatches are staged when CUDA is available; cross-GPU mismatches and CUDA tensors in process-wide CPU-only mode are rejected.

  • 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 and dtype and uses a supported device.

  • indices (if provided) is int32 and within bounds.

  • mask (if provided) is bool/uint8 with shape [N] on a supported 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.).

class ovphysx.api.ContactBinding(
sdk,
handle: int,
sensor_count: int,
filter_count: int,
max_contact_data_count: int,
)#

Bases: object

Contact tensor binding backed by IRigidContactView.

Do not instantiate directly. Use PhysxSDK.create_contact_binding() to obtain an instance. The sensor_paths and filter_paths properties expose the row/column metadata for the returned tensors.

destroy() None#

Release contact binding resources.

Safe to call multiple times. Captures strong references to the SDK and library before the C call to guard against GC ordering issues (Python may collect self._sdk before self if both go out of scope together).

property filter_count: int#

Number of filter bodies per sensor (0 when no filters specified).

property filter_paths: list[list[str]]#

Resolved filter USD prim paths in contact tensor column order.

The outer list is indexed by sensor row and the inner list by filter column. Each inner list is empty for unfiltered contact bindings (i.e. when filter_count == 0).

Returns:

Nested list of shape [sensor_count][filter_count].

Return type:

list[list[str]]

get_other_actor_paths_from_ids(ids_array) list[str]#

Resolve actor IDs from read_raw_contact_data() to USD prim paths.

ids_array is a 1D int64/uint64 array (numpy / warp / torch with DLPack support) holding actor IDs. IDs that cannot be resolved yield empty strings. Path strings are copied into Python – the caller can keep them across subsequent ovphysx calls.

Returns:

USD prim paths in the same order as the input IDs.

Return type:

list[str]

property max_contact_data_count: int#

Flat-buffer capacity for detailed contact and friction reads.

read_contact_data(
contact_forces,
positions,
normals,
separations,
counts,
start_indices,
) None#

Read detailed contact data into flat buffers.

Expected shapes are [C, 1] for contact_forces and separations, [C, 3] for positions and normals, and [sensor_count, filter_count] for counts and start_indices. C is max_contact_data_count; both C and filter_count must be positive. Count and start-index tensors may be int32 or uint32.

read_force_matrix(output) None#

Read contact force matrix into output. Expected shape: [sensor_count, filter_count, 3].

The dt for impulse-to-force conversion is taken automatically from the last PhysxSDK.step() call.

read_friction_data(
friction_forces,
friction_points,
counts,
start_indices,
) None#

Read detailed friction data into flat buffers.

Expected shapes are [C, 3] for friction_forces and friction_points, and [sensor_count, filter_count] for counts and start_indices. C is max_contact_data_count and must be positive; filter_count must also be positive. Count and start-index tensors may be int32 or uint32. Friction entries are per-anchor; sum each flat slice to build a pair-level [sensor_count, filter_count, 3] force tensor.

read_net_forces(output) None#

Read net contact forces into output. Expected shape: [sensor_count, 3].

The dt for impulse-to-force conversion is taken automatically from the last PhysxSDK.step() call.

read_raw_contact_data(
contact_forces,
positions,
normals,
separations,
counts,
start_indices,
other_actor_ids,
) None#

Read raw (unfiltered) contact data into flat buffers.

Filter-less variant of read_contact_data() — returns every contact involving each sensor regardless of which other actor it collided with, plus a per-contact other_actor_ids lookup for identifying the contacting body via get_other_actor_paths_from_ids().

Expected shapes are [C, 1] for contact_forces and separations, [C, 3] for positions and normals, [sensor_count] for counts and start_indices, and [C] for other_actor_ids. C is max_contact_data_count and must be positive; no filter dimension is required. Count and start-index tensors may be int32 or uint32; other_actor_ids must be int64 or uint64.

property sensor_count: int#

Number of sensor bodies matched.

property sensor_paths: list[str]#

Resolved sensor USD prim paths in contact tensor row order.

Returns:

One path per sensor row, in the same order as the contact data tensors.

Return type:

list[str]

Schema Path Registration#

ovphysx.register_schema_paths() None#

Register ovphysx’s namespaced USD schema/plugin paths before native bootstrap.

Call this before any USD stage open or schema-registry access when ovphysx shares a process with another USD-aware subsystem such as ovrtx. Standalone ovphysx applications do not need to call it because native startup registers the same ovphysx path automatically.

Always idempotent: re-reads the live env (Python and native views), merges, dedupes, and writes back only if the merged value differs. Safe to call repeatedly and after callers pop OV_PXR_PLUGINPATH_2511 from os.environ to force re-registration.

Raises:

RuntimeError – If no existing ovphysx plugins/usd directory can be found.

Logging#

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 (LogLevel.VERBOSE through LogLevel.NONE). Default: LogLevel.WARNING.

Raises:

ValueError – If level is out of range. No state change is applied.

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.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 False to suppress the built-in console output while keeping callbacks active. Call with True to re-enable it.

This is independent of callback registration and the global log level.

Parameters:

enableTrue to enable (default), False to 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.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.

Configuration#

Typed config for ovphysx.

Provides PhysXConfig, a dataclass whose fields map 1:1 to the C typed config enums in ovphysx_types.h. Only non-None fields are applied; the rest keep their Carbonite/PhysX defaults.

Usage:

from ovphysx import PhysX, PhysXConfig

physx = PhysX(config=PhysXConfig(
    disable_contact_processing=True,
    num_threads=4,
    carbonite_overrides={"/physics/updateToUsd": False},
))
class ovphysx.config.PhysXConfig(
disable_contact_processing: bool | None = None,
collision_cone_custom_geometry: bool | None = None,
collision_cylinder_custom_geometry: bool | None = None,
num_threads: int | None = None,
scene_multi_gpu_mode: int | None = None,
omnipvd_output_enabled: bool | None = None,
omnipvd_ovd_recording_directory: str | None = None,
cooked_collider_cache_dir: str | None = None,
carbonite_overrides: dict[str, bool | int | float | str] | None = None,
)#

Bases: object

Typed configuration for ovphysx.

All fields default to None (= use Carbonite/PhysX default). Only non-None fields are applied.

Example:

from ovphysx import PhysX, PhysXConfig

physx = PhysX(config=PhysXConfig(
    disable_contact_processing=True,
    num_threads=4,
    carbonite_overrides={"/physics/updateToUsd": False},
))
carbonite_overrides: dict[str, bool | int | float | str] | None = None#
collision_cone_custom_geometry: bool | None = None#
collision_cylinder_custom_geometry: bool | None = None#
cooked_collider_cache_dir: str | None = None#

Directory for the local cooked-collider (UJITSO) cache. Provide this to persist cooked colliders across runs and reuse them on the next launch; if left None, ovphysx does not choose a location and cooking runs without cross-run persistence.

disable_contact_processing: bool | None = None#
num_threads: int | None = None#
omnipvd_output_enabled: bool | None = None#

Must be set before instance creation

omnipvd_ovd_recording_directory: str | None = None#

Must be set before instance creation

scene_multi_gpu_mode: int | None = None#

0=disabled, 1=all GPUs, 2=skip first GPU

Types and Enums#

Pure-Python type definitions for ovphysx.

This module contains IntEnum definitions that mirror the C enums in ovphysx/include/ovphysx/ovphysx_types.h. It has zero native dependencies (no ctypes, no shared library loading, no USD) and is safe to import in any Python process regardless of USD version or native library state.

Keeping this module dependency-free is intentional: downstream consumers like IsaacLab can import TensorType without triggering ovphysx’s native bootstrap or USD version checks.

Naming convention: strip the OVPHYSX_TENSOR_ prefix and scalar dtype suffix (_F32 or _S32) from the C enum name. This keeps names unambiguous (ARTICULATION_ vs RIGID_BODY_) and makes the _bindings.py aliases mechanically verifiable.

class ovphysx.types.ApiStatus(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Return codes from the ovphysx C API. Mirrors ovphysx_api_status_t.

BUFFER_TOO_SMALL = 6#
DEVICE_MISMATCH = 7#
END_OF_ITERATION = 9#
ERROR = 1#
GPU_NOT_AVAILABLE = 8#
INVALID_ARGUMENT = 4#
NOT_FOUND = 5#
NOT_IMPLEMENTED = 3#
SUCCESS = 0#
TIMEOUT = 2#
class ovphysx.types.BindingPrimMode(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Prim selection mode for tensor bindings.

Unlike the other enums in this module, BindingPrimMode does not have a named typedef in ovphysx_types.h – the values come from the internal implementation. It is not covered by test_types_sync.py.

CREATE_NEW = 2#
EXISTING_ONLY = 0#
MUST_EXIST = 1#
class ovphysx.types.ConfigBool(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Boolean config keys. Mirrors ovphysx_config_bool_t.

COLLISION_CONE_CUSTOM_GEOMETRY = 1#
COLLISION_CYLINDER_CUSTOM_GEOMETRY = 2#
DISABLE_CONTACT_PROCESSING = 0#
OMNIPVD_OUTPUT_ENABLED = 3#
class ovphysx.types.ConfigFloat(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Float config keys (reserved). Mirrors ovphysx_config_float_t.

class ovphysx.types.ConfigInt32(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Int32 config keys. Mirrors ovphysx_config_int32_t.

NUM_THREADS = 0#
SCENE_MULTI_GPU_MODE = 1#
class ovphysx.types.ConfigString(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

String config keys. Mirrors ovphysx_config_string_t.

OMNIPVD_OVD_RECORDING_DIRECTORY = 0#
class ovphysx.types.LogLevel(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Log level for ovphysx output. Mirrors ovphysx_log_level_t.

ERROR = 3#
INFO = 1#
NONE = 4#
VERBOSE = 0#
WARNING = 2#
class ovphysx.types.ObjectScope(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Output query scope. Mirrors ovphysx_object_scope_t.

ACTIVE is single-frame (the active set is recomputed each step); ALL is stable until a structural change.

ACTIVE = 1#
ALL = 0#
class ovphysx.types.ObjectType(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

TensorAPI object classification. Mirrors ovphysx_object_type_t.

ARTICULATION = 2#
ARTICULATION_JOINT = 5#
INVALID = 0#
RIGID_BODY = 1#
class ovphysx.types.SceneQueryGeometryType(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Geometry type for sweep/overlap queries. Mirrors ovphysx_scene_query_geometry_type_t.

BOX = 1#
SHAPE = 2#
SPHERE = 0#
class ovphysx.types.SceneQueryMode(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Scene query hit mode. Mirrors ovphysx_scene_query_mode_t.

ALL = 2#
ANY = 1#
CLOSEST = 0#
class ovphysx.types.SimObjectType(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Simulated object type for the physics output read. Mirrors ovphysx_sim_object_type_t.

ARTICULATION_JOINT = 2#
DEFORMABLE_SURFACE = 5#
DEFORMABLE_VOLUME = 4#
PARTICLE_SET = 6#
RIGID_BODY = 0#
VEHICLE_WHEEL = 3#
class ovphysx.types.TensorType(
value,
names=<not given>,
*values,
module=None,
qualname=None,
type=None,
start=1,
boundary=None,
)#

Bases: IntEnum

Tensor type identifiers for TensorBindingsAPI.

Values match ovphysx_tensor_type_t in ovphysx_types.h. IntEnum members compare equal to plain ints, so they pass directly to the C API without conversion.

ARTICULATION_BODY_COM_POSE = 61#
ARTICULATION_BODY_INERTIA = 62#
ARTICULATION_BODY_INV_INERTIA = 64#
ARTICULATION_BODY_INV_MASS = 63#
ARTICULATION_BODY_MASS = 60#
ARTICULATION_CENTROIDAL_MOMENTUM = 14#
ARTICULATION_CONTACT_OFFSET = 111#
ARTICULATION_CORIOLIS_AND_CENTRIFUGAL_FORCE = 72#
ARTICULATION_DOF_ACTUATION_FORCE = 34#
ARTICULATION_DOF_ARMATURE = 40#
ARTICULATION_DOF_DAMPING = 36#
ARTICULATION_DOF_DRIVE_MODEL = 42#
ARTICULATION_DOF_FRICTION_PROPERTIES = 41#
ARTICULATION_DOF_LIMIT = 37#
ARTICULATION_DOF_MAX_FORCE = 39#
ARTICULATION_DOF_MAX_VELOCITY = 38#
ARTICULATION_DOF_POSITION = 30#
ARTICULATION_DOF_POSITION_TARGET = 32#
ARTICULATION_DOF_PROJECTED_JOINT_FORCE = 75#
ARTICULATION_DOF_STIFFNESS = 35#
ARTICULATION_DOF_VELOCITY = 31#
ARTICULATION_DOF_VELOCITY_TARGET = 33#
ARTICULATION_FIXED_TENDON_DAMPING = 81#
ARTICULATION_FIXED_TENDON_LIMIT = 83#
ARTICULATION_FIXED_TENDON_LIMIT_STIFFNESS = 82#
ARTICULATION_FIXED_TENDON_OFFSET = 85#
ARTICULATION_FIXED_TENDON_REST_LENGTH = 84#
ARTICULATION_FIXED_TENDON_STIFFNESS = 80#
ARTICULATION_GRAVITY_FORCE = 73#
ARTICULATION_JACOBIAN = 70#
ARTICULATION_MASS_CENTER_LOCAL = 13#
ARTICULATION_MASS_CENTER_WORLD = 12#
ARTICULATION_MASS_MATRIX = 71#
ARTICULATION_REST_OFFSET = 112#
ARTICULATION_ROOT_POSE = 10#
ARTICULATION_ROOT_VELOCITY = 11#
ARTICULATION_SHAPE_FRICTION_AND_RESTITUTION = 110#
ARTICULATION_SPATIAL_TENDON_DAMPING = 91#
ARTICULATION_SPATIAL_TENDON_LIMIT_STIFFNESS = 92#
ARTICULATION_SPATIAL_TENDON_OFFSET = 93#
ARTICULATION_SPATIAL_TENDON_STIFFNESS = 90#
DEFORMABLE_COLLISION_ELEMENT_INDICES = 125#
DEFORMABLE_MATERIAL_BENDING_DAMPING = 136#
DEFORMABLE_MATERIAL_BENDING_STIFFNESS = 134#
DEFORMABLE_MATERIAL_DYNAMIC_FRICTION = 130#
DEFORMABLE_MATERIAL_ELASTICITY_DAMPING = 133#
DEFORMABLE_MATERIAL_POISSONS_RATIO = 132#
DEFORMABLE_MATERIAL_THICKNESS = 135#
DEFORMABLE_MATERIAL_YOUNGS_MODULUS = 131#
DEFORMABLE_REST_NODAL_POSITION = 123#
DEFORMABLE_SIM_ELEMENT_INDICES = 124#
DEFORMABLE_SIM_KINEMATIC_TARGET = 122#
DEFORMABLE_SIM_NODAL_POSITION = 120#
DEFORMABLE_SIM_NODAL_VELOCITY = 121#
INVALID = 0#
RIGID_BODY_ACCELERATION = 6#
RIGID_BODY_COM_POSE = 5#
RIGID_BODY_CONTACT_OFFSET = 101#
RIGID_BODY_DISABLE_SIMULATION = 9#
RIGID_BODY_FORCE = 50#
RIGID_BODY_INERTIA = 4#
RIGID_BODY_INV_INERTIA = 8#
RIGID_BODY_INV_MASS = 7#
RIGID_BODY_MASS = 3#
RIGID_BODY_POSE = 1#
RIGID_BODY_REST_OFFSET = 102#
RIGID_BODY_SHAPE_FRICTION_AND_RESTITUTION = 100#
RIGID_BODY_VELOCITY = 2#
RIGID_BODY_WRENCH = 51#
SURFACE_DEFORMABLE_REST_POSITION = 143#
SURFACE_DEFORMABLE_SIM_ELEMENT_INDICES = 144#
SURFACE_DEFORMABLE_SIM_POSITION = 140#
SURFACE_DEFORMABLE_SIM_VELOCITY = 141#

DLPack Tensor Structures#

DLPack tensor structures for zero-copy data interchange.

This module provides ctypes wrappers for the vendored DLPack C header, enabling efficient data sharing between the C library and Python without copying.

NOTE: This file is NOT copied from another repo. It is a hand-written Python/ctypes mirror of the C structs defined in ovphysx/dlpack/dlpack.h (which itself is the upstream header from https://github.com/dmlc/dlpack). When the vendored C header is updated, this file must be updated to match.

class ovphysx.dlpack.DLDataType#

Bases: Structure

Descriptor of data type for elements of DLTensor.

TYPE_MAP = {'bfloat16': (4, 16, 1), 'float16': (2, 16, 1), 'float32': (2, 32, 1), 'float32x4': (2, 32, 4), 'float64': (2, 64, 1), 'int16': (0, 16, 1), 'int32': (0, 32, 1), 'int64': (0, 64, 1), 'int8': (0, 8, 1), 'uint16': (1, 16, 1), 'uint32': (1, 32, 1), 'uint64': (1, 64, 1), 'uint8': (1, 8, 1), 'uint8x4': (1, 8, 4)}#
bits#

Structure/Union member

code#

Structure/Union member

lanes#

Structure/Union member

class ovphysx.dlpack.DLDataTypeCode#

Bases: c_ubyte

An integer that encodes the category of DLTensor elements’ data type.

kDLBfloat = 4#
kDLBool = 6#
kDLComplex = 5#
kDLFloat = 2#
kDLFloat4_e2m1fn = 17#
kDLFloat6_e2m3fn = 15#
kDLFloat6_e3m2fn = 16#
kDLFloat8_e3m4 = 7#
kDLFloat8_e4m3 = 8#
kDLFloat8_e4m3b11fnuz = 9#
kDLFloat8_e4m3fn = 10#
kDLFloat8_e4m3fnuz = 11#
kDLFloat8_e5m2 = 12#
kDLFloat8_e5m2fnuz = 13#
kDLFloat8_e8m0fnu = 14#
kDLInt = 0#
kDLOpaqueHandle = 3#
kDLUInt = 1#
class ovphysx.dlpack.DLDevice#

Bases: Structure

Represents the device where DLTensor memory is allocated.

device_id#

Structure/Union member

device_type#

Structure/Union member

class ovphysx.dlpack.DLDeviceType#

Bases: c_long

The enum that encodes the type of the device where DLTensor memory is allocated.

kDLCPU = 1#
kDLCUDA = 2#
kDLCUDAHost = 3#
kDLCUDAManaged = 13#
kDLExtDev = 12#
kDLHexagon = 16#
kDLMAIA = 17#
kDLMetal = 8#
kDLOneAPI = 14#
kDLOpenCL = 4#
kDLROCM = 10#
kDLROCMHost = 11#
kDLTrn = 18#
kDLVPI = 9#
kDLVulkan = 7#
kDLWebGPU = 15#
class ovphysx.dlpack.DLManagedTensor#

Bases: Structure

C structure for managed DLPack tensor.

deleter#

Structure/Union member

dl_tensor#

Structure/Union member

manager_ctx#

Structure/Union member

class ovphysx.dlpack.DLTensor#

Bases: Structure

Plain C Tensor object, does not manage memory.

byte_offset#

Structure/Union member

data#

Structure/Union member

device#

Structure/Union member

dtype#

Structure/Union member

ndim#

Structure/Union member

shape#

Structure/Union member

strides#

Structure/Union member

class ovphysx.dlpack.ManagedDLTensor(
dl_tensor: DLTensor,
manager_ctx: Any,
deleter_callback: Callable | None = None,
)#

Bases: object

Managed DLPack tensor wrapper (CPU-only).

property data: int#

Data pointer address.

property device#

Device info.

property dtype#

Data type descriptor.

property ndim: int#

Number of dimensions.

property raw_dltensor: DLTensor#

Access underlying DLTensor (advanced use).

property shape: tuple[int, ...]#

Shape as Python tuple.

to_bytes() bytes#

Get pixel data as bytes (creates copy).

Contact Report Structures#

ctypes mirrors of the C ABI structs returned by ovphysx.api.PhysX.get_contact_report(); see the C API Reference for full field semantics.

Contact report ctypes structures.

These ctypes.Structure mirrors of the C ABI structs returned by ovphysx_get_contact_report() are used to access per-step contact data in Python without copying. Field layouts must stay in sync with the C definitions in ovphysx/include/ovphysx/ovphysx_types.h.

The module has no native-library dependencies and is safe to import in any Python process; the structures are populated by ctypes against pointers returned from the C API.

class ovphysx.contact_types.ContactEventHeader#

Bases: Structure

Contact event header. Mirrors ovphysx_contact_event_header_t.

actor0#

Structure/Union member

actor1#

Structure/Union member

collider0#

Structure/Union member

collider1#

Structure/Union member

contactDataOffset#

Structure/Union member

frictionAnchorsDataOffset#

Structure/Union member

numContactData#

Structure/Union member

numfrictionAnchorsData#

Structure/Union member

protoIndex0#

Structure/Union member

protoIndex1#

Structure/Union member

stageId#

Structure/Union member

type#

Structure/Union member

class ovphysx.contact_types.ContactPoint#

Bases: Structure

Per-contact-point data. Mirrors ovphysx_contact_point_t.

faceIndex0#

Structure/Union member

faceIndex1#

Structure/Union member

impulse#

Structure/Union member

material0#

Structure/Union member

material1#

Structure/Union member

normal#

Structure/Union member

position#

Structure/Union member

separation#

Structure/Union member

class ovphysx.contact_types.FrictionAnchor#

Bases: Structure

Friction anchor data. Mirrors ovphysx_friction_anchor_t.

impulse#

Structure/Union member

position#

Structure/Union member

Constants#

ovphysx.OP_INDEX_ALL#

Sentinel value (0xFFFFFFFFFFFFFFFF) passed to wait_op() to wait for all outstanding operations. Equivalent to OVPHYSX_OP_INDEX_ALL in the C API.