Skip to main content

ContactSolverConfig

Struct ContactSolverConfig 

Source
pub struct ContactSolverConfig {
    pub coupling: ContactCoupling,
    pub newton: bool,
    pub regularization: f64,
    pub tolerance: f64,
    pub max_iterations: usize,
    pub relaxation: f64,
    pub restitution_threshold: f64,
    pub mujoco_compat: bool,
}
Expand description

Tuning for the contact solve.

Fields§

§coupling: ContactCoupling

Which Delassus operator the sweep iterates on. See ContactCoupling.

§newton: bool

Allow the active-set Newton stage.

Off in the GPU-equivalent preset: a dense 3n x 3n factorization is not something a contact shader can do, so leaving it on would put the CPU reference out of the GPU’s reach by construction.

§regularization: f64

Diagonal regularization R added to the Delassus operator.

Larger values soften contact: more penetration, but a better conditioned solve and smoother sensitivities. Smaller values approach rigid contact and sharpen both the physics and the gradients.

§tolerance: f64

Residual tolerance for the fixed point (units of velocity).

§max_iterations: usize

Iteration cap, counted in units of solver work: one PGS sweep or one dense KKT solve each. Reaching it means the solve did not converge; the result is still feasible but is not a valid point to differentiate.

The solve may also stop short of the cap when the residual has stopped falling fast enough to reach Self::tolerance within it. That is reported identically — converged: false — because it means the same thing: this is not a KKT point.

§relaxation: f64

Successive over-relaxation factor in (0, 2).

§restitution_threshold: f64

Below this approach speed, restitution ramps smoothly to zero.

Without it a resting body micro-bounces forever and a stack never settles. The ramp is smoothstep, not a hard cutoff, so restitution stays differentiable in both e and the approach speed.

§mujoco_compat: bool

Reproduce MuJoCo’s regularization on the tangential rows as well as the normal one. Off by default, and it should stay off outside tests.

regularization_diag documents the divergence in full: MuJoCo applies the impedance-derived R = (1-d)/d * A_nn to all three rows of a contact frame, which on a friction row means a fraction 1-d of the slip velocity survives every step. This crate applies it to the normal row only, so a block below the friction angle holds exactly.

Turning this on re-introduces MuJoCo’s steady-state creep — g sin(alpha) dt (1-d)/d, roughly a millimetre per second on a 25-degree slope at dt = 2 ms — for a block Coulomb’s law says is stuck. That is the whole reason it is not the default.

It exists so MuJoCo trajectories remain usable as a cross-validation oracle: a divergence in the tangential regularizer makes a step-by-step comparison against MuJoCo meaningless, and without a way to match its behaviour there is no way to tell “phyz is right and MuJoCo creeps” apart from a real bug. mujoco_creep_matches_the_analytic_rate in tests/stabilization.rs measures both modes side by side.

Implementations§

Source§

impl ContactSolverConfig

Source

pub fn simulation() -> Self

Fidelity-biased preset: crisp contact, minimal penetration.

Source

pub fn gradients() -> Self

Gradient-biased preset: softer contact, better conditioned, smoother sensitivities. Documented in docs/design/differentiable-contact.md §2.5 — these differ on purpose, and a caller optimizing through the simulator should validate the result under Self::simulation.

Source

pub fn mujoco_compat() -> Self

Self::simulation with Self::mujoco_compat set — a test-only oracle preset for cross-validating trajectories against MuJoCo.

Sited alongside Self::gradients because it is the same kind of thing: a named point in config space that trades one property away on purpose. gradients trades fidelity for smoothness; this one trades exact stiction for bit-comparability with a reference implementation. Unlike gradients, it is not a preset anyone should ship with — see the field docs for the creep it buys back.

Source

pub fn gpu_equivalent() -> Self

The exact problem, operator and schedule the GPU contact pass runs.

This is the CPU’s model of the GPU: same convex problem, same staged Coulomb update, same solref bias and impedance regularizer, but the block-diagonal Delassus operator, no Newton stage, and a fixed sweep budget instead of a residual tolerance. Nothing here is a different contact model — it is the same model under a documented restriction.

It is the referee for GPU parity. A gap between this and the GPU is an implementation bug; a gap between this and Self::simulation is the price of the restriction. The two must be measured separately or neither number means anything.

tolerance is zero so the sweep budget always runs to completion: the shader has no early exit (a workgroup cannot cheaply agree that every contact has converged), so an early-exiting reference would drift from it on exactly the easy steps where the GPU keeps sweeping. converged is therefore false here by construction, which is honest — a fixed-budget iterate is not a KKT point and must not anchor an IFT gradient.

Trait Implementations§

Source§

impl Clone for ContactSolverConfig

Source§

fn clone(&self) -> ContactSolverConfig

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ContactSolverConfig

Source§

impl Debug for ContactSolverConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for ContactSolverConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.