Add mjmGeom to C API.
PiperOrigin-RevId: 605302719 Change-Id: Ib4208e60cf4299473a96f62db2c9dc8c7a5b0b36
This commit is contained in:
committed by
Copybara-Service
parent
3baab3784a
commit
1fe258fb60
@@ -77,11 +77,11 @@ void* mjm_addFreeJoint(mjmBody* bodyspec) {
|
||||
|
||||
|
||||
// add geom to body
|
||||
void* mjm_addGeom(mjmBody* bodyspec, void* defspec) {
|
||||
mjmGeom* mjm_addGeom(mjmBody* bodyspec, void* defspec) {
|
||||
mjCDef* def = static_cast<mjCDef*>(defspec);
|
||||
mjCBody* body = reinterpret_cast<mjCBody*>(bodyspec->element);
|
||||
mjCGeom* geom = body->AddGeom(def);
|
||||
return geom;
|
||||
return &geom->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+48
-1
@@ -31,6 +31,13 @@ extern "C" {
|
||||
|
||||
//---------------------------------- Public structs ------------------------------------------------
|
||||
|
||||
// type of mesh
|
||||
typedef enum _mjtGeomInertia {
|
||||
mjINERTIA_VOLUME,
|
||||
mjINERTIA_SHELL,
|
||||
} mjtGeomInertia;
|
||||
|
||||
|
||||
typedef struct _mjmOrientation {
|
||||
double axisangle[4]; // rotation axis and angle
|
||||
double xyaxes[6]; // x and y axes
|
||||
@@ -69,6 +76,43 @@ typedef struct _mjmBody {
|
||||
} mjmBody;
|
||||
|
||||
|
||||
typedef struct _mjmGeom {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // classname
|
||||
mjtGeom type; // geom type
|
||||
double pos[3]; // position
|
||||
double quat[4]; // orientation
|
||||
mjmOrientation alt; // alternative orientation specifications
|
||||
int contype; // contact type
|
||||
int conaffinity; // contact affinity
|
||||
int condim; // contact dimensionality
|
||||
int group; // used for rendering
|
||||
int priority; // contact priority
|
||||
double size[3]; // geom-specific size parameters
|
||||
double friction[3]; // one-sided friction coefficients: slide, roll, spin
|
||||
double solmix; // solver mixing for contact pairs
|
||||
mjtNum solref[mjNREF]; // solver reference
|
||||
mjtNum solimp[mjNIMP]; // solver impedance
|
||||
double mass; // used to compute density
|
||||
double density; // used to compute mass and inertia (from volume)
|
||||
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
|
||||
double margin; // margin for contact detection
|
||||
double gap; // include in solver if dist<margin-gap
|
||||
mjtNum fluid_ellipsoid; // whether ellipsoid-fluid model is active
|
||||
mjtNum fluid_coefs[5]; // ellipsoid-fluid interaction coefs
|
||||
mjString material; // name of material used for rendering
|
||||
mjString hfieldname; // hfield attached to geom
|
||||
mjString meshname; // mesh attached to geom
|
||||
double fitscale; // scale mesh uniformly
|
||||
mjDouble userdata; // user data
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
mjtGeomInertia typeinertia; // selects between surface and volume inertia
|
||||
mjmPlugin plugin; // sdf plugin
|
||||
mjString info;
|
||||
} mjmGeom;
|
||||
|
||||
|
||||
typedef struct _mjmSite {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
@@ -108,7 +152,7 @@ MJAPI void* mjm_addJoint(mjmBody* body, void* defspec);
|
||||
MJAPI void* mjm_addFreeJoint(mjmBody* body);
|
||||
|
||||
// Add geom to body.
|
||||
MJAPI void* mjm_addGeom(mjmBody* body, void* defspec);
|
||||
MJAPI mjmGeom* mjm_addGeom(mjmBody* body, void* defspec);
|
||||
|
||||
// Add camera to body.
|
||||
MJAPI void* mjm_addCamera(mjmBody* body, void* defspec);
|
||||
@@ -164,6 +208,9 @@ MJAPI const char* mjm_setFullInertia(mjmBody* body, double quat[4], double inert
|
||||
// Default body attributes.
|
||||
MJAPI void mjm_defaultBody(mjmBody& body);
|
||||
|
||||
// Default geom attributes.
|
||||
MJAPI void mjm_defaultGeom(mjmGeom& geom);
|
||||
|
||||
// Default site attributes.
|
||||
MJAPI void mjm_defaultSite(mjmSite& site);
|
||||
|
||||
|
||||
+47
-47
@@ -137,7 +137,7 @@ void mjCComposite::SetDefault(void) {
|
||||
|
||||
// set all deafult groups to 3
|
||||
for (int i=0; i<mjNCOMPKINDS; i++) {
|
||||
def[i].geom.group = 3;
|
||||
def[i].geom.spec.group = 3;
|
||||
def[i].site.spec.group = 3;
|
||||
def[i].tendon.group = 3;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ void mjCComposite::SetDefault(void) {
|
||||
type==mjCOMPTYPE_CABLE ||
|
||||
(type==mjCOMPTYPE_GRID && tmpdim==1)) {
|
||||
for (int i=0; i<mjNCOMPKINDS; i++) {
|
||||
def[i].geom.group = 0;
|
||||
def[i].geom.spec.group = 0;
|
||||
def[i].tendon.group = 0;
|
||||
}
|
||||
}
|
||||
@@ -163,8 +163,8 @@ void mjCComposite::SetDefault(void) {
|
||||
case mjCOMPTYPE_PARTICLE: // particle
|
||||
|
||||
// no friction with anything
|
||||
def[0].geom.condim = 1;
|
||||
def[0].geom.priority = 1;
|
||||
def[0].geom.spec.condim = 1;
|
||||
def[0].geom.spec.priority = 1;
|
||||
break;
|
||||
|
||||
case mjCOMPTYPE_GRID: // grid
|
||||
@@ -193,7 +193,7 @@ void mjCComposite::SetDefault(void) {
|
||||
case mjCOMPTYPE_ELLIPSOID:
|
||||
|
||||
// no self-collisions
|
||||
def[0].geom.contype = 0;
|
||||
def[0].geom.spec.contype = 0;
|
||||
|
||||
// soft smoothing
|
||||
AdjustSoft(solrefsmooth, solimpsmooth, 1);
|
||||
@@ -219,9 +219,9 @@ void mjCComposite::SetDefault(void) {
|
||||
// make composite object
|
||||
bool mjCComposite::Make(mjCModel* model, mjmBody* body, char* error, int error_sz) {
|
||||
// check geom type
|
||||
if ((def[0].geom.type!=mjGEOM_SPHERE &&
|
||||
def[0].geom.type!=mjGEOM_CAPSULE &&
|
||||
def[0].geom.type!=mjGEOM_ELLIPSOID) &&
|
||||
if ((def[0].geom.spec.type!=mjGEOM_SPHERE &&
|
||||
def[0].geom.spec.type!=mjGEOM_CAPSULE &&
|
||||
def[0].geom.spec.type!=mjGEOM_ELLIPSOID) &&
|
||||
type!=mjCOMPTYPE_PARTICLE && type!=mjCOMPTYPE_CABLE) {
|
||||
return comperr(error, "Composite geom type must be sphere, capsule or ellipsoid", error_sz);
|
||||
}
|
||||
@@ -240,8 +240,8 @@ bool mjCComposite::Make(mjCModel* model, mjmBody* body, char* error, int error_s
|
||||
|
||||
// check spacing
|
||||
if (type==mjCOMPTYPE_GRID || (type==mjCOMPTYPE_PARTICLE && uservert.empty())) {
|
||||
if (spacing < mju_max(def[0].geom.size[0],
|
||||
mju_max(def[0].geom.size[1], def[0].geom.size[2]))) {
|
||||
if (spacing < mju_max(def[0].geom.spec.size[0],
|
||||
mju_max(def[0].geom.spec.size[1], def[0].geom.spec.size[2]))) {
|
||||
return comperr(error, "Spacing must be larger than geometry size",
|
||||
error_sz);
|
||||
}
|
||||
@@ -333,8 +333,8 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
|
||||
|
||||
// populate vertices and names
|
||||
if (uservert.empty()) {
|
||||
if (spacing < mju_max(def[0].geom.size[0],
|
||||
mju_max(def[0].geom.size[1], def[0].geom.size[2])))
|
||||
if (spacing < mju_max(def[0].geom.spec.size[0],
|
||||
mju_max(def[0].geom.spec.size[1], def[0].geom.spec.size[2])))
|
||||
return comperr(error, "Spacing must be larger than geometry size", error_sz);
|
||||
|
||||
for (int ix=0; ix<count[0]; ix++) {
|
||||
@@ -475,8 +475,8 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
|
||||
}
|
||||
|
||||
// add geom
|
||||
mjCGeom* g = (mjCGeom*)mjm_addGeom(b, def);
|
||||
g->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
mjmGeom* g = mjm_addGeom(b, def);
|
||||
mjm_setDefault(g->element, mjm_getDefault(body->element));
|
||||
|
||||
// add site
|
||||
mjmSite* s = mjm_addSite(b, def);
|
||||
@@ -600,11 +600,11 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
|
||||
b->pos[2] = offset[2];
|
||||
|
||||
// add geom
|
||||
mjCGeom* g = (mjCGeom*)mjm_addGeom(b, def);
|
||||
g->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
mjmGeom* g = mjm_addGeom(b, def);
|
||||
mjm_setDefault(g->element, mjm_getDefault(body->element));
|
||||
g->type = mjGEOM_SPHERE;
|
||||
mju::sprintf_arr(txt, "%sG%d_%d", prefix.c_str(), ix, iy);
|
||||
g->name = txt;
|
||||
mjm_setString(g->name, txt);
|
||||
|
||||
// add site
|
||||
mjmSite* s = mjm_addSite(b, def);
|
||||
@@ -691,9 +691,9 @@ bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int er
|
||||
}
|
||||
|
||||
// check geom type
|
||||
if (def[0].geom.type!=mjGEOM_CYLINDER &&
|
||||
def[0].geom.type!=mjGEOM_CAPSULE &&
|
||||
def[0].geom.type!=mjGEOM_BOX) {
|
||||
if (def[0].geom.spec.type!=mjGEOM_CYLINDER &&
|
||||
def[0].geom.spec.type!=mjGEOM_CAPSULE &&
|
||||
def[0].geom.spec.type!=mjGEOM_BOX) {
|
||||
return comperr(error, "Cable geom type must be sphere, capsule or box", error_sz);
|
||||
}
|
||||
|
||||
@@ -739,14 +739,14 @@ bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int er
|
||||
}
|
||||
|
||||
// add skin
|
||||
if (def[0].geom.type==mjGEOM_BOX) {
|
||||
if (def[0].geom.spec.type==mjGEOM_BOX) {
|
||||
if (skinsubgrid>0) {
|
||||
count[1]+=2;
|
||||
MakeSkin2Subgrid(model, 2*def[0].geom.size[2]);
|
||||
MakeSkin2Subgrid(model, 2*def[0].geom.spec.size[2]);
|
||||
count[1]-=2;
|
||||
} else {
|
||||
count[1]++;
|
||||
MakeSkin2(model, 2*def[0].geom.size[2]);
|
||||
MakeSkin2(model, 2*def[0].geom.spec.size[2]);
|
||||
count[1]--;
|
||||
}
|
||||
}
|
||||
@@ -826,14 +826,14 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN
|
||||
}
|
||||
|
||||
// add geom
|
||||
mjCGeom* geom = (mjCGeom*)mjm_addGeom(body, def);
|
||||
geom->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
geom->name = txt_geom;
|
||||
if (def[0].geom.type==mjGEOM_CYLINDER ||
|
||||
def[0].geom.type==mjGEOM_CAPSULE) {
|
||||
mjmGeom* geom = mjm_addGeom(body, def);
|
||||
mjm_setDefault(geom->element, mjm_getDefault(body->element));
|
||||
mjm_setString(geom->name, txt_geom);
|
||||
if (def[0].geom.spec.type==mjGEOM_CYLINDER ||
|
||||
def[0].geom.spec.type==mjGEOM_CAPSULE) {
|
||||
mjuu_zerovec(geom->fromto, 6);
|
||||
geom->fromto[3] = length;
|
||||
} else if (def[0].geom.type==mjGEOM_BOX) {
|
||||
} else if (def[0].geom.spec.type==mjGEOM_BOX) {
|
||||
mjuu_zerovec(geom->pos, 3);
|
||||
geom->pos[0] = length/2;
|
||||
geom->size[0] = length/2;
|
||||
@@ -982,10 +982,10 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
|
||||
}
|
||||
|
||||
// add geom
|
||||
mjCGeom* geom = (mjCGeom*)mjm_addGeom(body, def);
|
||||
geom->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
mjmGeom* geom = mjm_addGeom(body, def);
|
||||
mjm_setDefault(geom->element, mjm_getDefault(body->element));
|
||||
mju::sprintf_arr(txt, "%sG%d", prefix.c_str(), ix1);
|
||||
geom->name = txt;
|
||||
mjm_setString(geom->name, txt);
|
||||
mjuu_setvec(geom->pos, 0, 0, 0);
|
||||
mjuu_setvec(geom->quat, sqrt(0.5), 0, sqrt(0.5), 0);
|
||||
|
||||
@@ -1094,11 +1094,11 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
|
||||
}
|
||||
|
||||
// center geom: two times bigger
|
||||
mjCGeom* geom = (mjCGeom*)mjm_addGeom(body, def);
|
||||
geom->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
mjmGeom* geom = mjm_addGeom(body, def);
|
||||
mjm_setDefault(geom->element, mjm_getDefault(body->element));
|
||||
geom->type = mjGEOM_SPHERE;
|
||||
mju::sprintf_arr(txt, "%sGcenter", prefix.c_str());
|
||||
geom->name = txt;
|
||||
mjm_setString(geom->name, txt);
|
||||
mjuu_setvec(geom->pos, 0, 0, 0);
|
||||
geom->size[0] *= 2;
|
||||
geom->size[1] = 0;
|
||||
@@ -1135,10 +1135,10 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
|
||||
mjuu_normvec(b->alt.zaxis, 3);
|
||||
|
||||
// add geom
|
||||
mjCGeom* g = (mjCGeom*) mjm_addGeom(b, def);
|
||||
g->def = (mjCDef*)mjm_getDefault(body->element);
|
||||
mjmGeom* g = mjm_addGeom(b, def);
|
||||
mjm_setDefault(g->element, mjm_getDefault(body->element));
|
||||
mju::sprintf_arr(txt, "%sG%d_%d_%d", prefix.c_str(), ix, iy, iz);
|
||||
g->name = txt;
|
||||
mjm_setString(g->name, txt);
|
||||
|
||||
// offset inwards, enforce sphere or capsule
|
||||
if (g->type==mjGEOM_CAPSULE) {
|
||||
@@ -1469,15 +1469,15 @@ void mjCComposite::MakeCableBones(mjCModel* model, mjCSkin* skin) {
|
||||
// bind pose
|
||||
if (iy==0) {
|
||||
skin->bodyname.push_back(this_body);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.size[1]);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1); skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0); skin->bindquat.push_back(0);
|
||||
} else {
|
||||
skin->bodyname.push_back(this_body);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.size[1]);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindquat.push_back(1); skin->bindquat.push_back(0);
|
||||
skin->bindquat.push_back(0); skin->bindquat.push_back(0);
|
||||
@@ -1509,15 +1509,15 @@ void mjCComposite::MakeCableBonesSubgrid(mjCModel* model, mjCSkin* skin) {
|
||||
|
||||
// bind pose
|
||||
if (iy==0) {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.size[1]);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(-def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
} else if (iy==2) {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.size[1]);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(def[0].geom.spec.size[1]);
|
||||
skin->bindpos.push_back(0);
|
||||
} else {
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.size[0] : 0);
|
||||
skin->bindpos.push_back((ix==count[0]-1) ? -2*def[0].geom.spec.size[0] : 0);
|
||||
skin->bindpos.push_back(0);
|
||||
skin->bindpos.push_back(0);
|
||||
}
|
||||
|
||||
+35
-4
@@ -19,14 +19,14 @@
|
||||
#include "user/user_util.h"
|
||||
|
||||
|
||||
// Default body parameters
|
||||
// default body attributes
|
||||
void mjm_defaultBody(mjmBody& body) {
|
||||
memset(&body, 0, sizeof(mjmBody));
|
||||
|
||||
// set non-zero defaults
|
||||
body.fullinertia[0] = mjNAN;
|
||||
body.explicitinertial = (mjtByte)false;
|
||||
body.mocap = (mjtByte)false;
|
||||
body.explicitinertial = 0;
|
||||
body.mocap = 0;
|
||||
body.quat[0] = 1;
|
||||
body.iquat[0] = 1;
|
||||
body.pos[0] = mjNAN;
|
||||
@@ -38,8 +38,39 @@ void mjm_defaultBody(mjmBody& body) {
|
||||
}
|
||||
|
||||
|
||||
// default geom attributes
|
||||
MJAPI void mjm_defaultGeom(mjmGeom& geom) {
|
||||
memset(&geom, 0, sizeof(mjmGeom));
|
||||
|
||||
// Default site parameters
|
||||
// set non-zero defaults
|
||||
geom.fromto[0] = mjNAN;
|
||||
geom.mass = mjNAN;
|
||||
geom.type = mjGEOM_SPHERE;
|
||||
geom.contype = 1;
|
||||
geom.conaffinity = 1;
|
||||
geom.condim = 3;
|
||||
geom.friction[0] = 1;
|
||||
geom.friction[1] = 0.005;
|
||||
geom.friction[2] = 0.0001;
|
||||
geom.solmix = 1.0;
|
||||
mj_defaultSolRefImp(geom.solref, geom.solimp);
|
||||
geom.density = 1000; // water density (1000 kg / m^3)
|
||||
geom.fitscale = 1;
|
||||
geom.rgba[0] = geom.rgba[1] = geom.rgba[2] = 0.5f;
|
||||
geom.rgba[3] = 1.0f;
|
||||
geom.typeinertia = mjINERTIA_VOLUME;
|
||||
geom.quat[0] = 1;
|
||||
geom.alt.axisangle[0] = geom.alt.xyaxes[0] = geom.alt.zaxis[0] = geom.alt.euler[0] = mjNAN;
|
||||
geom.fluid_coefs[0] = 0.5; // blunt drag coefficient
|
||||
geom.fluid_coefs[1] = 0.25; // slender drag coefficient
|
||||
geom.fluid_coefs[2] = 1.5; // angular drag coefficient
|
||||
geom.fluid_coefs[3] = 1.0; // kutta lift coefficient
|
||||
geom.fluid_coefs[4] = 1.0; // magnus lift coefficient
|
||||
}
|
||||
|
||||
|
||||
|
||||
// default site attributes
|
||||
void mjm_defaultSite(mjmSite& site) {
|
||||
memset(&site, 0, sizeof(mjmSite));
|
||||
|
||||
|
||||
+22
-22
@@ -647,8 +647,8 @@ void mjCMesh::SetBoundingVolume(int faceid) {
|
||||
|
||||
|
||||
// get position
|
||||
double* mjCMesh::GetPosPtr(mjtMeshType type) {
|
||||
if (type==mjSHELL_MESH) {
|
||||
double* mjCMesh::GetPosPtr(mjtGeomInertia type) {
|
||||
if (type==mjINERTIA_SHELL) {
|
||||
return pos_surface_;
|
||||
} else {
|
||||
return pos_volume_;
|
||||
@@ -658,8 +658,8 @@ double* mjCMesh::GetPosPtr(mjtMeshType type) {
|
||||
|
||||
|
||||
// get orientation
|
||||
double* mjCMesh::GetQuatPtr(mjtMeshType type) {
|
||||
if (type==mjSHELL_MESH) {
|
||||
double* mjCMesh::GetQuatPtr(mjtGeomInertia type) {
|
||||
if (type==mjINERTIA_SHELL) {
|
||||
return quat_surface_;
|
||||
} else {
|
||||
return quat_volume_;
|
||||
@@ -1162,7 +1162,7 @@ void mjCMesh::LoadMSH(mjResource* resource) {
|
||||
}
|
||||
|
||||
|
||||
void mjCMesh::ComputeVolume(double CoM[3], mjtMeshType type,
|
||||
void mjCMesh::ComputeVolume(double CoM[3], mjtGeomInertia type,
|
||||
const double facecen[3], bool exactmeshinertia) {
|
||||
double nrm[3];
|
||||
double cen[3];
|
||||
@@ -1174,10 +1174,10 @@ void mjCMesh::ComputeVolume(double CoM[3], mjtMeshType type,
|
||||
|
||||
// compute and add volume
|
||||
const double vec[3] = {cen[0]-facecen[0], cen[1]-facecen[1], cen[2]-facecen[2]};
|
||||
double vol = type==mjSHELL_MESH ? a : mjuu_dot3(vec, nrm) * a / 3;
|
||||
double vol = type==mjINERTIA_SHELL ? a : mjuu_dot3(vec, nrm) * a / 3;
|
||||
|
||||
// if legacy computation requested, then always positive
|
||||
if (!exactmeshinertia && type==mjVOLUME_MESH) {
|
||||
if (!exactmeshinertia && type==mjINERTIA_VOLUME) {
|
||||
vol = fabs(vol);
|
||||
}
|
||||
|
||||
@@ -1316,7 +1316,7 @@ void mjCMesh::Process() {
|
||||
ComputeFaceCentroid(facecen);
|
||||
|
||||
// compute inertial properties for both inertia types
|
||||
for ( const auto type : { mjtMeshType::mjVOLUME_MESH, mjtMeshType::mjSHELL_MESH } ) {
|
||||
for ( const auto type : { mjtGeomInertia::mjINERTIA_VOLUME, mjtGeomInertia::mjINERTIA_SHELL } ) {
|
||||
double CoM[3] = {0, 0, 0};
|
||||
double inert[6] = {0, 0, 0, 0, 0, 0};
|
||||
bool exactmeshinertia = model->exactmeshinertia;
|
||||
@@ -1344,7 +1344,7 @@ void mjCMesh::Process() {
|
||||
mjuu_copyvec(GetPosPtr(type), CoM, 3);
|
||||
|
||||
// re-center mesh at CoM
|
||||
if (type==mjVOLUME_MESH || validvolume_<=0) {
|
||||
if (type==mjINERTIA_VOLUME || validvolume_<=0) {
|
||||
for (int i=0; i<nvert_; i++) {
|
||||
for (int j=0; j<3; j++) {
|
||||
vert_[3*i+j] -= CoM[j];
|
||||
@@ -1363,10 +1363,10 @@ void mjCMesh::Process() {
|
||||
|
||||
// get area, normal and center; update volume
|
||||
double a = _triangle(nrm, cen, D, E, F);
|
||||
double vol = type==mjSHELL_MESH ? a : mjuu_dot3(cen, nrm) * a / 3;
|
||||
double vol = type==mjINERTIA_SHELL ? a : mjuu_dot3(cen, nrm) * a / 3;
|
||||
|
||||
// if legacy computation requested, then always positive
|
||||
if (!exactmeshinertia && type==mjVOLUME_MESH) {
|
||||
if (!exactmeshinertia && type==mjINERTIA_VOLUME) {
|
||||
vol = fabs(vol);
|
||||
}
|
||||
|
||||
@@ -1374,7 +1374,7 @@ void mjCMesh::Process() {
|
||||
GetVolumeRef(type) += vol;
|
||||
for (int j=0; j<6; j++) {
|
||||
P[j] += def->geom.density*vol /
|
||||
(type==mjSHELL_MESH ? 12 : 20) * (
|
||||
(type==mjINERTIA_SHELL ? 12 : 20) * (
|
||||
2*(D[k[j][0]] * D[k[j][1]] +
|
||||
E[k[j][0]] * E[k[j][1]] +
|
||||
F[k[j][0]] * F[k[j][1]]) +
|
||||
@@ -1422,8 +1422,8 @@ void mjCMesh::Process() {
|
||||
|
||||
// if volume was valid, copy volume quat to shell and stop,
|
||||
// otherwise use shell quat for coordinate transformations
|
||||
if (type==mjSHELL_MESH && validvolume_>0) {
|
||||
mju_copy4(GetQuatPtr(type), GetQuatPtr(mjVOLUME_MESH));
|
||||
if (type==mjINERTIA_SHELL && validvolume_>0) {
|
||||
mju_copy4(GetQuatPtr(type), GetQuatPtr(mjINERTIA_VOLUME));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1459,7 +1459,7 @@ void mjCMesh::Process() {
|
||||
|
||||
|
||||
// check that the mesh is valid
|
||||
void mjCMesh::CheckMesh(mjtMeshType type) {
|
||||
void mjCMesh::CheckMesh(mjtGeomInertia type) {
|
||||
if (!processed_) {
|
||||
return;
|
||||
}
|
||||
@@ -1468,11 +1468,11 @@ void mjCMesh::CheckMesh(mjtMeshType type) {
|
||||
"faces of mesh '%s' have inconsistent orientation. Please check the "
|
||||
"faces containing the vertices %d and %d.",
|
||||
name.c_str(), invalidorientation_.first, invalidorientation_.second);
|
||||
if (!validarea_ && type==mjSHELL_MESH)
|
||||
if (!validarea_ && type==mjINERTIA_SHELL)
|
||||
throw mjCError(this, "mesh surface area is too small: %s", name.c_str());
|
||||
if (validvolume_<0 && type==mjVOLUME_MESH)
|
||||
if (validvolume_<0 && type==mjINERTIA_VOLUME)
|
||||
throw mjCError(this, "mesh volume is negative (misoriented triangles): %s", name.c_str());
|
||||
if (!validvolume_ && type==mjVOLUME_MESH)
|
||||
if (!validvolume_ && type==mjINERTIA_VOLUME)
|
||||
throw mjCError(this, "mesh volume is too small: %s", name.c_str());
|
||||
if (!valideigenvalue_)
|
||||
throw mjCError(this, "eigenvalue of mesh inertia must be positive: %s", name.c_str());
|
||||
@@ -1482,15 +1482,15 @@ void mjCMesh::CheckMesh(mjtMeshType type) {
|
||||
|
||||
|
||||
// get inertia pointer
|
||||
double* mjCMesh::GetInertiaBoxPtr(mjtMeshType type) {
|
||||
double* mjCMesh::GetInertiaBoxPtr(mjtGeomInertia type) {
|
||||
CheckMesh(type);
|
||||
return type==mjSHELL_MESH ? boxsz_surface_ : boxsz_volume_;
|
||||
return type==mjINERTIA_SHELL ? boxsz_surface_ : boxsz_volume_;
|
||||
}
|
||||
|
||||
|
||||
double& mjCMesh::GetVolumeRef(mjtMeshType type) {
|
||||
double& mjCMesh::GetVolumeRef(mjtGeomInertia type) {
|
||||
CheckMesh(type);
|
||||
return type==mjSHELL_MESH ? surface_ : volume_;
|
||||
return type==mjINERTIA_SHELL ? surface_ : volume_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-16
@@ -565,6 +565,7 @@ mjCDef* mjCModel::AddDef(string name, int parentid) {
|
||||
if (parentid>=0 && parentid<thisid) {
|
||||
*def = *defaults[parentid];
|
||||
defaults[parentid]->childid.push_back(thisid);
|
||||
def->MakePointerLocal();
|
||||
}
|
||||
def->parentid = parentid;
|
||||
def->name = name;
|
||||
@@ -654,8 +655,8 @@ void mjCModel::MakeLists(mjCBody* body) {
|
||||
template <class T>
|
||||
void mjCModel::DeleteMaterial(std::vector<T*>& list, std::string_view name) {
|
||||
for (T* plist : list) {
|
||||
if (name.empty() || plist->material_ == name) {
|
||||
plist->material_.clear();
|
||||
if (name.empty() || plist->get_material() == name) {
|
||||
plist->del_material();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -776,18 +777,18 @@ void mjCModel::IndexAssets(bool discard) {
|
||||
mjCGeom* pgeom = geoms[i];
|
||||
|
||||
// find material by name
|
||||
if (!pgeom->material_.empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_MATERIAL, pgeom->material_);
|
||||
if (!pgeom->get_material().empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_MATERIAL, pgeom->get_material());
|
||||
if (m) {
|
||||
pgeom->matid = m->id;
|
||||
} else {
|
||||
throw mjCError(pgeom, "material '%s' not found in geom %d", pgeom->material_.c_str(), i);
|
||||
throw mjCError(pgeom, "material '%s' not found in geom %d", pgeom->get_material().c_str(), i);
|
||||
}
|
||||
}
|
||||
|
||||
// find mesh by name
|
||||
if (!pgeom->meshname.empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_MESH, pgeom->meshname);
|
||||
if (!pgeom->get_meshname().empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_MESH, pgeom->get_meshname());
|
||||
if (m) {
|
||||
if (discard && geoms[i]->visual_) {
|
||||
// do not associate with a mesh
|
||||
@@ -803,17 +804,17 @@ void mjCModel::IndexAssets(bool discard) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw mjCError(pgeom, "mesh '%s' not found in geom %d", pgeom->meshname.c_str(), i);
|
||||
throw mjCError(pgeom, "mesh '%s' not found in geom %d", pgeom->get_meshname().c_str(), i);
|
||||
}
|
||||
}
|
||||
|
||||
// find hfield by name
|
||||
if (!pgeom->hfieldname.empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_HFIELD, pgeom->hfieldname);
|
||||
if (!pgeom->get_hfieldname().empty()) {
|
||||
mjCBase* m = FindObject(mjOBJ_HFIELD, pgeom->get_hfieldname());
|
||||
if (m) {
|
||||
pgeom->hfield = (mjCHField*)m;
|
||||
} else {
|
||||
throw mjCError(pgeom, "hfield '%s' not found in geom %d", pgeom->hfieldname.c_str(), i);
|
||||
throw mjCError(pgeom, "hfield '%s' not found in geom %d", pgeom->get_hfieldname().c_str(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1683,7 +1684,7 @@ void mjCModel::CopyTree(mjModel* m) {
|
||||
m->geom_margin[gid] = (mjtNum)pg->margin;
|
||||
m->geom_gap[gid] = (mjtNum)pg->gap;
|
||||
copyvec(m->geom_fluid+mjNFLUID*gid, pg->fluid, mjNFLUID);
|
||||
copyvec(m->geom_user+nuser_geom*gid, pg->userdata.data(), nuser_geom);
|
||||
copyvec(m->geom_user+nuser_geom*gid, pg->get_userdata().data(), nuser_geom);
|
||||
copyvec(m->geom_rgba+4*gid, pg->rgba, 4);
|
||||
|
||||
// determine sameframe
|
||||
@@ -2868,8 +2869,8 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
||||
|
||||
// mark meshes that need convex hull
|
||||
for (int i=0; i<geoms.size(); i++) {
|
||||
if (geoms[i]->mesh && geoms[i]->type==mjGEOM_MESH &&
|
||||
(geoms[i]->contype || geoms[i]->conaffinity)) {
|
||||
if (geoms[i]->mesh && geoms[i]->spec.type==mjGEOM_MESH &&
|
||||
(geoms[i]->spec.contype || geoms[i]->spec.conaffinity)) {
|
||||
geoms[i]->mesh->set_needhull(true);
|
||||
}
|
||||
}
|
||||
@@ -2895,7 +2896,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
||||
if (nuser_geom == -1) {
|
||||
nuser_geom = 0;
|
||||
for (int i=0; i<geoms.size(); i++) {
|
||||
nuser_geom = mjMAX(nuser_geom, geoms[i]->userdata.size());
|
||||
nuser_geom = mjMAX(nuser_geom, geoms[i]->spec_userdata_.size());
|
||||
}
|
||||
}
|
||||
if (nuser_site == -1) {
|
||||
@@ -3369,7 +3370,7 @@ bool mjCModel::CopyBack(const mjModel* m) {
|
||||
pg->gap = (double)m->geom_gap[i];
|
||||
|
||||
if (nuser_geom) {
|
||||
copyvec(pg->userdata.data(), m->geom_user + nuser_geom*i, nuser_geom);
|
||||
copyvec(pg->userdata_.data(), m->geom_user + nuser_geom*i, nuser_geom);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+101
-80
@@ -471,7 +471,7 @@ mjCDef::mjCDef(void) {
|
||||
void mjCDef::Compile(const mjCModel* model) {
|
||||
// enforce length of all default userdata arrays
|
||||
joint.userdata.resize(model->nuser_jnt);
|
||||
geom.userdata.resize(model->nuser_geom);
|
||||
geom.userdata_.resize(model->nuser_geom);
|
||||
site.userdata_.resize(model->nuser_site);
|
||||
camera.userdata.resize(model->nuser_cam);
|
||||
tendon.userdata.resize(model->nuser_tendon);
|
||||
@@ -480,6 +480,13 @@ void mjCDef::Compile(const mjCModel* model) {
|
||||
|
||||
|
||||
|
||||
// assignment operator (TODO: use overloading)
|
||||
void mjCDef::MakePointerLocal() {
|
||||
geom.MakePointerLocal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------- class mjCBase implementation -------------------------------------------
|
||||
|
||||
// constructor
|
||||
@@ -867,7 +874,7 @@ void mjCBody::GeomFrame(void) {
|
||||
if (sz==1) {
|
||||
mjuu_copyvec(ipos, sel[0]->pos, 3);
|
||||
mjuu_copyvec(iquat, sel[0]->quat, 4);
|
||||
mass = sel[0]->mass;
|
||||
mass = sel[0]->mass_;
|
||||
mjuu_copyvec(inertia, sel[0]->inertia, 3);
|
||||
}
|
||||
|
||||
@@ -876,10 +883,10 @@ void mjCBody::GeomFrame(void) {
|
||||
// compute total mass and center of mass
|
||||
mass = 0;
|
||||
for (int i=0; i<sz; i++) {
|
||||
mass += sel[i]->mass;
|
||||
com[0] += sel[i]->mass * sel[i]->pos[0];
|
||||
com[1] += sel[i]->mass * sel[i]->pos[1];
|
||||
com[2] += sel[i]->mass * sel[i]->pos[2];
|
||||
mass += sel[i]->mass_;
|
||||
com[0] += sel[i]->mass_ * sel[i]->pos[0];
|
||||
com[1] += sel[i]->mass_ * sel[i]->pos[1];
|
||||
com[2] += sel[i]->mass_ * sel[i]->pos[2];
|
||||
}
|
||||
|
||||
// check for small mass
|
||||
@@ -902,7 +909,7 @@ void mjCBody::GeomFrame(void) {
|
||||
};
|
||||
|
||||
mjuu_globalinertia(inert0, sel[i]->inertia, sel[i]->quat);
|
||||
mjuu_offcenter(inert1, sel[i]->mass, dpos);
|
||||
mjuu_offcenter(inert1, sel[i]->mass_, dpos);
|
||||
for (int j=0; j<6; j++) {
|
||||
toti[j] = toti[j] + inert0[j] + inert1[j];
|
||||
}
|
||||
@@ -1003,8 +1010,8 @@ void mjCBody::Compile(void) {
|
||||
for (int i=0; i<geoms.size(); i++) {
|
||||
geoms[i]->inferinertia = id>0 &&
|
||||
(!explicitinertial || model->inertiafromgeom == mjINERTIAFROMGEOM_TRUE) &&
|
||||
geoms[i]->group >= model->inertiagrouprange[0] &&
|
||||
geoms[i]->group <= model->inertiagrouprange[1];
|
||||
geoms[i]->spec.group >= model->inertiagrouprange[0] &&
|
||||
geoms[i]->spec.group <= model->inertiagrouprange[1];
|
||||
geoms[i]->Compile();
|
||||
}
|
||||
|
||||
@@ -1367,57 +1374,29 @@ int mjCJoint::Compile(void) {
|
||||
|
||||
// initialize default geom
|
||||
mjCGeom::mjCGeom(mjCModel* _model, mjCDef* _def) {
|
||||
// clear alternatives
|
||||
fromto[0] = mjNAN;
|
||||
_mass = mjNAN;
|
||||
mjm_defaultGeom(spec);
|
||||
|
||||
// set defaults
|
||||
type = mjGEOM_SPHERE;
|
||||
mjuu_setvec(size, 0, 0, 0);
|
||||
contype = 1;
|
||||
conaffinity = 1;
|
||||
condim = 3;
|
||||
group = 0;
|
||||
priority = 0;
|
||||
mjuu_setvec(friction, 1, 0.005, 0.0001);
|
||||
solmix = 1.0;
|
||||
mj_defaultSolRefImp(solref, solimp);
|
||||
margin = 0;
|
||||
gap = 0;
|
||||
fluid_switch = 0.0;
|
||||
// user-tunable ellipsoid-fluid interaction coefs sorted from most to least likely to need tuning
|
||||
// defaults are tuned for slender bodies in a Re 50-1000 environment
|
||||
fluid_coefs[0] = 0.5; // blunt_drag_coef
|
||||
fluid_coefs[1] = 0.25; // slender_drag_coef
|
||||
fluid_coefs[2] = 1.5; // ang_drag_coef
|
||||
fluid_coefs[3] = 1.0; // kutta_lift_coef
|
||||
fluid_coefs[4] = 1.0; // magnus_lift_coef
|
||||
for (int i = 0; i < mjNFLUID; i++){
|
||||
fluid[i] = 0;
|
||||
}
|
||||
density = 1000; // water density (1000 kg / m^3)
|
||||
meshname.clear();
|
||||
fitscale = 1;
|
||||
material_.clear();
|
||||
rgba[0] = rgba[1] = rgba[2] = 0.5f;
|
||||
rgba[3] = 1.0f;
|
||||
userdata.clear();
|
||||
typeinertia = mjVOLUME_MESH;
|
||||
inferinertia = true;
|
||||
|
||||
// clear internal variables
|
||||
mjuu_setvec(quat, 1, 0, 0, 0);
|
||||
mjuu_setvec(pos, 0, 0, 0);
|
||||
mass = 0;
|
||||
mjuu_setvec(inertia, 0, 0, 0);
|
||||
mass_ = 0;
|
||||
body = 0;
|
||||
matid = -1;
|
||||
mesh = nullptr;
|
||||
hfield = nullptr;
|
||||
visual_ = false;
|
||||
mjuu_setvec(inertia, 0, 0, 0);
|
||||
inferinertia = true;
|
||||
spec_material_.clear();
|
||||
spec_userdata_.clear();
|
||||
spec_meshname_.clear();
|
||||
spec_hfieldname_.clear();
|
||||
spec_userdata_.clear();
|
||||
|
||||
for (int i = 0; i < mjNFLUID; i++){
|
||||
fluid[i] = 0;
|
||||
}
|
||||
|
||||
// reset to default if given
|
||||
if (_def) {
|
||||
_def->geom.CopyFromSpec();
|
||||
*this = _def->geom;
|
||||
}
|
||||
|
||||
@@ -1426,8 +1405,48 @@ mjCGeom::mjCGeom(mjCModel* _model, mjCDef* _def) {
|
||||
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
plugin.name = (mjString)&plugin_name;
|
||||
plugin.instance_name = (mjString)&plugin_instance_name;
|
||||
MakePointerLocal();
|
||||
|
||||
// in case this geom is not compiled
|
||||
CopyFromSpec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// to be called after any default copy constructor
|
||||
void mjCGeom::MakePointerLocal(void) {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.info = (mjString)&info;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.userdata = (mjDouble)&spec_userdata_;
|
||||
spec.material = (mjString)&spec_material_;
|
||||
spec.meshname = (mjString)&spec_meshname_;
|
||||
spec.hfieldname = (mjString)&spec_hfieldname_;
|
||||
spec.plugin.name = (mjString)&plugin_name;
|
||||
spec.plugin.instance_name = (mjString)&plugin_instance_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCGeom::CopyFromSpec() {
|
||||
*static_cast<mjmGeom*>(this) = spec;
|
||||
userdata_ = spec_userdata_;
|
||||
hfieldname_ = spec_hfieldname_;
|
||||
meshname_ = spec_meshname_;
|
||||
material_ = spec_material_;
|
||||
userdata = (mjDouble)&userdata_;
|
||||
hfieldname = (mjString)&hfieldname_;
|
||||
meshname = (mjString)&meshname_;
|
||||
material = (mjString)&material_;
|
||||
mju_copy4(alt_.axisangle, alt.axisangle);
|
||||
mju_copy(alt_.xyaxes, alt.xyaxes, 6);
|
||||
mju_copy3(alt_.zaxis, alt.zaxis);
|
||||
mju_copy3(alt_.euler, alt.euler);
|
||||
plugin.active = spec.plugin.active;
|
||||
plugin.instance = spec.plugin.instance;
|
||||
plugin.name = spec.plugin.name;
|
||||
plugin.instance_name = spec.plugin.instance_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -1496,9 +1515,9 @@ void mjCGeom::SetInertia(void) {
|
||||
}
|
||||
|
||||
double* boxsz = mesh->GetInertiaBoxPtr(typeinertia);
|
||||
inertia[0] = mass*(boxsz[1]*boxsz[1] + boxsz[2]*boxsz[2]) / 3;
|
||||
inertia[1] = mass*(boxsz[0]*boxsz[0] + boxsz[2]*boxsz[2]) / 3;
|
||||
inertia[2] = mass*(boxsz[0]*boxsz[0] + boxsz[1]*boxsz[1]) / 3;
|
||||
inertia[0] = mass_*(boxsz[1]*boxsz[1] + boxsz[2]*boxsz[2]) / 3;
|
||||
inertia[1] = mass_*(boxsz[0]*boxsz[0] + boxsz[2]*boxsz[2]) / 3;
|
||||
inertia[2] = mass_*(boxsz[0]*boxsz[0] + boxsz[1]*boxsz[1]) / 3;
|
||||
}
|
||||
|
||||
// compute from geom shape
|
||||
@@ -1508,14 +1527,14 @@ void mjCGeom::SetInertia(void) {
|
||||
name.c_str(), id);
|
||||
switch (type) {
|
||||
case mjGEOM_SPHERE:
|
||||
inertia[0] = inertia[1] = inertia[2] = 2*mass*size[0]*size[0]/5;
|
||||
inertia[0] = inertia[1] = inertia[2] = 2*mass_*size[0]*size[0]/5;
|
||||
return;
|
||||
|
||||
case mjGEOM_CAPSULE: {
|
||||
height = 2*size[1];
|
||||
double radius = size[0];
|
||||
double sphere_mass = mass*4*radius/(4*radius + 3*height); // mass*(sphere_vol/total_vol)
|
||||
double cylinder_mass = mass - sphere_mass;
|
||||
double sphere_mass = mass_*4*radius/(4*radius + 3*height); // mass*(sphere_vol/total_vol)
|
||||
double cylinder_mass = mass_ - sphere_mass;
|
||||
// cylinder part
|
||||
inertia[0] = inertia[1] = cylinder_mass*(3*radius*radius + height*height)/12;
|
||||
inertia[2] = cylinder_mass*radius*radius/2;
|
||||
@@ -1529,21 +1548,21 @@ void mjCGeom::SetInertia(void) {
|
||||
|
||||
case mjGEOM_CYLINDER:
|
||||
height = 2*size[1];
|
||||
inertia[0] = inertia[1] = mass*(3*size[0]*size[0]+height*height)/12;
|
||||
inertia[2] = mass*size[0]*size[0]/2;
|
||||
inertia[0] = inertia[1] = mass_*(3*size[0]*size[0]+height*height)/12;
|
||||
inertia[2] = mass_*size[0]*size[0]/2;
|
||||
return;
|
||||
|
||||
case mjGEOM_ELLIPSOID:
|
||||
inertia[0] = mass*(size[1]*size[1]+size[2]*size[2])/5;
|
||||
inertia[1] = mass*(size[0]*size[0]+size[2]*size[2])/5;
|
||||
inertia[2] = mass*(size[0]*size[0]+size[1]*size[1])/5;
|
||||
inertia[0] = mass_*(size[1]*size[1]+size[2]*size[2])/5;
|
||||
inertia[1] = mass_*(size[0]*size[0]+size[2]*size[2])/5;
|
||||
inertia[2] = mass_*(size[0]*size[0]+size[1]*size[1])/5;
|
||||
return;
|
||||
|
||||
case mjGEOM_HFIELD:
|
||||
case mjGEOM_BOX:
|
||||
inertia[0] = mass*(size[1]*size[1]+size[2]*size[2])/3;
|
||||
inertia[1] = mass*(size[0]*size[0]+size[2]*size[2])/3;
|
||||
inertia[2] = mass*(size[0]*size[0]+size[1]*size[1])/3;
|
||||
inertia[0] = mass_*(size[1]*size[1]+size[2]*size[2])/3;
|
||||
inertia[1] = mass_*(size[0]*size[0]+size[2]*size[2])/3;
|
||||
inertia[2] = mass_*(size[0]*size[0]+size[1]*size[1])/3;
|
||||
return;
|
||||
|
||||
default:
|
||||
@@ -1700,7 +1719,7 @@ void mjCGeom::SetFluidCoefs(void) {
|
||||
volume * kz / std::max(mjMINVAL, 2-kz)};
|
||||
const mjtNum virtual_inertia[3] = {volume*Ixfac/5, volume*Iyfac/5, volume*Izfac/5};
|
||||
|
||||
writeFluidGeomInteraction(fluid, &fluid_switch, &fluid_coefs[0],
|
||||
writeFluidGeomInteraction(fluid, &fluid_ellipsoid, &fluid_coefs[0],
|
||||
&fluid_coefs[1], &fluid_coefs[2],
|
||||
&fluid_coefs[3], &fluid_coefs[4],
|
||||
virtual_mass, virtual_inertia);
|
||||
@@ -1767,12 +1786,14 @@ void mjCGeom::ComputeAABB(void) {
|
||||
|
||||
// compiler
|
||||
void mjCGeom::Compile(void) {
|
||||
CopyFromSpec();
|
||||
|
||||
// resize userdata
|
||||
if (userdata.size() > model->nuser_geom) {
|
||||
if (userdata_.size() > model->nuser_geom) {
|
||||
throw mjCError(this, "user has more values than nuser_geom in geom '%s' (id = %d)",
|
||||
name.c_str(), id);
|
||||
}
|
||||
userdata.resize(model->nuser_geom);
|
||||
userdata_.resize(model->nuser_geom);
|
||||
|
||||
// check type
|
||||
if (type<0 || type>=mjNGEOMTYPES) {
|
||||
@@ -1853,7 +1874,7 @@ void mjCGeom::Compile(void) {
|
||||
|
||||
// not 'fromto': try alternative
|
||||
else {
|
||||
const char* err = alt.Set(quat, model->degree, model->euler);
|
||||
const char* err = alt_.Set(quat, model->degree, model->euler);
|
||||
if (err) {
|
||||
throw mjCError(this, "orientation specification error '%s' in geom %d", err, id);
|
||||
}
|
||||
@@ -1875,7 +1896,7 @@ void mjCGeom::Compile(void) {
|
||||
mesh->FitGeom(this, meshpos);
|
||||
|
||||
// remove reference to mesh
|
||||
meshname.clear();
|
||||
meshname_.clear();
|
||||
mesh = nullptr;
|
||||
} else {
|
||||
mjuu_copyvec(meshpos, mesh->GetPosPtr(typeinertia), 3);
|
||||
@@ -1913,28 +1934,28 @@ void mjCGeom::Compile(void) {
|
||||
|
||||
// compute geom mass and inertia
|
||||
if (inferinertia) {
|
||||
if (mjuu_defined(_mass)) {
|
||||
if (_mass==0) {
|
||||
mass = 0;
|
||||
if (mjuu_defined(mass)) {
|
||||
if (mass==0) {
|
||||
mass_ = 0;
|
||||
density = 0;
|
||||
} else if (GetVolume()>mjMINVAL) {
|
||||
mass = _mass;
|
||||
density = _mass / GetVolume();
|
||||
mass_ = mass;
|
||||
density = mass / GetVolume();
|
||||
SetInertia();
|
||||
}
|
||||
} else {
|
||||
mass = density * GetVolume();
|
||||
mass_ = density * GetVolume();
|
||||
SetInertia();
|
||||
}
|
||||
|
||||
// check for negative values
|
||||
if (mass<0 || inertia[0]<0 || inertia[1]<0 || inertia[2]<0 || density<0)
|
||||
if (mass_<0 || inertia[0]<0 || inertia[1]<0 || inertia[2]<0 || density<0)
|
||||
throw mjCError(this, "mass, inertia or density are negative in geom '%s' (id = %d)",
|
||||
name.c_str(), id);
|
||||
}
|
||||
|
||||
// fluid-interaction coefficients, requires computed inertia and mass
|
||||
if (fluid_switch > 0) {
|
||||
if (fluid_ellipsoid > 0) {
|
||||
SetFluidCoefs();
|
||||
}
|
||||
|
||||
|
||||
+41
-52
@@ -86,13 +86,6 @@ typedef enum _mjtMark {
|
||||
} mjtMark;
|
||||
|
||||
|
||||
// type of mesh
|
||||
typedef enum _mjtMeshType {
|
||||
mjVOLUME_MESH,
|
||||
mjSHELL_MESH,
|
||||
} mjtMeshType;
|
||||
|
||||
|
||||
// error information
|
||||
class [[nodiscard]] mjCError {
|
||||
public:
|
||||
@@ -378,23 +371,25 @@ class mjCJoint : public mjCBase {
|
||||
//------------------------- class mjCGeom ----------------------------------------------------------
|
||||
// Describes a geometric shape belonging to a body
|
||||
|
||||
class mjCGeom : public mjCBase {
|
||||
class mjCGeom : public mjCBase, private mjmGeom {
|
||||
friend class mjCDef;
|
||||
friend class mjCMesh;
|
||||
friend class mjCPair;
|
||||
friend class mjCBody;
|
||||
friend class mjCModel;
|
||||
friend class mjCWrap;
|
||||
friend class mjXWriter;
|
||||
friend class mjXURDF;
|
||||
|
||||
public:
|
||||
using mjCBase::name;
|
||||
mjmGeom spec; // variables set by user
|
||||
double GetVolume(void); // compute geom volume
|
||||
void SetInertia(void); // compute and set geom inertia
|
||||
bool IsVisual(void) const { return visual_; }
|
||||
void SetNotVisual(void) { visual_ = false; }
|
||||
|
||||
void set_material(std::string _material) { material_ = _material; }
|
||||
std::string& get_material() { return material_; }
|
||||
bool inferinertia; // true if inertia should be computed from geom
|
||||
|
||||
// Compute all coefs modeling the interaction with the surrounding fluid.
|
||||
void SetFluidCoefs(void);
|
||||
@@ -404,56 +399,46 @@ class mjCGeom : public mjCBase {
|
||||
// sets properties of a bounding volume
|
||||
void SetBoundingVolume(mjCBoundingVolume* bv) const;
|
||||
|
||||
// variables set by user and copied into mjModel
|
||||
mjtGeom type; // geom type
|
||||
int contype; // contact type
|
||||
int conaffinity; // contact affinity
|
||||
int condim; // contact dimensionality
|
||||
int group; // used for rendering
|
||||
int priority; // contact priority
|
||||
double size[3]; // geom-specific size parameters
|
||||
double friction[3]; // one-sided friction coefficients: slide, roll, spin
|
||||
double solmix; // solver mixing for contact pairs
|
||||
mjtNum solref[mjNREF]; // solver reference
|
||||
mjtNum solimp[mjNIMP]; // solver impedance
|
||||
double margin; // margin for contact detection
|
||||
double gap; // include in solver if dist<margin-gap
|
||||
mjtNum fluid_switch; // whether ellipsoid-fluid model is active
|
||||
mjtNum fluid_coefs[5]; // tunable ellipsoid-fluid interaction coefs
|
||||
mjtNum fluid[mjNFLUID]; // compile-time fluid-interaction parameters
|
||||
std::string hfieldname; // hfield attached to geom
|
||||
std::string meshname; // mesh attached to geom
|
||||
double fitscale; // scale mesh uniformly
|
||||
std::vector<double> userdata; // user data
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
mjtMeshType typeinertia; // selects between surface and volume inertia
|
||||
bool inferinertia; // true if inertia has to be computed from geom
|
||||
|
||||
// variables set by user and used during compilation
|
||||
double _mass; // used to compute density
|
||||
double density; // used to compute mass and inertia (from volume)
|
||||
double fromto[6]; // alternative for capsule, cylinder, box, ellipsoid
|
||||
mjCAlternative alt; // alternative orientation specifications
|
||||
|
||||
// variables set by user or 'Compile'
|
||||
double pos[3]; // position
|
||||
double quat[4]; // orientation
|
||||
// used by mjXWriter and mjCModel
|
||||
const std::vector<double>& get_userdata() { return userdata_; }
|
||||
const std::string& get_hfieldname() { return spec_hfieldname_; }
|
||||
const std::string& get_meshname() { return spec_meshname_; }
|
||||
const std::string& get_material() { return spec_material_; }
|
||||
void del_material() { spec_material_.clear(); }
|
||||
|
||||
private:
|
||||
mjCGeom(mjCModel* = 0, mjCDef* = 0);
|
||||
void Compile(void); // compiler
|
||||
double GetRBound(void); // compute bounding sphere radius
|
||||
void ComputeAABB(void); // compute axis-aligned bounding box
|
||||
void CopyFromSpec(void);
|
||||
void MakePointerLocal(void);
|
||||
|
||||
std::string material_; // name of material used for rendering
|
||||
mjCAlternative alt_;
|
||||
bool visual_; // true: geom does not collide and is unreferenced
|
||||
int matid; // id of geom's material
|
||||
mjCMesh* mesh; // geom's mesh
|
||||
mjCHField* hfield; // geom's hfield
|
||||
double mass; // mass
|
||||
double mass_; // mass
|
||||
double inertia[3]; // local diagonal inertia
|
||||
double aabb[6]; // axis-aligned bounding box (center, size)
|
||||
mjCBody* body; // geom's body
|
||||
mjtNum fluid[mjNFLUID]; // compile-time fluid-interaction parameters
|
||||
|
||||
// variable-size data
|
||||
std::string hfieldname_;
|
||||
std::string meshname_;
|
||||
std::string material_;
|
||||
std::vector<double> userdata_;
|
||||
std::string spec_hfieldname_;
|
||||
std::string spec_meshname_;
|
||||
std::string spec_material_;
|
||||
std::vector<double> spec_userdata_;
|
||||
|
||||
// inherited
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
using mjCBase::plugin;
|
||||
};
|
||||
|
||||
|
||||
@@ -479,6 +464,7 @@ class mjCSite : public mjCBase, private mjmSite {
|
||||
// used by mjXWriter and mjCModel
|
||||
const std::vector<double>& get_userdata() { return userdata_; }
|
||||
const std::string& get_material() { return material_; }
|
||||
void del_material() { material_.clear(); }
|
||||
|
||||
private:
|
||||
mjCSite(mjCModel* = 0, mjCDef* = 0); // constructor
|
||||
@@ -701,12 +687,12 @@ class mjCMesh: public mjCBase {
|
||||
void set_userface(std::optional<std::vector<int>>&& userface);
|
||||
|
||||
void Compile(const mjVFS* vfs); // compiler
|
||||
double* GetPosPtr(mjtMeshType type); // get position
|
||||
double* GetQuatPtr(mjtMeshType type); // get orientation
|
||||
double* GetPosPtr(mjtGeomInertia type); // get position
|
||||
double* GetQuatPtr(mjtGeomInertia type); // get orientation
|
||||
double* GetOffsetPosPtr(); // get position offset for geom
|
||||
double* GetOffsetQuatPtr(); // get orientation offset for geom
|
||||
double* GetInertiaBoxPtr(mjtMeshType type); // get inertia box
|
||||
double& GetVolumeRef(mjtMeshType type); // get volume
|
||||
double* GetInertiaBoxPtr(mjtGeomInertia type); // get inertia box
|
||||
double& GetVolumeRef(mjtGeomInertia type); // get volume
|
||||
void FitGeom(mjCGeom* geom, double* meshpos); // approximate mesh with simple geom
|
||||
bool HasTexcoord() const; // texcoord not null
|
||||
void DelTexcoord(); // delete texcoord
|
||||
@@ -753,10 +739,10 @@ class mjCMesh: public mjCBase {
|
||||
void ApplyTransformations(); // apply user transformations
|
||||
void ComputeFaceCentroid(double[3]); // compute centroid of all faces
|
||||
void RemoveRepeated(void); // remove repeated vertices
|
||||
void CheckMesh(mjtMeshType type); // check if the mesh is valid
|
||||
void CheckMesh(mjtGeomInertia type); // check if the mesh is valid
|
||||
|
||||
// compute the volume and center-of-mass of the mesh given the face center
|
||||
void ComputeVolume(double CoM[3], mjtMeshType type, const double facecen[3],
|
||||
void ComputeVolume(double CoM[3], mjtGeomInertia type, const double facecen[3],
|
||||
bool exactmeshinertia);
|
||||
|
||||
// mesh properties that indicate a well-formed mesh
|
||||
@@ -814,6 +800,7 @@ class mjCSkin: public mjCBase {
|
||||
std::string get_file() const { return file; }
|
||||
void set_material(std::string _material) { material_ = _material; }
|
||||
std::string& get_material() { return material_; }
|
||||
void del_material() { material_.clear(); }
|
||||
|
||||
std::string file; // skin file
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
@@ -1076,6 +1063,7 @@ class mjCTendon : public mjCBase {
|
||||
public:
|
||||
void set_material(std::string _material) { material_ = _material; }
|
||||
std::string& get_material() { return material_; }
|
||||
void del_material() { material_.clear(); }
|
||||
|
||||
// API for adding wrapping objects
|
||||
void WrapSite(std::string name, std::string_view info = ""); // site
|
||||
@@ -1326,6 +1314,7 @@ class mjCDef {
|
||||
public:
|
||||
mjCDef(void); // constructor
|
||||
void Compile(const mjCModel* model); // compiler
|
||||
void MakePointerLocal();
|
||||
|
||||
// identifiers
|
||||
std::string name; // class name
|
||||
|
||||
@@ -740,8 +740,8 @@ const mjMap tkind_map[2] = {
|
||||
|
||||
// mesh type
|
||||
const mjMap meshtype_map[2] = {
|
||||
{"false", mjVOLUME_MESH},
|
||||
{"true", mjSHELL_MESH},
|
||||
{"false", mjINERTIA_VOLUME},
|
||||
{"true", mjINERTIA_SHELL},
|
||||
};
|
||||
|
||||
|
||||
@@ -1504,13 +1504,19 @@ void mjXReader::OneJoint(XMLElement* elem, mjCJoint* pjoint) {
|
||||
|
||||
|
||||
// geom element parser
|
||||
void mjXReader::OneGeom(XMLElement* elem, mjCGeom* pgeom) {
|
||||
string text;
|
||||
void mjXReader::OneGeom(XMLElement* elem, mjmGeom* pgeom) {
|
||||
string text, name, classname;
|
||||
std::vector<double> userdata;
|
||||
std::string hfieldname, meshname, material;
|
||||
int n;
|
||||
|
||||
// read attributes
|
||||
ReadAttrTxt(elem, "name", pgeom->name);
|
||||
ReadAttrTxt(elem, "class", pgeom->classname);
|
||||
if (ReadAttrTxt(elem, "name", name)) {
|
||||
mjm_setString(pgeom->name, name.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "class", classname)) {
|
||||
mjm_setString(pgeom->classname, classname.c_str());
|
||||
}
|
||||
if (MapValue(elem, "type", &n, geom_map, mjNGEOMTYPES)) {
|
||||
pgeom->type = (mjtGeom)n;
|
||||
}
|
||||
@@ -1526,18 +1532,26 @@ void mjXReader::OneGeom(XMLElement* elem, mjCGeom* pgeom) {
|
||||
ReadAttr(elem, "solimp", mjNIMP, pgeom->solimp, text, false, false);
|
||||
ReadAttr(elem, "margin", 1, &pgeom->margin, text);
|
||||
ReadAttr(elem, "gap", 1, &pgeom->gap, text);
|
||||
ReadAttrTxt(elem, "hfield", pgeom->hfieldname);
|
||||
ReadAttrTxt(elem, "mesh", pgeom->meshname);
|
||||
if (ReadAttrTxt(elem, "hfield", hfieldname)) {
|
||||
mjm_setString(pgeom->hfieldname, hfieldname.c_str());
|
||||
}
|
||||
if (ReadAttrTxt(elem, "mesh", meshname)) {
|
||||
mjm_setString(pgeom->meshname, meshname.c_str());
|
||||
}
|
||||
ReadAttr(elem, "fitscale", 1, &pgeom->fitscale, text);
|
||||
ReadAttrTxt(elem, "material", pgeom->get_material());
|
||||
if (ReadAttrTxt(elem, "material", material)) {
|
||||
mjm_setString(pgeom->material, material.c_str());
|
||||
}
|
||||
ReadAttr(elem, "rgba", 4, pgeom->rgba, text);
|
||||
if (MapValue(elem, "fluidshape", &n, fluid_map, 2)) {
|
||||
pgeom->fluid_switch = (n == 1);
|
||||
pgeom->fluid_ellipsoid = (n == 1);
|
||||
}
|
||||
ReadAttr(elem, "fluidcoef", 5, pgeom->fluid_coefs, text, false, false);
|
||||
|
||||
// read userdata
|
||||
ReadVector(elem, "user", pgeom->userdata, text);
|
||||
if (ReadVector(elem, "user", userdata, text)) {
|
||||
mjm_setDouble(pgeom->userdata, userdata.data(), userdata.size());
|
||||
}
|
||||
|
||||
// plugin sub-element
|
||||
XMLElement* eplugin = elem->FirstChildElement("plugin");
|
||||
@@ -1546,7 +1560,7 @@ void mjXReader::OneGeom(XMLElement* elem, mjCGeom* pgeom) {
|
||||
}
|
||||
|
||||
// remaining attributes
|
||||
ReadAttr(elem, "mass", 1, &pgeom->_mass, text);
|
||||
ReadAttr(elem, "mass", 1, &pgeom->mass, text);
|
||||
ReadAttr(elem, "density", 1, &pgeom->density, text);
|
||||
ReadAttr(elem, "fromto", 6, pgeom->fromto, text);
|
||||
ReadAttr(elem, "pos", 3, pgeom->pos, text);
|
||||
@@ -1555,10 +1569,11 @@ void mjXReader::OneGeom(XMLElement* elem, mjCGeom* pgeom) {
|
||||
|
||||
// compute inertia using either solid or shell geometry
|
||||
if (MapValue(elem, "shellinertia", &n, meshtype_map, 2)) {
|
||||
pgeom->typeinertia = (mjtMeshType)n;
|
||||
pgeom->typeinertia = (mjtGeomInertia)n;
|
||||
}
|
||||
|
||||
GetXMLPos(elem, pgeom);
|
||||
mjm_setString(pgeom->info,
|
||||
std::string("line = " + std::to_string(elem->GetLineNum()) + ", column = -1").c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -2153,25 +2168,29 @@ void mjXReader::OneComposite(XMLElement* elem, mjmBody* pbody, mjCDef* def) {
|
||||
// geom
|
||||
XMLElement* egeom = elem->FirstChildElement("geom");
|
||||
if (egeom) {
|
||||
std::string material;
|
||||
mjmGeom& dgeom = comp.def[0].geom.spec;
|
||||
if (MapValue(egeom, "type", &n, geom_map, mjNGEOMTYPES)) {
|
||||
comp.def[0].geom.type = (mjtGeom)n;
|
||||
dgeom.type = (mjtGeom)n;
|
||||
}
|
||||
ReadAttr(egeom, "size", 3, comp.def[0].geom.size, text, false, false);
|
||||
ReadAttrInt(egeom, "contype", &comp.def[0].geom.contype);
|
||||
ReadAttrInt(egeom, "conaffinity", &comp.def[0].geom.conaffinity);
|
||||
ReadAttrInt(egeom, "condim", &comp.def[0].geom.condim);
|
||||
ReadAttrInt(egeom, "group", &comp.def[0].geom.group);
|
||||
ReadAttrInt(egeom, "priority", &comp.def[0].geom.priority);
|
||||
ReadAttr(egeom, "friction", 3, comp.def[0].geom.friction, text, false, false);
|
||||
ReadAttr(egeom, "solmix", 1, &comp.def[0].geom.solmix, text);
|
||||
ReadAttr(egeom, "solref", mjNREF, comp.def[0].geom.solref, text, false, false);
|
||||
ReadAttr(egeom, "solimp", mjNIMP, comp.def[0].geom.solimp, text, false, false);
|
||||
ReadAttr(egeom, "margin", 1, &comp.def[0].geom.margin, text);
|
||||
ReadAttr(egeom, "gap", 1, &comp.def[0].geom.gap, text);
|
||||
ReadAttrTxt(egeom, "material", comp.def[0].geom.get_material());
|
||||
ReadAttr(egeom, "rgba", 4, comp.def[0].geom.rgba, text);
|
||||
ReadAttr(egeom, "mass", 1, &comp.def[0].geom._mass, text);
|
||||
ReadAttr(egeom, "density", 1, &comp.def[0].geom.density, text);
|
||||
ReadAttr(egeom, "size", 3, dgeom.size, text, false, false);
|
||||
ReadAttrInt(egeom, "contype", &dgeom.contype);
|
||||
ReadAttrInt(egeom, "conaffinity", &dgeom.conaffinity);
|
||||
ReadAttrInt(egeom, "condim", &dgeom.condim);
|
||||
ReadAttrInt(egeom, "group", &dgeom.group);
|
||||
ReadAttrInt(egeom, "priority", &dgeom.priority);
|
||||
ReadAttr(egeom, "friction", 3, dgeom.friction, text, false, false);
|
||||
ReadAttr(egeom, "solmix", 1, &dgeom.solmix, text);
|
||||
ReadAttr(egeom, "solref", mjNREF, dgeom.solref, text, false, false);
|
||||
ReadAttr(egeom, "solimp", mjNIMP, dgeom.solimp, text, false, false);
|
||||
ReadAttr(egeom, "margin", 1, &dgeom.margin, text);
|
||||
ReadAttr(egeom, "gap", 1, &dgeom.gap, text);
|
||||
if (ReadAttrTxt(egeom, "material", material)) {
|
||||
mjm_setString(dgeom.material, material.c_str());
|
||||
}
|
||||
ReadAttr(egeom, "rgba", 4, dgeom.rgba, text);
|
||||
ReadAttr(egeom, "mass", 1, &dgeom.mass, text);
|
||||
ReadAttr(egeom, "density", 1, &dgeom.density, text);
|
||||
}
|
||||
|
||||
// site
|
||||
@@ -2494,7 +2513,7 @@ void mjXReader::Default(XMLElement* section, int parentid) {
|
||||
else if (name=="joint") OneJoint(elem, &def->joint);
|
||||
|
||||
// read geom
|
||||
else if (name=="geom") OneGeom(elem, &def->geom);
|
||||
else if (name=="geom") OneGeom(elem, &def->geom.spec);
|
||||
|
||||
// read site
|
||||
else if (name=="site") OneSite(elem, def->site.spec);
|
||||
@@ -3067,9 +3086,9 @@ void mjXReader::Body(XMLElement* section, mjmBody* pbody, mjCFrame* frame) {
|
||||
// geom sub-element
|
||||
else if (name=="geom") {
|
||||
// create geom and parse
|
||||
mjCGeom* pgeom = (mjCGeom*)mjm_addGeom(pbody, def);
|
||||
mjmGeom* pgeom = mjm_addGeom(pbody, def);
|
||||
OneGeom(elem, pgeom);
|
||||
pgeom->SetFrame(frame);
|
||||
mjm_setFrame(pgeom->element, frame);
|
||||
}
|
||||
|
||||
// site sub-element
|
||||
|
||||
@@ -58,7 +58,7 @@ class mjXReader : public mjXBase {
|
||||
void OneSkin(tinyxml2::XMLElement* elem, mjCSkin* pskin);
|
||||
void OneMaterial(tinyxml2::XMLElement* elem, mjCMaterial* pmaterial);
|
||||
void OneJoint(tinyxml2::XMLElement* elem, mjCJoint* pjoint);
|
||||
void OneGeom(tinyxml2::XMLElement* elem, mjCGeom* pgeom);
|
||||
void OneGeom(tinyxml2::XMLElement* elem, mjmGeom* pgeom);
|
||||
void OneSite(tinyxml2::XMLElement* elem, mjmSite& site);
|
||||
void OneCamera(tinyxml2::XMLElement* elem, mjCCamera* pcamera);
|
||||
void OneLight(tinyxml2::XMLElement* elem, mjCLight* plight);
|
||||
|
||||
@@ -342,7 +342,7 @@ void mjXWriter::OneGeom(XMLElement* elem, mjCGeom* pgeom, mjCDef* def) {
|
||||
if (mjGEOMINFO[pgeom->type]) {
|
||||
WriteAttr(elem, "size", mjGEOMINFO[pgeom->type], pgeom->size, def->geom.size);
|
||||
}
|
||||
if (mjuu_defined(pgeom->_mass)) {
|
||||
if (mjuu_defined(pgeom->mass)) {
|
||||
mass = pgeom->GetVolume() * def->geom.density;
|
||||
}
|
||||
|
||||
@@ -389,11 +389,11 @@ void mjXWriter::OneGeom(XMLElement* elem, mjCGeom* pgeom, mjCDef* def) {
|
||||
WriteAttr(elem, "margin", 1, &pgeom->margin, &def->geom.margin);
|
||||
WriteAttr(elem, "gap", 1, &pgeom->gap, &def->geom.gap);
|
||||
WriteAttr(elem, "gap", 1, &pgeom->gap, &def->geom.gap);
|
||||
WriteAttrKey(elem, "fluidshape", fluid_map, 2, pgeom->fluid_switch, def->geom.fluid_switch);
|
||||
WriteAttrKey(elem, "fluidshape", fluid_map, 2, pgeom->fluid_ellipsoid, def->geom.fluid_ellipsoid);
|
||||
WriteAttr(elem, "fluidcoef", 5, pgeom->fluid_coefs, def->geom.fluid_coefs);
|
||||
WriteAttrKey(elem, "shellinertia", meshtype_map, 2, pgeom->typeinertia, def->geom.typeinertia);
|
||||
if (mjuu_defined(pgeom->_mass)) {
|
||||
WriteAttr(elem, "mass", 1, &pgeom->mass, &mass);
|
||||
if (mjuu_defined(pgeom->mass)) {
|
||||
WriteAttr(elem, "mass", 1, &pgeom->mass_, &mass);
|
||||
} else {
|
||||
WriteAttr(elem, "density", 1, &pgeom->density, &def->geom.density);
|
||||
}
|
||||
@@ -404,17 +404,17 @@ void mjXWriter::OneGeom(XMLElement* elem, mjCGeom* pgeom, mjCDef* def) {
|
||||
|
||||
// hfield and mesh attributes
|
||||
if (pgeom->type==mjGEOM_HFIELD) {
|
||||
WriteAttrTxt(elem, "hfield", pgeom->hfieldname);
|
||||
WriteAttrTxt(elem, "hfield", pgeom->get_hfieldname());
|
||||
}
|
||||
if (pgeom->type==mjGEOM_MESH || pgeom->type==mjGEOM_SDF) {
|
||||
WriteAttrTxt(elem, "mesh", pgeom->meshname);
|
||||
WriteAttrTxt(elem, "mesh", pgeom->get_meshname());
|
||||
}
|
||||
|
||||
// userdata
|
||||
if (writingdefaults) {
|
||||
WriteVector(elem, "user", pgeom->userdata);
|
||||
WriteVector(elem, "user", pgeom->get_userdata());
|
||||
} else {
|
||||
WriteVector(elem, "user", pgeom->userdata, def->geom.userdata);
|
||||
WriteVector(elem, "user", pgeom->get_userdata(), def->geom.get_userdata());
|
||||
}
|
||||
|
||||
// write plugin
|
||||
|
||||
+7
-7
@@ -223,7 +223,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
|
||||
std::string name, text;
|
||||
XMLElement *elem, *temp, *temp1;
|
||||
mjmBody *pbody, *world;
|
||||
mjCGeom* pgeom;
|
||||
mjmGeom* pgeom;
|
||||
|
||||
// get body name and pointer to mjmBody
|
||||
ReadAttrTxt(body_elem, "name", name, true);
|
||||
@@ -322,7 +322,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
|
||||
mjXUtil::ReadAttrTxt(elem, "name", geom_name);
|
||||
name = GetPrefixedName(name);
|
||||
if (urGeomNames.find(geom_name) == urGeomNames.end()) {
|
||||
pgeom->name = geom_name;
|
||||
mjm_setString(pgeom->name, geom_name.c_str());
|
||||
urGeomNames.insert(geom_name);
|
||||
} else {
|
||||
std::cerr << "WARNING: Geom with duplicate name '" << geom_name
|
||||
@@ -345,7 +345,7 @@ void mjXURDF::Body(XMLElement* body_elem) {
|
||||
mjXUtil::ReadAttrTxt(elem, "name", geom_name);
|
||||
geom_name = GetPrefixedName(geom_name);
|
||||
if (urGeomNames.find(geom_name) == urGeomNames.end()) {
|
||||
pgeom->name = geom_name;
|
||||
mjm_setString(pgeom->name, geom_name.c_str());
|
||||
urGeomNames.insert(geom_name);
|
||||
} else {
|
||||
std::cerr << "WARNING: Geom with duplicate name '" << geom_name
|
||||
@@ -501,7 +501,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) {
|
||||
|
||||
|
||||
// parse origin and geometry elements of visual or collision
|
||||
mjCGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
|
||||
mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
|
||||
XMLElement *elem, *temp;
|
||||
std::string text, meshfile;
|
||||
|
||||
@@ -509,8 +509,8 @@ mjCGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
|
||||
elem = FindSubElem(geom_elem, "geometry", true);
|
||||
|
||||
// add BOX geom, modify type later
|
||||
mjCGeom* pgeom = (mjCGeom*)mjm_addGeom(pbody, 0);
|
||||
pgeom->name = "";
|
||||
mjmGeom* pgeom = mjm_addGeom(pbody, 0);
|
||||
mjm_setString(pgeom->name, "");
|
||||
pgeom->type = mjGEOM_BOX;
|
||||
if (collision) {
|
||||
pgeom->contype = 1;
|
||||
@@ -589,7 +589,7 @@ mjCGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) {
|
||||
// set fields
|
||||
pmesh->set_file(meshfile);
|
||||
pmesh->name = meshname;
|
||||
pgeom->meshname = meshname;
|
||||
mjm_setString(pgeom->meshname, meshname.c_str());
|
||||
pmesh->set_scale(meshscale);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class mjXURDF : public mjXBase {
|
||||
void AddToTree(int n); // add body to mjCModel tree
|
||||
void Body(tinyxml2::XMLElement* body_elem); // parse body
|
||||
void Joint(tinyxml2::XMLElement* joint_elem); // parse joint
|
||||
mjCGeom* Geom(tinyxml2::XMLElement* geom_elem,
|
||||
mjmGeom* Geom(tinyxml2::XMLElement* geom_elem,
|
||||
mjmBody* pbody, bool collision); // parse origin and geometry of geom
|
||||
void Origin(tinyxml2::XMLElement* origin_elem, double* pos, double* quat); // parse origin element
|
||||
|
||||
|
||||
@@ -549,7 +549,7 @@ TEST_F(MjCMeshTest, FlippedFaceAllowedNoMass) {
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
EXPECT_THAT(model, NotNull());
|
||||
EXPECT_THAT(model, NotNull()) << error.data();
|
||||
CheckTetrahedronWasRescaled(model);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user