google-deepmind / google-deepmind/mujoco_warp

reset_data leaves selected-world derived dynamics and island state stale

Open
#1,671 1 comment 0 reactions 1 assignee Claimed by @thowell View on GitHub
Dominant language
Python
Stars
1.5k
Forks
217
Avg merge
2d 11h
Merged PRs (30d)
48

Description

### Intro

Hi! I found that `reset_data` can publish a selected world with reset primary state but derived dynamics and island metadata from the preceding simulation epoch. The affected component is `google-deepmind/mujoco_warp`.

### My setup

- API: exported Python `put_model`, `make_data`, `forward`, and `reset_data`
- MuJoCo Warp: 3.13.0, tested `main` commit `d8a241ef1643295ebb85bfdfdf9171360bfb2c0e` on 2026-09-12
- MuJoCo: 3.13.0
- NVIDIA Warp: 1.17.0
- Python: 3.12.13
- OS: Linux 7.0.0-28-generic, x86_64, glibc 2.39
- GPU: NVIDIA GeForce RTX 5060 Ti; driver 595.84

### What's happening? What did you expect?

After `forward`, I call `reset_data(model, data, [True, False])`. Expected: the selected world is internally consistent with a freshly reset MuJoCo data object while the unselected world is preserved. Actual: the selected `qpos` and `nefc` reset, but multiple derived arrays remain exactly equal to their prior-epoch values. `nisland` also remains one even though `nefc` becomes zero.

```text
selected_before {'qpos_z': 0.0799999982, 'nefc': 4, 'nisland': 1, 'xpos': 0.0799999982, 'subtree_com': 0.0799999982, 'qfrc_bias': 9.8100004, 'qfrc_smooth': 9.8100004, 'qacc_smooth': 9.8100004, 'qfrc_constraint': 59.3195190}
selected_after {'qpos_z': 0.0500000007, 'nefc': 0, 'nisland': 1, 'xpos': 0.0799999982, 'subtree_com': 0.0799999982, 'qfrc_bias': 9.8100004, 'qfrc_smooth': 9.8100004, 'qacc_smooth': 9.8100004, 'qfrc_constraint': 59.3195190}
native_after {'qpos_z': 0.05, 'nefc': 0, 'nisland': 0, 'xpos': 0.05, 'subtree_com': 0.05, 'qfrc_bias': 0.0, 'qfrc_smooth': 0.0, 'qacc_smooth': 0.0, 'qfrc_constraint': 0.0}
stale_fields=['xpos', 'subtree_com', 'qfrc_bias', 'qfrc_smooth', 'qacc_smooth', 'qfrc_constraint']
PRIMARY_STATE_RESET=True
ISLAND_METADATA_INCONSISTENT=True
UNSELECTED_WORLD_PRESERVED=True
BUG_REPRODUCED=True
```

The native control starts from the same non-default `qpos`, calls `mj_forward`, then `mj_resetData`. MuJoCo clears its data buffer, restores defaults, resets island sizes, and performs the sleep-related initialization required by the model. MuJoCo Warp's `reset_nworld` resets only a bounded list of primary arrays and counters; it has no corresponding cleanup for the demonstrated output and island fields.

Source: https://github.com/google-deepmind/mujoco_warp/blob/d8a241ef1643295ebb85bfdfdf9171360bfb2c0e/mujoco_warp/_src/io.py#L2410-L2773

Native control: https://github.com/google-deepmind/mujoco/blob/main/src/engine/engine_io.c#L1340-L1670

This is observable immediately after reset. A later complete `forward` recomputes the representative arrays, so I am not claiming persistence after that recomputation. The defect affects full reset too; the two-world selective case supplies an untouched-world control.

This is distinct from the packed-contact bug addressed by PR #1665. The contact issue concerns the shared packed prefix; this report concerns ordinary per-world derived/output arrays and island counts that are never reset.

### Steps for reproduction

1. Clone MuJoCo Warp and check out `d8a241ef1643295ebb85bfdfdf9171360bfb2c0e`.
2. Extract the attached PoC beside the checkout as `reset-data-stale-derived-state-poc/`.
3. From the checkout, run `PYTHONPATH=$PWD python ../reset-data-stale-derived-state-poc/poc/repro.py` in a CUDA environment.
4. Confirm that the output ends with all four booleans true, including `BUG_REPRODUCED=True`.

Reproduction package:

[reset-data-stale-derived-state-poc.zip](https://github.com/user-attachments/files/32205206/reset-data-stale-derived-state-poc.zip)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.