Remove plugin support from Composite particles.

This functionality is replaced by FlexComp.

PiperOrigin-RevId: 672503965
Change-Id: I58953267de285f82e416f9f60576a336b7d0da4c
This commit is contained in:
Alessio Quaglino
2024-09-09 04:57:34 -07:00
committed by Copybara-Service
parent 44145742a7
commit 4862b9e765
18 changed files with 39 additions and 1963 deletions
+11 -201
View File
@@ -301,6 +301,17 @@ bool mjCComposite::Make(mjSpec* spec, mjsBody* body, char* error, int error_sz)
}
}
// check plugin compatibility
// TODO: move mujoco.elasticity.cable to the engine
if (plugin.active) {
if (type != mjCOMPTYPE_CABLE) {
return comperr(error, "Only cable composite supports plugins", error_sz);
}
if (plugin_name != "mujoco.elasticity.cable") {
return comperr(error, "Only mujoco.elasticity.cable is supported by composites", error_sz);
}
}
// overwrite plugin name
if (plugin_instance_name.empty() && plugin.active) {
plugin_instance_name = "composite" + prefix;
@@ -372,93 +383,6 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
}
}
// create faces
if (userface.empty()) {
if (dim == 3) {
int cube2tets[6][4] = {{0, 3, 1, 7}, {0, 1, 4, 7},
{1, 3, 2, 7}, {1, 2, 6, 7},
{1, 5, 4, 7}, {1, 6, 5, 7}};
for (int ix = 0; ix < count[0]-1; ix++) {
for (int iy = 0; iy < count[1]-1; iy++) {
for (int iz = 0; iz < count[2]-1; iz++) {
int vert[8] = {
count[2]*count[1]*(ix+0) + count[2]*(iy+0) + iz+0,
count[2]*count[1]*(ix+1) + count[2]*(iy+0) + iz+0,
count[2]*count[1]*(ix+1) + count[2]*(iy+1) + iz+0,
count[2]*count[1]*(ix+0) + count[2]*(iy+1) + iz+0,
count[2]*count[1]*(ix+0) + count[2]*(iy+0) + iz+1,
count[2]*count[1]*(ix+1) + count[2]*(iy+0) + iz+1,
count[2]*count[1]*(ix+1) + count[2]*(iy+1) + iz+1,
count[2]*count[1]*(ix+0) + count[2]*(iy+1) + iz+1,
};
for (int s = 0; s < 6; s++) {
for (int v = 0; v < 4; v++) {
face.push_back(vert[cube2tets[s][v]]);
}
}
}
}
}
} else if (dim == 2) {
int quad2tri[2][3] = {{0, 1, 2}, {0, 2, 3}};
for (int ix = 0; ix < count[0]-1; ix++) {
for (int iy = 0; iy < count[1]-1; iy++) {
int vert[4] = {
count[2]*count[1]*(ix+0) + count[2]*(iy+0),
count[2]*count[1]*(ix+1) + count[2]*(iy+0),
count[2]*count[1]*(ix+1) + count[2]*(iy+1),
count[2]*count[1]*(ix+0) + count[2]*(iy+1),
};
for (int s = 0; s < 2; s++) {
for (int v = 0; v < 3; v++) {
face.push_back(vert[quad2tri[s][v]]);
}
}
}
}
}
userface = VectorToString(face);
} else {
dim = 2; // can only load a surface for now
face = StringToVector<int>(userface);
for (int i=0; i<face.size(); face[i++]--) {};
userface = VectorToString(face);
}
// compute volume
std::vector<double> volume(uservert.size()/3);
double thickness = 1;
if (dim == 2 && plugin.active) {
try {
mjCPlugin* pplugin = static_cast<mjCPlugin*>(plugin.instance);
thickness = std::stod(pplugin->config_attribs["thickness"], nullptr);
} catch (const std::invalid_argument& e) {
return comperr(error, "Invalid thickness attribute", error_sz);
}
}
if (!userface.empty()) {
face = StringToVector<int>(userface);
for (int j=0; j<face.size()/3; j++) {
double area[3];
double edge1[3];
double edge2[3];
for (int i=0; i<3; i++) {
edge1[i] = uservert[3*face[3*j+1]+i] - uservert[3*face[3*j]+i];
edge2[i] = uservert[3*face[3*j+2]+i] - uservert[3*face[3*j]+i];
}
mjuu_crossvec(area, edge1, edge2);
for (int i=0; i<3; i++) {
volume[face[3*j+i]] += sqrt(mjuu_dot3(area, area)) / 2 * thickness;
}
}
} else {
for (int i=0; i<uservert.size()/3; i++) {
volume[i] = 6 * spacing * spacing / 2 * thickness;
}
}
// create bodies and geoms
for (int i=0; i<uservert.size()/3; i++) {
// create body
@@ -506,83 +430,6 @@ bool mjCComposite::MakeParticle(mjCModel* model, mjsBody* body, char* error, int
s->type = mjGEOM_SPHERE;
mju::sprintf_arr(txt, "%sS%d", prefix.c_str(), i);
mjs_setString(s->name, txt);
// add plugin
if (plugin.active) {
mjsPlugin* pplugin = &b->plugin;
mjCPlugin* cplugin = static_cast<mjCPlugin*>(plugin.instance);
pplugin->active = true;
pplugin->instance = plugin.instance;
mjs_setString(pplugin->instance_name, plugin_instance_name.c_str());
mjs_setString(pplugin->name, mjs_getString(plugin.name));
if (i==0 && !cplugin->config_attribs["face"].empty()) {
return comperr(error, "Face attribute already exists in plugin", error_sz);
}
cplugin->config_attribs["face"] = userface;
cplugin->config_attribs["edge"] = "";
// update density
if (dim == 2) {
g->density *= volume[i] / (4./3. * mjPI * pow(g->size[0], 3));
}
}
}
// add isometry constraints
if (dim==2) {
char txt0[100], txt1[100], txt2[100];
std::vector<std::pair<int, int>> edge;
// create edges
for (int i=0; i<face.size()/3; i++) {
for (int j=0; j<3; j++) {
int v0 = face[3*i+(j+0)%3];
int v1 = face[3*i+(j+1)%3];
edge.push_back(v0 < v1 ? std::pair(v0, v1) : std::pair(v1, v0));
}
}
std::sort(edge.begin(), edge.end());
auto last = std::unique(edge.begin(), edge.end());
edge.erase(last, edge.end());
// create constraints
for (int i=0; i<edge.size(); i++) {
int v0 = edge[i].first;
int v1 = edge[i].second;
mju::sprintf_arr(txt0, "%sT%d_%d", prefix.c_str(), v0, v1);
mju::sprintf_arr(txt1, "%sS%d", prefix.c_str(), v0);
mju::sprintf_arr(txt2, "%sS%d", prefix.c_str(), v1);
// create tendon
mjsTendon* ten = mjs_addTendon(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjs_setDefault(ten->element, &model->Default()->spec);
mjs_setString(ten->name, txt0);
ten->group = 4;
mjs_wrapSite(ten, txt1);
mjs_wrapSite(ten, txt2);
// add equality constraint
mjsEquality* eq = mjs_addEquality(&model->spec, &def[mjCOMPKIND_TENDON].spec);
mjs_setDefault(eq->element, &model->Default()->spec);
eq->type = mjEQ_TENDON;
mjs_setString(eq->name1, mjs_getString(ten->name));
}
}
if (skin && dim==3) {
MakeSkin3(model);
}
if (skin && dim==2) {
if (skinsubgrid>0) {
MakeSkin2Subgrid(model, skininflate);
} else {
MakeSkin2(model, skininflate);
}
}
return true;
@@ -1303,43 +1150,6 @@ void mjCComposite::MakeSkin2(mjCModel* model, mjtNum inflate) {
skin->inflate = inflate;
skin->group = skingroup;
// copy skin from existing mesh
if (type==mjCOMPTYPE_PARTICLE && username.empty()) {
std::vector<int> skinface;
skinface = StringToVector<int>(userface);
int nvert = uservert.size()/3;
for (int j=0; j<2; j++) {
for (int i=0; i<nvert; i++) {
vert.push_back(0);
vert.push_back(0);
vert.push_back(0);
mju::sprintf_arr(txt, "%sB%d", prefix.c_str(), i);
mjs_appendString(skin->bodyname, txt);
bindpos.push_back(0);
bindpos.push_back(0);
bindpos.push_back(0);
bindquat.push_back(1);
bindquat.push_back(0);
bindquat.push_back(0);
bindquat.push_back(0);
vertid.push_back({j*nvert+i});
vertweight.push_back({1});
}
for (int i=0; i<skinface.size()/3; i++) {
face.push_back(j*nvert+skinface[3*i]);
face.push_back(j*nvert+skinface[3*i+(j==0 ? 1 : 2)]);
face.push_back(j*nvert+skinface[3*i+(j==0 ? 2 : 1)]);
}
}
CopyIntoSkin(skin);
return;
}
// populate mesh: two sides
for (int i=0; i<2; i++) {
for (int ix=0; ix<count[0]; ix++) {
-1
View File
@@ -106,7 +106,6 @@ class mjCComposite {
// currently used only for cable
std::string initial; // root boundary type
std::vector<float> uservert; // user-specified vertex positions
std::string userface; // connectivity
double size[3]; // rope size (meaning depends on the shape)
mjtCompShape curve[3]; // geometric shape
+2 -5
View File
@@ -296,8 +296,8 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"<"},
{"config", "*", "2", "key", "value"},
{">"},
{"composite", "*", "13", "prefix", "type", "count", "spacing", "offset",
"flatinertia", "solrefsmooth", "solimpsmooth", "vertex", "face",
{"composite", "*", "12", "prefix", "type", "count", "spacing", "offset",
"flatinertia", "solrefsmooth", "solimpsmooth", "vertex",
"initial", "curve", "size"},
{"<"},
{"joint", "*", "17", "kind", "group", "stiffness", "damping", "armature",
@@ -2371,9 +2371,6 @@ void mjXReader::OneComposite(XMLElement* elem, mjsBody* body, mjsDefault* def) {
comp.uservert = std::move(uservert.value());
}
// shell
ReadAttrTxt(elem, "face", comp.userface);
// process curve string
std::istringstream iss(curves);
int i = 0;