diff --git a/python/mujoco/bindings_test.py b/python/mujoco/bindings_test.py
index 90ac1302..2d1f9e2f 100644
--- a/python/mujoco/bindings_test.py
+++ b/python/mujoco/bindings_test.py
@@ -632,8 +632,11 @@ class MuJoCoBindingsTest(parameterized.TestCase):
self.assertEqual(self.data.efc_J.shape, (nj,))
self.assertEqual(self.data.efc_KBIP.shape, (nefc, 4))
- expected_error = 'insufficient arena memory available'
- with self.assertRaisesWithLiteralMatch(mujoco.FatalError, expected_error):
+ expected_error = (
+ r'Insufficient arena memory, currently allocated memory=' +
+ r'"[0-9]+[A-Z]?". Increase using .'
+ )
+ with self.assertRaisesRegex(mujoco.FatalError, expected_error):
mujoco._functions._realloc_con_efc(self.data, 100000000, 100000000)
self.assertEmpty(self.data.contact)
self.assertEmpty(self.data.efc_id)
diff --git a/python/mujoco/functions.cc b/python/mujoco/functions.cc
index 78bf94b3..27e5b173 100644
--- a/python/mujoco/functions.cc
+++ b/python/mujoco/functions.cc
@@ -16,6 +16,7 @@
#include
#include
+#include
#include
#include
#include
@@ -264,27 +265,24 @@ PYBIND11_MODULE(_functions, pymodule) {
m, d, x.data(), y.data(), y.rows());
});
DEF_WITH_OMITTED_PY_ARGS(traits::mj_solveM2, "n")(
- pymodule,
- [](const raw::MjModel* m, raw::MjData* d, Eigen::Ref x,
- Eigen::Ref y, Eigen::Ref sqrtInvD) {
+ pymodule, [](const raw::MjModel* m, raw::MjData* d,
+ Eigen::Ref x, Eigen::Ref y,
+ Eigen::Ref sqrtInvD) {
if (x.rows() != y.rows()) {
throw py::type_error(
"the first dimension of x and y should be of the same size");
}
if (x.cols() != m->nv) {
- throw py::type_error(
- "the last dimension of x should be of size nv");
+ throw py::type_error("the last dimension of x should be of size nv");
}
if (y.cols() != m->nv) {
- throw py::type_error(
- "the last dimension of y should be of size nv");
+ throw py::type_error("the last dimension of y should be of size nv");
}
if (sqrtInvD.size() != m->nv) {
- throw py::type_error(
- "the size of sqrtInvD should be nv");
+ throw py::type_error("the size of sqrtInvD should be nv");
}
- return InterceptMjErrors(::mj_solveM2)(
- m, d, x.data(), y.data(), sqrtInvD.data(), y.rows());
+ return InterceptMjErrors(::mj_solveM2)(m, d, x.data(), y.data(),
+ sqrtInvD.data(), y.rows());
});
Def(pymodule);
Def(pymodule);
@@ -1533,6 +1531,11 @@ PYBIND11_MODULE(_functions, pymodule) {
#undef X
};
+ char error_msg[128];
+ error_msg[0] = '\0';
+ const char* error_msg_fmt =
+ "Insufficient arena memory, currently allocated memory=\"%s\". "
+ "Increase using .";
cleanup(data, nJ);
data->ncon = ncon;
data->nefc = nefc;
@@ -1542,7 +1545,9 @@ PYBIND11_MODULE(_functions, pymodule) {
data, ncon * sizeof(raw::MjContact), alignof(raw::MjContact)));
if (!data->contact) {
cleanup(data, nJ);
- throw FatalError("insufficient arena memory available");
+ std::snprintf(error_msg, sizeof(error_msg), error_msg_fmt,
+ mju_writeNumBytes(data->narena));
+ throw FatalError(error_msg);
}
#undef MJ_M
@@ -1553,8 +1558,10 @@ PYBIND11_MODULE(_functions, pymodule) {
data->name = static_cast(InterceptMjErrors(::mj_arenaAllocByte)( \
data, sizeof(type) * (nr) * (nc), alignof(type))); \
if (!data->name) { \
- cleanup(data, nJ); \
- throw FatalError("insufficient arena memory available"); \
+ cleanup(data, nJ); \
+ std::snprintf(error_msg, sizeof(error_msg), error_msg_fmt, \
+ mju_writeNumBytes(data->narena)); \
+ throw FatalError(error_msg); \
}
MJDATA_ARENA_POINTERS_SOLVER