newton.CollisionPipeline#

class newton.CollisionPipeline(model, *, reduce_contacts=True, rigid_contact_max=None, max_triangle_pairs=1000000, shape_pairs_filtered=None, include_static_kinematic_pairs=True, soft_contact_max=None, soft_contact_gap=None, soft_contact_margin=None, enable_rigid_soft_full_surface_contact=False, requires_grad=None, broad_phase=None, narrow_phase=None, sdf_hydroelastic_config=None, shape_pairs_max=None, deterministic=False, contact_matching='disabled', contact_matching_pos_threshold=0.0005, contact_matching_normal_dot_threshold=0.995, contact_report=False, verify_buffers=True, contact_reduction_hashtable_size_factor=0.25, speculative_contact_gap_max=None)[source]#

Bases: object

Full-featured collision pipeline with GJK/MPR narrow phase and pluggable broad phase.

Key features:
  • GJK/MPR algorithms for convex-convex collision detection

  • Multiple broad phase options: NXN (all-pairs), SAP (sweep-and-prune), EXPLICIT (precomputed pairs)

  • Mesh-mesh collision via SDF with contact reduction

  • Optional hydroelastic contact model for compliant surfaces

For most users, construct with CollisionPipeline(model, ...).

Experimental

Differentiable rigid-contact kinematics computed by newton.eval_rigid_contact_kinematics() may change without prior notice. The narrow phase stays frozen and gradients are a tangent approximation; validate accuracy and usefulness on your workflow before relying on them in optimization loops.

__init__(model, *, reduce_contacts=True, rigid_contact_max=None, max_triangle_pairs=1000000, shape_pairs_filtered=None, include_static_kinematic_pairs=True, soft_contact_max=None, soft_contact_gap=None, soft_contact_margin=None, enable_rigid_soft_full_surface_contact=False, requires_grad=None, broad_phase=None, narrow_phase=None, sdf_hydroelastic_config=None, shape_pairs_max=None, deterministic=False, contact_matching='disabled', contact_matching_pos_threshold=0.0005, contact_matching_normal_dot_threshold=0.995, contact_report=False, verify_buffers=True, contact_reduction_hashtable_size_factor=0.25, speculative_contact_gap_max=None)#

Initialize the CollisionPipeline (expert API).

