newton.solvers.experimental.coupled#

Experimental coupled-solver framework.

Experimental

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

Classes

class newton.solvers.experimental.coupled.CouplingInterface[source]#

Marker mixin for solvers that participate in coupled simulations.

Experimental

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

Inheriting buys into the coupling contract:

  • Override hook methods on the solver class to provide custom behavior. Otherwise, the mixin’s generic defaults are used.

  • Override a hook and raise NotImplementedError when no generic default can produce a meaningful result for the solver.

EndpointKind stays nested because it is coupling-specific. Input update notifications reuse newton.StateFlags.

class EndpointKind(*values)#

Kinds of model endpoints addressed by coupling hooks.

BODY = 0#
PARTICLE = 1#
coupling_eval_effective_mass(endpoint_kind, endpoint_index, endpoint_local_pos, out)#

Evaluate scalar effective masses for coupling endpoints.

Parameters:
  • endpoint_kind (wp.array(dtype=wp.int32, ndim=1)) – Endpoint kinds.

  • endpoint_index (wp.array(dtype=wp.int32, ndim=1)) – Endpoint-local body or particle ids.

  • endpoint_local_pos (wp.array(dtype=wp.vec3f, ndim=1)) – Body-frame endpoint positions [m].

  • out (wp.array(dtype=wp.float32, ndim=1)) – Output effective masses [kg].

coupling_eval_effective_mass_block(endpoint_kind, endpoint_index, endpoint_local_pos, out_mass, out_inertia=None)#

Evaluate effective mass and inertia blocks for coupling endpoints.

Parameters:
  • endpoint_kind (wp.array(dtype=wp.int32, ndim=1)) – Endpoint kinds.

  • endpoint_index (wp.array(dtype=wp.int32, ndim=1)) – Endpoint-local body or particle ids.

  • endpoint_local_pos (wp.array(dtype=wp.vec3f, ndim=1)) – Body-frame endpoint positions [m].

  • out_mass (wp.array(dtype=wp.float32, ndim=1)) – Output effective masses [kg].

  • out_inertia (wp.array(dtype=wp.mat33f, ndim=1) | None) – Optional output body inertia tensors [kg m^2]. Body effective inertia must not be smaller than modeled inertia around any axis.

coupling_eval_gravity_acceleration(out_body_acceleration, out_particle_acceleration)#

Evaluate solver-applied gravity-like acceleration for all local entities.

The coupled solvers cache these arrays at initialization and refresh them on relevant model changes. Solvers that apply scaled or compensated gravity should override this hook so proxy and ADMM coupling can remove exactly the acceleration the sub-solver will apply internally.

Parameters:
  • out_body_acceleration (wp.array(dtype=wp.vec3f, ndim=1) | None) – Optional output per local body [m/s^2].

  • out_particle_acceleration (wp.array(dtype=wp.vec3f, ndim=1) | None) – Optional output per local particle [m/s^2].

coupling_harvest_proxy_particle_forces(particle_local_to_proxy_global, out_particle_f, *, particle_qd_before, state, state_out, contacts, dt)#

Accumulate proxy-particle feedback from destination momentum change.

coupling_harvest_proxy_wrenches(body_local_to_proxy_global, out_body_f, *, body_qd_before, state, state_out, contacts, dt)#

Accumulate proxy-body feedback from destination momentum change.

coupling_notify_input_state_update(state, flags, *, iteration_restart=False, dt=0.0)#

React to coupler-produced public input updates.

flags uses StateFlags bits for both kinematic state arrays and public force-input buffers.

coupling_prepare_proxy_contacts(state, contacts, *, contacts_freshly_detected=False)#

Prepare contacts for a proxy destination solve.

The generic momentum harvest treats proxy feedback as a destination momentum change. Proxy-static and proxy-proxy rigid contacts therefore must not be passed through as solver contacts because they would feed constraints between virtual objects back to the source.

coupling_rewind_proxy_body(body_local_to_proxy_global, state, coupling_forces, body_gravity_acceleration, dt)#

