newton.solvers.SolverVBD#
- class newton.solvers.SolverVBD(model, *, iterations=10, friction_epsilon=1e-2, integrate_with_external_rigid_solver=False, particle_enable_self_contact=False, particle_self_contact_radius=0.2, particle_self_contact_margin=0.2, particle_conservative_bound_relaxation=0.85, particle_vertex_contact_buffer_size=32, particle_edge_contact_buffer_size=64, particle_collision_detection_interval=0, particle_edge_parallel_epsilon=1e-5, particle_enable_tile_solve=True, particle_topological_contact_filter_threshold=2, particle_rest_shape_contact_exclusion_radius=0.0, particle_external_vertex_contact_filtering_map=None, particle_external_edge_contact_filtering_map=None, rigid_compliant_alm=None, rigid_avbd_alpha=None, rigid_avbd_joint_alpha=None, rigid_avbd_contact_alpha=None, rigid_avbd_beta=0.0, rigid_avbd_linear_beta=None, rigid_avbd_angular_beta=None, rigid_avbd_gamma=0.999, rigid_contact_hard=True, rigid_contact_history=False, rigid_contact_stick_motion_eps=None, rigid_contact_stick_freeze_translation_eps=None, rigid_contact_stick_freeze_angular_eps=None, rigid_contact_k_start=1.0e2, rigid_body_contact_buffer_size=64, rigid_body_particle_contact_buffer_size=256, rigid_joint_linear_ke=1.0e5, rigid_joint_angular_ke=1.0e5, rigid_joint_linear_k_start=1.0e2, rigid_joint_angular_k_start=1.0e1, rigid_joint_linear_kd=0.0, rigid_joint_angular_kd=0.0, deterministic=None)[source]#
Bases:
SolverBase,CouplingInterfaceAn implicit solver using Vertex Block Descent (VBD) for particles and Augmented VBD (AVBD) for rigid bodies.
Experimental
SolverVBD’s public API and behavior may change without prior notice.
- This unified solver supports:
Particle simulation (cloth, soft bodies) using the VBD algorithm
Rigid body simulation (joints, contacts) using the AVBD algorithm
Coupled particle-rigid body systems
For rigid bodies, two paths are supported:
Compliant ALM (
rigid_compliant_alm=True, recommended): one finite-material formulation for structural joints, drives, limits, and body-body contacts. Authored finite stiffness controls physical compliance, whileSolverVBDselects an internal ALM metricrhofor numerical conditioning. For a material row, they combine ask_eff = k*rho/(k+rho), and a multiplierlambdacarries accumulated reaction. The per-slot joint hard/soft API (authored viamodel.vbd.joint_is_hardorset_joint_constraint_mode()) is deprecated.rigid_contact_hardis a separate legacy-contact control and has no formulation effect under compliant ALM. Both distinctions will be removed with the legacy path.Legacy AVBD (
rigid_compliant_alm=False, deprecated): penalty stiffness that is fixed by default (rigid_avbd_beta=0) or ramped per iteration fromk_startseeds, where non-cable joint slots default to hard mode (augmented Lagrangian with persistent lambda and C0 stabilization) and cable stretch, shear, bend, and twist default to soft (penalty-based). Deprecated as of Newton 1.6 and will be removed in a future release; omittingrigid_compliant_almis deprecated because the default will change toTrue.
- Joint limitations:
Supported joint types: BALL, FIXED, FREE, REVOLUTE, PRISMATIC, D6, CABLE. DISTANCE joints are not supported.
joint_enabledis supported for all joint types and is read live. After changing enable flags, callnotify_model_changed()withJOINT_PROPERTIESto refresh derived contact conditioning. Structural-slot material, constraint layout, and rest-angle offsets are captured at construction; rebuildSolverVBDafter changing them.joint_target_ke/joint_target_kdare supported for REVOLUTE, PRISMATIC, D6 (as drives), and CABLE (as stretch, shear, bend, and twist stiffness and damping). VBD interpretskdas absolute damping in physical units.joint_limit_lower/joint_limit_upperandjoint_limit_ke/joint_limit_kdare supported for REVOLUTE, PRISMATIC, and D6 joints.joint_f(feedforward forces) is supported.Not supported:
joint_armature,joint_friction,joint_effort_limit,joint_velocity_limit,joint_target_mode, equality constraints, mimic constraints.
See Joint Feature Support for the full comparison across solvers.
- Buffer sizing:
Body-body contact state is pre-allocated from
model.rigid_contact_maxwhen aCollisionPipelinehas already published it and this solver owns the rigid system. Body-particle contact state is pre-sized from a world-aware particle-shape pair count, which excludes theenable_rigid_soft_full_surface_contactedge/face headroom. Both grow fromContactson the firststep(), and the rigid contact force outputs grow incollect_rigid_contact_forces(). During graph capture, ordinary lazy resizing is supported on CPU and on CUDA with Warp’s stream-ordered memory pool enabled; otherwise the solver raises with guidance to pre-size before capture. Rigid contact history is cross-replay-persistent state, so it must always be allocated before capture regardless of the device’s allocation-during-capture support – allocating it inside a graph records a wp.zeros fill that wipes the warm-start buffers on every replay. Withrigid_contact_history=True, constructCollisionPipelinebeforeSolverVBD, or run one uncaptured solver step before capture.
References
Anka He Chen, Ziheng Liu, Yin Yang, and Cem Yuksel. 2024. Vertex Block Descent. ACM Trans. Graph. 43, 4, Article 116 (July 2024), 16 pages. https://doi.org/10.1145/3658179
Chris Giles, Elie Diaz, and Cem Yuksel. 2025. Augmented Vertex Block Descent. ACM Trans. Graph. 44, 4, Article 90 (August 2025), 12 pages. https://doi.org/10.1145/3731195
Note
SolverVBD requires coloring for each system it solves:
Particle coloring:
newton.Model.particle_color_groups(required if particles are present)Rigid body coloring:
newton.Model.body_color_groups(required if rigid bodies are integrated by VBD)
Call
newton.ModelBuilder.color()to automatically color both particles and rigid bodies.VBD uses
model.body_qas the structural rest pose and readsmodel.joint_qfor drive/limit rest-angle offsets. The body transforms must match the joint angles at solver creation time (see example below).For CUDA graph capture, the recommended construction order is
CollisionPipeline->Contacts->SolverVBD, all before capture.Example
# Automatically color both particles and rigid bodies builder.color() model = builder.finalize() collision_pipeline = newton.CollisionPipeline(model) contacts = collision_pipeline.contacts() solver = newton.solvers.SolverVBD( model, rigid_compliant_alm=True, ) # Initialize states and control state_in = model.state() state_out = model.state() control = model.control() # Simulation loop for i in range(100): collision_pipeline.collide(state_in, contacts) solver.step(state_in, state_out, control, contacts, dt) state_in, state_out = state_out, state_in
- class JointSlot#
Bases:
objectNamed constraint slot indices for
set_joint_constraint_mode().- Structural constraint slots by joint type:
CABLE: STRETCH=0, SHEAR=1, BEND=2, TWIST=3
BALL: LINEAR=0 only
FIXED/REVOLUTE/PRISMATIC/D6: LINEAR=0, ANGULAR=1
STRETCH/SHEAR/BEND/TWIST are cable-only names for the SolverVBD cable layout emitted by the builder cable APIs. Only structural slots are named here; per-DOF drive/limit slots (slot 2+ on non-cable joints) are not.
- ANGULAR = 1#
- BEND = 2#
- LINEAR = 0#
- SHEAR = 1#
- STRETCH = 0#
- TWIST = 3#
- classmethod register_custom_attributes(builder, *, dahl_defaults_enabled=False)#
Register SolverVBD custom Model attributes.
- Currently registers:
vbd:joint_is_hardfor per-joint hard/soft constraint mode (non-cable joints)vbd:dahl_eps_maxandvbd:dahl_taufor optional cable angular Dahl friction
Attributes are declared in the
vbdnamespace so they can be authored in scenes and in USD asnewton:vbd:<attr>.Dahl cable friction is enabled per joint only where both
model.vbd.dahl_eps_maxandmodel.vbd.dahl_tauare authored positive; the attributes default to zero.- Parameters:
builder (ModelBuilder) – Model builder to register attributes on.
dahl_defaults_enabled (bool) –
Deprecated compatibility mode. When True, Dahl parameters default to positive values instead of zero.
Deprecated since version 1.5: The compatibility mode will be removed; author positive Dahl values explicitly when Dahl cable friction is desired.
- __init__(model, *, iterations=10, friction_epsilon=1e-2, integrate_with_external_rigid_solver=False, particle_enable_self_contact=False, particle_self_contact_radius=0.2, particle_self_contact_margin=0.2, particle_conservative_bound_relaxation=0.85, particle_vertex_contact_buffer_size=32, particle_edge_contact_buffer_size=64, particle_collision_detection_interval=0, particle_edge_parallel_epsilon=1e-5, particle_enable_tile_solve=True, particle_topological_contact_filter_threshold=2, particle_rest_shape_contact_exclusion_radius=0.0, particle_external_vertex_contact_filtering_map=None, particle_external_edge_contact_filtering_map=None, rigid_compliant_alm=None, rigid_avbd_alpha=None, rigid_avbd_joint_alpha=None, rigid_avbd_contact_alpha=None, rigid_avbd_beta=0.0, rigid_avbd_linear_beta=None, rigid_avbd_angular_beta=None, rigid_avbd_gamma=0.999, rigid_contact_hard=True, rigid_contact_history=False, rigid_contact_stick_motion_eps=None, rigid_contact_stick_freeze_translation_eps=None, rigid_contact_stick_freeze_angular_eps=None, rigid_contact_k_start=1.0e2, rigid_body_contact_buffer_size=64, rigid_body_particle_contact_buffer_size=256, rigid_joint_linear_ke=1.0e5, rigid_joint_angular_ke=1.0e5, rigid_joint_linear_k_start=1.0e2, rigid_joint_angular_k_start=1.0e1, rigid_joint_linear_kd=0.0, rigid_joint_angular_kd=0.0, deterministic=None)#
- Parameters:
model (Model) – The Model object used to initialize the integrator. Must be identical to the Model object passed to the step function.
parameters (Rigid body)
iterations (int) – Number of VBD iterations per step.
friction_epsilon (float) – Threshold to smooth small relative velocities in friction computation (used for both particle and rigid body contacts).
integrate_with_external_rigid_solver (bool) – Indicator for coupled rigid body-cloth simulation. When set to True, the solver assumes rigid bodies are integrated by an external solver (one-way coupling).
parameters
particle_enable_self_contact (bool) – Whether to enable self-contact detection for particles.
particle_self_contact_radius (float) – The radius used for self-contact detection. This is the distance at which vertex-triangle pairs and edge-edge pairs will start to interact with each other.
particle_self_contact_margin (float) – The margin used for self-contact detection. This is the distance at which vertex-triangle pairs and edge-edge will be considered in contact generation. It should be larger than particle_self_contact_radius to avoid missing contacts.
particle_conservative_bound_relaxation (float) – Relaxation factor for conservative penetration-free projection.
particle_vertex_contact_buffer_size (int) – Preallocation size for each vertex’s vertex-triangle collision buffer.
particle_edge_contact_buffer_size (int) – Preallocation size for edge’s edge-edge collision buffer.
particle_collision_detection_interval (int) – Controls how frequently particle self-contact detection is applied during the simulation. If set to a value < 0, collision detection is only performed once before the initialization step. If set to 0, collision detection is applied twice: once before and once immediately after initialization. If set to a value n >= 1, collision detection is applied before every n VBD iterations.
particle_edge_parallel_epsilon (float) – Threshold to detect near-parallel edges in edge-edge collision handling.
particle_enable_tile_solve (bool) – Whether to accelerate the particle solver using tile API.
particle_topological_contact_filter_threshold (int) – Maximum topological distance (measured in rings) under which candidate self-contacts are discarded. Set to a higher value to tolerate contacts between more closely connected mesh elements. Only used when particle_enable_self_contact is True. Note that setting this to a value larger than 3 will result in a significant increase in computation time.
particle_rest_shape_contact_exclusion_radius (float) – Additional world-space distance threshold for filtering topologically close primitives. Candidate contacts with a rest separation shorter than this value are ignored. The distance is evaluated in the rest configuration conveyed by model.particle_q. Only used when particle_enable_self_contact is True.
particle_external_vertex_contact_filtering_map (dict | None) – Optional dictionary used to exclude additional vertex-triangle pairs during contact generation. Keys must be vertex primitive ids (integers), and each value must be a list or set containing the triangle primitives to be filtered out. Only used when particle_enable_self_contact is True.
particle_external_edge_contact_filtering_map (dict | None) – Optional dictionary used to exclude additional edge-edge pairs during contact generation. Keys must be edge primitive ids (integers), and each value must be a list or set containing the edges to be filtered out. Only used when particle_enable_self_contact is True.
parameters
rigid_compliant_alm (bool | None) – Unified compliant-ALM mode for body-body contacts, structural joints, drives, and limits. This is the recommended path. Defaults to
None, which currently selects the legacy path. WhenSolverVBDintegrates rigid bodies, omitting this argument emits aDeprecationWarningbecause the default will change toTrue(deprecated as of Newton 1.6; the legacy path will be removed in a future release). PassTrueto adopt compliant ALM now, orFalseto keep the legacy path during the migration window. Finite authored coefficients define the material response, whileSolverVBDselectsrhointernally for numerical conditioning. Values used with legacy hard constraints may require retuning for the desired deformation. Values must be finite and representable in float32; infinity is unsupported.rigid_avbd_alpha (float | None) – C0 stabilization strength (
C_stab = C - alpha * C0). Range: [0, 1]. Controls both joints and body-body contacts when neither class-specific override (rigid_avbd_joint_alpha/rigid_avbd_contact_alpha) is set.Noneleaves mode defaults: compliant ALM uses0.0for both constraint classes (the raw material residual), while the legacy path uses0.95.rigid_avbd_joint_alpha (float | None) – Joint-specific alpha override.
Nonefalls back torigid_avbd_alphawhen set, otherwise to0.0under compliant ALM or0.95on the legacy path.rigid_avbd_contact_alpha (float | None) – Body-body contact alpha override.
Nonefalls back torigid_avbd_alphawhen set, otherwise0.0under compliant ALM (authored contact stiffness applies to the raw residual) or0.95on the legacy path. Under compliant ALM, alpha is stabilization only; retention is set separately byrigid_avbd_gamma.rigid_avbd_beta (float) –
Legacy AVBD penalty ramp rate per iteration.
0(default) disables ramping (fixed-k). Set to e.g.1e5for ramping. Used for both linear and angular constraints unless overridden. Does not tune the internal compliant-ALMrhofor converted rigid rows. Note: linear (meters) and angular (radians) constraints have different units, so the overrides should be used for production tuning.Deprecated since version 1.6: Penalty ramping is deprecated for all uses. Body-particle contacts continue to honor this control during migration; keep the effective beta at
0(the default behavior) and author fixed material stiffness instead.rigid_avbd_linear_beta (float | None) –
Legacy linear beta override for linear constraints (meters).
None(default) usesrigid_avbd_beta. Does not tune compliant-ALMrho.Deprecated since version 1.6: Penalty ramping is deprecated for all uses. Body-particle contacts continue to honor this control during migration; keep the effective beta at
0(the default behavior) and author fixed material stiffness instead.rigid_avbd_angular_beta (float | None) –
Legacy angular beta override for angular constraints (radians).
None(default) usesrigid_avbd_beta. Does not tune compliant-ALMrho.Deprecated since version 1.6: Penalty ramping is deprecated. Keep the effective beta at
0(the default behavior) and author fixed material stiffness instead.rigid_avbd_gamma (float) – Per-step decay factor for penalty k and persisted lambda. Compliant ALM joints and validated contacts retain lambda by
gamma; the legacy path retains lambda byalpha * gamma. Lower values discard history faster.rigid_contact_hard (bool) –
Legacy body-body contact hard/soft mode. With
rigid_compliant_alm=True, contacts use the ALM path. Withrigid_compliant_alm=False,Trueselects legacy hard AVBD contact andFalseselects legacy penalty-only contact.Deprecated since version 1.6: Use
rigid_compliant_alm=Trueand author finite contact stiffness.rigid_contact_history (bool) – Whether to persist body-body numeric contact state across steps using
Contacts.rigid_contact_match_index. Compliant ALM restores the normal multiplier for matched rows. With latest matching it also restores projected tangential multipliers as a numerical warm start; with sticky matching, tangential memory is represented by the collision pipeline’s replayed material anchor. Legacy hard contacts restore the full multiplier; legacy soft contacts restore penalty k only. Contact geometry remains owned by the collision pipeline. RequiresCollisionPipeline(contact_matching="latest")or"sticky". Ignored whenintegrate_with_external_rigid_solver=Trueormodel.body_count == 0. During graph capture, construct the collision pipeline beforeSolverVBDso history is pre-allocated, or run one uncaptured solver step before capture.rigid_contact_stick_motion_eps (float | None) –
Deprecated and ignored. SolverVBD no longer classifies contacts as sticking. Use
CollisionPipeline(contact_matching="sticky", contact_matching_pos_threshold=...)for persistent contact geometry.Deprecated since version 1.5.
rigid_contact_stick_freeze_translation_eps (float | None) –
Deprecated and ignored. The SolverVBD body-level contact deadzone was removed.
Deprecated since version 1.5.
rigid_contact_stick_freeze_angular_eps (float | None) –
Deprecated and ignored. The SolverVBD body-level contact deadzone was removed.
Deprecated since version 1.5.
rigid_contact_k_start (float) –
Body-body and body-particle contact penalty seed for legacy AVBD ramping [N/m]. Used when
rigid_avbd_linear_beta(orrigid_avbd_betafallback) is greater than zero. When the linear beta is 0, k is fixed at the contact stiffness regardless of this value.Deprecated since version 1.6: Penalty ramping is deprecated for all uses. Body-particle contacts continue to honor this control during migration; keep the effective beta at
0(the default behavior) and author fixed contact stiffness instead.rigid_body_contact_buffer_size (int) – Max body-body contacts per rigid body for per-body contact lists.
rigid_body_particle_contact_buffer_size (int) – Max body-particle soft contacts tracked per rigid body, covering both particle-vs-surface and full-surface edge/face contacts.
rigid_joint_linear_ke (float) – Material stiffness for non-cable structural linear joint slots [N/m].
rigid_joint_angular_ke (float) – Material stiffness for non-cable structural angular joint slots [N·m/rad].
rigid_joint_linear_k_start (float) –
Linear penalty seed for legacy AVBD ramping [N/m]. Used when
rigid_avbd_linear_beta(orrigid_avbd_betafallback) is greater than zero. When the linear beta is 0, k is fixed at the joint stiffness regardless of this value.Deprecated since version 1.6: Penalty ramping is deprecated. Keep the effective beta at
0(the default behavior) and author fixed joint stiffness instead.rigid_joint_angular_k_start (float) –
Angular penalty seed for legacy AVBD ramping [N·m/rad]. Used when
rigid_avbd_angular_beta(orrigid_avbd_betafallback) is greater than zero. When the angular beta is 0, k is fixed at the joint stiffness regardless of this value.Deprecated since version 1.6: Penalty ramping is deprecated. Keep the effective beta at
0(the default behavior) and author fixed joint stiffness instead.rigid_joint_linear_kd (float) – Damping coefficient for non-cable linear joint constraints [N·s/m]. Negative values are clamped to 0.
rigid_joint_angular_kd (float) – Damping coefficient for non-cable angular joint constraints [N·m·s/rad]. Negative values are clamped to 0.
deterministic (DeterministicMode | None) – Opt-in determinism for this solver’s atomic-emitting kernel modules. Pass a
warp.DeterministicMode, orNone(default) to inherit the currentwp.config.deterministicmode.
Note
The integrate_with_external_rigid_solver argument enables one-way coupling between rigid body and soft body solvers. If set to True, the rigid states should be integrated externally, with state_in passed to step representing the previous rigid state and state_out representing the current one. Frictional forces are computed accordingly.
particle_vertex_contact_buffer_size, particle_edge_contact_buffer_size, rigid_body_contact_buffer_size, and rigid_body_particle_contact_buffer_size are fixed and will not be dynamically resized during runtime. Setting them too small may result in undetected collisions (particles) or contact overflow (rigid body contacts). Setting them excessively large may increase memory usage and degrade performance.
Dahl hysteresis friction for cable angular response is controlled by custom model attributes
model.vbd.dahl_eps_maxandmodel.vbd.dahl_tau. Register them withSolverVBD.register_custom_attributesbefore building the model. Dahl friction is enabled only when positive Dahl parameters are authored.
- collect_rigid_contact_forces(body_q, body_q_prev, contacts, dt)#
Collect per-contact rigid contact forces and world-space application points.
- Parameters:
body_q (wp.array[wp.transformf]) – Current body transforms (world frame), typically
state_out.body_qafter astep()call.body_q_prev (wp.array[wp.transformf]) – Effective previous-pose history used by the step (world frame). Snapshot
solver.body_q_prevbeforestep()(it is advanced after the step). On a first or reset step, overwrite each rebaselined row with that step’s inputbody_qso its reported force matches the solve. For externally integrated bodies, pass the external solver’s previous transforms.contacts (Contacts | None) – Contact data buffers containing rigid contact geometry/material references. If None, the function returns default zero/sentinel outputs.
dt (float) – Time step size [s].
Note
Call after collision generation and
step()with the sameContactsbuffer. If rigid contact state is absent or undersized, this returns sentinel/zero outputs without growing output buffers. Output buffers persist and grow on demand; they do not shrink, so iterate up to the returnedrigid_contact_countrather than the array length.- Returns:
- tuple[
wp.array[wp.int32], wp.array[wp.int32], wp.array[wp.vec3], wp.array[wp.vec3], wp.array[wp.vec3], wp.array[wp.int32],
- ]: Tuple of per-contact outputs:
body0: Body index for shape0, int32.
body1: Body index for shape1, int32.
point0_world: World-space contact point on body0, wp.vec3 [m].
point1_world: World-space contact point on body1, wp.vec3 [m].
force_on_body1: Contact force applied to body1 in world frame, wp.vec3 [N].
rigid_contact_count: Length-1 active rigid-contact count, int32.
- Return type:
tuple[wp.array[wp.int32], wp.array[wp.int32], wp.array[wp.vec3f], wp.array[wp.vec3f], wp.array[wp.vec3f], wp.array[wp.int32]]
- coupling_harvest_proxy_particle_forces(particle_local_to_proxy_global, out_particle_f, *, particle_qd_before, state, state_out, contacts, dt)#
Harvest contact-only proxy-particle forces.
As for proxy-body harvest, this stays contact-based because VBD allows some proxy interaction inside the destination solve for stronger coupling, but those proxy-only interactions should not appear as feedback forces on the source side.
- coupling_harvest_proxy_wrenches(body_local_to_proxy_global, out_body_f, *, body_qd_before, state, state_out, contacts, dt)#
Harvest contact-only proxy-body wrenches.
VBD deliberately does not rely on the default momentum harvest here. The generic proxy path filters proxy-vs-proxy and proxy-vs-static rigid contacts so harvested momentum only reflects coupling-relevant interactions. VBD relaxes that restriction because allowing some proxy interaction inside the destination solve can strengthen the coupled solve. Those extra interactions still must not feed back through the coupling interface, so VBD harvests explicit contact forces instead of inferring feedback from total proxy momentum change.
- coupling_notify_input_state_update(state, flags, *, iteration_restart=False, dt=0.0)#
Convert input body pose updates into VBD-compatible history updates.
- coupling_prepare_proxy_contacts(state, contacts, *, contacts_freshly_detected=False)#
Update rigid history cadence for proxy contacts.
- coupling_supports_full_surface_soft_contacts()#
- coupling_supports_inertial_property_refresh()#
- notify_model_changed(flags)#
- rebuild_bvh(state)#
This function will rebuild the BVHs used for detecting self-contacts using the input state.
When the simulated object deforms significantly, simply refitting the BVH can lead to deterioration of the BVH’s quality. In these cases, rebuilding the entire tree is necessary to achieve better querying efficiency.
- Parameters:
state (newton.State) – The state whose particle positions (
particle_q) will be used for rebuilding the BVHs.
- reset(state, world_mask=None, flags=None)#
Reset rigid solver history and optional body and particle state for selected worlds.
Body fields selected by flags are copied from the model defaults. Joint penalty is restored to its minimum; joint C0 and AVBD dual history is zeroed immediately. Pose and enabled-cable friction history (curvature, stress, and increment) are rebaselined together from the next
step()input pose, after any intervening state edits or forward kinematics. Selected-world contact warm-start is cold-started when fresh rigid contacts are next processed. Internal rigid history is reset regardless of flags. When an external solver integrates the bodies, reset performs no rigid mutation;stateandworld_maskvalidation and particle reset still apply, but body State arrays are not accessed or validated.BODY_Q/BODY_QDcopymodel.body_q/model.body_qdinto state; they do not restore a previously supplied state. A requested field is skipped if its state array isNone. If your initial pose differs from the model defaults, passflags=0and author the pose any time before the next step; reset then preserves it and only clears VBD history.JOINT_Q/JOINT_QDare ignored (VBD uses maximalbody_q/body_qd); to reset from joint coordinates, runeval_fk()after reset so the resultingbody_qsupersedes reset’s model copy.PARTICLE_Q/PARTICLE_QDlikewise copymodel.particle_q/model.particle_qdinto state for particles in the selected worlds, using the same masking as the body fields (world_mask=Nonealso restores globalworld == -1particles; an explicit mask restores globals only through its final entry). One path covers both cloth and volumetric (tet) soft bodies, and it runs even when an external solver integrates the bodies or the model has none. A requested particle field is skipped if its state array isNone. Particle and body-particle solver history is intentionally left untouched:particle_q_previs rebaselined from the incoming state at the start of the nextstep(), self-contact and body-particle contacts rebuild per step, and tet/cloth elasticity is stateless, so no particle history cold-start is required. Reset does not refresh the particle self-contact BVH; the nextstep()refits it from the incoming positions. After a large reset displacement, callrebuild_bvh()to restore acceleration-structure quality. Both reset andrebuild_bvh()are graph-capturable, so either may run inside a captured episode-reset graph.Reset does not run collision detection, and
step()consumes the supplied contacts rather than rerunningcollide(). After moving bodies or particles, regenerate contacts so stale soft contacts are not reused, and let the nextstep()refresh rigid contact state. The next rigidstep()consumes the pose and cable rebaseline even whencontacts=None, so author the final pose (or runeval_fk()) before stepping; contact invalidation instead waits for a fresh refresh. VBD cold-starts its numeric contact state for reset-selected worlds. Frame-to-frame correspondence and sticky contact geometry remain owned byCollisionPipeline; after a discontinuous episode reset, callreset_contact_matching()with the same world mask to discard that history. Reset does not changeset_rigid_history_update(); leave rigid history refresh enabled for the next contact-bearing step. Reusing contacts (set_rigid_history_update(False)) is unsupported only while contact invalidation is still pending.- Parameters:
state (newton.State) – The simulation state to reset (modified in place).
world_mask (wp.array[wp.bool] | None) –
One-dimensional Warp boolean mask on the solver device. Shape
(world_count + 1,), with the final entry selecting entities in global world-1.Noneselects all local and global entities.Deprecated since version 1.5: Passing a mask with shape
(world_count,)is deprecated. Use shape(world_count + 1,)with a finalFalseentry to select local worlds only.flags (StateFlags | int | None) –
StateFlags(orint) selecting which body and particle fields to copy from the model defaults. VBD honorsBODY_Q,BODY_QD,PARTICLE_Q, andPARTICLE_QD;Nonerequests all flags.
- set_joint_constraint_mode(joint_index, hard, slot=None)#
Set legacy hard/soft mode for a joint’s structural slots at runtime.
Deprecated since version 1.6: Per-slot joint hard/soft mode is deprecated. Under compliant ALM (the future default) all structural slots use the unified scheme, so this has no solver-mode effect; it will be removed with the legacy path.
Non-cable structural slots are LINEAR (slot 0) and ANGULAR (slot 1). Builder-created cable joints expose STRETCH (slot 0), SHEAR (slot 1), BEND (slot 2), and TWIST (slot 3). Other drive/limit slots are always soft and cannot be set to hard.
By default, cable stretch, shear, bend, and twist slots are soft, while non-cable structural slots are hard.
For non-cable joints, hard/soft mode can also be authored per joint at build time via the
vbd:joint_is_hardcustom attribute, avoiding a runtimeset_joint_constraint_mode()call:SolverVBD.register_custom_attributes(builder) # before adding joints builder.add_joint_fixed(..., custom_attributes={"vbd:joint_is_hard": 0}) model = builder.finalize() solver = SolverVBD(model, rigid_compliant_alm=False)
- Parameters:
joint_index (int) – Index of the joint to modify.
hard (bool) – In legacy mode, True selects hard AL mode and False selects soft penalty mode. Has no solver-mode effect under compliant ALM.
slot (int | None) – Specific slot index to set. If None, sets all structural slots. Use JointSlot.LINEAR / JointSlot.ANGULAR for non-cable joints, or JointSlot.STRETCH / JointSlot.SHEAR / JointSlot.BEND / JointSlot.TWIST for cables.
- Raises:
ValueError – If the joint index is out of range or the slot is not a structural slot for this joint.
- set_rigid_history_update(update)#
Set whether the next step() should update rigid solver history.
When True (default), the step refreshes rigid contact state from the provided
Contactsbuffer: rebuilds per-body contact lists, initializes penalty_k/lambda/C0, and restores warm-start state fromContacts.rigid_contact_match_indexwhen contact history is enabled. When False, the step reuses the current rigid contact lists and contact state. In that mode, the caller must pass the same contact result/buffers used by the previous refresh; do not run collision into the contacts buffer between refreshes. Passing newly collided contacts while update is disabled can mismatch stale per-body contact lists with current contact rows. For the same reason, do not change a body’s solvability (mass or kinematic flag) while update is disabled: the per-body lists depend on effective inverse mass and are not rebuilt until the next refresh.Joint constraint maintenance (C0 snapshot, lambda retention/decay, and automatic rho refresh) runs every step regardless of this flag via step_joint_C0_lambda_rho(). Rigid contact history snapshotting also runs every step when enabled.
This setting applies only to the next call to
step()and is then reset to True. Useful for substepping where collision detection frequency differs from the simulation step frequency.- Parameters:
update (bool) – If True, update rigid solver state. If False, reuse previous.
- step(state_in, state_out, control, contacts, dt)#
Execute one simulation timestep using VBD (particles) and AVBD (rigid bodies).
The solver follows a 3-phase structure: 1. Initialize: Forward integrate particles and rigid bodies, detect collisions, initialize contact state 2. Iterate: Interleave particle and rigid-body VBD iterations 3. Finalize: Update velocities and persistent state (Dahl friction)
To control rigid body substepping behavior, call set_rigid_history_update(). When True (default), the step rebuilds rigid contact lists, re-initializes rigid contact state (penalty_k, lambda, C0), and restores from history if enabled. When False, reuses previous rigid contact state. The flag is reset to True when consumed.
- Parameters:
state_in (newton.State) – Input state.
state_out (newton.State) – Output state.
control (Control) – Control inputs.
contacts (Contacts | None) – Contact data produced by
collide()(rigid-rigid and rigid-particle contacts), allocated withcontacts(). If None, rigid contact handling is skipped. Note that particle self-contact (if enabled) does not depend on this argument.dt (float) – Time step size.
- Raises:
RuntimeError – If required rigid contact-matching data is unavailable, or contact-history storage would need to be allocated or grown during graph capture.