Speed caps
Basics
Gold bodies have a fall-speed cap, a spin cap and spin damping.
steel preset (the default), recordedon an NVIDIA RTX PRO 6000 Blackwell.Run it
cd examples# the default preset (steel), then the othersuv run shelf play body_limits# change solver settings liveuv run shelf tune body_limitsSource: examples/shelf/00_basics/body_limits/ · ported from steel-webgpu tools/scenes.py body_limits() @ ad03e49
Presets
| Preset | Solver | Status | Checked |
|---|---|---|---|
steeldefault | steel | works | 2026-11-10, newton f6fc82a8b, NVIDIA RTX PRO 6000 Blackwell Server Edition |
xpbd | xpbd | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
vbd | vbd | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
mujoco | mujoco | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
featherstone | featherstone | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
semi_implicit | semi_implicit | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
feather_pgs | feather_pgs | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
kamino | kamino | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
implicit_mpm | implicit_mpm | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
style3d | style3d | unsupported | the gold bodies use Steel's steel:rigid_body_* attributes |
Solvers with no row are untested on this example. The full settings are inpresets.toml.
Code
# SPDX-FileCopyrightText: Copyright (c) 2026 Skild AI and the Steel contributors# SPDX-License-Identifier: Apache-2.0# Direct source: steel-webgpu; see presets.toml and THIRD_PARTY.md.# Modified for Steel Shelf: preset-driven execution and shared runner integration.
############################################################################ Example Speed caps## Steel's per-body attributes: max linear velocity, max angular velocity and angular damping.## Ported from steel-webgpu's tools/scenes.py (body_limits); the scene builds# as it does there and the shelf's preset drives the solver.## Command: python -m shelf run body_limits############################################################################
import math
import numpy as npimport warp as wp
import newtonimport newton.examplesfrom common.steel_scenes import BLUE, GOLD, GREY, RED, TEAL, SceneExample, cfg, tf
class Example(SceneExample): file = __file__ camera = {'eye': (0.0, -2.0, 1.0), 'target': (0.0, 0.0, 0.3)}
def build(self): """Steel's per-body attributes: max linear velocity, max angular velocity and angular damping.""" b = newton.ModelBuilder() newton.solvers.SolverSteel.register_custom_attributes(b) b.add_ground_plane(cfg=cfg(mu=0.0)) twists = {} rows = ( ("max linear velocity 1 m/s", {"steel:rigid_body_max_linear_velocity": 1.0}, (0.0, 0.0, 0.0, 0.0, 0.0, 0.0), 1.6), ("max angular velocity 5 rad/s", {"steel:rigid_body_max_angular_velocity": 5.0}, (0.0, 0.0, 0.0, 0.0, 0.0, 30.0), 0.3), ("angular damping 2 /s", {"steel:rigid_body_angular_damping": 2.0}, (0.0, 0.0, 0.0, 0.0, 0.0, 30.0), 0.3), ) for i, (_, custom, tw, z) in enumerate(rows): for k, limited in enumerate((False, True)): body = b.add_body(xform=tf((-0.4 + 0.4 * i, -0.15 + 0.3 * k, z)), custom_attributes=custom if limited else None) b.add_shape_box(body, hx=0.05, hy=0.05, hz=0.05, cfg=cfg(density=500, mu=0.0), color=[GREY, GOLD][k]) twists[body] = tw return b, twists, "Per-body limits (gold vs grey): a 1 m/s fall cap, a 5 rad/s spin cap and 2 /s angular damping on frictionless spinners."
def check(self): """At the end of the test run (100 frames): the twists reached the spinners and each gold limit acts.""" w = np.abs(self.state_0.body_qd.numpy()[:, 5]) # bodies: (grey, gold) per row; rows: fall cap, spin cap, angular damping assert w[2] > 25.0 and w[4] > 25.0, f"the grey spinners lost their 30 rad/s twist: {w[[2, 4]]}" assert 4.0 < w[3] <= 5.05, f"the spin-capped box spins at {w[3]:.3f} rad/s, not at its 5 rad/s cap" assert w[5] < 0.1 * w[4], f"the damped spinner still spins at {w[5]:.3f} rad/s"
if __name__ == "__main__": parser = Example.create_parser() viewer, args = newton.examples.init(parser) newton.examples.run(Example(viewer, args), args)example = "body_limits"source = "steel-webgpu tools/scenes.py body_limits() @ ad03e49"default = "steel"
[check]# Arguments `python -m shelf check` passes in test mode.args = []
[gallery]short = "Gold bodies have a fall-speed cap, a spin cap and spin damping."title = "Speed caps"frame = 90
[xpbd]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[vbd]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[mujoco]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[featherstone]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[semi_implicit]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[feather_pgs]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[steel]status = "works"# 1 substep x 2 iterations, immediate response: the gold caps act exactly as with 16 x 32 (fall capped at 1.000 m/s,# spin at 4.996 rad/s; the damped spinner decays as w *= 1 - 2 dt per step, 3.92 rad/s after 1 s vs 4.05 at 16# substeps) and every box lands and rests (0.3 mm peak penetration). 1 x 1 rests 0.7 mm deep. Free bodies only, so# the immediate response (0.30 ms) does what propagation_colored did (0.39 ms); no joint has limits, so they are off.# The port's 4 x 12 colored with limits: 2.43 ms.sim = { fps = 60, substeps = 1 }solver = { solve_mode = "matrix_free", iterations = 2, articulated_contact_response = "immediate", enable_joint_limits = false }checked = "2026-11-10, newton f6fc82a8b, NVIDIA RTX PRO 6000 Blackwell Server Edition"
[kamino]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[implicit_mpm]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"
[style3d]status = "unsupported"reason = "the gold bodies use Steel's steel:rigid_body_* attributes"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.