Rewind lagged proxy-body feedback, gravity acceleration and external forces before the destination solve, so those are not double-counted.

Implementations may update either state.body_qd or state.body_f.

coupling_rewind_proxy_particle(particle_local_to_proxy_global, state, coupling_forces, particle_gravity_acceleration, dt)#

Rewind lagged proxy-body feedback, gravity acceleration and external forces before the destination solve, so those are not double-counted.

Implementations may update either state.particle_qd or state.particle_f.

coupling_supports_inertial_property_refresh()#

Return whether inertial property refresh is safe during graph capture.

Solvers that read mass and inertia arrays directly, or can refresh their derived inertial buffers with device work only, should override this to return True and provide a graph-capturable implementation of notify_model_changed() for BODY_INERTIAL_PROPERTIES.

class newton.solvers.experimental.coupled.ModelView(parent, name)[source]#

A read-through view over a Model that overrides a subset of attributes.

Attribute access falls back to the parent Model for anything not explicitly overridden on this view. This allows coupled solvers to present a per-solver “model” (e.g. with zeroed masses for non-owned bodies) without duplicating the full Model.

A ModelView is intended to duck-type as a Model for the purpose of constructing solvers (SolverFoo(model=view)).

Example:

view = ModelView(model, "vbd")
view.body_inv_mass = zeroed_inv_mass  # override
view.body_count  # delegates to model.body_count
solver = SolverVBD(model=view)
__init__(parent, name)#
add_body_lumped_inertia(body_mass_lump, body_inertia_lump)#

Add diagonal lumped mass and isotropic inertia to body properties.

add_particle_lumped_mass(particle_mass_lump)#

Add diagonal lumped mass to particles on this view.

disable_body_dynamics(body_indices)#

Disable dynamics for the given body indices in this view.

Creates overridden copies of body_inv_mass and body_inv_inertia. Inverse inertial properties are zeroed, while forward mass, inertia, and body flags are left intact as metadata for solver conversion.

Parameters:

body_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of body indices to immobilize.

disable_joints(joint_indices)#

Disable the given joints in this view.

Creates view-local copies of joint_enabled and joint_type on first write. The parent model is never mutated.

Parameters:

joint_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of joint indices to disable.

disable_particles(particle_indices)#

Clear the active flag for the given particle indices in this view.

Creates a view-local copy of particle_flags on first write. The parent model is never mutated.

Parameters:

particle_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of particle indices to disable.

get_requested_state_attributes()#

Return requested state attributes using view-local counts.

mark_proxy_bodies(body_indices)#

Mark the given body indices as proxy bodies in this view.

Creates a view-local copy of body_flags on first write and ORs the PROXY bit into the selected bodies. The parent model is never mutated.

Parameters:

body_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of body indices to mark as proxies.

mark_proxy_particles(particle_indices)#

Mark the given particle indices as proxy particles in this view.

Creates a view-local copy of particle_flags on first write and ORs the PROXY bit into the selected particles. The parent model is never mutated.

Parameters:

particle_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of particle indices to mark.

scale_body_mass(body_indices, factor)#

Scale mass and inertia for the given body indices.

Multiplying mass by factor means dividing body_inv_mass and body_inv_inertia by factor, and multiplying body_mass and body_inertia by factor.

If overrides for these arrays already exist on this view they are modified in-place; otherwise fresh clones are created.

Parameters:
  • body_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of body indices to scale.

  • factor (float) – Multiplicative scale applied to mass / inertia. Values < 1 make proxy bodies lighter (softer coupling); values > 1 make them heavier.

scale_body_mass_mask(body_mask, factor)#

Scale mass and inertia for bodies whose mask entry is non-zero.

scale_particle_mass(particle_indices, factor)#

Scale mass for particles on this view by factor.

Multiplying mass by factor means dividing particle_inv_mass by factor and multiplying particle_mass by factor. Used by the ADMM coupler to inject the proximal term as a mass rescaling.

