Clean up X macros and usages for mjOption, mjStatistic, and mjVisual.
* Replace various MJOPTION_ macros with a single MJOPTION_FIELDS. * Use XVEC macro to denote vector members where there is a mixture of vector and scalar members in a given struct type. * Split up MJVISUAL_FIELDS into separate macros for each substruct. * Modify engine_print.c and Python bindings struct.h/cc to use the new X macros. PiperOrigin-RevId: 869760513 Change-Id: Idac4fe9aa99f0258e7c79802ca9023a0d4486e2d
This commit is contained in:
committed by
Copybara-Service
parent
6d8b6028e2
commit
5274e5f720
+126
-127
@@ -18,143 +18,142 @@
|
||||
|
||||
//-------------------------------- mjOption --------------------------------------------------------
|
||||
|
||||
// scalar fields of mjOption
|
||||
#define MJOPTION_FLOATS \
|
||||
X( mjtNum, timestep ) \
|
||||
X( mjtNum, impratio ) \
|
||||
X( mjtNum, tolerance ) \
|
||||
X( mjtNum, ls_tolerance ) \
|
||||
X( mjtNum, noslip_tolerance ) \
|
||||
X( mjtNum, ccd_tolerance ) \
|
||||
X( mjtNum, sleep_tolerance ) \
|
||||
X( mjtNum, density ) \
|
||||
X( mjtNum, viscosity ) \
|
||||
X( mjtNum, o_margin )
|
||||
|
||||
|
||||
#define MJOPTION_INTS \
|
||||
X( int, integrator ) \
|
||||
X( int, cone ) \
|
||||
X( int, jacobian ) \
|
||||
X( int, solver ) \
|
||||
X( int, iterations ) \
|
||||
X( int, ls_iterations ) \
|
||||
X( int, noslip_iterations ) \
|
||||
X( int, ccd_iterations ) \
|
||||
X( int, disableflags ) \
|
||||
X( int, enableflags ) \
|
||||
X( int, disableactuator ) \
|
||||
X( int, sdf_initpoints ) \
|
||||
X( int, sdf_iterations )
|
||||
|
||||
|
||||
#define MJOPTION_SCALARS \
|
||||
MJOPTION_FLOATS \
|
||||
MJOPTION_INTS
|
||||
|
||||
|
||||
// vector fields of mjOption
|
||||
#define MJOPTION_VECTORS \
|
||||
X( gravity, 3 ) \
|
||||
X( wind, 3 ) \
|
||||
X( magnetic, 3 ) \
|
||||
X( o_solref, mjNREF ) \
|
||||
X( o_solimp, mjNIMP ) \
|
||||
X( o_friction, 5 )
|
||||
// fields of mjOption
|
||||
// XVEC means that a field is a vector (i.e. size > 1)
|
||||
#define MJOPTION_FIELDS \
|
||||
X ( mjtNum, timestep, 1 ) \
|
||||
X ( mjtNum, impratio, 1 ) \
|
||||
X ( mjtNum, tolerance, 1 ) \
|
||||
X ( mjtNum, ls_tolerance, 1 ) \
|
||||
X ( mjtNum, noslip_tolerance, 1 ) \
|
||||
X ( mjtNum, ccd_tolerance, 1 ) \
|
||||
X ( mjtNum, sleep_tolerance, 1 ) \
|
||||
XVEC( mjtNum, gravity, 3 ) \
|
||||
XVEC( mjtNum, wind, 3 ) \
|
||||
XVEC( mjtNum, magnetic, 3 ) \
|
||||
X ( mjtNum, density, 1 ) \
|
||||
X ( mjtNum, viscosity, 1 ) \
|
||||
X ( mjtNum, o_margin, 1 ) \
|
||||
XVEC( mjtNum, o_solref, mjNREF ) \
|
||||
XVEC( mjtNum, o_solimp, mjNIMP ) \
|
||||
XVEC( mjtNum, o_friction, 5 ) \
|
||||
X ( int, integrator, 1 ) \
|
||||
X ( int, cone, 1 ) \
|
||||
X ( int, jacobian, 1 ) \
|
||||
X ( int, solver, 1 ) \
|
||||
X ( int, iterations, 1 ) \
|
||||
X ( int, ls_iterations, 1 ) \
|
||||
X ( int, noslip_iterations, 1 ) \
|
||||
X ( int, ccd_iterations, 1 ) \
|
||||
X ( int, disableflags, 1 ) \
|
||||
X ( int, enableflags, 1 ) \
|
||||
X ( int, disableactuator, 1 ) \
|
||||
X ( int, sdf_initpoints, 1 ) \
|
||||
X ( int, sdf_iterations, 1 )
|
||||
|
||||
|
||||
//-------------------------------- mjStatistic -----------------------------------------------------
|
||||
|
||||
// fields of mjStatistic
|
||||
#define MJSTATISTIC_FIELDS \
|
||||
X( mjtNum, meaninertia, 1 ) \
|
||||
X( mjtNum, meanmass, 1 ) \
|
||||
X( mjtNum, meansize, 1 ) \
|
||||
X( mjtNum, extent, 1 ) \
|
||||
X( mjtNum, center, 3 )
|
||||
#define MJSTATISTIC_FIELDS \
|
||||
X ( meaninertia, 1 ) \
|
||||
X ( meanmass, 1 ) \
|
||||
X ( meansize, 1 ) \
|
||||
X ( extent, 1 ) \
|
||||
XVEC( center, 3 )
|
||||
|
||||
|
||||
//-------------------------------- mjVisual --------------------------------------------------------
|
||||
|
||||
// fields of mjVisual
|
||||
#define MJVISUAL_FIELDS \
|
||||
X( global, int, cameraid, 1 ) \
|
||||
X( global, int, orthographic, 1 ) \
|
||||
X( global, float, fovy, 1 ) \
|
||||
X( global, float, ipd, 1 ) \
|
||||
X( global, float, azimuth, 1 ) \
|
||||
X( global, float, elevation, 1 ) \
|
||||
X( global, float, linewidth, 1 ) \
|
||||
X( global, float, glow, 1 ) \
|
||||
X( global, float, realtime, 1 ) \
|
||||
X( global, int, offwidth, 1 ) \
|
||||
X( global, int, offheight, 1 ) \
|
||||
X( global, int, ellipsoidinertia, 1 ) \
|
||||
X( global, int, bvactive, 1 ) \
|
||||
X( quality, int, shadowsize, 1 ) \
|
||||
X( quality, int, offsamples, 1 ) \
|
||||
X( quality, int, numslices, 1 ) \
|
||||
X( quality, int, numstacks, 1 ) \
|
||||
X( quality, int, numquads, 1 ) \
|
||||
X( headlight, float, ambient, 3 ) \
|
||||
X( headlight, float, diffuse, 3 ) \
|
||||
X( headlight, float, specular, 3 ) \
|
||||
X( headlight, int, active, 1 ) \
|
||||
X( map, float, stiffness, 1 ) \
|
||||
X( map, float, stiffnessrot, 1 ) \
|
||||
X( map, float, force, 1 ) \
|
||||
X( map, float, torque, 1 ) \
|
||||
X( map, float, alpha, 1 ) \
|
||||
X( map, float, fogstart, 1 ) \
|
||||
X( map, float, fogend, 1 ) \
|
||||
X( map, float, znear, 1 ) \
|
||||
X( map, float, zfar, 1 ) \
|
||||
X( map, float, haze, 1 ) \
|
||||
X( map, float, shadowclip, 1 ) \
|
||||
X( map, float, shadowscale, 1 ) \
|
||||
X( map, float, actuatortendon, 1 ) \
|
||||
X( scale, float, forcewidth, 1 ) \
|
||||
X( scale, float, contactwidth, 1 ) \
|
||||
X( scale, float, contactheight, 1 ) \
|
||||
X( scale, float, connect, 1 ) \
|
||||
X( scale, float, com, 1 ) \
|
||||
X( scale, float, camera, 1 ) \
|
||||
X( scale, float, light, 1 ) \
|
||||
X( scale, float, selectpoint, 1 ) \
|
||||
X( scale, float, jointlength, 1 ) \
|
||||
X( scale, float, jointwidth, 1 ) \
|
||||
X( scale, float, actuatorlength, 1 ) \
|
||||
X( scale, float, actuatorwidth, 1 ) \
|
||||
X( scale, float, framelength, 1 ) \
|
||||
X( scale, float, framewidth, 1 ) \
|
||||
X( scale, float, constraint, 1 ) \
|
||||
X( scale, float, slidercrank, 1 ) \
|
||||
X( scale, float, frustum, 1 ) \
|
||||
X( rgba, float, fog, 4 ) \
|
||||
X( rgba, float, haze, 4 ) \
|
||||
X( rgba, float, force, 4 ) \
|
||||
X( rgba, float, inertia, 4 ) \
|
||||
X( rgba, float, joint, 4 ) \
|
||||
X( rgba, float, actuator, 4 ) \
|
||||
X( rgba, float, actuatornegative, 4 ) \
|
||||
X( rgba, float, actuatorpositive, 4 ) \
|
||||
X( rgba, float, com, 4 ) \
|
||||
X( rgba, float, camera, 4 ) \
|
||||
X( rgba, float, light, 4 ) \
|
||||
X( rgba, float, selectpoint, 4 ) \
|
||||
X( rgba, float, connect, 4 ) \
|
||||
X( rgba, float, contactpoint, 4 ) \
|
||||
X( rgba, float, contactforce, 4 ) \
|
||||
X( rgba, float, contactfriction, 4 ) \
|
||||
X( rgba, float, contacttorque, 4 ) \
|
||||
X( rgba, float, contactgap, 4 ) \
|
||||
X( rgba, float, rangefinder, 4 ) \
|
||||
X( rgba, float, constraint, 4 ) \
|
||||
X( rgba, float, slidercrank, 4 ) \
|
||||
X( rgba, float, crankbroken, 4 ) \
|
||||
X( rgba, float, frustum, 4 ) \
|
||||
X( rgba, float, bv, 4 ) \
|
||||
X( rgba, float, bvactive, 4 )
|
||||
#define MJVISUAL_GLOBAL_FIELDS \
|
||||
X( int, cameraid ) \
|
||||
X( int, orthographic ) \
|
||||
X( float, fovy ) \
|
||||
X( float, ipd ) \
|
||||
X( float, azimuth ) \
|
||||
X( float, elevation ) \
|
||||
X( float, linewidth ) \
|
||||
X( float, glow ) \
|
||||
X( float, realtime ) \
|
||||
X( int, offwidth ) \
|
||||
X( int, offheight ) \
|
||||
X( int, ellipsoidinertia ) \
|
||||
X( int, bvactive )
|
||||
|
||||
#define MJVISUAL_QUALITY_FIELDS \
|
||||
X( shadowsize ) \
|
||||
X( offsamples ) \
|
||||
X( numslices ) \
|
||||
X( numstacks ) \
|
||||
X( numquads )
|
||||
|
||||
#define MJVISUAL_HEADLIGHT_FIELDS \
|
||||
XVEC( float, ambient, 3 ) \
|
||||
XVEC( float, diffuse, 3 ) \
|
||||
XVEC( float, specular, 3 ) \
|
||||
X ( int, active, 1 )
|
||||
|
||||
#define MJVISUAL_MAP_FIELDS \
|
||||
X( stiffness ) \
|
||||
X( stiffnessrot ) \
|
||||
X( force ) \
|
||||
X( torque ) \
|
||||
X( alpha ) \
|
||||
X( fogstart ) \
|
||||
X( fogend ) \
|
||||
X( znear ) \
|
||||
X( zfar ) \
|
||||
X( haze ) \
|
||||
X( shadowclip ) \
|
||||
X( shadowscale ) \
|
||||
X( actuatortendon )
|
||||
|
||||
#define MJVISUAL_SCALE_FIELDS \
|
||||
X( forcewidth ) \
|
||||
X( contactwidth ) \
|
||||
X( contactheight ) \
|
||||
X( connect ) \
|
||||
X( com ) \
|
||||
X( camera ) \
|
||||
X( light ) \
|
||||
X( selectpoint ) \
|
||||
X( jointlength ) \
|
||||
X( jointwidth ) \
|
||||
X( actuatorlength ) \
|
||||
X( actuatorwidth ) \
|
||||
X( framelength ) \
|
||||
X( framewidth ) \
|
||||
X( constraint ) \
|
||||
X( slidercrank ) \
|
||||
X( frustum )
|
||||
|
||||
#define MJVISUAL_RGBA_FIELDS \
|
||||
X( fog ) \
|
||||
X( haze ) \
|
||||
X( force ) \
|
||||
X( inertia ) \
|
||||
X( joint ) \
|
||||
X( actuator ) \
|
||||
X( actuatornegative ) \
|
||||
X( actuatorpositive ) \
|
||||
X( com ) \
|
||||
X( camera ) \
|
||||
X( light ) \
|
||||
X( selectpoint ) \
|
||||
X( connect ) \
|
||||
X( contactpoint ) \
|
||||
X( contactforce ) \
|
||||
X( contactfriction ) \
|
||||
X( contacttorque ) \
|
||||
X( contactgap ) \
|
||||
X( rangefinder ) \
|
||||
X( constraint ) \
|
||||
X( slidercrank ) \
|
||||
X( crankbroken ) \
|
||||
X( frustum ) \
|
||||
X( bv ) \
|
||||
X( bvactive )
|
||||
|
||||
|
||||
//-------------------------------- mjModel ---------------------------------------------------------
|
||||
|
||||
+51
-118
@@ -103,50 +103,53 @@ PYBIND11_MODULE(_structs, m) {
|
||||
});
|
||||
mjOption.def_property_readonly_static("_all_fields", [](py::object) {
|
||||
std::vector<std::string> fields;
|
||||
#define X(dtype, name) fields.push_back(#name);
|
||||
MJOPTION_FLOATS
|
||||
#undef X
|
||||
#define X(name, dim0) fields.push_back(#name);
|
||||
MJOPTION_VECTORS
|
||||
#undef X
|
||||
#define X(dtype, name) fields.push_back(#name);
|
||||
MJOPTION_INTS
|
||||
#define X(type, var, dim) fields.push_back(#var);
|
||||
#define XVEC X
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
return py::tuple(py::cast(fields));
|
||||
});
|
||||
DefineStructFunctions(mjOption);
|
||||
|
||||
#define X(type, var) \
|
||||
#define X(type, var, dim) \
|
||||
mjOption.def_property( \
|
||||
#var, [](const MjOptionWrapper& c) { return c.get()->var; }, \
|
||||
[](MjOptionWrapper& c, type rhs) { c.get()->var = rhs; });
|
||||
MJOPTION_SCALARS
|
||||
#undef X
|
||||
|
||||
#define X(var, dim) DefinePyArray(mjOption, #var, &MjOptionWrapper::var);
|
||||
MJOPTION_VECTORS
|
||||
#define XVEC(type, var, dim) \
|
||||
DefinePyArray(mjOption, #var, &MjOptionWrapper::var);
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
mjOption.def_property_readonly_static("_float_fields", [](py::object) {
|
||||
std::vector<std::string> field_names;
|
||||
#define X(type, var) field_names.push_back(#var);
|
||||
MJOPTION_FLOATS
|
||||
#define X(type, var, dim) \
|
||||
if constexpr (std::is_floating_point_v<type>) field_names.push_back(#var);
|
||||
#define XVEC(type, var, dim)
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
return py::tuple(py::cast(field_names));
|
||||
});
|
||||
|
||||
mjOption.def_property_readonly_static("_int_fields", [](py::object) {
|
||||
std::vector<std::string> field_names;
|
||||
#define X(type, var) field_names.push_back(#var);
|
||||
MJOPTION_INTS
|
||||
#define X(type, var, dim) \
|
||||
if constexpr (std::is_integral_v<type>) field_names.push_back(#var);
|
||||
#define XVEC(type, var, dim)
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
return py::tuple(py::cast(field_names));
|
||||
});
|
||||
|
||||
mjOption.def_property_readonly_static("_floatarray_fields", [](py::object) {
|
||||
std::vector<std::string> field_names;
|
||||
#define X(var, sz) field_names.push_back(#var);
|
||||
MJOPTION_VECTORS
|
||||
#define X(type, var, dim)
|
||||
#define XVEC(type, var, dim) field_names.push_back(#var);
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
return py::tuple(py::cast(field_names));
|
||||
});
|
||||
@@ -192,20 +195,9 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return raw::MjVisualGlobal(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualGlobal);
|
||||
#define X(var) mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var)
|
||||
X(cameraid);
|
||||
X(orthographic);
|
||||
X(fovy);
|
||||
X(ipd);
|
||||
X(azimuth);
|
||||
X(elevation);
|
||||
X(linewidth);
|
||||
X(glow);
|
||||
X(realtime);
|
||||
X(offwidth);
|
||||
X(offheight);
|
||||
X(ellipsoidinertia);
|
||||
X(bvactive);
|
||||
#define X(type, var) \
|
||||
mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var);
|
||||
MJVISUAL_GLOBAL_FIELDS
|
||||
#undef X
|
||||
|
||||
py::class_<raw::MjVisualQuality> mjVisualQuality(mjVisual, "Quality");
|
||||
@@ -217,12 +209,8 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return raw::MjVisualQuality(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualQuality);
|
||||
#define X(var) mjVisualQuality.def_readwrite(#var, &raw::MjVisualQuality::var)
|
||||
X(shadowsize);
|
||||
X(offsamples);
|
||||
X(numslices);
|
||||
X(numstacks);
|
||||
X(numquads);
|
||||
#define X(var) mjVisualQuality.def_readwrite(#var, &raw::MjVisualQuality::var);
|
||||
MJVISUAL_QUALITY_FIELDS
|
||||
#undef X
|
||||
|
||||
py::class_<MjVisualHeadlightWrapper> mjVisualHeadlight(mjVisual, "Headlight");
|
||||
@@ -234,18 +222,17 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return MjVisualHeadlightWrapper(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualHeadlight);
|
||||
#define X(var) \
|
||||
DefinePyArray(mjVisualHeadlight, #var, &MjVisualHeadlightWrapper::var)
|
||||
X(ambient);
|
||||
X(diffuse);
|
||||
X(specular);
|
||||
#undef X
|
||||
mjVisualHeadlight.def_property(
|
||||
"active",
|
||||
[](const MjVisualHeadlightWrapper& c) { return c.get()->active; },
|
||||
[](MjVisualHeadlightWrapper& c, int rhs) {
|
||||
return c.get()->active = rhs;
|
||||
#define X(type, var, dim) \
|
||||
mjVisualHeadlight.def_property( \
|
||||
#var, [](const MjVisualHeadlightWrapper& c) { return c.get()->var; }, \
|
||||
[](MjVisualHeadlightWrapper& c, type rhs) { \
|
||||
return c.get()->var = rhs; \
|
||||
});
|
||||
#define XVEC(type, var, dim) \
|
||||
DefinePyArray(mjVisualHeadlight, #var, &MjVisualHeadlightWrapper::var);
|
||||
MJVISUAL_HEADLIGHT_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
py::class_<raw::MjVisualMap> mjVisualMap(mjVisual, "Map");
|
||||
mjVisualMap.def("__copy__", [](const raw::MjVisualMap& other) {
|
||||
@@ -255,20 +242,8 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return raw::MjVisualMap(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualMap);
|
||||
#define X(var) mjVisualMap.def_readwrite(#var, &raw::MjVisualMap::var)
|
||||
X(stiffness);
|
||||
X(stiffnessrot);
|
||||
X(force);
|
||||
X(torque);
|
||||
X(alpha);
|
||||
X(fogstart);
|
||||
X(fogend);
|
||||
X(znear);
|
||||
X(zfar);
|
||||
X(haze);
|
||||
X(shadowclip);
|
||||
X(shadowscale);
|
||||
X(actuatortendon);
|
||||
#define X(var) mjVisualMap.def_readwrite(#var, &raw::MjVisualMap::var);
|
||||
MJVISUAL_MAP_FIELDS
|
||||
#undef X
|
||||
|
||||
py::class_<raw::MjVisualScale> mjVisualScale(mjVisual, "Scale");
|
||||
@@ -280,24 +255,8 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return raw::MjVisualScale(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualScale);
|
||||
#define X(var) mjVisualScale.def_readwrite(#var, &raw::MjVisualScale::var)
|
||||
X(forcewidth);
|
||||
X(contactwidth);
|
||||
X(contactheight);
|
||||
X(connect);
|
||||
X(com);
|
||||
X(camera);
|
||||
X(light);
|
||||
X(selectpoint);
|
||||
X(jointlength);
|
||||
X(jointwidth);
|
||||
X(actuatorlength);
|
||||
X(actuatorwidth);
|
||||
X(framelength);
|
||||
X(framewidth);
|
||||
X(constraint);
|
||||
X(slidercrank);
|
||||
X(frustum);
|
||||
#define X(var) mjVisualScale.def_readwrite(#var, &raw::MjVisualScale::var);
|
||||
MJVISUAL_SCALE_FIELDS
|
||||
#undef X
|
||||
|
||||
py::class_<MjVisualRgbaWrapper> mjVisualRgba(mjVisual, "Rgba");
|
||||
@@ -309,32 +268,8 @@ PYBIND11_MODULE(_structs, m) {
|
||||
return MjVisualRgbaWrapper(other);
|
||||
});
|
||||
DefineStructFunctions(mjVisualRgba);
|
||||
#define X(var) DefinePyArray(mjVisualRgba, #var, &MjVisualRgbaWrapper::var)
|
||||
X(fog);
|
||||
X(haze);
|
||||
X(force);
|
||||
X(inertia);
|
||||
X(joint);
|
||||
X(actuator);
|
||||
X(actuatornegative);
|
||||
X(actuatorpositive);
|
||||
X(com);
|
||||
X(camera);
|
||||
X(light);
|
||||
X(selectpoint);
|
||||
X(connect);
|
||||
X(contactpoint);
|
||||
X(contactforce);
|
||||
X(contactfriction);
|
||||
X(contacttorque);
|
||||
X(contactgap);
|
||||
X(rangefinder);
|
||||
X(constraint);
|
||||
X(slidercrank);
|
||||
X(crankbroken);
|
||||
X(frustum);
|
||||
X(bv);
|
||||
X(bvactive);
|
||||
#define X(var) DefinePyArray(mjVisualRgba, #var, &MjVisualRgbaWrapper::var);
|
||||
MJVISUAL_RGBA_FIELDS
|
||||
#undef X
|
||||
|
||||
#define X(var) \
|
||||
@@ -927,20 +862,18 @@ This is useful for example when the MJB is not available as a file on disk.)"));
|
||||
});
|
||||
DefineStructFunctions(mjStatistic);
|
||||
|
||||
#define X(var) \
|
||||
#define X(var, dim) \
|
||||
mjStatistic.def_property( \
|
||||
#var, [](const MjStatisticWrapper& c) { return c.get()->var; }, \
|
||||
[](MjStatisticWrapper& c, decltype(raw::MjStatistic::var) rhs) { \
|
||||
c.get()->var = rhs; \
|
||||
})
|
||||
X(meaninertia);
|
||||
X(meanmass);
|
||||
X(meansize);
|
||||
X(extent);
|
||||
#undef X
|
||||
});
|
||||
#define XVEC(var, dim) \
|
||||
DefinePyArray(mjStatistic, #var, &MjStatisticWrapper::var);
|
||||
|
||||
#define X(var) DefinePyArray(mjStatistic, #var, &MjStatisticWrapper::var)
|
||||
X(center);
|
||||
MJSTATISTIC_FIELDS
|
||||
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
// ==================== MJLROPT ==============================================
|
||||
|
||||
+16
-36
@@ -217,11 +217,13 @@ class MjWrapper<raw::MjOption> : public WrapperBase<raw::MjOption> {
|
||||
MjWrapper(raw::MjOption* ptr, pybind11::handle owner);
|
||||
~MjWrapper() = default;
|
||||
|
||||
#define X(var, dim) \
|
||||
#define X(type, var, dim)
|
||||
#define XVEC(type, var, dim) \
|
||||
py_array_or_tuple_t< \
|
||||
std::remove_all_extents_t<decltype(raw::MjOption::var)>> \
|
||||
var;
|
||||
MJOPTION_VECTORS
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
};
|
||||
|
||||
@@ -241,13 +243,13 @@ class MjWrapper<raw::MjVisualHeadlight>
|
||||
MjWrapper(raw::MjVisualHeadlight* ptr, pybind11::handle owner);
|
||||
~MjWrapper() = default;
|
||||
|
||||
#define X(var) \
|
||||
#define X(type, var, dim)
|
||||
#define XVEC(type, var, dim) \
|
||||
py_array_or_tuple_t< \
|
||||
std::remove_all_extents_t<decltype(raw::MjVisualHeadlight::var)>> \
|
||||
var
|
||||
X(ambient);
|
||||
X(diffuse);
|
||||
X(specular);
|
||||
var;
|
||||
MJVISUAL_HEADLIGHT_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
};
|
||||
|
||||
@@ -268,32 +270,8 @@ class MjWrapper<raw::MjVisualRgba> : public WrapperBase<raw::MjVisualRgba> {
|
||||
#define X(var) \
|
||||
py_array_or_tuple_t< \
|
||||
std::remove_all_extents_t<decltype(raw::MjVisualRgba::var)>> \
|
||||
var
|
||||
X(fog);
|
||||
X(haze);
|
||||
X(force);
|
||||
X(inertia);
|
||||
X(joint);
|
||||
X(actuator);
|
||||
X(actuatornegative);
|
||||
X(actuatorpositive);
|
||||
X(com);
|
||||
X(camera);
|
||||
X(light);
|
||||
X(selectpoint);
|
||||
X(connect);
|
||||
X(contactpoint);
|
||||
X(contactforce);
|
||||
X(contactfriction);
|
||||
X(contacttorque);
|
||||
X(contactgap);
|
||||
X(rangefinder);
|
||||
X(constraint);
|
||||
X(slidercrank);
|
||||
X(crankbroken);
|
||||
X(frustum);
|
||||
X(bv);
|
||||
X(bvactive);
|
||||
var;
|
||||
MJVISUAL_RGBA_FIELDS
|
||||
#undef X
|
||||
};
|
||||
|
||||
@@ -330,11 +308,13 @@ class MjWrapper<raw::MjStatistic> : public WrapperBase<raw::MjStatistic> {
|
||||
MjWrapper(raw::MjStatistic* ptr, pybind11::handle owner);
|
||||
~MjWrapper() = default;
|
||||
|
||||
#define X(var) \
|
||||
#define X(var, dim)
|
||||
#define XVEC(var, dim) \
|
||||
py_array_or_tuple_t< \
|
||||
std::remove_all_extents_t<decltype(raw::MjStatistic::var)>> \
|
||||
var
|
||||
X(center);
|
||||
var;
|
||||
MJSTATISTIC_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
||||
@@ -83,16 +83,20 @@ inline std::size_t NConMax(const mjData* d) {
|
||||
} // namespace
|
||||
|
||||
// ==================== MJOPTION ===============================================
|
||||
#define X(var, dim) , var(InitPyArray(std::array{dim}, ptr_->var, owner_))
|
||||
#define X(type, var, dim)
|
||||
#define XVEC(type, var, dim) \
|
||||
, var(InitPyArray(std::array{dim}, ptr_->var, owner_))
|
||||
MjOptionWrapper::MjWrapper()
|
||||
: WrapperBase([]() {
|
||||
raw::MjOption* const opt = new raw::MjOption;
|
||||
mj_defaultOption(opt);
|
||||
return opt;
|
||||
}()) MJOPTION_VECTORS {}
|
||||
}()) MJOPTION_FIELDS {}
|
||||
|
||||
MjOptionWrapper::MjWrapper(raw::MjOption* ptr, py::handle owner)
|
||||
: WrapperBase(ptr, owner) MJOPTION_VECTORS {}
|
||||
: WrapperBase(ptr, owner) MJOPTION_FIELDS {}
|
||||
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
MjOptionWrapper::MjWrapper(const MjOptionWrapper& other) : MjOptionWrapper() {
|
||||
|
||||
+112
-36
@@ -24,6 +24,7 @@
|
||||
#include <mujoco/mjmacro.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjsan.h> // IWYU pragma: keep
|
||||
#include <mujoco/mjtnum.h>
|
||||
#include <mujoco/mjxmacro.h>
|
||||
#include "engine/engine_core_constraint.h"
|
||||
#include "engine/engine_core_util.h"
|
||||
@@ -600,33 +601,111 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
||||
#undef X
|
||||
fprintf(fp, "\n");
|
||||
|
||||
// scalar options
|
||||
// options
|
||||
fprintf(fp, "OPTION\n");
|
||||
#define X( type, name ) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
fprintf(fp, float_format, m->opt.name); \
|
||||
#define X(type, name, sz) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
const char* format = \
|
||||
_Generic(m->opt.name, mjtNum: float_format, int: INT_FORMAT); \
|
||||
fprintf(fp, format, m->opt.name); \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
#define XVEC(type, name, sz) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
const char* format = \
|
||||
_Generic(m->opt.name[0], mjtNum: float_format, int: INT_FORMAT); \
|
||||
for (int i = 0; i < sz; i++) { \
|
||||
fprintf(fp, format, m->opt.name[i]); \
|
||||
} \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJOPTION_FLOATS
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
#define X( type, name ) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
fprintf(fp, INT_FORMAT "\n", m->opt.name);
|
||||
|
||||
MJOPTION_INTS
|
||||
#undef X
|
||||
|
||||
// vector options
|
||||
#define X( name, sz ) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
for (int i=0; i < sz; i++) { \
|
||||
fprintf(fp, float_format, m->opt.name[i]); \
|
||||
fprintf(fp, " "); \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJOPTION_VECTORS
|
||||
// visual
|
||||
fprintf(fp, "VISUAL\n");
|
||||
|
||||
fprintf(fp, " GLOBAL\n");
|
||||
#define X(type, name) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
const char* format = \
|
||||
_Generic(m->vis.global.name, float: float_format, int: INT_FORMAT); \
|
||||
fprintf(fp, format, m->vis.global.name); \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJVISUAL_GLOBAL_FIELDS
|
||||
#undef X
|
||||
|
||||
fprintf(fp, " QUALITY\n");
|
||||
#define X(name) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
fprintf(fp, INT_FORMAT, m->vis.quality.name); \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJVISUAL_QUALITY_FIELDS
|
||||
#undef X
|
||||
|
||||
fprintf(fp, " HEADLIGHT\n");
|
||||
#define X(type, name, sz) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
const char* format = \
|
||||
_Generic(m->vis.headlight.name, float: float_format, int: INT_FORMAT); \
|
||||
fprintf(fp, format, m->vis.headlight.name); \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
#define XVEC(type, name, sz) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
const char* format = _Generic( \
|
||||
m->vis.headlight.name[0], \
|
||||
float: float_format, \
|
||||
int: INT_FORMAT); \
|
||||
for (int i = 0; i < sz; i++) { \
|
||||
fprintf(fp, format, m->vis.headlight.name[i]); \
|
||||
} \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
MJVISUAL_HEADLIGHT_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
fprintf(fp, " MAP\n");
|
||||
#define X(name) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
fprintf(fp, float_format, m->vis.map.name); \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJVISUAL_MAP_FIELDS
|
||||
#undef X
|
||||
|
||||
fprintf(fp, " SCALE\n");
|
||||
#define X(name) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
fprintf(fp, float_format, m->vis.scale.name); \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJVISUAL_SCALE_FIELDS
|
||||
#undef X
|
||||
|
||||
fprintf(fp, " RGBA\n");
|
||||
#define X(name) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
for (int i = 0; i < 4; i++) { \
|
||||
fprintf(fp, float_format, m->vis.rgba.name[i]); \
|
||||
} \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
|
||||
MJVISUAL_RGBA_FIELDS
|
||||
#undef X
|
||||
fprintf(fp, "\n");
|
||||
|
||||
@@ -637,23 +716,20 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char*
|
||||
|
||||
// statistics
|
||||
fprintf(fp, "STATISTIC\n");
|
||||
fprintf(fp, NAME_FORMAT, " meaninertia");
|
||||
fprintf(fp, float_format, m->stat.meaninertia);
|
||||
#define X(name, sz) \
|
||||
fprintf(fp, NAME_FORMAT, " " #name); \
|
||||
{ \
|
||||
for (int i = 0; i < sz; i++) { \
|
||||
fprintf(fp, float_format, ((mjtNum*)(&m->stat.name))[i]); \
|
||||
} \
|
||||
} \
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, NAME_FORMAT, " meanmass");
|
||||
fprintf(fp, float_format, m->stat.meanmass);
|
||||
#define XVEC X
|
||||
|
||||
MJSTATISTIC_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, NAME_FORMAT, " meansize");
|
||||
fprintf(fp, float_format, m->stat.meansize);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, NAME_FORMAT, " extent");
|
||||
fprintf(fp, float_format, m->stat.extent);
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, NAME_FORMAT, " center");
|
||||
fprintf(fp, float_format, m->stat.center[0]);
|
||||
fprintf(fp, float_format, m->stat.center[1]);
|
||||
fprintf(fp, float_format, m->stat.center[2]);
|
||||
fprintf(fp, "\n\n");
|
||||
|
||||
// qpos0
|
||||
fprintf(fp, NAME_FORMAT, "qpos0");
|
||||
|
||||
+5
-8
@@ -274,19 +274,16 @@ mjtNum CompareModel(const mjModel* m1, const mjModel* m2,
|
||||
MJMODEL_POINTERS
|
||||
#undef X
|
||||
|
||||
// compare scalars in mjOption
|
||||
#define X(type, name) \
|
||||
// compare fields in mjOption
|
||||
#define X(type, name, n) \
|
||||
dif = Compare(m1->opt.name, m2->opt.name); \
|
||||
if (dif > maxdif) {maxdif = dif; field = #name;}
|
||||
MJOPTION_SCALARS
|
||||
#undef X
|
||||
|
||||
// compare arrays in mjOption
|
||||
#define X(name, n) \
|
||||
#define XVEC(type, name, n) \
|
||||
for (int c=0; c < n; c++) { \
|
||||
dif = Compare(m1->opt.name[c], m2->opt.name[c]); \
|
||||
if (dif > maxdif) {maxdif = dif; field = #name;} }
|
||||
MJOPTION_VECTORS
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
// Return largest difference and field name
|
||||
|
||||
+204
-31
@@ -24,6 +24,7 @@
|
||||
#include <mujoco/mjdata.h>
|
||||
#include <mujoco/mjmodel.h>
|
||||
#include <mujoco/mjrender.h>
|
||||
#include <mujoco/mjtnum.h>
|
||||
#include <mujoco/mjui.h>
|
||||
#include <mujoco/mjvisualize.h>
|
||||
#include <mujoco/mjxmacro.h>
|
||||
@@ -110,86 +111,258 @@ TEST_F(HeaderTest, EnumsAreInts) {
|
||||
EXPECT_EQ(sizeof(mjtStereo), sizeof(int));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, MjOptionFloatsOrdered) {
|
||||
TEST_F(HeaderTest, MjOptionFields) {
|
||||
mjOption o;
|
||||
std::vector<std::pair<const void*, const char*>> floats;
|
||||
std::vector<std::pair<const void*, const char*>> fields;
|
||||
|
||||
#define X(type, name) \
|
||||
floats.push_back({static_cast<const void*>(&o.name), #name});
|
||||
MJOPTION_FLOATS
|
||||
// check that all X macros have the correct type and dim
|
||||
#define XIMPL(type, name, dim) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(mjOption::name), ArrayOrScalarT<type, dim>>, \
|
||||
"incorrect type for mjOption::" #name);
|
||||
#define X(type, name, dim) \
|
||||
static_assert(dim == 1, "use XVEC for non-scalar fields"); \
|
||||
XIMPL(type, name, dim)
|
||||
#define XVEC(type, name, dim) \
|
||||
static_assert(dim > 1, "use X for scalar fields"); \
|
||||
XIMPL(type, name, dim)
|
||||
|
||||
MJOPTION_FIELDS
|
||||
|
||||
#undef XVEC
|
||||
#undef X
|
||||
#undef XIMPL
|
||||
|
||||
// check that the ordering of X macros agrees with the struct fields
|
||||
#define X(type, name, dim) \
|
||||
fields.push_back({static_cast<const void*>(&o.name), #name});
|
||||
#define XVEC X
|
||||
MJOPTION_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
CheckAddressOrdering(floats, "MJOPTION_FLOATS");
|
||||
}
|
||||
CheckAddressOrdering(fields, "MJOPTION_FIELDS");
|
||||
|
||||
TEST_F(HeaderTest, MjOptionVectorsOrdered) {
|
||||
mjOption o;
|
||||
std::vector<std::pair<const void*, const char*>> vectors;
|
||||
|
||||
#define X(name, dim) \
|
||||
vectors.push_back({static_cast<const void*>(&o.name), #name});
|
||||
MJOPTION_VECTORS
|
||||
// check that MJOPTION_FIELDS is a complete list of struct fields
|
||||
struct ExpectedMjOption {
|
||||
#define XVEC(type, name, dim) type name[dim];
|
||||
#define X XVEC
|
||||
MJOPTION_FIELDS
|
||||
#undef X
|
||||
|
||||
CheckAddressOrdering(vectors, "MJOPTION_VECTORS");
|
||||
#undef XVEC
|
||||
};
|
||||
static_assert(sizeof(mjOption) == sizeof(ExpectedMjOption));
|
||||
static_assert(alignof(mjOption) == alignof(ExpectedMjOption));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, MjStatisticFields) {
|
||||
mjStatistic s;
|
||||
std::vector<std::pair<const void*, const char*>> fields;
|
||||
|
||||
// All fields in mjStatistic are expected to be of type mjtNum.
|
||||
using ScalarType = mjtNum;
|
||||
|
||||
// check that all X macros have the correct type and dim
|
||||
#define X(type, name, dim) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(mjStatistic::name), ArrayOrScalarT<type, dim>>, \
|
||||
"incorrect type for mjStatistic::" #name); \
|
||||
#define XIMPL(name, dim) \
|
||||
static_assert(std::is_same_v<decltype(mjStatistic::name), \
|
||||
ArrayOrScalarT<ScalarType, dim>>, \
|
||||
"incorrect type for mjStatistic::" #name);
|
||||
#define X(name, dim) \
|
||||
static_assert(dim == 1, "use XVEC for non-scalar fields"); \
|
||||
XIMPL(name, dim)
|
||||
#define XVEC(name, dim) \
|
||||
static_assert(dim > 1, "use X for scalar fields"); \
|
||||
XIMPL(name, dim)
|
||||
|
||||
MJSTATISTIC_FIELDS
|
||||
|
||||
#undef XVEC
|
||||
#undef X
|
||||
#undef XIMPL
|
||||
|
||||
// check that the ordering of X macros agrees with the struct fields
|
||||
#define X(type, name, dim) \
|
||||
#define X(name, dim) \
|
||||
fields.push_back({static_cast<const void*>(&s.name), #name});
|
||||
#define XVEC X
|
||||
MJSTATISTIC_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
|
||||
CheckAddressOrdering(fields, "MJSTATISTIC_FIELDS");
|
||||
|
||||
// check that MJSTATISTIC_FIELDS is a complete list of struct fields
|
||||
struct ExpectedMjStatistic {
|
||||
#define X(type, name, dim) type name[dim];
|
||||
#define XVEC(name, dim) ScalarType name[dim];
|
||||
#define X XVEC
|
||||
MJSTATISTIC_FIELDS;
|
||||
#undef XVEC
|
||||
#undef X
|
||||
};
|
||||
static_assert(sizeof(mjStatistic) == sizeof(ExpectedMjStatistic));
|
||||
static_assert(alignof(mjStatistic) == alignof(ExpectedMjStatistic));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, MjVisualFields) {
|
||||
mjVisual v;
|
||||
std::vector<std::pair<const void*, const char*>> fields;
|
||||
|
||||
// All member fields in quality, map, scale, and rgba have the same type.
|
||||
using QualityMemberType = int;
|
||||
using MapMemberType = float;
|
||||
using ScaleMemberType = float;
|
||||
using RgbaMemberType = float[4];
|
||||
|
||||
// check that all X macros have the correct type and dim
|
||||
#define X(substruct, type, name, dim) \
|
||||
#define X(type, name) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.global.name), type>, \
|
||||
"incorrect type for mjVisual::global::" #name);
|
||||
|
||||
MJVISUAL_GLOBAL_FIELDS
|
||||
|
||||
#undef X
|
||||
|
||||
#define X(name) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.quality.name), QualityMemberType>, \
|
||||
"incorrect type for mjVisual::quality::" #name);
|
||||
|
||||
MJVISUAL_QUALITY_FIELDS
|
||||
|
||||
#undef X
|
||||
|
||||
#define XIMPL(type, name, dim) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.substruct.name), ArrayOrScalarT<type, dim>>, \
|
||||
"incorrect type for mjVisual::" #substruct "::" #name); \
|
||||
MJVISUAL_FIELDS
|
||||
std::is_same_v<decltype(v.headlight.name), ArrayOrScalarT<type, dim>>, \
|
||||
"incorrect type for mjVisual::headlight::" #name);
|
||||
#define X(type, name, dim) \
|
||||
static_assert(dim == 1, "use XVEC for non-scalar fields"); \
|
||||
XIMPL(type, name, dim)
|
||||
#define XVEC(type, name, dim) \
|
||||
static_assert(dim > 1, "use X for scalar fields"); \
|
||||
XIMPL(type, name, dim)
|
||||
|
||||
MJVISUAL_HEADLIGHT_FIELDS
|
||||
|
||||
#undef X
|
||||
#undef XVEC
|
||||
|
||||
#define X(name) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.map.name), MapMemberType>, \
|
||||
"incorrect type for mjVisual::map::" #name);
|
||||
|
||||
MJVISUAL_MAP_FIELDS
|
||||
|
||||
#undef X
|
||||
|
||||
#define X(name) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.scale.name), ScaleMemberType>, \
|
||||
"incorrect type for mjVisual::scale::" #name);
|
||||
|
||||
MJVISUAL_SCALE_FIELDS
|
||||
|
||||
#undef X
|
||||
|
||||
#define X(name) \
|
||||
static_assert( \
|
||||
std::is_same_v<decltype(v.rgba.name), RgbaMemberType>, \
|
||||
"incorrect type for mjVisual::rgba::" #name);
|
||||
|
||||
MJVISUAL_RGBA_FIELDS
|
||||
|
||||
#undef X
|
||||
|
||||
// check that the ordering of X macros agrees with the struct fields
|
||||
#define X(substruct, type, name, dim) \
|
||||
fields.push_back({static_cast<const void*>(&v.substruct.name), #name});
|
||||
MJVISUAL_FIELDS
|
||||
#define X(type, name) \
|
||||
fields.push_back({static_cast<const void*>(&v.global.name), #name});
|
||||
MJVISUAL_GLOBAL_FIELDS
|
||||
#undef X
|
||||
#define X(name) \
|
||||
fields.push_back({static_cast<const void*>(&v.quality.name), #name});
|
||||
MJVISUAL_QUALITY_FIELDS
|
||||
#undef X
|
||||
#define X(type, name, dim) \
|
||||
fields.push_back({static_cast<const void*>(&v.headlight.name), #name});
|
||||
#define XVEC X
|
||||
MJVISUAL_HEADLIGHT_FIELDS
|
||||
#undef XVEC
|
||||
#undef X
|
||||
#define X(name) \
|
||||
fields.push_back({static_cast<const void*>(&v.map.name), #name});
|
||||
MJVISUAL_MAP_FIELDS
|
||||
#undef X
|
||||
#define X(name) \
|
||||
fields.push_back({static_cast<const void*>(&v.scale.name), #name});
|
||||
MJVISUAL_SCALE_FIELDS
|
||||
#undef X
|
||||
#define X(name) \
|
||||
fields.push_back({static_cast<const void*>(&v.rgba.name), #name});
|
||||
MJVISUAL_RGBA_FIELDS
|
||||
#undef X
|
||||
|
||||
CheckAddressOrdering(fields, "MJVISUAL_FIELDS");
|
||||
|
||||
// check that MJVISUAL_FIELDS is a complete list of fields
|
||||
struct ExpectedMjVisual {
|
||||
#define X(substruct, type, name, dim) type substruct##_##name[dim];
|
||||
MJVISUAL_FIELDS;
|
||||
struct {
|
||||
#define X(type, name) type name;
|
||||
MJVISUAL_GLOBAL_FIELDS;
|
||||
#undef X
|
||||
} global;
|
||||
struct {
|
||||
#define X(name) QualityMemberType name;
|
||||
MJVISUAL_QUALITY_FIELDS;
|
||||
#undef X
|
||||
} quality;
|
||||
struct {
|
||||
#define X(type, name, dim) type name[dim];
|
||||
#define XVEC X
|
||||
MJVISUAL_HEADLIGHT_FIELDS;
|
||||
#undef XVEC
|
||||
#undef X
|
||||
} headlight;
|
||||
struct {
|
||||
#define X(name) MapMemberType name;
|
||||
MJVISUAL_MAP_FIELDS;
|
||||
#undef X
|
||||
} map;
|
||||
struct {
|
||||
#define X(name) ScaleMemberType name;
|
||||
MJVISUAL_SCALE_FIELDS;
|
||||
#undef X
|
||||
} scale;
|
||||
struct {
|
||||
#define X(name) RgbaMemberType name;
|
||||
MJVISUAL_RGBA_FIELDS;
|
||||
#undef X
|
||||
} rgba;
|
||||
};
|
||||
|
||||
static_assert(sizeof(mjVisual) == sizeof(ExpectedMjVisual));
|
||||
static_assert(alignof(mjVisual) == alignof(ExpectedMjVisual));
|
||||
|
||||
static_assert(sizeof(mjVisual::global) == sizeof(ExpectedMjVisual::global));
|
||||
static_assert(alignof(mjVisual::global) == alignof(ExpectedMjVisual::global));
|
||||
|
||||
static_assert(sizeof(mjVisual::quality) == sizeof(ExpectedMjVisual::quality));
|
||||
static_assert(alignof(mjVisual::quality) ==
|
||||
alignof(ExpectedMjVisual::quality));
|
||||
|
||||
static_assert(sizeof(mjVisual::headlight) ==
|
||||
sizeof(ExpectedMjVisual::headlight));
|
||||
static_assert(alignof(mjVisual::headlight) ==
|
||||
alignof(ExpectedMjVisual::headlight));
|
||||
|
||||
static_assert(sizeof(mjVisual::map) == sizeof(ExpectedMjVisual::map));
|
||||
static_assert(alignof(mjVisual::map) == alignof(ExpectedMjVisual::map));
|
||||
|
||||
static_assert(sizeof(mjVisual::scale) == sizeof(ExpectedMjVisual::scale));
|
||||
static_assert(alignof(mjVisual::scale) == alignof(ExpectedMjVisual::scale));
|
||||
|
||||
static_assert(sizeof(mjVisual::rgba) == sizeof(ExpectedMjVisual::rgba));
|
||||
static_assert(alignof(mjVisual::rgba) == alignof(ExpectedMjVisual::rgba));
|
||||
}
|
||||
|
||||
TEST_F(HeaderTest, MjModelIntsOrdered) {
|
||||
|
||||
Reference in New Issue
Block a user