// Copyright 2025 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. // NOLINTBEGIN(whitespace/line_length) // NOLINTBEGIN(whitespace/semicolon) #include "third_party/mujoco/wasm/codegen/generated/bindings.h" #include #include #include #include #include #include // NOLINT #include #include #include #include // NOLINT #include // NOLINT #include #include #include #include #include "engine/engine_util_errmem.h" #include "unpack.h" namespace mujoco::wasm { using emscripten::enum_; using emscripten::class_; using emscripten::function; using emscripten::val; using emscripten::constant; using emscripten::register_optional; using emscripten::register_type; using emscripten::register_vector; using emscripten::return_value_policy::reference; using emscripten::return_value_policy::take_ownership; // ERROR HANDLER void ThrowMujocoErrorToJS(const char* msg) { // Get a handle to the JS global Error constructor function, create a new // object instance and then throw the object as an exception using the // val::throw_() helper function. val(val::global("Error").new_(val("MuJoCo Error: " + std::string(msg)))) .throw_(); } __attribute__((constructor)) void InitMuJoCoErrorHandler() { mju_user_error = ThrowMujocoErrorToJS; } // CONSTANTS template val MakeValArray(const char* (&strings)[N]) { val result = val::array(); for (int i = 0; i < N; i++) { result.call("push", val(strings[i])); } return result; } template val MakeValArray3(const char* (&strings)[N][M]) { val result = val::array(); for (int i = 0; i < N; i++) { val inner = val::array(); for (int j = 0; j < M; j++) { inner.call("push", val(strings[i][j])); } result.call("push", inner); } return result; } val get_mjDISABLESTRING() { return MakeValArray(mjDISABLESTRING); } val get_mjENABLESTRING() { return MakeValArray(mjENABLESTRING); } val get_mjTIMERSTRING() { return MakeValArray(mjTIMERSTRING); } val get_mjLABELSTRING() { return MakeValArray(mjLABELSTRING); } val get_mjFRAMESTRING() { return MakeValArray(mjFRAMESTRING); } val get_mjVISSTRING() { return MakeValArray3(mjVISSTRING); } val get_mjRNDSTRING() { return MakeValArray3(mjRNDSTRING); } EMSCRIPTEN_BINDINGS(constants) { // from mjmodel.h constant("mjPI", mjPI); constant("mjMAXVAL", mjMAXVAL); constant("mjMINMU", mjMINMU); constant("mjMINIMP", mjMINIMP); constant("mjMAXIMP", mjMAXIMP); constant("mjMAXCONPAIR", mjMAXCONPAIR); constant("mjNEQDATA", mjNEQDATA); constant("mjNDYN", mjNDYN); constant("mjNGAIN", mjNGAIN); constant("mjNBIAS", mjNBIAS); constant("mjNREF", mjNREF); constant("mjNIMP", mjNIMP); constant("mjNSOLVER", mjNSOLVER); // from mjvisualize.h constant("mjNGROUP", mjNGROUP); constant("mjMAXLIGHT", mjMAXLIGHT); constant("mjMAXOVERLAY", mjMAXOVERLAY); constant("mjMAXLINE", mjMAXLINE); constant("mjMAXLINEPNT", mjMAXLINEPNT); constant("mjMAXPLANEGRID", mjMAXPLANEGRID); // from mujoco.h constant("mjVERSION_HEADER", mjVERSION_HEADER); // from mjtnum.h constant("mjMINVAL", mjMINVAL); // emscripten::constant() is designed for simple, compile-time literal values // (like numbers or a single string literal), complex values need to be // bound as functions. emscripten::function("get_mjDISABLESTRING", &get_mjDISABLESTRING); emscripten::function("get_mjENABLESTRING", &get_mjENABLESTRING); emscripten::function("get_mjTIMERSTRING", &get_mjTIMERSTRING); emscripten::function("get_mjLABELSTRING", &get_mjLABELSTRING); emscripten::function("get_mjFRAMESTRING", &get_mjFRAMESTRING); emscripten::function("get_mjVISSTRING", &get_mjVISSTRING); emscripten::function("get_mjRNDSTRING", &get_mjRNDSTRING); } EMSCRIPTEN_BINDINGS(mujoco_enums) { // {{ ENUM_BINDINGS }} } // STRUCTS // =============== MjLROpt =============== // // INSERT-GENERATED-MjLROpt-CONSTRUCTOR // =============== MjOption =============== // // INSERT-GENERATED-MjOption-CONSTRUCTOR // =============== MjStatistic =============== // // INSERT-GENERATED-MjStatistic-CONSTRUCTOR // =============== MjVisual... =============== // // INSERT-GENERATED-MjVisualGlobal-CONSTRUCTOR // INSERT-GENERATED-MjVisualQuality-CONSTRUCTOR // INSERT-GENERATED-MjVisualHeadlight-CONSTRUCTOR // INSERT-GENERATED-MjVisualMap-CONSTRUCTOR // INSERT-GENERATED-MjVisualScale-CONSTRUCTOR // INSERT-GENERATED-MjVisualRgba-CONSTRUCTOR // INSERT-GENERATED-MjVisual-CONSTRUCTOR // =============== MjSolverStat =============== // // INSERT-GENERATED-MjSolverStat-CONSTRUCTOR // =============== MjTimerStat =============== // // INSERT-GENERATED-MjTimerStat-CONSTRUCTOR // =============== MjWarningStat =============== // // INSERT-GENERATED-MjWarningStat-CONSTRUCTOR // =============== MjContact =============== // // INSERT-GENERATED-MjContact-CONSTRUCTOR // =============== MjModel =============== // MjModel::MjModel(mjModel *m) : ptr_(m), opt(&m->opt), stat(&m->stat), vis(&m->vis) {} MjModel::MjModel(const MjModel &other) : ptr_(mj_copyModel(nullptr, other.get())), opt(&ptr_->opt), stat(&ptr_->stat), vis(&ptr_->vis) {} MjModel::~MjModel() { if (ptr_) { mj_deleteModel(ptr_); } } // TODO(manevi): Consider passing `const MjModel& m` here, mj_makeData uses a const model. // =============== MjData =============== // MjData::MjData(MjModel *m) { model = m->get(); ptr_ = mj_makeData(model); if (ptr_) { solver = InitSolverArray(); timer = InitTimerArray(); warning = InitWarningArray(); } } MjData::MjData(const MjModel &model, const MjData &other) : ptr_(mj_copyData(nullptr, model.get(), other.get())), model(model.get()) { if (ptr_) { solver = InitSolverArray(); timer = InitTimerArray(); warning = InitWarningArray(); } } MjData::~MjData() { if (ptr_) { mj_deleteData(ptr_); } } std::vector MjData::InitSolverArray() { std::vector arr; arr.reserve(mjNSOLVER * mjNISLAND); for (int i = 0; i < mjNSOLVER * mjNISLAND; i++) { arr.emplace_back(&get()->solver[i]); } return arr; } std::vector MjData::InitTimerArray() { std::vector arr; arr.reserve(mjNTIMER); for (int i = 0; i < mjNTIMER; i++) { arr.emplace_back(&get()->timer[i]); } return arr; } std::vector MjData::InitWarningArray() { std::vector arr; arr.reserve(mjNWARNING); for (int i = 0; i < mjNWARNING; i++) { arr.emplace_back(&get()->warning[i]); } return arr; } std::vector MjData::contact() const { std::vector contacts; contacts.reserve(get()->ncon); for (int i = 0; i < get()->ncon; ++i) { contacts.emplace_back(&get()->contact[i]); } return contacts; } // =============== MjvPerturb =============== // // INSERT-GENERATED-MjvPerturb-CONSTRUCTOR // =============== MjvCamera =============== // // INSERT-GENERATED-MjvCamera-CONSTRUCTOR // =============== MjvGLCamera =============== // // INSERT-GENERATED-MjvGLCamera-CONSTRUCTOR // =============== MjvGeom =============== // MjvGeom::MjvGeom(mjvGeom *ptr) { ptr_ = ptr; }; MjvGeom::MjvGeom() : ptr_(new mjvGeom) { owned_ = true; mjv_initGeom(ptr_, mjGEOM_NONE, nullptr, nullptr, nullptr, nullptr); }; MjvGeom::MjvGeom(const MjvGeom &other) : MjvGeom() { *ptr_ = *other.get(); } MjvGeom &MjvGeom::operator=( const MjvGeom &other) { if (this == &other) { return *this; } *ptr_ = *other.get(); return *this; } MjvGeom::~MjvGeom() { if (owned_ && ptr_) delete ptr_; } std::unique_ptr MjvGeom::copy() { return std::make_unique(*this); } // =============== MjvLight =============== // // INSERT-GENERATED-MjvLight-CONSTRUCTOR // =============== MjvOption =============== // // INSERT-GENERATED-MjvOption-CONSTRUCTOR // =============== MjvScene =============== // MjvScene::MjvScene() { owned_ = true; ptr_ = new mjvScene; mjv_defaultScene(ptr_); mjv_makeScene(nullptr, ptr_, 0); lights = InitLightsArray(); camera = InitCameraArray(); }; MjvScene::MjvScene(MjModel *m, int maxgeom) { owned_ = true; model = m->get(); ptr_ = new mjvScene; mjv_defaultScene(ptr_); mjv_makeScene(model, ptr_, maxgeom); lights = InitLightsArray(); camera = InitCameraArray(); }; MjvScene::~MjvScene() { if (owned_ && ptr_) { mjv_freeScene(ptr_); delete ptr_; } } // Taken from the python mujoco bindings code for MjvScene Wrapper int MjvScene::GetSumFlexFaces() const { int nflexface = 0; int flexfacenum = 0; for (int f = 0; f < model->nflex; f++) { if (model->flex_dim[f] == 0) { // 1D : 0 flexfacenum = 0; } else if (model->flex_dim[f] == 2) { // 2D: 2*fragments + 2*elements flexfacenum = 2 * model->flex_shellnum[f] + 2 * model->flex_elemnum[f]; } else { // 3D: max(fragments, 4*maxlayer) // find number of elements in biggest layer int maxlayer = 0, layer = 0, nlayer = 1; while (nlayer) { nlayer = 0; for (int e = 0; e < model->flex_elemnum[f]; e++) { if (model->flex_elemlayer[model->flex_elemadr[f] + e] == layer) { nlayer++; } } maxlayer = mjMAX(maxlayer, nlayer); layer++; } flexfacenum = mjMAX(model->flex_shellnum[f], 4 * maxlayer); } // accumulate over flexes nflexface += flexfacenum; } return nflexface; } std::vector MjvScene::InitLightsArray() { std::vector arr; arr.reserve(mjMAXLIGHT); for (int i = 0; i < mjMAXLIGHT; i++) { arr.emplace_back(&ptr_->lights[i]); } return arr; } std::vector MjvScene::InitCameraArray() { std::vector arr; arr.reserve(2); for (int i = 0; i < 2; i++) { arr.emplace_back(&ptr_->camera[i]); } return arr; } std::vector MjvScene::geoms() const { std::vector geoms; geoms.reserve(ptr_->ngeom); for (int i = 0; i < ptr_->ngeom; ++i) { geoms.emplace_back(&ptr_->geoms[i]); } return geoms; } // =============== MjvFigure =============== // // INSERT-GENERATED-MjvFigure-CONSTRUCTOR // =============== MjsElement =============== // // INSERT-GENERATED-MjsElement-CONSTRUCTOR // =============== MjsCompiler =============== // // INSERT-GENERATED-MjsCompiler-CONSTRUCTOR // =============== MjSpec =============== // MjSpec::MjSpec() : ptr_(mj_makeSpec()), option(&ptr_->option), visual(&ptr_->visual), stat(&ptr_->stat), compiler(&ptr_->compiler), element(ptr_->element) { owned_ = true; mjs_defaultSpec(ptr_); }; MjSpec::MjSpec(mjSpec *ptr) : ptr_(ptr), option(&ptr_->option), visual(&ptr_->visual), stat(&ptr_->stat), compiler(&ptr_->compiler), element(ptr_->element) {} MjSpec::MjSpec(const MjSpec &other) : ptr_(mj_copySpec(other.get())), option(&ptr_->option), visual(&ptr_->visual), stat(&ptr_->stat), compiler(&ptr_->compiler), element(ptr_->element) { owned_ = true; } MjSpec& MjSpec::operator=(const MjSpec &other) { if (this == &other) { return *this; } if (owned_ && ptr_) { mj_deleteSpec(ptr_); } ptr_ = mj_copySpec(other.get()); owned_ = true; option.set(&ptr_->option); visual.set(&ptr_->visual); stat.set(&ptr_->stat); compiler.set(&ptr_->compiler); element.set(ptr_->element); return *this; } MjSpec::~MjSpec() { if (ptr_ && owned_) { mj_deleteSpec(ptr_); } } // =============== MjsOrientation =============== // // INSERT-GENERATED-MjsOrientation-CONSTRUCTOR // =============== MjsBody =============== // // INSERT-GENERATED-MjsBody-CONSTRUCTOR // =============== MjsGeom =============== // // INSERT-GENERATED-MjsGeom-CONSTRUCTOR // =============== MjsFrame =============== // // INSERT-GENERATED-MjsFrame-CONSTRUCTOR // =============== MjsJoint =============== // // INSERT-GENERATED-MjsJoint-CONSTRUCTOR // =============== MjsSite =============== // // INSERT-GENERATED-MjsSite-CONSTRUCTOR // =============== MjsCamera =============== // // INSERT-GENERATED-MjsCamera-CONSTRUCTOR // =============== MjsLight =============== // // INSERT-GENERATED-MjsLight-CONSTRUCTOR // =============== MjsFlex =============== // // INSERT-GENERATED-MjsFlex-CONSTRUCTOR // =============== MjsMesh =============== // // INSERT-GENERATED-MjsMesh-CONSTRUCTOR // =============== MjsHField =============== // // INSERT-GENERATED-MjsHField-CONSTRUCTOR // =============== MjsSkin =============== // // INSERT-GENERATED-MjsSkin-CONSTRUCTOR // =============== MjsTexture =============== // // INSERT-GENERATED-MjsTexture-CONSTRUCTOR // =============== MjsMaterial =============== // // INSERT-GENERATED-MjsMaterial-CONSTRUCTOR // =============== MjsPair =============== // // INSERT-GENERATED-MjsPair-CONSTRUCTOR // =============== MjsExclude =============== // // INSERT-GENERATED-MjsExclude-CONSTRUCTOR // =============== MjsEquality =============== // // INSERT-GENERATED-MjsEquality-CONSTRUCTOR // =============== MjsTendon =============== // // INSERT-GENERATED-MjsTendon-CONSTRUCTOR // =============== MjsWrap =============== // // INSERT-GENERATED-MjsWrap-CONSTRUCTOR // =============== MjsActuator =============== // // INSERT-GENERATED-MjsActuator-CONSTRUCTOR // =============== MjsSensor =============== // // INSERT-GENERATED-MjsSensor-CONSTRUCTOR // =============== MjsNumeric =============== // // INSERT-GENERATED-MjsNumeric-CONSTRUCTOR // =============== MjsText =============== // // INSERT-GENERATED-MjsText-CONSTRUCTOR // =============== MjsTuple =============== // // INSERT-GENERATED-MjsTuple-CONSTRUCTOR // =============== MjsKey =============== // // INSERT-GENERATED-MjsKey-CONSTRUCTOR // =============== MjsDefault =============== // // INSERT-GENERATED-MjsDefault-CONSTRUCTOR // =============== MjsPlugin =============== // // INSERT-GENERATED-MjsPlugin-CONSTRUCTOR // =============== MjVFS =============== // MjVFS::MjVFS(mjVFS *ptr) : ptr_(ptr) {} MjVFS::MjVFS() : ptr_(new mjVFS) { owned_ = true; mj_defaultVFS(ptr_); } MjVFS::~MjVFS() { if (owned_ && ptr_) { mj_deleteVFS(ptr_); } } // ======= FACTORY AND HELPER FUNCTIONS ========= // std::unique_ptr loadFromXML(std::string filename) { char error[1000]; mjModel *model = mj_loadXML(filename.c_str(), nullptr, error, sizeof(error)); if (!model) { printf("Loading error: %s\n", error); return nullptr; } return std::unique_ptr(new MjModel(model)); } std::unique_ptr parseXMLString(const std::string &xml) { char error[1000]; mjSpec *ptr = mj_parseXMLString(xml.c_str(), nullptr, error, sizeof(error)); if (!ptr) { printf("Could not create Spec from XML string: %s\n", error); return nullptr; } return std::unique_ptr(new MjSpec(ptr)); } EMSCRIPTEN_BINDINGS(mujoco_bindings) { function("parseXMLString", &parseXMLString, take_ownership()); emscripten::class_("MjLROpt") .constructor<>() .function("copy", &MjLROpt::copy, take_ownership()) // INSERT-GENERATED-MjLROpt-BINDINGS ; emscripten::class_("MjModel") .class_function("loadFromXML", &loadFromXML, take_ownership()) .constructor() // INSERT-GENERATED-MjModel-BINDINGS ; emscripten::class_("MjData") .constructor() .constructor() // INSERT-GENERATED-MjData-BINDINGS ; emscripten::class_("MjOption") .constructor<>() .function("copy", &MjOption::copy, take_ownership()) // INSERT-GENERATED-MjOption-BINDINGS ; emscripten::class_("MjStatistic") .constructor<>() .function("copy", &MjStatistic::copy, take_ownership()) // INSERT-GENERATED-MjStatistic-BINDINGS ; emscripten::class_("MjVisualGlobal") .constructor<>() .function("copy", &MjVisualGlobal::copy, take_ownership()) // INSERT-GENERATED-MjVisualGlobal-BINDINGS ; emscripten::class_("MjVisualQuality") .constructor<>() .function("copy", &MjVisualQuality::copy, take_ownership()) // INSERT-GENERATED-MjVisualQuality-BINDINGS ; emscripten::class_("MjVisualHeadlight") .constructor<>() .function("copy", &MjVisualHeadlight::copy, take_ownership()) // INSERT-GENERATED-MjVisualHeadlight-BINDINGS ; emscripten::class_("MjVisualMap") .constructor<>() .function("copy", &MjVisualMap::copy, take_ownership()) // INSERT-GENERATED-MjVisualMap-BINDINGS ; emscripten::class_("MjVisualScale") .constructor<>() .function("copy", &MjVisualScale::copy, take_ownership()) // INSERT-GENERATED-MjVisualScale-BINDINGS ; emscripten::class_("MjVisualRgba") .constructor<>() .function("copy", &MjVisualRgba::copy, take_ownership()) // INSERT-GENERATED-MjVisualRgba-BINDINGS ; emscripten::class_("MjVisual") .constructor<>() .function("copy", &MjVisual::copy, take_ownership()) // INSERT-GENERATED-MjVisual-BINDINGS ; emscripten::class_("MjSolverStat") .constructor<>() .function("copy", &MjSolverStat::copy, take_ownership()) // INSERT-GENERATED-MjSolverStat-BINDINGS ; emscripten::class_("MjTimerStat") .constructor<>() .function("copy", &MjTimerStat::copy, take_ownership()) // INSERT-GENERATED-MjTimerStat-BINDINGS ; emscripten::class_("MjWarningStat") .constructor<>() .function("copy", &MjWarningStat::copy, take_ownership()) // INSERT-GENERATED-MjWarningStat-BINDINGS ; emscripten::class_("MjContact") .constructor<>() .function("copy", &MjContact::copy, take_ownership()) // INSERT-GENERATED-MjContact-BINDINGS ; emscripten::class_("MjvPerturb") .constructor<>() .function("copy", &MjvPerturb::copy, take_ownership()) // INSERT-GENERATED-MjvPerturb-BINDINGS ; emscripten::class_("MjvCamera") .constructor<>() .function("copy", &MjvCamera::copy, take_ownership()) // INSERT-GENERATED-MjvCamera-BINDINGS ; emscripten::class_("MjvGLCamera") .constructor<>() .function("copy", &MjvGLCamera::copy, take_ownership()) // INSERT-GENERATED-MjvGLCamera-BINDINGS ; emscripten::class_("MjvGeom") .constructor<>() .function("copy", &MjvGLCamera::copy, take_ownership()) // INSERT-GENERATED-MjvGeom-BINDINGS ; emscripten::class_("MjvLight") .constructor<>() .function("copy", &MjvLight::copy, take_ownership()) // INSERT-GENERATED-MjvLight-BINDINGS ; emscripten::class_("MjvOption") .constructor<>() .function("copy", &MjvOption::copy, take_ownership()) // INSERT-GENERATED-MjvOption-BINDINGS ; emscripten::class_("MjvScene") .constructor<>() .constructor() // INSERT-GENERATED-MjvScene-BINDINGS ; emscripten::class_("MjvFigure") .constructor<>() .function("copy", &MjvFigure::copy, take_ownership()) // INSERT-GENERATED-MjvFigure-BINDINGS ; emscripten::class_("MjSpec") .constructor() // INSERT-GENERATED-MjSpec-BINDINGS ; emscripten::class_("MjsElement") // INSERT-GENERATED-MjsElement-BINDINGS ; emscripten::class_("MjsCompiler") // INSERT-GENERATED-MjsCompiler-BINDINGS ; emscripten::class_("MjsOrientation") .function("copy", &MjsOrientation::copy, take_ownership()) // INSERT-GENERATED-MjsOrientation-BINDINGS ; emscripten::class_("MjsBody") // INSERT-GENERATED-MjsBody-BINDINGS ; emscripten::class_("MjsGeom") // INSERT-GENERATED-MjsGeom-BINDINGS ; emscripten::class_("MjsFrame") // INSERT-GENERATED-MjsFrame-BINDINGS ; emscripten::class_("MjsJoint") // INSERT-GENERATED-MjsJoint-BINDINGS ; emscripten::class_("MjsSite") // INSERT-GENERATED-MjsSite-BINDINGS ; emscripten::class_("MjsCamera") // INSERT-GENERATED-MjsCamera-BINDINGS ; emscripten::class_("MjsLight") // INSERT-GENERATED-MjsLight-BINDINGS ; emscripten::class_("MjsFlex") // INSERT-GENERATED-MjsFlex-BINDINGS ; emscripten::class_("MjsMesh") // INSERT-GENERATED-MjsMesh-BINDINGS ; emscripten::class_("MjsHField") // INSERT-GENERATED-MjsHField-BINDINGS ; emscripten::class_("MjsSkin") // INSERT-GENERATED-MjsSkin-BINDINGS ; emscripten::class_("MjsTexture") // INSERT-GENERATED-MjsTexture-BINDINGS ; emscripten::class_("MjsMaterial") // INSERT-GENERATED-MjsMaterial-BINDINGS ; emscripten::class_("MjsPair") // INSERT-GENERATED-MjsPair-BINDINGS ; emscripten::class_("MjsExclude") // INSERT-GENERATED-MjsExclude-BINDINGS ; emscripten::class_("MjsEquality") // INSERT-GENERATED-MjsEquality-BINDINGS ; emscripten::class_("MjsTendon") // INSERT-GENERATED-MjsTendon-BINDINGS ; emscripten::class_("MjsWrap") // INSERT-GENERATED-MjsWrap-BINDINGS ; emscripten::class_("MjsActuator") // INSERT-GENERATED-MjsActuator-BINDINGS ; emscripten::class_("MjsSensor") // INSERT-GENERATED-MjsSensor-BINDINGS ; emscripten::class_("MjsNumeric") // INSERT-GENERATED-MjsNumeric-BINDINGS ; emscripten::class_("MjsText") // INSERT-GENERATED-MjsText-BINDINGS ; emscripten::class_("MjsTuple") // INSERT-GENERATED-MjsTuple-BINDINGS ; emscripten::class_("MjsKey") // INSERT-GENERATED-MjsKey-BINDINGS ; emscripten::class_("MjsDefault") // INSERT-GENERATED-MjsDefault-BINDINGS ; emscripten::class_("MjsPlugin") // INSERT-GENERATED-MjsPlugin-BINDINGS ; emscripten::class_("MjVFS").constructor<>() // INSERT-GENERATED-MjVFS-BINDINGS ; // TODO: should be generated in future CLs -- // emscripten::register_vector("MjSolverStatVec"); emscripten::register_vector("MjTimerStatVec"); emscripten::register_vector("MjWarningStatVec"); emscripten::register_vector("MjContactVec"); emscripten::register_vector("MjvLightVec"); emscripten::register_vector("MjvGLCameraVec"); emscripten::register_vector("MjvGeomVec"); } // FUNCTIONS EMSCRIPTEN_DECLARE_VAL_TYPE(NumberArray); EMSCRIPTEN_DECLARE_VAL_TYPE(String); // Raises an error if the given val is null or undefined. // A macro is used so that the error contains the name of the variable. // TODO(matijak): Remove this when we can handle strings using UNPACK_STRING? #define CHECK_VAL(val) \ if (val.isNull()) { \ mju_error("Invalid argument: %s is null", #val); \ } else if (val.isUndefined()) { \ mju_error("Invalid argument: %s is undefined", #val); \ } void error_wrapper(const String& msg) { mju_error("%s\n", msg.as().data()); } // {{ WRAPPER_FUNCTIONS }} void mju_printMatSparse_wrapper(const NumberArray& mat, const NumberArray& rownnz, const NumberArray& rowadr, const NumberArray& colind) { UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(int, rownnz); UNPACK_ARRAY(int, rowadr); UNPACK_ARRAY(int, colind); CHECK_SIZES(rownnz, rowadr); mju_printMatSparse(mat_.data(), rowadr_.size(), rownnz_.data(), rowadr_.data(), colind_.data()); } void mj_solveM_wrapper(const MjModel& m, MjData& d, const val& x, const NumberArray& y) { UNPACK_VALUE(mjtNum, x); UNPACK_ARRAY(mjtNum, y); CHECK_SIZES(x, y); CHECK_DIVISIBLE(x, m.nv()); mj_solveM(m.get(), d.get(), x_.data(), y_.data(), x_div.quot); } void mj_solveM2_wrapper(const MjModel& m, MjData& d, const val& x, const NumberArray& y, const NumberArray& sqrtInvD) { UNPACK_VALUE(mjtNum, x); UNPACK_ARRAY(mjtNum, y); UNPACK_ARRAY(mjtNum, sqrtInvD); CHECK_SIZES(x, y); CHECK_SIZE(sqrtInvD, m.nv()); CHECK_DIVISIBLE(x, m.nv()); mj_solveM2(m.get(), d.get(), x_.data(), y_.data(), sqrtInvD_.data(), x_div.quot); } void mj_rne_wrapper(const MjModel& m, MjData& d, int flg_acc, const val& result) { UNPACK_VALUE(mjtNum, result); CHECK_SIZE(result, m.nv()); mj_rne(m.get(), d.get(), flg_acc, result_.data()); } int mj_saveLastXML_wrapper(const String& filename, const MjModel& m) { CHECK_VAL(filename); std::array error; int result = mj_saveLastXML(filename.as().data(), m.get(), error.data(), error.size()); if (!result) { mju_error("%s", error.data()); } return result; } int mj_setLengthRange_wrapper(const MjModel& m, const MjData& d, int index, const MjLROpt& opt) { std::array error; int result = mj_setLengthRange(m.get(), d.get(), index, opt.get(), error.data(), error.size()); if (!result) { mju_error("%s", error.data()); } return result; } void mj_constraintUpdate_wrapper(const MjModel& m, MjData& d, const NumberArray& jar, const val& cost, int flg_coneHessian) { UNPACK_ARRAY(mjtNum, jar); UNPACK_NULLABLE_VALUE(mjtNum, cost); CHECK_SIZE(cost, 1); CHECK_SIZE(jar, d.nefc()); mj_constraintUpdate(m.get(), d.get(), jar_.data(), cost_.data(), flg_coneHessian); } void mj_getState_wrapper(const MjModel& m, const MjData& d, const val& state, unsigned int spec) { UNPACK_VALUE(mjtNum, state); CHECK_SIZE(state, mj_stateSize(m.get(), spec)); mj_getState(m.get(), d.get(), state_.data(), spec); } void mj_setState_wrapper(const MjModel& m, MjData& d, const NumberArray& state, unsigned int spec) { UNPACK_ARRAY(mjtNum, state); CHECK_SIZE(state, mj_stateSize(m.get(), spec)); mj_setState(m.get(), d.get(), state_.data(), spec); } void mj_mulJacVec_wrapper(const MjModel& m, const MjData& d, const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(res, d.nefc()); CHECK_SIZE(vec, m.nv()); mj_mulJacVec(m.get(), d.get(), res_.data(), vec_.data()); } void mj_mulJacTVec_wrapper(const MjModel& m, const MjData& d, const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(res, m.nv()); CHECK_SIZE(vec, d.nefc()); mj_mulJacTVec(m.get(), d.get(), res_.data(), vec_.data()); } void mj_jac_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, const NumberArray& point, int body) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); UNPACK_ARRAY(mjtNum, point); CHECK_SIZE(point, 3); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jac(m.get(), d.get(), jacp_.data(), jacr_.data(), point_.data(), body); } void mj_jacBody_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, int body) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jacBody(m.get(), d.get(), jacp_.data(), jacr_.data(), body); } void mj_jacBodyCom_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, int body) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jacBodyCom(m.get(), d.get(), jacp_.data(), jacr_.data(), body); } void mj_jacSubtreeCom_wrapper(const MjModel& m, MjData& d, const val& jacp, int body) { UNPACK_VALUE(mjtNum, jacp); CHECK_SIZE(jacp, m.nv() * 3); mj_jacSubtreeCom(m.get(), d.get(), jacp_.data(), body); } void mj_jacGeom_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, int geom) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jacGeom(m.get(), d.get(), jacp_.data(), jacr_.data(), geom); } void mj_jacSite_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, int site) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jacSite(m.get(), d.get(), jacp_.data(), jacr_.data(), site); } void mj_jacPointAxis_wrapper(const MjModel& m, MjData& d, const val& jacPoint, const val& jacAxis, const NumberArray& point, const NumberArray& axis, int body) { UNPACK_NULLABLE_VALUE(mjtNum, jacPoint); UNPACK_NULLABLE_VALUE(mjtNum, jacAxis); UNPACK_ARRAY(mjtNum, point); UNPACK_ARRAY(mjtNum, axis); CHECK_SIZE(point, 3); CHECK_SIZE(axis, 3); CHECK_SIZE(jacPoint, m.nv() * 3); CHECK_SIZE(jacAxis, m.nv() * 3); mj_jacPointAxis(m.get(), d.get(), jacPoint_.data(), jacAxis_.data(), point_.data(), axis_.data(), body); } void mj_jacDot_wrapper(const MjModel& m, const MjData& d, const val& jacp, const val& jacr, const NumberArray& point, int body) { UNPACK_NULLABLE_VALUE(mjtNum, jacp); UNPACK_NULLABLE_VALUE(mjtNum, jacr); UNPACK_ARRAY(mjtNum, point); CHECK_SIZE(point, 3); CHECK_SIZE(jacp, m.nv() * 3); CHECK_SIZE(jacr, m.nv() * 3); mj_jacDot(m.get(), d.get(), jacp_.data(), jacr_.data(), point_.data(), body); } void mj_angmomMat_wrapper(const MjModel& m, MjData& d, const val& mat, int body) { UNPACK_VALUE(mjtNum, mat); CHECK_SIZE(mat, m.nv() * 3); mj_angmomMat(m.get(), d.get(), mat_.data(), body); } void mj_fullM_wrapper(const MjModel& m, const val& dst, const NumberArray& M) { UNPACK_VALUE(mjtNum, dst); UNPACK_ARRAY(mjtNum, M); CHECK_SIZE(M, m.nM()); CHECK_SIZE(dst, m.nv() * m.nv()); mj_fullM(m.get(), dst_.data(), M_.data()); } void mj_mulM_wrapper(const MjModel& m, const MjData& d, const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(res, m.nv()); CHECK_SIZE(vec, m.nv()); mj_mulM(m.get(), d.get(), res_.data(), vec_.data()); } void mj_mulM2_wrapper(const MjModel& m, const MjData& d, const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(res, m.nv()); CHECK_SIZE(vec, m.nv()); mj_mulM2(m.get(), d.get(), res_.data(), vec_.data()); } void mj_addM_wrapper(const MjModel& m, MjData& d, const val& dst, const val& rownnz, const val& rowadr, const val& colind) { UNPACK_VALUE(mjtNum, dst); UNPACK_NULLABLE_VALUE(int, rownnz); UNPACK_NULLABLE_VALUE(int, rowadr); UNPACK_NULLABLE_VALUE(int, colind); CHECK_SIZE(rownnz, m.nv()); CHECK_SIZE(rowadr, m.nv()); CHECK_SIZE(colind, m.nM()); CHECK_SIZE(dst, m.nM()); mj_addM(m.get(), d.get(), dst_.data(), rownnz_.data(), rowadr_.data(), colind_.data()); } void mj_applyFT_wrapper(const MjModel& m, MjData& d, const NumberArray& force, const NumberArray& torque, const NumberArray& point, int body, const val& qfrc_target) { UNPACK_NULLABLE_ARRAY(mjtNum, force); UNPACK_NULLABLE_ARRAY(mjtNum, torque); UNPACK_ARRAY(mjtNum, point); UNPACK_VALUE(mjtNum, qfrc_target); CHECK_SIZE(qfrc_target, m.nv()); CHECK_SIZE(force, 3); CHECK_SIZE(torque, 3); CHECK_SIZE(point, 3); mj_applyFT(m.get(), d.get(), force_.data(), torque_.data(), point_.data(), body, qfrc_target_.data()); } mjtNum mj_geomDistance_wrapper(const MjModel& m, const MjData& d, int geom1, int geom2, mjtNum distmax, const val& fromto) { UNPACK_NULLABLE_VALUE(mjtNum, fromto); CHECK_SIZE(fromto, 6); return mj_geomDistance(m.get(), d.get(), geom1, geom2, distmax, fromto_.data()); } void mj_differentiatePos_wrapper(const MjModel& m, const val& qvel, mjtNum dt, const NumberArray& qpos1, const NumberArray& qpos2) { UNPACK_VALUE(mjtNum, qvel); UNPACK_ARRAY(mjtNum, qpos1); UNPACK_ARRAY(mjtNum, qpos2); CHECK_SIZE(qvel, m.nv()); CHECK_SIZE(qpos1, m.nq()); CHECK_SIZE(qpos2, m.nq()); mj_differentiatePos(m.get(), qvel_.data(), dt, qpos1_.data(), qpos2_.data()); } void mj_integratePos_wrapper(const MjModel& m, const val& qpos, const NumberArray& qvel, mjtNum dt) { UNPACK_VALUE(mjtNum, qpos); UNPACK_ARRAY(mjtNum, qvel); CHECK_SIZE(qpos, m.nq()); CHECK_SIZE(qvel, m.nv()); mj_integratePos(m.get(), qpos_.data(), qvel_.data(), dt); } void mj_normalizeQuat_wrapper(const MjModel& m, const val& qpos) { UNPACK_VALUE(mjtNum, qpos); CHECK_SIZE(qpos, m.nq()); mj_normalizeQuat(m.get(), qpos_.data()); } void mj_multiRay_wrapper(const MjModel& m, MjData& d, const NumberArray& pnt, const NumberArray& vec, const val& geomgroup, mjtByte flg_static, int bodyexclude, const val& geomid, const val& dist, int nray, mjtNum cutoff) { UNPACK_ARRAY(mjtNum, pnt); UNPACK_ARRAY(mjtNum, vec); UNPACK_VALUE(mjtByte, geomgroup); UNPACK_VALUE(int, geomid); UNPACK_VALUE(mjtNum, dist); CHECK_SIZE(dist, nray); CHECK_SIZE(geomid, nray); CHECK_SIZE(vec, 3 * nray); mj_multiRay(m.get(), d.get(), pnt_.data(), vec_.data(), geomgroup_.data(), flg_static, bodyexclude, geomid_.data(), dist_.data(), nray, cutoff); } void mju_zero_wrapper(const val& res) { UNPACK_VALUE(mjtNum, res); mju_zero(res_.data(), res_.size()); } void mju_fill_wrapper(const val& res, mjtNum val) { UNPACK_VALUE(mjtNum, res); mju_fill(res_.data(), val, res_.size()); } void mju_copy_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_copy(res_.data(), vec_.data(), res_.size()); } mjtNum mju_sum_wrapper(const NumberArray& vec) { UNPACK_ARRAY(mjtNum, vec); return mju_sum(vec_.data(), vec_.size()); } mjtNum mju_L1_wrapper(const NumberArray& vec) { UNPACK_ARRAY(mjtNum, vec); return mju_L1(vec_.data(), vec_.size()); } void mju_scl_wrapper(const val& res, const NumberArray& vec, mjtNum scl) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_scl(res_.data(), vec_.data(), scl, res_.size()); } void mju_add_wrapper(const val& res, const NumberArray& vec1, const NumberArray& vec2) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec1); UNPACK_ARRAY(mjtNum, vec2); CHECK_SIZES(res, vec1); CHECK_SIZES(res, vec2); mju_add(res_.data(), vec1_.data(), vec2_.data(), res_.size()); } void mju_sub_wrapper(const val& res, const NumberArray& vec1, const NumberArray& vec2) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec1); UNPACK_ARRAY(mjtNum, vec2); CHECK_SIZES(res, vec1); CHECK_SIZES(res, vec2); mju_sub(res_.data(), vec1_.data(), vec2_.data(), res_.size()); } void mju_addTo_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_addTo(res_.data(), vec_.data(), res_.size()); } void mju_subFrom_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_subFrom(res_.data(), vec_.data(), res_.size()); } void mju_addToScl_wrapper(const val& res, const NumberArray& vec, mjtNum scl) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_addToScl(res_.data(), vec_.data(), scl, res_.size()); } void mju_addScl_wrapper(const val& res, const NumberArray& vec1, const NumberArray& vec2, mjtNum scl) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, vec1); UNPACK_ARRAY(mjtNum, vec2); CHECK_SIZES(res, vec1); CHECK_SIZES(res, vec2); mju_addScl(res_.data(), vec1_.data(), vec2_.data(), scl, res_.size()); } mjtNum mju_normalize_wrapper(const val& res) { UNPACK_VALUE(mjtNum, res); return mju_normalize(res_.data(), res_.size()); } mjtNum mju_norm_wrapper(const NumberArray& res) { UNPACK_ARRAY(mjtNum, res); return mju_norm(res_.data(), res_.size()); } mjtNum mju_dot_wrapper(const NumberArray& vec1, const NumberArray& vec2) { UNPACK_ARRAY(mjtNum, vec1); UNPACK_ARRAY(mjtNum, vec2); CHECK_SIZES(vec1, vec2); return mju_dot(vec1_.data(), vec2_.data(), vec1_.size()); } void mju_mulMatVec_wrapper(const val& res, const NumberArray& mat, const NumberArray& vec, int nr, int nc) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(mat, nr * nc); CHECK_SIZE(res, nr); CHECK_SIZE(vec, nc); mju_mulMatVec(res_.data(), mat_.data(), vec_.data(), nr, nc); } void mju_mulMatTVec_wrapper(const val& res, const NumberArray& mat, const NumberArray& vec, int nr, int nc) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(mat, nr * nc); CHECK_SIZE(res, nc); CHECK_SIZE(vec, nr); mju_mulMatTVec(res_.data(), mat_.data(), vec_.data(), nr, nc); } mjtNum mju_mulVecMatVec_wrapper(const NumberArray& vec1, const NumberArray& mat, const NumberArray& vec2) { UNPACK_ARRAY(mjtNum, vec1); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec2); int64_t vec1_times_vec2 = vec1_.size() * vec2_.size(); CHECK_SIZES(vec1, vec2); CHECK_SIZE(mat, vec1_times_vec2); return mju_mulVecMatVec(vec1_.data(), mat_.data(), vec2_.data(), vec1_.size()); } void mju_transpose_wrapper(const val& res, const NumberArray& mat, int nr, int nc) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); CHECK_SIZE(mat, nr * nc); CHECK_SIZE(res, nr * nc); mju_transpose(res_.data(), mat_.data(), nr, nc); } void mju_symmetrize_wrapper(const val& res, const NumberArray& mat, int n) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); CHECK_SIZE(mat, n * n); CHECK_SIZE(res, n * n); mju_symmetrize(res_.data(), mat_.data(), n); } void mju_eye_wrapper(const val& mat) { UNPACK_VALUE(mjtNum, mat); CHECK_PERFECT_SQUARE(mat); mju_eye(mat_.data(), mat_sqrt); } void mju_mulMatMat_wrapper(const val& res, const NumberArray& mat1, const NumberArray& mat2, int r1, int c1, int c2) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat1); UNPACK_ARRAY(mjtNum, mat2); CHECK_SIZE(res, r1 * c2); CHECK_SIZE(mat1, r1 * c1); CHECK_SIZE(mat2, c1 * c2); mju_mulMatMat(res_.data(), mat1_.data(), mat2_.data(), r1, c1, c2); } void mju_mulMatMatT_wrapper(const val& res, const NumberArray& mat1, const NumberArray& mat2, int r1, int c1, int r2) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat1); UNPACK_ARRAY(mjtNum, mat2); CHECK_SIZE(res, r1 * r2); CHECK_SIZE(mat1, r1 * c1); CHECK_SIZE(mat2, r2 * c1); mju_mulMatMatT(res_.data(), mat1_.data(), mat2_.data(), r1, c1, r2); } void mju_mulMatTMat_wrapper(const val& res, const NumberArray& mat1, const NumberArray& mat2, int r1, int c1, int c2) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat1); UNPACK_ARRAY(mjtNum, mat2); CHECK_SIZE(res, c1 * c2); CHECK_SIZE(mat1, r1 * c1); CHECK_SIZE(mat2, r1 * c2); mju_mulMatTMat(res_.data(), mat1_.data(), mat2_.data(), r1, c1, c2); } void mju_sqrMatTD_wrapper(const val& res, const NumberArray& mat, const NumberArray& diag, int nr, int nc) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, diag); CHECK_SIZE(mat, nr * nc); CHECK_SIZE(res, nc * nc); CHECK_SIZE(diag, nr); mju_sqrMatTD(res_.data(), mat_.data(), diag_.data(), nr, nc); } int mju_dense2sparse_wrapper(const val& res, const NumberArray& mat, int nr, int nc, const val& rownnz, const val& rowadr, const val& colind) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_VALUE(int, rownnz); UNPACK_VALUE(int, rowadr); UNPACK_VALUE(int, colind); CHECK_SIZE(mat, nr * nc); CHECK_SIZE(rownnz, nr); CHECK_SIZE(rowadr, nr); CHECK_SIZE(colind, res_.size()); return mju_dense2sparse(res_.data(), mat_.data(), nr, nc, rownnz_.data(), rowadr_.data(), colind_.data(), res_.size()); } void mju_sparse2dense_wrapper(const val& res, const NumberArray& mat, int nr, int nc, const NumberArray& rownnz, const NumberArray& rowadr, const NumberArray& colind) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(int, rownnz); UNPACK_ARRAY(int, rowadr); UNPACK_ARRAY(int, colind); CHECK_SIZE(res, nr * nc); CHECK_SIZE(rownnz, nr); CHECK_SIZE(rowadr, nr); mju_sparse2dense(res_.data(), mat_.data(), nr, nc, rownnz_.data(), rowadr_.data(), colind_.data()); } int mju_cholFactor_wrapper(const val& mat, mjtNum mindiag) { UNPACK_VALUE(mjtNum, mat); CHECK_PERFECT_SQUARE(mat); return mju_cholFactor(mat_.data(), mat_sqrt, mindiag); } void mju_cholSolve_wrapper(const val& res, const NumberArray& mat, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec); CHECK_PERFECT_SQUARE(mat); CHECK_SIZE(res, mat_sqrt); CHECK_SIZE(vec, mat_sqrt); mju_cholSolve(res_.data(), mat_.data(), vec_.data(), mat_sqrt); } int mju_cholUpdate_wrapper(const val& mat, const val& x, int flg_plus) { UNPACK_VALUE(mjtNum, mat); UNPACK_VALUE(mjtNum, x); CHECK_PERFECT_SQUARE(mat); CHECK_SIZE(x, mat_sqrt); return mju_cholUpdate(mat_.data(), x_.data(), mat_sqrt, flg_plus); } mjtNum mju_cholFactorBand_wrapper(const val& mat, int ntotal, int nband, int ndense, mjtNum diagadd, mjtNum diagmul) { UNPACK_VALUE(mjtNum, mat); CHECK_SIZE(mat, (ntotal - ndense) * nband + ndense * ntotal); return mju_cholFactorBand(mat_.data(), ntotal, nband, ndense, diagadd, diagmul); } void mju_cholSolveBand_wrapper(const val& res, const NumberArray& mat, const NumberArray& vec, int ntotal, int nband, int ndense) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(mat, (ntotal - ndense) * nband + ndense * ntotal); CHECK_SIZE(res, ntotal); CHECK_SIZE(vec, ntotal); mju_cholSolveBand(res_.data(), mat_.data(), vec_.data(), ntotal, nband, ndense); } void mju_band2Dense_wrapper(const val& res, const NumberArray& mat, int ntotal, int nband, int ndense, mjtByte flg_sym) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); CHECK_SIZE(mat, (ntotal - ndense) * nband + ndense * ntotal); CHECK_SIZE(res, ntotal * ntotal); mju_band2Dense(res_.data(), mat_.data(), ntotal, nband, ndense, flg_sym); } void mju_dense2Band_wrapper(const val& res, const NumberArray& mat, int ntotal, int nband, int ndense) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); CHECK_SIZE(mat, ntotal * ntotal); CHECK_SIZE(res, (ntotal - ndense) * nband + ndense * ntotal); mju_dense2Band(res_.data(), mat_.data(), ntotal, nband, ndense); } void mju_bandMulMatVec_wrapper(const val& res, const NumberArray& mat, const NumberArray& vec, int ntotal, int nband, int ndense, int nvec, mjtByte flg_sym) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(mjtNum, mat); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZE(mat, (ntotal - ndense) * nband + ndense * ntotal); CHECK_SIZE(res, ntotal * nvec); CHECK_SIZE(vec, ntotal * nvec); mju_bandMulMatVec(res_.data(), mat_.data(), vec_.data(), ntotal, nband, ndense, nvec, flg_sym); } int mju_boxQP_wrapper(const val& res, const val& R, const val& index, const NumberArray& H, const NumberArray& g, const NumberArray& lower, const NumberArray& upper) { UNPACK_VALUE(mjtNum, res); UNPACK_VALUE(mjtNum, R); UNPACK_NULLABLE_VALUE(int, index); UNPACK_ARRAY(mjtNum, H); UNPACK_ARRAY(mjtNum, g); UNPACK_NULLABLE_ARRAY(mjtNum, lower); UNPACK_NULLABLE_ARRAY(mjtNum, upper); CHECK_SIZES(lower, res); CHECK_SIZES(upper, res); CHECK_SIZES(index, res); CHECK_SIZE(R, res_.size() * (res_.size() + 7)) CHECK_PERFECT_SQUARE(H); CHECK_SIZES(g, res); return mju_boxQP(res_.data(), R_.data(), index_.data(), H_.data(), g_.data(), res_.size(), lower_.data(), upper_.data()); } void mju_encodePyramid_wrapper(const val& pyramid, const NumberArray& force, const NumberArray& mu) { UNPACK_VALUE(mjtNum, pyramid); UNPACK_ARRAY(mjtNum, force); UNPACK_ARRAY(mjtNum, mu); CHECK_SIZE(pyramid, 2 * mu_.size()); CHECK_SIZE(force, mu_.size() + 1); mju_encodePyramid(pyramid_.data(), force_.data(), mu_.data(), mu_.size()); } void mju_decodePyramid_wrapper(const val& force, const NumberArray& pyramid, const NumberArray& mu) { UNPACK_VALUE(mjtNum, force); UNPACK_ARRAY(mjtNum, pyramid); UNPACK_ARRAY(mjtNum, mu); CHECK_SIZE(pyramid, 2 * mu_.size()); CHECK_SIZE(force, mu_.size() + 1); mju_decodePyramid(force_.data(), pyramid_.data(), mu_.data(), mu_.size()); } int mju_isZero_wrapper(const val& vec) { UNPACK_VALUE(mjtNum, vec); return mju_isZero(vec_.data(), vec_.size()); } void mju_f2n_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(float, vec); CHECK_SIZES(res, vec); mju_f2n(res_.data(), vec_.data(), res_.size()); } void mju_n2f_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(float, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_n2f(res_.data(), vec_.data(), res_.size()); } void mju_d2n_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(mjtNum, res); UNPACK_ARRAY(double, vec); CHECK_SIZES(res, vec); mju_d2n(res_.data(), vec_.data(), res_.size()); } void mju_n2d_wrapper(const val& res, const NumberArray& vec) { UNPACK_VALUE(double, res); UNPACK_ARRAY(mjtNum, vec); CHECK_SIZES(res, vec); mju_n2d(res_.data(), vec_.data(), res_.size()); } void mju_insertionSort_wrapper(const val& list) { UNPACK_VALUE(mjtNum, list); mju_insertionSort(list_.data(), list_.size()); } void mju_insertionSortInt_wrapper(const val& list) { UNPACK_VALUE(int, list); mju_insertionSortInt(list_.data(), list_.size()); } void mjd_transitionFD_wrapper(const MjModel& m, MjData& d, mjtNum eps, mjtByte flg_centered, const val& A, const val& B, const val& C, const val& D) { UNPACK_NULLABLE_VALUE(mjtNum, A); UNPACK_NULLABLE_VALUE(mjtNum, B); UNPACK_NULLABLE_VALUE(mjtNum, C); UNPACK_NULLABLE_VALUE(mjtNum, D); CHECK_SIZE(A, (2 * m.nv() + m.na()) * (2 * m.nv() + m.na())); CHECK_SIZE(B, (2 * m.nv() + m.na()) * m.nu()); CHECK_SIZE(C, m.nsensordata() * (2 * m.nv() + m.na())); CHECK_SIZE(D, m.nsensordata() * m.nu()); mjd_transitionFD(m.get(), d.get(), eps, flg_centered, A_.data(), B_.data(), C_.data(), D_.data()); } void mjd_inverseFD_wrapper(const MjModel& m, MjData& d, mjtNum eps, mjtByte flg_actuation, const val& DfDq, const val& DfDv, const val& DfDa, const val& DsDq, const val& DsDv, const val& DsDa, const val& DmDq) { UNPACK_NULLABLE_VALUE(mjtNum, DfDq); UNPACK_NULLABLE_VALUE(mjtNum, DfDv); UNPACK_NULLABLE_VALUE(mjtNum, DfDa); UNPACK_NULLABLE_VALUE(mjtNum, DsDq); UNPACK_NULLABLE_VALUE(mjtNum, DsDv); UNPACK_NULLABLE_VALUE(mjtNum, DsDa); UNPACK_NULLABLE_VALUE(mjtNum, DmDq); CHECK_SIZE(DfDq, m.nv() * m.nv()); CHECK_SIZE(DfDv, m.nv() * m.nv()); CHECK_SIZE(DfDa, m.nv() * m.nv()); CHECK_SIZE(DsDq, m.nv() * m.nsensordata()); CHECK_SIZE(DsDv, m.nv() * m.nsensordata()); CHECK_SIZE(DsDa, m.nv() * m.nsensordata()); CHECK_SIZE(DmDq, m.nv() * m.nM()); mjd_inverseFD(m.get(), d.get(), eps, flg_actuation, DfDq_.data(), DfDv_.data(), DfDa_.data(), DsDq_.data(), DsDv_.data(), DsDa_.data(), DmDq_.data()); } void mjd_subQuat_wrapper(const NumberArray& qa, const NumberArray& qb, const val& Da, const val& Db) { UNPACK_ARRAY(mjtNum, qa); UNPACK_ARRAY(mjtNum, qb); UNPACK_NULLABLE_VALUE(mjtNum, Da); UNPACK_NULLABLE_VALUE(mjtNum, Db); CHECK_SIZE(qa, 4); CHECK_SIZE(qb, 4); CHECK_SIZE(Da, 9); CHECK_SIZE(Db, 9); mjd_subQuat(qa_.data(), qb_.data(), Da_.data(), Db_.data()); } EMSCRIPTEN_BINDINGS(mujoco_functions) { // {{ FUNCTION_BINDINGS }} function("error", &error_wrapper); function("mju_printMatSparse", &mju_printMatSparse_wrapper); function("mj_solveM", &mj_solveM_wrapper); function("mj_solveM2", &mj_solveM2_wrapper); function("mj_rne", &mj_rne_wrapper); function("mj_saveLastXML", &mj_saveLastXML_wrapper); function("mj_setLengthRange", &mj_setLengthRange_wrapper); function("mj_constraintUpdate", &mj_constraintUpdate_wrapper); function("mj_getState", &mj_getState_wrapper); function("mj_setState", &mj_setState_wrapper); function("mj_mulJacVec", &mj_mulJacVec_wrapper); function("mj_mulJacTVec", &mj_mulJacTVec_wrapper); function("mj_jac", &mj_jac_wrapper); function("mj_jacBody", &mj_jacBody_wrapper); function("mj_jacBodyCom", &mj_jacBodyCom_wrapper); function("mj_jacSubtreeCom", &mj_jacSubtreeCom_wrapper); function("mj_jacGeom", &mj_jacGeom_wrapper); function("mj_jacSite", &mj_jacSite_wrapper); function("mj_jacPointAxis", &mj_jacPointAxis_wrapper); function("mj_jacDot", &mj_jacDot_wrapper); function("mj_angmomMat", &mj_angmomMat_wrapper); function("mj_fullM", &mj_fullM_wrapper); function("mj_mulM", &mj_mulM_wrapper); function("mj_mulM2", &mj_mulM2_wrapper); function("mj_addM", &mj_addM_wrapper); function("mj_applyFT", &mj_applyFT_wrapper); function("mj_geomDistance", &mj_geomDistance_wrapper); function("mj_differentiatePos", &mj_differentiatePos_wrapper); function("mj_integratePos", &mj_integratePos_wrapper); function("mj_normalizeQuat", &mj_normalizeQuat_wrapper); function("mj_multiRay", &mj_multiRay_wrapper); function("mju_zero", &mju_zero_wrapper); function("mju_fill", &mju_fill_wrapper); function("mju_copy", &mju_copy_wrapper); function("mju_sum", &mju_sum_wrapper); function("mju_L1", &mju_L1_wrapper); function("mju_scl", &mju_scl_wrapper); function("mju_add", &mju_add_wrapper); function("mju_sub", &mju_sub_wrapper); function("mju_addTo", &mju_addTo_wrapper); function("mju_subFrom", &mju_subFrom_wrapper); function("mju_addToScl", &mju_addToScl_wrapper); function("mju_addScl", &mju_addScl_wrapper); function("mju_normalize", &mju_normalize_wrapper); function("mju_norm", &mju_norm_wrapper); function("mju_dot", &mju_dot_wrapper); function("mju_mulMatVec", &mju_mulMatVec_wrapper); function("mju_mulMatTVec", &mju_mulMatTVec_wrapper); function("mju_mulVecMatVec", &mju_mulVecMatVec_wrapper); function("mju_transpose", &mju_transpose_wrapper); function("mju_symmetrize", &mju_symmetrize_wrapper); function("mju_eye", &mju_eye_wrapper); function("mju_mulMatMat", &mju_mulMatMat_wrapper); function("mju_mulMatMatT", &mju_mulMatMatT_wrapper); function("mju_mulMatTMat", &mju_mulMatTMat_wrapper); function("mju_sqrMatTD", &mju_sqrMatTD_wrapper); function("mju_dense2sparse", &mju_dense2sparse_wrapper); function("mju_sparse2dense", &mju_sparse2dense_wrapper); function("mju_cholFactor", &mju_cholFactor_wrapper); function("mju_cholSolve", &mju_cholSolve_wrapper); function("mju_cholUpdate", &mju_cholUpdate_wrapper); function("mju_cholFactorBand", &mju_cholFactorBand_wrapper); function("mju_cholSolveBand", &mju_cholSolveBand_wrapper); function("mju_band2Dense", &mju_band2Dense_wrapper); function("mju_dense2Band", &mju_dense2Band_wrapper); function("mju_bandMulMatVec", &mju_bandMulMatVec_wrapper); function("mju_boxQP", &mju_boxQP_wrapper); function("mju_encodePyramid", &mju_encodePyramid_wrapper); function("mju_decodePyramid", &mju_decodePyramid_wrapper); function("mju_isZero", &mju_isZero_wrapper); function("mju_f2n", &mju_f2n_wrapper); function("mju_n2f", &mju_n2f_wrapper); function("mju_d2n", &mju_d2n_wrapper); function("mju_n2d", &mju_n2d_wrapper); function("mju_insertionSort", &mju_insertionSort_wrapper); function("mju_insertionSortInt", &mju_insertionSortInt_wrapper); function("mjd_transitionFD", &mjd_transitionFD_wrapper); function("mjd_inverseFD", &mjd_inverseFD_wrapper); function("mjd_subQuat", &mjd_subQuat_wrapper); class_>("FloatBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); class_>("DoubleBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); class_>("IntBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); register_vector("mjStringVec"); register_vector("mjIntVec"); register_vector("mjIntVecVec"); register_vector("mjFloatVec"); register_vector("mjFloatVecVec"); register_vector("mjDoubleVec"); // register_type gives better type information (val is mapped to any by default) register_type("number[]"); register_type("string"); register_vector("mjByteVec"); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); register_optional(); } } // namespace mujoco::wasm // NOLINTEND(whitespace/semicolon) // NOLINTEND(whitespace/line_length)