If overrides for these arrays already exist on this view they are modified in-place; otherwise fresh clones are created. The parent model is never mutated.

Parameters:
  • particle_indices (wp.array(dtype=wp.int32, ndim=1) | None) – Optional 1-D int array of particle indices to scale. When None, all particles are scaled.

  • factor (float) – Multiplicative scale applied to particle masses.

scale_particle_mass_mask(particle_mask, factor)#

Scale mass for particles whose mask entry is non-zero.

set_body_inertial_properties(body_indices, body_mass, body_inertia)#

Set mass and full inertia tensors for the given body indices.

This replaces both the scalar mass and local body-frame inertia tensor for each selected body, updating inverse mass and inverse inertia consistently.

Parameters:
  • body_indices (wp.array(dtype=wp.int32, ndim=1)) – Body ids whose inertial properties should be replaced.

  • body_mass (wp.array(dtype=wp.float32, ndim=1)) – Replacement body masses [kg], indexed like body_indices.

  • body_inertia (wp.array(dtype=wp.mat33f, ndim=1)) – Replacement body inertia tensors [kg*m^2], indexed like body_indices.

set_body_mass(body_indices, body_mass)#

Set mass for the given body indices and scale inertia consistently.

Existing body inertia tensors are scaled by the ratio between the new and current mass. This preserves the inertia shape while allowing couplers to install scalar effective masses. Bodies with non-positive current mass cannot be assigned a positive scalar mass this way because there is no finite inertia tensor to scale; use set_body_inertial_properties() for that transition.

Parameters:
  • body_indices (wp.array(dtype=wp.int32, ndim=1)) – Body ids whose mass should be replaced.

  • body_mass (wp.array(dtype=wp.float32, ndim=1)) – Replacement body masses [kg], indexed like body_indices.

set_particle_mass(particle_indices, particle_mass)#

Set mass for the given particle indices.

Parameters:
  • particle_indices (wp.array(dtype=wp.int32, ndim=1)) – Particle ids whose mass should be replaced.

  • particle_mass (wp.array(dtype=wp.float32, ndim=1)) – Replacement particle masses [kg], indexed like particle_indices.

state(requires_grad=None)#

Create a State using view-local state overrides.

This calls the normal state() implementation with this view as the model object, so allocation follows the attributes and counts visible through the view.

zero_particle_mass(particle_indices)#

Zero mass and inverse mass for the given particle indices.

Creates view-local copies of particle_mass and particle_inv_mass on first write and sets the selected particles to zero mass. The parent model is never mutated.

Parameters:

particle_indices (wp.array(dtype=wp.int32, ndim=1)) – 1-D int array of particle indices to zero.

property joint_target_q_start: array | None#

View-local start indices for joint_target_q.

property name: str#

Name of this view (e.g. "vbd", "mjc").

property overrides: dict[str, object]#

Dictionary of attribute names that are overridden on this view.

property parent: Model#

The underlying Model.

class newton.solvers.experimental.coupled.SolverCoupled(model, entries, coupling=None)[source]#

Couple multiple solvers through explicit ownership and coupling config.

SolverCoupled owns generic mechanics that can be derived from Model, ModelView and State: per-solver views, ownership masks, state distribution/reconciliation, per-entry substeps, and shared coupling hook dispatch helpers. Algorithm-specific couplers such as SolverCoupledADMM and SolverCoupledProxy derive from this base class.

Parameters:
  • model (Model) – Shared model.

  • entries (Sequence[SolverCoupled.Entry]) – Sub-solver entries with explicit ownership.

  • coupling (object | None) – Optional algorithm configuration reserved for derived couplers. The base class steps entries independently and reconciles owned state.

class Entry(name, solver, bodies=(), particles=(), joints=(), shapes=(), configure_view=None, substeps=1, in_place=False)#

Public configuration for one sub-solver.

