Add fields for flex collisions in threaded narrowphase.
PiperOrigin-RevId: 949651632 Change-Id: I09dfa85eb57b9c3a97850c35f51d1d2872852704
This commit is contained in:
committed by
Copybara-Service
parent
135b482c9d
commit
e3293a5f29
@@ -352,11 +352,36 @@ int mj_isElemActive(const mjModel* m, int f, int e) {
|
|||||||
|
|
||||||
// internal structure for storing pairs meant for narrowphase collision detection
|
// internal structure for storing pairs meant for narrowphase collision detection
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int g1;
|
// type of collision pair
|
||||||
int g2;
|
enum {
|
||||||
int ipair;
|
mjCPAIR_GEOM_GEOM = 0,
|
||||||
|
mjCPAIR_GEOM_FLEX,
|
||||||
|
mjCPAIR_GEOM_ELEM,
|
||||||
|
mjCPAIR_ELEM_VERT,
|
||||||
|
mjCPAIR_ELEM_ELEM,
|
||||||
|
} type;
|
||||||
|
int conpos;
|
||||||
|
union {
|
||||||
|
struct { int g1, g2, ipair; } geom_geom;
|
||||||
|
struct { int g, f; } geom_flex;
|
||||||
|
struct { int g, f, e; } geom_elem;
|
||||||
|
struct { int f, e, v; } elem_vert;
|
||||||
|
struct { int f1, e1, f2, e2; } elem_elem;
|
||||||
|
};
|
||||||
} mjcPair;
|
} mjcPair;
|
||||||
|
|
||||||
|
|
||||||
|
// initialize a default collision pair
|
||||||
|
static inline void defaultPair(mjcPair* pair, int type) {
|
||||||
|
pair->type = type;
|
||||||
|
// clear all fields in the union
|
||||||
|
pair->elem_elem.f1 = -1;
|
||||||
|
pair->elem_elem.e1 = -1;
|
||||||
|
pair->elem_elem.f2 = -1;
|
||||||
|
pair->elem_elem.e2 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// binary search between two bodyflex trees
|
// binary search between two bodyflex trees
|
||||||
static void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
static void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
||||||
int merged, int startadr, int pairadr);
|
int merged, int startadr, int pairadr);
|
||||||
@@ -486,21 +511,30 @@ static void filterFlexContacts(mjData* d, int ncon_before) {
|
|||||||
|
|
||||||
|
|
||||||
// push a candidate collision pair onto the arena
|
// push a candidate collision pair onto the arena
|
||||||
static void pushPairArena(const mjModel* m, mjData* d, int g1, int g2, int ipair) {
|
static void pushPairArena(mjData* d, mjcPair* pair) {
|
||||||
// allocate geom pair on the arena
|
// allocate geom pair on the arena
|
||||||
mjcPair* pair = (mjcPair*) mj_arenaAllocByte(d, sizeof(mjcPair), _Alignof(mjcPair));
|
mjcPair* new_pair = (mjcPair*) mj_arenaAllocByte(d, sizeof(mjcPair), _Alignof(mjcPair));
|
||||||
if (!pair) {
|
if (!pair) {
|
||||||
mjERROR("arena too small to allocate geom pair");
|
mjERROR("arena too small to allocate geom pair");
|
||||||
}
|
}
|
||||||
|
*new_pair = *pair;
|
||||||
|
}
|
||||||
|
|
||||||
if (g1 >= 0 && g2 >= 0 && m->geom_type[g1] > m->geom_type[g2]) {
|
|
||||||
pair->g1 = g2;
|
// push a geom-geom collision pair onto the arena
|
||||||
pair->g2 = g1;
|
static void pushGeomGeom(const mjModel* m, mjData* d, int g1, int g2, int ipair) {
|
||||||
} else {
|
if (m->geom_type[g1] > m->geom_type[g2]) {
|
||||||
pair->g1 = g1;
|
int tmp = g1;
|
||||||
pair->g2 = g2;
|
g1 = g2;
|
||||||
|
g2 = tmp;
|
||||||
}
|
}
|
||||||
pair->ipair = ipair;
|
|
||||||
|
mjcPair pair;
|
||||||
|
defaultPair(&pair, mjCPAIR_GEOM_GEOM);
|
||||||
|
pair.geom_geom.g1 = g1;
|
||||||
|
pair.geom_geom.g2 = g2;
|
||||||
|
pair.geom_geom.ipair = ipair;
|
||||||
|
pushPairArena(d, &pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -616,7 +650,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
merged = (m->pair_signature[pairadr] == signature);
|
merged = (m->pair_signature[pairadr] == signature);
|
||||||
g1 = m->pair_geom1[pairadr], g2 = m->pair_geom2[pairadr];
|
g1 = m->pair_geom1[pairadr], g2 = m->pair_geom2[pairadr];
|
||||||
if (filterCollisionPair(m, d, g1, g2, pairadr, 0, 0, 0)) {
|
if (filterCollisionPair(m, d, g1, g2, pairadr, 0, 0, 0)) {
|
||||||
pushPairArena(m, d, g1, g2, pairadr);
|
pushGeomGeom(m, d, g1, g2, pairadr);
|
||||||
ngeompair++;
|
ngeompair++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,7 +685,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
// process bodyflex pair: two single-geom bodies
|
// process bodyflex pair: two single-geom bodies
|
||||||
if (isbody1 && isbody2 && m->body_geomnum[bf1] == 1 && m->body_geomnum[bf2] == 1) {
|
if (isbody1 && isbody2 && m->body_geomnum[bf1] == 1 && m->body_geomnum[bf2] == 1) {
|
||||||
if (filterCollisionPair(m, d, geomadr1, geomadr2, -1, merged, startadr, pairadr)) {
|
if (filterCollisionPair(m, d, geomadr1, geomadr2, -1, merged, startadr, pairadr)) {
|
||||||
pushPairArena(m, d, geomadr1, geomadr2, -1);
|
pushGeomGeom(m, d, geomadr1, geomadr2, -1);
|
||||||
ngeompair++;
|
ngeompair++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -697,7 +731,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
for (g1=geomadr1; g1 < geomadr_end1; g1++) {
|
for (g1=geomadr1; g1 < geomadr_end1; g1++) {
|
||||||
for (g2=geomadr2; g2 < geomadr_end2; g2++) {
|
for (g2=geomadr2; g2 < geomadr_end2; g2++) {
|
||||||
if (filterCollisionPair(m, d, g1, g2, -1, merged, startadr, pairadr)) {
|
if (filterCollisionPair(m, d, g1, g2, -1, merged, startadr, pairadr)) {
|
||||||
pushPairArena(m, d, g1, g2, -1);
|
pushGeomGeom(m, d, g1, g2, -1);
|
||||||
ngeompair++;
|
ngeompair++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -780,7 +814,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
for (; pairadr < npair; pairadr++) {
|
for (; pairadr < npair; pairadr++) {
|
||||||
g1 = m->pair_geom1[pairadr], g2 = m->pair_geom2[pairadr];
|
g1 = m->pair_geom1[pairadr], g2 = m->pair_geom2[pairadr];
|
||||||
if (filterCollisionPair(m, d, g1, g2, pairadr, 0, 0, 0)) {
|
if (filterCollisionPair(m, d, g1, g2, pairadr, 0, 0, 0)) {
|
||||||
pushPairArena(m, d, g1, g2, pairadr);
|
pushGeomGeom(m, d, g1, g2, pairadr);
|
||||||
ngeompair++;
|
ngeompair++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1048,9 +1082,9 @@ static void mj_collideTree(const mjModel* m, mjData* d, int bf1, int bf2,
|
|||||||
n2 = nodeid1;
|
n2 = nodeid1;
|
||||||
}
|
}
|
||||||
mjcPair pair;
|
mjcPair pair;
|
||||||
pair.g1 = n1;
|
defaultPair(&pair, mjCPAIR_GEOM_GEOM);
|
||||||
pair.g2 = n2;
|
pair.geom_geom.g1 = n1;
|
||||||
pair.ipair = -1;
|
pair.geom_geom.g2 = n2;
|
||||||
mj_narrowphase(m, d, &pair, 1, 0);
|
mj_narrowphase(m, d, &pair, 1, 0);
|
||||||
}
|
}
|
||||||
if (mark_active) {
|
if (mark_active) {
|
||||||
@@ -1833,16 +1867,23 @@ static void mj_makeCapsule(const mjModel* m, mjData* d, int f, const int vid[2],
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// struct holding extra data for a flex precontact
|
||||||
|
typedef struct {
|
||||||
|
int elem[2];
|
||||||
|
int vert[2];
|
||||||
|
} mjPreFlex;
|
||||||
|
|
||||||
// struct for collision task
|
// struct for collision task
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mjPreContact* conbuffer; // pre-contact buffer returned by collision functions
|
mjPreContact* conbuffer; // pre-contact buffer returned by collision functions
|
||||||
int* nconbuffer; // contact count for each collision pair
|
mjPreFlex* flexbuffer; // pre-flex buffer returned by collision functions
|
||||||
char* epabuffer; // buffer for nativeccd
|
int* nconbuffer; // contact count for each collision pair
|
||||||
int ccd_size; // size of nativeccd buffer
|
char* epabuffer; // buffer for nativeccd
|
||||||
const int* pairbuffer; // collision pairs (g1, g2, ipair, index into conbuffer)
|
int ccd_size; // size of nativeccd buffer
|
||||||
int npair; // number of collision pairs
|
const mjcPair* pairbuffer; // collision pairs
|
||||||
int chunksize; // number of pairs to process per task
|
int npair; // number of collision pairs
|
||||||
int maxcon; // maximum number of contacts (size of conbuffer)
|
int chunksize; // number of pairs to process per task
|
||||||
|
int maxcon; // maximum number of contacts (size of conbuffer)
|
||||||
} mjContactArg;
|
} mjContactArg;
|
||||||
|
|
||||||
|
|
||||||
@@ -1852,7 +1893,7 @@ static void collisionTask(const mjModel* m, mjData* d, void* arg, int thread_id,
|
|||||||
char* epabuffer = conargs->epabuffer;
|
char* epabuffer = conargs->epabuffer;
|
||||||
int chunksize = conargs->chunksize;
|
int chunksize = conargs->chunksize;
|
||||||
int globalidx = chunksize * idx;
|
int globalidx = chunksize * idx;
|
||||||
const int* pair = conargs->pairbuffer + 4 * globalidx;
|
const mjcPair* pair = conargs->pairbuffer + globalidx;
|
||||||
int* ncon = conargs->nconbuffer + chunksize * idx;
|
int* ncon = conargs->nconbuffer + chunksize * idx;
|
||||||
|
|
||||||
int npair = conargs->npair;
|
int npair = conargs->npair;
|
||||||
@@ -1860,10 +1901,10 @@ static void collisionTask(const mjModel* m, mjData* d, void* arg, int thread_id,
|
|||||||
|
|
||||||
mjc_setCCDBuffer(epabuffer + thread_id * conargs->ccd_size);
|
mjc_setCCDBuffer(epabuffer + thread_id * conargs->ccd_size);
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
int g1 = pair[4*i + 0];
|
int g1 = pair[i].geom_geom.g1;
|
||||||
int g2 = pair[4*i + 1];
|
int g2 = pair[i].geom_geom.g2;
|
||||||
int ipair = pair[4*i + 2];
|
int ipair = pair[i].geom_geom.ipair;
|
||||||
int conpos = pair[4*i + 3];
|
int conpos = pair[i].conpos;
|
||||||
|
|
||||||
mjfCollision collision_func = mjCOLLISIONFUNC[m->geom_type[g1]][m->geom_type[g2]];
|
mjfCollision collision_func = mjCOLLISIONFUNC[m->geom_type[g1]][m->geom_type[g2]];
|
||||||
mjtNum margin = getMargin(m, g1, g2, ipair);
|
mjtNum margin = getMargin(m, g1, g2, ipair);
|
||||||
@@ -1871,7 +1912,7 @@ static void collisionTask(const mjModel* m, mjData* d, void* arg, int thread_id,
|
|||||||
ncon[i] = collision_func(m, d, conbuffer + conpos, g1, g2, margin + gap);
|
ncon[i] = collision_func(m, d, conbuffer + conpos, g1, g2, margin + gap);
|
||||||
|
|
||||||
// SHOULD NOT OCCUR
|
// SHOULD NOT OCCUR
|
||||||
int expected_max = (globalidx + i + 1 < npair ? pair[4*(i+1) + 3] : conargs->maxcon) - conpos;
|
int expected_max = (globalidx + i + 1 < npair ? pair[i+1].conpos : conargs->maxcon) - conpos;
|
||||||
if (ncon[i] > expected_max) {
|
if (ncon[i] > expected_max) {
|
||||||
mjERROR("collision function returned %d contacts for geom pair (%d, %d), "
|
mjERROR("collision function returned %d contacts for geom pair (%d, %d), "
|
||||||
"expected at most %d from mj_maxContact", ncon[i], g1, g2, expected_max);
|
"expected at most %d from mj_maxContact", ncon[i], g1, g2, expected_max);
|
||||||
@@ -1906,18 +1947,16 @@ static void mj_narrowphase(const mjModel* m, mjData* d, const mjcPair* buffer, i
|
|||||||
|
|
||||||
mj_markStack(d);
|
mj_markStack(d);
|
||||||
|
|
||||||
// buffer for pair data (g1, g2, ipair, index into conbuffer)
|
// buffer for pair data
|
||||||
int* pairbuffer = mj_stackAllocInt(d, 4 * npair);
|
mjcPair* pairbuffer = mjSTACKALLOC(d, npair, mjcPair);
|
||||||
int maxcon = 0;
|
int maxcon = 0;
|
||||||
for (int i = 0; i < npair; i++) {
|
for (int i = 0; i < npair; i++) {
|
||||||
int g1 = buffer[i].g1;
|
int g1 = buffer[i].geom_geom.g1;
|
||||||
int g2 = buffer[i].g2;
|
int g2 = buffer[i].geom_geom.g2;
|
||||||
int ipair = buffer[i].ipair;
|
int ipair = buffer[i].geom_geom.ipair;
|
||||||
|
|
||||||
pairbuffer[4*i + 0] = g1;
|
pairbuffer[i] = buffer[i];
|
||||||
pairbuffer[4*i + 1] = g2;
|
pairbuffer[i].conpos = maxcon;
|
||||||
pairbuffer[4*i + 2] = ipair;
|
|
||||||
pairbuffer[4*i + 3] = maxcon;
|
|
||||||
margin = getMargin(m, g1, g2, ipair);
|
margin = getMargin(m, g1, g2, ipair);
|
||||||
gap = getGap(m, g1, g2, ipair);
|
gap = getGap(m, g1, g2, ipair);
|
||||||
maxcon += mj_maxContact(m, g1, g2, margin + gap > 0);
|
maxcon += mj_maxContact(m, g1, g2, margin + gap > 0);
|
||||||
@@ -1973,9 +2012,9 @@ static void mj_narrowphase(const mjModel* m, mjData* d, const mjcPair* buffer, i
|
|||||||
int condim;
|
int condim;
|
||||||
mjtNum friction[5], solref[mjNREF], solimp[mjNIMP];
|
mjtNum friction[5], solref[mjNREF], solimp[mjNIMP];
|
||||||
mjtNum solreffriction[mjNREF] = {0};
|
mjtNum solreffriction[mjNREF] = {0};
|
||||||
int g1 = pairbuffer[4*i + 0];
|
int g1 = pairbuffer[i].geom_geom.g1;
|
||||||
int g2 = pairbuffer[4*i + 1];
|
int g2 = pairbuffer[i].geom_geom.g2;
|
||||||
int ipair = pairbuffer[4*i + 2];
|
int ipair = pairbuffer[i].geom_geom.ipair;
|
||||||
|
|
||||||
if (ipair >= 0) {
|
if (ipair >= 0) {
|
||||||
condim = m->pair_dim[ipair];
|
condim = m->pair_dim[ipair];
|
||||||
@@ -1989,7 +2028,7 @@ static void mj_narrowphase(const mjModel* m, mjData* d, const mjcPair* buffer, i
|
|||||||
mj_contactParam(m, &condim, solref, solimp, friction, g1, g2, -1, -1);
|
mj_contactParam(m, &condim, solref, solimp, friction, g1, g2, -1, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
mjPreContact* bc = arg.conbuffer + pairbuffer[4*i+3];
|
mjPreContact* bc = arg.conbuffer + pairbuffer[i].conpos;
|
||||||
margin = getMargin(m, g1, g2, ipair);
|
margin = getMargin(m, g1, g2, ipair);
|
||||||
for (int j=0; j < ncon; j++) {
|
for (int j=0; j < ncon; j++) {
|
||||||
mjContact* c = con + conpos + j;
|
mjContact* c = con + conpos + j;
|
||||||
|
|||||||
Reference in New Issue
Block a user