diff --git a/doc/changelog.rst b/doc/changelog.rst index 8cc34291..4d83d9a6 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -80,6 +80,11 @@ Python bindings ^^^^^^^^^^^^^^^ 20. Fixed a memory leak when using ``copy.deepcopy()`` on a ``mujoco.MjData`` instance (:github:issue:`1572`). +Bug fixes +^^^^^^^^^ +21. Fix an issue where ``mj_copyData`` (or ``copy.copy()`` in the Python bindings) was not copying contact information + correctly (:github:issue:`1710`). + Version 3.1.6 (Jun 3, 2024) --------------------------- diff --git a/python/mujoco/bindings_test.py b/python/mujoco/bindings_test.py index f6201776..aa88d784 100644 --- a/python/mujoco/bindings_test.py +++ b/python/mujoco/bindings_test.py @@ -418,6 +418,9 @@ class MuJoCoBindingsTest(parameterized.TestCase): data_copy = copy.copy(self.data) self.assertEqual(data_copy.ncon, 2) + # Make sure contact details are copied. + self.assertEqual(data_copy.contact[0].dist, self.data.contact[0].dist) + # Make sure it's a copy. mujoco.mj_resetData(self.model, self.data) mujoco.mj_forward(self.model, self.data) diff --git a/src/engine/engine_io.c b/src/engine/engine_io.c index 5e5af9ae..bf68b4f5 100644 --- a/src/engine/engine_io.c +++ b/src/engine/engine_io.c @@ -1265,10 +1265,24 @@ mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) { } // copy arena memory +#undef MJ_D +#define MJ_D(n) (src->n) +#undef MJ_M +#define MJ_M(n) (m->n) #define X(type, name, nr, nc) \ - dest->name = src->name ? (type*)((char*)dest->arena + PTRDIFF(src->name, src->arena)) : NULL; + if (src->name) { \ + dest->name = (type*)((char*)dest->arena + PTRDIFF(src->name, src->arena)); \ + memcpy((char*)dest->name, (const char*)src->name, sizeof(type)*nr*nc); \ + } else { \ + dest->name = NULL; \ + } + MJDATA_ARENA_POINTERS #undef X +#undef MJ_M +#define MJ_M(n) n +#undef MJ_D +#define MJ_D(n) n // restore contact pointer dest->contact = dest->arena;