Porting from PhysX
Most PhysX scenes move to Steel through Newton’s USD importer without code changes, but a few defaults and conventions differ. Port in small, verifiable steps: prove the old setup still reproduces, switch the solver behind one flag, then compare behavior before you compare speed.
Attribute mapping
Section titled “Attribute mapping”What Newton’s importer reads from PhysX USD, and where Steel uses it.
| PhysX USD attribute | Newton / Steel | Notes |
|---|---|---|
physx |
steel: |
Free bodies and floating bases; default 0.05 as in PhysX. |
physx |
steel: |
Same bodies; default 0. |
physx |
steel: |
m/s. Enforced as free-body rows, which take free-body capacity. |
physx |
steel: |
Converted from deg/s to rad/s on import. |
physx |
steel: |
Bounds the contact correction velocity of free bodies. |
physx |
body gravity flag | Steel honors per-body gravity disable. |
physx, rest |
Shape, margin |
gap = contactOffset − restOffset. The gap decides which speculative contacts Steel sees. |
physx |
steel: |
Turns on contact torsion. torsional (depth scaling) is not used. |
physx |
Model. |
|
physx |
Model. |
Enforced only with enable_. |
physx |
not read | Author newton: and set enable_; the rows interact with drives differently from PhysX. |
Drive stiffness, damping, max force (Usd drive) |
joint_, joint_, joint_ |
Check angular gain units after import, and that gains are applied once (see below). |
| Joint limits | joint_, joint_ |
Imported, but enforced only with enable_. |
physx |
articulation self-collision | |
physx, Damping |
shape ke, kd |
Not used by Steel; its contacts are hard. Hydroelastic contacts with contact_ are the soft-contact route. |
| Material friction and restitution combine modes | friction_, restitution_ |
Solver options, not read from USD; integration branch only. Newton 1.8 averages. |
Solver option equivalents
Section titled “Solver option equivalents”| PhysX | Steel | Notes |
|---|---|---|
| Position iteration count | iterations |
Steel counts sweeps per substep; it does not read the scene’s iteration attributes. |
| Velocity iteration count | velocity_ |
Sweeps without position bias after the position solve. |
| Simulation frequency, substeps | your dt and substep loop |
Steel steps whatever dt you pass. |
| Articulation force drives solved with contacts | drive_, row_ |
Rows follow the PhysX articulation drive update and clamp at the effort limit. The default implicit drives are stiffer-stable but do not bound the implicit reaction. |
| Contact applied at one point | contact_ |
Applies rows at the witness midpoint. |
| Bounce threshold | restitution_ |
Steel uses the closing speed at the start of the step. |
| GPU contact and patch buffer sizes | rigid_, row capacities |
Separate capacities; each has its own overflow report. |
| Enhanced determinism | deterministic= + deterministic pipeline |
See Determinism. |
What differs
Section titled “What differs”- Joint limits and velocity limits are off by default. Turn on
enable_joint_limitsand, if the task relies on them,enable_joint_velocity_limits. - The state is joint coordinates. Resets must write
joint_q/joint_qd; poses written only to body arrays are lost. - Contacts are hard. Contact stiffness and damping do not apply; penetration is corrected through
baumgarte, and speculative contacts follow the shape gap. - Implicit drives. The default drive is integrated in the mass matrix and its reaction can exceed the effort limit under load. Use
drive_mode="rows"where torque limits matter. - Joint friction is opt-in and follows a different interaction with drives; the load-proportional term matches PhysX before 5.6.
- Ordering and conventions. Body and joint traversal order can differ from PhysX views; quaternion component order differs between APIs (xyzw in Newton arrays). Compare by name, not by index.
- Capacities are fixed per world and overflow drops rows. Read
check_constraint_capacity()and watermarks; a run that drops rows is not a valid comparison even if it exits cleanly.
Migration procedure
Section titled “Migration procedure”- Freeze a baseline. Pin every version (application, assets, checkpoints, dependencies) and keep the original PhysX setup runnable in its own environment. Record a deterministic trace of observations, actions, targets, torques, body and joint state, contacts, rewards and terminations, keyed by body and joint names.
- Check parity before switching solvers. If you upgrade the surrounding stack at the same time, first show the upgraded stack with PhysX reproduces the frozen trace: reset state, first observation and action, joint order, asset import, quaternion convention and actuation. Do not attribute differences to Steel until this passes.
- Switch the backend behind one flag. Same task, same assets. Smoke-test import, reset, zero-action stepping, controls, contacts and any force sensors before running a policy.
- Compare deterministic traces without randomization. Align by name. Audit actuation first: gains applied exactly once, effort limits, drive model. Re-apply external wrenches on every substep if your loop clears forces per substep. Then contacts, materials, limits and capacities.
- Add domain randomization one factor at a time (below), comparing distributions and per-sample deltas, not just mean return.
- Compare performance last, on the same GPU, task, trajectory or policy, randomization and timing protocol: warm up, capture CUDA graphs, synchronize around the timer, exclude construction and kernel compilation. Record throughput, memory, retained contacts and row high-water marks, and reject any run that reported dropped rows or contacts.
- Check policy transfer both ways. Evaluate policies trained on each solver under both solvers (a 2×2 matrix) and report completion and termination reasons alongside reward.
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.