Add X macros for mjVisual and mjStatistic.

PiperOrigin-RevId: 866502731
Change-Id: I7cfaf3cd96512d93c801b7611eedb71689e21a5b
This commit is contained in:
Saran Tunyasuvunakool
2026-02-06 09:52:24 -08:00
committed by Copybara-Service
parent 6419534bad
commit 74d657a777
2 changed files with 165 additions and 0 deletions
+94
View File
@@ -63,6 +63,100 @@
X( o_friction, 5 )
//-------------------------------- 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 )
//-------------------------------- 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 )
//-------------------------------- mjModel ---------------------------------------------------------
// size fields of mjModel
+71
View File
@@ -16,8 +16,10 @@
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
@@ -30,6 +32,17 @@
namespace mujoco {
namespace {
template <typename T, size_t N>
struct ArrayOrScalar {
using type = T[N];
};
template <typename T>
struct ArrayOrScalar<T, 1> {
using type = T;
};
template <typename T, size_t N>
using ArrayOrScalarT = typename ArrayOrScalar<T, N>::type;
// check that a vector of named pointers are ordered by address
void CheckAddressOrdering(
const std::vector<std::pair<const void*, const char*>>& pointers,
@@ -121,6 +134,64 @@ TEST_F(HeaderTest, MjOptionVectorsOrdered) {
CheckAddressOrdering(vectors, "MJOPTION_VECTORS");
}
TEST_F(HeaderTest, MjStatisticFields) {
mjStatistic s;
std::vector<std::pair<const void*, const char*>> fields;
// 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); \
MJSTATISTIC_FIELDS
#undef X
// check that the ordering of X macros agrees with the struct fields
#define X(type, name, dim) \
fields.push_back({static_cast<const void*>(&s.name), #name});
MJSTATISTIC_FIELDS
#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];
MJSTATISTIC_FIELDS;
#undef X
};
static_assert(sizeof(mjStatistic) == sizeof(ExpectedMjStatistic));
}
TEST_F(HeaderTest, MjVisualFields) {
mjVisual v;
std::vector<std::pair<const void*, const char*>> fields;
// check that all X macros have the correct type and dim
#define X(substruct, type, name, dim) \
static_assert( \
std::is_same_v<decltype(v.substruct.name), ArrayOrScalarT<type, dim>>, \
"incorrect type for mjVisual::" #substruct "::" #name); \
MJVISUAL_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
#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;
#undef X
};
static_assert(sizeof(mjVisual) == sizeof(ExpectedMjVisual));
}
TEST_F(HeaderTest, MjModelIntsOrdered) {
mjModel m;
std::vector<std::pair<const void*, const char*>> ints;