google-deepmind / google-deepmind/mujoco

Discrete actuator derivative indexes control limits by actuator ordinal

Open
#3,598 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 order invariance for the discrete integrator with variable-width actuator inputs. The effective-metric derivative reads the target control from its control-block address but checks its limits using the actuator ordinal.

### 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
- Normal GCC 11.5.0 build and GCC 13.3.0 AddressSanitizer build

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

`actuatorInput` correctly reads `d->ctrl[m->actuator_ctrladr[i]]`, but then uses `m->actuator_ctrllimited[i]` and `m->actuator_ctrlrange[2*i]`. Those metadata arrays are indexed by packed control slot. I expected inserting or moving a physically inactive variable-width actuator to leave the target actuator's force derivative and next state unchanged.

The first reproducer builds the same three-input zero-force PID and limited affine actuator in opposite orders. With an in-range target control, both steps agree. With raw control `100`, the forward path clamps both target forces to `0.5`, but only the target-first derivative uses the clamped input:

```text
control=1 target-first adr=0 qvel=0.0049995000499950008 force=0.5
control=1 target-second adr=3 qvel=0.0049995000499950008 force=0.5
control=1 velocity-delta=0
control=100 target-first adr=0 qvel=0.0049995000499950008 force=0.5
control=100 target-second adr=3 qvel=0.0049504950495049506 force=0.5
control=100 velocity-delta=-4.9005000490050243e-05
```

The second reproducer places a zero-input DC motor before the target. A whole-library AddressSanitizer build reports:

```text
ERROR: AddressSanitizer: use-after-poison
READ of size 1
#0 actuatorInput ... src/engine/engine_derivative.c:2415
#1 actuatorLenDeriv ... src/engine/engine_derivative.c:2495
#2 mjd_effActuation ... src/engine/engine_derivative.c:4088
```

Relevant source:

- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/user/user_model.cc#L3852-L3861
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/engine/engine_derivative.c#L2404-L2427
- https://github.com/google-deepmind/mujoco/blob/10124d5d9dca411ec3c8988aa1e3b619103d71bb/src/engine/engine_derivative.c#L4072-L4104

### Steps for reproduction

1. Build the affected revision normally and run `poc/order_invariance.cc` with the commands in `poc/README.md`.
2. Observe equal forces but different velocities only when the target is clamped and follows the three-input actuator.
3. Build MuJoCo and `poc/zero_input.cc` with AddressSanitizer.
4. Observe the invalid metadata read in `actuatorInput`.

Reproduction package:

[discrete-integrator-control-limit-indexing-poc.zip](https://github.com/user-attachments/files/32260545/discrete-integrator-control-limit-indexing-poc.zip)

### Minimal model for reproduction

Both complete asset-free MJCF models are embedded in the C++ programs. The order test includes a physically zero dummy actuator as the metamorphic control.

### Code required for reproduction

See `poc/order_invariance.cc` and `poc/zero_input.cc`. The attached `fix.patch` uses the resolved control address consistently and adds an order-invariance regression. The focused regression and all 142 `engine_forward_test` cases pass; single-precision and repository-wide CI remain pending.

### 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

Start with actuator metadata construction in src/user/user_model.cc and the actuatorInput and mjd_effActuation paths in src/engine/engine_derivative.c. Run poc/order_invariance.cc and poc/zero_input.cc using the commands in poc/README.md, then compare with the focused engine_forward_test regression. Done means the order-invariance case agrees, the AddressSanitizer metadata read is absent, and the reported test cases still pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
robotics
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.