Every keyword of SolverSteel.__init__, generated from the source by site/scripts/gen_reference.py. Descriptions are the solver’s own docstrings; “when to change” is guidance. every step marks options that may be assigned between steps; the others are fixed at construction. Newton main, not 1.8.0 and integration branch mark options that Newton 1.8.0 does not have.
Link to one option with #opt-<name>, for example /reference/options/#opt-friction_anchor_beta.
When to change Use "colored" (with the propagation response) for worlds with many free bodies, such as piles and pours. Keep "serial" for articulated robots, small scenes and loop closures.
Description
Gauss-Seidel sweep order of the matrix-free solve, which never assembles the Delassus matrix: it recomputes J v every iteration and uses only the diagonal for preconditioning. "serial" (default) sweeps each world's rows in order in one fused kernel. "colored" colors the propagation contact rows every step so that no two rows of a color share a responding body (a kinematic free body has no response and may be shared) and solves each color as one parallel launch across all worlds; contacts left without a color run last, in the order set by propagation_color_order. "colored" covers free bodies as well as articulations and requires articulated_contact_response="propagation"; any other response raises ValueError. On CPU both modes run world-serial portable kernels ("colored" sweeps in serial order), and the CUDA-only features listed in the class description raise NotImplementedError.
Deprecated 1.8."matrix_free" maps to "serial", and "split", whose dense Delassus solve was removed, runs "serial"; each emits a NewtonDeprecationWarning.
When to change Raise for tall stacks, large mass ratios, loop closures and slipping grasps. Lower only after a full-episode check passes at the lower value.
Description
Number of projected Gauss-Seidel iterations per step.
When to change Rarely changed. On ordinary scalar rows it shifts the diagonal, which damps the sweep like a relaxation below 1 and leaves the converged impulses of unregularized rows unchanged. It deepens the resting penetration of contacts under contact_regularization and floors the pre-elimination regularization; soften contacts with contact_regularization or contact_compliance instead.
Description
Constraint force mixing added to every row's effective-mass diagonal, which regularizes redundant rows. Drive rows of drive_mode="rows" use their exact unit response instead, and the coupled contact solves of a friction_mode other than "fixed_normal" leave it off their contact blocks.
When to change Loop closures or mimic couplings that drift at your iteration budget.
Description
Eliminate the mimic and connect rows of each articulation before the iterative sweep with a Schur complement of the bilateral block S = J_B H^-1 J_B^T: the predicted velocity is projected once and the responses of the other rows are corrected, so closures and mimic couplings depend much less on iterations. The block is factored with a diagonal regularization R of 1e-3 times each row's diagonal plus a floor of max(cfm, 1e-7), which keeps nearly dependent closure axes positive definite. The elimination is therefore not exact: a bilateral velocity residual of R (S + R)^-1 (J_B v + b_B) remains after the projection, and the corrected responses of other rows still couple into the bilateral rows by the same factor. The rows stay allocated and in the sweep, which reduces this residual further. If any articulation owns more than eight bilateral rows (a FIXED loop closure, such as a link-break weld, takes six), any loop closure has a kinematic or world parent, or velocity_iterations is positive, elimination is disabled for the whole solver (every articulation keeps iterative rows) with a warning at construction.
When to change Set False if a mimic row is nearly dependent on a closure and the eliminated block becomes singular.
Description
With pre-elimination enabled, also eliminate mimic rows. False eliminates only the connect rows and keeps mimic rows iterative, which avoids a singular block when a mimic row is nearly dependent on a closure.
When to change Set 2 to 4 when position correction launches bodies (deep start overlaps). Must be 0 with sleeping, compliance, and torsion under propagation.
Description
Number of velocity-only iterations after the position solve. Positions are integrated from the position solve; these iterations then refine the velocity without the position bias, so stabilization does not add velocity to the bodies. A positive-gap contact whose linearized gap at the end of the step stays open keeps its speculative allowance, and an impacting contact keeps its rebound target.
When to change Only matters with drive_mode="rows" and velocity_iterations > 0.
Description
Treatment of PGS joint-drive rows during the velocity-only iterations: "freeze" keeps the drive impulses of the position solve, "active" keeps solving the drive rows. Implicit (mass-matrix) drives have no rows, so the option has no effect for them.
When to change Try "phased" for grasps tuned against PhysX. Avoid "contact_then_internal" when contacts load a joint limit or drive: the load sinks through at any iteration count. Contact torsion, compliance and the sparse mass factors need "interleaved".
Description
Row order of the matrix-free sweeps. "interleaved" sweeps every row family in each iteration: the dense rows, the free-body contact rows, then the velocity limits. "contact_then_internal" runs every iteration of the contact rows first, then every iteration of the internal rows (drive, mimic, connect, joint-limit and joint-friction rows) and the velocity limits. "phased" approximates the order PhysX uses for grasping: each iteration solves the internal rows, then the contact rows, then the velocity limits, each in a launch of its own; the propagation responses use this order with "interleaved" as well. Contact torsion and contact compliance require "interleaved", and the sparse mass factors are selected only with "interleaved".
When to change "propagation" is required by the colored sweep. Keep "immediate" for loop-closing joints, Nesterov momentum and coupled solvers.
Description
How contacts touching an articulation that is not a free body are solved.
"immediate": dense rows of the articulation's generalized coordinates, Y = H^-1 J^T per row.
"propagation": fixed-size rows of the touched bodies at their centers of mass, with each body's 6x6 response from the articulated-body factorization of its tree. Each iteration solves these rows and then propagates the accumulated body impulses through the trees to the joint velocities. All contacts, including those of free bodies, use these rows, whose capacity per world is propagation_constraint_max, or free_body_constraint_max + articulation_constraint_max when that is None. With solve_mode="colored" each sweep solves the contacts of a world in batches of contacts that share no responding body, one batch after the other.
The propagation response avoids the per-row H^-1 J^T of contact rows at the cost of tree passes over every articulation in each iteration; which response is faster depends on the model. They keep joint-limit and velocity-limit rows dense, and contacts between two links of the same articulation dense unless propagation_same_articulation_rows is set. The tree factorization is rebuilt every step, independently of update_mass_matrix_interval.
Deprecated 1.8."propagation_colored" maps to solve_mode="colored" with "propagation" and emits a NewtonDeprecationWarning.
When to change Set wp.DeterministicMode.RUN_TO_RUN for tests, debugging and data generation that must reproduce bit for bit. Pair it with CollisionPipeline(deterministic=True).
Description
Run-to-run determinism of the solve. Pass a DeterministicMode, or None (default) to inherit wp.config.deterministic, which defaults to NOT_GUARANTEED. With RUN_TO_RUN the solver reserves its constraint rows in a fixed order instead of the order in which GPU threads reach the per-world row counters: joint rows in articulation order, contact rows in contact-buffer order within each world. Given identical inputs, including identically ordered contacts, repeated runs are then bitwise identical on the same GPU model, driver and Warp build, eagerly and under CUDA graph replay; combine it with CollisionPipeline(deterministic=True) for a reproducible contact order (see :ref:`Deterministic Contacts`). A world that overflows a row capacity keeps the rows of its earliest contacts and drops the rest, so unchanged inputs drop the same contacts every step; overflowed steps remain flagged in constraint_overflow. The mode adds a per-step sort of the contacts by world and row family and 24 bytes of storage per contact slot. With the "propagation" response it also lists each world's contact-active bodies by body index and sums each body's warm-start seed in row order. The seed walks a world's rows serially, so its cost grows with the contact rows in one world; solve_mode="colored" regroups a world's contact rows by color, an order fixed by the contact set. GPU_TO_GPU is not supported: passing it raises ValueError, and an inherited one emits a NewtonWarning and runs RUN_TO_RUN. deterministic reports the mode that runs, after any fallback. BODY_PARENT_F sums contact wrenches with atomics, so it is outside this guarantee. Steel's kernel modules always opt out of Warp's deterministic module option, so a process-wide wp.config.deterministic only selects this mode.
When to change Resting stacks with mass ratios of roughly 100:1 to 1000:1 and long chains, when more iterations alone are too slow. Serial sweep, immediate response, CUDA only.
Description
Accelerate the matrix-free Gauss-Seidel sweep with Nesterov momentum and O'Donoghue-Candes gradient restart, as in MuJoCo's PGS solver. Each sweep starts from the impulses extrapolated along the previous sweep's change, applied to the velocity through each row's response; momentum restarts when a sweep's correction opposes the extrapolation. Converges in fewer iterations on stacks, mass ratios and long chains; gains appear above a few iterations. The velocity_iterations post-pass runs the same sweep. Every world then runs the general sweep, bypassing the specialized sparse, local and paired-factor solves, and keeps 8 * (articulation_constraint_max + free_body_constraint_max) bytes of sweep history per world. Requires solve_mode="serial", articulated_contact_response="immediate" and row_schedule="interleaved"; other combinations raise ValueError. CUDA only: on CPU it raises NotImplementedError. Construction-only.
When to change Up to 0.5 for light bodies pressed into the ground by heavy ones. Higher values launched bodies in testing; prefer velocity_iterations for deep start overlaps.
Description
Baumgarte position-correction factor of contact and joint-limit rows, as a fraction of the position error removed per step.
When to change About 0.01 removes warm-start bursts on deeply wedged contacts and makes indeterminate load splits unique, at a small resting penetration.
Description
Dimensionless regularization g of penetrating contact rows (friction_mode="fixed_normal" only). Each iteration moves a row's impulse toward the rigid solution with weight 1 / (1 + g) and toward zero with weight g / (1 + g), the update of an implicitly integrated contact spring. It makes statically indeterminate normal-force splits unique and damps the sweep, at the cost of a resting penetration: a row at rest settles at baumgarte * phi / dt = -g * d * lambda (d its unsplit inverse effective mass, lambda its impulse), about g * a * dt^2 / baumgarte for a body under acceleration a resting on one row. Propagation rows whose response is split across coupled contact bodies, with split diagonal d_s, take weight w * d_s / (w * d_s + (1 - w) * d) with w = 1 / (1 + g), which reaches the same rest state. Speculative (positive-gap) rows, rows whose rebound fires and the velocity-only iterations stay rigid. 0 is the rigid law; at most 1e6.
When to change Rarely changed. 1 lets a contact close exactly its gap in one step; 0 removes the speculative allowance.
Description
Fraction of a positive contact gap that the contact may close during the step (rhs = scale * phi / dt). 0 removes the speculative allowance; penetration correction is unchanged.
When to change Set 0 where speculative rows never engage (for example many small rollers) to save rows.
Description
Contacts of the collision pipeline whose gap [m] exceeds this distance get no rows; 0 keeps touching contacts only. None (the default) keeps every contact. gap decides which contacts the pipeline reports (also to sensors and other solvers); this gate only decides which of them this solver solves. Finite and non-negative.
When to change Above 1 only for slowly moving articulations; it must divide the steps per captured graph. It does not cure energy gain on fast, light chains: on the measured chains the stale matrix lost energy instead.
Description
Rebuild and refactor the mass matrix every this many calls to step; 1 rebuilds it every step. Larger values reuse a stale factorization between rebuilds. A change of dt, reset and notify_model_changed still request a refresh of the affected articulations. Under CUDA graph capture the host-side cadence is baked into the graph, so the interval should divide the number of steps captured per graph.
When to change Broad trees such as hands; time the full step before keeping it.
Description
Traverse the independent branches of each articulation tree in parallel (forward kinematics and dynamics, the inverse-dynamics backward pass and state publication), with up to 32 threads per articulation instead of one. Results match the serial traversal up to floating-point summation order. Unbranched articulations, models whose joints are not ordered parent before child, and CPU devices keep the serial traversal. Broad trees can benefit; narrow trees can be slower, so measure the full step before enabling it.
When to change Time it on your scene; call notify_state_changed after writing state outside step().
Description
Opt in to carrying the kinematics and inverse-dynamics terms the solver forms when it publishes a step's body state into the next step, instead of re-deriving them from the joint coordinates. The carry runs on CUDA only and stays off with gradients, joint velocity limits, sleeping, the parallel tree, or a FREE or DISTANCE joint that is not the first joint of its articulation; the attribute of the same name reports whether it runs. Off by default: every step then re-derives the kinematics from its input state and publishes through eval_fk, as before. With the carry on, the terms belong to the state object they were published into: reset drops them for the selected worlds, notify_model_changed drops them for joint, body and model property changes, a coupler's input-state notice drops them, and a step whose input state is another object recomputes them; a caller that overwrites or replaces joint_q, joint_qd or body_q of that state outside step must call notify_state_changed (or reset with a world mask) first. The published body poses and velocities then come from the solver's own kinematics and can differ from eval_fk's in their last bit.
When to change Models with several articulation sizes, or many independent single-DOF joints on one base.
Description
Run the factorization, unconstrained solve and response kernels of each articulation-size group on a CUDA stream of its own, so groups of different sizes overlap. Results are unchanged; CPU devices and models with one size group ignore it.
When to change Time it on your scene; results are unchanged.
Description
Keep two sets of the grouped mass-matrix and Jacobian buffers and clear the set a step used on a separate CUDA stream, which the step joins before it returns. Results are unchanged; CPU devices and the sparse mass factors ignore it. Steps and graph launches of one solver must be ordered on one stream (or through explicit stream dependencies).
When to change Set True whenever the model authors joint limits. Off, limits are not simulated. DISTANCE joint limits are ignored either way.
Description
Enforce joint_limit_lower and joint_limit_upper of PRISMATIC, REVOLUTE and D6 DOFs as unilateral rows. When False (the default), no joint-limit rows are created, joint position limits are not enforced, and limits use no articulation_constraint_max capacity. The default matches the Steel reference implementation this solver is ported from.
Version note: default in Newton 1.8.0: float('inf'); default in Newton main: float('inf')
When to change A fixed gap such as 0.1 builds limit rows only near a limit and is often faster than the speed-aware default. Keep it above 2 * max|qd| * dt.
Description
Distance from a finite position limit [m or rad] at which its row is created, when enable_joint_limits is set. inf creates the rows of every finite limit each step; a smaller gap creates a row only when q <= lower + gap or q >= upper - gap. None (the default) uses a speed-aware gap of 0.05 + 2 * dt * |v| per DOF, where v is the joint's unconstrained velocity at the end of the step, after drives, gravity and parent motion. Limit rows are speculative and apply no impulse while the joint cannot reach its bound within the step, so the skipped rows are no-ops unless constraint impulses in the solve, such as contacts, accelerate the joint toward the bound by more than the margin in one step. Mimic and connect rows also act inside the solve, so both mimic ends, the tree joints between the two ends of each mimic or loop closure, and every joint below them always have their rows. Joints above a closure's common ancestor carry both ends and stay gated, which can miss a passive limited mount under opposed mimics. With drive_mode="rows" the drives act inside the solve too, so None creates every limit row, as inf does. A bound at or beyond MAXVAL, the builder's unlimited default (+/-1e10), has no row. The constructor warns when the finite limits alone exceed the capacity. The value is validated even when joint limits are disabled.
When to change Set True when the task depends on joint velocity limits.
Description
Enforce joint_velocity_limit of PRISMATIC, REVOLUTE and D6 DOFs with one row pair per limited DOF, after scaling articulation velocities that already exceed a limit. A DOF at the builder's default limit (1e6) or above has no rows. The free-body limits of register_custom_attributes are enforced whenever those attributes are registered, independently of this option.
When to change Raise toward 1 to skip rows of DOFs far below their limit.
Description
Create the velocity-limit rows of a DOF only when |qd| >= velocity_limit_activation_fraction * limit. 0 creates them for every limited DOF each step; inf never creates them. The gate samples the velocity before the solve, so a DOF that crosses the threshold during a step is clamped one step later. Must be in [0, 1] or inf.
When to change Set True for models that author joint friction (MJCF frictionloss). It disables several fast paths, so leave it off otherwise.
Description
Enforce joint_friction [N or N·m] as dry joint friction (MuJoCo frictionloss). Each PRISMATIC, REVOLUTE, BALL or D6 DOF with positive friction adds one row whose impulse is bounded by joint_friction * dt around a zero-velocity target, so the DOF sticks until the required effort exceeds the friction and then slides against it. A BALL joint's three DOFs are separate boxes about the axes of its angular velocity coordinates. The rows use the articulated response, so coupled inertia, armature, drives, limits and contacts act jointly; their impulses cold-start each step and count against articulation_constraint_max. The coefficients are read and checked on the device every step, also on graph replay, so in-place edits take effect on the next step. An eager step reads a replaced array; a captured graph keeps the array it was captured with, so recapture after replacing it. After editing or replacing the coefficients, call notify_model_changed with JOINT_DOF_PROPERTIES (or the narrower JOINT_DOF_FORCE_PROPERTIES) to wake sleeping islands whose friction changed. Non-finite or negative values, and nonzero friction on other joint types or loop-closing joints, are invalid: such a DOF builds no row, construction and eager notifications raise ValueError, and steps flag the owning world for check_constraint_capacity. Requires CUDA and is not supported with contact_compliance or enable_bilateral_preelimination; those combinations raise NotImplementedError. Enabling it disables the articulation-local, paired factor-coordinate and sparse-diagonal solves and sparse mass factors at construction, even when every coefficient is zero, so enable it only for models that need friction. When False, joint_friction is ignored.
A positive steel:joint_friction_load_coefficient at construction (see register_custom_attributes) adds load-proportional friction: each step, a DOF's bound grows by its coefficient times the load its joint transmits under that step's free dynamics. The row is solved together with the drives, so it resists a drive up to its bound, whereas PhysX applies the friction before each DOF's drive in every iteration and a stiff drive largely overrides it. With drive_mode="augmented" the implicit drive forces are part of the free dynamics and count toward the load; drive_mode="rows" leaves them out, as PhysX does. The coefficients follow the validity rules and notify contract of joint_friction. A model built with every coefficient zero must keep them zero; to randomize coefficients after construction, make at least one positive beforehand.
Experimental.enable_joint_friction and its supported combinations may change without the normal deprecation period.
When to change "rows" when drive torques must respect the effort limit exactly (torque-limited robots, sim-to-real), or to solve drives together with contacts.
Description
Joint drive formulation. "augmented" integrates drives implicitly in the mass matrix. "rows" adds one dense PGS row per driven DOF (positive joint_target_ke or joint_target_kd) whose impulse follows the PhysX articulation force-drive update in every iteration, so drives are solved together with contacts and limits instead of before them. Without contacts or limits and below the effort limit, the converged row reproduces the implicit drive of "augmented". Under effort saturation the two differ: "augmented" clamps the explicit drive force before the implicit solve, while the row clamps its accumulated impulse at joint_effort_limit * dt. Drive rows are allocated first in each world, count against articulation_constraint_max, and a drive whose row does not fit is not applied (the world is flagged in constraint_overflow).
When to change Leave on; set False to keep explicit velocity-limit rows on driven DOFs.
Description
With drive_mode="rows" and enable_joint_velocity_limits, enforce the velocity limit of each driven DOF with a clamp of its velocity at the end of every iteration (after the contact rows, like the velocity-limit rows it replaces) instead of two velocity-limit rows, and exclude it from the pre-solve velocity scaling. Limited DOFs without a drive row keep their rows. In every other configuration, including velocity_limit_activation_fraction=inf, the option has no effect; velocity_limits_fused reports whether the clamp is active.
When to change Size from row_watermark: about 2x the requested mark while overflowing, then 1.3x a non-overflowing mark. Robots with limits or self-contacts often need more than 32. An overflowing run can gain energy and diverge.
Description
Capacity of rows involving articulated bodies (mimic and connect rows, contacts, enabled joint limits, joint velocity limits, joint friction and, with drive_mode="rows", joint drives) per world. Rows beyond it are dropped and reported, see constraint_overflow.
When to change Size from row_watermark under the immediate response. Very large values stop the immediate kernels from building; move such scenes to colored propagation.
Description
Capacity of free-body rows per world: free-body contact rows and free-body velocity-limit rows. Under the "propagation" response free-body contacts use the propagation rows, so it sizes only the velocity-limit rows. Rows beyond it are dropped and reported, see constraint_overflow.
When to change Size from row_watermark under the propagation response.
Description
Capacity of the propagation row family per world in the "propagation" response, which holds every contact row except those between two links of one articulation; these stay dense unless propagation_same_articulation_rows is set. None (default) uses free_body_constraint_max + articulation_constraint_max. Setting it lets free_body_constraint_max shrink to the free-body velocity-limit rows. At least 1; rejected with articulated_contact_response="immediate".
When to change Turn off only when you check constraint_overflow yourself.
Description
Print a device-side warning the first time a world exceeds a row capacity. The warning does not synchronize the host and is compatible with CUDA graph capture. The host contact torsion preparation emits its overflow warning as a NewtonWarning through warnings instead.
When to change On while tuning. Read constraint_row_watermarks() after a full episode.
Description
Accumulate the high-water marks of the per-world row counts of every row family and of the contact count on the device in every step, including captured ones; read them with constraint_row_watermarks.
When to change Keep the default (anchors) for anything held, carried or pinched. Set 0 (point friction) for scenes where nothing is held; it is cheaper.
Description
Position-correction gain of persistent friction patches; 0 selects point friction. None selects 0.2, and point friction when contact_compliance is enabled or friction_mode is not "fixed_normal". With a positive gain, the contacts of a body pair whose normals, contact planes and friction coefficients agree and whose shapes touch form a region. Each region's friction acts at up to two anchors along its principal extent, which share the region's total normal impulse; every contact keeps its own normal row. An anchor carries its tangential displacement across steps, following the pose increments of both bodies, and the tangent rows add friction_anchor_beta * displacement / dt, so a held object does not creep under a static load. Anchors are released when their region is unloaded or slides at the Coulomb limit; history is matched by body pair and geometry, independently of collision contact matching. A one-anchor region has no torsional friction of its own. Call reset after teleporting a body to discard its history.
When to change Experimental. Leave at "fixed_normal"; "coulomb_newton" for free bodies near the friction limit. "bisection" and "bisection_desaxce" let a box near the friction limit slide; a fix is in review in skild-ai/newton#26.
Description
Experimental Coulomb friction update of the matrix-free solve. "fixed_normal" updates both tangent impulses together on the friction disk of the current normal impulse: sticking uses the inverse of their 2x2 block, sliding a bounded scalar solve that keeps isotropic maximum dissipation. "bisection" bisects the normal impulse of each contact and re-solves the 2x2 tangent problem at every probe, so normal and friction impulses are updated together. "bisection_desaxce" adds the de Saxce maximum-dissipation bias mu * |c_T| to the normal target velocity of free-body contacts (Le Lidec and Carpentier, 2024). "coulomb_newton" solves each free-body contact's Coulomb cone exactly with a bracketed scalar Newton iteration on the tangential-force ratio; articulated contacts keep the "fixed_normal" update. The other modes replace each contact's normal and friction impulses with their coupled solution, which relaxation does not scale, and use point friction: an omitted friction_anchor_beta selects it with a warning, and friction patches, contact torsion, contact compliance, contact_regularization and articulated_contact_response="propagation" with solve_mode="serial" require "fixed_normal". The free-body and articulated rules above apply to articulated_contact_response="immediate". solve_mode="colored" solves every contact on a propagation row, articulated ones included, with the free-body update of the selected mode; contacts between two links of one articulation stay on dense rows and keep the articulated update. This option may change without the normal deprecation period.
When to change Off by default. Turn on only where a measured scene needs it (for example a house of cards with momentum). Needs contact matching; never for a grasp without anchors.
Description
Start each step from the previous step's contact impulses, matched by contact identity through rigid_contact_match_index, so the CollisionPipeline must be created with contact matching enabled. Substeps that reuse a contact set without a collision pass seed each contact from its own previous substep. History carries across one collision pass into the same Contacts buffer when that pass matched against the solved contact set (rigid_contact_match_generation); a different buffer, skipped passes, or a pass after the pipeline wrote another buffer start cold. Carried impulses are scaled by the ratio of the step to the previous one, including under graph replay; tangent impulses are rotated into the current tangent frame and clamped to the current friction cone; other rows start cold. The pipeline's default matching compares world-space contact midpoints, so contacts that two bodies carry together farther than contact_matching_pos_threshold per step can lose their match and start cold; contact_matching_body_frame=True also matches them in their bodies' frames.
When to change Set False to ignore authored restitution everywhere, or to use contact_compliance with shapes that author restitution.
Description
Apply contact restitution, the only restitution switch. The default True leaves the shapes' coefficients in charge; they default to zero, so a model that authors no restitution does not bounce. False turns restitution off for every contact regardless of the coefficients, and lets contact_compliance accept shapes with positive restitution.
When to change Lower to let slower impacts bounce; raise to make slow impacts inelastic.
Description
Minimum closing speed [m/s] of a contact at the start of the step for a rebound. Contacts bounce with the two shapes' restitution coefficients combined by restitution_combine (restitution, clamped to [0, 1]; zero gives no rebound): an impacting contact replaces its position bias by the rebound target -e * u_start, where u_start is its relative normal velocity at the start of the step, as a lower bound on its separating velocity. The contact must also touch, or be predicted to reach the surface during the step. Slower contacts keep the ordinary contact law, so a resting contact pressed by gravity, a drive or an applied force does not bounce, and this step's forces do not enlarge a rebound. Finite and non-negative.
When to change Sweeps or domain randomization over friction without editing shape materials.
Description
Non-negative factor applied to every shape's friction coefficient (shape_material_mu) in the solver's copy of the materials, refreshed at construction and by notify_model_changed with SHAPE_PROPERTIES. It scales the friction rows, patches and the torsion budget; the model's coefficients are unchanged.
When to change Rarely changed. Solves friction only in the last k position iterations; rejects warm start and compliance.
Description
Number of position iterations that solve tangential friction rows. -1 (the default) solves them in every position iteration; k >= 0 solves them only in the last k position iterations (0 never), and holds their impulses at zero before that. Velocity-only iterations always solve friction. Values other than -1 reject contact_warmstart and contact_compliance.
When to change -inf for a frictionless scene, which saves the friction rows.
Description
Contacts with a gap [m] above this distance get a normal row only. None (the default) gives every contact friction rows; -inf gives none of them friction rows, which saves the rows that zero friction coefficients would keep. A finite negative value keeps friction rows for contacts that penetrate deeper than it. Switching between None (or inf) and a finite or -inf value requires a new solver.
When to change Match PhysX's single-point contact application.
Description
Apply every contact row at the midpoint of the two witness points instead of at each body's own witness point, as PhysX applies a contact at one point. phi still comes from the witness points. Friction patch rows keep their patch anchors, so with patches this moves only the normal rows.
When to change Remove the friction couple of witness points separated along the normal.
Description
Apply the friction rows at the witness midpoint, which removes the tangential force couple of witness points separated along the normal. It has no effect on friction patch rows, which act at their anchors.
When to change Set True whenever shapes author steel:min_torsional_patch_radius and you capture CUDA graphs or use the propagation response.
Description
Experimental contact torsion is enabled at construction when any shape has a positive steel:min_torsional_patch_radius (see register_custom_attributes). It adds one angular row per contact group of an articulated body, about the group's normal, bounded by r * (mu * N - sliding): sliding and spin share one Coulomb budget, N is the final solved load of the group's normal rows, and r is the largest radius of the group's shapes (a patch region can span several shape pairs; contacts whose pair has no positive radius get no torsion). With point friction a group is a coplanar cluster of touching contacts of one shape pair; with friction patches it is one patch region, budgeted by its pooled load and undivided friction coefficient. The radius is an effective footprint, not derived from the geometry: for uniform pressure on a disk of radius R it is 2 * R / 3. Rows are rebuilt every step and carry no spin history; free-body contacts get none. Supported geometry is sphere, box, capsule, cylinder, cone, ellipsoid, plane and convex mesh. Requires contact_warmstart=False; contacts with hydroelastic stiffness are rejected. Dense torsion rows count against articulation_constraint_max after the world's other dense rows. A world whose groups do not all fit keeps the rows that fit, and a world that dropped dense rows gets no dense torsion rows; both set the world's constraint_overflow entry and warn when warn_constraint_overflow is set, and other worlds step unaffected. contact_torsion_device prepares the torsion rows on the device instead of on the host. The host preparation is the reference implementation; it reads the contacts back every step and cannot be captured in a CUDA graph. The device preparation builds the same groups and rows with preallocated buffers and supports CUDA graph capture of step. Invalid torsion input (contact-buffer overflow, hydroelastic contacts, or a friction-patch load ring that does not match its group) makes an eager step raise before it applies torsion rows. In a captured step the error is deferred: the failing step restores its output motion arrays (joint_q, joint_qd, body_q, body_qd, body_qdd) to the input values, while other outputs, observables and solver history still advance, and check_constraint_capacity raises after the replays. Check before using replay results, discard failed output, fix the cause and reset. The input error is solver-wide: any reset clears it, and a cause that persists latches it again on the next step. Grouping runs serially per world with worst-case quadratic cost in the contacts of a world. No effect without contact torsion. With articulated_contact_response="propagation", every positive-radius contact on an articulated body that is routed to propagation reserves one more propagation row for torsion (same-articulation contacts stay dense unless propagation_same_articulation_rows is set), so size propagation_constraint_max, or articulation_constraint_max and free_body_constraint_max when it is unset, for it. A group's torsion row takes that row of its last member. The serial sweep solves the torsion rows after the other rows; the colored sweep solves each in its last member's contact unit, after the rows of the group's other members. Both use the same budget, and both solve modes require contact_torsion_device=True and velocity_iterations=0. solve_mode="colored" rejects contact torsion with contact_compliance, whose contacts are hydroelastic. When propagation rows overflow, a group keeps the contacts that received rows and the step does not raise: it sets constraint_overflow, warns when warn_constraint_overflow is set, and check_constraint_capacity raises.
When to change Experimental. Soft fingertips or pads modeled with hydroelastic contacts.
Description
Experimental: solve contacts that carry a positive rigid_contact_stiffness [N/m] with an implicit unilateral spring-damper law instead of the rigid normal law. The material comes from the contacts (per-shape hydroelastic stiffness, the contact damping [N s/m], zero staying zero, and the friction weight, applied once to the pair friction); contacts with zero stiffness stay rigid. A compliant row's force is max(0, -k phi_next - c u_next), solved with the residual u + k phi / (dt k + c) + lambda / (dt (dt k + c)) in every sweep; the damping term is dropped while the gap is open. Requires point friction (None or 0 for friction_anchor_beta; None warns), positive iterations, no warm start, no velocity-only iterations, no contact regularization, no shared anchors and zero shape restitution. With solve_mode="colored" the colored sweep solves the compliant rows, without contact torsion; "propagation" with solve_mode="serial" rejects it. The contacts must carry the hydroelastic material arrays. The rows are prepared on the device, so step can be captured in a CUDA graph. Invalid input (for example a compliant contact lost to a row capacity, even with warn_constraint_overflow off, or a positive shape restitution) makes an eager step raise. In a captured step the error is deferred: check_constraint_capacity raises after the replays, until reset, and their results are invalid; eager steps do not report it. Contacts the allocator excludes on purpose are counted in compliance_skipped_contact_count and compliant contacts in compliance_contact_count. This option may change without the normal deprecation period.
When to change Match the combine mode of the engine you are porting from (PhysX average, min, multiply or max).
Description
How a contact combines its two shapes' friction coefficients: "average", "min", "multiply" or "max", as PhysX's material combine modes. It applies to sliding friction (shape_material_mu); the free-body angular rows keep the larger coefficient of the pair under every mode. A contact with one shape keeps that shape's coefficient. Construction-only.
When to change Match the combine mode of the engine you are porting from.
Description
How a contact combines its two shapes' restitution coefficients, with the same modes as friction_combine, after each coefficient is clamped to [0, 1]. Construction-only.
When to change Sweeps over spin friction of free bodies without editing shapes.
Description
Experimental torsional coefficient [m] for every free-body contact, replacing the shapes' steel:condim gate and shape_material_mu_torsional for that coefficient only; None keeps the shape data. Meant for sweeps that cannot edit shape data. Construction-only.
When to change Sweeps over rolling friction of free bodies without editing shapes.
Description
Experimental rolling coefficient [m] for every free-body contact, replacing the shapes' steel:condim gate and shape_material_mu_rolling for that coefficient only; None keeps the shape data. Construction-only.
When to change Settling scenes with many passive objects. Excludes warm start and velocity iterations. In many worlds, pair it with CollisionPipeline(deterministic=True), or most islands can stay awake; check body_awake.
Description
Experimental passive-island sleeping. Articulations in contact are joined into islands every step. Static geometry and articulations with no responding degrees of freedom (such as a body welded to the world) support an island without joining it. A fixed-base articulation with responding joints, such as a robot arm, joins the island of everything it touches, so it can connect them into one island; its fixed root supports that island. A supported island whose bodies stay below sleep_linear_threshold and sleep_angular_threshold for sleep_quiet_time falls asleep, and its published state (joint_q, joint_qd, body_q, body_qd and, when requested, body_parent_f) is frozen until a wake event: a nonzero or nonfinite external force (body_f, joint_f), a changed state or gravity, a contact with an awake or moving body, lost support or row capacity, a reset of its world, or notify_model_changed for properties of its joints, DOFs, bodies or shapes (other notifications and changes to static or kinematic owners wake every island). Driven articulations (nonzero drive gains) and articulations with passive springs (nonzero joint_stiffness on a PRISMATIC, REVOLUTE or D6 tree joint) stay awake. Sleeping is configured at construction; rebuild captured graphs to change it. Construction raises ValueError with contact_warmstart or velocity_iterations, or for a model without articulations, and NotImplementedError with articulated_contact_response="propagation" and solve_mode="serial", and with solve_mode="colored" on CPU, where the colored mode runs the serial propagation sweep; with solve_mode="colored" on CUDA skipped islands are left out of the coloring, the colored sweep and the propagation trees, and, where CUDA conditional graph nodes are supported, a captured step in which every articulation that can sleep sleeps skips the propagation solve. step raises ValueError for a nonpositive or nonfinite dt and when state_in and state_out share arrays. The sleeping options are runtime solver settings with no USD schema.
When to change Set False when consumers read contact forces of sleeping bodies.
Description
Skip the work of sleeping islands: their contact and joint-limit rows (collision still runs, so wake events are complete), the rebuild of their friction-patch history (carried instead), and their articulated dynamics (kinematics, inverse dynamics, drives, mass matrix and factorization, velocity prediction and integration). False keeps the rows and dynamics of sleeping islands and only freezes their published state.
When to change Robots with many self-contacts under the propagation response, to move those contacts off the dense rows.
Description
Solve contacts between two links of the same articulation as propagation rows, with the exact cross response of the two links, instead of dense rows. Requires articulated_contact_response="propagation" (either solve_mode).
When to change Leave on; compare both on your model if the propagation sweep dominates.
Description
With articulated_contact_response="propagation" (either solve_mode), replace the per-iteration tree walk by cached responses: the setup extracts, for each contact-active body, its joint-space response R (DOFs x 6) and the 6x6 response blocks between active bodies, from the tree factorization that is fixed for the step, and each iteration applies them as a small matrix-vector product. The result equals the tree walk up to float reassociation. It applies to articulation groups with 0- or 1-DOF joints (optionally under a free root); other groups, and worlds with more cache-eligible active bodies than propagation_cached_response_body_max, keep the tree walk, selected per world on the device. Which is faster depends on the model.
Version note: 'rotating' not in Newton 1.8.0; 'rotating' not in Newton main
When to change "rotating" spreads Gauss-Seidel bias over a symmetric grasp on a sorted contact stream; "longest_first" can shorten sweeps with uneven row counts.
Description
Order in which solve_mode="colored" colors a world's contacts and runs those left without a batch: "contact" (default) by contact index, or "longest_first" by row count, longest first, then contact index. A batch takes as long as its longest contact, so "longest_first" puts long contacts together, which shortens the sweep where one body carries many contacts with different row counts; on some stacked scenes it converges more slowly at a fixed iteration count. "rotating" walks the contact-index order in a different deterministic permutation every step. Gauss-Seidel favours the contacts it solves last, so a fixed order over a sorted contact stream (CollisionPipeline(deterministic=True) or contact matching) can favour the same contacts every step and twist a symmetric grasp; rotating spreads that over the contacts. Equal contact streams and step counts give equal orders; reproducible runs still need deterministic and a deterministic pipeline. It supports fewer than 1,048,583 propagation rows per world. solve_mode="serial" ignores it.
No option matches. Clear the filter to see all options.
Generated from newton/_src/solvers/steel/solver_steel.py: 59 options (9 read every step), 9 attributes, 27 inputs, 17 methods.
Steel docs and tutorials are licensed under Apache-2.0. Third-party notices. "Skild", "Skild AI" and the Skild logo are trademarks of Skild AI and are not licensed under Apache-2.0.