compas-dev / compas-dev/compas_fab
tensors in the bundled robot library are not physically realisable (MuJoCo refuses to load them)
- Dominant language
- Python
- Stars
- 137
- Forks
- 47
- PR merge metrics
- No merged PRs in 30d
Description
The `` blocks in two of the bundled robot descriptions describe bodies
that cannot exist. This is not a precision complaint -- the tensors are
rejected outright by physics engines that validate them, and silently discarded
by ones that do not.
## What is wrong
A rigid body's inertia tensor must be symmetric **positive definite**, and its
eigenvalues (the principal moments) must additionally satisfy the triangle
inequality `J_a + J_b >= J_c`. The second condition follows from each principal
moment being an integral of a sum of two squared coordinates, so no arrangement
of matter can violate it. A tensor can be positive definite and still describe
no body.
Both files fail:
| file | tensors | invalid |
|---|---|---|
| `abb_irb4600_40_255/urdf/robot_description.urdf` | 7 | **7** |
| `rfl/urdf/robot_description.urdf` | 38 | **38** |
Per link in the ABB file, eigenvalues computed with `numpy.linalg.eigvalsh`:
| link | principal moments | fails |
|---|---|---|
| `base_link` (L20) | `[-6.0413, -5.9520, +1.8893]` | not positive definite |
| `link_1` (L40) | `[-6.0413, -5.9520, +1.8893]` | not positive definite |
| `link_2` (L60) | `[-20.3664, -18.8855, +2.6159]` | not positive definite |
| `link_3` (L80) | `[+1.2497, +2.5280, +4.9783]` | positive definite, **triangle short by 24.1%** |
| `link_4` (L100) | `[-8.0000, -8.0000, +0.4820]` | not positive definite |
| `link_5` (L120) | `[-0.0090, -0.0040, +0.0400]` | not positive definite |
| `link_6` (L140) | `[-0.3293, -0.3264, +0.0251]` | not positive definite |
## It is one defect, copy-pasted
The 45 bad tensors are only **6 distinct values**. In `rfl`, the single block
```xml
```
appears **18 times**, plus twice more in the ABB file -- 20 links sharing one
tensor. The remaining five values appear 4 times each. So this is one bad
inertial block propagated across the library, not 45 independent mistakes.
Two other signs that the whole block is placeholder data rather than CAD output:
`base_link`, `link_1`, `link_2` and `link_3` all declare **exactly 120.0 kg**,
and several inertial origins are round numbers far from the link's actual
geometry (`link_4` declares `xyz="0 0 1"` while its own collision mesh has its
centroid at `[0.654, 0.001, -0.001]`).
## Measured consequence
MuJoCo 3.11.0, loading the ABB file as shipped (`package://` resolved locally so
the meshes are found):
```
Error: error 'inertia must have positive eigenvalues' in fullinertia
```
The model does not load at all. PyBullet takes the other path -- it accepts the
file and silently zeroes the offending tensors, so a pipeline built on it runs
for years with massless links and never reports anything.
I appreciate compas_fab is a planning library and these values may simply never
be read on your own code paths. The reason it is still worth fixing is that the
bundled URDFs get handed to other tools, and in the strict half of them the
robot does not load.
## Proposed correction
Since the values are placeholders, there is no CAD ground truth to restore. But
the repo already ships the geometry, so a physically valid tensor can be derived
from **each link's own collision mesh at its own declared mass**, assuming
uniform density:
| link | principal moments (mesh-derived) | valid |
|---|---|---|
| `base_link` | `[1.9529, 4.0144, 5.2338]` | yes |
| `link_1` | `[3.2677, 4.0876, 5.0694]` | yes |
| `link_2` | `[0.8133, 14.4835, 14.8137]` | yes |
| `link_3` | `[3.5073, 4.4812, 5.1427]` | yes |
| `link_4` | `[0.1924, 3.7274, 3.7654]` | yes |
| `link_5` | `[0.0299, 0.0299, 0.0313]` | yes |
| `link_6` | `[0.0052, 0.0052, 0.0074]` | yes |
The inertial origins are set to the same meshes' centroids, since leaving the
declared origins in place would put physically valid tensors at positions the
geometry contradicts.
**Verified after patching:** MuJoCo loads the model (`nbody=7`, total mass
415 kg -- 535 kg declared, less the 120 kg base that becomes the world body) and
runs 500 steps with all state finite.
**Honest limits of this fix.** Uniform density is an approximation: a real
IRB4600 concentrates mass in the joint motors and gearboxes, so these numbers
are not what ABB's CAD would give. They are *physically realisable* values
consistent with the geometry and masses the repo already declares, which the
current ones are not. If you have access to real values, those should win. The
integrity tool used here is a straightforward signed-tetrahedron mesh
integration, self-tested against a closed box's analytic `m*(y^2+z^2)/12` to
2.8e-17.
The patch below covers the ABB file only. `rfl` needs the same treatment; I held
off because its links are assembled differently and I did not want to guess at
which meshes back which links -- happy to do it if the approach looks right to
you.
Patch for abb_irb4600_40_255 (git apply-able, 14 lines changed)
```diff
--- a/src/compas_fab/data/robot_library/abb_irb4600_40_255/urdf/robot_description.urdf
+++ b/src/compas_fab/data/robot_library/abb_irb4600_40_255/urdf/robot_description.urdf
@@ -15,9 +15,9 @@
-
+
-
+
@@ -35,9 +35,9 @@
-
+
-
+
@@ -55,9 +55,9 @@
-
+
-
+
@@ -75,9 +75,9 @@
-
+
-
+
@@ -95,9 +95,9 @@
-
+
-
+
@@ -115,9 +115,9 @@
-
+
-
+
@@ -135,9 +135,9 @@
-
+
-
+
```
Contributor guide
Assessment
This issue has not been assessed yet.