diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index 28040c82..12da5cad 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -1841,7 +1841,7 @@ mju_error_i .. mujoco-include:: mju_error_i -Error function with int argument; msg is a printf format string. +Deprecated: use mju_error .. _mju_error_s: @@ -1850,7 +1850,7 @@ mju_error_s .. mujoco-include:: mju_error_s -Error function with string argument. +Deprecated: use mju_error .. _mju_warning: @@ -1868,7 +1868,7 @@ mju_warning_i .. mujoco-include:: mju_warning_i -Warning function with int argument. +Deprecated: use mju_warning .. _mju_warning_s: @@ -1877,7 +1877,7 @@ mju_warning_s .. mujoco-include:: mju_warning_s -Warning function with string argument. +Deprecated: use_mju_warning .. _mju_clearHandlers: diff --git a/doc/changelog.rst b/doc/changelog.rst index 65fa17b1..a9b502a1 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -16,6 +16,8 @@ General For instance, the constraint Jacobian matrix from the `humanoid100.xml `_ model, which previously required ~500,000 ``mjtNum``'s, now only requires ~6000. Very large models can now load and run with the CG solver. +- Modified :ref:`mju_error` and :ref:`mju_warning` to be variadic functions (support for printf-like arguments). The + functions :ref:`mju_error_i`, :ref:`mju_error_s`, :ref:`mju_warning_i`, and :ref:`mju_warning_s` are now deprecated. diff --git a/doc/includes/references.h b/doc/includes/references.h index 0b9dc319..0b39e000 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -2041,10 +2041,10 @@ void mjui_update(int section, int item, const mjUI* ui, const mjuiState* state, const mjrContext* con); mjuiItem* mjui_event(mjUI* ui, mjuiState* state, const mjrContext* con); void mjui_render(mjUI* ui, const mjuiState* state, const mjrContext* con); -void mju_error(const char* msg); +void mju_error(const char* msg, ...) mjPRINTFLIKE(1, 2); void mju_error_i(const char* msg, int i); void mju_error_s(const char* msg, const char* text); -void mju_warning(const char* msg); +void mju_warning(const char* msg, ...) mjPRINTFLIKE(1, 2); void mju_warning_i(const char* msg, int i); void mju_warning_s(const char* msg, const char* text); void mju_clearHandlers(void); diff --git a/doc/programming/simulation.rst b/doc/programming/simulation.rst index 87250267..aa6b7f0a 100644 --- a/doc/programming/simulation.rst +++ b/doc/programming/simulation.rst @@ -724,16 +724,13 @@ triggers an error. It also keeps track of the maximum stack allocation; see :ref Errors, warnings, memory allocation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When a terminal error occurs, MuJoCo calls the function :ref:`mju_error` internally. This function has a single argument -which is the error message. The helper functions :ref:`mju_error_i` and :ref:`mju_error_s` are also used, but they -simply construct the error message using a printf format string and an additional integer or string argument, and then -call mju_error. Here is what mju_error does: +When a terminal error occurs, MuJoCo calls the function :ref:`mju_error` internally. Here is what mju_error does: #. Append the error message at the end of the file MUJOCO_LOG.TXT in the program directory (create the file if it does not exist). Also write the date and time along with the error message. -#. If the user error callback :ref:`mju_user_error` is installed, call that function - with the error message as argument. Otherwise printf the error message, printf "Press Enter to exit...", getchar() - and exit(1). +#. If the user error callback :ref:`mju_user_error` is installed, call that function with the error message as + argument. Otherwise, print the error message and "Press Enter to exit..." to standard output. Then wait for any + keyboard input, and then terminate the simulator with failure. If a user error callback is installed, it must **not** return, otherwise the behavior of the simulator is undefined. The idea here is that if mju_error is called, the simulation cannot continue and the user is expected to make some @@ -988,4 +985,4 @@ of mass of the kinematic tree). Such a rotation will not only rotate the body bu spatial vector must have non-zero linear velocity to compensate for the side-effect of rotation around an off-body axis. If you call mj_objectVelocity, the resulting 6D quantity will be represented in a frame that is centered at the body and aligned with the world. Thus the linear component will now be zero as expected. This function will also put -translation in front of rotation, which is our convention for local and global coordinates. \ No newline at end of file +translation in front of rotation, which is our convention for local and global coordinates. diff --git a/include/mujoco/mujoco.h b/include/mujoco/mujoco.h index 3e392a80..9a270529 100644 --- a/include/mujoco/mujoco.h +++ b/include/mujoco/mujoco.h @@ -47,6 +47,14 @@ extern "C" { #define mjDISABLED(x) (m->opt.disableflags & (x)) #define mjENABLED(x) (m->opt.enableflags & (x)) +#ifndef mjPRINTFLIKE + #if defined(__GNUC__) + #define mjPRINTFLIKE(n, m) __attribute__((format(printf, n, m))) + #else + #define mjPRINTFLIKE(n, m) + #endif // __GNUC__ +#endif // mjPRINTFLIKE + // user error and memory handlers MJAPI extern void (*mju_user_error)(const char*); @@ -730,21 +738,21 @@ MJAPI void mjui_render(mjUI* ui, const mjuiState* state, const mjrContext* con); //---------------------------------- Error and memory ---------------------------------------------- // Main error function; does not return to caller. -MJAPI void mju_error(const char* msg); +MJAPI void mju_error(const char* msg, ...) mjPRINTFLIKE(1, 2); -// Error function with int argument; msg is a printf format string. +// Deprecated: use mju_error MJAPI void mju_error_i(const char* msg, int i); -// Error function with string argument. +// Deprecated: use mju_error MJAPI void mju_error_s(const char* msg, const char* text); // Main warning function; returns to caller. -MJAPI void mju_warning(const char* msg); +MJAPI void mju_warning(const char* msg, ...) mjPRINTFLIKE(1, 2); -// Warning function with int argument. +// Deprecated: use mju_warning MJAPI void mju_warning_i(const char* msg, int i); -// Warning function with string argument. +// Deprecated: use_mju_warning MJAPI void mju_warning_s(const char* msg, const char* text); // Clear user error and memory handlers. diff --git a/introspect/functions.py b/introspect/functions.py index 9ef1f67a..929d72b1 100644 --- a/introspect/functions.py +++ b/introspect/functions.py @@ -4674,7 +4674,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ type=ValueType(name='int'), ), ), - doc='Error function with int argument; msg is a printf format string.', + doc='Deprecated: use mju_error', )), ('mju_error_s', FunctionDecl( @@ -4694,7 +4694,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ ), ), ), - doc='Error function with string argument.', + doc='Deprecated: use mju_error', )), ('mju_warning', FunctionDecl( @@ -4726,7 +4726,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ type=ValueType(name='int'), ), ), - doc='Warning function with int argument.', + doc='Deprecated: use mju_warning', )), ('mju_warning_s', FunctionDecl( @@ -4746,7 +4746,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ ), ), ), - doc='Warning function with string argument.', + doc='Deprecated: use_mju_warning', )), ('mju_clearHandlers', FunctionDecl( diff --git a/python/mujoco/codegen/generate_function_traits.py b/python/mujoco/codegen/generate_function_traits.py index 7d95ff7c..a92604a1 100644 --- a/python/mujoco/codegen/generate_function_traits.py +++ b/python/mujoco/codegen/generate_function_traits.py @@ -30,6 +30,11 @@ def main(argv: Sequence[str]) -> None: struct_decls = [] for func in FUNCTIONS.values(): + # Skip mju_error_{i,s} and mju_warning_{i,s} as these are not + # supported in the Python bindings, and Introspect currently + # doesn't support variadic functions. + if func.name.startswith('mju_error') or func.name == 'mju_warning': + continue # Modify some parameter types. parameters = [] diff --git a/sample/basic.cc b/sample/basic.cc index cfa94571..e307b0b7 100644 --- a/sample/basic.cc +++ b/sample/basic.cc @@ -115,7 +115,7 @@ int main(int argc, const char** argv) { m = mj_loadXML(argv[1], 0, error, 1000); } if (!m) { - mju_error_s("Load model error: %s", error); + mju_error("Load model error: %s", error); } // make data diff --git a/sample/record.cc b/sample/record.cc index c5d57386..dd07411a 100644 --- a/sample/record.cc +++ b/sample/record.cc @@ -57,7 +57,7 @@ void initMuJoCo(const char* filename) { m = mj_loadXML(filename, 0, error, 1000); } if (!m) { - mju_error_s("Load model error: %s", error); + mju_error("Load model error: %s", error); } // make data, run one computation to initialize all fields @@ -109,36 +109,36 @@ void initOpenGL(void) { // get default display EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (eglDpy==EGL_NO_DISPLAY) { - mju_error_i("Could not get EGL display, error 0x%x\n", eglGetError()); + mju_error("Could not get EGL display, error 0x%x\n", eglGetError()); } // initialize EGLint major, minor; if (eglInitialize(eglDpy, &major, &minor)!=EGL_TRUE) { - mju_error_i("Could not initialize EGL, error 0x%x\n", eglGetError()); + mju_error("Could not initialize EGL, error 0x%x\n", eglGetError()); } // choose config EGLint numConfigs; EGLConfig eglCfg; if (eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs)!=EGL_TRUE) { - mju_error_i("Could not choose EGL config, error 0x%x\n", eglGetError()); + mju_error("Could not choose EGL config, error 0x%x\n", eglGetError()); } // bind OpenGL API if (eglBindAPI(EGL_OPENGL_API)!=EGL_TRUE) { - mju_error_i("Could not bind EGL OpenGL API, error 0x%x\n", eglGetError()); + mju_error("Could not bind EGL OpenGL API, error 0x%x\n", eglGetError()); } // create context EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT, NULL); if (eglCtx==EGL_NO_CONTEXT) { - mju_error_i("Could not create EGL context, error 0x%x\n", eglGetError()); + mju_error("Could not create EGL context, error 0x%x\n", eglGetError()); } // make context current, no surface (let OpenGL handle FBO) if (eglMakeCurrent(eglDpy, EGL_NO_SURFACE, EGL_NO_SURFACE, eglCtx)!=EGL_TRUE) { - mju_error_i("Could not make EGL context current, error 0x%x\n", eglGetError()); + mju_error("Could not make EGL context current, error 0x%x\n", eglGetError()); } //------------------------ OSMESA diff --git a/src/engine/engine_collision_convex.c b/src/engine/engine_collision_convex.c index 8af3dea1..1a9296e7 100644 --- a/src/engine/engine_collision_convex.c +++ b/src/engine/engine_collision_convex.c @@ -191,7 +191,7 @@ void mjccd_support(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *vec) { break; default: - mju_error_i("ccd support function is undefined for geom type %d", m->geom_type[g]); + mju_error("ccd support function is undefined for geom type %d", m->geom_type[g]); } // add dir*margin/2 to result diff --git a/src/engine/engine_collision_driver.c b/src/engine/engine_collision_driver.c index 3ed98526..0cd9bb1b 100644 --- a/src/engine/engine_collision_driver.c +++ b/src/engine/engine_collision_driver.c @@ -766,7 +766,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user, for (i=0; i 6 || condim < 1) { // SHOULD NOT OCCUR - mju_error_i("Invalid condim value: %d", i); + mju_error("Invalid condim value: %d", i); } con[i].dim = condim; con[i].geom1 = g1; diff --git a/src/engine/engine_core_constraint.c b/src/engine/engine_core_constraint.c index 80adf0df..6c97d348 100644 --- a/src/engine/engine_core_constraint.c +++ b/src/engine/engine_core_constraint.c @@ -541,7 +541,7 @@ void mj_instantiateEquality(const mjModel* m, mjData* d) { break; default: // SHOULD NOT OCCUR - mju_error_i("Invalid equality constraint type %d", m->eq_type[i]); + mju_error("Invalid equality constraint type %d", m->eq_type[i]); } // add constraint @@ -917,7 +917,7 @@ void mj_diagApprox(const mjModel* m, mjData* d) { break; default: - mju_error_i("Unknown constraint type type %d", d->efc_type[i]); // SHOULD NOT OCCUR + mju_error("Unknown constraint type type %d", d->efc_type[i]); // SHOULD NOT OCCUR } break; @@ -1616,52 +1616,29 @@ void mj_makeConstraint(const mjModel* m, mjData* d) { // check sparse allocation if (mj_isSparse(m)) { if (d->ne != ne_allocated) { - char msg[1024]; - - // TODO(b/270530821): add var argument support to mju_error - mjSNPRINTF( - msg, "ne mis-allocation: found ne=%d but allocated %d", d->ne, ne_allocated); - mju_error(msg); + mju_error("ne mis-allocation: found ne=%d but allocated %d", d->ne, ne_allocated); } if (d->nf != nf_allocated) { - char msg[1024]; - - // TODO(b/270530821): add var argument support to mju_error - mjSNPRINTF( - msg, "nf mis-allocation: found nf=%d but allocated %d", d->nf, nf_allocated); - mju_error(msg); + mju_error("nf mis-allocation: found nf=%d but allocated %d", d->nf, nf_allocated); } // check that nefc was computed correctly if (d->nefc != nefc_allocated) { - char msg[1024]; - - // TODO(b/270530821): add var argument support to mju_error - mjSNPRINTF( - msg, "nefc mis-allocation: found nefc=%d but allocated %d", d->nefc, nefc_allocated); - mju_error(msg); + mju_error("nefc mis-allocation: found nefc=%d but allocated %d", d->nefc, nefc_allocated); } // check that nnzJ was computed correctly if (d->nefc > 0) { int nnz = d->efc_J_rownnz[d->nefc - 1] + d->efc_J_rowadr[d->nefc - 1]; if (d->nnzJ != nnz) { - char msg[1024]; - - // TODO(b/270530821): add var argument support to mju_error - mjSNPRINTF( - msg, "constraint Jacobian mis-allocation: found nnzJ=%d but allocated %d", nnz, d->nnzJ); - mju_error(msg); + mju_error("constraint Jacobian mis-allocation: found nnzJ=%d but allocated %d", + nnz, d->nnzJ); } } } else if (d->nefc > nefc_allocated) { - char msg[1024]; - - // TODO(b/270530821): add var argument support to mju_error - mjSNPRINTF( - msg, "nefc under-allocation: found nefc=%d but allocated only %d", d->nefc, nefc_allocated); - mju_error(msg); + mju_error("nefc under-allocation: found nefc=%d but allocated only %d", + d->nefc, nefc_allocated); } // collect memory use statistics diff --git a/src/engine/engine_core_smooth.c b/src/engine/engine_core_smooth.c index 80af54e5..7aec7741 100644 --- a/src/engine/engine_core_smooth.c +++ b/src/engine/engine_core_smooth.c @@ -135,7 +135,7 @@ void mj_kinematics(const mjModel* m, mjData* d) { break; default: - mju_error_i("Unknown joint type %d", jtype); // SHOULD NOT OCCUR + mju_error("Unknown joint type %d", jtype); // SHOULD NOT OCCUR } // assign xanchor and xaxis @@ -514,7 +514,7 @@ void mj_tendon(const mjModel* m, mjData* d) { // do wrapping, possibly get 2 extra points (wlen>=0) sideid = mju_round(m->wrap_prm[adr+j+1]); if (sideid<-1 || sideid>=m->nsite) { - mju_error_i("Invalid sideid %d in wrap_prm", sideid); // SHOULD NOT OCCUR + mju_error("Invalid sideid %d in wrap_prm", sideid); // SHOULD NOT OCCUR } wlen = mju_wrap(wpnt+3, d->site_xpos+3*id0, d->site_xpos+3*id1, @@ -943,7 +943,7 @@ void mj_transmission(const mjModel* m, mjData* d) { break; default: - mju_error_i("Unknown transmission type %d", m->actuator_trntype[i]); // SHOULD NOT OCCUR + mju_error("Unknown transmission type %d", m->actuator_trntype[i]); // SHOULD NOT OCCUR } } @@ -1503,7 +1503,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) { int i = 0; while (i < d->ne) { if (d->efc_type[i]!=mjCNSTR_EQUALITY) - mju_error_i("Row %d of efc is not an equality constraint", i); // SHOULD NOT OCCUR + mju_error("Row %d of efc is not an equality constraint", i); // SHOULD NOT OCCUR int id = d->efc_id[i]; mjtNum* eq_data = m->eq_data + mjNEQDATA*id; @@ -1555,7 +1555,7 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) { break; default: - mju_error_i("Unknown constraint type type %d", m->eq_type[id]); // SHOULD NOT OCCUR + mju_error("Unknown constraint type type %d", m->eq_type[id]); // SHOULD NOT OCCUR } } diff --git a/src/engine/engine_file.c b/src/engine/engine_file.c index dbbf9b75..a0c52815 100644 --- a/src/engine/engine_file.c +++ b/src/engine/engine_file.c @@ -30,7 +30,7 @@ void* mju_fileToMemory(const char* filename, int* filesize) { // find size if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); - mju_warning_s("Failed to calculate size for '%s'", filename); + mju_warning("Failed to calculate size for '%s'", filename); return NULL; } @@ -38,11 +38,11 @@ void* mju_fileToMemory(const char* filename, int* filesize) { long long_filesize = ftell(fp); // NOLINT(runtime/int) if (long_filesize > INT_MAX) { fclose(fp); - mju_warning_s("File size over 2GB is not supported. File: '%s'", filename); + mju_warning("File size over 2GB is not supported. File: '%s'", filename); return NULL; } else if (long_filesize < 0) { fclose(fp); - mju_warning_s("Failed to calculate size for '%s'", filename); + mju_warning("Failed to calculate size for '%s'", filename); return NULL; } *filesize = long_filesize; @@ -50,7 +50,7 @@ void* mju_fileToMemory(const char* filename, int* filesize) { // go back to start of file if (fseek(fp, 0, SEEK_SET) != 0) { fclose(fp); - mju_warning_s("Read error while reading '%s'", filename); + mju_warning("Read error while reading '%s'", filename); return NULL; } @@ -67,7 +67,7 @@ void* mju_fileToMemory(const char* filename, int* filesize) { fclose(fp); mju_free(buffer); *filesize = 0; - mju_warning_s("Read error while reading '%s'", filename); + mju_warning("Read error while reading '%s'", filename); return NULL; } else if (feof(fp)) { *filesize = bytes_read; diff --git a/src/engine/engine_forward.c b/src/engine/engine_forward.c index 250e28cd..d7747001 100644 --- a/src/engine/engine_forward.c +++ b/src/engine/engine_forward.c @@ -278,11 +278,11 @@ void mj_fwdActuation(const mjModel* m, mjData* d) { const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if (plugin->capabilityflags & mjPLUGIN_ACTUATOR) { if (!plugin->compute) { - mju_error_i("`compute` is a null function pointer for plugin at slot %d", slot); + mju_error("`compute` is a null function pointer for plugin at slot %d", slot); } plugin->compute(m, d, i, mjPLUGIN_ACTUATOR); } @@ -480,7 +480,7 @@ void mj_fwdConstraint(const mjModel* m, mjData* d) { break; default: - mju_error_i("Unknown solver type %d", m->opt.solver); + mju_error("Unknown solver type %d", m->opt.solver); } // save result for next step warmstart @@ -533,7 +533,7 @@ static void mj_advance(const mjModel* m, mjData* d, const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if (plugin->advance) { plugin->advance(m, d, i); diff --git a/src/engine/engine_io.c b/src/engine/engine_io.c index ac2e571c..b6293861 100644 --- a/src/engine/engine_io.c +++ b/src/engine/engine_io.c @@ -566,7 +566,7 @@ void mj_saveModel(const mjModel* m, const char* filename, void* buffer, int buff if (!buffer) { fp = fopen(filename, "wb"); if (!fp) { - mju_warning_s("Could not open file '%s'", filename); + mju_warning("Could not open file '%s'", filename); return; } } @@ -632,7 +632,7 @@ mjModel* mj_loadModel(const char* filename, const mjVFS* vfs) { if (!buffer) { fp = fopen(filename, "rb"); if (!fp) { - mju_warning_s("Could not open file '%s'", filename); + mju_warning("Could not open file '%s'", filename); return 0; } } @@ -765,7 +765,7 @@ mjModel* mj_loadModel(const char* filename, const mjVFS* vfs) { const char* validationError = mj_validateReferences(m); if (validationError) { - mju_warning(validationError); + mju_warning("%s", validationError); mj_deleteModel(m); return 0; } @@ -888,7 +888,7 @@ static mjData* _makeData(const mjModel* m) { mju_free(d->buffer); mju_free(d->arena); mju_free(d); - mju_error_i("plugin->init failed for plugin id %d", i); + mju_error("plugin->init failed for plugin id %d", i); } } } @@ -1018,12 +1018,10 @@ mjtNum* mj_stackAlloc(mjData* d, int size) { size_t stack_available_bytes = d->nstack * sizeof(mjtNum) - d->parena; size_t stack_required_bytes = (d->pstack + size) * sizeof(mjtNum); if (stack_required_bytes > stack_available_bytes) { - char err[256]; - mjSNPRINTF(err, "stack overflow: max = %zu, available = %zu, requested = %zu " - "(ne = %d, nf = %d, nefc = %d, ncon = %d)", - d->nstack * sizeof(mjtNum), stack_available_bytes, stack_required_bytes, - d->ne, d->nf, d->nefc, d->ncon); - mju_error(err); + mju_error("stack overflow: max = %zu, available = %zu, requested = %zu " + "(ne = %d, nf = %d, nefc = %d, ncon = %d)", + d->nstack * sizeof(mjtNum), stack_available_bytes, stack_required_bytes, + d->ne, d->nf, d->nefc, d->ncon); } // allocate at end of arena @@ -1596,8 +1594,8 @@ const char* mj_validateReferences(const mjModel* m) { if (sensor_type == mjSENS_PLUGIN) { const mjpPlugin* plugin = mjp_getPluginAtSlot(m->plugin[m->sensor_plugin[i]]); if (!plugin->nsensordata) { - mju_error_i("`nsensordata` is a null function pointer for plugin at slot %d", - m->plugin[m->sensor_plugin[i]]); + mju_error("`nsensordata` is a null function pointer for plugin at slot %d", + m->plugin[m->sensor_plugin[i]]); } sensor_size = plugin->nsensordata(m, m->sensor_plugin[i], i); } else { diff --git a/src/engine/engine_passive.c b/src/engine/engine_passive.c index 7c38b539..4da2c278 100644 --- a/src/engine/engine_passive.c +++ b/src/engine/engine_passive.c @@ -168,11 +168,11 @@ void mj_passive(const mjModel* m, mjData* d) { const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if (plugin->capabilityflags & mjPLUGIN_PASSIVE) { if (!plugin->compute) { - mju_error_i("`compute` is a null function pointer for plugin at slot %d", slot); + mju_error("`compute` is a null function pointer for plugin at slot %d", slot); } plugin->compute(m, d, i, mjPLUGIN_PASSIVE); } diff --git a/src/engine/engine_plugin.cc b/src/engine/engine_plugin.cc index e933a361..046e5b1c 100644 --- a/src/engine/engine_plugin.cc +++ b/src/engine/engine_plugin.cc @@ -223,8 +223,8 @@ int mjp_registerPlugin(const mjpPlugin* plugin) { } else if (plugin->nattribute < 0) { mju_error("plugin->nattribute is negative"); } else if (plugin->nattribute > kMaxAttributes) { - mju_error_i("plugin->nattribute exceeds the maximum limit of ", - kMaxAttributes); + mju_error("plugin->nattribute exceeds the maximum limit of %i", + kMaxAttributes); } char err[512]; @@ -339,7 +339,7 @@ int mjp_registerPlugin(const mjpPlugin* plugin) { // plugin registration failed, throw an mju_error if (slot < 0) { err[sizeof(err) - 1] = '\0'; - mju_error(err); + mju_error("%s", err); } return slot; diff --git a/src/engine/engine_print.c b/src/engine/engine_print.c index 8bf02d49..78724273 100644 --- a/src/engine/engine_print.c +++ b/src/engine/engine_print.c @@ -139,13 +139,13 @@ static bool validateFloatFormat(const char* float_format) { // example valid format string: "% -9.2g" if (strnlen(float_format, FLOAT_FORMAT_MAX_LEN + 1) > FLOAT_FORMAT_MAX_LEN) { - mju_warning_i("Format string longer than limit of %d.", FLOAT_FORMAT_MAX_LEN); + mju_warning("Format string longer than limit of %d.", FLOAT_FORMAT_MAX_LEN); return false; } int cur_idx = 0; if (float_format[cur_idx] != '%') { - mju_warning("Format string must start with '%'."); + mju_warning("Format string must start with '%%'."); return false; } cur_idx++; @@ -192,8 +192,8 @@ static bool validateFloatFormat(const char* float_format) { if (float_format[cur_idx] == '\0') { return true; } else { - mju_warning_s("Unable to match format string %s with expected pattern for a single float.", - float_format); + mju_warning("Unable to match format string %s with expected pattern for a single float.", + float_format); return false; } } @@ -219,7 +219,7 @@ void mj_printFormattedModel(const mjModel* m, const char* filename, const char* // check for nullptr if (!fp) { - mju_warning_s("Could not open file '%s' for writing mjModel", filename); + mju_warning("Could not open file '%s' for writing mjModel", filename); return; } @@ -748,7 +748,7 @@ void mj_printFormattedData(const mjModel* m, mjData* d, const char* filename, // check for nullptr if (!fp) { - mju_warning_s("Could not open file '%s' for writing mjModel", filename); + mju_warning("Could not open file '%s' for writing mjModel", filename); mjFREESTACK; return; } diff --git a/src/engine/engine_ray.c b/src/engine/engine_ray.c index 066b2cf7..b32ca2a4 100644 --- a/src/engine/engine_ray.c +++ b/src/engine/engine_ray.c @@ -674,7 +674,7 @@ mjtNum mju_rayGeom(const mjtNum* pos, const mjtNum* mat, const mjtNum* size, return ray_box(pos, mat, size, pnt, vec, NULL); default: - mju_error_i("mju_rayGeom: unexpected geom type %d", geomtype); + mju_error("mju_rayGeom: unexpected geom type %d", geomtype); return -1; } } diff --git a/src/engine/engine_sensor.c b/src/engine/engine_sensor.c index 9f2cbf44..2acc7d35 100644 --- a/src/engine/engine_sensor.c +++ b/src/engine/engine_sensor.c @@ -96,7 +96,7 @@ static void add_noise(const mjModel* m, mjData* d, mjtStage stage) { // unknown datatype else { - mju_error_i("Unknown datatype in sensor %d", i); + mju_error("Unknown datatype in sensor %d", i); } } } @@ -158,7 +158,7 @@ static void get_xpos_xmat(const mjData* d, int type, int id, int sensor_id, *xmat = d->cam_xmat + 9*id; break; default: - mju_error_i("Invalid object type in sensor %d", sensor_id); + mju_error("Invalid object type in sensor %d", sensor_id); } } @@ -182,7 +182,7 @@ static void get_xquat(const mjModel* m, const mjData* d, int type, int id, int s mju_mulQuat(quat, d->xquat+4*m->cam_bodyid[id], m->cam_quat+4*id); break; default: - mju_error_i("Invalid object type in sensor %d", sensor_id); + mju_error("Invalid object type in sensor %d", sensor_id); } } @@ -334,7 +334,7 @@ void mj_sensorPos(const mjModel* m, mjData* d) { break; default: - mju_error_i("Invalid sensor type in POS stage, sensor %d", i); + mju_error("Invalid sensor type in POS stage, sensor %d", i); } } } @@ -356,12 +356,12 @@ void mj_sensorPos(const mjModel* m, mjData* d) { const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && (plugin->needstage==mjSTAGE_POS || plugin->needstage==mjSTAGE_NONE)) { if (!plugin->compute) { - mju_error_i("`compute` is a null function pointer for plugin at slot %d", slot); + mju_error("`compute` is a null function pointer for plugin at slot %d", slot); } plugin->compute(m, d, i, mjPLUGIN_SENSOR); } @@ -515,7 +515,7 @@ void mj_sensorVel(const mjModel* m, mjData* d) { break; default: - mju_error_i("Invalid type in VEL stage, sensor %d", i); + mju_error("Invalid type in VEL stage, sensor %d", i); } } } @@ -537,11 +537,11 @@ void mj_sensorVel(const mjModel* m, mjData* d) { const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage==mjSTAGE_VEL) { if (!plugin->compute) { - mju_error_i("`compute` is null for plugin at slot %d", slot); + mju_error("`compute` is null for plugin at slot %d", slot); } if (subtreeVel == 0) { // compute subtree_linvel, subtree_angmom @@ -724,7 +724,7 @@ void mj_sensorAcc(const mjModel* m, mjData* d) { break; default: - mju_error_i("Invalid type in ACC stage, sensor %d", i); + mju_error("Invalid type in ACC stage, sensor %d", i); } } } @@ -746,11 +746,11 @@ void mj_sensorAcc(const mjModel* m, mjData* d) { const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if ((plugin->capabilityflags & mjPLUGIN_SENSOR) && plugin->needstage==mjSTAGE_ACC) { if (!plugin->compute) { - mju_error_i("`compute` is null for plugin at slot %d", slot); + mju_error("`compute` is null for plugin at slot %d", slot); } if (rnePost == 0) { // compute cacc, cfrc_int, cfrc_ext diff --git a/src/engine/engine_support.c b/src/engine/engine_support.c index 7860e45e..77315a30 100644 --- a/src/engine/engine_support.c +++ b/src/engine/engine_support.c @@ -267,7 +267,7 @@ void mj_jacSparse(const mjModel* m, const mjData* d, // make sure we found it; SHOULD NOT OCCUR if (chain[ci]!=da) { - mju_error_i("dof index %d not found in chain", da); + mju_error("dof index %d not found in chain", da); } // construct rotation jacobian @@ -1083,7 +1083,7 @@ void mj_applyFT(const mjModel* m, mjData* d, // make sure body is in range if (body<0 || body>=m->nbody) { - mju_error_i("Invalid body %d in applyFT", body); + mju_error("Invalid body %d in applyFT", body); } // compute Jacobians @@ -1158,7 +1158,7 @@ void mj_objectVelocity(const mjModel* m, const mjData* d, // object without spatial frame else { - mju_error_i("Invalid object type %d in mj_objectVelocity", objtype); + mju_error("Invalid object type %d in mj_objectVelocity", objtype); } // transform velocity @@ -1211,7 +1211,7 @@ void mj_objectAcceleration(const mjModel* m, const mjData* d, // object without spatial frame else { - mju_error_i("Invalid object type %d in mj_objectAcceleration", objtype); + mju_error("Invalid object type %d in mj_objectAcceleration", objtype); } // transform com-based velocity to local frame @@ -1416,11 +1416,10 @@ void mj_setTotalmass(mjModel* m, mjtNum newmass) { // count warnings, print only the first time void mj_warning(mjData* d, int warning, int info) { - char str[1000]; // check type if (warning<0 || warning>=mjNWARNING) { - mju_error_i("Invalid warning type %d", warning); + mju_error("Invalid warning type %d", warning); } // save info (override previous) @@ -1428,8 +1427,7 @@ void mj_warning(mjData* d, int warning, int info) { // print message only the first time this warning is encountered if (!d->warning[warning].number) { - mjSNPRINTF(str, "%s Time = %.4f.", mju_warningText(warning, info), d->time); - mju_warning(str); + mju_warning("%s Time = %.4f.", mju_warningText(warning, info), d->time); } // increase counter diff --git a/src/engine/engine_util_errmem.c b/src/engine/engine_util_errmem.c index 9ce54358..d8cce6f0 100644 --- a/src/engine/engine_util_errmem.c +++ b/src/engine/engine_util_errmem.c @@ -18,12 +18,14 @@ #include #include #include +#include #include #if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) #include #endif +#include "engine/engine_array_safety.h" #include "engine/engine_macro.h" //------------------------- cross-platform aligned malloc/free ------------------------------------- @@ -122,70 +124,74 @@ void mju_writeLog(const char* type, const char* msg) { // write message to logfile and console, pause and exit -void mju_error(const char* msg) { +void mju_error(const char* msg, ...) { + char errmsg[1000]; + + // Format msg into errmsg + va_list args; + va_start(args, msg); + vsnprintf(errmsg, mjSIZEOFARRAY(errmsg), msg, args); + va_end(args); + if (_mjPRIVATE_tls_error_fn) { - _mjPRIVATE_tls_error_fn(msg); + _mjPRIVATE_tls_error_fn(errmsg); } else if (mju_user_error) { - mju_user_error(msg); + mju_user_error(errmsg); } else { // write to log and console - mju_writeLog("ERROR", msg); - printf("ERROR: %s\n\nPress Enter to exit ...", msg); + mju_writeLog("ERROR", errmsg); + printf("ERROR: %s\n\nPress Enter to exit ...", errmsg); // pause, exit getchar(); - exit(1); + exit(EXIT_FAILURE); } } // write message to logfile and console -void mju_warning(const char* msg) { +void mju_warning(const char* msg, ...) { + char wrnmsg[1000]; + + // Format msg into wrnmsg + va_list args; + va_start(args, msg); + vsnprintf(wrnmsg, mjSIZEOFARRAY(wrnmsg), msg, args); + va_end(args); + if (_mjPRIVATE_tls_warning_fn) { - _mjPRIVATE_tls_warning_fn(msg); + _mjPRIVATE_tls_warning_fn(wrnmsg); } else if (mju_user_warning) { - mju_user_warning(msg); + mju_user_warning(wrnmsg); } else { // write to log file and console - mju_writeLog("WARNING", msg); - printf("WARNING: %s\n\n", msg); + mju_writeLog("WARNING", wrnmsg); + printf("WARNING: %s\n\n", wrnmsg); } } // error with int argument void mju_error_i(const char* msg, int i) { - char errmsg[1000]; - snprintf(errmsg, sizeof(errmsg), msg, i); - errmsg[999] = '\0'; - mju_error(errmsg); + mju_error(msg, i); } // warning with int argument void mju_warning_i(const char* msg, int i) { - char wrnmsg[1000]; - snprintf(wrnmsg, sizeof(wrnmsg), msg, i); - wrnmsg[999] = '\0'; - mju_warning(wrnmsg); + mju_warning(msg, i); } // error string argument void mju_error_s(const char* msg, const char* text) { - char errmsg[1000]; - snprintf(errmsg, sizeof(errmsg), msg, text); - errmsg[999] = '\0'; - mju_error(errmsg); + mju_error(msg, text); } // warning string argument void mju_warning_s(const char* msg, const char* text) { - char wrnmsg[1000]; - snprintf(wrnmsg, sizeof(wrnmsg), msg, text); - wrnmsg[999] = '\0'; - mju_warning(wrnmsg); + mju_warning(msg, text); } diff --git a/src/engine/engine_util_errmem.h b/src/engine/engine_util_errmem.h index 99bcf880..e2e4beb8 100644 --- a/src/engine/engine_util_errmem.h +++ b/src/engine/engine_util_errmem.h @@ -23,6 +23,15 @@ extern "C" { #endif +#ifndef mjPRINTFLIKE + #if defined(__GNUC__) + #define mjPRINTFLIKE(n, m) __attribute__((format(printf, n, m))) + #else + #define mjPRINTFLIKE(n, m) + #endif // __GNUC__ +#endif // mjPRINTFLIKE + + //------------------------------ user handlers ----------------------------------------------------- MJAPI extern void (*mju_user_error)(const char*); @@ -42,12 +51,12 @@ MJAPI void _mjPRIVATE__set_tls_warning_fn(void (*h)(const char*)); //------------------------------ errors and warnings ----------------------------------------------- // errors -MJAPI void mju_error(const char* msg); +MJAPI void mju_error(const char* msg, ...) mjPRINTFLIKE(1, 2); MJAPI void mju_error_i(const char* msg, int i); MJAPI void mju_error_s(const char* msg, const char* text); // warnings -MJAPI void mju_warning(const char* msg); +MJAPI void mju_warning(const char* msg, ...) mjPRINTFLIKE(1, 2); MJAPI void mju_warning_i(const char* msg, int i); MJAPI void mju_warning_s(const char* msg, const char* text); diff --git a/src/engine/engine_util_misc.c b/src/engine/engine_util_misc.c index 60a1e127..656f9bf0 100644 --- a/src/engine/engine_util_misc.c +++ b/src/engine/engine_util_misc.c @@ -286,7 +286,7 @@ mjtNum mju_wrap(mjtNum* wpnt, const mjtNum* x0, const mjtNum* x1, // check object type; SHOULD NOT OCCUR if (type!=mjWRAP_SPHERE && type!=mjWRAP_CYLINDER) { - mju_error_i("mju_wrap: unknown wrapping object type %d", type); + mju_error("mju_wrap: unknown wrapping object type %d", type); } // map sites to wrap object's local frame diff --git a/src/engine/engine_vis_interact.c b/src/engine/engine_vis_interact.c index f4bc276c..0a077541 100644 --- a/src/engine/engine_vis_interact.c +++ b/src/engine/engine_vis_interact.c @@ -295,7 +295,7 @@ static void convert2D(mjtNum* res, int action, mjtNum dx, mjtNum dy, const mjtNu break; default: - mju_error_i("Unexpected mouse action %d in convert2D", action); + mju_error("Unexpected mouse action %d in convert2D", action); } // call 3D converter @@ -347,7 +347,7 @@ void mjv_moveCamera(const mjModel* m, int action, mjtNum reldx, mjtNum reldy, break; default: - mju_error_i("Unexpected action %d in mjv_moveCamera", action); + mju_error("Unexpected action %d in mjv_moveCamera", action); } // clamp camera parameters @@ -434,7 +434,7 @@ void mjv_movePerturb(const mjModel* m, const mjData* d, int action, mjtNum reldx break; default: - mju_error_i("Unexpected mouse action %d in mjv_movePerturb", action); + mju_error("Unexpected mouse action %d in mjv_movePerturb", action); } } @@ -510,7 +510,7 @@ void mjv_moveModel(const mjModel* m, int action, mjtNum reldx, mjtNum reldy, break; default: - mju_error_i("Unexpected action %d in mjv_moveModel", action); + mju_error("Unexpected action %d in mjv_moveModel", action); } } diff --git a/src/engine/engine_vis_visualize.c b/src/engine/engine_vis_visualize.c index d1a71b11..e079b0e8 100644 --- a/src/engine/engine_vis_visualize.c +++ b/src/engine/engine_vis_visualize.c @@ -304,7 +304,7 @@ void mjv_makeConnector(mjvGeom* geom, int type, mjtNum width, if (type!=mjGEOM_CAPSULE && type!=mjGEOM_CYLINDER && type!=mjGEOM_ARROW && type!=mjGEOM_ARROW1 && type!=mjGEOM_ARROW2 && type!=mjGEOM_LINE) { - mju_error_i("Invalid geom type %d for connector", type); + mju_error("Invalid geom type %d for connector", type); } // assign type @@ -770,7 +770,7 @@ void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* vopt, break; default: - mju_error_i("Unknown joint type %d in mjv_visualize", m->jnt_type[i]); + mju_error("Unknown joint type %d in mjv_visualize", m->jnt_type[i]); } f2f(thisgeom->rgba, m->vis.rgba.joint, 4); @@ -2008,7 +2008,7 @@ void mjv_updateScene(const mjModel* m, mjData* d, const mjvOption* opt, const int slot = m->plugin[i]; const mjpPlugin* plugin = mjp_getPluginAtSlotUnsafe(slot, nslot); if (!plugin) { - mju_error_i("invalid plugin slot: %d", slot); + mju_error("invalid plugin slot: %d", slot); } if (plugin->visualize) { plugin->visualize(m, d, scn, i); @@ -2190,4 +2190,3 @@ int mjv_catenary(const mjtNum x0[3], const mjtNum x1[3], const mjtNum gravity[3] return 0; // SHOULD NOT OCCUR } - diff --git a/src/render/glad/glad.c b/src/render/glad/glad.c index 9b2a157a..71028903 100644 --- a/src/render/glad/glad.c +++ b/src/render/glad/glad.c @@ -199,7 +199,7 @@ static int mjGlad_open_gl(void) { handle = dlopen(libname, RTLD_NOW | RTLD_LOCAL); if (!handle) { - mju_error_s("failed to dlopen %s", libname); + mju_error("failed to dlopen %s", libname); } if (platform == mjGL_GLX) { diff --git a/src/render/render_context.c b/src/render/render_context.c index ead72db6..8f2dff12 100644 --- a/src/render/render_context.c +++ b/src/render/render_context.c @@ -212,7 +212,7 @@ void mjr_uploadMesh(const mjModel* m, const mjrContext* con, int meshid) { // check index if (meshid<0 || meshid>=m->nmesh) { - mju_error_i("Invalid mesh index %d", meshid); + mju_error("Invalid mesh index %d", meshid); } // delete old lists (mesh and convex hull) @@ -405,7 +405,7 @@ void mjr_uploadHField(const mjModel* m, const mjrContext* con, int hfieldid) { // check index if (hfieldid<0 || hfieldid>=m->nhfield) { - mju_error_i("Invalid height field index %d", hfieldid); + mju_error("Invalid height field index %d", hfieldid); } // delete old list @@ -1076,7 +1076,7 @@ static void makeShadow(const mjModel* m, mjrContext* con) { // check FBO status GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err!=GL_FRAMEBUFFER_COMPLETE) { - mju_error_i("Shadow framebuffer is not complete, error 0x%x", err); + mju_error("Shadow framebuffer is not complete, error 0x%x", err); } glDisable(GL_TEXTURE_2D); @@ -1137,7 +1137,7 @@ static void makeOff(mjrContext* con) { // check FBO status GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err!=GL_FRAMEBUFFER_COMPLETE) { - mju_error_i("Offscreen framebuffer is not complete, error 0x%x", err); + mju_error("Offscreen framebuffer is not complete, error 0x%x", err); } // get actual number of samples @@ -1175,7 +1175,7 @@ static void makeOff(mjrContext* con) { // check FBO status GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err!=GL_FRAMEBUFFER_COMPLETE) { - mju_error_i("Offscreen framebuffer_r is not complete, error 0x%x", err); + mju_error("Offscreen framebuffer_r is not complete, error 0x%x", err); } } } @@ -1296,7 +1296,7 @@ static void makeFont(mjrContext* con, int fontscale) { static void makeTexture(const mjModel* m, mjrContext* con) { // checks size if (m->ntex>mjMAXTEXTURE) { - mju_error_i("Maximum number of textures is %d", mjMAXTEXTURE); + mju_error("Maximum number of textures is %d", mjMAXTEXTURE); } // save new size @@ -1498,7 +1498,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale, } else if (status==GL_FRAMEBUFFER_UNDEFINED) { con->windowAvailable = 0; } else { - mju_error_i("Default framebuffer is not complete, error 0x%x", status); + mju_error("Default framebuffer is not complete, error 0x%x", status); } } @@ -1601,7 +1601,7 @@ void mjr_makeContext_offSize(const mjModel* m, mjrContext* con, int fontscale, // issue warnings for any OpenGL errors GLenum err; while ((err = glGetError())) { - mju_warning_i("OpenGL error 0x%x in or before mjr_makeContext", err); + mju_warning("OpenGL error 0x%x in or before mjr_makeContext", err); } // set default color pixel format for mjr_readPixels @@ -1706,7 +1706,7 @@ void mjr_addAux(int index, int width, int height, int samples, mjrContext* con) // check FBO status GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err!=GL_FRAMEBUFFER_COMPLETE) { - mju_error_i("Auxiliary framebuffer is not complete, error 0x%x", err); + mju_error("Auxiliary framebuffer is not complete, error 0x%x", err); } // create FBO for resolving @@ -1730,7 +1730,7 @@ void mjr_addAux(int index, int width, int height, int samples, mjrContext* con) // check FBO status err = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (err!=GL_FRAMEBUFFER_COMPLETE) { - mju_error_i("Auxiliary framebuffer resolve is not complete, error 0x%x", err); + mju_error("Auxiliary framebuffer resolve is not complete, error 0x%x", err); } // restore diff --git a/src/render/render_gl2.c b/src/render/render_gl2.c index 7ea8f91b..6e18b886 100644 --- a/src/render/render_gl2.c +++ b/src/render/render_gl2.c @@ -300,7 +300,7 @@ void mjr_setAux(int index, const mjrContext* con) { glReadBuffer(GL_COLOR_ATTACHMENT0); glDrawBuffer(GL_COLOR_ATTACHMENT0); } else { - mju_error_i("auxFBO %d does not exist", index); + mju_error("auxFBO %d does not exist", index); } } diff --git a/src/user/user_composite.cc b/src/user/user_composite.cc index 5f902986..6e5dfd37 100644 --- a/src/user/user_composite.cc +++ b/src/user/user_composite.cc @@ -206,7 +206,7 @@ void mjCComposite::SetDefault(void) { break; default: // SHOULD NOT OCCUR - mju_error_i("Invalid composite type: %d", type); + mju_error("Invalid composite type: %d", type); break; } } @@ -543,7 +543,7 @@ bool mjCComposite::MakeCable(mjCModel* model, mjCBody* body, char* error, int er break; default: // SHOULD NOT OCCUR - mju_error_i("Invalid composite shape: %d", curve[k]); + mju_error("Invalid composite shape: %d", curve[k]); break; } } diff --git a/src/user/user_model.cc b/src/user/user_model.cc index f8bf1ab8..304f0d50 100644 --- a/src/user/user_model.cc +++ b/src/user/user_model.cc @@ -2697,7 +2697,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) { for (int i = 0; i < nplugin; ++i) { const mjpPlugin* plugin = mjp_getPluginAtSlot(m->plugin[i]); if (!plugin->nstate) { - mju_error_i("`nstate` is null for plugin at slot %d", m->plugin[i]); + mju_error("`nstate` is null for plugin at slot %d", m->plugin[i]); } int nstate = plugin->nstate(m, i); m->plugin_stateadr[i] = stateadr; @@ -2706,7 +2706,7 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) { if (plugin->capabilityflags & mjPLUGIN_SENSOR) { for (int sensor_id : plugin_to_sensors[i]) { if (!plugin->nsensordata) { - mju_error_i("`nsensordata` is null for plugin at slot %d", m->plugin[i]); + mju_error("`nsensordata` is null for plugin at slot %d", m->plugin[i]); } int nsensordata = plugin->nsensordata(m, i, sensor_id); sensors[sensor_id]->dim = nsensordata; diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index 9fdfe589..d02042c6 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -3259,18 +3259,12 @@ public static unsafe extern mjuiItem_* mjui_event(mjUI_* ui, mjuiState_* state, [DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] public static unsafe extern void mjui_render(mjUI_* ui, mjuiState_* state, mjrContext_* con); -[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] -public static unsafe extern void mju_error([MarshalAs(UnmanagedType.LPStr)]string msg); - [DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] public static unsafe extern void mju_error_i([MarshalAs(UnmanagedType.LPStr)]string msg, int i); [DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] public static unsafe extern void mju_error_s([MarshalAs(UnmanagedType.LPStr)]string msg, [MarshalAs(UnmanagedType.LPStr)]string text); -[DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] -public static unsafe extern void mju_warning([MarshalAs(UnmanagedType.LPStr)]string msg); - [DllImport("mujoco", CallingConvention = CallingConvention.Cdecl)] public static unsafe extern void mju_warning_i([MarshalAs(UnmanagedType.LPStr)]string msg, int i);