Parameters:
  • model (Model) – The simulation model.

  • reduce_contacts (bool) – Whether to reduce contacts for mesh-mesh collisions. Defaults to True.

  • rigid_contact_max (int | None) – Maximum number of rigid contacts to allocate. Resolution order: - If provided, use this value. - Else if model.rigid_contact_max > 0, use the model value. - Else estimate automatically from model shape and pair metadata. The automatic estimate is a conservative heuristic that generally grows linearly with replicated worlds, but it is not a guaranteed worst-case bound. A warning reports automatic estimates whose base rigid-contact buffers require at least 256 MiB. Pass an explicit value to select the memory budget and silence the warning.

  • max_triangle_pairs (int) – Maximum number of triangle pairs allocated by narrow phase for mesh and heightfield collisions. Increase this when scenes with large/complex meshes or heightfields report triangle-pair overflow warnings.

  • contact_reduction_hashtable_size_factor (float) – Multiplier applied to max_triangle_pairs when allocating the global contact reduction hashtable. Increase this if hashtable fill/failure warnings appear. Defaults to 0.25 for memory compatibility.

  • soft_contact_max (int | None) – Maximum number of soft contacts to allocate. If None, defaults to soft_contact_pair_count, the number of precomputed soft-rigid (particle-shape) pairs launched for soft contact generation, plus the full-surface edge/face headroom when enable_rigid_soft_full_surface_contact is set.

  • soft_contact_gap (float | None) – Detection-only distance [m] added to the per-particle radius for particle-shape (soft) contact queries. Defaults to 0.01.

  • soft_contact_margin (float | None) – Deprecated alias of soft_contact_gap (the value is detection-only slack on top of the particle radius, i.e. a gap under the margin/gap convention).

  • enable_rigid_soft_full_surface_contact (bool) – Generate soft contacts over the full soft-mesh surface – the edges and triangle interiors – against rigid SDFs, in addition to the per-vertex (particle) contacts. Catches rigid features that pass between soft vertices (e.g. a thin box edge through a coarse cloth cell), which the per-particle path misses. Requires an SDF on every participating rigid mesh/convex shape (provision via ModelBuilder.ShapeConfig.configure_sdf(), e.g. configure_sdf(force_sdf=True) on the builder’s default_shape_cfg), and is consumed only by SolverVBD; other solvers raise on such contacts. Records are emitted into Contacts.soft_contact_indices. Defaults to False. Fixed at construction because it sizes the soft-contact buffer headroom.

  • requires_grad (bool | None) – Whether pipeline-generated soft contacts and the deprecated automatic rigid-contact outputs require gradients. If None, uses model.requires_grad. Explicit calls to newton.eval_rigid_contact_kinematics() do not depend on this flag.

  • broad_phase (Literal['nxn', 'sap', 'explicit'] | ~newton._src.geometry.broad_phase_nxn.BroadPhaseAllPairs | ~newton._src.geometry.broad_phase_sap.BroadPhaseSAP | ~newton._src.geometry.broad_phase_nxn.BroadPhaseExplicit | None) – Either a broad phase mode string (“explicit”, “nxn”, “sap”) or a prebuilt broad phase instance for expert usage.

  • narrow_phase (NarrowPhase | None) – Optional prebuilt narrow phase instance. Must be provided together with a broad phase instance for expert usage.

  • shape_pairs_filtered (wp.array[wp.vec2i] | None) – Precomputed shape pairs for EXPLICIT mode. When broad_phase is “explicit”, uses model.shape_contact_pairs if not provided. For “nxn”/”sap” modes, ignored. The pair count and shape-type routing are used to size and specialize internal buffers at construction, so do not modify or resize the array while the pipeline is in use. Rebuild the pipeline after changing the pairs.

  • include_static_kinematic_pairs (bool) – Whether to generate contacts for static-kinematic and kinematic-kinematic pairs. Set to False to filter those pairs. Static-static pairs are always filtered. Defaults to True for backward compatibility.

  • sdf_hydroelastic_config (Config | None) – Configuration for hydroelastic collision handling. Defaults to None.

  • shape_pairs_max (int | None) – Override for the broad-phase candidate-pair buffer capacity used by the "nxn" and "sap" modes. Defaults to the worst-case N*(N-1)/2 per-world bound, which is rarely hit by either "nxn" or "sap" in practice – "nxn" still applies AABB overlap, group, and excluded-pair filtering inside BroadPhaseAllPairs before writing, and "sap" is sparse by design – so the default sizing is typically 10-100x larger than what gets emitted on real scenes. Set this to a tighter value (e.g. measured peak with ~25% headroom) to avoid multi-GB allocations on large scenes; a too-small value triggers a buffer overflow warning at runtime. Ignored for the "explicit" mode (which uses the filtered pair list length directly) and for expert paths that pass a pre-built narrow_phase.

  • deterministic (bool) – Sort contacts after the narrow phase so that results are independent of GPU thread scheduling. This also enables deterministic hydroelastic accumulation and contact allocation. Adds a radix sort + gather pass.

  • contact_matching (Literal['disabled', 'latest', 'sticky']) –

    Frame-to-frame contact matching mode. One of "disabled", "latest", or "sticky". Any non-disabled mode implies deterministic=True and populates Contacts.rigid_contact_match_index. Defaults to "disabled".

    Experimental

    The "sticky" mode may change without prior notice.

  • contact_matching_pos_threshold (float) – World-space distance threshold [m] between the previous and current contact midpoints 0.5 * (world(point0) + world(point1)). Contacts whose midpoint moves more than this are considered broken. Defaults to 0.0005.

  • contact_matching_normal_dot_threshold (float) – Minimum dot product between old and new contact normals for a match.

  • contact_report (bool) – Allocate rigid_contact_new_indices / rigid_contact_new_count / rigid_contact_broken_indices / rigid_contact_broken_count on the Contacts container, populated each frame. Requires a non-disabled contact_matching mode.

  • verify_buffers (bool) – Run a dim=[1] diagnostic kernel at the end of the narrow phase that prints warnings on any intermediate candidate-pair or final rigid contact buffer overflow; see NarrowPhase for the full counter list. Defaults to True. Overhead is one extra kernel launch per collision pass; disable in hot loops or CUDA graph capture once buffer sizes are known to be adequate.

  • speculative_contact_gap_max (float | None) – Cap on the velocity-derived rigid-contact detection gap [m]. The effective gap is the larger of the authored gap and the capped velocity-derived gap. Must be a non-negative finite number or None. None disables speculative contacts; 0.0 enables them without enlarging authored gaps. Defaults to None. See Speculative contacts.

