Add compiler settings to mjmModel.

PiperOrigin-RevId: 608908314
Change-Id: Id3b0d8c62ca710b5b6d6e423abbbddcb7e7079a1
This commit is contained in:
Alessio Quaglino
2024-02-21 01:57:19 -08:00
committed by Copybara-Service
parent abf6d41b7f
commit 042760eba8
12 changed files with 130 additions and 91 deletions
+31 -3
View File
@@ -69,11 +69,39 @@ typedef enum _mjtLimited { // type of limit specification
} mjtLimited;
typedef enum _mjtInertiaFromGeom {
mjINERTIAFROMGEOM_FALSE = 0, // do not use; inertial element required
mjINERTIAFROMGEOM_TRUE, // always use; overwrite inertial element
mjINERTIAFROMGEOM_AUTO // use only if inertial element is missing
} mjtInertiaFromGeom;
//---------------------------------- attribute structs (mjm) ---------------------------------------
typedef struct _mjmModel { // model specification
mjElement element; // internal, do not modify
mjStatistic stat; // statistics override (if defined)
//------------------------ compiler settings
mjtByte autolimits; // infer "limited" attribute based on range
double boundmass; // enforce minimum body mass
double boundinertia; // enforce minimum body diagonal inertia
double settotalmass; // rescale masses and inertias; <=0: ignore
mjtByte balanceinertia; // automatically impose A + B >= C rule
mjtByte strippath; // automatically strip paths from mesh files
mjtByte fitaabb; // meshfit to aabb instead of inertia box
mjtByte degree; // angles in radians or degrees
char euler[3]; // sequence for euler rotations
mjString meshdir; // mesh and hfield directory
mjString texturedir; // texture directory
mjtByte discardvisual; // discard visual geoms in parser
mjtByte convexhull; // compute mesh convex hulls
mjtByte usethread; // use multiple threads to speed up compiler
mjtByte fusestatic; // fuse static bodies with parent
int inertiafromgeom; // use geom inertias (mjtInertiaFromGeom)
int inertiagrouprange[2]; // range of geom groups used to compute inertia
mjtByte exactmeshinertia; // if false, use old formula
mjLROpt LRopt; // options for lengthrange computation
} mjmModel;
typedef struct _mjmOrientation { // alternative orientation specifiers
@@ -320,8 +348,8 @@ typedef struct _mjmFlex {
// other properties
int dim; // element dimensionality
double radius; // radius around primitive element
bool internal; // enable internal collisions
bool flatskin; // render flex skin with flat shading
mjtByte internal; // enable internal collisions
mjtByte flatskin; // render flex skin with flat shading
int selfcollide; // mode for flex self colllision
int activelayers; // number of active element layers in 3D
int group; // group for visualizatioh
@@ -442,7 +470,7 @@ typedef struct _mjmMaterial { // material specification
mjString name; // name
mjString classname; // class name
mjString texture; // name of texture (empty: none)
bool texuniform; // make texture cube uniform
mjtByte texuniform; // make texture cube uniform
float texrepeat[2]; // texture repetition for 2D mapping
float emission; // emission
float specular; // specular
+5 -5
View File
@@ -124,7 +124,7 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz
}
// compute orientation
const char* alterr = alt.Set(quat, model->degree, model->euler);
const char* alterr = alt.Set(quat, model->spec.degree, model->spec.euler);
if (alterr) {
return comperr(error, alterr, error_sz);
}
@@ -814,7 +814,7 @@ template <typename T> static T* VecToArray(std::vector<T>& vector, bool clear =
// make mesh
bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
// strip path
if (!file.empty() && model->strippath) {
if (!file.empty() && model->spec.strippath) {
file = mjuu_strippath(file);
}
@@ -837,7 +837,7 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
}
// load resource
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file);
string filename = mjuu_makefullname(model->modelfiledir, mjm_getString(model->spec.meshdir), file);
mjResource* resource = nullptr;
try {
@@ -933,7 +933,7 @@ static int findstring(const char* buffer, int buffer_sz, const char* str) {
// load points and elements from GMSH file
bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
// strip path
if (!file.empty() && model->strippath) {
if (!file.empty() && model->spec.strippath) {
file = mjuu_strippath(file);
}
@@ -943,7 +943,7 @@ bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
}
// open resource
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file);
string filename = mjuu_makefullname(model->modelfiledir, mjm_getString(model->spec.meshdir), file);
mjResource* resource = nullptr;
try {
+22
View File
@@ -31,6 +31,28 @@ void mjm_defaultModel(mjmModel& model) {
model.stat.meansize = mjNAN;
model.stat.extent = mjNAN;
model.stat.center[0] = mjNAN;
// compiler settings
model.autolimits = true;
model.boundmass = 0;
model.boundinertia = 0;
model.settotalmass = -1;
model.balanceinertia = false;
model.strippath = false;
model.fitaabb = false;
model.degree = true;
model.euler[0] = 'x';
model.euler[1] = 'y';
model.euler[2] = 'z';
model.discardvisual = false;
model.convexhull = true;
model.usethread = true;
model.fusestatic = false;
model.inertiafromgeom = mjINERTIAFROMGEOM_AUTO;
model.inertiagrouprange[0] = 0;
model.inertiagrouprange[1] = mjNGROUP-1;
model.exactmeshinertia = false;
mj_defaultLROpt(&model.LRopt);
}
+2 -2
View File
@@ -347,7 +347,7 @@ void mjCMesh::Compile(const mjVFS* vfs) {
throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str());
}
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file_);
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir_, file_);
mjResource* resource = LoadResource(filename, vfs);
try {
@@ -1950,7 +1950,7 @@ void mjCSkin::Compile(const mjVFS* vfs) {
throw mjCError(this, "Unknown skin file type: %s", file_.c_str());
}
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file_);
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir_, file_);
mjResource* resource = LoadResource(filename, vfs);
try {
+22 -32
View File
@@ -86,30 +86,8 @@ mjCModel::mjCModel() {
mjm_defaultModel(spec);
comment.clear();
modelfiledir.clear();
//------------------------ compiler settings
autolimits = true;
boundmass = 0;
boundinertia = 0;
settotalmass = -1;
balanceinertia = false;
strippath = false;
fitaabb = false;
degree = true;
euler[0] = 'x';
euler[1] = 'y';
euler[2] = 'z';
meshdir.clear();
texturedir.clear();
discardvisual = false;
convexhull = true;
usethread = true;
fusestatic = false;
inertiafromgeom = mjINERTIAFROMGEOM_AUTO;
inertiagrouprange[0] = 0;
inertiagrouprange[1] = mjNGROUP-1;
exactmeshinertia = false;
mj_defaultLROpt(&LRopt);
spec_meshdir_.clear();
spec_texturedir_.clear();
//------------------------ auto-computed statistics
#ifndef MEMORY_SANITIZER
@@ -211,13 +189,25 @@ mjCModel::mjCModel() {
// point to model from spec
PointToLocal();
}
void mjCModel::PointToLocal() {
spec.element = (mjElement)this;
spec.meshdir = (mjString)&spec_meshdir_;
spec.texturedir = (mjString)&spec_texturedir_;
}
void mjCModel::CopyFromSpec() {
*static_cast<mjmModel*>(this) = spec;
meshdir_ = spec_meshdir_;
texturedir_ = spec_texturedir_;
meshdir = (mjString)&meshdir_;
texturedir = (mjString)&texturedir_;
}
@@ -2828,16 +2818,16 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
}
// append directory separator
if (!meshdir.empty()) {
int n = meshdir.length();
if (meshdir[n-1]!='/' && meshdir[n-1]!='\\') {
meshdir += '/';
if (!meshdir_.empty()) {
int n = meshdir_.length();
if (meshdir_[n-1]!='/' && meshdir_[n-1]!='\\') {
meshdir_ += '/';
}
}
if (!texturedir.empty()) {
int n = texturedir.length();
if (texturedir[n-1]!='/' && texturedir[n-1]!='\\') {
texturedir += '/';
if (!texturedir_.empty()) {
int n = texturedir_.length();
if (texturedir_[n-1]!='/' && texturedir_[n-1]!='\\') {
texturedir_ += '/';
}
}
+21 -27
View File
@@ -25,15 +25,10 @@
#include <mujoco/mjdata.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjplugin.h>
#include <mujoco/mjtnum.h>
#include "user/user_api.h"
#include "user/user_objects.h"
typedef enum _mjtInertiaFromGeom {
mjINERTIAFROMGEOM_FALSE = 0, // do not use; inertial element required
mjINERTIAFROMGEOM_TRUE, // always use; overwrite inertial element
mjINERTIAFROMGEOM_AUTO // use only if inertial element is missing
} mjtInertiaFromGeom;
typedef std::map<std::string, int, std::less<> > mjKeyMap;
typedef std::array<mjKeyMap, mjNOBJECT> mjListKeyMap;
@@ -49,10 +44,19 @@ typedef std::array<mjKeyMap, mjNOBJECT> mjListKeyMap;
class mjCModel : private mjmModel {
friend class mjCBody;
friend class mjCCamera;
friend class mjCGeom;
friend class mjCFlex;
friend class mjCHField;
friend class mjCFrame;
friend class mjCJoint;
friend class mjCEquality;
friend class mjCMesh;
friend class mjCSkin;
friend class mjCSite;
friend class mjCTendon;
friend class mjCTexture;
friend class mjCActuator;
friend class mjXReader;
friend class mjXWriter;
@@ -60,6 +64,7 @@ class mjCModel : private mjmModel {
mjCModel(); // constructor
~mjCModel(); // destructor
void CopyFromSpec(); // copy spec to private attributes
void PointToLocal();
mjmModel spec;
@@ -110,6 +115,10 @@ class mjCModel : private mjmModel {
mjCBase* FindObject(mjtObj type, std::string name); // find object given type and name
bool IsNullPose(const mjtNum* pos, const mjtNum* quat); // detect null pose
//------------------------ getters
std::string get_meshdir(void) const { return meshdir_; }
std::string get_texturedir(void) const { return texturedir_; }
//------------------------ API for plugins
void ResolvePlugin(mjCBase* obj, // resolve plugin instance, create a new one if needed
const std::string& plugin_name,
@@ -122,27 +131,6 @@ class mjCModel : private mjmModel {
std::string modelfiledir; // path to model file
std::vector<mjCDef*> defaults; // settings for each defaults class
//------------------------ compiler settings
bool autolimits; // infer "limited" attribute based on range
double boundmass; // enforce minimum body mass
double boundinertia; // enforce minimum body diagonal inertia
double settotalmass; // rescale masses and inertias; <=0: ignore
bool balanceinertia; // automatically impose A + B >= C rule
bool strippath; // automatically strip paths from mesh files
bool fitaabb; // meshfit to aabb instead of inertia box
bool degree; // angles in radians or degrees
char euler[3]; // sequence for euler rotations
std::string meshdir; // mesh and hfield directory
std::string texturedir; // texture directory
bool discardvisual; // discard visual geoms in parser
bool convexhull; // compute mesh convex hulls
bool usethread; // use multiple threads to speed up compiler
bool fusestatic; // fuse static bodies with parent
int inertiafromgeom; // use geom inertias (mjtInertiaFromGeom)
int inertiagrouprange[2]; // range of geom groups used to compute inertia
bool exactmeshinertia; // if false, use old formula
mjLROpt LRopt; // options for lengthrange computation
//------------------------ engine data
std::string modelname; // model name
mjOption option; // options
@@ -307,5 +295,11 @@ class mjCModel : private mjmModel {
mjCError errInfo; // last error info
int fixCount; // how many bodies have been fixed
std::vector<mjtNum> qpos0; // save qpos0, to recognize changed key_qpos in write
// variable-size attributes
std::string meshdir_;
std::string texturedir_;
std::string spec_meshdir_;
std::string spec_texturedir_;
};
#endif // MUJOCO_SRC_USER_USER_MODEL_H_
+4 -4
View File
@@ -1246,7 +1246,7 @@ void mjCFrame::Compile() {
}
CopyFromSpec();
const char* err = alt_.Set(quat, model->degree, model->euler);
const char* err = alt_.Set(quat, model->spec.degree, model->spec.euler);
if (err) {
throw mjCError(this, "orientation specification error '%s' in site %d", err, id);
}
@@ -2599,7 +2599,7 @@ void mjCHField::Compile(const mjVFS* vfs) {
throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str());
}
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir, file_);
string filename = mjuu_makefullname(model->modelfiledir, model->meshdir_, file_);
mjResource* resource = LoadResource(filename, vfs);
try {
@@ -3218,7 +3218,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
}
// make filename
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, cubefiles_[i]);
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir_, cubefiles_[i]);
// load PNG or custom
unsigned int w, h;
@@ -3318,7 +3318,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
}
// make filename
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir, file_);
string filename = mjuu_makefullname(model->modelfiledir, model->texturedir_, file_);
// dispatch
if (type==mjTEXTURE_2D) {
+3 -3
View File
@@ -376,9 +376,9 @@ mjCModel* mjParseXML(const char* filename, const mjVFS* vfs,
// set reasonable default for parsing a URDF
// this is separate from the Parser to allow multiple URDFs to be loaded.
model->strippath = true;
model->fusestatic = true;
model->discardvisual = true;
model->spec.strippath = true;
model->spec.fusestatic = true;
model->spec.discardvisual = true;
parser.SetModel(model);
parser.Parse(root);
+11 -6
View File
@@ -818,7 +818,7 @@ void mjXReader::Parse(XMLElement* root) {
for (XMLElement* section = FirstChildElement(root, "compiler"); section;
section = NextSiblingElement(section, "compiler")) {
Compiler(section, model);
Compiler(section, &model->spec);
}
for (XMLElement* section = FirstChildElement(root, "option"); section;
@@ -909,7 +909,7 @@ void mjXReader::Parse(XMLElement* root) {
// compiler section parser
void mjXReader::Compiler(XMLElement* section, mjCModel* mod) {
void mjXReader::Compiler(XMLElement* section, mjmModel* mod) {
string text;
int n;
@@ -945,12 +945,17 @@ void mjXReader::Compiler(XMLElement* section, mjCModel* mod) {
memcpy(mod->euler, text.c_str(), 3);
}
if (ReadAttrTxt(section, "assetdir", text)) {
mod->meshdir = text;
mod->texturedir = text;
mjm_setString(mod->meshdir, text.c_str());
mjm_setString(mod->texturedir, text.c_str());
}
// meshdir and texturedir take precedence over assetdir
ReadAttrTxt(section, "meshdir", mod->meshdir);
ReadAttrTxt(section, "texturedir", mod->texturedir);
std::string meshdir, texturedir;
if (ReadAttrTxt(section, "meshdir", meshdir)) {
mjm_setString(mod->meshdir, meshdir.c_str());
};
if (ReadAttrTxt(section, "texturedir", texturedir)) {
mjm_setString(mod->texturedir, texturedir.c_str());
}
if (MapValue(section, "discardvisual", &n, bool_map, 2)) {
mod->discardvisual = (n==1);
}
+1 -1
View File
@@ -43,7 +43,7 @@ class mjXReader : public mjXBase {
void SetTextureDir(std::string texturedir);
// XML sections embedded in all formats
static void Compiler(tinyxml2::XMLElement* section, mjCModel* mod); // compiler section
static void Compiler(tinyxml2::XMLElement* section, mjmModel* mod); // compiler section
static void Option(tinyxml2::XMLElement* section, mjOption* opt); // option section
static void Size(tinyxml2::XMLElement* section, mjCModel* mod); // size section
+4 -4
View File
@@ -821,11 +821,11 @@ void mjXWriter::Compiler(XMLElement* root) {
WriteAttrTxt(section, "convexhull", FindValue(bool_map, 2, model->convexhull));
}
WriteAttrTxt(section, "angle", "radian");
if (!model->meshdir.empty()) {
WriteAttrTxt(section, "meshdir", model->meshdir);
if (!model->get_meshdir().empty()) {
WriteAttrTxt(section, "meshdir", model->get_meshdir());
}
if (!model->texturedir.empty()) {
WriteAttrTxt(section, "texturedir", model->texturedir);
if (!model->get_texturedir().empty()) {
WriteAttrTxt(section, "texturedir", model->get_texturedir());
}
if (!model->usethread) {
WriteAttrTxt(section, "usethread", "false");
+4 -4
View File
@@ -93,7 +93,7 @@ void mjXURDF::Parse(
if (mjc) {
XMLElement *section;
if ((section = FindSubElem(mjc, "compiler"))) {
mjXReader::Compiler(section, model);
mjXReader::Compiler(section, &model->spec);
}
if ((section = FindSubElem(mjc, "option"))) {
@@ -106,7 +106,7 @@ void mjXURDF::Parse(
}
// enforce required compiler defaults for URDF
model->degree = false;
model->spec.degree = false;
// get model name
ReadAttrTxt(root, "name", model->modelname);
@@ -310,7 +310,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
}
}
// create geom if not discarded
if (!model->discardvisual) {
if (!model->spec.discardvisual) {
pgeom = Geom(elem, pbody, false);
// save color
@@ -563,7 +563,7 @@ mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
.value_or(default_meshscale);
// strip file name if necessary
if (model->strippath) {
if (model->spec.strippath) {
meshfile = mjuu_strippath(meshfile);
}