Support pinned flex vertices with bending

The flexcomp compiler previously rejected pins on dim-2 flexes with
bending (elastic2d bend/both). Allow them: mj_flexPassiveBend treats a
pinned vertex (body without 3 free slide dofs) as static -- zero
velocity, and no bending force applied to it (the reaction is carried
by the pin) -- while its position still enters every neighbor's
bending force, which is exactly what the pin constrains.

PiperOrigin-RevId: 944410969
Change-Id: Ib0a69c8d5fb6f64d3e2a76af3b6b2c7be1898191
This commit is contained in:
Alessio Quaglino
2026-07-08 04:01:51 -07:00
committed by Copybara-Service
parent c4c2cad503
commit fb6d1cf18f
4 changed files with 107 additions and 11 deletions
+14 -8
View File
@@ -481,10 +481,14 @@ static void mj_flexPassiveBend(const mjModel* m, mjData* d, int f,
frc[0][1] = -(frc[1][1] + frc[2][1] + frc[3][1]);
frc[0][2] = -(frc[1][2] + frc[2][2] + frc[3][2]);
// velocities
mjtNum* vel[4];
// a pinned vertex is welded to a static (jointless) parent body: its bending reaction is
// absorbed by the pin, so its velocity is zero and (below) no force is applied to it.
static const mjtNum zero3[3] = {0, 0, 0};
const mjtNum* vel[4]; int isfree[4];
for (int i = 0; i < 4; i++) {
vel[i] = d->qvel + m->body_dofadr[bodyid[v[i]]];
int bid = bodyid[v[i]];
isfree[i] = (m->body_dofnum[bid] == 3);
vel[i] = isfree[i] ? (d->qvel + m->body_dofadr[bid]) : zero3;
}
// force
@@ -506,12 +510,14 @@ static void mj_flexPassiveBend(const mjModel* m, mjData* d, int f,
}
}
// insert into global force
// insert into global force (free flex vertices only: 3 translational dofs, no moment arm).
// A pinned vertex has no free flex dof -- its bending reaction is carried by the pin -- so it
// is skipped (its POSITION still enters every neighbor's force via the xpos sum above,
// which is what the pin constrains).
for (int i = 0; i < 4; i++) {
int bid = bodyid[v[i]];
int body_dofnum = m->body_dofnum[bid];
int body_dofadr = m->body_dofadr[bid];
for (int x = 0; x < body_dofnum; x++) {
if (!isfree[i]) continue;
int body_dofadr = m->body_dofadr[bodyid[v[i]]];
for (int x = 0; x < 3; x++) {
if (enbl_spring) d->qfrc_spring[body_dofadr+x] -= spring[3*i+x];
if (enbl_damper) d->qfrc_damper[body_dofadr+x] -= damper[3*i+x] * m->flex_damping[f];
}