From 5e353efaafbd1ddc8cbbf27e42c80ff13e531bb0 Mon Sep 17 00:00:00 2001 From: Alessio Quaglino Date: Fri, 16 Feb 2024 02:20:29 -0800 Subject: [PATCH] Add mjmModel opaque pointer to C API. PiperOrigin-RevId: 607619891 Change-Id: Ic1eaaa842438d9c2e19f742deff41967287853f5 --- src/user/user_api.cc | 88 ++++++++++++++++++------------------ src/user/user_api.h | 48 +++++++++++--------- src/user/user_composite.cc | 32 ++++++------- src/user/user_flexcomp.cc | 2 +- src/user/user_model.cc | 5 ++ src/user/user_model.h | 2 + src/xml/xml_native_reader.cc | 44 +++++++++--------- src/xml/xml_urdf.cc | 14 +++--- test/user/user_api_test.cc | 2 +- 9 files changed, 124 insertions(+), 113 deletions(-) diff --git a/src/user/user_api.cc b/src/user/user_api.cc index 05f03cc6..4473ee35 100644 --- a/src/user/user_api.cc +++ b/src/user/user_api.cc @@ -24,16 +24,16 @@ // create model -void* mjm_createModel() { +mjmModel* mjm_createModel() { mjCModel* modelC = new mjCModel(); - return modelC; + return &modelC->spec; } // delete model -void mjm_deleteModel(void* modelspec) { - mjCModel* model = static_cast(modelspec); +void mjm_deleteModel(mjmModel* modelspec) { + mjCModel* model = reinterpret_cast(modelspec->element); delete model; } @@ -116,8 +116,8 @@ mjmLight* mjm_addLight(mjmBody* bodyspec, mjmDefault* defspec) { // add flex to model -mjmFlex* mjm_addFlex(void* model) { - mjCModel* modelC = static_cast(model); +mjmFlex* mjm_addFlex(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCFlex* flex = modelC->AddFlex(); return &flex->spec; } @@ -138,9 +138,9 @@ mjmFrame* mjm_addFrame(mjmBody* bodyspec, mjmFrame* parentframe) { // add mesh to model -mjmMesh* mjm_addMesh(void* model, mjmDefault* defspec) { +mjmMesh* mjm_addMesh(mjmModel* model, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; - mjCModel* modelC = static_cast(model); + mjCModel* modelC = reinterpret_cast(model->element); mjCMesh* mesh = modelC->AddMesh(def); return &mesh->spec; } @@ -148,8 +148,8 @@ mjmMesh* mjm_addMesh(void* model, mjmDefault* defspec) { // add height field to model -mjmHField* mjm_addHField(void* model) { - mjCModel* modelC = static_cast(model); +mjmHField* mjm_addHField(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCHField* heightField = modelC->AddHField(); return &heightField->spec; } @@ -157,8 +157,8 @@ mjmHField* mjm_addHField(void* model) { // add skin to model -mjmSkin* mjm_addSkin(void* model) { - mjCModel* modelC = static_cast(model); +mjmSkin* mjm_addSkin(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCSkin* skin = modelC->AddSkin(); return &skin->spec; } @@ -166,8 +166,8 @@ mjmSkin* mjm_addSkin(void* model) { // add texture to model -mjmTexture* mjm_addTexture(void* model) { - mjCModel* modelC = static_cast(model); +mjmTexture* mjm_addTexture(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCTexture* texture = modelC->AddTexture(); return &texture->spec; } @@ -175,8 +175,8 @@ mjmTexture* mjm_addTexture(void* model) { // add material to model -mjmMaterial* mjm_addMaterial(void* model, mjmDefault* defspec) { - mjCModel* modelC = static_cast(model); +mjmMaterial* mjm_addMaterial(mjmModel* model, mjmDefault* defspec) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCMaterial* material = modelC->AddMaterial(def); return &material->spec; @@ -185,8 +185,8 @@ mjmMaterial* mjm_addMaterial(void* model, mjmDefault* defspec) { // add pair to model -mjmPair* mjm_addPair(void* model, mjmDefault* defspec) { - mjCModel* modelC = static_cast(model); +mjmPair* mjm_addPair(mjmModel* model, mjmDefault* defspec) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCPair* pair = modelC->AddPair(def); return &pair->spec; @@ -195,8 +195,8 @@ mjmPair* mjm_addPair(void* model, mjmDefault* defspec) { // add pair exclusion to model -mjmExclude* mjm_addExclude(void* model) { - mjCModel* modelC = static_cast(model); +mjmExclude* mjm_addExclude(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCBodyPair* bodypair = modelC->AddExclude(); return &bodypair->spec; } @@ -204,8 +204,8 @@ mjmExclude* mjm_addExclude(void* model) { // add equality to model -mjmEquality* mjm_addEquality(void* model, mjmDefault* defspec) { - mjCModel* modelC = static_cast(model); +mjmEquality* mjm_addEquality(mjmModel* model, mjmDefault* defspec) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCEquality* equality = modelC->AddEquality(def); return &equality->spec; @@ -214,8 +214,8 @@ mjmEquality* mjm_addEquality(void* model, mjmDefault* defspec) { // add tendon to model -mjmTendon* mjm_addTendon(void* model, mjmDefault* defspec) { - mjCModel* modelC = static_cast(model); +mjmTendon* mjm_addTendon(mjmModel* model, mjmDefault* defspec) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCTendon* tendon = modelC->AddTendon(def); return &tendon->spec; @@ -260,8 +260,8 @@ mjmWrap* mjm_wrapPulley(mjmTendon* tendonspec, double divisor) { // add actuator to model -mjmActuator* mjm_addActuator(void* model, mjmDefault* defspec) { - mjCModel* modelC = static_cast(model); +mjmActuator* mjm_addActuator(mjmModel* model, mjmDefault* defspec) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCActuator* actuator = modelC->AddActuator(def); return &actuator->spec; @@ -270,8 +270,8 @@ mjmActuator* mjm_addActuator(void* model, mjmDefault* defspec) { // add sensor to model -mjmSensor* mjm_addSensor(void* model) { - mjCModel* modelC = static_cast(model); +mjmSensor* mjm_addSensor(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCSensor* sensor = modelC->AddSensor(); return &sensor->spec; } @@ -279,8 +279,8 @@ mjmSensor* mjm_addSensor(void* model) { // add numeric to model -mjmNumeric* mjm_addNumeric(void* model) { - mjCModel* modelC = static_cast(model); +mjmNumeric* mjm_addNumeric(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCNumeric* numeric = modelC->AddNumeric(); return &numeric->spec; } @@ -288,8 +288,8 @@ mjmNumeric* mjm_addNumeric(void* model) { // add text to model -mjmText* mjm_addText(void* model) { - mjCModel* modelC = static_cast(model); +mjmText* mjm_addText(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCText* text = modelC->AddText(); return &text->spec; } @@ -297,8 +297,8 @@ mjmText* mjm_addText(void* model) { // add tuple to model -mjmTuple* mjm_addTuple(void* model) { - mjCModel* modelC = static_cast(model); +mjmTuple* mjm_addTuple(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCTuple* tuple = modelC->AddTuple(); return &tuple->spec; } @@ -306,8 +306,8 @@ mjmTuple* mjm_addTuple(void* model) { // add keyframe to model -mjmKey* mjm_addKey(void* model) { - mjCModel* modelC = static_cast(model); +mjmKey* mjm_addKey(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCKey* key = modelC->AddKey(); return &key->spec; } @@ -315,8 +315,8 @@ mjmKey* mjm_addKey(void* model) { // add plugin to model -mjElement mjm_addPlugin(void* model) { - mjCModel* modelC = static_cast(model); +mjElement mjm_addPlugin(mjmModel* model) { + mjCModel* modelC = reinterpret_cast(model->element); mjCPlugin* plugin = modelC->AddPlugin(); return (mjElement)plugin; } @@ -324,8 +324,8 @@ mjElement mjm_addPlugin(void* model) { // add default to model -mjmDefault* mjm_addDefault(void* model, const char* classname, int parentid) { - mjCModel* modelC = static_cast(model); +mjmDefault* mjm_addDefault(mjmModel* model, const char* classname, int parentid) { + mjCModel* modelC = reinterpret_cast(model->element); mjCDef* def = modelC->AddDef(classname, parentid); if (def) { return &def->spec; @@ -337,8 +337,8 @@ mjmDefault* mjm_addDefault(void* model, const char* classname, int parentid) { // get objects -void* mjm_getModel(mjmBody* bodyspec) { - return reinterpret_cast(bodyspec->element)->model; +mjmModel* mjm_getModel(mjmBody* bodyspec) { + return &(reinterpret_cast(bodyspec->element)->model->spec); } @@ -351,8 +351,8 @@ mjmDefault* mjm_getDefault(mjElement element) { // find body in model by name -mjmBody* mjm_findBody(void* modelspec, const char* name) { - mjCModel* model = static_cast(modelspec); +mjmBody* mjm_findBody(mjmModel* modelspec, const char* name) { + mjCModel* model = reinterpret_cast(modelspec->element); mjCBase* body = model->FindObject(mjOBJ_BODY, std::string(name)); if (!body) { return 0; diff --git a/src/user/user_api.h b/src/user/user_api.h index 05ca79d2..d6142abe 100644 --- a/src/user/user_api.h +++ b/src/user/user_api.h @@ -71,6 +71,10 @@ typedef enum _mjtLimited { // type of limit specification //---------------------------------- attribute structs (mjm) --------------------------------------- +typedef struct _mjmModel { // model specification + mjElement element; // internal, do not modify +} mjmModel; + typedef struct _mjmOrientation { // alternative orientation specifiers double axisangle[4]; // rotation axis and angle double xyaxes[6]; // x and y axes @@ -662,10 +666,10 @@ typedef struct _mjmDefault { // default specification //---------------------------------- API functions ------------------------------------------------- // Create model. -MJAPI void* mjm_createModel(); +MJAPI mjmModel* mjm_createModel(); // Delete model. -MJAPI void mjm_deleteModel(void* modelspec); +MJAPI void mjm_deleteModel(mjmModel* modelspec); // Copy spec into private attributes. MJAPI void mjm_finalize(mjElement object); @@ -695,34 +699,34 @@ MJAPI mjmLight* mjm_addLight(mjmBody* body, mjmDefault* def); MJAPI mjmFrame* mjm_addFrame(mjmBody* body, mjmFrame* parentframe); // Add flex to model. -MJAPI mjmFlex* mjm_addFlex(void* model); +MJAPI mjmFlex* mjm_addFlex(mjmModel* model); // Add mesh to model. -MJAPI mjmMesh* mjm_addMesh(void* model, mjmDefault* def); +MJAPI mjmMesh* mjm_addMesh(mjmModel* model, mjmDefault* def); // Add height field to model. -MJAPI mjmHField* mjm_addHField(void* model); +MJAPI mjmHField* mjm_addHField(mjmModel* model); // Add skin to model. -MJAPI mjmSkin* mjm_addSkin(void* model); +MJAPI mjmSkin* mjm_addSkin(mjmModel* model); // Add texture to model. -MJAPI mjmTexture* mjm_addTexture(void* model); +MJAPI mjmTexture* mjm_addTexture(mjmModel* model); // Add material to model. -MJAPI mjmMaterial* mjm_addMaterial(void* model, mjmDefault* def); +MJAPI mjmMaterial* mjm_addMaterial(mjmModel* model, mjmDefault* def); // Add pair to model. -MJAPI mjmPair* mjm_addPair(void* model, mjmDefault* def); +MJAPI mjmPair* mjm_addPair(mjmModel* model, mjmDefault* def); // Add excluded body pair to model. -MJAPI mjmExclude* mjm_addExclude(void *model); +MJAPI mjmExclude* mjm_addExclude(mjmModel *model); // Add equality to model. -MJAPI mjmEquality* mjm_addEquality(void* model, mjmDefault* def); +MJAPI mjmEquality* mjm_addEquality(mjmModel* model, mjmDefault* def); // Add tendon to model. -MJAPI mjmTendon* mjm_addTendon(void* model, mjmDefault* def); +MJAPI mjmTendon* mjm_addTendon(mjmModel* model, mjmDefault* def); // Wrap site using tendon. MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendon, const char* name); @@ -737,37 +741,37 @@ MJAPI mjmWrap* mjm_wrapJoint(mjmTendon* tendon, const char* name, double coef); MJAPI mjmWrap* mjm_wrapPulley(mjmTendon* tendon, double divisor); // Add actuator to model. -MJAPI mjmActuator* mjm_addActuator(void* model, mjmDefault* def); +MJAPI mjmActuator* mjm_addActuator(mjmModel* model, mjmDefault* def); // Add sensor to model. -MJAPI mjmSensor* mjm_addSensor(void* model); +MJAPI mjmSensor* mjm_addSensor(mjmModel* model); // Add numeric to model. -MJAPI mjmNumeric* mjm_addNumeric(void* model); +MJAPI mjmNumeric* mjm_addNumeric(mjmModel* model); // Add text to model. -MJAPI mjmText* mjm_addText(void* model); +MJAPI mjmText* mjm_addText(mjmModel* model); // Add tuple to model. -MJAPI mjmTuple* mjm_addTuple(void* model); +MJAPI mjmTuple* mjm_addTuple(mjmModel* model); // Add keyframe to model. -MJAPI mjmKey* mjm_addKey(void* model); +MJAPI mjmKey* mjm_addKey(mjmModel* model); // Add plugin to model. -MJAPI mjElement mjm_addPlugin(void* model); +MJAPI mjElement mjm_addPlugin(mjmModel* model); // Add default to model. -MJAPI mjmDefault* mjm_addDefault(void* model, const char* classname, int parentid); +MJAPI mjmDefault* mjm_addDefault(mjmModel* model, const char* classname, int parentid); // Get model from body. -MJAPI void* mjm_getModel(mjmBody* body); +MJAPI mjmModel* mjm_getModel(mjmBody* body); // Get default corresponding to an mjElement. MJAPI mjmDefault* mjm_getDefault(mjElement element); // Find body in model by name. -MJAPI mjmBody* mjm_findBody(void* modelspec, const char* name); +MJAPI mjmBody* mjm_findBody(mjmModel* modelspec, const char* name); // Find child body by name. MJAPI mjmBody* mjm_findChild(mjmBody* body, const char* name); diff --git a/src/user/user_composite.cc b/src/user/user_composite.cc index f30e9fd9..415fde0a 100644 --- a/src/user/user_composite.cc +++ b/src/user/user_composite.cc @@ -551,7 +551,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1); // create tendon - mjmTendon* ten = mjm_addTendon(model, &def[mjCOMPKIND_TENDON].spec); + mjmTendon* ten = mjm_addTendon(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjm_setDefault(ten->element, &model->defaults[0]->spec); mjm_setString(ten->name, txt0); ten->group = 4; @@ -559,7 +559,7 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjmBody* body, char* error, int mjm_wrapSite(ten, txt2); // add equality constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_TENDON].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_TENDON; mjm_setString(eq->name1, mjm_getString(ten->name)); @@ -673,7 +673,7 @@ bool mjCComposite::MakeGrid(mjCModel* model, mjmBody* body, char* error, int err ten->WrapSite(txt2); // add equality constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_TENDON].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_TENDON; mjm_setString(eq->name1, ten->name.c_str()); @@ -714,7 +714,7 @@ bool mjCComposite::MakeCable(mjCModel* model, mjmBody* body, char* error, int er } // add name to model - mjmText* pte = mjm_addText(model); + mjmText* pte = mjm_addText(&model->spec); mjm_setString(pte->name, ("composite_" + prefix).c_str()); mjm_setString(pte->data, ("rope_" + prefix).c_str()); @@ -880,7 +880,7 @@ mjmBody* mjCComposite::AddCableBody(mjCModel* model, mjmBody* body, int ix, mjtN // exclude contact pair if (!last) { - mjmExclude* exclude = mjm_addExclude(model); + mjmExclude* exclude = mjm_addExclude(&model->spec); mjm_setString(exclude->bodyname1, std::string(this_body).c_str()); mjm_setString(exclude->bodyname2, std::string(next_body).c_str()); } @@ -944,7 +944,7 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err char txt2[200]; // add equality constraint - mjmEquality* eq = mjm_addEquality(model, 0); + mjmEquality* eq = mjm_addEquality(&model->spec, 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); @@ -955,7 +955,7 @@ bool mjCComposite::MakeRope(mjCModel* model, mjmBody* body, char* error, int err mju_copy(eq->solimp, solimpsmooth, mjNIMP); // remove contact between connected bodies - mjmExclude* pair = mjm_addExclude(model); + mjmExclude* pair = mjm_addExclude(&model->spec); mjm_setString(pair->bodyname1, std::string(txt).c_str()); mjm_setString(pair->bodyname2, std::string(txt2).c_str()); } @@ -1035,7 +1035,7 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i mjuu_setvec(jnt->axis, 1, 0, 0); // add constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_TWIST].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TWIST].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_JOINT; mjm_setString(eq->name1, mjm_getString(jnt->name)); @@ -1053,7 +1053,7 @@ mjmBody* mjCComposite::AddRopeBody(mjCModel* model, mjmBody* body, int ix, int i mjuu_setvec(jnt->axis, 1, 0, 0); // add constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_STRETCH].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_STRETCH].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_JOINT; mjm_setString(eq->name1, mjm_getString(jnt->name)); @@ -1174,7 +1174,7 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro mjuu_setvec(jnt->axis, 0, 0, 1); // add fix constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_JOINT].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_JOINT].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_JOINT; mjm_setString(eq->name1, mjm_getString(jnt->name)); @@ -1194,7 +1194,7 @@ 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); - mjmEquality* eqn = mjm_addEquality(model, 0); + mjmEquality* eqn = mjm_addEquality(&model->spec, 0); mju_copy(eqn->solref, solrefsmooth, mjNREF); mju_copy(eqn->solimp, solimpsmooth, mjNIMP); eqn->type = mjEQ_JOINT; @@ -1208,7 +1208,7 @@ bool mjCComposite::MakeBox(mjCModel* model, mjmBody* body, char* error, int erro } // finalize fixed tendon - mjmEquality* eqt = mjm_addEquality(model, &def[mjCOMPKIND_TENDON].spec); + mjmEquality* eqt = mjm_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec); mjm_setDefault(eqt->element, &model->defaults[0]->spec); eqt->type = mjEQ_TENDON; mjm_setString(eqt->name1, ten->name.c_str()); @@ -1244,7 +1244,7 @@ void mjCComposite::MakeShear(mjCModel* model) { ten->name = txt; // equality constraint - mjmEquality* eq = mjm_addEquality(model, &def[mjCOMPKIND_SHEAR].spec); + mjmEquality* eq = mjm_addEquality(&model->spec, &def[mjCOMPKIND_SHEAR].spec); mjm_setDefault(eq->element, &model->defaults[0]->spec); eq->type = mjEQ_TENDON; mjm_setString(eq->name1, txt); @@ -1286,7 +1286,7 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) { int N = count[0]*count[1]; // add skin, set name and material - mjmSkin* skin = mjm_addSkin(model); + mjmSkin* skin = mjm_addSkin(&model->spec); mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mjm_setString(skin->name, txt); mjm_setString(skin->material, skinmaterial.c_str()); @@ -1879,7 +1879,7 @@ void mjCComposite::MakeSkin2Subgrid(mjCModel* model, mjtNum inflate) { // add skin, set name and material char txt[100]; - mjmSkin* skin = mjm_addSkin(model); + mjmSkin* skin = mjm_addSkin(&model->spec); mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mjm_setString(skin->name, txt); mjm_setString(skin->material, skinmaterial.c_str()); @@ -2034,7 +2034,7 @@ void mjCComposite::MakeSkin3(mjCModel* model) { mju::sprintf_arr(cnt2, "%d", count[2]-1); // add skin, set name and material - mjmSkin* skin = mjm_addSkin(model); + mjmSkin* skin = mjm_addSkin(&model->spec); mju::sprintf_arr(txt, "%sSkin", prefix.c_str()); mjm_setString(skin->name, txt); mjm_setString(skin->material, skinmaterial.c_str()); diff --git a/src/user/user_flexcomp.cc b/src/user/user_flexcomp.cc index ef298c05..9e149d08 100644 --- a/src/user/user_flexcomp.cc +++ b/src/user/user_flexcomp.cc @@ -484,7 +484,7 @@ bool mjCFlexcomp::Make(mjCModel* model, mjmBody* body, char* error, int error_sz // create edge equality constraint if (equality) { - mjmEquality* pe = mjm_addEquality(model, &def.spec); + mjmEquality* pe = mjm_addEquality(&model->spec, &def.spec); mjm_setDefault(pe->element, &model->defaults[0]->spec); pe->type = mjEQ_FLEX; pe->active = true; diff --git a/src/user/user_model.cc b/src/user/user_model.cc index 2f28479c..49b31542 100644 --- a/src/user/user_model.cc +++ b/src/user/user_model.cc @@ -41,6 +41,7 @@ #include "engine/engine_util_blas.h" #include "engine/engine_util_errmem.h" #include "engine/engine_util_misc.h" +#include "user/user_api.h" #include "user/user_objects.h" #include "user/user_util.h" @@ -214,6 +215,10 @@ mjCModel::mjCModel() { object_lists[mjOBJ_TUPLE] = (std::vector*) &tuples; object_lists[mjOBJ_KEY] = (std::vector*) &keys; object_lists[mjOBJ_PLUGIN] = (std::vector*) &plugins; + + + // point to model from spec + spec.element = (mjElement)this; } diff --git a/src/user/user_model.h b/src/user/user_model.h index 5287eb2c..15d5ae31 100644 --- a/src/user/user_model.h +++ b/src/user/user_model.h @@ -72,6 +72,8 @@ class mjCModel { mjCModel(); // constructor ~mjCModel(); // destructor + mjmModel spec; + mjModel* Compile(const mjVFS* vfs = 0); // COMPILER: construct mjModel bool CopyBack(const mjModel*); // DECOMPILER: copy numeric back void FuseStatic(void); // fuse static bodies with parent diff --git a/src/xml/xml_native_reader.cc b/src/xml/xml_native_reader.cc index 13834b72..3f9ce15a 100644 --- a/src/xml/xml_native_reader.cc +++ b/src/xml/xml_native_reader.cc @@ -2263,7 +2263,7 @@ void mjXReader::OneComposite(XMLElement* elem, mjmBody* pbody, mjmDefault* def) ReadAttrTxt(eplugin, "plugin", comp.plugin_name); ReadAttrTxt(eplugin, "instance", comp.plugin_instance_name); if (comp.plugin_instance_name.empty()) { - comp.plugin_instance = (mjCPlugin*)mjm_addPlugin(model); + comp.plugin_instance = (mjCPlugin*)mjm_addPlugin(&model->spec); comp.plugin_instance->name = "composite"+comp.prefix; comp.plugin_instance_name = comp.plugin_instance->name; } else { @@ -2594,7 +2594,7 @@ void mjXReader::OneFlexcomp(XMLElement* elem, mjmBody* pbody) { ReadAttrTxt(eplugin, "plugin", fcomp.plugin_name); ReadAttrTxt(eplugin, "instance", fcomp.plugin_instance_name); if (fcomp.plugin_instance_name.empty()) { - fcomp.plugin_instance = (mjCPlugin*)mjm_addPlugin(model); + fcomp.plugin_instance = (mjCPlugin*)mjm_addPlugin(&model->spec); fcomp.plugin_instance->name = "flexcomp_" + fcomp.name; fcomp.plugin_instance_name = fcomp.plugin_instance->name; } else { @@ -2625,7 +2625,7 @@ void mjXReader::OnePlugin(XMLElement* elem, mjmPlugin* plugin) { mjm_setString(plugin->name, name.c_str()); mjm_setString(plugin->instance_name, instance_name.c_str()); if (instance_name.empty()) { - plugin->instance = mjm_addPlugin(model); + plugin->instance = mjm_addPlugin(&model->spec); ReadPluginConfigs(elem, (mjCPlugin*)plugin->instance); } else { model->hasImplicitPluginElem = true; @@ -2655,7 +2655,7 @@ void mjXReader::Default(XMLElement* section, int parentid) { } if (parentid>=0) { thisid = (int)model->defaults.size(); - def = mjm_addDefault(model, text.c_str(), parentid); + def = mjm_addDefault(&model->spec, text.c_str(), parentid); if (!def) { throw mjXError(section, "repeated default class name"); } @@ -2784,7 +2784,7 @@ void mjXReader::Extension(XMLElement* section) { throw mjXError( child, "explicit plugin instance must appear before implicit plugin elements"); } - mjCPlugin* pp = (mjCPlugin*)mjm_addPlugin(model); + mjCPlugin* pp = (mjCPlugin*)mjm_addPlugin(&model->spec); GetXMLPos(child, pp); ReadAttrTxt(child, "name", pp->name, /* required = */ true); if (pp->name.empty()) { @@ -2821,7 +2821,7 @@ void mjXReader::Custom(XMLElement* section) { // numeric if (name=="numeric") { // create custom - mjmNumeric* pnum = mjm_addNumeric(model); + mjmNumeric* pnum = mjm_addNumeric(&model->spec); // write error info mjm_setString(pnum->info, @@ -2853,7 +2853,7 @@ void mjXReader::Custom(XMLElement* section) { // text else if (name=="text") { // create custom - mjmText* pte = mjm_addText(model); + mjmText* pte = mjm_addText(&model->spec); // write error info mjm_setString(pte->info, @@ -2874,7 +2874,7 @@ void mjXReader::Custom(XMLElement* section) { // tuple else if (name=="tuple") { // create custom - mjmTuple* ptu = mjm_addTuple(model); + mjmTuple* ptu = mjm_addTuple(&model->spec); // write error info mjm_setString(ptu->info, @@ -3082,7 +3082,7 @@ void mjXReader::Asset(XMLElement* section) { // texture sub-element if (name=="texture") { // create texture - mjmTexture* ptex = mjm_addTexture(model); + mjmTexture* ptex = mjm_addTexture(&model->spec); // write error info mjm_setString(ptex->info, @@ -3150,28 +3150,28 @@ void mjXReader::Asset(XMLElement* section) { // material sub-element else if (name=="material") { // create material and parse - mjmMaterial* pmat = mjm_addMaterial(model, def); + mjmMaterial* pmat = mjm_addMaterial(&model->spec, def); OneMaterial(elem, pmat); } // mesh sub-element else if (name=="mesh") { // create mesh and parse - mjmMesh* pmesh = mjm_addMesh(model, def); + mjmMesh* pmesh = mjm_addMesh(&model->spec, def); OneMesh(elem, pmesh); } // skin sub-element... deprecate ??? else if (name=="skin") { // create skin and parse - mjmSkin* pskin = mjm_addSkin(model); + mjmSkin* pskin = mjm_addSkin(&model->spec); OneSkin(elem, pskin); } // hfield sub-element else if (name=="hfield") { // create hfield - mjmHField* phf = mjm_addHField(model); + mjmHField* phf = mjm_addHField(&model->spec); // write error info mjm_setString(phf->info, @@ -3453,13 +3453,13 @@ void mjXReader::Contact(XMLElement* section) { // geom pair to include if (name=="pair") { // create pair and parse - mjmPair* ppair = mjm_addPair(model, def); + mjmPair* ppair = mjm_addPair(&model->spec, def); OnePair(elem, ppair); } // body pair to exclude else if (name=="exclude") { - mjmExclude* pexclude = mjm_addExclude(model); + mjmExclude* pexclude = mjm_addExclude(&model->spec); string exname, exbody1, exbody2; // write error info @@ -3496,7 +3496,7 @@ void mjXReader::Equality(XMLElement* section) { } // create equality constraint and parse - mjmEquality* pequality = mjm_addEquality(model, def); + mjmEquality* pequality = mjm_addEquality(&model->spec, def); OneEquality(elem, pequality); // advance to next element @@ -3526,14 +3526,14 @@ void mjXReader::Deformable(XMLElement* section) { // flex sub-element if (name=="flex") { // create flex and parse - mjmFlex* pflex = mjm_addFlex(model); + mjmFlex* pflex = mjm_addFlex(&model->spec); OneFlex(elem, pflex); } // skin sub-element else if (name=="skin") { // create skin and parse - mjmSkin* pskin = mjm_addSkin(model); + mjmSkin* pskin = mjm_addSkin(&model->spec); OneSkin(elem, pskin); } @@ -3560,7 +3560,7 @@ void mjXReader::Tendon(XMLElement* section) { } // create equality constraint and parse - mjmTendon* pten = mjm_addTendon(model, def); + mjmTendon* pten = mjm_addTendon(&model->spec, def); OneTendon(elem, pten); // process wrap sub-elements @@ -3626,7 +3626,7 @@ void mjXReader::Actuator(XMLElement* section) { } // create actuator and parse - mjmActuator* pact = mjm_addActuator(model, def); + mjmActuator* pact = mjm_addActuator(&model->spec, def); OneActuator(elem, pact); // advance to next element @@ -3642,7 +3642,7 @@ void mjXReader::Sensor(XMLElement* section) { XMLElement* elem = FirstChildElement(section); while (elem) { // create sensor, get string type - mjmSensor* psen = mjm_addSensor(model); + mjmSensor* psen = mjm_addSensor(&model->spec); string type = elem->Value(); string text, name, objname, refname; std::vector userdata; @@ -3960,7 +3960,7 @@ void mjXReader::Keyframe(XMLElement* section) { string text, name = ""; // add keyframe - mjmKey* pk = mjm_addKey(model); + mjmKey* pk = mjm_addKey(&model->spec); // read name, time ReadAttrTxt(elem, "name", name); diff --git a/src/xml/xml_urdf.cc b/src/xml/xml_urdf.cc index 9a180c11..3f57bc20 100644 --- a/src/xml/xml_urdf.cc +++ b/src/xml/xml_urdf.cc @@ -202,7 +202,7 @@ void mjXURDF::Parse( // override the pose for the base link and add a free joint for (int i = 0; i < (int)urName.size(); i++) { if (urParent[i] < 0) { - mjmBody* world = mjm_findBody(model, "world"); + mjmBody* world = mjm_findBody(&model->spec, "world"); mjmBody* pbody = mjm_findChild(world, urName[i].c_str()); mjuu_copyvec(pbody->pos, pos, 3); mjuu_copyvec(pbody->quat, quat, 4); @@ -228,7 +228,7 @@ void mjXURDF::Body(XMLElement* body_elem) { // get body name and pointer to mjmBody ReadAttrTxt(body_elem, "name", name, true); name = GetPrefixedName(name); - world = mjm_findBody(model, "world"); + world = mjm_findBody(&model->spec, "world"); pbody = mjm_findChild(world, name.c_str()); if (!pbody) { throw mjXError(body_elem, "URDF body not found"); // SHOULD NOT OCCUR @@ -386,7 +386,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) { elem = FindSubElem(joint_elem, "parent", true); ReadAttrTxt(elem, "link", name, true); name = GetPrefixedName(name); - world = mjm_findBody(model, "world"); + world = mjm_findBody(&model->spec, "world"); parent = mjm_findChild(world, name.c_str()); if (!parent) { // SHOULD NOT OCCUR throw mjXError(elem, "invalid parent name in URDF joint definition"); @@ -396,7 +396,7 @@ void mjXURDF::Joint(XMLElement* joint_elem) { elem = FindSubElem(joint_elem, "child", true); ReadAttrTxt(elem, "link", name, true); name = GetPrefixedName(name); - world = mjm_findBody(model, "world"); + world = mjm_findBody(&model->spec, "world"); pbody = mjm_findChild(world, name.c_str()); if (!pbody) { // SHOULD NOT OCCUR throw mjXError(elem, "invalid child name in URDF joint definition"); @@ -577,14 +577,14 @@ mjmGeom* mjXURDF::Geom(XMLElement* geom_elem, mjmBody* pbody, bool collision) { // does not exist: create if (!mesh) { - pmesh = mjm_addMesh(model, 0); + pmesh = mjm_addMesh(&model->spec, 0); } // exists with different scale: append name with '1', create else if (mesh->spec.scale[0]!=meshscale[0] || mesh->spec.scale[1]!=meshscale[1] || mesh->spec.scale[2]!=meshscale[2]) { - pmesh = mjm_addMesh(model, 0); + pmesh = mjm_addMesh(&model->spec, 0); meshname = meshname + "1"; } @@ -681,7 +681,7 @@ void mjXURDF::AddToTree(int n) { // get pointer to parent in mjCModel tree mjmBody *parent = 0, *child = 0, *world = 0; if (urParent[n]>=0) { - world = mjm_findBody(model, "world"); + world = mjm_findBody(&model->spec, "world"); parent = mjm_findChild(world, urName[urParent[n]].c_str()); if (!parent) diff --git a/test/user/user_api_test.cc b/test/user/user_api_test.cc index c8dce45e..5bd73525 100644 --- a/test/user/user_api_test.cc +++ b/test/user/user_api_test.cc @@ -29,7 +29,7 @@ using ::testing::HasSubstr; // ----------------------------- test set/get -------------------------------- TEST_F(MujocoTest, ReadWriteData) { - void* model = mjm_createModel(); + mjmModel* model = mjm_createModel(); mjmBody* world = mjm_findBody(model, "world"); mjmBody* body = mjm_addBody(world, 0); mjmSite* site = mjm_addSite(body, 0);