Each entry names a solver factory, the global model ids owned by that solver, an optional ModelView customization callback, and stepping policy. The factory is called as solver(view) with the per-entry ModelView and must return a configured SolverBase. Bind any extra constructor arguments in the factory itself (e.g. lambda v: SolverVBD(model=v, iterations=10)). Entry names must be unique. In-place stepping is only valid for solvers that explicitly support it. Shape ids remain in the parent model namespace so all entries can consume shared contact buffers.

Parameters:
  • name (str) – Unique entry name used by coupling configuration.

  • solver (Callable[[ModelView], SolverBase]) – Factory called with this entry’s ModelView.

  • bodies (Sequence[int]) – Global body ids owned by this entry.

  • particles (Sequence[int]) – Global particle ids owned by this entry.

  • joints (Sequence[int]) – Global joint ids owned by this entry.

  • shapes (Sequence[int]) – Global shape ids owned by this entry.

  • configure_view (Callable[[ModelView], None] | None) – Optional callback invoked after compaction for entry-local view overrides.

  • substeps (int) – Number of substeps to run per coupled step.

  • in_place (bool) – Whether the sub-solver may step in-place.

__init__(name, solver, bodies=(), particles=(), joints=(), shapes=(), configure_view=None, substeps=1, in_place=False)#
bodies: Sequence[int] = ()#
in_place: bool = False#
joints: Sequence[int] = ()#
name: str#
particles: Sequence[int] = ()#
shapes: Sequence[int] = ()#
solver: Callable[[ModelView], SolverBase]#
substeps: int = 1#
__init__(model, entries, coupling=None)#
entry_contacts(name, contacts)#

Return contacts filtered for a coupled entry’s view, when possible.

Parameters:
  • name (str) – Coupled sub-solver entry name.

  • contacts (Contacts | None) – Parent-model contacts to filter.

Returns:

Entry-local contacts, or None when no compatible contact buffer is available.

Return type:

Contacts | None

entry_names()#

Return coupled sub-solver entry names in stepping order.

entry_output_state_valid()#

Return whether entry output states reflect the last coupled step.

entry_state(name, phase='current')#

Return an entry-local state suitable for visualization.

Parameters:
  • name (str) – Coupled sub-solver entry name.

  • phase (Literal['current', 'input', 'output']) – Which state phase to return. "input" returns the distributed input state, "output" returns the last sub-solver output state, and "current" returns output after the coupled solver has stepped at least once or input before the first step.

Returns:

Entry-local state whose arrays match view().

Return type:

newton.State

notify_model_changed(flags)#

Forward model change notifications to all sub-solvers.

prepare_contacts(contacts)#

Preallocate entry-local filtered contact buffers for graph capture.

reset(state, world_mask=None, flags=None)#

Reset coupled sub-solvers and clear coupled-solver transient state.

Parameters:
  • state (newton.State) – Parent-model simulation state to reset (modified in place).

  • world_mask (array | None) – Optional boolean mask of shape (world_count,) selecting which worlds to reset. If None, all worlds are reset.

  • flags (StateFlags | int | None) – Optional StateFlags bitmask controlling which state quantities sub-solvers should reset. If None, all state quantities are reset.

solver(name)#

Return the sub-solver registered under name.

step(state_in, state_out, control, contacts, dt)#

Step all coupled sub-solvers for one time step.

contacts is forwarded to sub-solvers that accept it; SolverCoupled itself does not maintain a global contact buffer. Coupling schemes that need a private contact pipeline (e.g. proxy collisions, ADMM internal contacts) own their own buffers internally.

sync_entry_states(state_in, dt=0.0)#

Synchronize entry input states from a parent-model state.

This is primarily useful for visualization before the first coupled step has produced entry output states.

Parameters:
  • state_in (newton.State) – Parent-model state to distribute into entry-local states.

  • dt (float) – Time step metadata forwarded to coupling input-state hooks.

view(name)#

Return the ModelView for the sub-solver name.

class newton.solvers.experimental.coupled.SolverCoupledADMM(model, entries, coupling)[source]#

Couple multiple solvers with linearized ADMM over model-derived constraints.

