google-deepmind / google-deepmind/mujoco

Delayed multi-input actuators use uninitialized control slots

Open
#3,597 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C++
Stars
15.2k
Forks
1.8k
Avg merge
10d 16h
Merged PRs (30d)
25

Description

### Intro

Hi!

I am testing the interaction between current multi-input actuators and actuator history/delay. The control-history path remains scalar and leaves the remaining inputs of a delayed actuator uninitialized.

### My setup

- MuJoCo source build from `main` at `10124d5d9dca411ec3c8988aa1e3b619103d71bb`
- C API, double precision
- Ubuntu 24.04.5 LTS, Linux 7.0.0-28-generic x86_64
- CMake 3.28.3 and GCC 11.5.0

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

A PID actuator with `input="pos vel ff"` owns three control values. With live controls `[1, 2, 3]`, its force is `6`. I expected the delayed path to record and later use the same complete control block.

Actuator history allocation, insertion, `mj_readCtrl`, and `mj_initCtrlHistory` are hard-coded to dimension one. During actuation, a local array of all `nu` controls is allocated, but a delayed actuator assigns only `ctrl[adr]`. The remaining two slots are consumed by the PID gain without initialization.

The minimal reproduction reuses MuJoCo's stack allocation with canaries so the omitted slots are deterministic:

```text
nu=3 delayed-force=501.0 direct-force=6.0
```

The delayed path uses the recorded first input `1` plus stale stack values `200` and `300`. Disabling only delay uses the live complete block and produces `6`.

Relevant source and documentation:

- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/user/user_model.cc#L2213-L2224
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/user/user_model.cc#L3863-L3872
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/engine/engine_forward.c#L386-L400
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/engine/engine_forward.c#L1344-L1360
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/engine/engine_support.c#L934-L1013

### Steps for reproduction

1. Check out and build the commit above.
2. Compile `poc/reproducer.cc` using `poc/README.md`.
3. Run it and compare delayed force with the direct-control causal control.

Reproduction package:

[multi-input-actuator-delay-history-poc.zip](https://github.com/user-attachments/files/32260502/multi-input-actuator-delay-history-poc.zip)

### Minimal model for reproduction

The complete MJCF is embedded in the C++ file and contains one slider, one sphere, and one delayed three-input PID. No assets are required.

### Code required for reproduction

See `poc/reproducer.cc`. A complete patch needs a block-aware history layout and API decision, so I have included a fix design rather than a partial one-line change.

### Confirmations

- [x] I searched the [latest documentation](https://mujoco.readthedocs.io/en/latest/overview.html) thoroughly before posting.
- [x] I searched previous [Issues](https://github.com/google-deepmind/mujoco/issues) and [Discussions](https://github.com/google-deepmind/mujoco/discussions), I am certain this has not been raised before.

Contributor guide

Open the contributing guide

Research direction

Compile and run poc/reproducer.cc using poc/README.md to confirm the delayed and direct force values. Then trace the history allocation, insertion, mj_readCtrl, and mj_initCtrlHistory paths in src/user/user_model.cc and src/engine/engine_support.c, along with delayed actuation in src/engine/engine_forward.c. Done means a delayed multi-input actuator preserves its complete control block and the history API decision is resolved.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
robotics
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.