diff --git a/src/engine/engine_forward.c b/src/engine/engine_forward.c index 996741d2..a3388d83 100644 --- a/src/engine/engine_forward.c +++ b/src/engine/engine_forward.c @@ -760,7 +760,7 @@ void mj_forwardSkip(const mjModel* m, mjData* d, int skipstage, int skipsensor) } // acceleration-dependent - if (mjcb_control) { + if (mjcb_control && !mjDISABLED(mjDSBL_ACTUATION)) { mjcb_control(m, d); } mj_fwdActuation(m, d); diff --git a/test/engine/engine_forward_test.cc b/test/engine/engine_forward_test.cc index fb83d2f4..dd651d70 100644 --- a/test/engine/engine_forward_test.cc +++ b/test/engine/engine_forward_test.cc @@ -15,6 +15,7 @@ // Tests for engine/engine_forward.c. #include "src/engine/engine_forward.h" +#include #include #include @@ -22,6 +23,7 @@ #include #include #include "src/cc/array_safety.h" +#include "src/engine/engine_callback.h" #include "src/engine/engine_io.h" #include "test/fixture.h" @@ -274,8 +276,6 @@ TEST_F(ImplicitIntegratorTest, EnergyConservation) { mj_deleteModel(model); } -// --------------------------- control clamping -------------------------------- - TEST_F(ForwardTest, ControlClamping) { static constexpr char xml[] = R"( @@ -344,5 +344,48 @@ TEST_F(ForwardTest, ControlClamping) { mj_deleteModel(model); } +void control_callback(const mjModel* m, mjData *d) { + d->ctrl[0] = 2; +} + +TEST_F(ForwardTest, MjcbControlDisabled) { + static constexpr char xml[] = R"( + + + + + + + + + + + + )"; + mjModel* model = LoadModelFromString(xml); + mjData* data = mj_makeData(model); + + // install global control callback + mjcb_control = control_callback; + + // call forward + mj_forward(model, data); + // expect that callback was used + EXPECT_EQ(data->ctrl[0], 2.0); + + // reset, disable actuation, call forward + mj_resetData(model, data); + model->opt.disableflags |= mjDSBL_ACTUATION; + mj_forward(model, data); + // expect that callback was not used + EXPECT_EQ(data->ctrl[0], 0.0); + + // remove global control callback + mjcb_control = nullptr; + + mj_deleteData(data); + mj_deleteModel(model); +} + } // namespace } // namespace mujoco