Skip to content

Friction

Steel uses the isotropic , not a pyramid, and solves both tangent directions of a contact together on their 2×2 block AttA_{tt} at the contact’s current normal impulse. If the unconstrained (“stick”) solution lies inside the disk of radius ρ=μλn\rho = \mu\lambda_n, the contact sticks. If not, scaling it back onto the circle is wrong whenever AttA_{tt} is anisotropic, which it almost always is for an articulated finger. Steel solves the trust-region problem

min⁡∥x∥≤ρ 12x⊤Attx−b⊤x⇒(Att+αI) x=b,  ∥x∥=ρ,  α≥0,\min_{\|x\|\le\rho}\ \tfrac12 x^\top A_{tt}x - b^\top x \quad\Rightarrow\quad (A_{tt} + \alpha I)\,x = b,\ \ \|x\| = \rho,\ \ \alpha \ge 0,

with up to eight safeguarded Newton steps on α\alpha and a bisection fallback. An impulse that already satisfies the optimality conditions is kept unchanged, so a converged sweep can be exactly stationary.

Demo 2Where the sliding impulse lands
stick solution (drag it)radial projectionconstrained minimum

A box on a table has four contact points, three rows each, acting on six degrees of freedom. The solver can shift load between corners from step to step without changing the motion, and with per-point friction the friction budget moves with the load, so a held object creeps. By default (friction_anchor_beta=None, which selects 0.2) Steel separates the friction budget from how load is distributed:

  • Contacts of one body pair form a region when their normals agree within about six degrees, their friction coefficients match, their contact planes are close and the shapes touch. Every contact keeps its own normal row, so support and tipping are unchanged.
  • Friction moves to at most two anchors at the ends of the region’s principal axis, which share the region’s pooled normal load.
  • Each anchor carries its tangential displacement across steps, from the SE(3) logarithm of both bodies’ pose increments, and its rows add β d/h\beta\,d/h so static friction holds position, not just zero velocity.
  • History is matched by body pair and geometry, independently of the collision pipeline’s contact matching. An anchor is released when its region unloads, or when it is within 5% of the cone and slipping against it.

Figure 5Rows of a box resting on a table. Blue arrows are the four normal rows, one per contact. With patch friction the region's friction acts at two anchors (green spheres) at the ends of the footprint's long axis, each with two tangent rows; with point friction every contact carries its own tangent pair. Drag to orbit.
Figure 6Pushing a box sideways.

Turn the push and change its size. Each friction location solves the coupled disk update of the friction demo, after enough Gauss-Seidel sweeps to converge; the dashed circles are each location’s friction disk. Below, what Steel measured on a box near its friction limit: point friction creeps, the anchors hold. Tutorial: Patch friction vs point friction · Friction combine modes · Global friction scale

Set friction_anchor_beta=0 for point friction: two coupled tangent rows per contact. It is cheaper where nothing is held. Call reset after teleporting a body to discard its history.

Friction modes. friction_mode is experimental, and every mode other than the default uses point friction. "fixed_normal" (default) is the disk solve above at the contact’s current normal impulse. "coulomb_newton" solves each free-body contact’s cone exactly, normal and tangent together. Under the immediate response articulated contacts keep the "fixed_normal" update; solve_mode="colored" puts articulated contacts on propagation rows with the selected mode, except contacts between two links of one articulation, which stay on dense rows with the articulated update. "bisection" and "bisection_desaxce" search the normal impulse, but each probe scales the stick impulse radially onto the disk, the projection ruled out above for an anisotropic AttA_{tt}. Near the friction limit that converges to a slipping answer, and more iterations do not change it: a box at 97% of its limit slides away under both, while "fixed_normal" and "coulomb_newton" hold it. A fix is in review in skild-ai/newton#26. Until it lands, use "fixed_normal", or "coulomb_newton" for free bodies near the friction limit.

Spin friction about the normal is opt-in per shape with steel:min_torsional_patch_radius rr, imported from PhysX’s physxCollision:minTorsionalPatchRadius. Sliding and spin share one Coulomb budget, ∣τn∣≤r(μN−sliding)|\tau_n| \le r(\mu N - \text{sliding}). The radius is an effective footprint: 2R/32R/3 for a uniformly loaded disk of radius RR. On the integration branch, free-body contacts also take MuJoCo’s condim convention through steel:condim: 4 adds a spin row and 6 adds a rolling pair. The MJCF importer reads a geom’s friction triple but not its condim into steel:condim, so set the attribute after import or author newton:steel:condim in USD; a change that reads MJCF condim is in review in skild-ai/newton#22.

Figure 7Spin and rolling friction.

At a sphere–plane point contact, sliding friction cannot oppose spin about the contact normal; it changes rolling while the contact slips, but adds no rolling resistance once the ball rolls without slipping. Spin and rolling rows add those resistances. The curves are Steel runs from the tutorials. Tutorial: Torsional friction on articulated bodies · Spin and rolling friction