class Config(iterations=5, rho=1.0, gamma=0.0, baumgarte=0.0, joint_stiffness=10000.0, joint_damping=0.0, joint_angular_stiffness=10000.0, joint_angular_damping=0.0, joint_proximal_bodies=True, joint_proximal_destination_entries=None, joint_proximal_mass_scale=1.0, rigid_contact_matching='disabled', contact_matching_pos_threshold=None, contact_matching_normal_dot_threshold=None, contact_matching_force_scale=0.9, contact_pairs=())#

Linearized ADMM coupling configuration.

Parameters:
  • iterations (int) – Positive number of ADMM iterations per solver step.

  • rho (float) – Positive ADMM penalty parameter.

  • gamma (float) – Nonnegative proximal mass scaling parameter.

  • baumgarte (float) – Nonnegative position error correction fraction.

  • joint_stiffness (float) – Quadratic stiffness for translational ADMM attachments derived from cross-solver model joints [N/m].

  • joint_damping (float) – Quadratic damping for translational ADMM attachments derived from cross-solver model joints [N*s/m].

  • joint_angular_stiffness (float) – Quadratic stiffness for angular ADMM attachments derived from cross-solver fixed and revolute joints [N*m/rad].

  • joint_angular_damping (float) – Quadratic damping for angular ADMM attachments derived from cross-solver fixed and revolute joints [N*m*s/rad].

  • joint_proximal_bodies (bool) – Keep cross-solver joint neighbor bodies dynamic in each subsolver view as local inertial proxies.

  • joint_proximal_destination_entries (Sequence[str] | None) – Optional entry names that receive cross-solver joint proximal proxy bodies. None keeps the default symmetric visibility.

  • joint_proximal_mass_scale (float) – Multiplier applied to source effective masses before installing cross-solver joint proxy inertias.

  • rigid_contact_matching (Literal['disabled', 'latest', 'sticky']) – Frame-to-frame contact matching mode for collision-detected rigid-rigid ADMM contacts. Use "disabled" to reset dynamic rigid contact state every refresh, "latest" to warm start matched contacts from the previous refresh, or "sticky" to also replay matched contact geometry. Matched contacts reuse only ADMM dual warm-start state; primal contact state is reset on every refresh.

  • contact_matching_pos_threshold (float | None) – World-space distance threshold [m] between previous and current rigid contact midpoints for non-disabled rigid_contact_matching modes. None uses the CollisionPipeline default.

  • contact_matching_normal_dot_threshold (float | None) – Minimum dot product between previous and current rigid contact normals for non-disabled rigid_contact_matching modes. None uses the CollisionPipeline default.

  • contact_matching_force_scale (float) – Multiplier applied to the rescaled previous-refresh ADMM contact dual when a rigid-rigid contact matches. 0 disables dual warm-start while preserving contact matching.

  • contact_pairs (Sequence[ContactPair]) – Per-interface contact pairs to enable. Empty list disables ADMM-managed contacts. Use SolverCoupledADMM.auto_detect_contact_pairs() to build the old auto-discovery list.

__init__(iterations=5, rho=1.0, gamma=0.0, baumgarte=0.0, joint_stiffness=10000.0, joint_damping=0.0, joint_angular_stiffness=10000.0, joint_angular_damping=0.0, joint_proximal_bodies=True, joint_proximal_destination_entries=None, joint_proximal_mass_scale=1.0, rigid_contact_matching='disabled', contact_matching_pos_threshold=None, contact_matching_normal_dot_threshold=None, contact_matching_force_scale=0.9, contact_pairs=())#
baumgarte: float = 0.0#
contact_matching_force_scale: float = 0.9#
contact_pairs: Sequence[ContactPair] = ()#
gamma: float = 0.0#
iterations: int = 5#
joint_angular_damping: float = 0.0#
joint_angular_stiffness: float = 10000.0#
joint_damping: float = 0.0#
joint_proximal_bodies: bool = True#
joint_proximal_mass_scale: float = 1.0#
joint_stiffness: float = 10000.0#
rho: float = 1.0#
rigid_contact_matching: Literal['disabled', 'latest', 'sticky'] = 'disabled'#
class ContactPair(source, destination)#

