Add mjStatistic to mjmModel.

PiperOrigin-RevId: 607657424
Change-Id: I17f6ef37570651e002258ee2a509fc52d213c0f5
This commit is contained in:
Alessio Quaglino
2024-02-16 05:16:47 -08:00
committed by Copybara-Service
parent f1d4f8f0a1
commit d7c47de353
6 changed files with 55 additions and 52 deletions
+4
View File
@@ -73,6 +73,7 @@ typedef enum _mjtLimited { // type of limit specification
typedef struct _mjmModel { // model specification typedef struct _mjmModel { // model specification
mjElement element; // internal, do not modify mjElement element; // internal, do not modify
mjStatistic stat; // statistics override (if defined)
} mjmModel; } mjmModel;
typedef struct _mjmOrientation { // alternative orientation specifiers typedef struct _mjmOrientation { // alternative orientation specifiers
@@ -825,6 +826,9 @@ MJAPI const char* mjm_setFullInertia(mjmBody* body, double quat[4], double inert
//---------------------------------- Initialization functions -------------------------------------- //---------------------------------- Initialization functions --------------------------------------
// Default model attributes.
MJAPI void mjm_defaultModel(mjmModel& model);
// Default body attributes. // Default body attributes.
MJAPI void mjm_defaultBody(mjmBody& body); MJAPI void mjm_defaultBody(mjmBody& body);
+14
View File
@@ -21,6 +21,20 @@
// default model attributes
void mjm_defaultModel(mjmModel& model) {
memset(&model, 0, sizeof(mjmModel));
// default statistics
model.stat.meaninertia = mjNAN;
model.stat.meanmass = mjNAN;
model.stat.meansize = mjNAN;
model.stat.extent = mjNAN;
model.stat.center[0] = mjNAN;
}
// default body attributes // default body attributes
void mjm_defaultBody(mjmBody& body) { void mjm_defaultBody(mjmBody& body) {
memset(&body, 0, sizeof(mjmBody)); memset(&body, 0, sizeof(mjmBody));
+19 -18
View File
@@ -83,6 +83,7 @@ static void copyvec(T1* dest, T2* src, int n) {
// constructor // constructor
mjCModel::mjCModel() { mjCModel::mjCModel() {
mjm_defaultModel(spec);
comment.clear(); comment.clear();
modelfiledir.clear(); modelfiledir.clear();
@@ -110,14 +111,6 @@ mjCModel::mjCModel() {
exactmeshinertia = false; exactmeshinertia = false;
mj_defaultLROpt(&LRopt); mj_defaultLROpt(&LRopt);
//------------------------ statistics override
meaninertia = mjNAN;
meanmass = mjNAN;
meansize = mjNAN;
extent = mjNAN;
center[0] = mjNAN;
center[1] = center[2] = 0;
//------------------------ auto-computed statistics //------------------------ auto-computed statistics
#ifndef MEMORY_SANITIZER #ifndef MEMORY_SANITIZER
// initializing as best practice, but want MSAN to catch unintialized use // initializing as best practice, but want MSAN to catch unintialized use
@@ -223,6 +216,12 @@ mjCModel::mjCModel() {
void mjCModel::CopyFromSpec() {
*static_cast<mjmModel*>(this) = spec;
}
// destructor // destructor
mjCModel::~mjCModel() { mjCModel::~mjCModel() {
// delete kinematic tree and all objects allocated in it // delete kinematic tree and all objects allocated in it
@@ -2748,6 +2747,8 @@ static void warninghandler(const char* msg) {
// compiler // compiler
mjModel* mjCModel::Compile(const mjVFS* vfs) { mjModel* mjCModel::Compile(const mjVFS* vfs) {
CopyFromSpec();
// The volatile keyword is necessary to prevent a possible memory leak due to // The volatile keyword is necessary to prevent a possible memory leak due to
// an interaction between longjmp and compiler optimization. Specifically, at // an interaction between longjmp and compiler optimization. Specifically, at
// the point where the setjmp takes places, these pointers have never been // the point where the setjmp takes places, these pointers have never been
@@ -3208,11 +3209,11 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
copyvec(center_auto, m->stat.center, 3); copyvec(center_auto, m->stat.center, 3);
// override model statistics if defined by user // override model statistics if defined by user
if (mjuu_defined(extent)) m->stat.extent = (mjtNum)extent; if (mjuu_defined(stat.extent)) m->stat.extent = (mjtNum)stat.extent;
if (mjuu_defined(meaninertia)) m->stat.meaninertia = (mjtNum)meaninertia; if (mjuu_defined(stat.meaninertia)) m->stat.meaninertia = (mjtNum)stat.meaninertia;
if (mjuu_defined(meanmass)) m->stat.meanmass = (mjtNum)meanmass; if (mjuu_defined(stat.meanmass)) m->stat.meanmass = (mjtNum)stat.meanmass;
if (mjuu_defined(meansize)) m->stat.meansize = (mjtNum)meansize; if (mjuu_defined(stat.meansize)) m->stat.meansize = (mjtNum)stat.meansize;
if (mjuu_defined(center[0])) copyvec(m->stat.center, center, 3); if (mjuu_defined(stat.center[0])) copyvec(m->stat.center, stat.center, 3);
// assert that model has valid references // assert that model has valid references
const char* validationerr = mj_validateReferences(m); const char* validationerr = mj_validateReferences(m);
@@ -3284,14 +3285,14 @@ bool mjCModel::CopyBack(const mjModel* m) {
visual = m->vis; visual = m->vis;
// runtime-modifiable members of mjStatistic, if different from computed values // runtime-modifiable members of mjStatistic, if different from computed values
if (m->stat.meaninertia != meaninertia_auto) meaninertia = m->stat.meaninertia; if (m->stat.meaninertia != meaninertia_auto) stat.meaninertia = m->stat.meaninertia;
if (m->stat.meanmass != meanmass_auto) meanmass = m->stat.meanmass; if (m->stat.meanmass != meanmass_auto) stat.meanmass = m->stat.meanmass;
if (m->stat.meansize != meansize_auto) meansize = m->stat.meansize; if (m->stat.meansize != meansize_auto) stat.meansize = m->stat.meansize;
if (m->stat.extent != extent_auto) extent = m->stat.extent; if (m->stat.extent != extent_auto) stat.extent = m->stat.extent;
if (m->stat.center[0] != center_auto[0] || if (m->stat.center[0] != center_auto[0] ||
m->stat.center[1] != center_auto[1] || m->stat.center[1] != center_auto[1] ||
m->stat.center[2] != center_auto[2]) { m->stat.center[2] != center_auto[2]) {
mju_copy3(center, m->stat.center); mju_copy3(stat.center, m->stat.center);
} }
// qpos0, qpos_spring // qpos0, qpos_spring
+3 -21
View File
@@ -25,6 +25,7 @@
#include <mujoco/mjdata.h> #include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include <mujoco/mjplugin.h> #include <mujoco/mjplugin.h>
#include "user/user_api.h"
#include "user/user_objects.h" #include "user/user_objects.h"
typedef enum _mjtInertiaFromGeom { typedef enum _mjtInertiaFromGeom {
@@ -46,31 +47,19 @@ typedef std::array<mjKeyMap, mjNOBJECT> mjListKeyMap;
// constructed, 'Compile' can be called to generate the corresponding mjModel object // constructed, 'Compile' can be called to generate the corresponding mjModel object
// (which is the low-level model). The mjCModel object can then be deleted. // (which is the low-level model). The mjCModel object can then be deleted.
class mjCModel { class mjCModel : private mjmModel {
friend class mjCBody; friend class mjCBody;
friend class mjCJoint;
friend class mjCGeom; friend class mjCGeom;
friend class mjCFlex; friend class mjCFlex;
friend class mjCMesh;
friend class mjCSkin;
friend class mjCHField;
friend class mjCPair;
friend class mjCBodyPair;
friend class mjCSite;
friend class mjCEquality; friend class mjCEquality;
friend class mjCTendon; friend class mjCTendon;
friend class mjCWrap;
friend class mjCActuator;
friend class mjCSensor;
friend class mjCNumeric;
friend class mjCTuple;
friend class mjCKey;
friend class mjXReader; friend class mjXReader;
friend class mjXWriter; friend class mjXWriter;
public: public:
mjCModel(); // constructor mjCModel(); // constructor
~mjCModel(); // destructor ~mjCModel(); // destructor
void CopyFromSpec(); // copy spec to private attributes
mjmModel spec; mjmModel spec;
@@ -154,13 +143,6 @@ class mjCModel {
bool exactmeshinertia; // if false, use old formula bool exactmeshinertia; // if false, use old formula
mjLROpt LRopt; // options for lengthrange computation mjLROpt LRopt; // options for lengthrange computation
//------------------------ statistics override (if defined)
double meaninertia; // mean diagonal inertia
double meanmass; // mean body mass
double meansize; // mean body size
double extent; // spatial extent
double center[3]; // center of model
//------------------------ engine data //------------------------ engine data
std::string modelname; // model name std::string modelname; // model name
mjOption option; // options mjOption option; // options
+9 -8
View File
@@ -1253,14 +1253,15 @@ void mjXReader::Statistic(XMLElement* section) {
string text; string text;
// read statistics // read statistics
ReadAttr(section, "meaninertia", 1, &model->meaninertia, text); mjmModel* pmodel = &model->spec;
ReadAttr(section, "meanmass", 1, &model->meanmass, text); ReadAttr(section, "meaninertia", 1, &pmodel->stat.meaninertia, text);
ReadAttr(section, "meansize", 1, &model->meansize, text); ReadAttr(section, "meanmass", 1, &pmodel->stat.meanmass, text);
ReadAttr(section, "extent", 1, &model->extent, text); ReadAttr(section, "meansize", 1, &pmodel->stat.meansize, text);
if (mjuu_defined(model->extent) && model->extent<=0) { ReadAttr(section, "extent", 1, &pmodel->stat.extent, text);
if (mjuu_defined(pmodel->stat.extent) && pmodel->stat.extent<=0) {
throw mjXError(section, "extent must be strictly positive"); throw mjXError(section, "extent must be strictly positive");
} }
ReadAttr(section, "center", 3, model->center, text); ReadAttr(section, "center", 3, pmodel->stat.center, text);
} }
@@ -2482,7 +2483,7 @@ void mjXReader::OneComposite(XMLElement* elem, mjmBody* pbody, mjmDefault* def)
// make composite // make composite
char error[200]; char error[200];
bool res = comp.Make((mjCModel*)mjm_getModel(pbody), pbody, error, 200); bool res = comp.Make(model, pbody, error, 200);
// throw error // throw error
if (!res) { if (!res) {
@@ -2617,7 +2618,7 @@ void mjXReader::OneFlexcomp(XMLElement* elem, mjmBody* pbody) {
// make flexcomp // make flexcomp
char error[200]; char error[200];
bool res = fcomp.Make((mjCModel*)mjm_getModel(pbody), pbody, error, 200); bool res = fcomp.Make(model, pbody, error, 200);
// throw error // throw error
if (!res) { if (!res) {
+6 -5
View File
@@ -975,12 +975,13 @@ void mjXWriter::Size(XMLElement* root) {
// statistic section // statistic section
void mjXWriter::Statistic(XMLElement* root) { void mjXWriter::Statistic(XMLElement* root) {
XMLElement* section = InsertEnd(root, "statistic"); XMLElement* section = InsertEnd(root, "statistic");
mjStatistic* s = &model->stat;
if (mjuu_defined(model->meaninertia)) WriteAttr(section, "meaninertia", 1, &model->meaninertia); if (mjuu_defined(s->meaninertia)) WriteAttr(section, "meaninertia", 1, &s->meaninertia);
if (mjuu_defined(model->meanmass)) WriteAttr(section, "meanmass", 1, &model->meanmass); if (mjuu_defined(s->meanmass)) WriteAttr(section, "meanmass", 1, &s->meanmass);
if (mjuu_defined(model->meansize)) WriteAttr(section, "meansize", 1, &model->meansize); if (mjuu_defined(s->meansize)) WriteAttr(section, "meansize", 1, &s->meansize);
if (mjuu_defined(model->extent)) WriteAttr(section, "extent", 1, &model->extent); if (mjuu_defined(s->extent)) WriteAttr(section, "extent", 1, &s->extent);
if (mjuu_defined(model->center[0])) WriteAttr(section, "center", 3, model->center); if (mjuu_defined(s->center[0])) WriteAttr(section, "center", 3, s->center);
// remove entire section if no attributes // remove entire section if no attributes
if (!section->FirstAttribute()) root->DeleteChild(section); if (!section->FirstAttribute()) root->DeleteChild(section);