Implement bending forces for interpolated flex shells.

This change adds a new passive force computation for flexes with elastic2d="bend" and dof="trilinear". The bending energy is based on the squared difference of normals between adjacent face elements at their shared edge midpoint. The edge data is precomputed during model compilation and stored in flex_bending.

PiperOrigin-RevId: 910772638
Change-Id: I3b12c7b7f1ba6ac1875df495d89e8cfec921ca80
This commit is contained in:
Alessio Quaglino
2026-05-05 10:32:28 -07:00
committed by Copybara-Service
parent a692283db3
commit d933b195ee
9 changed files with 622 additions and 51 deletions
+28
View File
@@ -116,6 +116,34 @@ MJAPI void mju_flexInterpRotation2D(int order, const mjtNum* xpos_f, int npe,
int axis0, int axis1, int normal_axis,
const mjtNum local[2], mjtNum* quat);
// compute unnormalized surface normal and tangent vectors at a parametric point
// on a 2D face element; normal = t1 x t2 (unnormalized)
MJAPI void mju_flexFaceNormal2D(mjtNum normal[3], mjtNum t1[3], mjtNum t2[3],
int order, const mjtNum* xpos_f,
const mjtNum local[2]);
// 1D shape function: order 1 (linear) or 2 (quadratic), node index i
static inline mjtNum mju_flexPhi(mjtNum s, int i, int order) {
if (order == 1) return i == 0 ? 1 - s : s;
switch (i) {
case 0: return 2*s*s - 3*s + 1;
case 1: return 4*(s - s*s);
case 2: return 2*s*s - s;
default: return 0;
}
}
// 1D shape function gradient
static inline mjtNum mju_flexDphi(mjtNum s, int i, int order) {
if (order == 1) return i == 0 ? -1 : 1;
switch (i) {
case 0: return 4*s - 3;
case 1: return 4*(1 - 2*s);
case 2: return 4*s - 1;
default: return 0;
}
}
// ----------------------------- Base64 ------------------------------------------------------------