One cross-solver contact interface for ADMM coupling.

A ContactPair activates ADMM contacts between two solver entries. The coupler inspects ownership for source and destination and emits the applicable subset of {rigid-rigid, rigid-particle, particle-particle} ADMM contact rows. If neither entry owns shapes or particles, no contacts are emitted.

Friction is derived from shape and particle material properties (shape_material_mu and Model.particle_mu), so it is not a ContactPair field — set those on the model to control friction.

Parameters:
  • source (str) – Name of one solver entry.

  • destination (str) – Name of the other solver entry. Must differ from source.

__init__(source, destination)#
destination: str#
source: str#
classmethod add_body_particle_attachment(builder, body, particle, *, body_point=(0.0, 0.0, 0.0), stiffness=1.0e4, damping=0.0, enabled=True)#

Add a model-level rigid-body-to-particle ADMM attachment.

Parameters:
  • builder (ModelBuilder) – Model builder that owns the body and particle.

  • body (int) – Body index for the rigid endpoint.

  • particle (int) – Particle index for the deformable endpoint.

  • body_point (tuple[float, float, float] | wp.vec3) – Body-local attachment point [m].

  • stiffness (float) – Quadratic ADMM attachment stiffness [N/m].

  • damping (float) – Quadratic ADMM attachment damping [N*s/m].

  • enabled (bool) – Whether the attachment row is active.

Returns:

The custom-frequency row index for the attachment.

Return type:

int

classmethod auto_detect_contact_pairs(entries)#

Return ContactPair entries for every cross-owner interface.

Mirrors the prior auto-detection behavior: a pair is emitted for every distinct combination of entries. Friction is read from shape_material_mu and Model.particle_mu at contact-fill time.

Parameters:

entries (Sequence[Entry]) – Sub-solver entries that will be passed to SolverCoupledADMM.

classmethod register_custom_attributes(builder)#

Register ADMM coupling custom attributes on a model builder.

The registered coupling:body_particle_attachment custom frequency stores model-level rigid-body-to-particle attachment annotations. During construction, SolverCoupledADMM converts rows whose body and particle endpoints are owned by different solver entries into ADMM attachment constraints.

Parameters:

builder (ModelBuilder) – Model builder receiving the custom frequency and attributes.

__init__(model, entries, coupling)#
notify_model_changed(flags)#
BODY_PARTICLE_ATTACHMENT_BODY_ATTR = 'coupling:body_particle_attachment_body'#
BODY_PARTICLE_ATTACHMENT_BODY_POINT_ATTR = 'coupling:body_particle_attachment_body_point'#
BODY_PARTICLE_ATTACHMENT_DAMPING_ATTR = 'coupling:body_particle_attachment_damping'#
BODY_PARTICLE_ATTACHMENT_ENABLED_ATTR = 'coupling:body_particle_attachment_enabled'#
BODY_PARTICLE_ATTACHMENT_FREQUENCY = 'coupling:body_particle_attachment'#
BODY_PARTICLE_ATTACHMENT_PARTICLE_ATTR = 'coupling:body_particle_attachment_particle'#
BODY_PARTICLE_ATTACHMENT_STIFFNESS_ATTR = 'coupling:body_particle_attachment_stiffness'#
property collision_contact_count: int#

Number of collision-detected ADMM contacts active in the last step.

property collision_contact_count_max: int#

Maximum collision-detected ADMM contact count observed so far.

class newton.solvers.experimental.coupled.SolverCoupledProxy(model, entries, coupling)[source]#

Couple two solvers with lagged-impulse virtual proxy bodies or particles.

class Config(proxies, iterations=1)#

Lagged-impulse proxy coupling configuration.

Parameters:
  • proxies (Sequence[Proxy]) – Directed proxy mappings between solver entries.

  • iterations (int) – Positive number of proxy relaxation passes per step.

