Rename mpr_tolerance and mpr_iterations to ccd_tolerance and ccd_iterations.

PiperOrigin-RevId: 666438658
Change-Id: I23dbdf939b9ab581f0fca4445f95c5bb36f6b463
This commit is contained in:
Yuval Tassa
2024-08-22 12:01:04 -07:00
committed by Copybara-Service
parent abe57c234b
commit 088079eff0
17 changed files with 68 additions and 59 deletions
+6 -6
View File
@@ -444,16 +444,16 @@ adjust it properly through the XML.
:at:`noslip_tolerance`: :at-val:`real, "1e-6"`
Tolerance threshold used for early termination of the Noslip solver.
.. _option-mpr_iterations:
.. _option-ccd_iterations:
:at:`mpr_iterations`: :at-val:`int, "50"`
Maximum number of iterations of the MPR algorithm used for convex mesh collisions. This rarely needs to be adjusted,
:at:`ccd_iterations`: :at-val:`int, "50"`
Maximum number of iterations of the algorithm used for convex collisions. This rarely needs to be adjusted,
except in situations where some geoms have very large aspect ratios.
.. _option-mpr_tolerance:
.. _option-ccd_tolerance:
:at:`mpr_tolerance`: :at-val:`real, "1e-6"`
Tolerance threshold used for early termination of the MPR algorithm.
:at:`ccd_tolerance`: :at-val:`real, "1e-6"`
Tolerance threshold used for early termination of the convex collision algorithm.
.. _option-sdf_iterations:
+2 -2
View File
@@ -12,7 +12,7 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`timestep<option-timestep>` | :ref:`apirate<option-apirate>` | :ref:`impratio<option-impratio>` | :ref:`tolerance<option-tolerance>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`ls_tolerance<option-ls_tolerance>` | :ref:`noslip_tolerance<option-noslip_tolerance>` | :ref:`mpr_tolerance<option-mpr_tolerance>` | :ref:`gravity<option-gravity>` | |
| | | | :ref:`ls_tolerance<option-ls_tolerance>` | :ref:`noslip_tolerance<option-noslip_tolerance>` | :ref:`ccd_tolerance<option-ccd_tolerance>` | :ref:`gravity<option-gravity>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`wind<option-wind>` | :ref:`magnetic<option-magnetic>` | :ref:`density<option-density>` | :ref:`viscosity<option-viscosity>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
@@ -20,7 +20,7 @@
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`integrator<option-integrator>` | :ref:`cone<option-cone>` | :ref:`jacobian<option-jacobian>` | :ref:`solver<option-solver>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`iterations<option-iterations>` | :ref:`ls_iterations<option-ls_iterations>` | :ref:`noslip_iterations<option-noslip_iterations>` | :ref:`mpr_iterations<option-mpr_iterations>` | |
| | | | :ref:`iterations<option-iterations>` | :ref:`ls_iterations<option-ls_iterations>` | :ref:`noslip_iterations<option-noslip_iterations>` | :ref:`ccd_iterations<option-ccd_iterations>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`sdf_iterations<option-sdf_iterations>` | :ref:`sdf_initpoints<option-sdf_initpoints>` | :ref:`actuatorgroupdisable<option-actuatorgroupdisable>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+9
View File
@@ -7,6 +7,15 @@ Upcoming version (not yet released)
General
^^^^^^^
.. admonition:: Breaking API changes
:class: attention
- The runtime options ``mpr_tolerance`` and ``mpr_iterations`` were renamed to
:ref:`ccd_tolerance<option-ccd_tolerance>` and :ref:`ccd_iterations<option-ccd_iterations>`, both in XML and in
the :ref:`mjOption` struct. This is because the new convex collision detection pipeline (see below) does not use
the MPR algorithm. The semantics of these options remain identical.
- Added the :ref:`nativeccd<option-flag-nativeccd>` flag. When this flag is enabled, general convex collision
detection is handled natively, as opposed to using `libccd <https://github.com/danfis/libccd>`__. This feature is in
early stages of testing.
+2 -2
View File
@@ -734,7 +734,7 @@ struct mjOption_ { // physics options
mjtNum tolerance; // main solver tolerance
mjtNum ls_tolerance; // CG/Newton linesearch tolerance
mjtNum noslip_tolerance; // noslip solver tolerance
mjtNum mpr_tolerance; // MPR solver tolerance
mjtNum ccd_tolerance; // convex collision solver tolerance
// physical constants
mjtNum gravity[3]; // gravitational acceleration
@@ -757,7 +757,7 @@ struct mjOption_ { // physics options
int iterations; // maximum number of main solver iterations
int ls_iterations; // maximum number of CG/Newton linesearch iterations
int noslip_iterations; // maximum number of noslip solver iterations
int mpr_iterations; // maximum number of MPR solver iterations
int ccd_iterations; // maximum number of convex collision solver iterations
int disableflags; // bit flags for disabling standard features
int enableflags; // bit flags for enabling optional features
int disableactuator; // bit flags for disabling actuators by group id
+2 -2
View File
@@ -438,7 +438,7 @@ struct mjOption_ { // physics options
mjtNum tolerance; // main solver tolerance
mjtNum ls_tolerance; // CG/Newton linesearch tolerance
mjtNum noslip_tolerance; // noslip solver tolerance
mjtNum mpr_tolerance; // MPR solver tolerance
mjtNum ccd_tolerance; // convex collision solver tolerance
// physical constants
mjtNum gravity[3]; // gravitational acceleration
@@ -461,7 +461,7 @@ struct mjOption_ { // physics options
int iterations; // maximum number of main solver iterations
int ls_iterations; // maximum number of CG/Newton linesearch iterations
int noslip_iterations; // maximum number of noslip solver iterations
int mpr_iterations; // maximum number of MPR solver iterations
int ccd_iterations; // maximum number of convex collision solver iterations
int disableflags; // bit flags for disabling standard features
int enableflags; // bit flags for enabling optional features
int disableactuator; // bit flags for disabling actuators by group id
+2 -2
View File
@@ -26,7 +26,7 @@
X( mjtNum, tolerance ) \
X( mjtNum, ls_tolerance ) \
X( mjtNum, noslip_tolerance ) \
X( mjtNum, mpr_tolerance ) \
X( mjtNum, ccd_tolerance ) \
X( mjtNum, density ) \
X( mjtNum, viscosity ) \
X( mjtNum, o_margin ) \
@@ -40,7 +40,7 @@
X( int, iterations ) \
X( int, ls_iterations ) \
X( int, noslip_iterations ) \
X( int, mpr_iterations ) \
X( int, ccd_iterations ) \
X( int, disableflags ) \
X( int, enableflags ) \
X( int, disableactuator ) \
+4 -4
View File
@@ -135,9 +135,9 @@ STRUCTS: Mapping[str, StructDecl] = dict([
doc='noslip solver tolerance',
),
StructFieldDecl(
name='mpr_tolerance',
name='ccd_tolerance',
type=ValueType(name='mjtNum'),
doc='MPR solver tolerance',
doc='convex collision solver tolerance',
),
StructFieldDecl(
name='gravity',
@@ -238,9 +238,9 @@ STRUCTS: Mapping[str, StructDecl] = dict([
doc='maximum number of noslip solver iterations',
),
StructFieldDecl(
name='mpr_iterations',
name='ccd_iterations',
type=ValueType(name='int'),
doc='maximum number of MPR solver iterations',
doc='maximum number of convex collision solver iterations',
),
StructFieldDecl(
name='disableflags',
+4 -4
View File
@@ -362,7 +362,7 @@ class Option(PyTreeNode):
tolerance: main solver tolerance
ls_tolerance: CG/Newton linesearch tolerance
noslip_tolerance: noslip solver tolerance (not used)
mpr_tolerance: MPR solver tolerance (not used)
ccd_tolerance: CCD solver tolerance (not used)
gravity: gravitational acceleration (3,)
wind: wind (for lift, drag and viscosity)
magnetic: global magnetic flux (not used)
@@ -384,7 +384,7 @@ class Option(PyTreeNode):
iterations: number of main solver iterations
ls_iterations: maximum number of CG/Newton linesearch iterations
noslip_iterations: maximum number of noslip solver iterations (not used)
mpr_iterations: maximum number of MPR solver iterations (not used)
ccd_iterations: maximum number of CCD solver iterations (not used)
disableflags: bit flags for disabling standard features
enableflags: bit flags for enabling optional features (not used)
disableactuator: bit flags for disabling actuators by group id (not used)
@@ -397,7 +397,7 @@ class Option(PyTreeNode):
tolerance: jax.Array
ls_tolerance: jax.Array
noslip_tolerance: jax.Array = _restricted_to('mujoco')
mpr_tolerance: jax.Array = _restricted_to('mujoco')
ccd_tolerance: jax.Array = _restricted_to('mujoco')
gravity: jax.Array
wind: jax.Array
magnetic: jax.Array
@@ -415,7 +415,7 @@ class Option(PyTreeNode):
iterations: int
ls_iterations: int
noslip_iterations: int = _restricted_to('mujoco')
mpr_iterations: int = _restricted_to('mujoco')
ccd_iterations: int = _restricted_to('mujoco')
disableflags: DisableBit
enableflags: int
disableactuator: int
+4 -4
View File
@@ -690,8 +690,8 @@ void MakePhysicsSection(mj::Simulate* sim) {
{mjITEM_EDITNUM, "LS Tol", 2, &(opt->ls_tolerance), "1 0 0.1"},
{mjITEM_EDITINT, "Noslip Iter", 2, &(opt->noslip_iterations), "1 0 1000"},
{mjITEM_EDITNUM, "Noslip Tol", 2, &(opt->noslip_tolerance), "1 0 1"},
{mjITEM_EDITINT, "MPR Iter", 2, &(opt->mpr_iterations), "1 0 1000"},
{mjITEM_EDITNUM, "MPR Tol", 2, &(opt->mpr_tolerance), "1 0 1"},
{mjITEM_EDITINT, "CCD Iter", 2, &(opt->ccd_iterations), "1 0 1000"},
{mjITEM_EDITNUM, "CCD Tol", 2, &(opt->ccd_tolerance), "1 0 1"},
{mjITEM_EDITNUM, "API Rate", 2, &(opt->apirate), "1 0 1000"},
{mjITEM_EDITINT, "SDF Iter", 2, &(opt->sdf_iterations), "1 1 20"},
{mjITEM_EDITINT, "SDF Init", 2, &(opt->sdf_initpoints), "1 1 100"},
@@ -1886,7 +1886,7 @@ void Simulate::Sync() {
X(impratio);
X(tolerance);
X(noslip_tolerance);
X(mpr_tolerance);
X(ccd_tolerance);
X(gravity);
X(wind);
X(magnetic);
@@ -1902,7 +1902,7 @@ void Simulate::Sync() {
X(solver);
X(iterations);
X(noslip_iterations);
X(mpr_iterations);
X(ccd_iterations);
X(disableflags);
X(enableflags);
X(disableactuator);
+5 -5
View File
@@ -291,9 +291,9 @@ void mjc_support(mjtNum res[3], mjCCDObj* obj, const mjtNum dir[3]) {
// initialize CCD structure
static void mjc_initCCD(ccd_t* ccd, const mjModel* m) {
CCD_INIT(ccd);
ccd->mpr_tolerance = m->opt.mpr_tolerance;
ccd->epa_tolerance = m->opt.mpr_tolerance; // use MPR tolerance for EPA
ccd->max_iterations = m->opt.mpr_iterations;
ccd->mpr_tolerance = m->opt.ccd_tolerance;
ccd->epa_tolerance = m->opt.ccd_tolerance; // use MPR tolerance for EPA
ccd->max_iterations = m->opt.ccd_iterations;
}
@@ -1237,8 +1237,8 @@ int mjc_HFieldElem(const mjModel* m, const mjData* d, mjContact* con,
ccd.support2 = mjccd_support;
// set ccd parameters
ccd.max_iterations = m->opt.mpr_iterations;
ccd.mpr_tolerance = m->opt.mpr_tolerance;
ccd.max_iterations = m->opt.ccd_iterations;
ccd.mpr_tolerance = m->opt.ccd_tolerance;
// compute real-valued grid step, and triangulation direction
dx = (2.0*hsize[0]) / (ncol-1);
+2 -2
View File
@@ -124,7 +124,7 @@ void mj_defaultOption(mjOption* opt) {
opt->tolerance = 1e-8;
opt->ls_tolerance = 0.01;
opt->noslip_tolerance = 1e-6;
opt->mpr_tolerance = 1e-6;
opt->ccd_tolerance = 1e-6;
// physical constants
opt->gravity[0] = 0;
@@ -156,7 +156,7 @@ void mj_defaultOption(mjOption* opt) {
opt->iterations = 100;
opt->ls_iterations = 50;
opt->noslip_iterations = 0;
opt->mpr_iterations = 50;
opt->ccd_iterations = 50;
opt->disableflags = 0;
opt->enableflags = 0;
opt->disableactuator = 0;
+4 -4
View File
@@ -110,10 +110,10 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"option", "*", "27",
"timestep", "apirate", "impratio", "tolerance", "ls_tolerance", "noslip_tolerance",
"mpr_tolerance", "gravity", "wind", "magnetic", "density", "viscosity",
"ccd_tolerance", "gravity", "wind", "magnetic", "density", "viscosity",
"o_margin", "o_solref", "o_solimp", "o_friction",
"integrator", "cone", "jacobian",
"solver", "iterations", "ls_iterations", "noslip_iterations", "mpr_iterations",
"solver", "iterations", "ls_iterations", "noslip_iterations", "ccd_iterations",
"sdf_iterations", "sdf_initpoints", "actuatorgroupdisable"},
{"<"},
{"flag", "?", "23", "constraint", "equality", "frictionloss", "limit", "contact",
@@ -1061,7 +1061,7 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) {
ReadAttr(section, "tolerance", 1, &opt->tolerance, text);
ReadAttr(section, "ls_tolerance", 1, &opt->ls_tolerance, text);
ReadAttr(section, "noslip_tolerance", 1, &opt->noslip_tolerance, text);
ReadAttr(section, "mpr_tolerance", 1, &opt->mpr_tolerance, text);
ReadAttr(section, "ccd_tolerance", 1, &opt->ccd_tolerance, text);
ReadAttr(section, "gravity", 3, opt->gravity, text);
ReadAttr(section, "wind", 3, opt->wind, text);
ReadAttr(section, "magnetic", 3, opt->magnetic, text);
@@ -1080,7 +1080,7 @@ void mjXReader::Option(XMLElement* section, mjOption* opt) {
ReadAttrInt(section, "iterations", &opt->iterations);
ReadAttrInt(section, "ls_iterations", &opt->ls_iterations);
ReadAttrInt(section, "noslip_iterations", &opt->noslip_iterations);
ReadAttrInt(section, "mpr_iterations", &opt->mpr_iterations);
ReadAttrInt(section, "ccd_iterations", &opt->ccd_iterations);
ReadAttrInt(section, "sdf_iterations", &opt->sdf_iterations);
ReadAttrInt(section, "sdf_initpoints", &opt->sdf_initpoints);
+2 -2
View File
@@ -940,7 +940,7 @@ void mjXWriter::Option(XMLElement* root) {
WriteAttr(section, "tolerance", 1, &model->option.tolerance, &opt.tolerance);
WriteAttr(section, "ls_tolerance", 1, &model->option.ls_tolerance, &opt.ls_tolerance);
WriteAttr(section, "noslip_tolerance", 1, &model->option.noslip_tolerance, &opt.noslip_tolerance);
WriteAttr(section, "mpr_tolerance", 1, &model->option.mpr_tolerance, &opt.mpr_tolerance);
WriteAttr(section, "ccd_tolerance", 1, &model->option.ccd_tolerance, &opt.ccd_tolerance);
WriteAttr(section, "gravity", 3, model->option.gravity, opt.gravity);
WriteAttr(section, "wind", 3, model->option.wind, opt.wind);
WriteAttr(section, "magnetic", 3, model->option.magnetic, opt.magnetic);
@@ -963,7 +963,7 @@ void mjXWriter::Option(XMLElement* root) {
WriteAttrInt(section, "iterations", model->option.iterations, opt.iterations);
WriteAttrInt(section, "ls_iterations", model->option.ls_iterations, opt.ls_iterations);
WriteAttrInt(section, "noslip_iterations", model->option.noslip_iterations, opt.noslip_iterations);
WriteAttrInt(section, "mpr_iterations", model->option.mpr_iterations, opt.mpr_iterations);
WriteAttrInt(section, "ccd_iterations", model->option.ccd_iterations, opt.ccd_iterations);
WriteAttrInt(section, "sdf_iterations", model->option.sdf_iterations, opt.sdf_iterations);
WriteAttrInt(section, "sdf_initpoints", model->option.sdf_initpoints, opt.sdf_initpoints);
+2 -2
View File
@@ -5008,7 +5008,7 @@ public unsafe struct mjOption_ {
public double tolerance;
public double ls_tolerance;
public double noslip_tolerance;
public double mpr_tolerance;
public double ccd_tolerance;
public fixed double gravity[3];
public fixed double wind[3];
public fixed double magnetic[3];
@@ -5025,7 +5025,7 @@ public unsafe struct mjOption_ {
public int iterations;
public int ls_iterations;
public int noslip_iterations;
public int mpr_iterations;
public int ccd_iterations;
public int disableflags;
public int enableflags;
public int disableactuator;
+8 -8
View File
@@ -190,9 +190,9 @@ public struct MjOptionStruct {
[Tooltip("Threshold used for early termination of the Noslip solver.")]
public float NoSlipTolerance;
[Tooltip("Maximum iterations for convex mesh collisions.")]
public int MprIterations;
public int CcdIterations;
[Tooltip("Threshold used for early termination of the MPR algorithm.")]
public float MprTolerance;
public float CcdTolerance;
public MjcfOptionFlag Flag;
@@ -214,8 +214,8 @@ public struct MjOptionStruct {
Tolerance = 1e-8f,
NoSlipIterations = 0,
NoSlipTolerance = 1e-6f,
MprIterations = 50,
MprTolerance = 1e-6f,
CcdIterations = 50,
CcdTolerance = 1e-6f,
Flag = MjcfOptionFlag.Default
};
@@ -258,8 +258,8 @@ public struct MjOptionStruct {
NoSlipIterations = (int)mjcf.GetFloatAttribute(
"noslip_iterations", localDefault.NoSlipIterations);
NoSlipTolerance = mjcf.GetFloatAttribute("noslip_tolerance", localDefault.NoSlipTolerance);
MprIterations = (int)mjcf.GetFloatAttribute("mpr_iterations", localDefault.MprIterations);
MprTolerance = mjcf.GetFloatAttribute("mpr_tolerance", localDefault.MprTolerance);
CcdIterations = (int)mjcf.GetFloatAttribute("ccd_iterations", localDefault.CcdIterations);
CcdTolerance = mjcf.GetFloatAttribute("ccd_tolerance", localDefault.CcdTolerance);
var flagElements = mjcf.GetElementsByTagName("flag");
if (flagElements.Count == 1) {
@@ -291,8 +291,8 @@ public struct MjOptionStruct {
mjcf.SetAttribute("tolerance", MjEngineTool.MakeLocaleInvariant($"{Tolerance}"));
mjcf.SetAttribute("noslip_iterations", MjEngineTool.MakeLocaleInvariant($"{NoSlipIterations}"));
mjcf.SetAttribute("noslip_tolerance", MjEngineTool.MakeLocaleInvariant($"{NoSlipTolerance}"));
mjcf.SetAttribute("mpr_iterations", MjEngineTool.MakeLocaleInvariant($"{MprIterations}"));
mjcf.SetAttribute("mpr_tolerance", MjEngineTool.MakeLocaleInvariant($"{MprTolerance}"));
mjcf.SetAttribute("ccd_iterations", MjEngineTool.MakeLocaleInvariant($"{CcdIterations}"));
mjcf.SetAttribute("ccd_tolerance", MjEngineTool.MakeLocaleInvariant($"{CcdTolerance}"));
var flags = (XmlElement)mjcf.AppendChild(
mjcf.OwnerDocument.CreateElement("flag"));
@@ -56,8 +56,8 @@ public class MjGlobalSettingsGenerationTests {
_settings.GlobalOptions.Tolerance = 3.4f;
_settings.GlobalOptions.NoSlipIterations = 5;
_settings.GlobalOptions.NoSlipTolerance = 6.7f;
_settings.GlobalOptions.MprIterations = 8;
_settings.GlobalOptions.MprTolerance = 0.9f;
_settings.GlobalOptions.CcdIterations = 8;
_settings.GlobalOptions.CcdTolerance = 0.9f;
_settings.GlobalSizes.Memory = "1M";
_settings.GlobalsToMjcf(_root);
@@ -77,8 +77,8 @@ public class MjGlobalSettingsGenerationTests {
Assert.That(_doc.OuterXml, Does.Contain(@"tolerance=""3.4"""));
Assert.That(_doc.OuterXml, Does.Contain(@"noslip_iterations=""5"""));
Assert.That(_doc.OuterXml, Does.Contain(@"noslip_tolerance=""6.7"""));
Assert.That(_doc.OuterXml, Does.Contain(@"mpr_iterations=""8"""));
Assert.That(_doc.OuterXml, Does.Contain(@"mpr_tolerance=""0.9"""));
Assert.That(_doc.OuterXml, Does.Contain(@"ccd_iterations=""8"""));
Assert.That(_doc.OuterXml, Does.Contain(@"ccd_tolerance=""0.9"""));
Assert.That(_doc.OuterXml, Does.Contain(@"memory=""1M"""));
}
@@ -147,8 +147,8 @@ public class MjGlobalSettingsParsingTests {
_option.SetAttribute("tolerance", "3.4");
_option.SetAttribute("noslip_iterations", "5");
_option.SetAttribute("noslip_tolerance", "6.7");
_option.SetAttribute("mpr_iterations", "8");
_option.SetAttribute("mpr_tolerance", "0.9");
_option.SetAttribute("ccd_iterations", "8");
_option.SetAttribute("ccd_tolerance", "0.9");
_flag.SetAttribute("gravity", "disable");
@@ -172,8 +172,8 @@ public class MjGlobalSettingsParsingTests {
Assert.That(_settings.GlobalOptions.Tolerance, Is.EqualTo(3.4f));
Assert.That(_settings.GlobalOptions.NoSlipIterations, Is.EqualTo(5));
Assert.That(_settings.GlobalOptions.NoSlipTolerance, Is.EqualTo(6.7f));
Assert.That(_settings.GlobalOptions.MprIterations, Is.EqualTo(8));
Assert.That(_settings.GlobalOptions.MprTolerance, Is.EqualTo(0.9f));
Assert.That(_settings.GlobalOptions.CcdIterations, Is.EqualTo(8));
Assert.That(_settings.GlobalOptions.CcdTolerance, Is.EqualTo(0.9f));
Assert.That(_settings.GlobalOptions.Flag.Gravity, Is.EqualTo(EnableDisableFlag.disable));
@@ -74,8 +74,8 @@ public class MjcfGenerationContextTests {
Assert.That(mjcf.OuterXml, Does.Contain("tolerance"));
Assert.That(mjcf.OuterXml, Does.Contain("noslip_iterations"));
Assert.That(mjcf.OuterXml, Does.Contain("noslip_tolerance"));
Assert.That(mjcf.OuterXml, Does.Contain("mpr_iterations"));
Assert.That(mjcf.OuterXml, Does.Contain("mpr_tolerance"));
Assert.That(mjcf.OuterXml, Does.Contain("ccd_iterations"));
Assert.That(mjcf.OuterXml, Does.Contain("ccd_tolerance"));
}
[Test]