diff --git a/doc/_static/example_saved.xml b/doc/_static/example_saved.xml
index 17a40303..fab7d45b 100644
--- a/doc/_static/example_saved.xml
+++ b/doc/_static/example_saved.xml
@@ -1,44 +1,38 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/overview.rst b/doc/overview.rst
index 42732472..bc41c731 100644
--- a/doc/overview.rst
+++ b/doc/overview.rst
@@ -177,14 +177,14 @@ objects and cast shadows, and a floating box with 6 DOFs (this is what the "free
.. code:: xml
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
The built-in OpenGL visualizer renders this model as:
@@ -244,43 +244,46 @@ Next we provide a more elaborate example illustrating several features of MJCF.
.. code:: xml
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
.. raw:: html
diff --git a/model/adhesion/active_adhesion.xml b/model/adhesion/active_adhesion.xml
index b36931e1..1c6d6ce0 100644
--- a/model/adhesion/active_adhesion.xml
+++ b/model/adhesion/active_adhesion.xml
@@ -4,7 +4,7 @@
-->
-
+
diff --git a/model/composite/cloth.xml b/model/composite/cloth.xml
index dca99fcb..d0d1d3e1 100644
--- a/model/composite/cloth.xml
+++ b/model/composite/cloth.xml
@@ -18,7 +18,7 @@
-
+
diff --git a/model/composite/grid2pin.xml b/model/composite/grid2pin.xml
index 65ff1ab3..c9595d23 100644
--- a/model/composite/grid2pin.xml
+++ b/model/composite/grid2pin.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/model/composite/loop.xml b/model/composite/loop.xml
index 2e0bb95d..ba0a5993 100644
--- a/model/composite/loop.xml
+++ b/model/composite/loop.xml
@@ -18,7 +18,7 @@
-
+
diff --git a/model/composite/particle.xml b/model/composite/particle.xml
index 005f89d9..83aef5f0 100644
--- a/model/composite/particle.xml
+++ b/model/composite/particle.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/model/composite/rope.xml b/model/composite/rope.xml
index 659e15b8..50865d76 100644
--- a/model/composite/rope.xml
+++ b/model/composite/rope.xml
@@ -18,7 +18,7 @@
-
+
diff --git a/model/composite/softbox.xml b/model/composite/softbox.xml
index 51d82e03..ab129dfd 100644
--- a/model/composite/softbox.xml
+++ b/model/composite/softbox.xml
@@ -22,7 +22,7 @@
-
+
diff --git a/model/hammock/hammock.xml b/model/hammock/hammock.xml
index 97f9bb2c..28e69ff5 100644
--- a/model/hammock/hammock.xml
+++ b/model/hammock/hammock.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/model/humanoid/22_humanoids.xml b/model/humanoid/22_humanoids.xml
index f5887c0c..c0078d60 100644
--- a/model/humanoid/22_humanoids.xml
+++ b/model/humanoid/22_humanoids.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/model/humanoid100/humanoid100.xml b/model/humanoid100/humanoid100.xml
index 42be52e7..21618bda 100644
--- a/model/humanoid100/humanoid100.xml
+++ b/model/humanoid100/humanoid100.xml
@@ -23,7 +23,7 @@
-
+
diff --git a/model/plugin/cable.xml b/model/plugin/cable.xml
index bcda386e..5edd11cc 100644
--- a/model/plugin/cable.xml
+++ b/model/plugin/cable.xml
@@ -27,7 +27,7 @@
-
+
@@ -53,4 +53,4 @@
-
\ No newline at end of file
+
diff --git a/model/tendon_arm/arm26.xml b/model/tendon_arm/arm26.xml
index 177765f9..0875358a 100644
--- a/model/tendon_arm/arm26.xml
+++ b/model/tendon_arm/arm26.xml
@@ -16,8 +16,6 @@
-
-
diff --git a/simulate/simulate.cc b/simulate/simulate.cc
index 210253fc..326c2798 100644
--- a/simulate/simulate.cc
+++ b/simulate/simulate.cc
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include "glfw_dispatch.h"
#include "uitools.h"
#include "array_safety.h"
@@ -478,7 +479,7 @@ void infotext(mj::Simulate* sim,
// prepare info text
mju::strcpy_arr(title, "Time\nSize\nCPU\nSolver \nFPS\nMemory");
mju::sprintf_arr(content,
- "%-9.3f\n%d (%d con)\n%.3f\n%.1f (%d it)\n%.0f\n%.3f",
+ "%-9.3f\n%d (%d con)\n%.3f\n%.1f (%d it)\n%.0f\n%.2g of %s",
d->time,
d->nefc, d->ncon,
sim->run ?
@@ -486,7 +487,8 @@ void infotext(mj::Simulate* sim,
d->timer[mjTIMER_FORWARD].duration / mjMAX(1, d->timer[mjTIMER_FORWARD].number),
solerr, d->solver_iter,
1/interval,
- d->maxuse_arena/(double)(d->nstack * sizeof(mjtNum)));
+ d->maxuse_arena/(double)(d->nstack * sizeof(mjtNum)),
+ mju_writeNumBytes(d->nstack * sizeof(mjtNum)));
// add Energy if enabled
{
diff --git a/src/user/user_model.cc b/src/user/user_model.cc
index 5ca85d76..231db8fb 100644
--- a/src/user/user_model.cc
+++ b/src/user/user_model.cc
@@ -2689,6 +2689,12 @@ void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
njmax * m->nv * (2 * sizeof(int) + 2 * sizeof(mjtNum)) +
njmax * njmax * (sizeof(int) + sizeof(mjtNum)));
m->nstack += (arena_bytes / sizeof(mjtNum)) + (arena_bytes % sizeof(mjtNum) ? 1 : 0);
+
+ // round up to the nearest megabyte
+ constexpr int kMegabyte = (1 << 20) / sizeof(mjtNum); // number of mjtNum's in 1 Mb
+ int nstack_mb = m->nstack / kMegabyte;
+ int residual_mb = m->nstack % kMegabyte ? 1 : 0;
+ m->nstack = kMegabyte * (nstack_mb + residual_mb);
}
// create data
diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc
index fc4e4531..088bdc2a 100644
--- a/src/xml/xml_native_writer.cc
+++ b/src/xml/xml_native_writer.cc
@@ -847,6 +847,9 @@ void mjXWriter::Size(XMLElement* root) {
WriteAttrInt(section, "nuser_tendon", model->nuser_tendon, 0);
WriteAttrInt(section, "nuser_actuator", model->nuser_actuator, 0);
WriteAttrInt(section, "nuser_sensor", model->nuser_sensor, 0);
+
+ // remove entire section if no attributes
+ if (!section->FirstAttribute()) root->DeleteChild(section);
}
diff --git a/test/engine/testdata/collision_convex/stacked_boxes.xml b/test/engine/testdata/collision_convex/stacked_boxes.xml
index 50bb3f32..affaaa00 100644
--- a/test/engine/testdata/collision_convex/stacked_boxes.xml
+++ b/test/engine/testdata/collision_convex/stacked_boxes.xml
@@ -9,7 +9,7 @@
-
+