#3598·mujoco

Discrete actuator derivative indexes control limits by actuator ordinal

Author: peachtree0222Created Sep 15, 2026Updated Sep 15, 2026
Labelsbug

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:

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:

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:

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

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