// Copyright 2024 DeepMind Technologies Limited // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "user/user_api.h" #include #include #include #include "user/user_model.h" #include "user/user_objects.h" #include "xml/xml_util.h" // create model mjmModel* mjm_createModel() { mjCModel* modelC = new mjCModel(); return &modelC->spec; } // delete model void mjm_deleteModel(mjmModel* modelspec) { mjCModel* model = reinterpret_cast(modelspec->element); delete model; } // copy spec into private attributes MJAPI void mjm_finalize(mjElement object) { mjCBase* baseC = reinterpret_cast(object); baseC->CopyFromSpec(); } // add child body to body, return child spec mjmBody* mjm_addBody(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element)->AddBody(def); return &body->spec; } // add site to body, return site spec mjmSite* mjm_addSite(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element); mjCSite* site = body->AddSite(def); return &site->spec; } // add joint to body mjmJoint* mjm_addJoint(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element); mjCJoint* joint = body->AddJoint(def); return &joint->spec; } // add free joint to body mjmJoint* mjm_addFreeJoint(mjmBody* bodyspec) { mjCBody* body = reinterpret_cast(bodyspec->element); mjCJoint* joint = body->AddFreeJoint(); return &joint->spec; } // add geom to body mjmGeom* mjm_addGeom(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element); mjCGeom* geom = body->AddGeom(def); return &geom->spec; } // add camera to body mjmCamera* mjm_addCamera(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element); mjCCamera* camera = body->AddCamera(def); return &camera->spec; } // add light to body mjmLight* mjm_addLight(mjmBody* bodyspec, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCBody* body = reinterpret_cast(bodyspec->element); mjCLight* light = body->AddLight(def); return &light->spec; } // add flex to model mjmFlex* mjm_addFlex(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCFlex* flex = modelC->AddFlex(); return &flex->spec; } // add frame to body mjmFrame* mjm_addFrame(mjmBody* bodyspec, mjmFrame* parentframe) { mjCFrame* parentframeC = 0; if (parentframe) { parentframeC = reinterpret_cast(parentframe->element); } mjCBody* body = reinterpret_cast(bodyspec->element); mjCFrame* frameC = body->AddFrame(parentframeC); return &frameC->spec; } // add mesh to model mjmMesh* mjm_addMesh(mjmModel* model, mjmDefault* defspec) { mjCDef* def = defspec ? reinterpret_cast(defspec->element) : 0; mjCModel* modelC = reinterpret_cast(model->element); mjCMesh* mesh = modelC->AddMesh(def); return &mesh->spec; } // add height field to model mjmHField* mjm_addHField(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCHField* heightField = modelC->AddHField(); return &heightField->spec; } // add skin to model mjmSkin* mjm_addSkin(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCSkin* skin = modelC->AddSkin(); return &skin->spec; } // add texture to model mjmTexture* mjm_addTexture(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCTexture* texture = modelC->AddTexture(); return &texture->spec; } // add material to 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; } // add pair to 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; } // add pair exclusion to model mjmExclude* mjm_addExclude(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCBodyPair* bodypair = modelC->AddExclude(); return &bodypair->spec; } // add equality to 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; } // add tendon to 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; } // wrap site using tendon MJAPI mjmWrap* mjm_wrapSite(mjmTendon* tendonspec, const char* name) { mjCTendon* tendon = reinterpret_cast(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(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(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(tendonspec->element); tendon->WrapPulley(divisor); return &tendon->path.back()->spec; } // add actuator to 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; } // add sensor to model mjmSensor* mjm_addSensor(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCSensor* sensor = modelC->AddSensor(); return &sensor->spec; } // add numeric to model mjmNumeric* mjm_addNumeric(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCNumeric* numeric = modelC->AddNumeric(); return &numeric->spec; } // add text to model mjmText* mjm_addText(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCText* text = modelC->AddText(); return &text->spec; } // add tuple to model mjmTuple* mjm_addTuple(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCTuple* tuple = modelC->AddTuple(); return &tuple->spec; } // add keyframe to model mjmKey* mjm_addKey(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCKey* key = modelC->AddKey(); return &key->spec; } // add plugin to model mjElement mjm_addPlugin(mjmModel* model) { mjCModel* modelC = reinterpret_cast(model->element); mjCPlugin* plugin = modelC->AddPlugin(); return (mjElement)plugin; } // add default to 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; } else { return nullptr; } } // get objects mjmModel* mjm_getModel(mjmBody* bodyspec) { return &(reinterpret_cast(bodyspec->element)->model->spec); } // get default mjmDefault* mjm_getDefault(mjElement element) { return &(reinterpret_cast(element)->def->spec); } // find body in model by name 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; } return &(static_cast(body)->spec); } // find child of a body by name mjmBody* mjm_findChild(mjmBody* bodyspec, const char* name) { mjCBody* body = reinterpret_cast(bodyspec->element); mjCBase* child = body->FindObject(mjOBJ_BODY, std::string(name)); if (!child) { return 0; } return &(static_cast(child)->spec); } // set frame void mjm_setFrame(mjElement dest, mjmFrame* frame) { if (!frame) { return; } mjCFrame* frameC = reinterpret_cast(frame->element); mjCBase* baseC = reinterpret_cast(dest); baseC->SetFrame(frameC); } // get id int mjm_getId(mjElement element) { return reinterpret_cast(element)->id; } // set default void mjm_setDefault(mjElement element, mjmDefault* defspec) { mjCBase* baseC = reinterpret_cast(element); baseC->def = reinterpret_cast(defspec->element); baseC->def->PointToLocal(); } // set string void mjm_setString(mjString dest, const char* text) { std::string* str = reinterpret_cast(dest); *str = std::string(text); } // Set specific entry in destination string vector. mjtByte mjm_setInStringVec(mjStringVec dest, int i, const char* text) { std::vector* v = reinterpret_cast*>(dest); if (v->size() <= i) { mju_error("Requested index in mjm_setInStringVec is out of bounds"); return 0; } v->at(i) = std::string(text); return 1; } // split text and copy into string array void mjm_setStringVec(mjStringVec dest, const char* text) { std::vector* v = reinterpret_cast*>(dest); mjXUtil::String2Vector(text, *v); } // add text entry to destination string vector void mjm_appendString(mjStringVec dest, const char* text) { std::vector* v = reinterpret_cast*>(dest); v->push_back(std::string(text)); } // copy int array to vector void mjm_setInt(mjIntVec dest, const int* array, int size) { std::vector* v = reinterpret_cast*>(dest); v->assign(size, 0.0); for (int i = 0; i < size; ++i) { (*v)[i] = array[i]; } } // append int array to vector of arrays void mjm_appendIntVec(mjIntVecVec dest, const int* array, int size) { std::vector>* v = reinterpret_cast>*>(dest); v->push_back(std::vector(array, array + size)); } // copy float array to vector void mjm_setFloat(mjFloatVec dest, const float* array, int size) { std::vector* v = reinterpret_cast*>(dest); v->assign(size, 0.0); for (int i = 0; i < size; ++i) { (*v)[i] = array[i]; } } // append float array to vector of arrays void mjm_appendFloatVec(mjFloatVecVec dest, const float* array, int size) { std::vector>* v = reinterpret_cast>*>(dest); v->push_back(std::vector(array, array + size)); } // copy double array to vector void mjm_setDouble(mjDoubleVec dest, const double* array, int size) { std::vector* v = reinterpret_cast*>(dest); v->assign(size, 0.0); for (int i = 0; i < size; ++i) { (*v)[i] = array[i]; } } // get string const char* mjm_getString(const mjString source) { std::string* str = reinterpret_cast(source); return str->c_str(); } // get double array const double* mjm_getDouble(const mjDoubleVec source, int* size) { std::vector* v = reinterpret_cast*>(source); if (size) { *size = v->size(); } return v->data(); } // compute full inertia const char* mjm_setFullInertia(mjmBody* bodyspec, double quat[4], double inertia[3]) { mjCBody* body = reinterpret_cast(bodyspec->element); return body->FullInertia(quat, inertia); }