Remove thread_local EPA data in favor of using mjData stack.
PiperOrigin-RevId: 900201369 Change-Id: I82fbe9bf0ef9ea117c2124353d876dd42a57fb3a
This commit is contained in:
committed by
Copybara-Service
parent
7ac30a39fe
commit
d9b3faf8f4
@@ -34,17 +34,6 @@
|
|||||||
|
|
||||||
#define mjMINVAL2 (mjMINVAL * mjMINVAL)
|
#define mjMINVAL2 (mjMINVAL * mjMINVAL)
|
||||||
|
|
||||||
// allocate callback for EPA in nativeccd
|
|
||||||
static void* ccd_allocate(void* data, size_t nbytes) {
|
|
||||||
mj_markStack((mjData*)data);
|
|
||||||
return mj_stackAllocByte((mjData*)data, nbytes, sizeof(mjtNum));
|
|
||||||
}
|
|
||||||
|
|
||||||
// free callback for EPA in nativeccd
|
|
||||||
static void ccd_free(void* data, void* buffer) {
|
|
||||||
mj_freeStack((mjData*)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ccd prism first dir
|
// ccd prism first dir
|
||||||
static void prism_firstdir(const void* o1, const void* o2, ccd_vec3_t *vec) {
|
static void prism_firstdir(const void* o1, const void* o2, ccd_vec3_t *vec) {
|
||||||
ccdVec3Set(vec, 0, 0, 1);
|
ccdVec3Set(vec, 0, 0, 1);
|
||||||
@@ -98,15 +87,15 @@ static int mjc_penetration(const mjModel* m, mjData* d, mjCCDObj* obj1, mjCCDObj
|
|||||||
mjtNum dist;
|
mjtNum dist;
|
||||||
|
|
||||||
// set config
|
// set config
|
||||||
|
mj_markStack(d);
|
||||||
config.max_iterations = m->opt.ccd_iterations;
|
config.max_iterations = m->opt.ccd_iterations;
|
||||||
config.tolerance = m->opt.ccd_tolerance;
|
config.tolerance = m->opt.ccd_tolerance;
|
||||||
config.max_contacts = ncon;
|
config.max_contacts = ncon;
|
||||||
config.dist_cutoff = 0; // no geom distances needed
|
config.dist_cutoff = 0; // no geom distances needed
|
||||||
config.context = (void*)d;
|
config.buffer = mj_stackAllocByte(d, mjc_ccdSize(config.max_iterations), sizeof(mjtNum));
|
||||||
config.alloc = ccd_allocate;
|
|
||||||
config.free = ccd_free;
|
|
||||||
|
|
||||||
if ((dist = mjc_ccd(&config, &status, obj1, obj2)) < 0) {
|
if ((dist = mjc_ccd(&config, &status, obj1, obj2)) < 0) {
|
||||||
|
mj_freeStack(d);
|
||||||
int nwitness = status.nx;
|
int nwitness = status.nx;
|
||||||
for (int i = 0; i < nwitness; i++, con++) {
|
for (int i = 0; i < nwitness; i++, con++) {
|
||||||
con->dist = margin + dist;
|
con->dist = margin + dist;
|
||||||
@@ -119,6 +108,7 @@ static int mjc_penetration(const mjModel* m, mjData* d, mjCCDObj* obj1, mjCCDObj
|
|||||||
}
|
}
|
||||||
return nwitness;
|
return nwitness;
|
||||||
}
|
}
|
||||||
|
mj_freeStack(d);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -516,6 +516,7 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mj_freeStack(d);
|
||||||
|
|
||||||
// finish merging predefined geom pairs
|
// finish merging predefined geom pairs
|
||||||
for (; pairadr < npair; pairadr++) {
|
for (; pairadr < npair; pairadr++) {
|
||||||
@@ -572,8 +573,6 @@ void mj_collision(const mjModel* m, mjData* d) {
|
|||||||
|
|
||||||
// end narrowphase and midphase timer
|
// end narrowphase and midphase timer
|
||||||
TM_END(mjTIMER_COL_NARROW);
|
TM_END(mjTIMER_COL_NARROW);
|
||||||
|
|
||||||
mj_freeStack(d);
|
|
||||||
TM_END1(mjTIMER_POS_COLLISION);
|
TM_END1(mjTIMER_POS_COLLISION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
#include <mujoco/mjtnum.h>
|
#include <mujoco/mjtnum.h>
|
||||||
#include <mujoco/mjmodel.h>
|
#include <mujoco/mjmodel.h>
|
||||||
#include "engine/engine_collision_convex.h"
|
#include "engine/engine_collision_convex.h"
|
||||||
#include "engine/engine_macro.h"
|
|
||||||
#include "engine/engine_util_blas.h"
|
#include "engine/engine_util_blas.h"
|
||||||
#include "engine/engine_util_errmem.h"
|
#include "engine/engine_util_errmem.h"
|
||||||
|
|
||||||
@@ -2208,16 +2207,17 @@ static inline void inflate(mjCCDStatus* status, mjtNum margin1, mjtNum margin2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// return size in bytes of the buffer needed for mjc_ccd for a given number of iterations
|
||||||
|
size_t mjc_ccdSize(int iterations) {
|
||||||
|
return (sizeof(Face) * 6 * iterations) // faces in polytope
|
||||||
|
+ (sizeof(Face*) * 6 * iterations) // map in polytope
|
||||||
|
+ (sizeof(Vertex) * (5 + iterations)) // vertices in polytope
|
||||||
|
+ 2 * (24 * sizeof(int)); // horizon data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// general convex collision detection
|
// general convex collision detection
|
||||||
mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, mjCCDObj* obj2) {
|
mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, mjCCDObj* obj2) {
|
||||||
// pre-allocate static memory for low iterations
|
|
||||||
void* buffer = NULL;
|
|
||||||
static mjTHREADLOCAL Vertex vert_data[5 + mjMAX_EPA_ITERATIONS];
|
|
||||||
static mjTHREADLOCAL Face face_data[6 * mjMAX_EPA_ITERATIONS];
|
|
||||||
static mjTHREADLOCAL Face* map_data[6 * mjMAX_EPA_ITERATIONS];
|
|
||||||
static mjTHREADLOCAL int index_data[6 + mjMAX_EPA_ITERATIONS];
|
|
||||||
static mjTHREADLOCAL int edge_data[6 + mjMAX_EPA_ITERATIONS];
|
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
obj1->center(status->x1, obj1);
|
obj1->center(status->x1, obj1);
|
||||||
obj2->center(status->x2, obj2);
|
obj2->center(status->x2, obj2);
|
||||||
@@ -2295,42 +2295,24 @@ mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, m
|
|||||||
return status->dist;
|
return status->dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status->dist <= config->tolerance && status->nsimplex > 1) {
|
if (status->dist <= config->tolerance && status->nsimplex > 1 && config->buffer) {
|
||||||
status->dist = 0; // assume touching
|
status->dist = 0; // assume touching
|
||||||
Polytope pt;
|
Polytope pt;
|
||||||
pt.nfaces = pt.nmap = pt.nverts = pt.horizon.nedges = 0;
|
pt.nfaces = pt.nmap = pt.nverts = pt.horizon.nedges = 0;
|
||||||
|
|
||||||
// allocate memory via static thread-local storage
|
// allocate memory for polytope
|
||||||
int N = config->max_iterations;
|
int N = config->max_iterations;
|
||||||
if (N <= mjMAX_EPA_ITERATIONS) {
|
pt.maxfaces = 6 * N;
|
||||||
pt.maxfaces = 6 * mjMAX_EPA_ITERATIONS;
|
uint8_t* buffer = config->buffer;
|
||||||
pt.verts = vert_data;
|
pt.verts = (Vertex*)buffer;
|
||||||
pt.faces = face_data;
|
buffer += sizeof(Vertex) * (5 + N);
|
||||||
pt.map = map_data;
|
pt.faces = (Face*)buffer;
|
||||||
pt.horizon.indices = index_data;
|
buffer += sizeof(Face) * (6 * N);
|
||||||
pt.horizon.edges = edge_data;
|
pt.map = (Face**)buffer;
|
||||||
}
|
buffer += sizeof(Face*) * (6 * N);
|
||||||
|
pt.horizon.indices = (int*)buffer;
|
||||||
// static storage insufficient, allocate with callback
|
buffer += sizeof(int) * 24;
|
||||||
else {
|
pt.horizon.edges = (int*)buffer;
|
||||||
size_t nbytes = (sizeof(Face) * 6 * N) // faces in polytope
|
|
||||||
+ (sizeof(Face*) * 6 * N) // map in polytope
|
|
||||||
+ (sizeof(Vertex) * (5 + N)) // vertices in polytope
|
|
||||||
+ 2*(sizeof(int) * (6 + N)); // horizon data
|
|
||||||
|
|
||||||
pt.maxfaces = 6 * N;
|
|
||||||
buffer = config->alloc(config->context, nbytes);
|
|
||||||
uint8_t* bbuffer = (uint8_t*)buffer;
|
|
||||||
pt.verts = (Vertex*)bbuffer;
|
|
||||||
bbuffer += sizeof(Vertex) * (5 + N);
|
|
||||||
pt.faces = (Face*)bbuffer;
|
|
||||||
bbuffer += sizeof(Face) * (6 * N);
|
|
||||||
pt.map = (Face**)bbuffer;
|
|
||||||
bbuffer += sizeof(Face*) * (6 * N);
|
|
||||||
pt.horizon.indices = (int*)bbuffer;
|
|
||||||
bbuffer += sizeof(int) * (6 + N);
|
|
||||||
pt.horizon.edges = (int*)bbuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
if (status->nsimplex == 2) {
|
if (status->nsimplex == 2) {
|
||||||
@@ -2350,9 +2332,6 @@ mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (buffer) {
|
|
||||||
config->free(config->context, buffer);
|
|
||||||
}
|
|
||||||
return status->dist;
|
return status->dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,6 @@ extern "C" {
|
|||||||
#define mjMAX_LIMIT FLT_MAX
|
#define mjMAX_LIMIT FLT_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// max number of EPA iterations
|
|
||||||
#define mjMAX_EPA_ITERATIONS 170
|
|
||||||
|
|
||||||
// tolerance for normal alignment of two faces (cosine of 1.6e-3)
|
// tolerance for normal alignment of two faces (cosine of 1.6e-3)
|
||||||
#define mjFACE_TOL 0.99999872
|
#define mjFACE_TOL 0.99999872
|
||||||
|
|
||||||
@@ -77,13 +74,7 @@ typedef struct {
|
|||||||
mjtNum tolerance; // tolerance used by GJK and EPA
|
mjtNum tolerance; // tolerance used by GJK and EPA
|
||||||
int max_contacts; // set to max number of contact points to recover
|
int max_contacts; // set to max number of contact points to recover
|
||||||
mjtNum dist_cutoff; // set to max geom distance to recover
|
mjtNum dist_cutoff; // set to max geom distance to recover
|
||||||
void* context; // opaque data pointer passed to callbacks
|
void* buffer; // buffer memory for polytope (should be sized given by mjc_ccdSize)
|
||||||
|
|
||||||
// callback to allocate memory for polytope (only needed for penetration recovery)
|
|
||||||
void*(*alloc)(void* context, size_t nbytes);
|
|
||||||
|
|
||||||
// callback to free memory from alloc callback
|
|
||||||
void(*free)(void* context, void* buffer);
|
|
||||||
} mjCCDConfig;
|
} mjCCDConfig;
|
||||||
|
|
||||||
// data produced from running GJK and EPA
|
// data produced from running GJK and EPA
|
||||||
@@ -108,6 +99,9 @@ typedef struct {
|
|||||||
int nsimplex;
|
int nsimplex;
|
||||||
} mjCCDStatus;
|
} mjCCDStatus;
|
||||||
|
|
||||||
|
// return size in bytes of the buffer needed for mjc_ccd for a given number of iterations
|
||||||
|
MJAPI size_t mjc_ccdSize(int iterations);
|
||||||
|
|
||||||
// run general convex collision detection, returns positive for distance, negative for penetration
|
// run general convex collision detection, returns positive for distance, negative for penetration
|
||||||
MJAPI mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, mjCCDObj* obj2);
|
MJAPI mjtNum mjc_ccd(const mjCCDConfig* config, mjCCDStatus* status, mjCCDObj* obj1, mjCCDObj* obj2);
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -526,6 +526,7 @@ void mj_xfrcAccumulate(const mjModel* m, mjData* d, mjtNum* qfrc) {
|
|||||||
// returns the smallest distance between two geoms (using nativeccd)
|
// returns the smallest distance between two geoms (using nativeccd)
|
||||||
static mjtNum mj_geomDistanceCCD(const mjModel* m, mjData* d, int g1, int g2,
|
static mjtNum mj_geomDistanceCCD(const mjModel* m, mjData* d, int g1, int g2,
|
||||||
mjtNum distmax, mjtNum fromto[6]) {
|
mjtNum distmax, mjtNum fromto[6]) {
|
||||||
|
mj_markStack(d);
|
||||||
mjCCDConfig config;
|
mjCCDConfig config;
|
||||||
mjCCDStatus status;
|
mjCCDStatus status;
|
||||||
|
|
||||||
@@ -534,12 +535,14 @@ static mjtNum mj_geomDistanceCCD(const mjModel* m, mjData* d, int g1, int g2,
|
|||||||
config.tolerance = m->opt.ccd_tolerance;
|
config.tolerance = m->opt.ccd_tolerance;
|
||||||
config.max_contacts = 1; // want contacts
|
config.max_contacts = 1; // want contacts
|
||||||
config.dist_cutoff = distmax; // want geom distances
|
config.dist_cutoff = distmax; // want geom distances
|
||||||
|
config.buffer = mj_stackAllocByte(d, mjc_ccdSize(config.max_iterations), sizeof(mjtNum));
|
||||||
|
|
||||||
mjCCDObj obj1, obj2;
|
mjCCDObj obj1, obj2;
|
||||||
mjc_initCCDObj(&obj1, m, d, g1, 0);
|
mjc_initCCDObj(&obj1, m, d, g1, 0);
|
||||||
mjc_initCCDObj(&obj2, m, d, g2, 0);
|
mjc_initCCDObj(&obj2, m, d, g2, 0);
|
||||||
|
|
||||||
mjtNum dist = mjc_ccd(&config, &status, &obj1, &obj2);
|
mjtNum dist = mjc_ccd(&config, &status, &obj1, &obj2);
|
||||||
|
mj_freeStack(d);
|
||||||
|
|
||||||
// witness points are only computed if dist <= distmax
|
// witness points are only computed if dist <= distmax
|
||||||
if (fromto && status.nx > 0) {
|
if (fromto && status.nx > 0) {
|
||||||
|
|||||||
@@ -61,14 +61,6 @@ constexpr char kEllipsoidXml[] = R"(
|
|||||||
</keyframe>
|
</keyframe>
|
||||||
</mujoco>)";
|
</mujoco>)";
|
||||||
|
|
||||||
void* CCDAllocate(void* data, std::size_t nbytes) {
|
|
||||||
return new std::byte[nbytes];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCDFree(void* data, void* buffer) {
|
|
||||||
delete [] (std::byte*)buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
mjtNum GeomDist(mjModel* m, mjData* d, int g1, int g2, mjtNum x1[3],
|
mjtNum GeomDist(mjModel* m, mjData* d, int g1, int g2, mjtNum x1[3],
|
||||||
mjtNum x2[3], mjtNum cutoff = mjMAX_LIMIT) {
|
mjtNum x2[3], mjtNum cutoff = mjMAX_LIMIT) {
|
||||||
mjCCDConfig config;
|
mjCCDConfig config;
|
||||||
@@ -79,6 +71,7 @@ mjtNum GeomDist(mjModel* m, mjData* d, int g1, int g2, mjtNum x1[3],
|
|||||||
config.tolerance = kTolerance,
|
config.tolerance = kTolerance,
|
||||||
config.max_contacts = 0; // no geom contacts needed
|
config.max_contacts = 0; // no geom contacts needed
|
||||||
config.dist_cutoff = cutoff;
|
config.dist_cutoff = cutoff;
|
||||||
|
config.buffer = nullptr;
|
||||||
|
|
||||||
mjCCDObj obj1, obj2;
|
mjCCDObj obj1, obj2;
|
||||||
mjc_initCCDObj(&obj1, m, d, g1, 0);
|
mjc_initCCDObj(&obj1, m, d, g1, 0);
|
||||||
@@ -129,14 +122,13 @@ int Penetration(mjCCDStatus& status, mjtNum& depth, std::vector<mjtNum>& dir,
|
|||||||
mjCCDConfig config;
|
mjCCDConfig config;
|
||||||
|
|
||||||
// set config
|
// set config
|
||||||
|
auto buffer = std::vector<std::byte>(mjc_ccdSize(kMaxIterations));
|
||||||
config.max_iterations = kMaxIterations;
|
config.max_iterations = kMaxIterations;
|
||||||
config.tolerance = kTolerance;
|
config.tolerance = kTolerance;
|
||||||
config.max_contacts = max_contacts;
|
config.max_contacts = max_contacts;
|
||||||
config.dist_cutoff = 0; // no geom distances needed
|
config.dist_cutoff = 0; // no geom distances needed
|
||||||
config.max_contacts = max_contacts;
|
config.max_contacts = max_contacts;
|
||||||
config.context = nullptr;
|
config.buffer = buffer.data();
|
||||||
config.alloc = CCDAllocate;
|
|
||||||
config.free = CCDFree;
|
|
||||||
|
|
||||||
mjtNum dist = mjc_ccd(&config, &status, &obj1, &obj2);
|
mjtNum dist = mjc_ccd(&config, &status, &obj1, &obj2);
|
||||||
if (dist < 0) {
|
if (dist < 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user