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):
from ovphysx.types import ObjectScope, SimObjectType
def step_and_read(physx, stage, initial_ordinal, from_ordinal, to_ordinal, dt):
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
with physx.read(
SimObjectType.RIGID_BODY, ["position"], scope=ObjectScope.ALL
) as result: # Reads current state
for group in result.groups:
... # use group.tensors (native CPU/CUDA columns)
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.
Only one instance may own a live ovstage attach in a process. A peer attach attempt raises
RuntimeErrorand leaves the owner’s stage and bindings unchanged. Detach the owner before attaching another instance.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()andPhysX.read()/PhysX.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:
objectHigh-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, callupdate_from_ovstage()with only those subsequent ordinals. Tensor bindings remain available as a perf escape hatch.- Parameters:
stage – An
ovstage.Stageor a rawovstage_instance_t*handle.read_ordinal – Caller-owned ovstage ordinal at which selected physics data is sealed. Must be non-zero. 0 is reserved as the runtime skip-cursor sentinel. The application owns ordinal advancement. Defaults to 1.
open_usd()/ population does not seal data, so calladvance_write_floor()first. Attachment fails if the initial articulation/joint schema scan cannot read that ordinal.
- Preconditions:
Instance must be valid.
Not already attached to a Stage.
No other instance owns the process-wide live ovstage attach.
Selected physics data must be sealed at
read_ordinal.read_ordinalmust be non-zero.The application registered ovphysx’s codeless PhysX schemas with ovstage before the first population in the process (
ovstage.population.register_usd_schemas([str(ovphysx.codeless_schema_root())])). Population drops every Physx* API it cannot resolve, so an unregistered stage carries none of the asset’s PhysX settings. This call verifies the registration and raisesRuntimeErrornaming the missing call when population ran without it (for the rest of the process; the Carbonite setting/ovphysx/schemas/requireRegistration = falsedowngrades this to a warning).Scenes that author Newton
newton:*attributes need the Newton USD schema (pip install newton-usd-schemas) registered in the same call (ovphysx.newton_schema_root()); population drops those attributes otherwise. Before the native attach this call checks, once per process, that the installed package was registered before the first population and emits aRuntimeWarningwhen it was not; a warning promoted to an error therefore leaves the instance detached. When the package is not installed it logs a warning on theovphysxlogger instead (nothing is wrong for scenes withoutnewton:*attributes, and suites that promote warnings to errors stay unaffected). The check probes only once USD has built its schema definitions (a procedurally authored stage attached before any USD population is left alone, so the check never registers a schema on the application’s behalf), and it recognizes the Newton schema family registered from any complete copy. The setting/ovphysx/schemas/warnMissingNewtonSchema = false(PhysXConfig(carbonite_overrides=...),"false"accepted) silences the check, for a registration ovstage cannot observe.
- Lifetime:
stagemust outlive the attachment because ovphysx captures and dereferences its native pointer until detach. This wrapper holds a reference tostagefor the duration of the attachment, so a Stage created inline (attach_ovstage(ovstage.Stage(...))) stays alive. The reference is dropped bydetach_ovstage()anddestroy().
- Errors:
Raises
ValueErrorifread_ordinalis 0.Raises
RuntimeErrorif already attached, another instance owns the live process-wide attach,stageis null, or the runtime attach fails. Instance remains unattached on failure.
- clone(
- source_path: str,
- target_paths: list[str],
- anchor_transforms: list[tuple[float, float, float, float, float, float, float]] | None = None,
- env_ids: list[int] | None = None,
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/useEnvIdssetting (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 (anchor_transforms=None) are collision-isolated from the source as well. Environment ids do not provide collision isolation in CPU mode. Give CPU clones spatially disjointanchor_transforms. Otherwise all copies share one collision space. The runtime logs a warning when env ids are requested but GPU dynamics or GPU broadphase is unavailable. Callovphysx.enable_python_logging()to receive it on theovphysxPython logger. Like all carbonite settings,useEnvIdsis 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/Robotto every environment, then/env0/Object), passenv_idsso objects that share an environment share an environment id. Withenv_ids=Noneeach call numbers its copies afresh, so/env1/Robotand/env1/Objectcloned 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"], env_ids=env_ids) physx.clone("/env0/Object", ["/env1/Object", "/env2/Object"], env_ids=env_ids)
- Parameters:
source_path – USD path of the source prim hierarchy to clone (e.g., “/World/env0”)
target_paths – Runtime physics-object paths for the cloned hierarchies (e.g., [“/World/env1”, “/World/env2”])
anchor_transforms – Optional list of (px, py, pz, qx, qy, qz, qw) transforms giving the absolute world pose of each target subtree root. Entry i anchors the exact subtree at target_paths[i]. Position is followed by quaternion rotation (imaginary-first, matching tensor API convention). Identity rotation = (0, 0, 0, 1). Must have the same length as target_paths. Descendants keep their poses relative to the source subtree root: target_object_world = anchor_transforms[i] * inverse(source_root_world) * source_object_world. Pass None to co-locate every copy on the source. Co-location is collision-isolated only under GPU dynamics + GPU broadphase. In CPU mode, provide spatially disjoint transforms to avoid cross-environment collisions.
env_ids – Optional logical environment id per target (list of int, same length as target_paths, each 0 <= id < 0x00FFFFFF, because 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 paths are invalid,
anchor_transformshas the wrong length or contains an invalid pose, orenv_idshas the wrong length or contains an invalid id.RuntimeError – If clone fails to queue, if no USD scene is loaded, or if clone() is called after
warmup()or the firststep()/step_sync(). Cloning after warmup corrupts simulation state on GPU and is rejected in all modes for API consistency. To recover, callreset_stage(), wait for it to complete, then reload the source scene or reattach its ovstage before cloning again.
- Preconditions:
A USD stage is loaded and source_path exists.
target_paths are unique and do not already exist.
warmup()has not been called and nostep()/step_sync()has run since the current stage was attached.
- 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,
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 viaContactBinding.read_contact_data()andContactBinding.read_friction_data().A sensor is a set of rigid bodies matched by a physics-object path pattern. A filter is a second set of bodies whose contacts with each sensor you want to measure. Patterns include authored USD objects and runtime-only clones.
Contact reporting is opt-in: every authored USD prim matched by
sensor_patternsmust havePhysxContactReportAPIapplied, on the prim named as the sensor itself (not a parent body or child collider). A matched prim without the schema is dropped from the binding, and if that leaves no sensors this call raisesRuntimeError. Filter prims need no extra schema, and runtime-only clones inherit contact reporting from the source actor.The binding must be created before the first simulation step whose contacts you want to observe. Call
ContactBinding.read_net_forces()orContactBinding.read_force_matrix()after a successfulPhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call. Before the first step, both return all-zeros tensors.- Result tensor shapes after step:
net forces:
[S, 3]where S = matched sensor countforce matrix:
[S, F, 3]where F = matched filter count per sensordetailed data: flat
[C, 1]or[C, 3]buffers indexed bycountsandstart_indiceswith shape[S, F]
Use
ContactBinding.sensor_pathsandContactBinding.filter_pathsto map rows and columns back to resolved physics-object paths.Example:
import torch def read_contact_forces(physx): with physx.create_contact_binding( sensor_patterns=["/World/robot_0/ee"], filter_patterns=["/World/obstacles/box"], filters_per_sensor=1, max_contact_data_count=256, ) as binding: # Call this after a successful simulation step. forces = torch.zeros( (binding.sensor_count, 3), device="cuda" ) binding.read_net_forces(forces) return forces
- Parameters:
sensor_patterns – Physics-object path patterns for sensor bodies. A single path component may be at most 4096 characters long; a longer one raises
RuntimeError(also forfilter_patterns).filter_patterns – Flat list of physics-object path patterns for filters. Total length must equal
len(sensor_patterns) * filters_per_sensor. PassNonewithfilters_per_sensor=0to 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_sensorto be positive.
- create_sdf_view(
- pattern: str,
- max_query_points: int,
Create an SDF shape view for evaluating signed distance fields.
Requires a GPU instance. CPU SDF evaluation is not implemented.
- Parameters:
pattern – USD-style object-path glob matching SDF collision shapes, including runtime-only clones. A single path component may be at most 4096 characters long; a longer one raises
RuntimeError.max_query_points – Number of query points per shape per call. Query tensors passed to
SdfView.evaluatemust 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,
Create tensor binding for bulk physics data access (synchronous).
Deprecated since version 0.6.0: The tensor-binding API is deprecated. Use
PhysX.read()for reads andPhysX.write()for writes.A tensor binding connects physics objects (by path pattern or explicit paths) to a tensor type, including authored USD objects and runtime-only clones.
- Parameters:
pattern – Physics-object path glob pattern (e.g., “/World/robot*”, “/World/env[N]/robot”). A single path component (the text between two slashes; a parenthesized group counts as one component even if it contains a slash) may be at most 4096 characters long; a longer component is rejected with
RuntimeError. Mutually exclusive withprim_paths.prim_paths – Explicit list of physics-object paths. Mutually exclusive with
pattern.tensor_type – Tensor type enum value (
TensorType.*).raise_if_empty – If
True, raiseValueErrorwhen the binding matches zero physics objects. The default keeps empty bindings valid. Prefer it for optional or broad queries and checkbinding.count.
- Returns:
TensorBinding object for reading/writing tensor data.
- Raises:
ValueError – If neither
patternnorprim_pathsis provided, both are, orraise_if_emptyis true and no physics objects match.RuntimeError – If binding creation fails.
Examples:
import numpy as np from ovphysx import TensorType def use_tensor_bindings(physx): # Optional broad queries can be empty. with physx.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) 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
patternorprim_pathsmust be provided.A USD stage is loaded.
- Side effects:
Allocates native binding resources.
- Ownership/Lifetime:
Returned TensorBinding owns native resources until
destroy().Use
binding.shapeandbinding.dtype(orbinding.spec) for layout andbinding.native_devicefor no-staging placement. Most tensor types are float32, but some types such asRIGID_BODY_DISABLE_SIMULATIONare 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 physics objects, so expected TensorAPI no-match diagnostics are quieted on the simulation view used to create that binding.
Explicit
prim_pathskeep the default error-level no-match diagnostics for typo detection. To detect partial misses programmatically, compare the requestedprim_pathswith the resolvedbinding.prim_pathsreturned after creation.
- Threading:
Do not create bindings concurrently with stage mutation.
- Errors:
Raises
ValueErrorfor invalid arguments.Raises
RuntimeErroron creation failure.
- destroy() None#
Destroy this PhysX instance.
- Preconditions:
No other thread is using this instance. Calling
destroy()again after terminal destruction is a valid no-op.
- Side effects:
Releases native resources and unregisters the instance.
- Ownership/Lifetime:
All tensor bindings and contact bindings created by this instance are automatically released.
Drop every output-read Warp array and downstream view before destruction. Destroying with live aliases warns and leaves their read-session resources allocated so their pointers do not dangle.
The instance becomes unusable after destruction.
- Threading:
Do not call concurrently with other operations on this instance.
- Errors:
Raises
RuntimeErrorwithout changing the instance if called from a native log callback. Retry after the callback returns.Raises
RuntimeErrorif native destruction reports a failure or process shutdown fails. The instance is already destroyed when either failure is reported, so a later call is an idempotent no-op. If both fail, the process-shutdown error is reported with the native status included.A Python or ctypes exception raised while invoking native destruction leaves ownership intact so the call can be retried.
Because this is a checked operation, a cleanup failure raised from a
finallyblock becomes the active exception. Python preserves any in-flight exception as chained context; applications that need different precedence must catch and log cleanup failures explicitly.
- 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 asupdate_from_ovstage()andstep()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 callingattach_ovstage()and realizing a stage again. If this instance owns an active OmniPVD recording, detach stops and finalizes it. On reattach, capability-only recording is dormant and can start immediately. Configured startup output instead starts a new startup session owned by the reattaching instance. Stop it before starting a late destination.- Errors:
Raises
RuntimeErroron internal failures.
- get_attach_handle() int#
Return the handle identifying this instance’s current attach.
An attach handle is an attach identity, not a USD stage id: it is nonzero for every live attach (including an ovstage attach whose source has no backing USD stage), and a fresh handle is minted per attach. A caller that stores it when it binds can tell “still the attach I bound to” apart from “detached” and from “a different attach that happens to reuse the same stage id”. See ADR-0016.
- Returns:
The current attach handle, or
0when nothing is attached.
- Errors:
Raises
RuntimeErrorif the instance is invalid.
- 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,
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 returnedheaders,points, andanchorsare zero-copy ctypes views into internal C buffers that are valid only until the nextstep()orstep_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=Trueto 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 nextstep()/step_sync()).
- Returns a dict with:
headers: contact event headers describing each contact pair (actors, colliders, event type). Whencopy=False, a ctypes array ofContactEventHeader; whencopy=True, alist[dict]with the same field names. Length isnum_headers.num_headers(int): Number of contact event headers.points: per-contact-point data (position, normal, impulse, separation). Whencopy=False, a ctypes array ofContactPoint; whencopy=True, alist[dict]. Length isnum_points.num_points(int): Number of contact point entries.anchors(only ifinclude_friction_anchors=True): friction anchor data. Whencopy=False, a ctypes array ofFrictionAnchor; whencopy=True, alist[dict]. Length isnum_anchors.num_anchors(int, only ifinclude_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
PhysxContactReportAPIapplied in the USD stage for contacts to be reported.- Raises:
RuntimeError – If the call fails.
- static get_cpu_mode() bool#
Return whether process-wide hard CPU-only mode is in effect.
True when
PhysX.set_cpu_mode(True)has succeeded, or whenOVPHYSX_DISABLE_GPUis active. The environment variable is read live beforeovphysx_initialize(and again after shutdown until the next initialize). Initialize latches it for that interval. This is not a query of per-scene USDphysxScene:enableGPUDynamics, a CUDA ordinal (active_cuda_gpus), or attach-time resolved dynamics.Callable at any time. No PhysX instance is required.
- get_object_type(prim_path: str) ObjectType#
Classify an authored USD prim by TensorAPI object type.
See
ObjectTypefor the taxonomy. Paths with no classified simulation object returnObjectType.INVALIDwith success – the call did not fail, the path just isn’t a known simulation object. Live standalone, custom, and articulation joints at their authored prim paths must not returnObjectType.INVALID.Raises
RuntimeErrorfor 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, JOINT, CUSTOM_JOINT, or INVALID.
- Return type:
- get_scene_query_paths_from_ids(ids: tuple | list) list[str]#
Resolve scene-query hit identity fields to physics-object paths.
idsholds opaque identity handles taken directly from thecollision,rigid_body, ormaterialentries of hit dicts returned byraycast(),sweep(), oroverlap(). IDs that cannot be resolved (a zero id, an id from an object removed since the query, or no active attach) yield empty strings.- Parameters:
ids – Sequence of
intidentity handles.- Returns:
Physics-object paths in the same order as
ids.- Return type:
list[str]
- property handle: int#
The raw
ovphysx_handle_tfor 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 destroyed.
- is_recording() bool#
Return
Trueonly while this instance owns active sampling.A peer reports
Falsewhile another instance owns a startup or late session.
- overlap(
- geometry_type: SceneQueryGeometryType,
- mode: SceneQueryMode = SceneQueryMode.ALL,
- **kwargs,
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.
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
attributetoken /prim_listhandle resolve through anovstage.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,
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).
mode –
SceneQueryMode(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,
Read physics output (ADR-0007) for one simulated type as column groups.
Mirrors the ovstage read idiom: open a query over
object_typeinscope, read the namedattribute_names(e.g.["position", "orientation"]), and return a context-managedReadResultwhosegroupsis oneReadGroupper 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
withblock so each group’s internedprim_list/attributehandles are valid. Feed them straight into the ovstage write path (stage.query_from_path_list(group.prim_list)) for a no-repack write-back. Grouptensorsarewarp.arraysnapshots on the native CPU or CUDA device. They keep their read-session storage alive until the array, its Warp views, and any downstream framework views are dropped, so they are 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.Step at least once before reading on DirectGPU. On a DirectGPU scene, simulated state columns for
RIGID_BODY,ARTICULATION_LINK,ARTICULATION, andARTICULATION_JOINTcome from PhysX’s direct-GPU API, which sizes its structures during the first simulation step and refuses reads until that step has run. Whole-articulation shape/material columns remain on the CPU, so one result can mix devices. Reading before the first step returns no groups for those types even though the objects exist and a query reports them. Step once, then read. CPU scenes can report authored initial state once buffered scene insertion is complete; a still-pending articulation root or joint partition is omitted normally rather than reported as an error.- Parameters:
object_type – Simulated type to read (
SimObjectType).attribute_names – Semantic attribute names to read.
scope –
ALLorACTIVE(active is single-frame).
- Returns:
A
ReadResultcontext manager.result.groupsis empty if no objects matched, and, on a DirectGPU scene before the first step, for the direct-GPU-sourced types described above. Readiness is evaluated per scene, so a multi-scene result can contain ready partitions while omitting an unready DirectGPU scene’s partition.- Raises:
RuntimeError – on a native error (e.g. no ovstage attached).
TypeError – if a returned column carries a device or DLPack dtype this Warp frontend does not support.
- read_tokens(
- object_type: SimObjectType,
- attribute_tokens: list[int],
- *,
- scope: ObjectScope = ObjectScope.ALL,
Token form of
read().Identical to
read()but the attributes are given as interned attribute tokens (e.g. an emittedReadGroup.attribute, or a token obtained through the C query API) instead of strings, so a token can be fed straight back in with no token-to-string-to-name round-trip. Both forms build the sameovx_string_or_token_tarray under the hood.- Parameters:
object_type – Simulated type to read (
SimObjectType).attribute_tokens – Interned attribute tokens to read.
scope –
ALLorACTIVE(active is single-frame).
- Returns:
A
ReadResultcontext manager (seeread()).- Raises:
RuntimeError – on a native error (e.g. no ovstage attached).
TypeError – if a returned column carries a device or DLPack dtype this Warp frontend does not support.
- 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,
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 keep ovphysx’s own code from touching CUDA. The call requires no active instances. Once set to True successfully, the mode cannot be reversed for this process.
When called before the first instance, True prevents CUDA driver use by ovphysx and makes all PhysX scenes use CPU dynamics regardless of their USD physxScene:enableGPUDynamics settings. Other libraries in the process may still open the driver. A call after an earlier instance was destroyed may succeed, but cannot provide ovphysx’s no-CUDA-touch guarantee or retarget an already-bootstrapped runtime. For CPU-only deployments, setting OVPHYSX_DISABLE_GPU before ovphysx initialization provides the equivalent process-wide policy.
- 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).
- start_recording(destination: OmniPvdDestination) None#
Start a late OmniPVD recording session.
The shared runtime must have recording capability selected before the first instance is created, either explicitly with
PhysXConfig(omnipvd_recording_capable=True)or implicitly withomnipvd_output_enabled=True. Once an inactive capable runtime is established, an unconfigured peer may start a late session. A runtime created without capability deliberately rejects late start withINVALID_STATEand an error namingomnipvd_recording_capable. Unsupported platforms retainNOT_IMPLEMENTED.A failed validation or destination-open attempt may be retried. A start while recording is active is invalid and does not replace its destination. After stop, another FILE or TCP session may be started.
- 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 byn * 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 bydt.- Parameters:
dt – Delta time [s] for this step.
- Raises:
RuntimeError – If the step or wait fails.
- stop_recording() None#
Stop and finalize the OmniPVD recording owned by this instance.
This also stops a startup session owned by the instance that created the shared runtime. Peer instances cannot stop that owner’s session.
- sweep(
- geometry_type: SceneQueryGeometryType,
- direction: tuple | list,
- distance: float,
- mode: SceneQueryMode = SceneQueryMode.CLOSEST,
- both_sides: bool = False,
- **kwargs,
Sweep a geometry shape along a direction and return hits.
- Parameters:
geometry_type –
SceneQueryGeometryType.direction – Normalized sweep direction [x, y, z].
distance – Maximum sweep distance (>= 0).
mode –
SceneQueryMode.both_sides – If True, test both sides of mesh triangles.
**kwargs –
Geometry parameters:
SPHERE:
radius,positionBOX:
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; completestage.advance_write_floor(ordinal).wait()before this call. ovphysx forwards the range (as ovstage’s ownovstage_ordinal_range_t) to the runtime ovstage change feed and applies the resulting deltas to the simulation.Ordinals at or below the latest successfully consumed ordinal are skipped. A fully consumed range succeeds as a no-op. An overlapping range applies only its unread suffix.
attach_ovstage()consumes its initialread_ordinal, so replaying it does not repeat initial population events. Later authored and sealed population changes are applied normally.
- wait_all(*, timeout_ns: int | None = None) None#
Wait for all pending operations (convenience wrapper for wait_op(ALL)).
- Parameters:
timeout_ns – Readiness timeout in nanoseconds, with the same semantics as
wait_op().
- 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 – Readiness timeout in nanoseconds. None waits indefinitely, and 0 performs one non-blocking readiness poll. A positive value bounds only the wait for readiness; once an operation is ready, synchronous result finalization may make the total call duration exceed this timeout.
- 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:
def wait_for_operation(physx, op_index): # Blocking wait (default) physx.wait_op(op_index) def poll_operation(physx, op_index): # Non-blocking poll try: physx.wait_op(op_index, timeout_ns=0) except TimeoutError: return False return True
- warmup() None#
Explicitly run the warmup step (synchronous).
On first call, runs a minimal simulation step (~1ns) to initialize PhysX structures. Works in both CPU and GPU mode (in GPU mode this also populates DirectGPU buffers).
Normally done automatically on the first tensor read, but calling it explicitly lets you control when the latency occurs.
This function is idempotent. Calling it multiple times has no effect after the first successful call. Warmup state resets after reset_stage() or attaching a new USD stage.
- Raises:
RuntimeError – If warmup fails.
- Side effects:
Advances simulation by a minimal timestep on first call.
- Threading:
Do not call concurrently with other operations on this instance.
- write(
- object_type: SimObjectType,
- attribute_name: str,
- *,
- scope: ObjectScope = ObjectScope.ALL,
Open an app -> physics write session for ONE attribute (ADR-0012).
The return direction of
read(), and its mirror: the groups cover the same prims in the same order. Each tensor exposes the native residency of the write path. This can differ from the corresponding read when a write uses host staging on a GPU scene. Inspecttensor.deviceinstead of inferring placement from the scene or read result.One attribute per session, unlike
read()’s list: the native group carries no attribute field, so a session that mixed attributes could not label its groups. Writing position and orientation is two sessions.Every group tensor is a
warp.arrayon its native CPU or CUDA device. Non-empty tensors are MUTABLE VIEWS onto runtime-owned storage. Empty tensors are Warp-owned empty arrays. Fill a non-empty tensor, thenWriteSession.commit()its group. Anything left uncommitted when the block exits is discarded rather than published.An attribute the type does not accept raises here rather than silently writing nothing.
Raises RuntimeError if no ovstage Stage is attached, or if the attribute is not writable for
object_type.
- class ovphysx.api.TensorBinding(
- sdk,
- handle: int,
- tensor_type: int,
- ndim: int,
- shape: tuple,
- dtype: DLDataType | None = None,
- *,
- _from_factory: bool = False,
Bases:
objectTensor binding for bulk physics data access via DLPack.
Deprecated since version 0.6.0: The tensor-binding API is deprecated. Use
PhysX.read()for reads andPhysX.write()for writes.A tensor binding connects a physics-object path pattern to a tensor type, enabling efficient bulk read/write for authored USD objects and runtime-only clones (poses, velocities, joint positions, etc.). The
shape,ndim, anddtypemetadata come fromovphysx_get_tensor_binding_spec(). Use them to allocate compatible buffers instead of assuming every tensor type isfloat32. Usenative_deviceto choose the no-staging CPU or CUDA device.CPU-only property bindings cover standalone rigid-body mass/inertia/COM values, articulation DOF/body properties, rigid-body/articulation shape properties, deformable-material properties, and disable-simulation/gravity flags. Fixed and spatial tendon property bindings are not CPU-only. CPU-only property bindings require host-resident tensor, index, and mask buffers, including when the simulation runs on GPU.
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):
import numpy as np from ovphysx import TensorType def raise_robot_poses(physx): with physx.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):
import numpy as np from ovphysx import TensorType def read_robot_poses(physx): binding = physx.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() return poses
- 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) useint32. The bool bindings (DISABLE_SIMULATION, DISABLE_GRAVITY) useuint8, as does ARTICULATION_DOF_DRIVE_TYPE, which is a per-DOF enum byte rather than a flag. Seedtype_namefor a compact string form.
- property dtype_name: str#
Get the required tensor dtype as a short string such as
float32,int32, oruint8.
- 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 native_device: DLDevice#
Get the binding’s native DLPack device.
Deprecated since version 0.6.0: The tensor-binding API is deprecated. Use
PhysX.read()for reads andPhysX.write()for writes.CPU-only property tensors report
DLDevice(kDLCPU, 0)even when the scene uses GPU dynamics. Other bindings follow their native TensorAPI view and reportDLDevice(kDLCUDA, ordinal)in DirectGPU mode orDLDevice(kDLCPU, 0)otherwise. This property identifies the no-staging device and does not change existing read/write behavior. A CUDAdevice_idis the process-visible runtime ordinal used by a framework device such ascuda:N, not a physical PCI bus index. Comparedevice_type.valuewith a constant such asDLDeviceType.kDLCUDA. This is a live query, not cached metadata: it may wait for pending operations and rejects an invalidated simulation view.
- property ndim: int#
Get the number of dimensions reported by
ovphysx_get_tensor_binding_spec().
- property prim_paths: list[str]#
Resolved physics-object paths in tensor row order.
Rigid-body bindings return one path per rigid-body tensor row. Articulation bindings return one root object 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 (
shapeanddtype). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.When called repeatedly with the same NumPy, PyTorch, Warp, or direct
DLTensorbuffer 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. Other DLPack providers are reacquired on every call. Callers that want the fast path should reuse the same tensor object with unchanged backing storage across calls. Do not resize or rebind storage between cached calls. The staleness guard rebuilds the cache when it detects a pointer change, but storage mutations that reuse the same pointer violate the cache contract. DirectDLTensorinputs retain their caller-owned descriptor.- Parameters:
tensor – DLPack-compatible tensor with pre-allocated storage matching self.shape. Must use
self.dtype. When CUDA is available, CPU/CUDA device mismatches are staged for binding types whose storage follows the simulation device. CPU-only property bindings require a host-resident tensor (kDLCPUorkDLCUDAHost), including on GPU simulations; CUDA and CUDA-managed tensors are rejected rather than staged. 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. A staleness guard detects pointer changes for NumPy, PyTorch, and Warp inputs and falls back to the slow path. DirectDLTensorinputs retain their caller-owned descriptor.
- 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 towake_up(). Bodies that haveRIGID_BODY_DISABLE_SIMULATIONset 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 haveRIGID_BODY_DISABLE_SIMULATIONset 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 (
shapeanddtype). Can be a NumPy array, PyTorch tensor, or any object with __dlpack__ protocol.When called repeatedly with the same supported 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 supported providers and full contract.- Parameters:
tensor – DLPack-compatible tensor with data to write, shape matching self.shape. Must use
self.dtype. When CUDA is available, CPU/CUDA device mismatches are staged for binding types whose storage follows the simulation device. For CPU-only property bindings, this tensor and optionalindicesormaskmust be host-resident (kDLCPUorkDLCUDAHost), including on GPU simulations; CUDA and CUDA-managed tensors are rejected rather than staged. 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:
objectContact tensor binding backed by IRigidContactView.
Do not instantiate directly. Use
PhysX.create_contact_binding()to obtain an instance. Thesensor_pathsandfilter_pathsproperties 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 physics-object 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 physics-object paths.ids_arrayis a 1D int64/uint64 array (numpy / warp / torch with DLPack support) holding actor IDs, from either column of theactor_idstensor. Both use the same namespace. A column is a strided view and this boundary requires C-contiguous input, so wrap a column slice innp.ascontiguousarray()before passing it. Path strings are copied into Python, so the caller can keep them across subsequent ovphysx calls.Every non-zero ID is checked against the attached stage first, so an ID whose actor has been removed yields an empty path rather than the path it used to name. Since the caller holds the IDs, that makes the failure explicit: a non-zero ID with an empty path is stale, while ID
0simply means no actor. The check is as precise as the backend’s notion of existence. On a USD stage a merely deactivated prim still resolves.- Returns:
Physics-object 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,
Read detailed contact data into flat buffers.
Expected shapes are
[C, 1]forcontact_forcesandseparations,[C, 3]forpositionsandnormals, and[sensor_count, filter_count]forcountsandstart_indices.Cismax_contact_data_count. BothCandfilter_countmust be positive. Count and start-index tensors may be int32 or uint32. Contact force magnitudes use the timestep from the last successfulPhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call.
- 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 successful
PhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call.
- read_friction_data(
- friction_forces,
- friction_points,
- counts,
- start_indices,
Read detailed friction data into flat buffers.
Expected shapes are
[C, 3]forfriction_forcesandfriction_points, and[sensor_count, filter_count]forcountsandstart_indices.Cismax_contact_data_countand must be positive, andfilter_countmust 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. Friction forces use the timestep from the last successfulPhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call.
- 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 successful
PhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call.
- read_raw_contact_data(
- contact_forces,
- positions,
- normals,
- separations,
- sensor_layout,
- actor_ids,
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 per-contact actor-identity tensors for identifying both the sensor and the contacting body viaget_other_actor_paths_from_ids().Expected shapes are
[C, 1]forcontact_forcesandseparations,[C, 3]forpositionsandnormals,[sensor_count, 2]forsensor_layout(column 0 count, column 1 start index), and[C, 2]foractor_ids(column 0 the reporting sensor’s actor, column 1 the actor it contacted).Cismax_contact_data_countand must be positive. No filter dimension is required.sensor_layoutmay be int32 or uint32.actor_idsmust be int64 or uint64. Slicing the columns out as views costs no copy. Contact force magnitudes use the timestep from the last successfulPhysX.step(),PhysX.step_sync(), orPhysX.step_n_sync()call.Truncation: when the total contact count for a step exceeds
max_contact_data_count, the runtime fills the buffers with as many contacts as fit and emits a logged warning. A sensor’s count reports only the contacts actually written, and its start index is clamped tomax_contact_data_count, so[start, start + count)is always an in-range (possibly empty) slice. Increasemax_contact_data_countat binding creation if truncation occurs.Token lifetime: tokens in
actor_idsare opaque actor handles, not encoded paths, and are stable while the corresponding actor is alive on the attached stage. After an actor is removed, its token is stale andget_other_actor_paths_from_ids()reports it as an empty path rather than as the path it used to name.
- property sensor_count: int#
Number of sensor bodies matched.
- property sensor_paths: list[str]#
Resolved sensor physics-object 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]
Codeless Schema Discovery#
ovphysx ships its PhysX USD schemas as codeless resources and never registers them itself; these helpers tell the application where they are so it can register them with the USD runtime it owns (see Physics Schemas).
- ovphysx.codeless_schema_root() Path#
Return the directory holding ovphysx’s codeless PhysX USD schema packages.
The returned directory follows the convention
schemas/physx/<module>/resources/and contains one subdirectory per PhysX schema module ovphysx ships (e.g.PhysxSchemaandOmniUsdPhysicsDeformableSchema).- Raises:
FileNotFoundError – If no staged codeless schema tree can be found. Install the ovphysx wheel (
pip install ovphysx) or runcmake -P scripts/install.cmakefrom a source checkout to stage the schemas.
- ovphysx.codeless_schema_paths() list[Path]#
Return the per-module codeless schema resource directories.
Each returned path is a
resourcesdirectory containing a USDplugInfo.json(Type: resource) andgeneratedSchema.usda, ready to hand topxr.Plug.Registry().RegisterPlugins()for use with a stockusd-coreruntime.- Raises:
FileNotFoundError – If the staged schema tree is missing or contains no registrable schema packages. See
codeless_schema_root().
The Newton USD schema (pip install newton-usd-schemas) is a separate package
whose newton:* attributes ovphysx reads as fallbacks for the PhysX spellings;
this helper locates the installed package so it can be registered in the same call.
- ovphysx.newton_schema_root() Path#
Return the directory of the installed Newton USD schema (
newton-usd-schemas).Register it with ovstage alongside
codeless_schema_root(), before the first population call in the process; the parser reads the schema’snewton:*attributes as fallbacks for the PhysX spellings, and population drops them unless the schema is registered.- Raises:
FileNotFoundError – If the
newton-usd-schemaspackage is not installed in this Python environment. The message carries the install hint.
Logging#
- ovphysx.api.set_log_level(level: int) None#
Set the process-scoped libovphysx source log level threshold.
Messages emitted under the named Carbonite sources
omni_physx_sdk,omni.physx, andovphysx_internalbelow this level are suppressed for console and callback delivery. Every other process source and channel, including any unnamed source, remains unchanged and is subject only to the callback’s severity and channel filter. Callable at any time, including before instance creation.LogLevel.NONEmutes only the three named sources. It is not a whole-runtime or process mute.- Parameters:
level – Log level threshold (LogLevel.DEFAULT through LogLevel.NONE). LogLevel.DEFAULT restores LogLevel.WARNING.
- Raises:
ValueError – If level is out of range. No state change is applied.
RuntimeError – If the native API rejects the call for another reason, including callback-time reconfiguration.
- ovphysx.api.get_log_level() int#
Get the current process-scoped libovphysx source 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 a custom callback is set (or
enable_python_logging()is active), both the built-in console output and the callback receive messages, which may cause duplicate output.Call with
Falseto suppress the built-in console output while keeping the callback active. Call withTrueto re-enable it.This is independent of callback registration and the libovphysx source log level. It controls Carbonite’s process-global built-in console logger and therefore affects every Carbonite tenant in the process. Multi-tenant hosts should normally own this policy and leave the logger enabled.
- Parameters:
enable –
Trueto enable (default),Falseto disable.- Raises:
RuntimeError – If the native API rejects the call, including when it is made from the active native log callback.
- ovphysx.api.flush_log(timeout_ns: int = 1 << 64 - 1) None#
Wait for callback delivery already accepted before this call.
The barrier covers records already handed to ovphysx by Carbonite. If the host enabled Carbonite asynchronous logging, records still buffered upstream are outside this barrier. Successful native shutdown flushes the upstream buffer before disabling and draining the callback.
- Parameters:
timeout_ns – Maximum wait in nanoseconds. Zero polls;
2**64 - 1waits indefinitely.- Raises:
ValueError – If
timeout_nsis outside the unsigned 64-bit range.TimeoutError – If the timeout expires.
RuntimeError – If native log delivery cannot be flushed.
- ovphysx.api.enable_python_logging(
- logger_name: str = 'ovphysx',
- *,
- min_severity: int = LogLevel.VERBOSE,
- channel_filter: str | None = None,
Route native log messages to Python’s logging module.
Sets the sole C-level callback slot and forwards matching native messages to
logging.getLogger(logger_name). Calling this function again replaces any existing native callback, including one installed outside Python. Successful shutdown of the Python process-lifecycle scope, normally when the finalPhysXinstance is destroyed, also disables this bridge. Enable it again after creating an instance in a new lifecycle scope. Each forwardedLogRecordincludesovphysx_channelandovphysx_timestampattributes for the native source and Unix-epoch timestamp seconds.Call
disable_python_logging()to stop forwarding.- Parameters:
logger_name – Name of the Python logger to route to (default: “ovphysx”).
min_severity – Minimum severity for records observed from the process log stream (default: LogLevel.VERBOSE). Records from libovphysx’s
omni_physx_sdk,omni.physx, andovphysx_internalsources are also subject toset_log_level().channel_filter – Optional comma-separated
channel=levelrules. The native API copies this string, compares levels case-insensitively, and uses raw channel-prefix matching. The longest matching prefix wins. A later rule wins ties of equal length.
- Raises:
RuntimeError – If called from a native log callback, another Python logging transition is in progress, or the native API rejects the severity, filter, or callback configuration.
- 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.- Raises:
RuntimeError – If called from a native log callback or while another Python logging transition is in progress.
Configuration#
Typed config for ovphysx.
@implements REQ-CAPI-NVTX-001 @covers AC-6
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.OmniPvdDestination(
- transport: str,
- file_path: str = '',
- tcp_address: str = '',
- tcp_port: int = 0,
- tcp_timeout_ms: int = 0,
Bases:
objectExact destination for a late OmniPVD recording session.
- classmethod file(
- path: str,
Record to the exact file path
path.
- file_path: str = ''#
- classmethod tcp(
- address: str,
- port: int,
- *,
- timeout_ms: int = 0,
Connect to a ready TCP listener.
- tcp_address: str = ''#
- tcp_port: int = 0#
- tcp_timeout_ms: int = 0#
- transport: str#
- 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_recording_capable: bool | None = None,
- omnipvd_ovd_recording_directory: str | None = None,
- omnipvd_transport: str | None = None,
- omnipvd_tcp_address: str | None = None,
- omnipvd_tcp_port: int | None = None,
- omnipvd_tcp_timeout_ms: int | None = None,
- nvtx_enabled: bool | None = None,
- cooked_collider_cache_dir: str | None = None,
- ovstage_read_pool_max_mb: int | None = None,
- carbonite_overrides: dict[str, bool | int | float | str] | None = None,
Bases:
objectTyped 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 cooks to a process-private temp directory that is discarded at shutdown, so nothing persists. Applied when the runtime first starts in a process. Later changes have no effect.
- disable_contact_processing: bool | None = None#
- num_threads: int | None = None#
- nvtx_enabled: bool | None = None#
Emit NVTX ranges for the ovphysx API calls and the PhysX SDK profile zones, for capture with Nsight Systems. Off by default. Must be set before instance creation. Setting OVPHYSX_NVTX=1 in the environment has the same effect.
- 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
- omnipvd_recording_capable: bool | None = None#
Enables late
PhysX.start_recording(). Set before the first instance is created. Process-wide and unset/false by default.omnipvd_output_enabled=Truealso enables this capability. Otherwise default creation installs no OmniPVD provider.
- omnipvd_tcp_address: str | None = None#
- omnipvd_tcp_port: int | None = None#
- omnipvd_tcp_timeout_ms: int | None = None#
0 uses the OS send timeout and a 3000 ms connect window
- omnipvd_transport: str | None = None#
Exact lowercase “file” or “tcp”
- ovstage_read_pool_max_mb: int | None = None#
Retention budget in MiB for the per-context device read-buffer pool that backs the ovstage output read (/physics/ovstageReadPoolMaxMB). Bounds the device and pinned-host memory the pool keeps between reads for reuse.
0or any negative value DISABLES the pool (nothing is retained and every read allocates and frees as if the pool were absent). Default 256 when left None. Does not cap the memory a single read allocates, only what is retained.
- scene_multi_gpu_mode: int | None = None#
0=disabled, 1=all GPUs, 2=skip first GPU. Used only when active_cuda_gpus is empty
Types and Enums#
Pure-Python type definitions for ovphysx.
@implements REQ-CAPI-NVTX-001 @covers AC-2
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:
IntEnumReturn 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#
- INVALID_STATE = 10#
- 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:
IntEnumPrim selection mode for tensor bindings.
Deprecated since version 0.6.0: The tensor-binding API is deprecated. Use
PhysX.read()for reads andPhysX.write()for writes.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:
IntEnumBoolean config keys. Mirrors ovphysx_config_bool_t.
- COLLISION_CONE_CUSTOM_GEOMETRY = 1#
- COLLISION_CYLINDER_CUSTOM_GEOMETRY = 2#
- DISABLE_CONTACT_PROCESSING = 0#
- NVTX_ENABLED = 4#
- OMNIPVD_OUTPUT_ENABLED = 3#
- OMNIPVD_RECORDING_CAPABLE = 5#
- class ovphysx.types.ConfigFloat(
- value,
- names=_not_given,
- *values,
- module=None,
- qualname=None,
- type=None,
- start=1,
- boundary=None,
Bases:
IntEnumFloat 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:
IntEnumInt32 config keys. Mirrors ovphysx_config_int32_t.
- NUM_THREADS = 0#
- OMNIPVD_TCP_PORT = 2#
- OMNIPVD_TCP_TIMEOUT_MS = 3#
- OVSTAGE_READ_POOL_MAX_MB = 4#
- 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:
IntEnumString config keys. Mirrors ovphysx_config_string_t.
- COOKED_COLLIDER_CACHE_DIRECTORY = 1#
- OMNIPVD_OVD_RECORDING_DIRECTORY = 0#
- OMNIPVD_TCP_ADDRESS = 3#
- OMNIPVD_TRANSPORT = 2#
- class ovphysx.types.LogLevel(
- value,
- names=_not_given,
- *values,
- module=None,
- qualname=None,
- type=None,
- start=1,
- boundary=None,
Bases:
IntEnumLog level for ovphysx output. Mirrors ovphysx_log_level_t.
DEFAULTrestores the effectiveWARNINGthreshold.DEFAULTandNONEconfigure logging but are never delivered as callback severities.- DEFAULT = 0#
- ERROR = 4#
- INFO = 2#
- NONE = 5#
- VERBOSE = 1#
- WARNING = 3#
- class ovphysx.types.ObjectScope(
- value,
- names=_not_given,
- *values,
- module=None,
- qualname=None,
- type=None,
- start=1,
- boundary=None,
Bases:
IntEnumOutput 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:
IntEnumTensorAPI object classification. Mirrors
ovphysx_object_type_t.Returned by
PhysX.get_object_type(). Standalone UsdPhysics joints areJOINT; plugin-registered custom joints areCUSTOM_JOINT(pair withOVPHYSX_PHYSX_TYPE_CUSTOM_JOINT/get_physx_ptr); articulation joints areARTICULATION_JOINT.- ARTICULATION = 2#
- ARTICULATION_JOINT = 5#
- ARTICULATION_LINK = 3#
- ARTICULATION_ROOT_LINK = 4#
- CUSTOM_JOINT = 7#
- INVALID = 0#
- JOINT = 6#
- RIGID_BODY = 1#
- class ovphysx.types.SceneQueryGeometryType(
- value,
- names=_not_given,
- *values,
- module=None,
- qualname=None,
- type=None,
- start=1,
- boundary=None,
Bases:
IntEnumGeometry 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:
IntEnumScene 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:
IntEnumSimulated object type for the physics output read.
Mirrors
ovphysx_sim_object_type_t. This is a separate enum domain from the TensorBindingsObjectType. In particular,SimObjectType.ARTICULATIONis 9 whileObjectType.ARTICULATIONis 2.- ARTICULATION = 9#
- ARTICULATION_JOINT = 2#
- ARTICULATION_LINK = 1#
- DEFORMABLE_MATERIAL = 10#
- DEFORMABLE_SURFACE = 5#
- DEFORMABLE_VOLUME = 4#
- FIXED_TENDON = 7#
- PARTICLE_SET = 6#
- RIGID_BODY = 0#
- SPATIAL_TENDON = 8#
- VEHICLE_WHEEL = 3#
- class ovphysx.types.TensorType(
- value,
- names=_not_given,
- *values,
- module=None,
- qualname=None,
- type=None,
- start=1,
- boundary=None,
Bases:
IntEnumTensor type identifiers for TensorBindingsAPI.
Deprecated since version 0.6.0: The tensor-binding API is deprecated. Use
PhysX.read()for reads andPhysX.write()for writes.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_DISABLE_GRAVITY = 65#
- 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_DRIVE_TYPE = 43#
- 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_LINK_ACCELERATION = 22#
- ARTICULATION_LINK_INCOMING_JOINT_FORCE = 74#
- ARTICULATION_LINK_POSE = 20#
- ARTICULATION_LINK_VELOCITY = 21#
- ARTICULATION_LINK_WRENCH = 52#
- 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_GRAVITY = 103#
- 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:
StructureDescriptor 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_ubyteAn 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:
StructureRepresents the device where DLTensor memory is allocated.
- device_id#
Structure/Union member
- device_type#
Structure/Union member
- class ovphysx.dlpack.DLDeviceType#
Bases:
c_longThe 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:
StructureC structure for managed DLPack tensor.
- deleter#
Structure/Union member
- dl_tensor#
Structure/Union member
- manager_ctx#
Structure/Union member
- class ovphysx.dlpack.DLTensor#
Bases:
StructurePlain 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
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:
StructureContact event header. Mirrors
ovphysx_contact_event_header_t.- actor0#
Structure/Union member
- actor1#
Structure/Union member
- attachHandle#
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
- type#
Structure/Union member
- class ovphysx.contact_types.ContactPoint#
Bases:
StructurePer-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
Physics Utilities#
USD physics authoring utilities.
ovphysx.api.PhysX simulates a stage; this subpackage mostly builds one. Its
bulk is a pure-Python layer over pxr that authors the geometry, xform ops
and physics API schemas a scene needs, so a caller does not have to spell out a
rigid body’s collider, mass and transform by hand for every prim. The one
exception is simulation, described at the end.
The helpers come from omni.physx.scripts, whose names mixed camelCase
and snake_case. Every name here is snake_case, so setCollider is
set_collider() and
createAPISchemaPropertyCache is
create_api_schema_property_cache(). Aliasing the
subpackage on import keeps a ported snippet close to its original shape:
from ovphysx import utils as physicsUtils
physicsUtils.add_rigid_box(stage, "/World/box", position=Gf.Vec3f(0, 0, 5))
Eight camelCase spellings survive as deprecated aliases: setCollider,
setRigidBody, removeCollider, removePhysics, removeRigidBodySubtree,
hasSchema, createJoint and extractTriangleSurfaceFromTetra. Each
forwards to the new spelling and raises a DeprecationWarning naming both, and
each is reachable as ovphysx.utils.<name> and by explicit import. None is in
__all__, so from ovphysx.utils import * and the rendered documentation
show the new spellings only. No other camelCase name is kept.
Keyword parameters are snake_case on the same terms, so
setCollider(prim, approximationShape=...) becomes
set_collider(prim, approximation_shape=...). Three old spellings stay
accepted, being the ones on the helpers above: approximationShape on
set_collider() and
set_rigid_body(), and schemaName on
has_schema(). Each raises a DeprecationWarning
naming both spellings; passing both in one call raises TypeError.
Importing this subpackage does not load the ovphysx native library, contact a
USD resolver or start a simulation, so it is usable in a process that only
authors USD. Diagnostics go through the standard logging module under the
ovphysx.utils logger hierarchy.
The authoring helpers need pxr. An authoring process supplies its own stock
usd-core, and this subpackage is reached with an explicit
import ovphysx.utils so that import ovphysx keeps working for
simulation-only users who have no pxr.
pxr is required only once an authoring name is actually touched, not to
import this subpackage. Submodules load on first attribute access, so
from ovphysx.utils import step_and_write_to_ovstage resolves in a process
that has ovstage but no USD at all – which is what the output_read
sample does.
ovphysx ships the PhysX schemas codeless, so PhysX API schemas are applied by
identifier and their properties authored by name; core UsdPhysics schemas
still use their typed bindings.
Register the schemas before opening any stage:
from ovphysx.utils import codeless
codeless.register_schemas()
Refer to codeless for the registration rules, which are
strict about ordering and fail silently when ignored.
The submodules group the surface by theme, and every name is also re-exported
here, so both ovphysx.utils.shapes.add_rigid_box and
ovphysx.utils.add_rigid_box resolve:
codeless- registration and access for the codeless PhysX schemasschema- schema registry introspection, API schema property snapshot and restoretransform- xform op stacks, basis vectors, joint-relative transformspaths- collision-free stage paths for a prim about to be definedshapes- cube, sphere, capsule, cylinder, cone and xform constructors, plain, collider and rigid-body flavoredplanes- ground planes and sized quad planesjoints- joints between two prims or between a prim and the worldmaterials- physics materials and their binding to primsfiltering- collision groups and filtered pairsauthoring- mass, force, physics scenes and the collider and rigid-body API sets on prims that already existmesh- procedural meshes, triangle and tetrahedron mesh mathparticles- particle systems, particle sets, PBD materialsdeformable- volume and surface deformable bodies and their materialssimulation- stepping a running simulation and writing its output back to an attached ovstage Stageconstants- shared tokens and limits
ovphysx.utils is the home for any supported ovphysx helper that does not
belong in the top-level API, a wider remit than USD authoring alone:
simulation is the one such submodule today.
A submodule of that kind - one that drives a simulation rather than authoring a
stage - must import runtime dependencies such as ovstage, warp and
numpy inside its functions rather than
at module scope, and reach ovphysx.api either the same way or under
if TYPE_CHECKING:, so that import ovphysx.utils keeps needing nothing
beyond pxr and the standard library and still loads no native library. Such
a helper may need ovstage and a live PhysX instance when called; only
the import-time guarantee is subpackage-wide.
Utilities are grouped by submodule. Except for the codeless schema helpers,
public names are also available directly from ovphysx.utils.
Codeless schema access#
Not flat re-exported. Import it as from ovphysx.utils import codeless.
Access to ovphysx’s codeless PhysX USD schemas.
ovphysx ships the PhysX and Omni deformable schemas as codeless artifacts: a
plugInfo.json and generatedSchema.usda per module. API schemas are
applied by their schema identifier and their properties are reached by name:
from ovphysx.utils import codeless
codeless.apply_api(prim, "PhysxRigidBodyAPI")
codeless.set_attr(prim, "physxRigidBody:disableGravity", True)
Multiple-apply schemas take an instance name, which becomes the middle component of the property path:
codeless.apply_api(prim, "PhysxCookedDataAPI", "convexHull")
codeless.set_attr(prim, codeless.instanced_name("physxCookedData", "convexHull", "buffer"), buf)
Registration comes first#
The schemas must be registered with the USD runtime before anything in the
process opens a stage or queries the schema registry. USD builds that registry
once, on first access, and never rebuilds it, so a late registration is
silently ineffective and the process it happened in cannot be repaired: there
is no reload, no reset, and a second register_schemas() call reports
success while changing nothing. Getting the order wrong costs a restart.
Under ovphysx’s own bundled runtime, import ovphysx handles this by
appending to OV_PXR_PLUGINPATH_2511. Under a stock usd-core – which is
what pxr resolves to in an authoring process – call register_schemas()
as the first thing in the program, or preset PXR_PLUGINPATH_NAME before the
process starts. Presetting the environment variable is the only route that also
works inside a host that has already initialized USD, because USD reads it
while constructing the registry rather than afterwards. Refer to
docs/physics_schemas.md.
The helpers here turn USD’s “invalid schema” error into one that names the likely cause.
- exception ovphysx.utils.codeless.CodelessSchemaError#
Bases:
RuntimeErrorA codeless PhysX schema could not be applied, removed or authored.
- ovphysx.utils.codeless.apply_api(
- prim: pxr.Usd.Prim,
- identifier: str,
- instance_name: str | None = None,
Apply a codeless API schema to a prim by schema identifier.
- Parameters:
prim – The prim to apply the API to.
identifier – The schema identifier, e.g.
"PhysxRigidBodyAPI".instance_name – The instance name for a multiple-apply schema, e.g.
"convexHull"forPhysxCookedDataAPI. Omit for single-apply schemas.
- Raises:
CodelessSchemaError – If the API could not be applied. The message distinguishes the two usual causes – the schemas not being registered, or the identifier not naming a known API schema – from USD refusing to author a schema it knows.
- ovphysx.utils.codeless.get_attr(prim: pxr.Usd.Prim, name: str) pxr.Usd.Attribute#
Return a prim attribute by name, with a readable error when it is missing.
- Parameters:
prim – The prim to read from.
name – The full property name, e.g.
"physxRigidBody:disableGravity".
- Raises:
CodelessSchemaError – If the prim is invalid or has no such attribute. Usually the owning API was not applied first, or the schemas are unregistered.
- ovphysx.utils.codeless.instanced_name(
- prefix: str,
- instance_name: str,
- property_name: str,
Build the property name of a multiple-apply schema instance.
For example
instanced_name("physxCookedData", "convexHull", "buffer")gives"physxCookedData:convexHull:buffer".
- ovphysx.utils.codeless.register_schemas(verify: bool = False)#
Register ovphysx’s codeless PhysX schemas with the active USD runtime.
Intended for authoring processes running on a stock
usd-core. Call it before opening any stage or querying the schema registry; USD builds that registry once and a later call cannot repair it, in this process or by any other means short of a restart.A late call gives no sign of it on its own.
RegisterPluginsstill reports the plugin roots as registered andTf.Type.FindByNamestill resolves the schema types; only applying an API fails, arbitrarily far away. Passverifyto convert that into an immediate error.Idempotent: USD ignores a plugin root it has already seen.
- Parameters:
verify – Confirm the schemas reached the schema registry and raise if they did not. Off by default because the check is not free: the only way to ask is to query the schema registry, which builds it, so a verified call has to be the last plugin registration in the process. Leave it off where another USD component registers plugins after ovphysx.
- Returns:
The list of registered
Plug.Pluginobjects, which is empty when the schemas were already registered.- Raises:
FileNotFoundError – If the staged codeless schema tree cannot be found. See
ovphysx.codeless_schema_paths().CodelessSchemaError – If
verifyis set and any of the schema roots did not reach the schema registry, because something built it first or because that root is not staged.
- ovphysx.utils.codeless.remove_api(
- prim: pxr.Usd.Prim,
- identifier: str,
- instance_name: str | None = None,
Remove a codeless API schema from a prim by schema identifier.
With the schemas registered, removing an API that was never applied is not an error; USD reports it as a no-op and this returns its result unchanged, so a whole family of mutually exclusive APIs can be stripped without asking which one is there.
The returned bool is USD’s answer to whether it authored the removal on the current edit target, not a promise that the API is gone: an opinion on a stronger layer survives a successful removal on a weaker one. A removal USD refuses on a schema it knows – on a layer that is not editable, for instance – is
Falsetoo, on the same terms astry_apply_api().- Parameters:
prim – The prim to strip.
identifier – The schema identifier.
instance_name – The instance name for a multiple-apply schema.
- Returns:
Whether USD reports the removal as successful.
- Raises:
CodelessSchemaError – If the prim is invalid or USD cannot resolve the call at all, on the same terms as
try_apply_api().
- ovphysx.utils.codeless.schema_is_registered() bool#
Whether the codeless PhysX schemas are visible to the schema registry.
Every schema root ovphysx ships has to be there: a partial registration – the PhysX schemas without the Omni deformable ones, say – answers False.
Note that calling this builds the schema registry if it does not exist yet, which locks out every later schema plugin registration in the process, ovphysx’s and any other library’s alike. Register first, then query.
- ovphysx.utils.codeless.set_attr(prim: pxr.Usd.Prim, name: str, value) pxr.Usd.Attribute#
Author a prim attribute by name.
The attribute must already be declared, which for a codeless schema means its API was applied first. This is the codeless replacement for the typed
api.CreateFooAttr(value)calls.- Parameters:
prim – The prim to author on.
name – The full property name.
value – The value to set.
- Returns:
The authored attribute.
- Raises:
CodelessSchemaError – If the attribute does not exist or cannot be set.
- ovphysx.utils.codeless.set_attrs(prim: pxr.Usd.Prim, values: dict) None#
Author several attributes, skipping the ones whose value is
None.The authoring helpers expose every schema attribute as an optional keyword defaulting to
None, so that an unsupplied attribute keeps its schema fallback instead of being pinned to a value chosen by the helper. This applies that convention in one call.- Parameters:
prim – The prim to author on.
values – A mapping of full property name to value.
Nonevalues are skipped.
- Raises:
CodelessSchemaError – If the prim is invalid or an attribute cannot be set.
- ovphysx.utils.codeless.set_rel(
- prim: pxr.Usd.Prim,
- name: str,
- targets,
Set a relationship’s targets by name.
- Parameters:
prim – The prim to author on.
name – The full relationship name, e.g.
"physxParticle:particleSystem".targets – A single target path or a list of them.
- Raises:
CodelessSchemaError – If the prim has no such relationship, or the targets could not be set.
- ovphysx.utils.codeless.try_apply_api(
- prim: pxr.Usd.Prim,
- identifier: str,
- instance_name: str | None = None,
Apply a codeless API schema, returning whether USD accepted it.
The bool-returning half of
apply_api(), for a caller that already reports a refused application its own way – the deformable helpers warn and return False rather than raising.A refusal is USD declining to author a schema it knows, as for a prim on a layer that is not editable. USD reports it either by answering
Falseor by raising, and both come back asFalsehere. The two causes below are not refusals: USD cannot resolve the identifier at all, so it has nothing to answer about.- Parameters:
prim – The prim to apply the API to.
identifier – The schema identifier, e.g.
"PhysxRigidBodyAPI".instance_name – The instance name for a multiple-apply schema.
- Raises:
CodelessSchemaError – If the prim is invalid or USD cannot resolve the call at all – the schemas not being registered, the identifier not naming a known API schema, or the instance name contradicting the one it does name.
Shape constructors#
Shape constructors: geometry, colliders and rigid bodies in one call.
Every shape comes in three flavors. The plain add_* helper defines the
UsdGeom prim with a display color and a translate-orient-scale xform op
stack; add_collider_* additionally applies UsdPhysics.CollisionAPI; and
add_rigid_* applies UsdPhysics.RigidBodyAPI and UsdPhysics.MassAPI
with a density and initial velocities on top of that. Each is a one-line way to
put a falling box or a static ramp on a stage.
The physics APIs are applied here directly rather than through
set_collider(), so a shape carries a bare
collision API and no mesh approximation: these are all analytic UsdGeom
shapes, for which an approximation has nothing to describe. Reach for
set_collider instead when the prim is a mesh or already exists.
- ovphysx.utils.shapes.add_box(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cube to the stage.
- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_capsule(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Capsule to the stage.
The extent authored here is the one UsdGeom.Capsule’s own schema computation produces, so it follows
axisand reachesheight / 2 + radiusalong it – the cylindrical section plus a hemispherical cap at each end – andradiusacross it.- Parameters:
stage – The Usd.Stage to add capsule.
path – The desired capsule path.
radius – The radius of the capsule.
height – The height of the capsule.
axis – The axis of the capsule.
position – The position where the capsule should be placed in stage.
orientation – The capsule orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_box(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cube to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_capsule(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Capsule to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add capsule.
path – The desired capsule path.
radius – The radius of the capsule.
height – The height of the capsule.
axis – The axis of the capsule.
position – The position where the capsule should be placed in stage.
orientation – The capsule orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_cone(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cone to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add cone.
path – The desired cone path.
radius – The radius of the cone.
height – The height of the cone.
axis – The axis of the cone.
position – The position where the cone should be placed in stage.
orientation – The cone orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_cube(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cube to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_cylinder(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cylinder to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add cylinder.
path – The desired cylinder path.
radius – The radius of the cylinder.
height – The height of the cylinder.
axis – The axis of the cylinder.
position – The position where the cylinder should be placed in stage.
orientation – The cylinder orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_collider_sphere(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Sphere to the stage and add physics collider API to it.
- Parameters:
stage – The Usd.Stage to add sphere.
path – The desired sphere path.
radius – The radius of the sphere.
position – The position where the sphere should be placed in stage.
orientation – The sphere orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_cone(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cone to the stage.
The extent authored here is the one UsdGeom.Cone’s own schema computation produces, so it follows
axisand reachesheight / 2along it andradiusacross it.- Parameters:
stage – The Usd.Stage to add cone.
path – The desired cone path.
radius – The radius of the cone.
height – The height of the cone.
axis – The axis of the cone.
position – The position where the cone should be placed in stage.
orientation – The cone orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_cube(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cube to the stage.
- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_cylinder(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Cylinder to the stage.
The extent authored here is the one UsdGeom.Cylinder’s own schema computation produces, so it follows
axisand reachesheight / 2along it andradiusacross it.- Parameters:
stage – The Usd.Stage to add cylinder.
path – The desired cylinder path.
radius – The radius of the cylinder.
height – The height of the cylinder.
axis – The axis of the cylinder.
position – The position where the cylinder should be placed in stage.
orientation – The cylinder orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_rigid_box(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Cube to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_box for that.- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_capsule(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Capsule to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_capsule for that.- Parameters:
stage – The Usd.Stage to add capsule.
path – The desired capsule path.
radius – The radius of the capsule.
height – The height of the capsule.
axis – The axis of the capsule.
position – The position where the capsule should be placed in stage.
orientation – The capsule orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_cone(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Cone to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_cone for that.- Parameters:
stage – The Usd.Stage to add cone.
path – The desired cone path.
radius – The radius of the cone.
height – The height of the cone.
axis – The axis of the cone.
position – The position where the cone should be placed in stage.
orientation – The cone orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_cube(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- size: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Cube to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_cube for that.- Parameters:
stage – The Usd.Stage to add cube.
path – The desired cube path.
size – The size of the cube.
position – The position where the cube should be placed in stage.
orientation – The cube orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_cylinder(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- height: float = 1.0,
- axis: str = 'Y',
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Cylinder to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_cylinder for that.- Parameters:
stage – The Usd.Stage to add cylinder.
path – The desired cylinder path.
radius – The radius of the cylinder.
height – The height of the cylinder.
axis – The axis of the cylinder.
position – The position where the cylinder should be placed in stage.
orientation – The cylinder orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_sphere(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
- density: float = 1.0,
- lin_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- ang_velocity: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
Add UsdGeom.Sphere to the stage and add physics rigid body and collider API to it.
A
densityof 0.0 still appliesUsdPhysics.RigidBodyAPIandUsdPhysics.MassAPI; it is not a request for a static collider. Use add_collider_sphere for that.- Parameters:
stage – The Usd.Stage to add sphere.
path – The desired sphere path.
radius – The radius of the sphere.
position – The position where the sphere should be placed in stage.
orientation – The sphere orientation.
color – The color of the mesh.
density – The density of the rigid body.
lin_velocity – The initial linear velocity of the rigid body.
ang_velocity – The initial angular velocity of the rigid body.
- ovphysx.utils.shapes.add_rigid_xform(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- scale: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add xform to the stage with given transformation and add rigid body API to it.
- Parameters:
stage – The Usd.Stage to add the xform.
path – The desired xform path.
position – The position where the xform should be placed in stage.
orientation – The xform orientation.
scale – The xform scale.
- ovphysx.utils.shapes.add_sphere(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- radius: float = 1.0,
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- color: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add UsdGeom.Sphere to the stage.
- Parameters:
stage – The Usd.Stage to add sphere.
path – The desired sphere path.
radius – The radius of the sphere.
position – The position where the sphere should be placed in stage.
orientation – The sphere orientation.
color – The color of the mesh.
- ovphysx.utils.shapes.add_xform(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- position: pxr.Gf.Vec3f = Gf.Vec3f(0.0),
- orientation: pxr.Gf.Quatf = Gf.Quatf(1.0),
- scale: pxr.Gf.Vec3f = Gf.Vec3f(1.0),
Add xform to the stage with given transformation.
- Parameters:
stage – The Usd.Stage to add the xform.
path – The desired xform path.
position – The position where the xform should be placed in stage.
orientation – The xform orientation.
scale – The xform scale.
Ground and quad planes#
Ground planes and sized quad planes.
A UsdPhysics.Plane is infinite and renders as nothing, so a usable ground
plane is two prims: a mesh for the viewport and a collision prim beside it.
add_ground_plane() authors that pair under one Xform;
add_quad_plane() and add_cube_ground_plane() instead give the
collider the finite extent of the geometry itself, which is what a scene needs
when a body must be able to fall off the edge.
- ovphysx.utils.planes.add_cube_ground_plane(
- stage: pxr.Usd.Stage,
- cube_path: str | pxr.Sdf.Path,
- axis: str,
- size: float,
- position: pxr.Gf.Vec3f | pxr.Gf.Vec3d,
- color: pxr.Gf.Vec3f,
Add UsdGeom.Cube to the stage to act as a sized plane with thickness. The cube is scaled by a vector Gf.Vec3f(0.01, 1.0, 1.0) depending on the up Axis
sizeis the cube’s full edge length, which is whatUsdGeom.Cube’s ownsizeattribute means, sosize=2reaches[-1, 1]across the two lateral axes. Onadd_ground_plane()andadd_quad_plane()sizeis a half size instead.- Parameters:
stage – The Usd.Stage to add path.
cube_path – The desired ground plane path.
axis – The up axis - “Y”, “Z”
size – The edge length of the cube, before the flattening scale.
position – The position where the mesh should be placed in stage.
color – The color of the mesh.
- ovphysx.utils.planes.add_ground_plane(
- stage: pxr.Usd.Stage,
- plane_path: str | pxr.Sdf.Path,
- axis: str,
- size: float,
- position: pxr.Gf.Vec3f | pxr.Gf.Vec3d,
- color: pxr.Gf.Vec3f,
Add ground plane to the stage. Note that it will add a mesh for rendering purpose and UsdPhysics.Plane for collision purpose.
- Parameters:
stage – The Usd.Stage to add path.
plane_path – The desired ground plane path.
axis – The up axis - “Y”, “Z”
size – The half size of the mesh.
position – The position where the mesh should be placed in stage.
color – The color of the mesh.
- ovphysx.utils.planes.add_plane_collider(
- stage: pxr.Usd.Stage,
- prim_path: str | pxr.Sdf.Path,
- up_axis: str,
Define a guide-purpose UsdGeom.Plane and make it a collider.
An occupied path raises
ValueErrorand is not modified.- Parameters:
stage – The Usd.Stage to add the plane.
prim_path – The desired plane path.
up_axis – The plane’s up axis.
- ovphysx.utils.planes.add_quad_plane(
- stage: pxr.Usd.Stage,
- quad_path: str | pxr.Sdf.Path,
- axis: str,
- size: float,
- position: pxr.Gf.Vec3f | pxr.Gf.Vec3d,
- color: pxr.Gf.Vec3f,
Add quad mesh to the stage to act as a sized plane.
- Parameters:
stage – The Usd.Stage to add path.
quad_path – The desired ground plane path.
axis – The up axis - “Y”, “Z”
size – The half size of the mesh.
position – The position where the mesh should be placed in stage.
color – The color of the mesh.
Joints#
Joint creation between two prims, or between a prim and the world.
create_joint() computes the two local frames from the bodies’ current world
poses, so the joint holds them where they already are; add_joint_fixed()
takes those frames from the caller instead. Passing one body anchors the joint
to the world.
The PhysX joint types are codeless, so they are defined by type name. They
derive from UsdPhysicsJoint, which stock usd-core does bind, so they are
then reached through that typed base. Refer to ovphysx.utils.codeless.
- ovphysx.utils.joints.add_joint_fixed(
- stage: pxr.Usd.Stage,
- joint_path: str | pxr.Sdf.Path,
- actor0: str | pxr.Sdf.Path,
- actor1: str | pxr.Sdf.Path,
- local_pos0: pxr.Gf.Vec3f,
- local_rot0: pxr.Gf.Quatf,
- local_pos1: pxr.Gf.Vec3f,
- local_rot1: pxr.Gf.Quatf,
- break_force: float,
- break_torque: float,
Add fixed joint to the stage.
- Parameters:
stage – The Usd.Stage to add the joint.
joint_path – The desired joint path.
actor0 – The actor0 for the joint.
actor1 – The actor1 for the joint.
local_pos0 – The joint local position offset from the actor0
local_rot0 – The joint local rotation offset from the actor0
local_pos1 – The joint local position offset from the actor1
local_rot1 – The joint local rotation offset from the actor1
break_force – The joint break force.
break_torque – The joint break torque.
- ovphysx.utils.joints.create_joint(
- stage: pxr.Usd.Stage,
- joint_type: str,
- from_prim: pxr.Usd.Prim,
- to_prim: pxr.Usd.Prim,
Create a joint between two prims, with local frames computed from their world poses.
The joint prim is placed under the first writable ancestor of to_prim, so that instanced and prototype prims do not break authoring. Passing only one prim anchors the joint to the world.
- Parameters:
stage – The Usd.Stage to add the joint.
joint_type – One of “Fixed”, “Revolute”, “Prismatic”, “Spherical”, “Distance”, “Gear”, “RackAndPinion”; anything else creates a D6 joint with all axes locked.
from_prim – The body0 prim, or None.
to_prim – The body1 prim.
- ovphysx.utils.joints.create_joints(
- stage: pxr.Usd.Stage,
- joint_type: str,
- paths: List[str | pxr.Sdf.Path],
- join_to_parent: bool = False,
Create one joint per path, optionally anchoring each to its parent prim.
- Parameters:
stage – The Usd.Stage to add the joints.
joint_type – The joint type, see create_joint.
paths – The body1 prim paths.
join_to_parent – Whether to use each prim’s parent as body0.
Physics materials#
Physics materials and their binding to prims.
A physics material is a UsdShade.Material carrying
UsdPhysics.MaterialAPI, bound to a collider through the physics purpose
of UsdShade.MaterialBindingAPI so that it composes independently of any
render material on the same prim. Only the friction, restitution and density
values the caller supplies are authored; the rest keep their schema fallback.
- ovphysx.utils.materials.add_physics_material_to_prim(
- stage: pxr.Usd.Stage,
- prim: pxr.Usd.Prim,
- material_path: str | pxr.Sdf.Path,
Bind physics material to a given prim.
- Parameters:
stage – The Usd.Stage to add path.
prim – The Usd.Prim where material should have the binding to.
material_path – The path of the material.
- ovphysx.utils.materials.add_rigid_body_material(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- density=None,
- static_friction=None,
- dynamic_friction=None,
- restitution=None,
Define a physics material, authoring only the attributes that were supplied.
- Parameters:
stage – The Usd.Stage to add the material.
path – The desired material path.
density – The material density.
static_friction – The static friction coefficient.
dynamic_friction – The dynamic friction coefficient.
restitution – The restitution coefficient.
- ovphysx.utils.materials.ensure_material_on_path(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
Define a UsdShade.Material at path if nothing incompatible is already there.
- Parameters:
stage – The Usd.Stage to add the material.
path – The desired material path.
Collision filtering#
Collision filtering: collision groups and filtered pairs.
Two independent mechanisms decide which colliders are allowed to interact. A
UsdPhysics.CollisionGroup holds a collection of colliders and a relationship
naming the groups it does not collide with, which is the scalable one. A
UsdPhysics.FilteredPairsAPI names individual prims on the prim itself, which
is the one to reach for when two specific bodies must ignore each other.
- ovphysx.utils.filtering.add_collision_group(stage: pxr.Usd.Stage, path: str | pxr.Sdf.Path)#
Define a collision group with an empty filtered-groups relationship.
- Parameters:
stage – The Usd.Stage to add the group.
path – The desired collision group path.
- ovphysx.utils.filtering.add_collision_to_collision_group(
- stage: pxr.Usd.Stage,
- collision_path: str | pxr.Sdf.Path,
- collision_group_path: str | pxr.Sdf.Path,
Add collision path to a collision group include rel.
- Parameters:
stage – The Usd.Stage to add path.
collision_path – Collision path to add.
collision_group_path – Collision group prim path.
- ovphysx.utils.filtering.add_pair_filter(
- stage: pxr.Usd.Stage,
- paths: List[str | pxr.Sdf.Path],
Make every prim in paths filter collisions against every other one.
Duplicate entries and a mix of
strandSdf.Pathspellings of the same prim are tolerated. Paths are compared by value, so no prim is given a filter against itself.- Parameters:
stage – The Usd.Stage holding the prims.
paths – The prim paths to filter against each other.
- ovphysx.utils.filtering.is_in_collision_group(
- stage: pxr.Usd.Stage,
- collision_path: str | pxr.Sdf.Path,
- collision_group_path: str | pxr.Sdf.Path,
Checks if a collision path belongs to a collision group include rel.
- Parameters:
stage – The Usd.Stage to add path.
collision_path – Collision path to add.
collision_group_path – Collision group prim path.
- ovphysx.utils.filtering.remove_collision_from_collision_group(
- stage: pxr.Usd.Stage,
- collision_path: str | pxr.Sdf.Path,
- collision_group_path: str | pxr.Sdf.Path,
Remove collision path to a collision group include rel.
- Parameters:
stage – The Usd.Stage to add path.
collision_path – Collision path to add.
collision_group_path – Collision group prim path.
- ovphysx.utils.filtering.remove_pair_filter(
- stage: pxr.Usd.Stage,
- paths: List[str | pxr.Sdf.Path],
Undo add_pair_filter for the given paths.
The UsdPhysics.FilteredPairsAPI is removed, and the physics:filteredPairs relationship with it, so a later add_pair_filter starts from no targets.
- Parameters:
stage – The Usd.Stage holding the prims.
paths – The prim paths to stop filtering.
Stage paths#
Stage path uniquification.
Authoring a prim at a path another prim already holds silently redefines that prim, so every helper that defines geometry resolves its path through here first. Both helpers only compute a name – neither touches the stage beyond asking what is already at a path.
- ovphysx.utils.paths.get_stage_next_free_path(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- prepend_default_prim: bool,
Gets valid path in stage, if the path already exists it will append number.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
prepend_default_prim – Whether prepend default prim path name.
Transforms#
Transform and xform-op helpers.
The physics runtime expects a translate-orient-scale xform op stack, and
authoring one correctly by hand is fiddly: an op may already exist at a
different precision, and resetXformStack has to survive a rewrite. These
helpers encapsulate that.
- ovphysx.utils.transform.copy_transform_as_scale_orient_translate(
- src: pxr.Usd.Prim | pxr.UsdGeom.Xformable,
- dst: pxr.Usd.Prim | pxr.UsdGeom.Xformable,
Copies the local transforms from one Xformable to another as a default scale->orient->translate stack.
- Note that:
Any skew in the src transform will be lost.
A resetXformStack is preserved, but not the XformOps that are ignored due to the reset.
The transform attribute precision of added XformOps is set to UsdGeom.XformOp.PrecisionFloat.
Obsolete xformOp: namespace attributes in dst are not removed (and cannot be for layers)
- Parameters:
src – The source prim or Xformable.
dst – The destination prim or Xformable.
- ovphysx.utils.transform.get_aligned_body_transform(stage, cache, joint, body0base)#
Compute the transform that aligns one joint body onto the other.
- Parameters:
stage – The Usd.Stage holding the bodies.
cache – A UsdGeom.XformCache used for the world transforms.
joint – The UsdPhysics.Joint to read.
body0base – True to treat body0 as the fixed base, False for body1.
- ovphysx.utils.transform.get_axis_aligned_vector(axis, len)#
Build an axis-aligned vector of the given length.
- Parameters:
axis – The axis name - “X”, “Y” or “Z”.
len – The signed length along that axis.
- ovphysx.utils.transform.get_basis(up_axis)#
Get the (up, forward, right) basis vectors for a stage’s up axis.
- Parameters:
up_axis – The stage up axis - “Y” selects a Y-up basis, anything else selects a Z-up basis.
- ovphysx.utils.transform.get_forward_vector(up_axis)#
Get the forward vector for a stage’s up axis.
- Parameters:
up_axis – The stage up axis - “Y” or “Z”.
- ovphysx.utils.transform.get_translation(prim: pxr.Usd.Prim) pxr.Gf.Vec3f | pxr.Gf.Vec3d#
Return the translate xform op value from the given prim.
- Parameters:
prim – The Usd.Prim to check.
- ovphysx.utils.transform.get_unit_scale_factor(stage)#
Get the stage’s units-per-meter scale factor.
- Parameters:
stage – The Usd.Stage to query.
- ovphysx.utils.transform.get_world_position(stage, path)#
Get the world-space center of a prim’s axis-aligned world bound.
- Parameters:
stage – The Usd.Stage to query.
path – The path of the imageable prim.
- ovphysx.utils.transform.set_or_add_orient_op(
- xformable: pxr.UsdGeom.Xformable,
- orient: pxr.Gf.Quatf | pxr.Gf.Quatd | pxr.Gf.Quath,
Sets or adds the orient XformOp on the input Xformable to provided orient value.
- Note that:
The precision of an added attribute is UsdGeom.XformOp.PrecisionFloat.
- Parameters:
xformable – The Xformable to modify.
orient – The orient quaternion
- Returns:
The set or added XformOp, or
Noneif the prim is not an Xformable. Its scale and translate siblings answerFalsefor that case rather thanNone.
- ovphysx.utils.transform.set_or_add_scale_op(
- xformable: pxr.UsdGeom.Xformable,
- scale: pxr.Gf.Vec3f | pxr.Gf.Vec3d | pxr.Gf.Vec3h,
Sets or adds the scale XformOp on the input Xformable to provided scale value.
- Note that:
The precision of an added attribute is UsdGeom.XformOp.PrecisionFloat.
- Parameters:
xformable – The Xformable to modify.
scale – The scale vector
- Returns:
The set or added XformOp, or
Falseif the prim is not an Xformable.
- ovphysx.utils.transform.set_or_add_scale_orient_translate(
- xformable: pxr.UsdGeom.Xformable,
- scale: pxr.Gf.Vec3f | pxr.Gf.Vec3d | pxr.Gf.Vec3h,
- orient: pxr.Gf.Quatf | pxr.Gf.Quatd | pxr.Gf.Quath,
- translate: pxr.Gf.Vec3f | pxr.Gf.Vec3d | pxr.Gf.Vec3h,
Sets or adds scale, orient, and translate XformOps of xformable.
- Note that:
The precision of created attributes is UsdGeom.XformOp.PrecisionFloat.
- Parameters:
xformable – The Xformable to modify.
scale – The scale vector
orient – The orientation quaternion
translate – The translation vector
- Returns:
List of set and created xform ops that will be [translate, orient, scale], or
Falseif the prim is not an Xformable.
- ovphysx.utils.transform.set_or_add_translate_op(
- xformable: pxr.UsdGeom.Xformable,
- translate: pxr.Gf.Vec3f | pxr.Gf.Vec3d | pxr.Gf.Vec3h,
Sets or adds the translate XformOp on the input Xformable to provided translate value.
- Note that:
The precision of an added attribute is UsdGeom.XformOp.PrecisionFloat.
- Parameters:
xformable – The Xformable to modify.
translate – The translate vector
- Returns:
The set or added XformOp, or
Falseif the prim is not an Xformable.
- ovphysx.utils.transform.setup_transform_as_scale_orient_translate(
- xformable: pxr.Usd.Prim | pxr.UsdGeom.Xformable,
Changes the local transform (ops) to the physics default scale->orient->translate stack.
- Note that:
Any skew in the transform will be lost.
A resetXformStack is preserved, but not the XformOps that are ignored due to the reset.
The transform attribute precision is set to UsdGeom.XformOp.PrecisionFloat.
Obsolete xformOp: namespace attributes are not removed (and cannot be for layers)
- Parameters:
xformable – The prim or Xformable to modify.
Mesh construction and tetrahedral meshes#
Procedural mesh construction and triangle / tetrahedron mesh math.
Two groups of helper live here: constructors that define a UsdGeom.Mesh for
a primitive shape, and pure geometry routines over point and index lists that
carry no USD state.
create_tetra_voxels yields an empty mesh for a non-positive integer
voxel_dim rather than raising.
- ovphysx.utils.mesh.calculate_tetra_volume(a, b, c, d)#
Compute the signed volume of a tetrahedron.
- Parameters:
a – The four tetrahedron corner points.
b – The four tetrahedron corner points.
c – The four tetrahedron corner points.
d – The four tetrahedron corner points.
- ovphysx.utils.mesh.compute_bounding_box_diagonal(points) float#
Gets diagonal length of given point bounds.
- Parameters:
points – The input points. Any iterable of indexable three-component points, e.g. Gf.Vec3f, tuples or lists.
- Raises:
ValueError – If
pointsis empty.
- ovphysx.utils.mesh.convert_tetra_to_triangle_soup(points_in, indices_in)#
Expand every tetrahedron into its four unshared triangles.
- Parameters:
points_in – The tet mesh points.
indices_in – The tet mesh vertex indices, four per tetrahedron.
- ovphysx.utils.mesh.create_mesh(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- points: List[pxr.Gf.Vec3f] | List[pxr.Gf.Vec3d],
- normals: List[pxr.Gf.Vec3f] | List[pxr.Gf.Vec3d],
- indices: List[int],
- vertex_counts: List[int],
Create UsdGeom.Mesh from given points, normals, indices and face counts.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
points – The input points.
normals – The input normals.
indices – The indices for faces.
vertex_counts – Face counts.
- ovphysx.utils.mesh.create_mesh_concave(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- half_size: float,
Create UsdGeom.Mesh that represents a concave mesh.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
half_size – The half size of the mesh.
- ovphysx.utils.mesh.create_mesh_cone(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- height: float,
- radius: float,
- tesselation: int = 32,
Create UsdGeom.Mesh that represents a cone mesh.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
height – The height of the cone.
radius – The radius of the cone.
tesselation – The tesselation of the cone mesh.
- ovphysx.utils.mesh.create_mesh_cube(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- half_size: float,
Create UsdGeom.Mesh that represents a cube mesh.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
half_size – The half size of the cube.
- ovphysx.utils.mesh.create_mesh_cylinder(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- height: float,
- radius: float,
- tesselation: int = 32,
Create UsdGeom.Mesh that represents a cylinder mesh.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
height – The height of the cylinder.
radius – The radius of the cylinder.
tesselation – The tesselation of the cylinder mesh.
- ovphysx.utils.mesh.create_mesh_square_axis(
- stage: pxr.Usd.Stage,
- path: str | pxr.Sdf.Path,
- axis: str,
- half_size: float,
Create UsdGeom.Mesh that represents a square.
- Parameters:
stage – The Usd.Stage to add path.
path – The desired path to create.
axis – The up axis “Y”, “Z”.
half_size – The half size of the square.
- ovphysx.utils.mesh.create_tetra_voxel_box(voxel_dim)#
Build a unit-cube tetrahedral mesh centered on the origin.
A non-positive integer grid resolution yields an empty mesh.
- Parameters:
voxel_dim – The voxel grid resolution.
- ovphysx.utils.mesh.create_tetra_voxel_sphere(voxel_dim)#
Build a unit-diameter sphere tetrahedral mesh centered on the origin.
A non-positive integer grid resolution yields an empty mesh.
- Parameters:
voxel_dim – The voxel grid resolution.
- ovphysx.utils.mesh.create_tetra_voxels(voxel_dim, occupancy_filter_func)#
Build a tetrahedral mesh from an occupancy-filtered voxel grid.
Every occupied voxel is split into the five tetrahedra of
cube_tetrahedra. Alternate cubes are mirrored per axis, and a cube mirrored an odd number of times has its tetrahedra re-wound, so neighbouring cubes share faces.- Parameters:
voxel_dim – The grid resolution, used for all three axes. A non-positive integer yields an empty mesh.
occupancy_filter_func – Called as (x, y, z, dimx, dimy, dimz); returns True for an occupied voxel.
- ovphysx.utils.mesh.create_triangle_mesh_cube(dim: int)#
Build the surface triangle mesh of a voxelized unit cube.
A non-positive integer grid resolution yields an empty mesh.
- Parameters:
dim – The voxel grid resolution.
- ovphysx.utils.mesh.create_triangle_mesh_square(dimx: int, dimy: int, scale: float = 1.0)#
Creates points and vertex data for a regular-grid flat triangle mesh square.
A non-positive integer grid dimension yields an empty mesh.
- Parameters:
dimx – Mesh-vertex resolution in X
dimy – Mesh-vertex resolution in Y
scale – Uniform scale applied to vertices
- Returns:
The vertex and index data
- Return type:
points, indices
- ovphysx.utils.mesh.cube_tetrahedra()#
Return the five-tetrahedron decomposition of a unit cube.
- ovphysx.utils.mesh.extract_triangle_surface_from_tetra(tetra_points, tetra_indices)#
Extract the outer surface triangles of a tetrahedral mesh.
Occurrences of each face are counted: a face that appears more than once is interior and is discarded, and the faces appearing exactly once form the surface.
- Parameters:
tetra_points – The tet mesh points.
tetra_indices – The tet mesh vertex indices, four per tetrahedron.
- ovphysx.utils.mesh.fixup_tetra_mesh_volumes(points, indices)#
Return tet indices with inverted tetrahedra re-wound to positive volume.
- Parameters:
points – The tet mesh points.
indices – The tet mesh vertex indices, four per tetrahedron.
- ovphysx.utils.mesh.triangulate_mesh(mesh: pxr.UsdGeom.Mesh) List[int]#
Fan-triangulate a mesh’s faces into a flat triangle index list.
- Parameters:
mesh – The UsdGeom.Mesh to read.
- ovphysx.utils.mesh.verify_tetra_mesh(points, indices)#
Check a tet mesh for index-count, out-of-range and inverted-volume errors.
Problems are logged as warnings; the first one found stops the check. An index below zero is out of range on the same terms as one past the end.
- Parameters:
points – The tet mesh points.
indices – The tet mesh vertex indices, four per tetrahedron.
Particles#
Particle system, particle set and PBD material authoring.
A particle simulation needs a PhysxParticleSystem prim, a set prim carrying
PhysxParticleSetAPI that points back at it, and usually a PBD material. The
helpers here author all three, plus the optional feature APIs (anisotropy,
smoothing, isosurface, diffuse particles) and the sampling API.
Every schema attribute is an optional keyword that defaults to None and is
only authored when supplied, so an unset attribute keeps the schema fallback
rather than being pinned to a value chosen here.
The PhysX schemas are codeless, so these helpers apply APIs by identifier and
author properties by name; add_physx_particle_system() answers with the
Usd.Prim it defined. Refer to ovphysx.utils.codeless.
- ovphysx.utils.particles.add_pbd_material_viscous(p)#
Applies a viscous-fluid PBD material preset to a material prim.
The surface tension and viscosity presets are in SI, so they are converted to the stage’s units before being authored.
- Parameters:
p – The UsdShade.Material prim.
- ovphysx.utils.particles.add_pbd_material_water(p)#
Applies a water PBD material preset to a material prim.
The surface tension and viscosity presets are in SI, so they are converted to the stage’s units before being authored.
- Parameters:
p – The UsdShade.Material prim.
- ovphysx.utils.particles.add_pbd_particle_material(
- stage,
- path,
- friction=None,
- particle_friction_scale=None,
- damping=None,
- viscosity=None,
- vorticity_confinement=None,
- surface_tension=None,
- cohesion=None,
- adhesion=None,
- particle_adhesion_scale=None,
- adhesion_offset_scale=None,
- gravity_scale=None,
- density=None,
- cfl_coefficient=None,
Applies the PhysxPBDMaterialAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to UsdShade.Material to which the material API should be applied to
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.particles.add_physx_diffuse_particles(
- stage,
- path,
- enabled=None,
- max_diffuse_particle_multiplier=None,
- threshold=None,
- lifetime=None,
- air_drag=None,
- bubble_drag=None,
- buoyancy=None,
- kinetic_energy_weight=None,
- pressure_weight=None,
- divergence_weight=None,
- collision_decay=None,
- use_accurate_velocity=None,
Applies the PhysxDiffuseParticlesAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to the prim to which the diffuse particle API should be applied to
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.particles.add_physx_particle_anisotropy(
- stage,
- path,
- enabled=None,
- scale=None,
- min=None,
- max=None,
Applies the PhysxParticleAnisotropyAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to the prim to which the anisotropy API should be applied to
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.particles.add_physx_particle_isosurface(
- stage,
- path,
- enabled=None,
- max_vertices=None,
- max_triangles=None,
- max_subgrids=None,
- grid_spacing=None,
- surface_distance=None,
- grid_filtering_passes=None,
- grid_smoothing_radius=None,
- num_mesh_smoothing_passes=None,
- num_mesh_normal_smoothing_passes=None,
Applies the PhysxParticleIsosurfaceAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to the prim to which the isosurface API should be applied to
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.particles.add_physx_particle_smoothing(stage, path, enabled=None, strength=None)#
Applies the PhysxParticleSmoothingAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to the prim to which the smoothing API should be applied to
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.particles.add_physx_particle_system(
- stage,
- particle_system_path,
- particle_system_enabled=None,
- simulation_owner=None,
- contact_offset=None,
- rest_offset=None,
- particle_contact_offset=None,
- solid_rest_offset=None,
- fluid_rest_offset=None,
- enable_ccd=None,
- solver_position_iterations=None,
- max_depenetration_velocity=None,
- wind=None,
- max_neighborhood=None,
- neighborhood_scale=None,
- max_velocity=None,
- global_self_collision_enabled=None,
- non_particle_collision_enabled=None,
Creates a PhysxParticleSystem prim at particle_system_path on stage.
- Parameters:
stage – The stage
particle_system_path – Path where the system should be created at
attributes (... schema) – See USD schema for documentation
An occupied path is rejected with a
ValueErrorrather than the prim that is already there being retyped.The concrete codeless prim type must be registered before this function mutates the stage.
- Returns:
The particle system
Usd.Prim, or None if the prim could not be defined.- Raises:
CodelessSchemaError – If
PhysxParticleSystemis not registered.
- ovphysx.utils.particles.add_physx_particleset_pointinstancer(
- stage,
- path: str | pxr.Sdf.Path,
- positions,
- velocities,
- particle_system_path,
- self_collision,
- fluid,
- particle_group,
- particle_mass,
- density,
- num_prototypes: int = 1,
- prototype_indices: list | None = None,
Creates a particle set based on a UsdGeom.PointInstancer at path on stage.
- Parameters:
stage – The stage
path – Path where the UsdGeom.PointInstancer particle set should be created
positions – List of particle positions
velocities – List of particle velocities
particle_system_path – Path to particle system that simulates the set
self_collision – Enable particle-particle collision in the set
fluid – Simulate the particle set as fluid
particle_group – The particle group, see schema API doc
particle_mass – The per-particle mass - total mass of set is num particles * particle_mass
density – The density of the particles - is used to compute particle (set) mass if no mass provided
num_prototypes – The number of render prototypes to create (children of point instancer)
prototype_indices – The prototype indices for the particles (same length as positions). Will default to 0 for all if not provided.
An occupied path is rejected with a
ValueErrorrather than the prim that is already there being retyped.- Returns:
The created UsdGeom.PointInstancer prim
- ovphysx.utils.particles.add_physx_particleset_points(
- stage,
- path,
- positions_list,
- velocities_list,
- widths_list,
- particle_system_path,
- self_collision,
- fluid,
- particle_group,
- particle_mass,
- density,
Creates a particle set based on a UsdGeom.Points at path on stage.
- Parameters:
stage – The stage
path – Path where the UsdGeom.Points particle set should be created
positions_list – List of particle positions
velocities_list – List of particle velocities
widths_list – List of particle widths
particle_system_path – Path to particle system that simulates the set
self_collision – Enable particle-particle collision in the set
fluid – Simulate the particle set as fluid
particle_group – The particle group, see schema API doc
particle_mass – The per-particle mass - total mass of set is num particles * particle_mass
density – The density of the particles - is used to compute particle (set) mass if no mass provided
An occupied path is rejected with a
ValueErrorrather than the prim that is already there being retyped.- Returns:
The UsdGeom.Points
- ovphysx.utils.particles.configure_particle_set(
- particle_set_prim,
- particle_system_path,
- self_collision,
- fluid,
- particle_group,
- mass=0.0,
- density=0.0,
Applies the particle set and mass APIs that turn a points or instancer prim into particles.
- Parameters:
particle_set_prim – The UsdGeom.Points or UsdGeom.PointInstancer prim.
particle_system_path – Path to the particle system that simulates the set.
self_collision – Enable particle-particle collision in the set.
fluid – Simulate the particle set as fluid.
particle_group – The particle group, see schema API doc.
mass – The total mass of the set.
density – The density used when no mass is provided.
- ovphysx.utils.particles.create_particles_grid(
- lower,
- particle_spacing,
- dim_x,
- dim_y,
- dim_z,
- uniform_particle_velocity=Gf.Vec3f(0.0),
Builds a regular grid of particle positions and a matching velocity list.
- Parameters:
lower – The grid’s minimum corner.
particle_spacing – The distance between adjacent particles.
dim_x – Particle count along X.
dim_y – Particle count along Y.
dim_z – Particle count along Z.
uniform_particle_velocity – The velocity given to every particle.
- Returns:
A (positions, velocities) tuple.
- ovphysx.utils.particles.poisson_sample_mesh(stage: pxr.Usd.Stage, prim_path: pxr.Sdf.Path)#
Marks a mesh for volume particle sampling, creating a particle system if the stage has none.
Only authors the sampling request; the runtime performs the sampling when the stage is simulated.
The stage’s first particle system is reused wherever it sits. Creating one defines
/Worldand makes it the stage default prim when the stage has none.- Parameters:
stage – The stage.
prim_path – Path to the mesh to sample.
- Returns:
The path of the particle system that will sample the mesh, or an empty
Sdf.Pathif no particle system could be obtained.A stage that has no particle system and whose default particle system path is already held by a prim of another type gets the empty path too, rather than that prim being written over.
Deformables#
Volume and surface deformable body authoring.
A deformable body is spread across several prims and API schemas, and getting the combination wrong fails quietly at parse time rather than loudly at authoring time. These helpers validate the prim type up front, apply the schema set in the order the parser expects, and author the rest-shape attributes.
Two shapes are supported. The set_physics_*_deformable_body pair configures
a single prim that is both the simulation and the collision geometry. The
create_auto_*_deformable_hierarchy pair builds the multi-prim layout instead,
where a root prim carries the body API, a cooking source mesh drives generation
of the simulation and collision meshes, and any remaining point-based geometry
in the subtree becomes skinned visual geometry with a bind pose.
The deformable schemas are multiple-apply and partly codeless, so they are
reached by type name through Usd.Prim.ApplyAPI and by property path rather
than through generated Python classes.
The bind-pose writes in the two create_auto_* helpers are the one exception
to routing property access through codeless. They use
Usd.Prim.CreateAttribute directly, so that a prim whose
OmniPhysicsDeformablePoseAPI application USD refuses does not abort the pass
over the rest of the subtree; codeless.set_attr would raise there.
REQ-PYTHON-UTILS-001, “Where the deformable pose attributes stay raw”,
records the reasoning.
- ovphysx.utils.deformable.add_auto_deformable_mesh_simplification(
- stage,
- prim_path: pxr.Sdf.Path,
- Add a simplification collision mesh on a prim with PhysxAutoDeformableBodyAPI, and setup the deformable
body correspondingly.
- Parameters:
stage – The stage
prim_path – Path to UsdGeom.Scope/UsdGeom.Xform to which the PhysxAutoDeformableBodyAPI is applied to.
- Returns:
True / False that indicates success of schema application
- ovphysx.utils.deformable.add_deformable_material(
- stage: pxr.Usd.Stage,
- path,
- density=None,
- static_friction=None,
- dynamic_friction=None,
- youngs_modulus=None,
- poissons_ratio=None,
Applies the UsdPhysics.DeformableMaterialAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to UsdShade.Material to which the material API should be applied to.
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.deformable.add_surface_deformable_material(
- stage: pxr.Usd.Stage,
- path,
- density=None,
- static_friction=None,
- dynamic_friction=None,
- youngs_modulus=None,
- poissons_ratio=None,
- surface_thickness=None,
- surface_stretch_stiffness=None,
- surface_shear_stiffness=None,
- surface_bend_stiffness=None,
Applies the UsdPhysics.SurfaceDeformableMaterialAPI to the prim at path on stage.
- Parameters:
stage – The stage
path – Path to UsdShade.Material to which the material API should be applied to.
attributes (... schema) – See USD schema for documentation
- Returns:
True if the API apply succeeded.
- ovphysx.utils.deformable.create_auto_surface_deformable_hierarchy(
- stage: pxr.Usd.Stage,
- root_prim_path: str | pxr.Sdf.Path,
- simulation_mesh_path: str | pxr.Sdf.Path,
- cooking_src_mesh_path: str | pxr.Sdf.Path,
- cooking_src_simplification_enabled: bool,
- set_visibility_with_guide_purpose: bool = False,
Creates a surface deformable body from a stage hierachy and adds necessary prims and APIs. For single prim deformable bodies, use set_physics_surface_deformable_body on a UsdGeom.Mesh.
- Parameters:
stage – The stage
root_prim_path – Path to valid a UsdGeom.Imageable which cannot be a UsdGeom.Gprim. The UsdPhysics.DeformableBodyAPI is applied to this prim.
simulation_mesh_path – Path to where simulation mesh should be created or a valid UsdGeom.Mesh.
cooking_src_mesh_path – Path to valid UsdGeom.Mesh that is used in cooking to generate the simulation mesh. May be outside of root_prim_path sub-hierarchy.
cooking_src_simplification_enabled – If True, PhysxAutoDeformableMeshSimplificationAPI is applied.
set_visibility_with_guide_purpose – If True, the simulation mesh is assigned the guide purpose to hide it from rendering - but only if other GPrims are present under root_prim_path to provide visible geometry.
- Returns:
True / False that indicates success of creation.
A PointBased visual prim without points at the default time returns False before the stage is modified.
- ovphysx.utils.deformable.create_auto_volume_deformable_hierarchy(
- stage: pxr.Usd.Stage,
- root_prim_path: str | pxr.Sdf.Path,
- simulation_tetmesh_path: str | pxr.Sdf.Path,
- collision_tetmesh_path: str | pxr.Sdf.Path,
- cooking_src_mesh_path: str | pxr.Sdf.Path,
- simulation_hex_mesh_enabled: bool,
- cooking_src_simplification_enabled: bool,
- set_visibility_with_guide_purpose: bool = False,
Creates a volume deformable body from a stage hierachy and adds necessary prims and APIs. For single prim deformable bodies, use set_physics_volume_deformable_body on a UsdGeom.TetMesh.
- Parameters:
stage – The stage
root_prim_path – Path to valid a UsdGeom.Imageable which cannot be a UsdGeom.Gprim. The UsdPhysics.DeformableBodyAPI is applied to this prim.
simulation_tetmesh_path – Path to where simulation mesh should be created or a valid UsdGeom.TetMesh.
collision_tetmesh_path – Path to where collision mesh should be created or a valid UsdGeom.TetMesh. CollisionAPI is applied to the collision mesh. May be identical to simulation_tetmesh_path.
cooking_src_mesh_path – Path to valid UsdGeom.Mesh that is used in cooking to generate the simulation and collision mesh. May be outside of root_prim_path sub-hierarchy.
simulation_hex_mesh_enabled – If True, simulation mesh is generated as a hexahedral mesh.
cooking_src_simplification_enabled – If True, PhysxAutoDeformableMeshSimplificationAPI is applied.
set_visibility_with_guide_purpose – If True, the simulation and collision meshes are assigned the guide purpose to hide them from rendering - but only if other GPrims are present under root_prim_path to provide visible geometry. If the simulation and collision meshes are the only geometry present and are distinct, then only the simulation mesh is assigned the guide purpose, leaving the collision mesh for visual representation.
- Returns:
True / False that indicates success of creation.
A hexahedral mesh API that fails to apply returns False, on the same terms as a failed mesh simplification request. A caller that asked for a hexahedral simulation mesh is never told it succeeded with a tetrahedral one.
A PointBased visual prim without points at the default time returns False before the stage is modified.
- ovphysx.utils.deformable.remove_auto_deformable_body(stage, prim_path: pxr.Sdf.Path)#
Removes the auto deformable body API set and its generated sub-component APIs.
- Parameters:
stage – The stage.
prim_path – Path to the prim carrying PhysxAutoDeformableBodyAPI.
- ovphysx.utils.deformable.remove_auto_deformable_hexahedral_mesh(stage, prim_path: pxr.Sdf.Path)#
Removes the hexahedral simulation mesh request from an auto deformable body.
- Parameters:
stage – The stage.
prim_path – Path to the prim carrying PhysxAutoDeformableHexahedralMeshAPI.
- ovphysx.utils.deformable.remove_auto_deformable_mesh_simplification(
- stage,
- prim_path: pxr.Sdf.Path,
Removes the cooking-source simplification request from an auto deformable body.
- Parameters:
stage – The stage.
prim_path – Path to the prim carrying PhysxAutoDeformableMeshSimplificationAPI.
- ovphysx.utils.deformable.remove_deformable_body(stage, prim_path: pxr.Sdf.Path)#
Removes every deformable body API, and its local properties, from a prim and its subtree.
Both the single-prim and the hierarchical layouts are handled, and the per-instance deformable pose APIs are removed too. A simulation mesh prim that was generated automatically is left in place, since a caller may have taken ownership of it.
The sweep covers the supplied prim and every descendant, at any depth. It does not stop at a prim that resets its xform stack, so it also reaches pose APIs a caller applied outside the range the
create_auto_*_deformable_hierarchyhelpers author over.UsdPhysics.CollisionAPIis the exception, and is taken only from a prim carrying a deformable simulation API, at any depth of that same sweep. Every other prim keeps it, a volume hierarchy’s separate collision mesh included. A collision API the caller applied to the simulation geometry goes with the body.A property is removed from the current edit target, so one whose opinion arrives over a reference or an inherit arc, or from a stronger layer, keeps its resolved value after its API is gone. The API itself does go: the removal composes over such an arc.
- Parameters:
stage – The stage.
prim_path – Path to the deformable body root prim.
- ovphysx.utils.deformable.set_physics_surface_deformable_body(
- stage,
- prim_path: pxr.Sdf.Path,
Setup a surface deformable body based on a UsdGeom.Mesh at prim_path on stage and add necessary prims and APIs. For hierarchical setups use create_auto_surface_deformable_hierarchy.
- Parameters:
stage – The stage
prim_path – Path to UsdGeom.Mesh ‘sim mesh’ to which the UsdPhysics.DeformableBodyAPI is applied to.
- Returns:
True / False that indicates success of schema application
Missing default-time points or face topology return False before the stage is modified.
- ovphysx.utils.deformable.set_physics_volume_deformable_body(
- stage,
- prim_path: pxr.Sdf.Path,
Setup a volume deformable body based on a UsdGeom.TetMesh at prim_path on stage and add necessary prims and APIs. For hierarchical setups use create_auto_volume_deformable_hierarchy.
- Parameters:
stage – The stage
prim_path – Path to UsdGeom.TetMesh ‘sim mesh’ to which the UsdPhysics.DeformableBodyAPI is applied to.
- Returns:
True / False that indicates success of schema application
Missing default-time points or tetrahedron indices return False before the stage is modified.
Schema introspection#
USD schema introspection and API-schema property manipulation.
These helpers work against the USD schema registry, so they cover schemas that
were registered from a codeless plugin as well as compiled ones. That is what
makes them useful outside Kit: a caller that only has pxr can still
enumerate a PhysX API schema’s properties, snapshot them, and restore them.
How properties are reached#
ovphysx ships the PhysX schemas codeless, so TfType.pythonClass is None
for them and every property here is reached through the registry:
get_schema_attribute()andget_schema_relationship()return theSdfproperty spec.create_api_schema_property_cache()records the property’s value type, andapply_api_schema_property_cache()replays it through the genericUsd.PrimAPI rather than a typedCreate*Attrmethod.
- ovphysx.utils.schema.ancestor_has_api(name, prim)#
Check whether a prim or any ancestor has an API schema applied.
A prim that resets its xform stack terminates the ascent, because it no longer inherits its ancestors’ transform. The boundary is read with
UsdGeom.Xformable.GetResetXformStack().- Parameters:
name – The API schema to look for, as a schema identifier string, a typed schema class, or a
Tf.Type.prim – The Usd.Prim to start from.
- ovphysx.utils.schema.apply_api_schema_property_cache(cache, prim, multiple_api_token=None)#
Restore values captured by
create_api_schema_property_cache().Replays the cache through the generic
Usd.Primproperty API, so it works for codeless and compiled schemas alike. Apply the owning API schema to the prim first; this only authors properties.Unset properties – a
Noneattribute value, orNonerelationship targets – are skipped so that restoring does not author an opinion the snapshot did not have. The relationship test istargets is Noneand notnot targets: an empty target list is how an authored-empty relationship is snapshotted. Seecreate_api_schema_property_cache().- Parameters:
cache – The cache to replay.
prim – The Usd.Prim to author on.
multiple_api_token – The instance name, for a multiple-apply schema.
- ovphysx.utils.schema.create_api_schema_property_cache(api, prim)#
Snapshot an API schema’s attribute and relationship values on a prim.
The result is consumed by
apply_api_schema_property_cache(), which makes it possible to remove an API schema and restore its authored values later.Only authored state is recorded. The snapshot holds one entry per property the API declares, and what that entry carries is the property’s authored value or targets, or nothing at all: an attribute that has only its schema fallback, and a relationship with no authored targets, are both snapshotted as unset.
“Authored” is USD’s own sense of the word throughout: an opinion exists somewhere in the prim’s composed property stack, as opposed to the value coming from a schema fallback. An opinion arriving over a reference, an inherit, a specialize, a variant or a weaker sublayer therefore counts as authored and is recorded. The snapshot does not tell a local opinion from a composed one; what it excludes is the fallback.
A relationship needs
Usd.Relationship.HasAuthoredTargetsfor that distinction, because an unauthored relationship and one authored with an empty target list both compose to an empty list. An unauthored one is stored withNonetargets, as an unauthored attribute is stored with aNonevalue; an authored one is stored with its target list whether or not that list is empty.apply_api_schema_property_cache()skipsNonetargets and not the empty list, so a relationship authored with no targets is replayed and one carrying no opinion is left alone.The cache exists for
remove_api_schema_properties(), not for the removal of the API schema:Usd.Prim.RemoveAPIandovphysx.utils.codeless.remove_api()drop the prim’sapiSchemasentry and leave every property authored under it in place.remove_collider()strips the approximation and cooked-data APIs’ properties itself and leavesPhysxCollisionAPI’s, so removing those is the caller’s to ask for and snapshotting them first is how the caller gets them back.Example:
from pxr import UsdPhysics from ovphysx.utils import ( apply_api_schema_property_cache, create_api_schema_property_cache, remove_api_schema_properties, remove_collider, set_collider, ) # prim is a UsdGeom.Mesh set up as a convexHull collider, carrying # authored physxCollision:contactOffset and physxCollision:restOffset # and a physxConvexHullCollision:hullVertexLimit. tuning = create_api_schema_property_cache("PhysxCollisionAPI", prim) # Takes the hull API's own opinions with it; leaves the two offsets, # which is why they have to be removed explicitly here. remove_collider(prim) remove_api_schema_properties("PhysxCollisionAPI", prim) set_collider(prim, UsdPhysics.Tokens.convexDecomposition) apply_api_schema_property_cache(tuning, prim)
The prim ends up approximated as a convex decomposition, carrying the two offsets it started with and no leftover
physxConvexHullCollisionopinion. The other attributesPhysxCollisionAPIdeclares stay unauthored, because the snapshot recorded no value for them.- Parameters:
api – The API schema type-name string or schema class.
prim – The Usd.Prim to read.
- Returns:
[attributes, relationships], where each attribute entry is(name, value_type, value)and each relationship entry is(name, targets). The value type is theSdf.ValueTypeNameneeded to recreate the property, a codeless schema having no class to name.valueandtargetsare bothNonefor an unauthored property.targetsis an empty list only for a relationship authored with no targets, which is what lets that opinion survive a restore.
- ovphysx.utils.schema.create_multiple_api_schema_property_cache(
- api,
- prim,
- api_prefix,
- multiple_token,
Snapshot one instance of a multiple-apply API schema’s properties.
- Parameters:
api – The API schema type-name string or schema class.
prim – The Usd.Prim to read.
api_prefix – The property namespace prefix, e.g. “physxCookedData”.
multiple_token – The instance name.
- Returns:
The same shape as
create_api_schema_property_cache(), except that names are recorded asprefix:__INSTANCE_NAME__:nametemplates.apply_api_schema_property_cache()substitutes itsmultiple_api_tokeninto them, so a snapshot can be replayed onto a different instance. It records authored state only, on the same terms – includingNonetargets for a relationship instance with no authored ones, as against an empty list for one authored with none.
- ovphysx.utils.schema.descendant_has_api(name, prim)#
Check whether a prim or any descendant has an API schema applied.
A prim that resets its xform stack terminates the descent, because its subtree no longer inherits the ancestor’s transform. The boundary is read with
UsdGeom.Xformable.GetResetXformStack().- Parameters:
name – The API schema to look for, as a schema identifier string, a typed schema class, or a
Tf.Type.prim – The Usd.Prim to start from.
- ovphysx.utils.schema.get_schema_attribute(
- schema,
List (name, spec) pairs for a schema’s attributes.
- Parameters:
schema – A schema type-name string or schema class.
- Returns:
(bare_property_name, Sdf.AttributeSpec)pairs. Readspec.typeNamefor the value type.
- ovphysx.utils.schema.get_schema_instances(prim, schema_type_name)#
Get the instance names of a multiple-apply schema applied to a prim.
- Parameters:
prim – The Usd.Prim to inspect.
schema_type_name – The multiple-apply schema type name.
- ovphysx.utils.schema.get_schema_prim_def(schema)#
Get the registry prim definition for an applied API or concrete schema.
- Parameters:
schema – A schema type-name string or schema class.
- ovphysx.utils.schema.get_schema_property_names(schema)#
List the property names a schema registers.
- Parameters:
schema – A schema type-name string or schema class.
- ovphysx.utils.schema.get_schema_relationship(
- schema,
List (name, spec) pairs for a schema’s relationships.
- Parameters:
schema – A schema type-name string or schema class.
- Returns:
(bare_property_name, Sdf.RelationshipSpec)pairs. Seeget_schema_attribute()for why this is a spec and not a class.
- ovphysx.utils.schema.get_tf_type_compatible(schema_type_or_type_name)#
Resolve a schema identifier to a TfType, passing a TfType through.
Accepts a schema type-name string (the only form available for a codeless schema), a typed schema class, or an existing
Tf.Type.- Parameters:
schema_type_or_type_name – A schema type-name string, schema class, or type.
- ovphysx.utils.schema.has_schema(prim, schema_name)#
Check whether a prim has an applied schema, matching by name.
- Parameters:
prim – The Usd.Prim to check.
schema_name – The applied schema name, e.g. “PhysicsRigidBodyAPI”.
- ovphysx.utils.schema.remove_api_schema_properties(api, prim)#
Remove every property an API schema defines from a prim.
- Parameters:
api – The API schema type-name string or schema class.
prim – The Usd.Prim to strip.
- ovphysx.utils.schema.remove_multiple_api_schema_properties(
- api,
- prim,
- api_prefix,
- multiple_token,
Remove one instance of a multiple-apply API schema’s properties.
- Parameters:
api – The API schema type-name string or schema class.
prim – The Usd.Prim to strip.
api_prefix – The property namespace prefix, e.g. “physxCookedData”.
multiple_token – The instance name.
Simulation#
Stepping a running simulation and writing its output back to ovstage.
Every other submodule here authors a stage; this one drives a running
simulation. step_and_write_to_ovstage() performs the whole
step-read-write-back loop an application would otherwise spell out by hand,
without that workflow becoming part of the core ovphysx.api.PhysX surface.
That makes this the one submodule whose helpers are not pure pxr: they need
ovstage when called, and an attached PhysX instance to call them on.
ovstage is therefore imported inside the function bodies, so
import ovphysx.utils still needs nothing beyond pxr and the standard
library and still loads no native library.
- class ovphysx.utils.simulation.OvStageOutputCache(physx: PhysX)#
Reusable application-owned state for
step_and_write_to_ovstage().The cache binds to the exact OVStage attachment and lazily owns copies of scales derived from
omni:fabric:worldMatrixand point-instancer pose arrays. It also reuses Warp buffers on each producing device. Callrefresh()after authored transforms, point-instancer pose arrays, or topology change. Omit the cache fromstep_and_write_to_ovstage()to read current OVStage values on every call instead.- close() None#
Release cache-owned wrappers and buffers. Safe to call repeatedly.
- refresh() None#
Discard owned snapshots and device-specific buffers.
- ovphysx.utils.simulation.step_and_write_to_ovstage(
- physx: PhysX,
- *,
- dt: float,
- output_ordinal: int,
- cache: OvStageOutputCache | None = None,
- outputs: Mapping[SimObjectType, Sequence[str]] | None = None,
Step once and write selected physics output to the attached OVStage.
Fixed rigid-body, articulation-link, and vehicle-wheel poses are combined with scale derived from the current
omni:fabric:worldMatrixand written directly to that attribute. The helper never writesomni:xformoromni:resetXformStack. Point-instancer rigid-body poses are written to their native instancer-localpositionsandorientationsarrays; unsimulated slots retain the current OVStage values.By default the helper reads current OVStage values on every call and keeps no snapshots after returning. Passing an application-owned
cacheopts into retaining derived scale, point-instancer baselines, Warp buffers, and CUDA events across calls. Persistent borrowed OVStage views are never kept.Other selected output is written to its shadow
sim:<name>attribute.output_ordinalis caller-owned and must never be drained back into physics withovphysx.api.PhysX.update_from_ovstage().- Parameters:
physx – Attached simulation instance to step and read.
dt – Simulation time step in seconds.
output_ordinal – OVStage ordinal used only for physics output.
cache – Optional application-owned snapshots and reusable buffers.
outputs – Optional object-type-to-attribute selection.
Noneuses the documented default dynamic output set.
- Returns:
Number of OVStage attributes written.
Metadata keys and naming constants#
Constants shared by the authoring helpers.
Collected here rather than duplicated per module.
ovphysx ships the PhysX schemas codeless, so PhysX schema tokens are spelled
out here as string literals; refer to ovphysx.utils.codeless.
- ovphysx.utils.constants.AXES_INDICES = {'X': 0, 'Y': 1, 'Z': 2}#
Maps an axis name to its index in a 3-vector.
- ovphysx.utils.constants.COOKED_DATA_TOKENS = [pxr.UsdPhysics.Tokens.convexHull, pxr.UsdPhysics.Tokens.convexDecomposition, 'triangleMesh']#
The
PhysxCookedDataAPIinstance names, one per cooked representation. Each is the instance name of a multiple-apply API, so its buffer lives atphysxCookedData:<token>:buffer.The three values are
"convexHull","convexDecomposition"and"triangleMesh". They are spelled out here because the first two are read fromUsdPhysics.Tokens, which the documentation build mocks along with the rest ofpxr: the rendered value of this list therefore shows a mock placeholder in place of each of the two, besidetriangleMeshas a real literal. Do not read the rendered list as the values.
- ovphysx.utils.constants.MAX_FLOAT = 3.40282347e+38#
The largest finite value a USD
floatattribute can hold.
- ovphysx.utils.constants.MESH_APPROXIMATIONS = {'sdf': 'PhysxSDFMeshCollisionAPI', 'sphereFill': 'PhysxSphereFillCollisionAPI', pxr.UsdPhysics.Tokens.boundingCube: None, pxr.UsdPhysics.Tokens.boundingSphere: None, pxr.UsdPhysics.Tokens.convexDecomposition: 'PhysxConvexDecompositionCollisionAPI', pxr.UsdPhysics.Tokens.convexHull: 'PhysxConvexHullCollisionAPI', pxr.UsdPhysics.Tokens.meshSimplification: 'PhysxTriangleMeshSimplificationCollisionAPI', pxr.UsdPhysics.Tokens.none: 'PhysxTriangleMeshCollisionAPI'}#
Maps a mesh approximation token to the identifier of the PhysX collision API schema carrying that approximation’s tuning parameters. A
Nonevalue means the approximation is fully described by the token and needs no extra API. The values are schema identifier strings rather than typed classes because the PhysX schemas are codeless; apply them withovphysx.utils.codeless.apply_api().The eight entries are spelled out below, and the keys are the whole of what
ovphysx.utils.set_collider()accepts as itsapproximation_shape:"none"–"PhysxTriangleMeshCollisionAPI""convexHull"–"PhysxConvexHullCollisionAPI""convexDecomposition"–"PhysxConvexDecompositionCollisionAPI""meshSimplification"–"PhysxTriangleMeshSimplificationCollisionAPI""boundingCube"–None"boundingSphere"–None"sphereFill"–"PhysxSphereFillCollisionAPI""sdf"–"PhysxSDFMeshCollisionAPI"
Spelled out because six of the eight keys are read from
UsdPhysics.Tokens, which the documentation build mocks along with the rest ofpxr, so the rendered value of this dict shows a mock placeholder in place of each of those six keys. Do not read the rendered mapping as the mapping.
- ovphysx.utils.constants.METADATA_ATTRIBUTE_NAME_LOCALSPACEVELOCITIES = 'physics:localSpaceVelocities'#
The
customDatadict key that makes the runtime read a rigid body’s authored velocities in the body frame instead of world space.
- ovphysx.utils.constants.SCENE_UPDATE_TYPE_ASYNCHRONOUS = 'Asynchronous'#
the scene steps asynchronously.
- Type:
physxScene:updateTypevalue
- ovphysx.utils.constants.SCENE_UPDATE_TYPE_DISABLED = 'Disabled'#
the scene does not step.
- Type:
physxScene:updateTypevalue
- ovphysx.utils.constants.SCENE_UPDATE_TYPE_SYNCHRONOUS = 'Synchronous'#
the scene steps in the update thread.
- Type:
physxScene:updateTypevalue
- ovphysx.utils.constants.TOKEN_SDF = 'sdf'#
Mesh approximation token for a signed-distance-field collider.
- ovphysx.utils.constants.TOKEN_SPHERE_FILL = 'sphereFill'#
Mesh approximation token for a sphere-fill collider.
- ovphysx.utils.constants.TOKEN_TRIANGLE_MESH = 'triangleMesh'#
Mesh approximation token for an exact triangle mesh collider.
Constants#
- ovphysx.OP_INDEX_ALL#
Sentinel value (
0xFFFFFFFFFFFFFFFF) passed towait_op()to wait for all outstanding operations. Equivalent toOVPHYSX_OP_INDEX_ALLin the C API.