Move SDF precomputation to the mujoco compiler.

Before:
```
 Simulation time      : 2.24 s
 Steps per second     : 4472
 Realtime factor      : 8.94 x
 Time per step        : 223.6 µs

 Newton iters / step  : 2.47
 Contacts / step      : 3.37
 Constraints / step   : 13.49
 Degrees of freedom   : 12
 Dynamic memory usage : 0.2% of 14M
```

After:
```
 Simulation time      : 1.71 s
 Steps per second     : 5854
 Realtime factor      : 11.71 x
 Time per step        : 170.8 µs

 Newton iters / step  : 2.19
 Contacts / step      : 3.45
 Constraints / step   : 13.79
 Degrees of freedom   : 12
 Dynamic memory usage : 0.2% of 14M
```

PiperOrigin-RevId: 781075182
Change-Id: Ie509047ff581ab0df4b10bbd394c27d350ab5a13
This commit is contained in:
Alessio Quaglino
2025-07-09 08:56:20 -07:00
committed by Copybara-Service
parent a3d251f552
commit 96118da08b
10 changed files with 45 additions and 32 deletions
+20
View File
@@ -32,6 +32,7 @@
#include <mujoco/mjspec.h>
#include "user/user_api.h"
#include <TriangleMeshDistance/include/tmd/TriangleMeshDistance.h>
#ifdef MUJOCO_TINYOBJLOADER_IMPL
#define TINYOBJLOADER_IMPLEMENTATION
@@ -1548,6 +1549,25 @@ void mjCMesh::Process() {
}
octree_.SetFace(vert_, face_);
octree_.CreateOctree(aamm);
// compute sdf coefficients
// TODO: only check !plugin.active once sdflib is removed
if (plugin.active && *plugin.name == "sdf") {
tmd::TriangleMeshDistance sdf(vert_.data(), nvert(), face_.data(), nface());
// TODO: do not evaluate the SDF multiple times at the same vertex
// TODO: the value at hanging vertices should be computed from the parent
const double* nodes = octree_.Nodes().data();
for (int i = 0; i < octree_.NumNodes(); ++i) {
for (int j = 0; j < 8; j++) {
mjtNum v[3];
v[0] = nodes[6*i+0] + (j&1 ? 1 : -1) * nodes[6*i+3];
v[1] = nodes[6*i+1] + (j&2 ? 1 : -1) * nodes[6*i+4];
v[2] = nodes[6*i+2] + (j&4 ? 1 : -1) * nodes[6*i+5];
octree_.AddCoeff(sdf.signed_distance(v).distance);
}
}
}
}
// transform CoM to origin
+5
View File
@@ -2997,6 +2997,11 @@ void mjCModel::CopyObjects(mjModel* m) {
memcpy(m->oct_aabb + 6*oct_adr, pme->octree().Nodes().data(), 6*n_oct*sizeof(mjtNum));
memcpy(m->oct_child + 8*oct_adr, pme->octree().Child().data(), 8*n_oct*sizeof(int));
memcpy(m->oct_depth + oct_adr, pme->octree().Level().data(), n_oct*sizeof(int));
if (!pme->octree().Coeff().empty()) {
memcpy(m->oct_coeff + 8*oct_adr, pme->octree().Coeff().data(), 8*n_oct*sizeof(mjtNum));
} else {
mjuu_zerovec(m->oct_coeff + 8*oct_adr, 8*n_oct);
}
}
// advance counters
+3
View File
@@ -222,6 +222,7 @@ struct mjCOctree_ {
std::vector<int> child_; // children of each node (nnode x 8)
std::vector<double> node_; // bounding boxes (nnode x 6)
std::vector<int> level_; // levels of each node (nnode x 1)
std::vector<double> coeff_; // interpo coefficients (nnode x 8)
std::vector<Triangle> face_; // mesh faces (nface x 3)
double ipos_[3] = {0, 0, 0};
double iquat_[4] = {1, 0, 0, 0};
@@ -246,6 +247,8 @@ class mjCOctree : public mjCOctree_ {
level_.clear();
face_.clear();
}
void AddCoeff(double coeff) { coeff_.push_back(coeff); }
const std::vector<double>& Coeff() const { return coeff_; }
private:
void Make(std::vector<Triangle>& elements);