Skip to content

Tutorials

One short script per Steel feature. Each replay is a recording of that exact script on a GPU, played back in 3D. Where a tutorial compares settings, the variants run side by side with one option changed. The scripts are intutorials/; run one withcd tutorials && python 01_hello_steel.py.

Getting started

Contact and friction

Impacts and penetration

Compliance and adhesion

Convergence

Joints and drives

Mimic joints and loop closures

Bodies

Solver and runtime

Coupling

Domain randomization

Planned tutorials

Steel supports these features, and tutorials for them are still to be written or recorded.

  • USD import of Steel attributesReading physxRigidBody:* and newton:steel:* attributes from USD works through add_usd; the recording environment has no USD runtime, so this tutorial is still to be recorded.
  • MuJoCo equality constraintsEnabled MJCF equality constraints that the importer converts to loop joints or mimic rows.
  • State edits with carried kinematicsnotify_state_changed after writing joint_q, joint_qd or body_q outside step when reuse_kinematics is on.
  • CPU deviceThe world-serial portable kernels, and which features stay CUDA only.

Domain randomization: not covered yet

Needs a new solver (rebuild instead of notify)

  • Turning a solver feature on or off. Options such as enable_joint_friction, enable_joint_velocity_limits, enable_joint_limits, friction_combine, restitution_combine, drive_mode and the row capacities are fixed when SolverSteel is constructed. Randomize the values those features read, not whether the features exist.
  • Restitution with sparse mass factors. A solver that uses sparse mass factors raises ValueError when a shape notification gives a shape positive restitution. Construct the solver with the restitution you will need.
  • Making a kinematic body dynamic. A kinematic free body that was removed from the dynamics at construction cannot become dynamic again.

Not shown or not yet validated

  • Collision geometry and offsets. Shape scale, transforms, contact margin and gap are covered by SHAPE_PROPERTIES, but randomizing them changes contact generation and is not demonstrated here.
  • Swapping shapes between variants (Model.select_body_variants, SHAPE_TYPE_AND_SOURCE) is experimental and is meant for resets, not every step.
  • Per-world friction on a shared ground plane. A ground plane added to the global world is one shape with one coefficient. Give each world its own floor shape instead (see the terrain friction tutorial).
  • Contact stiffness and damping (shape_material_ke, shape_material_kd): Steel's default rigid-contact rows are constraints and do not read these arrays, so randomizing them has no effect there. The experimental opt-in contact_compliance route for hydroelastic contacts has its own stiffness and damping inputs and is not covered here.
  • CUDA graph capture of every notification. Joint, joint DOF, body inertial and shape notifications can be captured. Body (kinematic flag) notifications, sleeping, and shape notifications on a solver with sparse mass factors and restitution enabled read data on the host and must run outside capture. A captured notification also skips the eager validation of joint friction and rolling or torsional friction coefficients; notify eagerly to get those checks.

Outside the solver

  • Actuator latency and delays, observation noise and action noise belong in the environment or actuator model that feeds Control, not in the physics solver.
  • Explicit (framework-side) actuator models keep their own gains; randomize those in the actuator model, because the simulator's drive gains are usually zero in that setup.

Not supported by Steel yet: tendons through native routes, ROD joints, particles and soft bodies (Steel simulates rigid bodies and articulations; couple it with another solver for those), gradients, mimic joints across articulations, and loop closures between two dynamic articulations, and limits on a root DISTANCE joint (Steel simulates it as a free joint and ignores its minimum and maximum distance; use a ball joint and a limited prismatic joint, as in the tether tutorial).