Experimental

Rigid-contact autodiff via newton.eval_rigid_contact_kinematics() may change without prior notice; see collide().

collide(state, contacts, *, soft_contact_margin=None, soft_self_contact=False, dt=None)#

Run the collision pipeline using NarrowPhase.

Safe to call inside a wp.Tape context. The non-differentiable broad-phase and narrow-phase kernels are launched with tape recording hardcoded record_tape=False internally. The differentiable kernels (soft-contact generation and rigid-contact augmentation) are recorded on the tape so that gradients flow through state.body_q and state.particle_q.

For backward compatibility, when requires_grad=True the deprecated contacts.rigid_contact_diff_* arrays are populated by a lightweight augmentation kernel. New code should call newton.eval_rigid_contact_kinematics() explicitly after collision detection to reconstruct only the quantities it needs.

Experimental

This rigid-contact gradient path may change without prior notice. Usefulness and numerical behaviour are still being assessed across real-world scenarios.

Parameters:
  • state (newton.State) – The current simulation state.

  • contacts (Contacts) – The contacts buffer to populate (will be cleared first).

  • soft_contact_margin (float | None) – Deprecated; set soft_contact_gap on the CollisionPipeline constructor instead. When not None, the value is still honored for this call and a DeprecationWarning is emitted.

  • soft_self_contact (bool) – Also run soft (cloth) self-contact detection into contacts.soft_self_contact_data. Requires init_soft_self_contact() to have been called. The self-contact BVHs are refitted to state.particle_q before detection. Use refit_soft_self_contact_bvh() directly when an explicit full rebuild is needed.

  • dt (float | None) – Collision-update horizon [s]. Required when speculative contacts are enabled. 0.0 disables velocity adaptation for this call. Ignored when speculative contacts are disabled. See Speculative contacts.

contacts()#

Allocate and return a new newton.Contacts object for this pipeline.

The returned buffer uses this pipeline’s requires_grad flag (resolved at construction from the argument or model.requires_grad).

Returns:

A newly allocated contacts buffer sized for this pipeline.

Return type:

Contacts

Experimental

If requires_grad is true, deprecated rigid-contact distance and point compatibility arrays are allocated. New code should allocate only the outputs it needs and pass them to newton.eval_rigid_contact_kinematics().

init_soft_self_contact(*, margin=0.2, gap=0.0, rest_shape_exclusion_radius=0.0, vertex_buffer_pre_alloc=32, edge_buffer_pre_alloc=64, edge_edge_parallel_epsilon=1e-5, record_triangle_contacting_vertices=False, topological_filter_threshold=2, external_vertex_filter_map=None, external_edge_filter_map=None)#

Configure soft (cloth) self-contact detection on this pipeline.

After configuration, contacts() allocates the self-contact result buffers (Contacts.soft_self_contact_data) on every returned buffer, and collide() runs vertex-triangle and edge-edge detection into them when called with soft_self_contact=True.

