From 43cde9716ccd43e13d9815d5bacf772278535efa Mon Sep 17 00:00:00 2001 From: Kevin Zakka Date: Wed, 25 Feb 2026 13:59:33 -0800 Subject: [PATCH] Fix mj_sensorAcc returning zero after mj_step1 by clearing flg_rnepost in mj_step2. Fixes #3133. --- src/engine/engine_forward.c | 1 + test/engine/engine_sensor_test.cc | 35 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/engine/engine_forward.c b/src/engine/engine_forward.c index f2a7c3c4..f294f69e 100644 --- a/src/engine/engine_forward.c +++ b/src/engine/engine_forward.c @@ -1530,6 +1530,7 @@ void mj_step2(const mjModel* m, mjData* d) { mj_fwdActuation(m, d); mj_fwdAcceleration(m, d); mj_fwdConstraint(m, d); + d->flg_rnepost = 0; // clear flag for lazy evaluation mj_sensorAcc(m, d); mj_checkAcc(m, d); diff --git a/test/engine/engine_sensor_test.cc b/test/engine/engine_sensor_test.cc index 498ec4a2..135789c2 100644 --- a/test/engine/engine_sensor_test.cc +++ b/test/engine/engine_sensor_test.cc @@ -1591,5 +1591,40 @@ TEST_F(SensorTest, ReadSensor) { mj_deleteModel(model); } +// mj_sensorAcc returns correct accelerometer after mj_step1 (issue #3133) +TEST_F(SensorTest, AccelerometerAfterStep1) { + constexpr char xml[] = R"( + + + + + + + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + mjData* data = mj_makeData(model); + + // settle the simulation with split-step loop + for (int i = 0; i < 100; i++) { + mj_step1(model, data); + mj_step2(model, data); + } + + // call mj_step1 + mj_sensorAcc, expect gravity reading (~9.81 m/s^2) + mj_step1(model, data); + mj_sensorAcc(model, data); + EXPECT_NEAR(data->sensordata[2], 9.81, 1e-2); + + mj_deleteData(data); + mj_deleteModel(model); +} + } // namespace } // namespace mujoco