__init__(proxies, iterations=1)#
iterations: int = 1#
proxies: Sequence[Proxy]#
class Proxy(source, destination, bodies=(), proxy_bodies=None, joints=(), proxy_joints=None, mass_scale=1.0, mode='lagged', proxy_relaxation=1.0, proxy_relaxation_mode='fixed', proxy_relaxation_min=0.1, proxy_relaxation_max=1.0, particles=(), proxy_particles=None, collision_pipeline=None, collide_interval=None)#

Proxy mapping for virtual-inertia coupling.

Parameters:
  • source (str) – Name of the source solver that owns bodies and/or particles.

  • destination (str) – Name of the destination solver that receives proxies.

  • bodies (Sequence[int]) – Source body ids to map into destination proxies.

  • proxy_bodies (Sequence[int] | None) – Optional destination body ids. Defaults to bodies.

  • joints (Sequence[int]) – Source joint ids to keep enabled in the destination proxy view. One-DoF drive targets are copied from the source control before the destination solve.

  • proxy_joints (Sequence[int] | None) – Optional destination joint ids. Defaults to joints.

  • mass_scale (float) – Scale factor applied to source effective body mass/inertia and particle mass when assigning destination proxy properties. This does not modify the source modeled free-body mass/inertia or particle mass. Must be finite and positive.

  • mode (str) – Proxy transfer mode, "lagged" or "staggered". "lagged" syncs source begin poses and end velocities, then prepares proxies to avoid double-counting lagged feedback. "staggered" syncs source end poses and end velocities directly.

  • proxy_relaxation (float) – Nonnegative relaxation factor used when updating lagged proxy feedback after the destination solve: proxy_relaxation * coupling_forces_new + (1 - proxy_relaxation) * coupling_forces_old. Values below 1 underrelax the update, 1 keeps the harvested force unchanged, and values above 1 overrelax it.

  • proxy_relaxation_mode (str) – Feedback relaxation mode. "fixed" uses proxy_relaxation directly. "aitken" updates it from consecutive feedback residuals within one solver step.

  • proxy_relaxation_min (float) – Minimum Aitken relaxation factor.

  • proxy_relaxation_max (float) – Maximum Aitken relaxation factor.

  • particles (Sequence[int]) – Source particle ids to map into destination proxies.

  • proxy_particles (Sequence[int] | None) – Optional destination particle ids. Defaults to particles.

  • collision_pipeline (Callable[[ModelView], object | None] | None) – Optional factory called as collision_pipeline(destination_model_view). When supplied, SolverCoupledProxy uses the returned pipeline to detect destination proxy contacts before each destination solve. If the factory returns None, the destination solve receives the outer-level contacts passed to step().

  • collide_interval (int | None) – Collision-detection refresh interval for collision_pipeline. None means every proxy pass when a custom pipeline is supplied. Explicit values must be positive integers.

__init__(source, destination, bodies=(), proxy_bodies=None, joints=(), proxy_joints=None, mass_scale=1.0, mode='lagged', proxy_relaxation=1.0, proxy_relaxation_mode='fixed', proxy_relaxation_min=0.1, proxy_relaxation_max=1.0, particles=(), proxy_particles=None, collision_pipeline=None, collide_interval=None)#
bodies: Sequence[int] = ()#
destination: str#
joints: Sequence[int] = ()#
mass_scale: float = 1.0#
mode: str = 'lagged'#
particles: Sequence[int] = ()#
proxy_relaxation: float = 1.0#
proxy_relaxation_max: float = 1.0#
proxy_relaxation_min: float = 0.1#
proxy_relaxation_mode: str = 'fixed'#
source: str#
__init__(model, entries, coupling)#
get_proxy_collision_state()#

Return host-side proxy collision cadence state for later restore.

get_proxy_contacts(source, destination)#

Return the internally detected contacts for one proxy direction.

notify_model_changed(flags)#

Refresh proxy inertia after source solvers consume model updates.

restore_proxy_collision_state(state)#

Restore host-side proxy collision cadence state.