Inertia in Robot Simulation — why your model explodes and how to fix it
What the inertia tensor in a URDF actually is, the three failure modes (zero mass, fake values, triangle-inequality violations), and how to get physically correct values from CAD geometry.
Ask why a simulated robot jitters, spins wildly, or launches itself into orbit, and the answer is usually one XML block: <inertial>. It's the least understood part of a robot description because it's invisible — wrong inertia renders perfectly and then destroys the dynamics.
What the numbers mean
Each link's <inertial> block carries three things: mass (kg), the center of mass (the <origin>, in the link frame), and the inertia tensor — six numbers (ixx iyy izz ixy ixz iyz) forming a symmetric 3×3 matrix that describes how the mass is distributed, i.e. how hard the body is to rotate about each axis. Units are kg·m². For intuition: a 1 kg, 10 cm solid cube has ixx = iyy = izz = m·a²/6 = 0.00167 — note how small real values are; if your tensor entries are near 1.0 for a small part, they're almost certainly wrong.
The three failure modes
| Mistake | Symptom | Why |
|---|---|---|
| Zero or missing mass on a jointed link | Link vanishes from physics, or the solver fails | Gazebo silently drops zero-mass links; MuJoCo refuses to compile them |
Copy-pasted "identity-ish" values (ixx=1 iyy=1 izz=1) | Sluggish, wrong dynamics; controllers tuned in sim fail on hardware | Values 100–1000× too large for typical parts — the simulated robot is effectively made of lead flywheels |
Tensor violating the triangle inequality (ixx + iyy ≥ izz and permutations) | Jitter, energy gain, NaN explosions | No physical object can have such a distribution; solvers go unstable rather than erroring |
The URDF validator checks mass positivity and the triangle inequality on every link automatically.
How to get real values
- From CAD (best): your CAD package knows the geometry and material density — SolidWorks/Fusion/Onshape all report mass properties. Or skip the manual step: the STEP → URDF converter integrates mass, center of mass, and the full six-component tensor directly from the tessellated geometry (divergence-theorem integration over the mesh, verified against analytic solutions), at whatever material density you specify. Already have an STL/OBJ mesh but not the original CAD file? The mesh inertia calculator runs the same integration on the mesh directly.
- From primitive formulas (good): for boxes, cylinders, and spheres, textbook formulas are exact — and belong in xacro expressions (
ixx="${m*(3*r*r+h*h)/12}") so they update when dimensions change. - From measurement (for sim-to-real): weigh the real part; find the COM by balancing; refine tensors via system identification if the application demands it.
Two subtleties that bite experts
- The tensor is frame-dependent. URDF expects it about the center of mass, in the inertial frame you declare. CAD tools often report it about the part origin — using that value without the parallel-axis correction is wrong by
m·d². - Off-diagonal terms matter for asymmetric parts. Setting
ixy=ixz=iyz=0is only correct if the frame axes align with the principal axes. Some URDF→MJCF scripts silently drop the off-diagonals; this converter preserves them via MJCF'sfullinertia.
Rule of thumb
If you wouldn't trust the number on a datasheet, don't put it in the robot. Honest inertia from geometry beats precise-looking fiction — it's the difference between a simulation that predicts hardware behavior and one that merely animates it. This is step one of closing the sim-to-real gap.