For a MuJoCo checkpoint that should reproduce the next simulation step, save the integration-state components used by the model, not only joint positions and velocities. Keep the state signature, compiled model, engine version and application-side inputs together. A pose that looks correct in a viewer can still resume with different actuator state, controls or solver history.
This guide examines the C engine documentation for MuJoCo 3.15.0. It is a source-based checkpoint audit; no model, snapshot or numerical comparison was executed for this article. A state vector is meaningful only with the model and state-component selection that produced it.
Capture inputs at one stepping boundary
The 3.15.0 state-and-control documentation groups positions, velocities, actuator activation and history separately from time, plugin state, user inputs and warmstart accelerations. Its mjSTATE_INTEGRATION selection covers the documented inputs to forward dynamics. The state helpers mj_stateSize, mj_getState and mj_setState use a declared bitfield to size, retrieve and restore a vector.
Choose a definite save point, such as immediately before the next step after controls have been assigned. Write that boundary in the checkpoint record. Saving joint state before updating a control buffer and saving that buffer afterward creates a snapshot assembled from two different moments. A timestamp on the file does not repair that mismatch.
For an illustrative failure, suppose the saved run had ctrl[0] = 0.4 immediately before stepping. A new data instance is reset, then only qpos and qvel are restored; with no subsequent controller write, its control remains 0.0. The displayed pose can match while the next actuator input differs. These are invented input values, not a simulated result or a recommended control magnitude. Compare the actual control buffers at the stepping boundary before blaming numerical drift.
Use the following as an audit worksheet, not as a replacement for the version’s state enum. A field absent from a particular model can be marked unused with a reason; an unknown field should not silently become zero.
| Checkpoint layer | Examples to inspect | Question for the record |
|---|---|---|
| Integrated physical state | qpos, qvel, act, history | Were stateful actuators or delayed samples in use? |
| Time and plugin state | time, plugin_state | What selects the next control or plugin update? |
| User-supplied inputs | ctrl, applied forces, mocap poses, equality toggles | Which input values were active at the save boundary? |
| Numerical continuation | qacc_warmstart | Is the requested comparison sensitive to exact numerical continuation? |
Compare the next step before a long rollout
The reproducibility notes specifically identify warmstart accelerations when bitwise equality is required. They limit exact reproducibility to one engine version and architecture. Small differences can grow during a contact-rich rollout, so a later trajectory mismatch is a poor first clue to which checkpoint component was omitted.
Plan a comparison that starts with one step from the recorded boundary. Retain the source and restored vectors, the state signature and the next assigned controls. Compare each component in its own units and representation before summarizing the result. Do not interpret a single tolerance across positions, velocities and activation variables as a universal accuracy specification.
If the first step disagrees, keep the evidence small. First compare the saved components and their dimensions. Then check which input was overwritten between restoration and stepping. Only after those agree should the investigation move to model settings or longer-horizon sensitivity. A successful pose restoration is useful evidence, but it does not complete this sequence.
Keep model and callback state beside the vector
A checkpoint file should identify the model artifact, compiler options, engine version, state signature and save boundary. Record the integrator, timestep and relevant solver settings rather than relying on whichever defaults the next machine provides. The 3.15.0 documentation warns that fully retaining sleeping elements requires copying the entire mjData. Standard state saving and loading remains valid, but implicitly wakes sleeping islands. Separate that requirement from a compact integration-state snapshot.
Application bookkeeping needs a separate inventory. A controller’s trajectory index, random-number generator or external callback memory may live outside the serialized vector. Mark where each item is stored and how it is restored. Merely giving the state file a new name cannot establish that those producers will supply the same next input.
For the broader distinction between restoring a scene and validating an episode, see Isaac Lab demonstration replay. The checkpoint job here is narrower: identify the exact C-engine continuation state and the inputs surrounding its next step. Start with that record, then extend the replay only after the first-step comparison has a clear explanation.
Version-pinned documentation checked October 14, 2026. No MuJoCo model, checkpoint restoration or numerical rollout was executed for this article.