Add mjmEquality, mjmTendon and mjmWrap to C API.
PiperOrigin-RevId: 605853716 Change-Id: Ieb468cdec5a3032200cf1121960408a61bb08fc5
This commit is contained in:
committed by
Copybara-Service
parent
4ad1dc4b84
commit
1bd6a32af2
@@ -123,6 +123,62 @@ void* mjm_addFrame(mjmBody* bodyspec, void* parentframe) {
|
||||
|
||||
|
||||
|
||||
// add equality to model
|
||||
mjmEquality* mjm_addEquality(void* model, void* defspec) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
mjCDef* def = static_cast<mjCDef*>(defspec);
|
||||
mjCEquality* equality = modelC->AddEquality(def);
|
||||
return &equality->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add tendon to model
|
||||
mjmTendon* mjm_addTendon(void* model, void* defspec) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
mjCDef* def = static_cast<mjCDef*>(defspec);
|
||||
mjCTendon* tendon = modelC->AddTendon(def);
|
||||
return &tendon->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// wrap site using tendon
|
||||
MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendonspec, const char* name) {
|
||||
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element);
|
||||
tendon->WrapSite(name);
|
||||
return &tendon->path.back()->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// wrap geom using tendon
|
||||
mjmWrap* mjm_wrapGeom(mjmTendon* tendonspec, const char* name, const char* sidesite) {
|
||||
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element);
|
||||
tendon->WrapGeom(name, sidesite);
|
||||
return &tendon->path.back()->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// wrap joint using tendon
|
||||
mjmWrap* mjm_wrapJoint(mjmTendon* tendonspec, const char* name, double coef) {
|
||||
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element);
|
||||
tendon->WrapJoint(name, coef);
|
||||
return &tendon->path.back()->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// wrap pulley using tendon
|
||||
mjmWrap* mjm_wrapPulley(mjmTendon* tendonspec, double divisor) {
|
||||
mjCTendon* tendon = reinterpret_cast<mjCTendon*>(tendonspec->element);
|
||||
tendon->WrapPulley(divisor);
|
||||
return &tendon->path.back()->spec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// add actuator to model
|
||||
mjmActuator* mjm_addActuator(void* model, void* defspec) {
|
||||
mjCModel* modelC = static_cast<mjCModel*>(model);
|
||||
|
||||
@@ -211,6 +211,53 @@ typedef struct _mjmLight {
|
||||
} mjmLight;
|
||||
|
||||
|
||||
typedef struct _mjmEquality {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // class name
|
||||
mjtEq type; // constraint type
|
||||
mjString name1; // name of object 1
|
||||
mjString name2; // name of object 2
|
||||
mjtByte active; // initial activation state
|
||||
mjtNum solref[mjNREF]; // solver reference
|
||||
mjtNum solimp[mjNIMP]; // solver impedance
|
||||
double data[mjNEQDATA]; // type-dependent data
|
||||
mjString info; // message appended to errors
|
||||
} mjmEquality;
|
||||
|
||||
|
||||
typedef struct _mjmTendon {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // class name
|
||||
int group; // group for visualization
|
||||
int limited; // does tendon have limits: 0 false, 1 true, 2 auto
|
||||
double width; // width for rendering
|
||||
mjtNum solref_limit[mjNREF]; // solver reference: tendon limits
|
||||
mjtNum solimp_limit[mjNIMP]; // solver impedance: tendon limits
|
||||
mjtNum solref_friction[mjNREF]; // solver reference: tendon friction
|
||||
mjtNum solimp_friction[mjNIMP]; // solver impedance: tendon friction
|
||||
double range[2]; // length limits
|
||||
double margin; // margin value for tendon limit detection
|
||||
double stiffness; // stiffness coefficient
|
||||
double damping; // damping coefficient
|
||||
double frictionloss; // friction loss
|
||||
double springlength[2]; // spring resting length; {-1, -1}: use qpos_spring
|
||||
mjString material; // name of material for rendering
|
||||
mjDouble userdata; // user data
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
mjString info; // message appended to errors
|
||||
} mjmTendon;
|
||||
|
||||
|
||||
typedef struct _mjmWrap {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
mjString classname; // class name
|
||||
mjString info; // message appended to errors
|
||||
} mjmWrap;
|
||||
|
||||
|
||||
typedef struct _mjmActuator {
|
||||
mjElement element; // compiler only, do not modify
|
||||
mjString name; // name
|
||||
@@ -299,6 +346,24 @@ MJAPI mjmLight* mjm_addLight(mjmBody* body, void* defspec);
|
||||
// Add frame to body.
|
||||
MJAPI void* mjm_addFrame(mjmBody* body, void* parentframe);
|
||||
|
||||
// Add equality to model.
|
||||
MJAPI mjmEquality* mjm_addEquality(void* model, void* defspec);
|
||||
|
||||
// Add tendon to model.
|
||||
MJAPI mjmTendon* mjm_addTendon(void* model, void* defspec);
|
||||
|
||||
// Wrap site using tendon.
|
||||
MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendon, const char* name);
|
||||
|
||||
// Wrap geom using tendon.
|
||||
MJAPI mjmWrap* mjm_wrapGeom(mjmTendon* tendon, const char* name, const char* sidesite);
|
||||
|
||||
// Wrap joint using tendon.
|
||||
MJAPI mjmWrap* mjm_wrapJoint(mjmTendon* tendon, const char* name, double coef);
|
||||
|
||||
// Wrap pulley using tendon.
|
||||
MJAPI mjmWrap* mjm_wrapPulley(mjmTendon* tendon, double divisor);
|
||||
|
||||
// Add actuator to model.
|
||||
MJAPI mjmActuator* mjm_addActuator(void* model, void* defspec);
|
||||
|
||||
@@ -365,6 +430,12 @@ MJAPI void mjm_defaultCamera(mjmCamera& camera);
|
||||
// Default light attributes.
|
||||
MJAPI void mjm_defaultLight(mjmLight& light);
|
||||
|
||||
// Default equality attributes.
|
||||
MJAPI void mjm_defaultEquality(mjmEquality& equality);
|
||||
|
||||
// Default tendon attributes.
|
||||
MJAPI void mjm_defaultTendon(mjmTendon& tendon);
|
||||
|
||||
// Default actuator attributes.
|
||||
MJAPI void mjm_defaultActuator(mjmActuator& actuator);
|
||||
|
||||
|
||||
+39
-39
@@ -139,7 +139,7 @@ void mjCComposite::SetDefault(void) {
|
||||
for (int i=0; i<mjNCOMPKINDS; i++) {
|
||||
def[i].geom.spec.group = 3;
|
||||
def[i].site.spec.group = 3;
|
||||
def[i].tendon.group = 3;
|
||||
def[i].tendon.spec.group = 3;
|
||||
}
|
||||
|
||||
// set default joint
|
||||
@@ -154,7 +154,7 @@ void mjCComposite::SetDefault(void) {
|
||||
(type==mjCOMPTYPE_GRID && tmpdim==1)) {
|
||||
for (int i=0; i<mjNCOMPKINDS; i++) {
|
||||
def[i].geom.spec.group = 0;
|
||||
def[i].tendon.group = 0;
|
||||
def[i].tendon.spec.group = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +170,8 @@ void mjCComposite::SetDefault(void) {
|
||||
case mjCOMPTYPE_GRID: // grid
|
||||
|
||||
// hard main tendon fix
|
||||
AdjustSoft(def[mjCOMPKIND_TENDON].equality.solref,
|
||||
def[mjCOMPKIND_TENDON].equality.solimp, 0);
|
||||
AdjustSoft(def[mjCOMPKIND_TENDON].equality.spec.solref,
|
||||
def[mjCOMPKIND_TENDON].equality.spec.solimp, 0);
|
||||
|
||||
break;
|
||||
|
||||
@@ -200,12 +200,12 @@ void mjCComposite::SetDefault(void) {
|
||||
|
||||
// soft fix everywhere
|
||||
for (int i=0; i<mjNCOMPKINDS; i++) {
|
||||
AdjustSoft(def[i].equality.solref, def[i].equality.solimp, 1);
|
||||
AdjustSoft(def[i].equality.spec.solref, def[i].equality.spec.solimp, 1);
|
||||
}
|
||||
|
||||
// hard main tendon fix
|
||||
AdjustSoft(def[mjCOMPKIND_TENDON].equality.solref,
|
||||
def[mjCOMPKIND_TENDON].equality.solimp, 0);
|
||||
AdjustSoft(def[mjCOMPKIND_TENDON].equality.spec.solref,
|
||||
def[mjCOMPKIND_TENDON].equality.spec.solimp, 0);
|
||||
break;
|
||||
default:
|
||||
// SHOULD NOT OCCUR
|
||||
@@ -535,18 +535,18 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int
|
||||
mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1);
|
||||
|
||||
// create tendon
|
||||
mjCTendon* ten = model->AddTendon(def + mjCOMPKIND_TENDON);
|
||||
ten->def = model->defaults[0];
|
||||
ten->name = txt0;
|
||||
mjmTendon* ten = mjm_addTendon(model, def + mjCOMPKIND_TENDON);
|
||||
mjm_setDefault(ten->element, model->defaults[0]);
|
||||
mjm_setString(ten->name, txt0);
|
||||
ten->group = 4;
|
||||
ten->WrapSite(txt1);
|
||||
ten->WrapSite(txt2);
|
||||
mjm_wrapSite(ten, txt1);
|
||||
mjm_wrapSite(ten, txt2);
|
||||
|
||||
// add equality constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_TENDON);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_TENDON);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_TENDON;
|
||||
eq->name1 = ten->name;
|
||||
mjm_setString(eq->name1, mjm_getString(ten->name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,10 +657,10 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err
|
||||
ten->WrapSite(txt2);
|
||||
|
||||
// add equality constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_TENDON);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_TENDON);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_TENDON;
|
||||
eq->name1 = ten->name;
|
||||
mjm_setString(eq->name1, ten->name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -928,12 +928,12 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err
|
||||
char txt2[200];
|
||||
|
||||
// add equality constraint
|
||||
mjCEquality* eq = model->AddEquality();
|
||||
mjmEquality* eq = mjm_addEquality(model, 0);
|
||||
eq->type = mjEQ_CONNECT;
|
||||
mju::sprintf_arr(txt, "%sB0", prefix.c_str());
|
||||
mju::sprintf_arr(txt2, "%sB%d", prefix.c_str(), count[0]-1);
|
||||
eq->name1 = txt;
|
||||
eq->name2 = txt2;
|
||||
mjm_setString(eq->name1, txt);
|
||||
mjm_setString(eq->name2, txt2);
|
||||
mjuu_setvec(eq->data, -0.5*spacing, 0, 0);
|
||||
mju_copy(eq->solref, solrefsmooth, mjNREF);
|
||||
mju_copy(eq->solimp, solimpsmooth, mjNIMP);
|
||||
@@ -1019,10 +1019,10 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
|
||||
mjuu_setvec(jnt->axis, 1, 0, 0);
|
||||
|
||||
// add constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_TWIST);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_TWIST);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_JOINT;
|
||||
eq->name1 = mjm_getString(jnt->name);
|
||||
mjm_setString(eq->name1, mjm_getString(jnt->name));
|
||||
}
|
||||
|
||||
// add stretch joint
|
||||
@@ -1037,10 +1037,10 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i
|
||||
mjuu_setvec(jnt->axis, 1, 0, 0);
|
||||
|
||||
// add constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_STRETCH);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_STRETCH);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_JOINT;
|
||||
eq->name1 = mjm_getString(jnt->name);
|
||||
mjm_setString(eq->name1, mjm_getString(jnt->name));
|
||||
}
|
||||
|
||||
return body;
|
||||
@@ -1158,10 +1158,10 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
|
||||
mjuu_setvec(jnt->axis, 0, 0, 1);
|
||||
|
||||
// add fix constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_JOINT);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_JOINT);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_JOINT;
|
||||
eq->name1 = mjm_getString(jnt->name);
|
||||
mjm_setString(eq->name1, mjm_getString(jnt->name));
|
||||
|
||||
// add joint to tendon
|
||||
ten->WrapJoint(std::string(mjm_getString(jnt->name)), 1);
|
||||
@@ -1178,12 +1178,12 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
|
||||
char txt2[200];
|
||||
mju::sprintf_arr(txt2,
|
||||
"%sJ%d_%d_%d", prefix.c_str(), ix1, iy1, iz1);
|
||||
mjCEquality* eqn = model->AddEquality();
|
||||
mjmEquality* eqn = mjm_addEquality(model, 0);
|
||||
mju_copy(eqn->solref, solrefsmooth, mjNREF);
|
||||
mju_copy(eqn->solimp, solimpsmooth, mjNIMP);
|
||||
eqn->type = mjEQ_JOINT;
|
||||
eqn->name1 = txt;
|
||||
eqn->name2 = txt2;
|
||||
mjm_setString(eqn->name1, txt);
|
||||
mjm_setString(eqn->name2, txt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1192,10 +1192,10 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro
|
||||
}
|
||||
|
||||
// finalize fixed tendon
|
||||
mjCEquality* eqt = model->AddEquality(def + mjCOMPKIND_TENDON);
|
||||
eqt->def = model->defaults[0];
|
||||
mjmEquality* eqt = mjm_addEquality(model, def + mjCOMPKIND_TENDON);
|
||||
mjm_setDefault(eqt->element, model->defaults[0]);
|
||||
eqt->type = mjEQ_TENDON;
|
||||
eqt->name1 = ten->name;
|
||||
mjm_setString(eqt->name1, ten->name.c_str());
|
||||
|
||||
// skin
|
||||
if (skin) {
|
||||
@@ -1228,10 +1228,10 @@ void mjCComposite::MakeShear(mjCModel* model) {
|
||||
ten->name = txt;
|
||||
|
||||
// equality constraint
|
||||
mjCEquality* eq = model->AddEquality(def + mjCOMPKIND_SHEAR);
|
||||
eq->def = model->defaults[0];
|
||||
mjmEquality* eq = mjm_addEquality(model, def + mjCOMPKIND_SHEAR);
|
||||
mjm_setDefault(eq->element, model->defaults[0]);
|
||||
eq->type = mjEQ_TENDON;
|
||||
eq->name1 = txt;
|
||||
mjm_setString(eq->name1, txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,11 +478,11 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz
|
||||
|
||||
// create edge equality constraint
|
||||
if (equality) {
|
||||
mjCEquality *pe = model->AddEquality(&def);
|
||||
pe->def = model->defaults[0];
|
||||
mjmEquality* pe = mjm_addEquality(model, &def);
|
||||
mjm_setDefault(pe->element, model->defaults[0]);
|
||||
pe->type = mjEQ_FLEX;
|
||||
pe->active = true;
|
||||
pe->name1 = name;
|
||||
mjm_setString(pe->name1, name.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -134,6 +134,39 @@ void mjm_defaultLight(mjmLight& light) {
|
||||
|
||||
|
||||
|
||||
// Default equality attributes.
|
||||
void mjm_defaultEquality(mjmEquality& equality) {
|
||||
memset(&equality, 0, sizeof(mjmEquality));
|
||||
equality.type = mjEQ_CONNECT;
|
||||
equality.active = 1;
|
||||
mj_defaultSolRefImp(equality.solref, equality.solimp);
|
||||
equality.data[1] = 1;
|
||||
equality.data[10] = 1; // torque:force ratio
|
||||
}
|
||||
|
||||
|
||||
|
||||
// default tendon attributes
|
||||
void mjm_defaultTendon(mjmTendon& tendon) {
|
||||
memset(&tendon, 0, sizeof(mjmTendon));
|
||||
tendon.group = 0;
|
||||
tendon.width = 0.003;
|
||||
tendon.limited = 2;
|
||||
tendon.range[0] = 0;
|
||||
tendon.range[1] = 0;
|
||||
mj_defaultSolRefImp(tendon.solref_limit, tendon.solimp_limit);
|
||||
mj_defaultSolRefImp(tendon.solref_friction, tendon.solimp_friction);
|
||||
tendon.margin = 0;
|
||||
tendon.stiffness = 0;
|
||||
tendon.damping = 0;
|
||||
tendon.frictionloss = 0;
|
||||
tendon.springlength[0] = tendon.springlength[1] = -1;
|
||||
tendon.rgba[0] = tendon.rgba[1] = tendon.rgba[2] = 0.5f;
|
||||
tendon.rgba[3] = 1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// default actuator attributes
|
||||
void mjm_defaultActuator(mjmActuator& actuator) {
|
||||
memset(&actuator, 0, sizeof(mjmActuator));
|
||||
|
||||
@@ -2022,7 +2022,7 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
// find equality constraint referencing this flex
|
||||
m->flex_edgeequality[i] = 0;
|
||||
for (int k=0; k<(int)equalities.size(); k++) {
|
||||
if (equalities[k]->type==mjEQ_FLEX && equalities[k]->name1==pfl->name) {
|
||||
if (equalities[k]->type==mjEQ_FLEX && equalities[k]->name1_==pfl->name) {
|
||||
m->flex_edgeequality[i] = 1;
|
||||
break;
|
||||
}
|
||||
@@ -2251,7 +2251,7 @@ void mjCModel::CopyObjects(mjModel* m) {
|
||||
m->tendon_frictionloss[i] = (mjtNum)pte->frictionloss;
|
||||
m->tendon_lengthspring[2*i] = (mjtNum)pte->springlength[0];
|
||||
m->tendon_lengthspring[2*i+1] = (mjtNum)pte->springlength[1];
|
||||
copyvec(m->tendon_user+nuser_tendon*i, pte->userdata.data(), nuser_tendon);
|
||||
copyvec(m->tendon_user+nuser_tendon*i, pte->get_userdata().data(), nuser_tendon);
|
||||
copyvec(m->tendon_rgba+4*i, pte->rgba, 4);
|
||||
|
||||
// set wraps
|
||||
@@ -2914,7 +2914,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
||||
if (nuser_tendon == -1) {
|
||||
nuser_tendon = 0;
|
||||
for (int i=0; i<tendons.size(); i++) {
|
||||
nuser_tendon = mjMAX(nuser_tendon, tendons[i]->userdata.size());
|
||||
nuser_tendon = mjMAX(nuser_tendon, tendons[i]->spec_userdata_.size());
|
||||
}
|
||||
}
|
||||
if (nuser_actuator == -1) {
|
||||
@@ -3480,7 +3480,7 @@ bool mjCModel::CopyBack(const mjModel* m) {
|
||||
tendons[i]->frictionloss = (double)m->tendon_frictionloss[i];
|
||||
|
||||
if (nuser_tendon) {
|
||||
copyvec(tendons[i]->userdata.data(), m->tendon_user + nuser_tendon*i, nuser_tendon);
|
||||
copyvec(tendons[i]->userdata_.data(), m->tendon_user + nuser_tendon*i, nuser_tendon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+87
-38
@@ -474,7 +474,7 @@ void mjCDef::Compile(const mjCModel* model) {
|
||||
geom.userdata_.resize(model->nuser_geom);
|
||||
site.userdata_.resize(model->nuser_site);
|
||||
camera.userdata_.resize(model->nuser_cam);
|
||||
tendon.userdata.resize(model->nuser_tendon);
|
||||
tendon.userdata_.resize(model->nuser_tendon);
|
||||
actuator.userdata_.resize(model->nuser_actuator);
|
||||
}
|
||||
|
||||
@@ -3509,33 +3509,55 @@ void mjCBodyPair::Compile(void) {
|
||||
|
||||
// initialize default constraint
|
||||
mjCEquality::mjCEquality(mjCModel* _model, mjCDef* _def) {
|
||||
// set defaults
|
||||
type = mjEQ_CONNECT;
|
||||
name1.clear();
|
||||
name2.clear();
|
||||
active = true;
|
||||
mj_defaultSolRefImp(solref, solimp);
|
||||
|
||||
mjuu_zerovec(data, mjNEQDATA);
|
||||
data[1] = 1;
|
||||
data[10] = 1; // torque:force ratio
|
||||
mjm_defaultEquality(spec);
|
||||
|
||||
// clear internal variables
|
||||
spec_name1_.clear();
|
||||
spec_name2_.clear();
|
||||
obj1id = obj2id = -1;
|
||||
|
||||
// reset to default if given
|
||||
if (_def) {
|
||||
_def->equality.CopyFromSpec();
|
||||
*this = _def->equality;
|
||||
}
|
||||
|
||||
// set model, def
|
||||
model = _model;
|
||||
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
||||
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
PointToLocal();
|
||||
|
||||
// in case this camera is not compiled
|
||||
CopyFromSpec();
|
||||
}
|
||||
|
||||
|
||||
void mjCEquality::PointToLocal() {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.name1 = (mjString)&spec_name1_;
|
||||
spec.name2 = (mjString)&spec_name2_;
|
||||
spec.info = (mjString)&info;
|
||||
}
|
||||
|
||||
|
||||
void mjCEquality::CopyFromSpec() {
|
||||
*static_cast<mjmEquality*>(this) = spec;
|
||||
name1_ = spec_name1_;
|
||||
name2_ = spec_name2_;
|
||||
name1 = (mjString)&name1_;
|
||||
name2 = (mjString)&name2_;
|
||||
}
|
||||
|
||||
|
||||
// compiler
|
||||
void mjCEquality::Compile(void) {
|
||||
CopyFromSpec();
|
||||
|
||||
mjtObj objtype;
|
||||
mjCBase *px1, *px2;
|
||||
mjtJoint jt1, jt2;
|
||||
@@ -3554,17 +3576,17 @@ void mjCEquality::Compile(void) {
|
||||
}
|
||||
|
||||
// find object 1, get id
|
||||
px1 = model->FindObject(objtype, name1);
|
||||
px1 = model->FindObject(objtype, name1_);
|
||||
if (!px1) {
|
||||
throw mjCError(this, "unknown element '%s' in equality constraint %d", name1.c_str(), id);
|
||||
throw mjCError(this, "unknown element '%s' in equality constraint %d", name1_.c_str(), id);
|
||||
}
|
||||
obj1id = px1->id;
|
||||
|
||||
// find object 2, get id
|
||||
if (!name2.empty()) {
|
||||
px2 = model->FindObject(objtype, name2);
|
||||
if (!name2_.empty()) {
|
||||
px2 = model->FindObject(objtype, name2_);
|
||||
if (!px2) {
|
||||
throw mjCError(this, "unknown element '%s' in equality constraint %d", name2.c_str(), id);
|
||||
throw mjCError(this, "unknown element '%s' in equality constraint %d", name2_.c_str(), id);
|
||||
}
|
||||
obj2id = px2->id;
|
||||
}
|
||||
@@ -3587,12 +3609,12 @@ void mjCEquality::Compile(void) {
|
||||
|
||||
// make sure flex is not rigid
|
||||
if (type==mjEQ_FLEX && model->flexes[obj1id]->rigid) {
|
||||
throw mjCError(this, "rigid flex '%s' in equality constraint %d", name1.c_str(), id);
|
||||
throw mjCError(this, "rigid flex '%s' in equality constraint %d", name1_.c_str(), id);
|
||||
}
|
||||
|
||||
// make sure the two objects are different
|
||||
if (obj1id==obj2id) {
|
||||
throw mjCError(this, "element '%s' is repeated in equality constraint %d", name1.c_str(), id);
|
||||
throw mjCError(this, "element '%s' is repeated in equality constraint %d", name1_.c_str(), id);
|
||||
}
|
||||
|
||||
// make sure joints are scalar
|
||||
@@ -3613,25 +3635,11 @@ void mjCEquality::Compile(void) {
|
||||
|
||||
// constructor
|
||||
mjCTendon::mjCTendon(mjCModel* _model, mjCDef* _def) {
|
||||
// tendon defaults
|
||||
group = 0;
|
||||
material_.clear();
|
||||
width = 0.003;
|
||||
limited = 2;
|
||||
range[0] = 0;
|
||||
range[1] = 0;
|
||||
mj_defaultSolRefImp(solref_limit, solimp_limit);
|
||||
mj_defaultSolRefImp(solref_friction, solimp_friction);
|
||||
margin = 0;
|
||||
stiffness = 0;
|
||||
damping = 0;
|
||||
frictionloss = 0;
|
||||
springlength[0] = springlength[1] = -1;
|
||||
rgba[0] = rgba[1] = rgba[2] = 0.5f;
|
||||
rgba[3] = 1.0f;
|
||||
userdata.clear();
|
||||
mjm_defaultTendon(spec);
|
||||
|
||||
// clear internal variables
|
||||
spec_material_.clear();
|
||||
spec_userdata_.clear();
|
||||
path.clear();
|
||||
matid = -1;
|
||||
|
||||
@@ -3643,6 +3651,33 @@ mjCTendon::mjCTendon(mjCModel* _model, mjCDef* _def) {
|
||||
// set model, def
|
||||
model = _model;
|
||||
def = (_def ? _def : (_model ? _model->defaults[0] : 0));
|
||||
|
||||
// point to local (needs to be after defaults)
|
||||
PointToLocal();
|
||||
|
||||
// in case this camera is not compiled
|
||||
CopyFromSpec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCTendon::PointToLocal() {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.material = (mjString)&spec_material_;
|
||||
spec.userdata = (mjDouble)&spec_userdata_;
|
||||
spec.info = (mjString)&info;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCTendon::CopyFromSpec() {
|
||||
*static_cast<mjmTendon*>(this) = spec;
|
||||
material_ = spec_material_;
|
||||
userdata_ = spec_userdata_;
|
||||
material = (mjString)&material_;
|
||||
userdata = (mjDouble)&userdata_;
|
||||
}
|
||||
|
||||
|
||||
@@ -3741,12 +3776,14 @@ mjCWrap* mjCTendon::GetWrap(int id) {
|
||||
|
||||
// compiler
|
||||
void mjCTendon::Compile(void) {
|
||||
CopyFromSpec();
|
||||
|
||||
// resize userdata
|
||||
if (userdata.size() > model->nuser_tendon) {
|
||||
if (userdata_.size() > model->nuser_tendon) {
|
||||
throw mjCError(this, "user has more values than nuser_tendon in tendon '%s' (id = %d)",
|
||||
name.c_str(), id);
|
||||
}
|
||||
userdata.resize(model->nuser_tendon);
|
||||
userdata_.resize(model->nuser_tendon);
|
||||
|
||||
// check for empty path
|
||||
int sz = (int)path.size();
|
||||
@@ -3880,6 +3917,18 @@ mjCWrap::mjCWrap(mjCModel* _model, mjCTendon* _tendon) {
|
||||
sideid = -1;
|
||||
prm = 0;
|
||||
sidesite.clear();
|
||||
|
||||
// point to local
|
||||
PointToLocal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void mjCWrap::PointToLocal() {
|
||||
spec.element = (mjElement)this;
|
||||
spec.name = (mjString)&name;
|
||||
spec.classname = (mjString)&classname;
|
||||
spec.info = (mjString)&info;
|
||||
}
|
||||
|
||||
|
||||
@@ -4528,7 +4577,7 @@ void mjCSensor::Compile(void) {
|
||||
}
|
||||
|
||||
// make sure tendon has limit
|
||||
if (!((mjCTendon*)obj)->limited) {
|
||||
if (!((mjCTendon*)obj)->spec.limited) {
|
||||
throw mjCError(this, "tendon must be limited in sensor '%s' (id = %d)", name.c_str(), id);
|
||||
}
|
||||
|
||||
|
||||
+39
-29
@@ -1016,21 +1016,20 @@ class mjCBodyPair : public mjCBase {
|
||||
//------------------------- class mjCEquality ------------------------------------------------------
|
||||
// Describes an equality constraint
|
||||
|
||||
class mjCEquality : public mjCBase {
|
||||
class mjCEquality : public mjCBase, private mjmEquality {
|
||||
friend class mjCDef;
|
||||
friend class mjCBody;
|
||||
friend class mjCModel;
|
||||
friend class mjXWriter;
|
||||
|
||||
public:
|
||||
// variables set by user
|
||||
mjtEq type; // constraint type
|
||||
std::string name1; // name of object 1
|
||||
std::string name2; // name of object 2
|
||||
bool active; // initial activation state
|
||||
mjtNum solref[mjNREF]; // solver reference
|
||||
mjtNum solimp[mjNIMP]; // solver impedance
|
||||
double data[mjNEQDATA]; // type-dependent data
|
||||
mjmEquality spec;
|
||||
using mjCBase::name;
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
|
||||
void CopyFromSpec();
|
||||
void PointToLocal();
|
||||
|
||||
private:
|
||||
mjCEquality(mjCModel* = 0, mjCDef* = 0); // constructor
|
||||
@@ -1038,6 +1037,11 @@ class mjCEquality : public mjCBase {
|
||||
|
||||
int obj1id; // id of object 1
|
||||
int obj2id; // id of object 2
|
||||
|
||||
std::string name1_;
|
||||
std::string name2_;
|
||||
std::string spec_name1_;
|
||||
std::string spec_name2_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1045,12 +1049,17 @@ class mjCEquality : public mjCBase {
|
||||
//------------------------- class mjCTendon --------------------------------------------------------
|
||||
// Describes a tendon
|
||||
|
||||
class mjCTendon : public mjCBase {
|
||||
class mjCTendon : public mjCBase, private mjmTendon {
|
||||
friend class mjCDef;
|
||||
friend class mjCModel;
|
||||
friend class mjXWriter;
|
||||
|
||||
public:
|
||||
mjmTendon spec;
|
||||
using mjCBase::name;
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
|
||||
void set_material(std::string _material) { material_ = _material; }
|
||||
std::string& get_material() { return material_; }
|
||||
void del_material() { material_.clear(); }
|
||||
@@ -1064,32 +1073,26 @@ class mjCTendon : public mjCBase {
|
||||
// API for access to wrapping objects
|
||||
int NumWraps(void); // number of wraps
|
||||
mjCWrap* GetWrap(int); // pointer to wrap
|
||||
std::vector<mjCWrap*> path; // wrapping objects
|
||||
|
||||
// variables set by user
|
||||
int group; // group for visualization
|
||||
int limited; // does tendon have limits: 0 false, 1 true, 2 auto
|
||||
double width; // width for rendering
|
||||
mjtNum solref_limit[mjNREF]; // solver reference: tendon limits
|
||||
mjtNum solimp_limit[mjNIMP]; // solver impedance: tendon limits
|
||||
mjtNum solref_friction[mjNREF]; // solver reference: tendon friction
|
||||
mjtNum solimp_friction[mjNIMP]; // solver impedance: tendon friction
|
||||
double range[2]; // length limits
|
||||
double margin; // margin value for tendon limit detection
|
||||
double stiffness; // stiffness coefficient
|
||||
double damping; // damping coefficient
|
||||
double frictionloss; // friction loss
|
||||
double springlength[2]; // spring resting length; {-1, -1}: use qpos_spring
|
||||
std::vector<double> userdata; // user data
|
||||
float rgba[4]; // rgba when material is omitted
|
||||
// used by mjXWriter and mjCModel
|
||||
const std::vector<double>& get_userdata() { return userdata_; }
|
||||
|
||||
void CopyFromSpec();
|
||||
void PointToLocal();
|
||||
|
||||
private:
|
||||
mjCTendon(mjCModel* = 0, mjCDef* = 0); // constructor
|
||||
~mjCTendon(); // destructor
|
||||
void Compile(void); // compiler
|
||||
|
||||
std::string material_; // name of material for rendering
|
||||
int matid; // material id for rendering
|
||||
std::vector<mjCWrap*> path; // wrapping objects
|
||||
|
||||
// variable-size data
|
||||
std::string material_;
|
||||
std::string spec_material_;
|
||||
std::vector<double> userdata_;
|
||||
std::vector<double> spec_userdata_;
|
||||
};
|
||||
|
||||
|
||||
@@ -1097,11 +1100,18 @@ class mjCTendon : public mjCBase {
|
||||
//------------------------- class mjCWrap ----------------------------------------------------------
|
||||
// Describes a tendon wrap object
|
||||
|
||||
class mjCWrap : public mjCBase {
|
||||
class mjCWrap : public mjCBase, private mjmWrap {
|
||||
friend class mjCTendon;
|
||||
friend class mjCModel;
|
||||
|
||||
public:
|
||||
mjmWrap spec;
|
||||
using mjCBase::name;
|
||||
using mjCBase::classname;
|
||||
using mjCBase::info;
|
||||
|
||||
void PointToLocal();
|
||||
|
||||
mjtWrap type; // wrap object type
|
||||
mjCBase* obj; // wrap object pointer
|
||||
int sideid; // side site id; -1 if not applicable
|
||||
|
||||
Reference in New Issue
Block a user