diff --git a/doc/includes/references.h b/doc/includes/references.h index 0ee5a22b..1e1db78d 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -494,8 +494,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags mjDSBL_AUTORESET = 1<<16, // automatic reset when numerical issues are detected mjDSBL_NATIVECCD = 1<<17, // native convex collision detection mjDSBL_ISLAND = 1<<18, // constraint island discovery + mjDSBL_MULTICCD = 1<<19, // multiple CCD contact points - mjNDISABLE = 19 // number of disable flags + mjNDISABLE = 20 // number of disable flags } mjtDisableBit; typedef enum mjtEnableBit_ { // enable optional feature bitflags mjENBL_OVERRIDE = 1<<0, // override contact parameters @@ -503,10 +504,9 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags mjENBL_FWDINV = 1<<2, // record solver statistics mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics // experimental features: - mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection - mjENBL_SLEEP = 1<<5, // sleeping + mjENBL_SLEEP = 1<<4, // sleeping - mjNENABLE = 6 // number of enable flags + mjNENABLE = 5 // number of enable flags } mjtEnableBit; typedef enum mjtJoint_ { // type of degree of freedom mjJNT_FREE = 0, // global position and orientation (quat) (7) diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index fba680f9..1c9214ae 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -70,8 +70,9 @@ typedef enum mjtDisableBit_ { // disable default feature bitflags mjDSBL_AUTORESET = 1<<16, // automatic reset when numerical issues are detected mjDSBL_NATIVECCD = 1<<17, // native convex collision detection mjDSBL_ISLAND = 1<<18, // constraint island discovery + mjDSBL_MULTICCD = 1<<19, // multiple CCD contact points - mjNDISABLE = 19 // number of disable flags + mjNDISABLE = 20 // number of disable flags } mjtDisableBit; @@ -81,10 +82,9 @@ typedef enum mjtEnableBit_ { // enable optional feature bitflags mjENBL_FWDINV = 1<<2, // record solver statistics mjENBL_INVDISCRETE = 1<<3, // discrete-time inverse dynamics // experimental features: - mjENBL_MULTICCD = 1<<4, // multi-point convex collision detection - mjENBL_SLEEP = 1<<5, // sleeping + mjENBL_SLEEP = 1<<4, // sleeping - mjNENABLE = 6 // number of enable flags + mjNENABLE = 5 // number of enable flags } mjtEnableBit; diff --git a/mjx/mujoco/mjx/_src/types.py b/mjx/mujoco/mjx/_src/types.py index 8bc60bd2..ff08579c 100644 --- a/mjx/mujoco/mjx/_src/types.py +++ b/mjx/mujoco/mjx/_src/types.py @@ -92,8 +92,6 @@ class EnableBit(enum.IntFlag): INVDISCRETE = mujoco.mjtEnableBit.mjENBL_INVDISCRETE # unsupported: OVERRIDE, ENERGY, FWDINV, ISLAND - # required by the C implementation only, ignored otherwise: MULTICCD - MULTICCD = mujoco.mjtEnableBit.mjENBL_MULTICCD SLEEP = mujoco.mjtEnableBit.mjENBL_SLEEP diff --git a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/collision_convex.py b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/collision_convex.py index 4f6b21c5..88917ea7 100644 --- a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/collision_convex.py +++ b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/collision_convex.py @@ -36,7 +36,7 @@ from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAX_EPAHORIZON from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXCONPAIR from mujoco.mjx.third_party.mujoco_warp._src.types import MJ_MAXVAL from mujoco.mjx.third_party.mujoco_warp._src.types import Data -from mujoco.mjx.third_party.mujoco_warp._src.types import EnableBit +from mujoco.mjx.third_party.mujoco_warp._src.types import DisableBit from mujoco.mjx.third_party.mujoco_warp._src.types import GeomType from mujoco.mjx.third_party.mujoco_warp._src.types import Model from mujoco.mjx.third_party.mujoco_warp._src.types import mat43 @@ -1127,7 +1127,7 @@ def convex_narrowphase(m: Model, d: Data, ctx: CollisionContext, collision_table epa_iterations = 16 if nboxbox == ncollision else m.opt.ccd_iterations # set to true to enable multiccd - use_multiccd = m.opt.enableflags & EnableBit.MULTICCD + use_multiccd = m.opt.disableflags & DisableBit.MULTICCD == 0 # need at least 4 (square sides) if there's a box collision needing multiccd nmaxpolygon = 4 if nboxbox > 0 else 0 diff --git a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/io.py b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/io.py index 4a743681..56bbb18c 100644 --- a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/io.py +++ b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/io.py @@ -370,7 +370,7 @@ def put_model(mjm: mujoco.MjModel) -> types.Model: ) # check for unsupported margin + multicontact / box-box CCD combinations - use_multiccd = mjm.opt.enableflags & types.EnableBit.MULTICCD + use_multiccd = (mjm.opt.disableflags & types.DisableBit.MULTICCD) == 0 nativeccd_disabled = mjm.opt.disableflags & types.DisableBit.NATIVECCD BOX = int(mujoco.mjtGeom.mjGEOM_BOX) MESH = int(mujoco.mjtGeom.mjGEOM_MESH) diff --git a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/types.py b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/types.py index 7a9dc2a5..bf4f1b6b 100644 --- a/mjx/mujoco/mjx/third_party/mujoco_warp/_src/types.py +++ b/mjx/mujoco/mjx/third_party/mujoco_warp/_src/types.py @@ -184,6 +184,7 @@ class DisableBit(enum.IntFlag): EULERDAMP: implicit damping for Euler integration NATIVECCD: native convex collision detection (ignored in MJWarp) ISLAND: constraint islands + MULTICCD: multiple CCD contact points """ CONSTRAINT = mujoco.mjtDisableBit.mjDSBL_CONSTRAINT @@ -203,6 +204,7 @@ class DisableBit(enum.IntFlag): EULERDAMP = mujoco.mjtDisableBit.mjDSBL_EULERDAMP NATIVECCD = mujoco.mjtDisableBit.mjDSBL_NATIVECCD ISLAND = mujoco.mjtDisableBit.mjDSBL_ISLAND + MULTICCD = mujoco.mjtDisableBit.mjDSBL_MULTICCD # unsupported: MIDPHASE, AUTORESET @@ -212,12 +214,10 @@ class EnableBit(enum.IntFlag): Attributes: ENERGY: energy computation INVDISCRETE: discrete-time inverse dynamics - MULTICCD: multiple contacts with CCD """ ENERGY = mujoco.mjtEnableBit.mjENBL_ENERGY INVDISCRETE = mujoco.mjtEnableBit.mjENBL_INVDISCRETE - MULTICCD = mujoco.mjtEnableBit.mjENBL_MULTICCD # unsupported: OVERRIDE, FWDINV, ISLAND diff --git a/plugin/usd_decoder/usd_decoder.cc b/plugin/usd_decoder/usd_decoder.cc index f1ab1c05..04fe6976 100644 --- a/plugin/usd_decoder/usd_decoder.cc +++ b/plugin/usd_decoder/usd_decoder.cc @@ -704,7 +704,7 @@ void ParseUsdPhysicsScene(mjSpec* spec, bool multiccd_flag; mjc_physics_scene.GetMultiCCDFlagAttr().Get(&multiccd_flag); - spec->option.enableflags |= (multiccd_flag ? mjENBL_MULTICCD : 0); + spec->option.disableflags |= (!multiccd_flag ? mjDSBL_MULTICCD : 0); // Compiler attributes auto auto_limits_attr = mjc_physics_scene.GetAutoLimitsAttr(); diff --git a/python/mujoco/bindings_test.py b/python/mujoco/bindings_test.py index 8dd91c60..c4b550d1 100644 --- a/python/mujoco/bindings_test.py +++ b/python/mujoco/bindings_test.py @@ -966,7 +966,7 @@ Euler integrator, semi-implicit in velocity. self.assertEqual(mujoco.mjtEnableBit.mjENBL_OVERRIDE, 1 << 0) self.assertEqual(mujoco.mjtEnableBit.mjENBL_ENERGY, 1 << 1) self.assertEqual(mujoco.mjtEnableBit.mjENBL_FWDINV, 1 << 2) - self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 6) + self.assertEqual(mujoco.mjtEnableBit.mjNENABLE, 5) self.assertEqual(mujoco.mjtGeom.mjGEOM_PLANE, 0) self.assertEqual(mujoco.mjtGeom.mjGEOM_HFIELD, 1) self.assertEqual(mujoco.mjtGeom.mjGEOM_SPHERE, 2) diff --git a/python/mujoco/introspect/enums.py b/python/mujoco/introspect/enums.py index d686e861..1ec77cb1 100644 --- a/python/mujoco/introspect/enums.py +++ b/python/mujoco/introspect/enums.py @@ -46,7 +46,8 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjDSBL_AUTORESET', 65536), ('mjDSBL_NATIVECCD', 131072), ('mjDSBL_ISLAND', 262144), - ('mjNDISABLE', 19), + ('mjDSBL_MULTICCD', 524288), + ('mjNDISABLE', 20), ]), )), ('mjtEnableBit', @@ -58,9 +59,8 @@ ENUMS: Mapping[str, EnumDecl] = dict([ ('mjENBL_ENERGY', 2), ('mjENBL_FWDINV', 4), ('mjENBL_INVDISCRETE', 8), - ('mjENBL_MULTICCD', 16), - ('mjENBL_SLEEP', 32), - ('mjNENABLE', 6), + ('mjENBL_SLEEP', 16), + ('mjNENABLE', 5), ]), )), ('mjtJoint', diff --git a/python/mujoco/introspect/enums_test.py b/python/mujoco/introspect/enums_test.py index d023fbcb..e373034b 100644 --- a/python/mujoco/introspect/enums_test.py +++ b/python/mujoco/introspect/enums_test.py @@ -42,9 +42,8 @@ class EnumsTest(absltest.TestCase): ('mjENBL_ENERGY', 1<<1), ('mjENBL_FWDINV', 1<<2), ('mjENBL_INVDISCRETE', 1<<3), - ('mjENBL_MULTICCD', 1<<4), - ('mjENBL_SLEEP', 1<<5), - ('mjNENABLE', 6))) + ('mjENBL_SLEEP', 1<<4), + ('mjNENABLE', 5))) # values mostly increment by one with occasional overrides def test_mjtGeom(self): # pylint: disable=invalid-name diff --git a/src/engine/engine_collision_convex.c b/src/engine/engine_collision_convex.c index a847a099..46f4cf09 100644 --- a/src/engine/engine_collision_convex.c +++ b/src/engine/engine_collision_convex.c @@ -828,7 +828,7 @@ static int maxContacts(const mjModel* m, const mjCCDObj* obj1, const mjCCDObj* o // reduce mesh collisions to 4 contacts max if (type1 == mjGEOM_BOX || type1 == mjGEOM_MESH) { if (type2 == mjGEOM_BOX || type2 == mjGEOM_MESH) { - return mjENABLED(mjENBL_MULTICCD) ? 4 : 1; + return mjDISABLED(mjDSBL_MULTICCD) ? 1 : 4; } } @@ -857,7 +857,7 @@ int mjc_Convex(const mjModel* m, mjData* d, mjContact* con, int g1, int g2, mjtN } // look for additional contacts - if (ncon == 1 && mjENABLED(mjENBL_MULTICCD) // TODO(tassa) leave as bitflag or make geom attribute (?) + if (ncon == 1 && !mjDISABLED(mjDSBL_MULTICCD) // TODO(tassa) leave as bitflag or make geom attribute (?) && m->geom_type[g1] != mjGEOM_ELLIPSOID && m->geom_type[g1] != mjGEOM_SPHERE && m->geom_type[g2] != mjGEOM_ELLIPSOID && m->geom_type[g2] != mjGEOM_SPHERE) { // multiCCD parameters diff --git a/src/engine/engine_support.c b/src/engine/engine_support.c index a8725bf7..2cff8056 100644 --- a/src/engine/engine_support.c +++ b/src/engine/engine_support.c @@ -66,7 +66,8 @@ const char* mjDISABLESTRING[mjNDISABLE] = { "Eulerdamp", "AutoReset", "NativeCCD", - "Island" + "Island", + "MultiCCD" }; @@ -76,7 +77,6 @@ const char* mjENABLESTRING[mjNENABLE] = { "Energy", "Fwdinv", "InvDiscrete", - "MultiCCD", "Sleep" }; diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc index 2820a3aa..ccc4158c 100644 --- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc +++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc @@ -649,7 +649,6 @@ class ModelWriter { }; const std::vector> enable_flags = { - {MjcPhysicsTokens->mjcFlagMulticcd, mjENBL_MULTICCD}, {MjcPhysicsTokens->mjcFlagFwdinv, mjENBL_FWDINV}, {MjcPhysicsTokens->mjcFlagEnergy, mjENBL_ENERGY}, {MjcPhysicsTokens->mjcFlagOverride, mjENBL_OVERRIDE}, @@ -677,7 +676,8 @@ class ModelWriter { {MjcPhysicsTokens->mjcFlagEulerdamp, mjDSBL_EULERDAMP}, {MjcPhysicsTokens->mjcFlagAutoreset, mjDSBL_AUTORESET}, {MjcPhysicsTokens->mjcFlagNativeccd, mjDSBL_NATIVECCD}, - {MjcPhysicsTokens->mjcFlagIsland, mjDSBL_ISLAND}}; + {MjcPhysicsTokens->mjcFlagIsland, mjDSBL_ISLAND}, + {MjcPhysicsTokens->mjcFlagMulticcd, mjDSBL_MULTICCD}}; for (const auto &[token, flag] : disable_flags) { create_flag_attr(token, flag, false); } diff --git a/src/xml/xml_native_reader.cc b/src/xml/xml_native_reader.cc index 5e17aa1d..af291787 100644 --- a/src/xml/xml_native_reader.cc +++ b/src/xml/xml_native_reader.cc @@ -1284,6 +1284,7 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) { READDSBL("autoreset", mjDSBL_AUTORESET) READDSBL("nativeccd", mjDSBL_NATIVECCD) READDSBL("island", mjDSBL_ISLAND) + READDSBL("multiccd", mjDSBL_MULTICCD) #undef READDSBL #define READENBL(NAME, MASK) \ @@ -1295,7 +1296,6 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) { READENBL("energy", mjENBL_ENERGY) READENBL("fwdinv", mjENBL_FWDINV) READENBL("invdiscrete", mjENBL_INVDISCRETE) - READENBL("multiccd", mjENBL_MULTICCD) READENBL("sleep", mjENBL_SLEEP) #undef READENBL } diff --git a/src/xml/xml_native_writer.cc b/src/xml/xml_native_writer.cc index ebe95bab..0bc4c07a 100644 --- a/src/xml/xml_native_writer.cc +++ b/src/xml/xml_native_writer.cc @@ -1093,7 +1093,7 @@ void mjXWriter::Option(XMLElement* root) { XMLElement* sub = InsertEnd(section, "flag"); #define WRITEDSBL(NAME, MASK) \ - if( model->option.disableflags & MASK ) \ + if (model->option.disableflags & MASK) \ WriteAttrKey(sub, NAME, enable_map, 2, 0); WRITEDSBL("constraint", mjDSBL_CONSTRAINT) WRITEDSBL("equality", mjDSBL_EQUALITY) @@ -1114,16 +1114,16 @@ void mjXWriter::Option(XMLElement* root) { WRITEDSBL("autoreset", mjDSBL_AUTORESET) WRITEDSBL("nativeccd", mjDSBL_NATIVECCD) WRITEDSBL("island", mjDSBL_ISLAND) + WRITEDSBL("multiccd", mjDSBL_MULTICCD) #undef WRITEDSBL #define WRITEENBL(NAME, MASK) \ - if( model->option.enableflags & MASK ) \ + if (model->option.enableflags & MASK) \ WriteAttrKey(sub, NAME, enable_map, 2, 1); WRITEENBL("override", mjENBL_OVERRIDE) WRITEENBL("energy", mjENBL_ENERGY) WRITEENBL("fwdinv", mjENBL_FWDINV) WRITEENBL("invdiscrete", mjENBL_INVDISCRETE) - WRITEENBL("multiccd", mjENBL_MULTICCD) WRITEENBL("sleep", mjENBL_SLEEP) #undef WRITEENBL } diff --git a/test/engine/engine_collision_convex_test.cc b/test/engine/engine_collision_convex_test.cc index 9615b542..7d4346e5 100644 --- a/test/engine/engine_collision_convex_test.cc +++ b/test/engine/engine_collision_convex_test.cc @@ -68,7 +68,7 @@ TEST_F(MjcConvexTest, CylinderBox) { EXPECT_EQ(data->ncon, 5); // with multiCCD disabled, should find 1 contact - model->opt.enableflags &= ~mjENBL_MULTICCD; + model->opt.disableflags |= mjDSBL_MULTICCD; mj_forward(model, data); EXPECT_EQ(data->ncon, 1); diff --git a/test/engine/engine_collision_gjk_test.cc b/test/engine/engine_collision_gjk_test.cc index 653abbb4..4e4f9f10 100644 --- a/test/engine/engine_collision_gjk_test.cc +++ b/test/engine/engine_collision_gjk_test.cc @@ -1998,7 +1998,7 @@ TEST_F(MjGjkTest, CylinderBoxMargin) { diff --git a/test/engine/engine_solver_test.cc b/test/engine/engine_solver_test.cc index 523dfd33..8aaf1d9d 100644 --- a/test/engine/engine_solver_test.cc +++ b/test/engine/engine_solver_test.cc @@ -46,6 +46,7 @@ TEST_F(SolverTest, IslandsEquivalent) { model->opt.tolerance = 0; // set tolerance to 0 model->opt.ls_tolerance = 0; // set ls_tolerance to 0 model->opt.ccd_tolerance = 0; // set ccd_tolerance to 0 + model->opt.disableflags |= mjDSBL_MULTICCD; // disable multiccd int nv = model->nv; diff --git a/test/experimental/usd/mjcPhysics/mjc_physics_scene_test.cc b/test/experimental/usd/mjcPhysics/mjc_physics_scene_test.cc index 30cb4d70..d7f106d4 100644 --- a/test/experimental/usd/mjcPhysics/mjc_physics_scene_test.cc +++ b/test/experimental/usd/mjcPhysics/mjc_physics_scene_test.cc @@ -179,8 +179,6 @@ TEST_F(MjcPhysicsSceneTest, TestDefaults) { EXPECT_ENABLE_FLAG_USD_FALLBACK_EQ_MODEL_DEFAULT(FwdinvFlag, mjENBL_FWDINV); EXPECT_ENABLE_FLAG_USD_FALLBACK_EQ_MODEL_DEFAULT(InvDiscreteFlag, mjENBL_INVDISCRETE); - EXPECT_ENABLE_FLAG_USD_FALLBACK_EQ_MODEL_DEFAULT(MultiCCDFlag, - mjENBL_MULTICCD); mj_deleteModel(default_model); mj_deleteSpec(empty_spec); diff --git a/unity/Runtime/Bindings/MjBindings.cs b/unity/Runtime/Bindings/MjBindings.cs index 1673c4d0..d5ea2b37 100644 --- a/unity/Runtime/Bindings/MjBindings.cs +++ b/unity/Runtime/Bindings/MjBindings.cs @@ -137,16 +137,16 @@ public enum mjtDisableBit : int{ mjDSBL_AUTORESET = 65536, mjDSBL_NATIVECCD = 131072, mjDSBL_ISLAND = 262144, - mjNDISABLE = 19, + mjDSBL_MULTICCD = 524288, + mjNDISABLE = 20, } public enum mjtEnableBit : int{ mjENBL_OVERRIDE = 1, mjENBL_ENERGY = 2, mjENBL_FWDINV = 4, mjENBL_INVDISCRETE = 8, - mjENBL_MULTICCD = 16, - mjENBL_SLEEP = 32, - mjNENABLE = 6, + mjENBL_SLEEP = 16, + mjNENABLE = 5, } public enum mjtJoint : int{ mjJNT_FREE = 0, diff --git a/wasm/codegen/generated/bindings.cc b/wasm/codegen/generated/bindings.cc index 185f5bb7..dfe18aea 100644 --- a/wasm/codegen/generated/bindings.cc +++ b/wasm/codegen/generated/bindings.cc @@ -10942,6 +10942,7 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) { .value("mjDSBL_AUTORESET", mjDSBL_AUTORESET) .value("mjDSBL_NATIVECCD", mjDSBL_NATIVECCD) .value("mjDSBL_ISLAND", mjDSBL_ISLAND) + .value("mjDSBL_MULTICCD", mjDSBL_MULTICCD) .value("mjNDISABLE", mjNDISABLE); enum_("mjtDyn") .value("mjDYN_NONE", mjDYN_NONE) @@ -10956,7 +10957,6 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) { .value("mjENBL_ENERGY", mjENBL_ENERGY) .value("mjENBL_FWDINV", mjENBL_FWDINV) .value("mjENBL_INVDISCRETE", mjENBL_INVDISCRETE) - .value("mjENBL_MULTICCD", mjENBL_MULTICCD) .value("mjENBL_SLEEP", mjENBL_SLEEP) .value("mjNENABLE", mjNENABLE); enum_("mjtEq") diff --git a/wasm/tests/bindings_test.ts b/wasm/tests/bindings_test.ts index 516cf507..a58fd087 100644 --- a/wasm/tests/bindings_test.ts +++ b/wasm/tests/bindings_test.ts @@ -684,10 +684,10 @@ describe('MuJoCo WASM Bindings', () => { it('should check constants values', () => { expect(mujoco.mjNEQDATA).toBe(11); expect(mujoco.mjDISABLESTRING).toEqual([ - 'Constraint', 'Equality', 'Frictionloss', 'Limit', 'Contact', 'Spring', - 'Damper', 'Gravity', 'Clampctrl', 'Warmstart', 'Filterparent', - 'Actuation', 'Refsafe', 'Sensor', 'Midphase', 'Eulerdamp', 'AutoReset', - 'NativeCCD', 'Island' + 'Constraint', 'Equality', 'Frictionloss', 'Limit', 'Contact', + 'Spring', 'Damper', 'Gravity', 'Clampctrl', 'Warmstart', + 'Filterparent', 'Actuation', 'Refsafe', 'Sensor', 'Midphase', + 'Eulerdamp', 'AutoReset', 'NativeCCD', 'Island', 'MultiCCD', ]); expect(mujoco.mjRNDSTRING).toEqual([ ['Shadow', '1', 'S'], ['Wireframe', '0', 'W'], ['Reflection', '1', 'R'],