Add mjv_copyData

PiperOrigin-RevId: 760642972
Change-Id: I16227fd91bf42618fda684b15b3650758ae29b13
This commit is contained in:
Yuval Tassa
2025-05-19 08:58:45 -07:00
committed by Copybara-Service
parent 670c97c4f7
commit 8268c6d1ff
9 changed files with 236 additions and 113 deletions
+9
View File
@@ -1364,6 +1364,15 @@ If the model buffer is unallocated the initial configuration will not be set.
Copy mjData.
m is only required to contain the size fields from MJMODEL_INTS.
.. _mjv_copyData:
`mjv_copyData <#mjv_copyData>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mjv_copyData
Copy mjData, skip large arrays not required for visualization.
.. _mj_resetData:
`mj_resetData <#mj_resetData>`__
+1
View File
@@ -3283,6 +3283,7 @@ void mj_deleteModel(mjModel* m);
int mj_sizeModel(const mjModel* m);
mjData* mj_makeData(const mjModel* m);
mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src);
mjData* mjv_copyData(mjData* dest, const mjModel* m, const mjData* src);
void mj_resetData(const mjModel* m, mjData* d);
void mj_resetDataDebug(const mjModel* m, mjData* d, unsigned char debug_value);
void mj_resetDataKeyframe(const mjModel* m, mjData* d, int key);
+103 -103
View File
@@ -268,7 +268,7 @@
X ( mjtNum, geom_friction, ngeom, 3 ) \
X ( mjtNum, geom_margin, ngeom, 1 ) \
X ( mjtNum, geom_gap, ngeom, 1 ) \
X ( mjtNum, geom_fluid, ngeom, mjNFLUID ) \
XNV ( mjtNum, geom_fluid, ngeom, mjNFLUID ) \
X ( mjtNum, geom_user, ngeom, MJ_M(nuser_geom) ) \
XMJV( float, geom_rgba, ngeom, 4 ) \
XMJV( int, site_type, nsite, 1 ) \
@@ -401,15 +401,15 @@
XNV ( int, mesh_facetexcoord, nmeshface, 3 ) \
XNV ( int, mesh_graph, nmeshgraph, 1 ) \
XMJV( int, mesh_pathadr, nmesh, 1 ) \
X ( int, mesh_polynum, nmesh, 1 ) \
X ( int, mesh_polyadr, nmesh, 1 ) \
X ( mjtNum, mesh_polynormal, nmeshpoly, 3 ) \
X ( int, mesh_polyvertadr, nmeshpoly, 1 ) \
X ( int, mesh_polyvertnum, nmeshpoly, 1 ) \
X ( int, mesh_polyvert, nmeshpolyvert, 1 ) \
X ( int, mesh_polymapadr, nmeshvert, 1 ) \
X ( int, mesh_polymapnum, nmeshvert, 1 ) \
X ( int, mesh_polymap, nmeshpolymap, 1 ) \
XNV ( int, mesh_polynum, nmesh, 1 ) \
XNV ( int, mesh_polyadr, nmesh, 1 ) \
XNV ( mjtNum, mesh_polynormal, nmeshpoly, 3 ) \
XNV ( int, mesh_polyvertadr, nmeshpoly, 1 ) \
XNV ( int, mesh_polyvertnum, nmeshpoly, 1 ) \
XNV ( int, mesh_polyvert, nmeshpolyvert, 1 ) \
XNV ( int, mesh_polymapadr, nmeshvert, 1 ) \
XNV ( int, mesh_polymapnum, nmeshvert, 1 ) \
XNV ( int, mesh_polymap, nmeshpolymap, 1 ) \
XMJV( int, skin_matid, nskin, 1 ) \
XMJV( int, skin_group, nskin, 1 ) \
XMJV( float, skin_rgba, nskin, 4 ) \
@@ -655,10 +655,10 @@
X ( int, moment_rowadr, nu, 1 ) \
X ( int, moment_colind, nJmom, 1 ) \
X ( mjtNum, actuator_moment, nJmom, 1 ) \
X ( mjtNum, crb, nbody, 10 ) \
X ( mjtNum, qM, nM, 1 ) \
X ( mjtNum, M, nC, 1 ) \
X ( mjtNum, qLD, nC, 1 ) \
XNV ( mjtNum, crb, nbody, 10 ) \
XNV ( mjtNum, qM, nM, 1 ) \
XNV ( mjtNum, M, nC, 1 ) \
XNV ( mjtNum, qLD, nC, 1 ) \
X ( mjtNum, qLDiagInv, nv, 1 ) \
XMJV( mjtNum, bvh_aabb_dyn, nbvhdynamic, 6 ) \
XMJV( mjtByte, bvh_active, nbvh, 1 ) \
@@ -675,23 +675,23 @@
X ( mjtNum, qfrc_passive, nv, 1 ) \
X ( mjtNum, subtree_linvel, nbody, 3 ) \
X ( mjtNum, subtree_angmom, nbody, 3 ) \
X ( mjtNum, qH, nC, 1 ) \
XNV ( mjtNum, qH, nC, 1 ) \
X ( mjtNum, qHDiagInv, nv, 1 ) \
X ( int, B_rownnz, nbody, 1 ) \
X ( int, B_rowadr, nbody, 1 ) \
X ( int, B_colind, nB, 1 ) \
X ( int, M_rownnz, nv, 1 ) \
X ( int, M_rowadr, nv, 1 ) \
X ( int, M_colind, nC, 1 ) \
X ( int, mapM2M, nC, 1 ) \
X ( int, D_rownnz, nv, 1 ) \
X ( int, D_rowadr, nv, 1 ) \
X ( int, D_diag, nv, 1 ) \
X ( int, D_colind, nD, 1 ) \
X ( int, mapM2D, nD, 1 ) \
X ( int, mapD2M, nM, 1 ) \
X ( mjtNum, qDeriv, nD, 1 ) \
X ( mjtNum, qLU, nD, 1 ) \
XNV ( int, B_rownnz, nbody, 1 ) \
XNV ( int, B_rowadr, nbody, 1 ) \
XNV ( int, B_colind, nB, 1 ) \
XNV ( int, M_rownnz, nv, 1 ) \
XNV ( int, M_rowadr, nv, 1 ) \
XNV ( int, M_colind, nC, 1 ) \
XNV ( int, mapM2M, nC, 1 ) \
XNV ( int, D_rownnz, nv, 1 ) \
XNV ( int, D_rowadr, nv, 1 ) \
XNV ( int, D_diag, nv, 1 ) \
XNV ( int, D_colind, nD, 1 ) \
XNV ( int, mapM2D, nD, 1 ) \
XNV ( int, mapD2M, nM, 1 ) \
XNV ( mjtNum, qDeriv, nD, 1 ) \
XNV ( mjtNum, qLU, nD, 1 ) \
X ( mjtNum, actuator_force, nu, 1 ) \
X ( mjtNum, qfrc_actuator, nv, 1 ) \
X ( mjtNum, qfrc_smooth, nv, 1 ) \
@@ -712,83 +712,83 @@
X( mjContact, contact, MJ_D(ncon), 1 )
// array fields of mjData that are used in the primal problem
#define MJDATA_ARENA_POINTERS_SOLVER \
X( int, efc_type, MJ_D(nefc), 1 ) \
X( int, efc_id, MJ_D(nefc), 1 ) \
X( int, efc_J_rownnz, MJ_D(nefc), 1 ) \
X( int, efc_J_rowadr, MJ_D(nefc), 1 ) \
X( int, efc_J_rowsuper, MJ_D(nefc), 1 ) \
X( int, efc_J_colind, MJ_D(nJ), 1 ) \
X( int, efc_JT_rownnz, MJ_M(nv), 1 ) \
X( int, efc_JT_rowadr, MJ_M(nv), 1 ) \
X( int, efc_JT_rowsuper, MJ_M(nv), 1 ) \
X( int, efc_JT_colind, MJ_D(nJ), 1 ) \
X( mjtNum, efc_J, MJ_D(nJ), 1 ) \
X( mjtNum, efc_JT, MJ_D(nJ), 1 ) \
X( mjtNum, efc_pos, MJ_D(nefc), 1 ) \
X( mjtNum, efc_margin, MJ_D(nefc), 1 ) \
X( mjtNum, efc_frictionloss, MJ_D(nefc), 1 ) \
X( mjtNum, efc_diagApprox, MJ_D(nefc), 1 ) \
X( mjtNum, efc_KBIP, MJ_D(nefc), 4 ) \
X( mjtNum, efc_D, MJ_D(nefc), 1 ) \
X( mjtNum, efc_R, MJ_D(nefc), 1 ) \
X( int, tendon_efcadr, MJ_M(ntendon), 1 ) \
X( mjtNum, efc_vel, MJ_D(nefc), 1 ) \
X( mjtNum, efc_aref, MJ_D(nefc), 1 ) \
X( mjtNum, efc_b, MJ_D(nefc), 1 ) \
X( mjtNum, efc_force, MJ_D(nefc), 1 ) \
X( int, efc_state, MJ_D(nefc), 1 )
#define MJDATA_ARENA_POINTERS_SOLVER \
X ( int, efc_type, MJ_D(nefc), 1 ) \
X ( int, efc_id, MJ_D(nefc), 1 ) \
XNV( int, efc_J_rownnz, MJ_D(nefc), 1 ) \
XNV( int, efc_J_rowadr, MJ_D(nefc), 1 ) \
XNV( int, efc_J_rowsuper, MJ_D(nefc), 1 ) \
XNV( int, efc_J_colind, MJ_D(nJ), 1 ) \
XNV( int, efc_JT_rownnz, MJ_M(nv), 1 ) \
XNV( int, efc_JT_rowadr, MJ_M(nv), 1 ) \
XNV( int, efc_JT_rowsuper, MJ_M(nv), 1 ) \
XNV( int, efc_JT_colind, MJ_D(nJ), 1 ) \
XNV( mjtNum, efc_J, MJ_D(nJ), 1 ) \
XNV( mjtNum, efc_JT, MJ_D(nJ), 1 ) \
X ( mjtNum, efc_pos, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_margin, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_frictionloss, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_diagApprox, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_KBIP, MJ_D(nefc), 4 ) \
X ( mjtNum, efc_D, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_R, MJ_D(nefc), 1 ) \
X ( int, tendon_efcadr, MJ_M(ntendon), 1 ) \
X ( mjtNum, efc_vel, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_aref, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_b, MJ_D(nefc), 1 ) \
X ( mjtNum, efc_force, MJ_D(nefc), 1 ) \
X ( int, efc_state, MJ_D(nefc), 1 )
// array fields of mjData that are used in the dual problem
#define MJDATA_ARENA_POINTERS_DUAL \
X( int, efc_AR_rownnz, MJ_D(nefc), 1 ) \
X( int, efc_AR_rowadr, MJ_D(nefc), 1 ) \
X( int, efc_AR_colind, MJ_D(nA), 1 ) \
X( mjtNum, efc_AR, MJ_D(nA), 1 )
#define MJDATA_ARENA_POINTERS_DUAL \
XNV( int, efc_AR_rownnz, MJ_D(nefc), 1 ) \
XNV( int, efc_AR_rowadr, MJ_D(nefc), 1 ) \
XNV( int, efc_AR_colind, MJ_D(nA), 1 ) \
XNV( mjtNum, efc_AR, MJ_D(nA), 1 )
// array fields of mjData that are used for constraint islands
#define MJDATA_ARENA_POINTERS_ISLAND \
X( int, dof_island, MJ_M(nv), 1 ) \
X( int, island_nv, MJ_D(nisland), 1 ) \
X( int, island_idofadr, MJ_D(nisland), 1 ) \
X( int, island_dofadr, MJ_D(nisland), 1 ) \
X( int, map_dof2idof, MJ_M(nv), 1 ) \
X( int, map_idof2dof, MJ_M(nv), 1 ) \
X( mjtNum, ifrc_smooth, MJ_D(nidof), 1 ) \
X( mjtNum, iacc_smooth, MJ_D(nidof), 1 ) \
X( int, iM_rownnz, MJ_D(nidof), 1 ) \
X( int, iM_rowadr, MJ_D(nidof), 1 ) \
X( int, iM_colind, MJ_M(nC), 1 ) \
X( mjtNum, iM, MJ_M(nC), 1 ) \
X( mjtNum, iLD, MJ_M(nC), 1 ) \
X( mjtNum, iLDiagInv, MJ_D(nidof), 1 ) \
X( mjtNum, iacc, MJ_D(nidof), 1 ) \
X( int, efc_island, MJ_D(nefc), 1 ) \
X( int, island_ne, MJ_D(nisland), 1 ) \
X( int, island_nf, MJ_D(nisland), 1 ) \
X( int, island_nefc, MJ_D(nisland), 1 ) \
X( int, island_iefcadr, MJ_D(nisland), 1 ) \
X( int, map_efc2iefc, MJ_D(nefc), 1 ) \
X( int, map_iefc2efc, MJ_D(nefc), 1 ) \
X( int, iefc_type, MJ_D(nefc), 1 ) \
X( int, iefc_id, MJ_D(nefc), 1 ) \
X( int, iefc_J_rownnz, MJ_D(nefc), 1 ) \
X( int, iefc_J_rowadr, MJ_D(nefc), 1 ) \
X( int, iefc_J_rowsuper, MJ_D(nefc), 1 ) \
X( int, iefc_J_colind, MJ_D(nJ), 1 ) \
X( int, iefc_JT_rownnz, MJ_D(nidof), 1 ) \
X( int, iefc_JT_rowadr, MJ_D(nidof), 1 ) \
X( int, iefc_JT_rowsuper, MJ_D(nidof), 1 ) \
X( int, iefc_JT_colind, MJ_D(nJ), 1 ) \
X( mjtNum, iefc_J, MJ_D(nJ), 1 ) \
X( mjtNum, iefc_JT, MJ_D(nJ), 1 ) \
X( mjtNum, iefc_frictionloss, MJ_D(nefc), 1 ) \
X( mjtNum, iefc_D, MJ_D(nefc), 1 ) \
X( mjtNum, iefc_R, MJ_D(nefc), 1 ) \
X( mjtNum, iefc_aref, MJ_D(nefc), 1 ) \
X( int, iefc_state, MJ_D(nefc), 1 ) \
X( mjtNum, iefc_force, MJ_D(nefc), 1 ) \
X( mjtNum, ifrc_constraint, MJ_D(nidof), 1 )
#define MJDATA_ARENA_POINTERS_ISLAND \
X ( int, dof_island, MJ_M(nv), 1 ) \
X ( int, island_nv, MJ_D(nisland), 1 ) \
X ( int, island_idofadr, MJ_D(nisland), 1 ) \
X ( int, island_dofadr, MJ_D(nisland), 1 ) \
X ( int, map_dof2idof, MJ_M(nv), 1 ) \
X ( int, map_idof2dof, MJ_M(nv), 1 ) \
X ( mjtNum, ifrc_smooth, MJ_D(nidof), 1 ) \
X ( mjtNum, iacc_smooth, MJ_D(nidof), 1 ) \
XNV( int, iM_rownnz, MJ_D(nidof), 1 ) \
XNV( int, iM_rowadr, MJ_D(nidof), 1 ) \
XNV( int, iM_colind, MJ_M(nC), 1 ) \
XNV( mjtNum, iM, MJ_M(nC), 1 ) \
XNV( mjtNum, iLD, MJ_M(nC), 1 ) \
X ( mjtNum, iLDiagInv, MJ_D(nidof), 1 ) \
X ( mjtNum, iacc, MJ_D(nidof), 1 ) \
X ( int, efc_island, MJ_D(nefc), 1 ) \
X ( int, island_ne, MJ_D(nisland), 1 ) \
X ( int, island_nf, MJ_D(nisland), 1 ) \
X ( int, island_nefc, MJ_D(nisland), 1 ) \
X ( int, island_iefcadr, MJ_D(nisland), 1 ) \
X ( int, map_efc2iefc, MJ_D(nefc), 1 ) \
X ( int, map_iefc2efc, MJ_D(nefc), 1 ) \
X ( int, iefc_type, MJ_D(nefc), 1 ) \
X ( int, iefc_id, MJ_D(nefc), 1 ) \
XNV( int, iefc_J_rownnz, MJ_D(nefc), 1 ) \
XNV( int, iefc_J_rowadr, MJ_D(nefc), 1 ) \
XNV( int, iefc_J_rowsuper, MJ_D(nefc), 1 ) \
XNV( int, iefc_J_colind, MJ_D(nJ), 1 ) \
XNV( int, iefc_JT_rownnz, MJ_D(nidof), 1 ) \
XNV( int, iefc_JT_rowadr, MJ_D(nidof), 1 ) \
XNV( int, iefc_JT_rowsuper, MJ_D(nidof), 1 ) \
XNV( int, iefc_JT_colind, MJ_D(nJ), 1 ) \
XNV( mjtNum, iefc_J, MJ_D(nJ), 1 ) \
XNV( mjtNum, iefc_JT, MJ_D(nJ), 1 ) \
X ( mjtNum, iefc_frictionloss, MJ_D(nefc), 1 ) \
X ( mjtNum, iefc_D, MJ_D(nefc), 1 ) \
X ( mjtNum, iefc_R, MJ_D(nefc), 1 ) \
X ( mjtNum, iefc_aref, MJ_D(nefc), 1 ) \
X ( int, iefc_state, MJ_D(nefc), 1 ) \
X ( mjtNum, iefc_force, MJ_D(nefc), 1 ) \
X ( mjtNum, ifrc_constraint, MJ_D(nidof), 1 )
// array fields of mjData that live in d->arena
#define MJDATA_ARENA_POINTERS \
+3
View File
@@ -187,6 +187,9 @@ MJAPI mjData* mj_makeData(const mjModel* m);
// m is only required to contain the size fields from MJMODEL_INTS.
MJAPI mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src);
// Copy mjData, skip large arrays not required for visualization.
MJAPI mjData* mjv_copyData(mjData* dest, const mjModel* m, const mjData* src);
// Reset data to defaults.
MJAPI void mj_resetData(const mjModel* m, mjData* d);
+28
View File
@@ -745,6 +745,34 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
doc='Copy mjData. m is only required to contain the size fields from MJMODEL_INTS.', # pylint: disable=line-too-long
)),
('mjv_copyData',
FunctionDecl(
name='mjv_copyData',
return_type=PointerType(
inner_type=ValueType(name='mjData'),
),
parameters=(
FunctionParameterDecl(
name='dest',
type=PointerType(
inner_type=ValueType(name='mjData'),
),
),
FunctionParameterDecl(
name='m',
type=PointerType(
inner_type=ValueType(name='mjModel', is_const=True),
),
),
FunctionParameterDecl(
name='src',
type=PointerType(
inner_type=ValueType(name='mjData', is_const=True),
),
),
),
doc='Copy mjData, skip large arrays not required for visualization.',
)),
('mj_resetData',
FunctionDecl(
name='mj_resetData',
+54 -9
View File
@@ -1415,8 +1415,9 @@ mjData* mj_makeData(const mjModel* m) {
// copy mjData, if dest==NULL create new data
mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
// copy mjData, if dest==NULL create new data;
// flg_all 1: copy all fields, 0: skip fields not required for visualization
mjData* mj_copyDataVisual(mjData* dest, const mjModel* m, const mjData* src, int flg_all) {
void* save_buffer;
void* save_arena;
@@ -1461,10 +1462,25 @@ mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
// copy buffer
{
MJDATA_POINTERS_PREAMBLE(m)
#define X(type, name, nr, nc) \
memcpy((char*)dest->name, (const char*)src->name, sizeof(type)*(m->nr)*nc);
MJDATA_POINTERS
#undef X
if (flg_all) {
#define X(type, name, nr, nc) \
memcpy((char*)dest->name, (const char*)src->name, sizeof(type)*(m->nr)*nc);
MJDATA_POINTERS
#undef X
} else {
// redefine XNV to nothing
#undef XNV
#define XNV(type, name, nr, nc)
#define X(type, name, nr, nc) \
memcpy((char*)dest->name, (const char*)src->name, sizeof(type)*(m->nr)*nc);
MJDATA_POINTERS
#undef X
// redefine XNV to be the same as X
#undef XNV
#define XNV X
}
}
@@ -1474,7 +1490,8 @@ mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
#undef MJ_M
#define MJ_M(n) (m->n)
#define X(type, name, nr, nc) \
if (flg_all) {
#define X(type, name, nr, nc) \
if (src->name) { \
dest->name = (type*)((char*)dest->arena + PTRDIFF(src->name, src->arena)); \
ASAN_UNPOISON_MEMORY_REGION(dest->name, sizeof(type) * nr * nc); \
@@ -1482,8 +1499,28 @@ mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
} else { \
dest->name = NULL; \
}
MJDATA_ARENA_POINTERS
#undef X
MJDATA_ARENA_POINTERS
#undef X
} else {
// redefine XNV to nothing
#undef XNV
#define XNV(type, name, nr, nc)
#define X(type, name, nr, nc) \
if (src->name) { \
dest->name = (type*)((char*)dest->arena + PTRDIFF(src->name, src->arena)); \
ASAN_UNPOISON_MEMORY_REGION(dest->name, sizeof(type) * nr * nc); \
memcpy((char*)dest->name, (const char*)src->name, sizeof(type) * nr * nc); \
} else { \
dest->name = NULL; \
}
MJDATA_ARENA_POINTERS
#undef X
// redefine XNV to be the same as X
#undef XNV
#define XNV X
}
#undef MJ_M
#define MJ_M(n) n
@@ -1515,6 +1552,14 @@ mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
}
mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src) {
return mj_copyDataVisual(dest, m, src, /*flg_all=*/1);
}
mjData* mjv_copyData(mjData* dest, const mjModel* m, const mjData* src) {
return mj_copyDataVisual(dest, m, src, /*flg_all=*/0);
}
static void maybe_lock_alloc_mutex(mjData* d) {
if (d->threadpool != 0) {
+3
View File
@@ -99,6 +99,9 @@ MJAPI void mj_makeRawData(mjData** dest, const mjModel* m);
// m is only required to contain the size fields from MJMODEL_INTS.
MJAPI mjData* mj_copyData(mjData* dest, const mjModel* m, const mjData* src);
// copy mjData, skip large arrays not required for abstract visualization
MJAPI mjData* mjv_copyData(mjData* dest, const mjModel* m, const mjData* src);
// set data to defaults
MJAPI void mj_resetData(const mjModel* m, mjData* d);
+32 -1
View File
@@ -226,11 +226,42 @@ TEST_F(EngineIoTest, MjvCopyModel) {
EXPECT_FLOAT_EQ(model2->mesh_vert[0], 0.1); // unchanged
EXPECT_FLOAT_EQ(model2->geom_rgba[0], 0.4);
// mj_deleteData(data);
mj_deleteModel(model2);
mj_deleteModel(model1);
}
TEST_F(EngineIoTest, MjvCopyData) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<body pos="0 0 0.8">
<freejoint/>
<geom type="sphere" size="0.1"/>
</body>
<geom type="plane" size="1 1 1"/>
</worldbody>
</mujoco>
)";
char error[1024];
mjModel* model = LoadModelFromString(xml, error, sizeof(error));
ASSERT_THAT(model, NotNull()) << error;
mjData* data1 = mj_makeData(model);
mj_forward(model, data1);
EXPECT_THAT(data1->efc_J, NotNull());
mjData* data2 = mj_copyData(nullptr, model, data1);
EXPECT_THAT(data2->efc_J, NotNull());
mj_deleteData(data2);
data2 = mjv_copyData(nullptr, model, data1);
EXPECT_THAT(data2->efc_J, IsNull());
mj_deleteData(data2);
mj_deleteData(data1);
mj_deleteModel(model);
}
using ValidateReferencesTest = MujocoTest;
TEST_F(ValidateReferencesTest, BodyReferences) {
+3
View File
@@ -6622,6 +6622,9 @@ public static unsafe extern mjData_* mj_makeData(mjModel_* m);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern mjData_* mj_copyData(mjData_* dest, mjModel_* m, mjData_* src);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern mjData_* mjv_copyData(mjData_* dest, mjModel_* m, mjData_* src);
[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void mj_resetData(mjModel_* m, mjData_* d);