Convert mju_error and mju_warning to variadic functions, supporting printf-like arguments. The functions mju_error_i, mju_error_s, mju_warning_i, and mju_warning_s are now deprecated.

PiperOrigin-RevId: 515431052
Change-Id: I440de0cb417ce216b6d636a5d86dc9ef6cc1fc06
This commit is contained in:
Kyle Bayes
2023-03-09 13:50:39 -08:00
committed by Copybara-Service
parent 2e6a37e8c5
commit d3d789cf7d
33 changed files with 177 additions and 184 deletions
+4 -4
View File
@@ -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:
+2
View File
@@ -16,6 +16,8 @@ General
For instance, the constraint Jacobian matrix from the `humanoid100.xml
<https://github.com/deepmind/mujoco/blob/main/model/humanoid100/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.
+2 -2
View File
@@ -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);
+5 -8
View File
@@ -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.
translation in front of rotation, which is our convention for local and global coordinates.
+14 -6
View File
@@ -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.
+4 -4
View File
@@ -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(
@@ -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 = []
+1 -1
View File
@@ -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
+7 -7
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -766,7 +766,7 @@ void mj_collideGeoms(const mjModel* m, mjData* d, int g1, int g2, int flg_user,
for (i=0; i<num; i++) {
// set contact data
if (condim > 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;
+9 -32
View File
@@ -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
+5 -5
View File
@@ -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
}
}
+5 -5
View File
@@ -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;
+4 -4
View File
@@ -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);
+10 -12
View File
@@ -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 {
+2 -2
View File
@@ -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);
}
+3 -3
View File
@@ -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;
+6 -6
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
}
+12 -12
View File
@@ -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
+6 -8
View File
@@ -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
+33 -27
View File
@@ -18,12 +18,14 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include <unistd.h>
#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);
}
+11 -2
View File
@@ -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);
+1 -1
View File
@@ -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
+4 -4
View File
@@ -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);
}
}
+3 -4
View File
@@ -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
}
+1 -1
View File
@@ -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) {
+10 -10
View File
@@ -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
+1 -1
View File
@@ -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);
}
}
+2 -2
View File
@@ -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;
}
}
+2 -2
View File
@@ -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;
-6
View File
@@ -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);