Add nativeccd flag. When this flag is enabled, general convex collision detection is handled natively, as opposed to using libccd.

PiperOrigin-RevId: 663859009
Change-Id: Ife18bb1de62f2154e4725fdf764484a18586b836
This commit is contained in:
Kyle Bayes
2024-08-16 14:07:53 -07:00
committed by Copybara-Service
parent 390bce2352
commit 0bffd744f9
13 changed files with 62 additions and 39 deletions
+13 -9
View File
@@ -623,13 +623,13 @@ from its default.
.. _option-flag-multiccd: .. _option-flag-multiccd:
:at:`multiccd`: :at-val:`[disable, enable], "disable"` |nbsp| |nbsp| |nbsp| (experimental feature) :at:`multiccd`: :at-val:`[disable, enable], "disable"` |nbsp| |nbsp| |nbsp| (experimental feature)
This flag enables multiple-contact collision detection for geom pairs that use the general-purpose convex-convex This flag enables multiple-contact collision detection for geom pairs that use a general-purpose convex-convex
collider based on :ref:`libccd <coChecking>` e.g., mesh-mesh collisions. This can be useful when the contacting geoms collider e.g., mesh-mesh collisions. This can be useful when the contacting geoms have a flat surface, and the
have a flat surface, and the single contact point generated by the convex-convex collider cannot accurately capture single contact point generated by the convex-convex collider cannot accurately capture the surface contact, leading
the surface contact, leading to instabilities that typically manifest as sliding or wobbling. Multiple contact points to instabilities that typically manifest as sliding or wobbling. Multiple contact points are found by rotating the
are found by rotating the two geoms by ±1e-3 radians around the tangential axes and re-running the collision two geoms by ±1e-3 radians around the tangential axes and re-running the collision function. If a new contact is
function. If a new contact is detected it is added, allowing for up to 4 additional contact points. This feature is detected it is added, allowing for up to 4 additional contact points. This feature is currently considered
currently considered experimental, and both the behavior and the way it is activated may change in the future. experimental, and both the behavior and the way it is activated may change in the future.
.. _option-flag-island: .. _option-flag-island:
@@ -639,15 +639,19 @@ from its default.
allows for `island visualization <https://youtu.be/Vc1tq0fFvQA>`__. allows for `island visualization <https://youtu.be/Vc1tq0fFvQA>`__.
In a future release, the constraint solver will exploit the disjoint nature of constraint islands. In a future release, the constraint solver will exploit the disjoint nature of constraint islands.
.. _option-flag-nativeccd:
:at:`nativeccd`: :at-val:`[disable, enable], "disable"`
This flag enables the native convex collision detection pipeline instead of using the
`libccd library <https://github.com/danfis/libccd>`__.
.. _compiler: .. _compiler:
**compiler** (*) **compiler** (*)
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
This element is used to set options for the built-in parser and compiler. After parsing and compilation it no longer has This element is used to set options for the built-in parser and compiler. After parsing and compilation it no longer
any effect. The settings here are global and apply to the entire model. has any effect. The settings here are global and apply to the entire model.
.. _compiler-autolimits: .. _compiler-autolimits:
+1 -1
View File
@@ -39,7 +39,7 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`override<option-flag-override>` | :ref:`energy<option-flag-energy>` | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | | | | | | :ref:`override<option-flag-override>` | :ref:`energy<option-flag-energy>` | :ref:`fwdinv<option-flag-fwdinv>` | :ref:`invdiscrete<option-flag-invdiscrete>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`multiccd<option-flag-multiccd>` | :ref:`island<option-flag-island>` | | | | | | | | :ref:`multiccd<option-flag-multiccd>` | :ref:`island<option-flag-island>` | :ref:`nativeccd<option-flag-nativeccd>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| mujoco |br| |L| | | .. table:: | | mujoco |br| |L| | | .. table:: |
+15 -12
View File
@@ -7,28 +7,31 @@ Upcoming version (not yet released)
General General
^^^^^^^ ^^^^^^^
1. Added :ref:`mjSpec` option for creating a texture from a buffer. 1. Added the :ref:`nativeccd<option-flag-nativeccd>` flag. When this flag is enabled, general convex collision
2. :ref:`shellinertia <body-geom-shellinertia>` is now supported by all geom types. detection is handled natively, as opposed to using `libccd <https://github.com/danfis/libccd>`__. This feature is in
3. Added support for :ref:`attaching<meAttachment>` keyframes. early stages of testing.
2. Added :ref:`mjSpec` option for creating a texture from a buffer.
3. :ref:`shellinertia <body-geom-shellinertia>` is now supported by all geom types.
4. Added support for :ref:`attaching<meAttachment>` keyframes.
MJX MJX
^^^ ^^^
4. Added ``efc_pos`` to ``mjx.Data`` (:github:issue:`1388`). 5. Added ``efc_pos`` to ``mjx.Data`` (:github:issue:`1388`).
5. Added position-dependent sensors: ``MAGNETOMETER``, ``JOINTPOS``, ``ACTUATORPOS``, ``BALLQUAT``, ``FRAMEPOS``, 6. Added position-dependent sensors: ``MAGNETOMETER``, ``JOINTPOS``, ``ACTUATORPOS``, ``BALLQUAT``, ``FRAMEPOS``,
``FRAMEXAXIS``, ``FRAMEYAXIS``, ``FRAMEZAXIS``, ``SUBTREECOM``, ``CLOCK``. ``FRAMEXAXIS``, ``FRAMEYAXIS``, ``FRAMEZAXIS``, ``SUBTREECOM``, ``CLOCK``.
6. Changed default policy to avoid placing unused (MuJoCo-only) arrays on device. 7. Changed default policy to avoid placing unused (MuJoCo-only) arrays on device.
7. Added ``device`` parameter to ``mjx.make_data`` to bring it to parity with ``mjx.put_model`` and ``mjx.put_data``. 8. Added ``device`` parameter to ``mjx.make_data`` to bring it to parity with ``mjx.put_model`` and ``mjx.put_data``.
Bug fixes Bug fixes
^^^^^^^^^ ^^^^^^^^^
8. Fixed a performance regression introduced in 3.1.7 in mesh Bounding Volume Hierarchies (:github:issue:`1875`, 9. Fixed a performance regression introduced in 3.1.7 in mesh Bounding Volume Hierarchies (:github:issue:`1875`,
contribution by :github:user:`michael-ahn`). contribution by :github:user:`michael-ahn`).
9. Fixed a bug wherein, for models that have both muscles and stateless actuators and used one of the implicit 10. Fixed a bug wherein, for models that have both muscles and stateless actuators and used one of the implicit
integrators, wrong derivatives would be computed. integrators, wrong derivatives would be computed.
Python bindings Python bindings
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
10. Added support for engine plugins in :ref:`mjSpec` (:github:issue:`1903`). 11. Added support for engine plugins in :ref:`mjSpec` (:github:issue:`1903`).
Version 3.2.2 (Aug 8, 2024) Version 3.2.2 (Aug 8, 2024)
+2 -1
View File
@@ -430,8 +430,9 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
// experimental features: // experimental features:
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
mjENBL_ISLAND = 1<<5, // constraint island discovery mjENBL_ISLAND = 1<<5, // constraint island discovery
mjENBL_NATIVECCD = 1<<6, // native convex collision detection
mjNENABLE = 6 // number of enable flags mjNENABLE = 7 // number of enable flags
} mjtEnableBit; } mjtEnableBit;
typedef enum mjtJoint_ { // type of degree of freedom typedef enum mjtJoint_ { // type of degree of freedom
mjJNT_FREE = 0, // global position and orientation (quat) (7) mjJNT_FREE = 0, // global position and orientation (quat) (7)
+2 -1
View File
@@ -75,8 +75,9 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags
// experimental features: // experimental features:
mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection
mjENBL_ISLAND = 1<<5, // constraint island discovery mjENBL_ISLAND = 1<<5, // constraint island discovery
mjENBL_NATIVECCD = 1<<6, // native convex collision detection
mjNENABLE = 6 // number of enable flags mjNENABLE = 7 // number of enable flags
} mjtEnableBit; } mjtEnableBit;
+2 -1
View File
@@ -57,7 +57,8 @@ ENUMS: Mapping[str, EnumDecl] = dict([
('mjENBL_INVDISCRETE', 8), ('mjENBL_INVDISCRETE', 8),
('mjENBL_MULTICCD', 16), ('mjENBL_MULTICCD', 16),
('mjENBL_ISLAND', 32), ('mjENBL_ISLAND', 32),
('mjNENABLE', 6), ('mjENBL_NATIVECCD', 64),
('mjNENABLE', 7),
]), ]),
)), )),
('mjtJoint', ('mjtJoint',
+2 -1
View File
@@ -44,7 +44,8 @@ class EnumsTest(absltest.TestCase):
('mjENBL_INVDISCRETE', 1<<3), ('mjENBL_INVDISCRETE', 1<<3),
('mjENBL_MULTICCD', 1<<4), ('mjENBL_MULTICCD', 1<<4),
('mjENBL_ISLAND', 1<<5), ('mjENBL_ISLAND', 1<<5),
('mjNENABLE', 6))) ('mjENBL_NATIVECCD', 1<<6),
('mjNENABLE', 7)))
# values mostly increment by one with occasional overrides # values mostly increment by one with occasional overrides
def test_mjtGeom(self): # pylint: disable=invalid-name def test_mjtGeom(self): # pylint: disable=invalid-name
+1 -1
View File
@@ -870,7 +870,7 @@ Euler integrator, semi-implicit in velocity.
self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1<<0) self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1<<0)
self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1<<1) self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1<<1)
self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1<<2) self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1<<2)
self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 6) self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 7)
self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0) self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0)
self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1) self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1)
self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2) self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2)
+16 -8
View File
@@ -23,14 +23,24 @@
#include <mujoco/mjdata.h> #include <mujoco/mjdata.h>
#include <mujoco/mjmacro.h> #include <mujoco/mjmacro.h>
#include <mujoco/mjmodel.h> #include <mujoco/mjmodel.h>
#include "engine/engine_collision_gjk.h"
#include "engine/engine_collision_primitive.h" #include "engine/engine_collision_primitive.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"
#include "engine/engine_util_misc.h" #include "engine/engine_util_misc.h"
#include "engine/engine_util_spatial.h" #include "engine/engine_util_spatial.h"
// the LibCCD penetration function we use (ccdMPRPenetration or ccdGJKPenetration)
#define _mjCCDPENETRATION ccdMPRPenetration // call LibCCD or GJK to recover penetration info
static int mjc_penetration(const mjModel* m, const void *obj1, const void *obj2, const ccd_t *ccd,
ccd_real_t *depth, ccd_vec3_t *dir, ccd_vec3_t *pos) {
if (mjENABLED(mjENBL_NATIVECCD)) {
return mj_gjkPenetration(obj1, obj2, ccd, depth, dir, pos);
} else {
return ccdMPRPenetration(obj1, obj2, ccd, depth, dir, pos);
}
}
// ccd center function // ccd center function
void mjccd_center(const void *obj, ccd_vec3_t *center) { void mjccd_center(const void *obj, ccd_vec3_t *center) {
@@ -294,7 +304,7 @@ static int mjc_MPRIteration(mjCCDObj* obj1, mjCCDObj* obj2, const ccd_t* ccd,
mjContact* con, mjtNum margin) { mjContact* con, mjtNum margin) {
ccd_vec3_t dir, pos; ccd_vec3_t dir, pos;
ccd_real_t depth; ccd_real_t depth;
if (_mjCCDPENETRATION(obj1, obj2, ccd, &depth, &dir, &pos) == 0) { if (mjc_penetration(m, obj1, obj2, ccd, &depth, &dir, &pos) == 0) {
// contact is found but normal is undefined // contact is found but normal is undefined
if (ccdVec3Eq(&dir, ccd_vec3_origin)) { if (ccdVec3Eq(&dir, ccd_vec3_origin)) {
return 0; return 0;
@@ -806,8 +816,8 @@ int mjc_ConvexHField(const mjModel* m, const mjData* d,
continue; continue;
} }
// run MPR, save contact // run penetration function, save contact
if (_mjCCDPENETRATION(&obj1, &obj2, &ccd, &depth, &dirccd, &vecccd) == 0 if (mjc_penetration(m, &obj1, &obj2, &ccd, &depth, &dirccd, &vecccd) == 0
&& !ccdVec3Eq(&dirccd, ccd_vec3_origin)) { && !ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
// fill in contact data, transform to global coordinates // fill in contact data, transform to global coordinates
con[cnt].dist = -depth; con[cnt].dist = -depth;
@@ -1257,7 +1267,7 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
} }
// run MPR, save contact // run MPR, save contact
if (_mjCCDPENETRATION(&obj1, &obj2, &ccd, &depth, &dirccd, &vecccd) == 0) { if (mjc_penetration(m, &obj1, &obj2, &ccd, &depth, &dirccd, &vecccd) == 0) {
if (!ccdVec3Eq(&dirccd, ccd_vec3_origin)) { if (!ccdVec3Eq(&dirccd, ccd_vec3_origin)) {
// fill in contact data, transform to global coordinates // fill in contact data, transform to global coordinates
con[cnt].dist = -depth; con[cnt].dist = -depth;
@@ -1289,5 +1299,3 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
return cnt; return cnt;
} }
#undef _mjCCDPENETRATION
+2 -1
View File
@@ -69,7 +69,8 @@ const char* mjENABLESTRING[mjNENABLE] = {
"Fwdinv", "Fwdinv",
"InvDiscrete", "InvDiscrete",
"MultiCCD", "MultiCCD",
"Island" "Island",
"NativeCCD"
}; };
+3 -2
View File
@@ -116,10 +116,10 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
"solver", "iterations", "ls_iterations", "noslip_iterations", "mpr_iterations", "solver", "iterations", "ls_iterations", "noslip_iterations", "mpr_iterations",
"sdf_iterations", "sdf_initpoints", "actuatorgroupdisable"}, "sdf_iterations", "sdf_initpoints", "actuatorgroupdisable"},
{"<"}, {"<"},
{"flag", "?", "22", "constraint", "equality", "frictionloss", "limit", "contact", {"flag", "?", "23", "constraint", "equality", "frictionloss", "limit", "contact",
"passive", "gravity", "clampctrl", "warmstart", "passive", "gravity", "clampctrl", "warmstart",
"filterparent", "actuation", "refsafe", "sensor", "midphase", "eulerdamp", "autoreset", "filterparent", "actuation", "refsafe", "sensor", "midphase", "eulerdamp", "autoreset",
"override", "energy", "fwdinv", "invdiscrete", "multiccd", "island"}, "override", "energy", "fwdinv", "invdiscrete", "multiccd", "island", "nativeccd"},
{">"}, {">"},
{"size", "*", "14", "memory", "njmax", "nconmax", "nstack", "nuserdata", "nkey", {"size", "*", "14", "memory", "njmax", "nconmax", "nstack", "nuserdata", "nkey",
@@ -1137,6 +1137,7 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) {
READENBL("invdiscrete", mjENBL_INVDISCRETE) READENBL("invdiscrete", mjENBL_INVDISCRETE)
READENBL("multiccd", mjENBL_MULTICCD) READENBL("multiccd", mjENBL_MULTICCD)
READENBL("island", mjENBL_ISLAND) READENBL("island", mjENBL_ISLAND)
READENBL("nativeccd", mjENBL_NATIVECCD)
#undef READENBL #undef READENBL
} }
} }
+1
View File
@@ -1011,6 +1011,7 @@ void mjXWriter::Option(XMLElement* root) {
WRITEENBL("invdiscrete", mjENBL_INVDISCRETE) WRITEENBL("invdiscrete", mjENBL_INVDISCRETE)
WRITEENBL("multiccd", mjENBL_MULTICCD) WRITEENBL("multiccd", mjENBL_MULTICCD)
WRITEENBL("island", mjENBL_ISLAND) WRITEENBL("island", mjENBL_ISLAND)
WRITEENBL("nativeccd", mjENBL_NATIVECCD)
#undef WRITEENBL #undef WRITEENBL
} }
+2 -1
View File
@@ -167,7 +167,8 @@ public enum mjtEnableBit : int{
mjENBL_INVDISCRETE = 8, mjENBL_INVDISCRETE = 8,
mjENBL_MULTICCD = 16, mjENBL_MULTICCD = 16,
mjENBL_ISLAND = 32, mjENBL_ISLAND = 32,
mjNENABLE = 6, mjENBL_NATIVECCD = 64,
mjNENABLE = 7,
} }
public enum mjtJoint : int{ public enum mjtJoint : int{
mjJNT_FREE = 0, mjJNT_FREE = 0,