Add compiler settings to mjmModel.
PiperOrigin-RevId: 608908314 Change-Id: Id3b0d8c62ca710b5b6d6e423abbbddcb7e7079a1
This commit is contained in:
committed by
Copybara-Service
parent
abf6d41b7f
commit
042760eba8
+31
-3
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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_
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user