diff --git a/doc/APIreference.rst b/doc/APIreference.rst index 2721b3a0..05f323ce 100644 --- a/doc/APIreference.rst +++ b/doc/APIreference.rst @@ -324,7 +324,7 @@ mjtEq mjEQ_WELD, // fix relative position and orientation of two bodies mjEQ_JOINT, // couple the values of two scalar joints with cubic mjEQ_TENDON, // couple the lengths of two tendons with cubic - mjEQ_DISTANCE // fix the contact distance betweent two geoms + mjEQ_DISTANCE // unsupported, will cause an error if used } mjtEq; | Defined in `mjmodel.h `_ diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index c7688cd5..f0960356 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -4061,20 +4061,8 @@ This element constrains the length of one tendon to be a quartic polynomial of a :el-prefix:`equality/` **distance** (*) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This element constrains the nearest distance between two geoms. When the distance attribute is set to 0 the two geom -surfaces slide over each other, otherwise they slide over a virtual cushion with depth equal to the specified distance. -This mechanism is implemented as a modification to the collision detector. For geom pairs handled by the general-purpose -convex collider, large distance values in this constraint are handled approximately, due to the nature of the underlying -collision algorithm. - -:at:`name`, :at:`class`, :at:`active`, :at:`solref`, :at:`solimp` - Same as in :ref:`connect ` element. -:at:`geom1`: :at-val:`string, required` - Name of the first geom. -:at:`geom2`: :at-val:`string, required` - Name of the second geom. -:at:`distance`: :at-val:`real, "0"` - Desired distance between the two geom surfaces. The constraint solver enforces this distance softly. +Distance equality constraints were removed in MuJoCo version 2.2.2. If you are using an earlier version, please switch +to the corresponding version of the documentation. .. _tendon: diff --git a/doc/changelog.rst b/doc/changelog.rst index 497d698d..6b6e9314 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -18,9 +18,13 @@ General inaccurate. If this occurs, open the mesh in MeshLab or Blender and recalculate the faces. - Added ``azimuth`` and ``elevation`` attributes to :ref:`visual/global`, defining the initial orientation of the free camera at model load time. - - Added ``mjv_defaultFreeCamera`` which sets the default free camera, respecting the above attributes. +- Added ``mjv_defaultFreeCamera`` which sets the default free camera, respecting the above attributes. - ``simulate`` now supports taking a screenshot via a button in the File section or via ``Ctrl-P``. +Deleted/deprecated features +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Removed ``distance`` constraints. + Bug fixes ^^^^^^^^^ - Fixed rendering of some transparent geoms in reflection. diff --git a/include/mujoco/mjmodel.h b/include/mujoco/mjmodel.h index cb00f4a3..1017b0b9 100644 --- a/include/mujoco/mjmodel.h +++ b/include/mujoco/mjmodel.h @@ -163,7 +163,7 @@ typedef enum mjtEq_ { // type of equality constraint mjEQ_WELD, // fix relative position and orientation of two bodies mjEQ_JOINT, // couple the values of two scalar joints with cubic mjEQ_TENDON, // couple the lengths of two tendons with cubic - mjEQ_DISTANCE // fix the contact distance betweent two geoms + mjEQ_DISTANCE // unsupported, will cause an error if used } mjtEq; diff --git a/src/engine/engine_core_constraint.c b/src/engine/engine_core_constraint.c index 8edc29c2..35c8a6e4 100644 --- a/src/engine/engine_core_constraint.c +++ b/src/engine/engine_core_constraint.c @@ -342,11 +342,10 @@ void mj_mulJacTVec(const mjModel* m, mjData* d, mjtNum* res, const mjtNum* vec) // equality constraints void mj_instantiateEquality(const mjModel* m, mjData* d) { int issparse = mj_isSparse(m), nv = m->nv; - int oldncon, id[2], size, NV, NV2, *chain = NULL, *chain2 = NULL, *buf_ind = NULL; - mjtNum cpos[6], pos[2][3], ref[2], dif, deriv, dist; + int id[2], size, NV, NV2, *chain = NULL, *chain2 = NULL, *buf_ind = NULL; + mjtNum cpos[6], pos[2][3], ref[2], dif, deriv; mjtNum quat[4], quat1[4], quat2[4], quat3[4], axis[3]; mjtNum *jac[2], *jacdif, *data, *sparse_buf = NULL; - mjContact *con; mjMARKSTACK; // disabled or no equality contraints: return @@ -529,70 +528,7 @@ void mj_instantiateEquality(const mjModel* m, mjData* d) { break; case mjEQ_DISTANCE: - // find contacts between constrained geoms - oldncon = d->ncon; - mj_collideGeoms(m, d, id[0], id[1], 1, - mju_dist3(d->geom_xpos+3*id[0], d->geom_xpos+3*id[1])); - - // make sure we got some contacts - if (oldncon==d->ncon) { - size = 0; - break; - } - - // find smallest dist - dist = d->contact[oldncon].dist; - for (int j=1; jncon-oldncon; j++) { - if (d->contact[oldncon+j].distcontact[oldncon+j].dist; - } - } - - // collide again with adjusted distance (because libccd messes up with big margin) - d->ncon = oldncon; - mjtNum adjustment = 0.01; - mj_collideGeoms(m, d, id[0], id[1], 1, dist + adjustment); - - // make sure we still got some contacts - if (oldncon==d->ncon) { - size = 0; - break; - } - - // find smallest-dist contact - int k = 0; - dist = d->contact[oldncon].dist; - for (int j=1; jncon-oldncon; j++) - if (d->contact[oldncon+j].distcontact[oldncon+j].dist; - k = j; - } - - // move smallest-dist contact to first position, discard the rest - if (k>0) { - d->contact[oldncon] = d->contact[oldncon+k]; - } - d->ncon = oldncon+1; - con = d->contact + oldncon; - - // label contact, make sure solver does not include it - con->efc_address = -2-i; - con->exclude = 3; - - // compute position error - cpos[0] = dist - data[0]; - - // compute Jacobian difference - NV = mj_jacDifPair(m, d, chain, - m->geom_bodyid[con->geom1], m->geom_bodyid[con->geom2], - con->pos, con->pos, - jac[0], jac[1], jacdif, NULL, NULL, NULL); - - // construct contact normal Jacobian - mju_mulMatMat(jac[0], con->frame, jacdif, 1, 3, NV); - - size = 1; - break; + mju_error("distance equality constraints are no longer supported"); default: // SHOULD NOT OCCUR mju_error_i("Invalid equality constraint type %d", m->eq_type[i]); @@ -977,10 +913,7 @@ void mj_diagApprox(const mjModel* m, mjData* d) { break; case mjEQ_DISTANCE: - // body translation - b1 = m->geom_bodyid[m->eq_obj1id[id]]; - b2 = m->geom_bodyid[m->eq_obj2id[id]]; - dA[i] = m->body_invweight0[2*b1] + m->body_invweight0[2*b2]; + mju_error("distance equality constraints are no longer supported"); } break; diff --git a/src/engine/engine_core_smooth.c b/src/engine/engine_core_smooth.c index 36174dd0..b79dbea3 100644 --- a/src/engine/engine_core_smooth.c +++ b/src/engine/engine_core_smooth.c @@ -1904,11 +1904,13 @@ void mj_rnePostConstraint(const mjModel* m, mjData* d) { case mjEQ_JOINT: case mjEQ_TENDON: - case mjEQ_DISTANCE: // increment 1 row i++; break; + case mjEQ_DISTANCE: + mju_error("distance equality constraints are no longer supported"); + default: mju_error_i("Unknown constraint type type %d", m->eq_type[id]); // SHOULD NOT OCCUR } diff --git a/src/engine/engine_io.c b/src/engine/engine_io.c index d8a85059..6c74d0a7 100644 --- a/src/engine/engine_io.c +++ b/src/engine/engine_io.c @@ -1370,13 +1370,7 @@ const char* mj_validateReferences(const mjModel* m) { } break; case mjEQ_DISTANCE: - if (obj1id >= m->ngeom || obj1id < 0) { - return "Invalid model: eq_obj1id out of bounds."; - } - if (obj2id >= m->ngeom || obj2id < 0) { - return "Invalid model: eq_obj2id out of bounds."; - } - break; + return "distance equality constraints are no longer supported"; case mjEQ_WELD: case mjEQ_CONNECT: if (obj1id >= m->nbody || obj1id < 0) { diff --git a/src/xml/xml_native_reader.cc b/src/xml/xml_native_reader.cc index f2fcc6c4..488ecc03 100644 --- a/src/xml/xml_native_reader.cc +++ b/src/xml/xml_native_reader.cc @@ -1328,9 +1328,7 @@ void mjXReader::OneEquality(XMLElement* elem, mjCEquality* pequality) { break; case mjEQ_DISTANCE: - ReadAttrTxt(elem, "geom1", pequality->name1, true); - ReadAttrTxt(elem, "geom2", pequality->name2, true); - ReadAttr(elem, "distance", 1, pequality->data, text); + throw mjXError(elem, "support for distance equality contraints was removed in MuJoCo 2.2.2"); break; default: // SHOULD NOT OCCUR diff --git a/test/engine/engine_io_test.cc b/test/engine/engine_io_test.cc index 2407c37c..d555ef0f 100644 --- a/test/engine/engine_io_test.cc +++ b/test/engine/engine_io_test.cc @@ -549,7 +549,6 @@ TEST_F(ValidateReferencesTest, EqualityConstraints) { - @@ -590,18 +589,6 @@ TEST_F(ValidateReferencesTest, EqualityConstraints) { EXPECT_THAT(mj_validateReferences(model), HasSubstr("eq_obj2id")); model->eq_obj2id[1] = model->nbody - 1; - // distance constraint - model->eq_obj1id[2] = -1; - EXPECT_THAT(mj_validateReferences(model), HasSubstr("eq_obj1id")); - model->eq_obj1id[2] = model->ngeom; - EXPECT_THAT(mj_validateReferences(model), HasSubstr("eq_obj1id")); - model->eq_obj1id[2] = 1; - - model->eq_obj2id[2] = -1; - EXPECT_THAT(mj_validateReferences(model), HasSubstr("eq_obj2id")); - model->eq_obj2id[2] = model->ngeom; - EXPECT_THAT(mj_validateReferences(model), HasSubstr("eq_obj2id")); - model->eq_obj2id[2] = model->ngeom - 1; mj_deleteModel(model); } diff --git a/unity/Runtime/Components/Equality/MjDistance.cs b/unity/Runtime/Components/Equality/MjDistance.cs deleted file mode 100644 index 9a5b21f2..00000000 --- a/unity/Runtime/Components/Equality/MjDistance.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2019 DeepMind Technologies Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Xml; -using UnityEngine; - -namespace Mujoco { - - public class MjDistance : MjBaseConstraint { - public MjGeom Geom1; - public MjGeom Geom2; - protected override string _constraintName => "distance"; - - protected override void FromMjcf(XmlElement mjcf) { - Geom1 = mjcf.GetObjectReferenceAttribute("geom1"); - Geom2 = mjcf.GetObjectReferenceAttribute("geom2"); - } - - protected override void ToMjcf(XmlElement mjcf) { - if (Geom1 == null || Geom2 == null) { - throw new NullReferenceException($"Both geoms in distance {name} must be assigned."); - } - - mjcf.SetAttribute("geom1", Geom1.MujocoName); - mjcf.SetAttribute("geom2", Geom2.MujocoName); - } - - public void OnValidate() { - if (Geom1 != null && Geom1 == Geom2) { - Debug.LogError("Geom1 and Geom2 can't be the same - resetting Geom2.", this); - Geom2 = null; - } - } - } -} diff --git a/unity/Runtime/Components/Equality/MjDistance.cs.meta b/unity/Runtime/Components/Equality/MjDistance.cs.meta deleted file mode 100644 index d43611e6..00000000 --- a/unity/Runtime/Components/Equality/MjDistance.cs.meta +++ /dev/null @@ -1,13 +0,0 @@ -fileFormatVersion: 2 -guid: ad0689a32f102481fb189836c11931f9 -timeCreated: 1552309644 -licenseType: Pro -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/unity/Runtime/Importer/MjcfImporter.cs b/unity/Runtime/Importer/MjcfImporter.cs index 8af4ea29..a4afe010 100644 --- a/unity/Runtime/Importer/MjcfImporter.cs +++ b/unity/Runtime/Importer/MjcfImporter.cs @@ -296,9 +296,6 @@ public class MjcfImporter { case "tendon": equalityType = typeof(MjTendonConstraint); break; - case "distance": - equalityType = typeof(MjDistance); - break; default: Debug.Log($"The importer does not yet support equality <{node.Name}>."); break; diff --git a/unity/Tests/Editor/Components/Equality/MjDistanceTests.cs b/unity/Tests/Editor/Components/Equality/MjDistanceTests.cs deleted file mode 100644 index 466b1965..00000000 --- a/unity/Tests/Editor/Components/Equality/MjDistanceTests.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2019 DeepMind Technologies Limited -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Xml; -using NUnit.Framework; -using UnityEngine; - -namespace Mujoco { - [TestFixture] - public class MjDistanceTests { - private MjGeom _geom1; - private MjGeom _geom2; - private MjDistance _distance; - private XmlDocument _doc; - - [SetUp] - public void SetUp() { - _geom1 = new GameObject("geom1").AddComponent(); - _geom2 = new GameObject("geom2").AddComponent(); - _distance = new GameObject("distance").AddComponent(); - _doc = new XmlDocument(); - } - - [TearDown] - public void TearDown() { - UnityEngine.Object.DestroyImmediate(_distance.gameObject); - UnityEngine.Object.DestroyImmediate(_geom1.gameObject); - UnityEngine.Object.DestroyImmediate(_geom2.gameObject); - } - - [Test] - public void ErrorThrownWhenGeom1Empty() { - // This is an illegal MJCF, but the purpose of this test is to verify that if - // the user didn't assign the geom in the editor, an error will be thrown when play is hit. - _doc.LoadXml(""); - _distance.ParseMjcf(_doc.GetElementsByTagName("geom")[0] as XmlElement); - Assert.That(() => { _distance.GenerateMjcf("name", _doc); }, Throws.Exception); - } - - // In this constraint both elements are required. - [Test] - public void ErrorThrownWhenGeom2Empty() { - _doc.LoadXml(""); - _distance.ParseMjcf(_doc.GetElementsByTagName("geom")[0] as XmlElement); - Assert.That(() => { _distance.GenerateMjcf("name", _doc); }, Throws.Exception); - } - - [Test] - public void ParseAndGenerate() { - _doc.LoadXml(""); - _distance.ParseMjcf(_doc.GetElementsByTagName("distance")[0] as XmlElement); - Assert.That(_distance.Geom1, Is.EqualTo(_geom1)); - Assert.That(_distance.Geom2, Is.EqualTo(_geom2)); - var mjcf = _distance.GenerateMjcf("name", _doc); - Assert.That(mjcf.OuterXml, Does.Contain("