This is the configuration entry point for standalone pipeline use; a solver that owns the pipeline calls this internally, seeded from its own self-contact parameters.

Parameters:
  • margin (float) – Self-contact interaction distance [m] (surface offset at which force terms begin to act), consumed by solver force terms.

  • gap (float) – Additional detection-only distance [m]; detection queries use margin + gap, mirroring the ShapeConfig.margin / ShapeConfig.gap convention.

  • rest_shape_exclusion_radius (float) – Pairs closer than this distance [m] in the rest shape (model.particle_q) are excluded from detection — for meshes whose regions are close by design (layered cloth, seams). 0 disables the filter.

  • vertex_buffer_pre_alloc (int) – Per-vertex collision buffer capacity; pairs beyond it are silently dropped during detection.

  • edge_buffer_pre_alloc (int) – Per-edge collision buffer capacity; pairs beyond it are silently dropped during detection.

  • edge_edge_parallel_epsilon (float) – Near-parallel edge-pair threshold.

  • record_triangle_contacting_vertices (bool) – Also record per-triangle contacting vertices.

  • topological_filter_threshold (int) – Ring distance under which candidate pairs are filtered out.

  • external_vertex_filter_map (dict | None) – Extra vertex-triangle exclusions.

  • external_edge_filter_map (dict | None) – Extra edge-edge exclusions.

refit_soft_self_contact_bvh(new_pos, *, rebuild=False)#

Refit (or fully rebuild) the soft self-contact BVHs to new_pos.

collide() automatically refits before self-contact detection. Call this method directly to update the trees without detecting, or pass rebuild=True to rebuild them from scratch when repeated refitting has degraded their quality under large deformation.

Parameters:
  • new_pos (wp.array[wp.vec3f]) – Particle positions [m] to fit the BVHs to, e.g. state.particle_q.

  • rebuild (bool) – Rebuild the trees instead of refitting them.

reset_contact_matching(world_mask=None)#

Clear all or reset-selected previous-frame contact history.

Masked selections accumulate until the next collide() call consumes them.

Experimental

Experimental feature. API, behavior, defaults, and supported use cases may change without prior notice.

Parameters:

world_mask (wp.array[wp.bool] | None) – Optional one-dimensional Warp boolean mask on the model device with shape (model.world_count + 1,). The final entry selects global entities whose world index is -1. If None, clear all previous-frame contact history immediately.

set_collision_detection_range(*, soft_contact_gap=None, soft_self_contact_margin=None, soft_self_contact_gap=None)#

Update the detection ranges consumed by collide().

Only the values provided are changed; None keeps the current setting, and changes take effect at the next collide() call. Rigid (shape-shape) ranges are per-shape model data (Model.shape_margin, Model.shape_gap) and are not covered here. A solver that owns the pipeline drives self-contact detection from its own parameters, so this setter affects standalone collide() use.

Parameters:
  • soft_contact_gap (float | None) – Detection-only distance [m] added to the per-particle radius for particle-shape contact queries.

  • soft_self_contact_margin (float | None) – Self-contact interaction distance [m]; requires init_soft_self_contact() to have been called.

  • soft_self_contact_gap (float | None) – Additional detection-only self-contact distance [m] (queries use margin + gap); requires init_soft_self_contact() to have been called.

property rigid_contact_max: int#

Maximum rigid contact buffer capacity used by this pipeline.

property soft_contact_margin: float#

Deprecated alias of soft_contact_gap.

property soft_contact_max: int#

Maximum soft contact buffer capacity used by this pipeline.

property soft_contact_pair_count: int#

Number of precomputed (particle, shape) pairs launched for soft contacts.

This is the base of the default soft_contact_max, which additionally reserves edge/face headroom when enable_rigid_soft_full_surface_contact is set.

property soft_rigid_contact_pair_count: int#

Deprecated alias of soft_contact_pair_count.