diff --git a/CMakeLists.txt b/CMakeLists.txt index f7da3fcd..c1ac72a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ set(MSVC_INCREMENTAL_DEFAULT ON) project( mujoco - VERSION 3.1.5 + VERSION 3.1.6 DESCRIPTION "MuJoCo Physics Simulator" HOMEPAGE_URL "https://mujoco.org" ) diff --git a/README.md b/README.md index ecd22c72..7ce14c2d 100644 --- a/README.md +++ b/README.md @@ -50,16 +50,17 @@ your machine. If you are a Python user, you might want to start with our tutorial notebooks running on Google Colab: - - The **introductory tutorial** teaches MuJoCo basics: + - The **introductory** tutorial teaches MuJoCo basics: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/python/tutorial.ipynb) - The **LQR** tutorial synthesizes a linear-quadratic controller, balancing a humanoid on one leg: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/python/LQR.ipynb) - The **least-squares** tutorial explains how to use the Python-based nonlinear least-squares solver: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/python/least_squares.ipynb) - The **MJX** tutorial provides usage examples of - [MuJoCo XLA](https://mujoco.readthedocs.io/en/stable/mjx.html), a branch of MuJoCo written in - JAX: + [MuJoCo XLA](https://mujoco.readthedocs.io/en/stable/mjx.html), a branch of MuJoCo written in JAX: [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/mjx/tutorial.ipynb) + - The **differentiable physics** tutorial trains locomotion policies with analytical gradients automatically derived from MuJoCo's physics step: + [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/google-deepmind/mujoco/blob/main/mjx/training_apg.ipynb) ## Installation diff --git a/cmake/MujocoDependencies.cmake b/cmake/MujocoDependencies.cmake index 44962272..4efe7c87 100644 --- a/cmake/MujocoDependencies.cmake +++ b/cmake/MujocoDependencies.cmake @@ -27,7 +27,7 @@ set(MUJOCO_DEP_VERSION_tinyobjloader CACHE STRING "Version of `tinyobjloader` to be fetched." ) set(MUJOCO_DEP_VERSION_MarchingCubeCpp - 5b79e5d6bded086a0abe276a4b5a69fc17ae9bf1 + f03a1b3ec29b1d7d865691ca8aea4f1eb2c2873d CACHE STRING "Version of `MarchingCubeCpp` to be fetched." ) set(MUJOCO_DEP_VERSION_ccd @@ -44,7 +44,7 @@ set(MUJOCO_DEP_VERSION_Eigen3 ) set(MUJOCO_DEP_VERSION_abseil - 2f9e432cce407ce0ae50676696666f33a77d42ac # LTS 20240116.1 + d7aaad83b488fd62bd51c81ecf16cd938532cc0a # LTS 20240116.2 CACHE STRING "Version of `abseil` to be fetched." ) diff --git a/dist/mujoco.rc b/dist/mujoco.rc index 51760163..6ae69239 100644 --- a/dist/mujoco.rc +++ b/dist/mujoco.rc @@ -1,6 +1,6 @@ 1 VERSIONINFO -FILEVERSION 3,1,5,0 -PRODUCTVERSION 3,1,5,0 +FILEVERSION 3,1,6,0 +PRODUCTVERSION 3,1,6,0 FILEOS 0x4 FILETYPE 0x1 { @@ -9,9 +9,9 @@ FILETYPE 0x1 BLOCK "040904b0" { VALUE "ProductName", "MuJoCo" - VALUE "ProductVersion", "3.1.5" + VALUE "ProductVersion", "3.1.6" VALUE "FileDescription", "MuJoCo" - VALUE "FileVersion", "3.1.5" + VALUE "FileVersion", "3.1.6" VALUE "InternalName", "mujoco.dll" VALUE "OriginalFilename", "mujoco.dll" VALUE "CompanyName", "Google DeepMind" diff --git a/dist/simulate.rc b/dist/simulate.rc index 636f1d2f..68633346 100644 --- a/dist/simulate.rc +++ b/dist/simulate.rc @@ -1,8 +1,8 @@ MUJOCO ICON "mujoco.ico" 1 VERSIONINFO -FILEVERSION 3,1,5,0 -PRODUCTVERSION 3,1,5,0 +FILEVERSION 3,1,6,0 +PRODUCTVERSION 3,1,6,0 FILEOS 0x4 FILETYPE 0x1 { @@ -11,9 +11,9 @@ FILETYPE 0x1 BLOCK "040904b0" { VALUE "ProductName", "MuJoCo" - VALUE "ProductVersion", "3.1.5" + VALUE "ProductVersion", "3.1.6" VALUE "FileDescription", "MuJoCo" - VALUE "FileVersion", "3.1.5" + VALUE "FileVersion", "3.1.6" VALUE "InternalName", "simulate.exe" VALUE "OriginalFilename", "simulate.exe" VALUE "CompanyName", "Google DeepMind" diff --git a/doc/APIreference/APIglobals.rst b/doc/APIreference/APIglobals.rst index 993d47f8..9f534b5a 100644 --- a/doc/APIreference/APIglobals.rst +++ b/doc/APIreference/APIglobals.rst @@ -522,7 +522,7 @@ shown in the table below. Their names are in the format ``mjKEY_XXX``. They corr - Maximum number of UI rectangles. Defined in `mjui.h `_. * - ``mjVERSION_HEADER`` - - 315 + - 316 - The version of the MuJoCo headers; changes with every release. This is an integer equal to 100x the software version, so 210 corresponds to version 2.1. Defined in mujoco.h. The API function :ref:`mj_version` returns a number with the same meaning but for the compiled library. diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index 182f708e..7bc60256 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -57,27 +57,27 @@ Main simulation These are the main entry points to the simulator. Most users will only need to call :ref:`mj_step`, which computes everything and advanced the simulation state by one time step. Controls and applied forces must either be set in advance -(in mjData.{ctrl, qfrc_applied, xfrc_applied}), or a control callback :ref:`mjcb_control` must be installed which will be -called just before the controls and applied forces are needed. Alternatively, one can use :ref:`mj_step1` and +(in ``mjData.{ctrl, qfrc_applied, xfrc_applied}``), or a control callback :ref:`mjcb_control` must be installed which +will be called just before the controls and applied forces are needed. Alternatively, one can use :ref:`mj_step1` and :ref:`mj_step2` which break down the simulation pipeline into computations that are executed before and after the controls are needed; in this way one can set controls that depend on the results from :ref:`mj_step1`. Keep in mind -though that the RK4 solver does not work with mj_step1/2. +though that the RK4 solver does not work with mj_step1/2. See :ref:`Pipeline` for a more detailed description. mj_forward performs the same computations as :ref:`mj_step` but without the integration. It is useful after loading or resetting a model (to put the entire mjData in a valid state), and also for out-of-order computations that involve sampling or finite-difference approximations. -mj_inverse runs the inverse dynamics, and writes its output in ``mjData.qfrc_inverse``. Note that ``mjData.qacc`` must -be set before calling this function. Given the state (qpos, qvel, act), mj_forward maps from force to acceleration, +:ref:`mj_inverse` runs the inverse dynamics, and writes its output in ``mjData.qfrc_inverse``. Note that ``mjData.qacc`` +must be set before calling this function. Given the state (qpos, qvel, act), mj_forward maps from force to acceleration, while mj_inverse maps from acceleration to force. Mathematically these functions are inverse of each other, but numerically this may not always be the case because the forward dynamics rely on a constraint optimization algorithm which is usually terminated early. The difference between the results of forward and inverse dynamics can be computed -with the function :ref:`mj_compareFwdInv`, which can be thought of as another solver accuracy check (as well as a general -sanity check). +with the function :ref:`mj_compareFwdInv`, which can be thought of as another solver accuracy check (as well as a +general sanity check). The skip version of :ref:`mj_forward` and :ref:`mj_inverse` are useful for example when qpos was unchanged but qvel was changed (usually in the context of finite differencing). Then there is no point repeating the computations that only -depend on qpos. Calling the dynamics with skipstage = mjSTAGE_POS will achieve these savings. +depend on qpos. Calling the dynamics with skipstage = :ref:`mjSTAGE_POS` will achieve these savings. .. _mj_step: @@ -249,8 +249,8 @@ degrees-of-freedom and a given point. Given a body specified by its integer id ( frame (``point``) treated as attached to the body, the Jacobian has both translational (``jacp``) and rotational (``jacr``) components. Passing ``NULL`` for either pointer will skip that part of the computation. Each component is a 3-by-nv matrix. Each row of this matrix is the gradient of the corresponding coordinate of the specified point with -respect to the degrees-of-freedom. The ability to compute end-effector Jacobians efficiently and analytically is one of -the advantages of working in minimal coordinates. +respect to the degrees-of-freedom. The :ref:`pipeline stages` required for Jacobian computations to be +consistenst with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos`. .. _mj_jacBody: @@ -408,6 +408,28 @@ Compute object 6D acceleration (rot:lin) in object-centered frame, world/local o sensors are not present in the model, :ref:`mj_rnePostConstraint` must be manually called in order to calculate mjData.cacc -- the total body acceleration, including contributions from the constraint solver. +.. _mj_geomDistance: + +mj_geomDistance +~~~~~~~~~~~~~~~ + +.. mujoco-include:: mj_geomDistance + +Returns the smallest signed distance between two geoms and optionally the segment from ``geom1`` to ``geom2``. +Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is +found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0). + +.. admonition:: Positive ``distmax`` values + :class: note + + .. TODO: b/339596989 - Improve mjc_Convex. + + For some colliders, a large, positive ``distmax`` will result in an accurate measurement. However, for collision + pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely innacurate. + This is considered a bug to be fixed in a future release. + In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of + `engine_collision_driver.c `__. + .. _mj_contactForce: mj_contactForce diff --git a/doc/APIreference/functions_override.rst b/doc/APIreference/functions_override.rst index ea7ec0cc..9f39042d 100644 --- a/doc/APIreference/functions_override.rst +++ b/doc/APIreference/functions_override.rst @@ -33,27 +33,27 @@ The model and all files referenced in it can be loaded from disk or from a VFS w These are the main entry points to the simulator. Most users will only need to call :ref:`mj_step`, which computes everything and advanced the simulation state by one time step. Controls and applied forces must either be set in advance -(in mjData.{ctrl, qfrc_applied, xfrc_applied}), or a control callback :ref:`mjcb_control` must be installed which will be -called just before the controls and applied forces are needed. Alternatively, one can use :ref:`mj_step1` and +(in ``mjData.{ctrl, qfrc_applied, xfrc_applied}``), or a control callback :ref:`mjcb_control` must be installed which +will be called just before the controls and applied forces are needed. Alternatively, one can use :ref:`mj_step1` and :ref:`mj_step2` which break down the simulation pipeline into computations that are executed before and after the controls are needed; in this way one can set controls that depend on the results from :ref:`mj_step1`. Keep in mind -though that the RK4 solver does not work with mj_step1/2. +though that the RK4 solver does not work with mj_step1/2. See :ref:`Pipeline` for a more detailed description. mj_forward performs the same computations as :ref:`mj_step` but without the integration. It is useful after loading or resetting a model (to put the entire mjData in a valid state), and also for out-of-order computations that involve sampling or finite-difference approximations. -mj_inverse runs the inverse dynamics, and writes its output in ``mjData.qfrc_inverse``. Note that ``mjData.qacc`` must -be set before calling this function. Given the state (qpos, qvel, act), mj_forward maps from force to acceleration, +:ref:`mj_inverse` runs the inverse dynamics, and writes its output in ``mjData.qfrc_inverse``. Note that ``mjData.qacc`` +must be set before calling this function. Given the state (qpos, qvel, act), mj_forward maps from force to acceleration, while mj_inverse maps from acceleration to force. Mathematically these functions are inverse of each other, but numerically this may not always be the case because the forward dynamics rely on a constraint optimization algorithm which is usually terminated early. The difference between the results of forward and inverse dynamics can be computed -with the function :ref:`mj_compareFwdInv`, which can be thought of as another solver accuracy check (as well as a general -sanity check). +with the function :ref:`mj_compareFwdInv`, which can be thought of as another solver accuracy check (as well as a +general sanity check). The skip version of :ref:`mj_forward` and :ref:`mj_inverse` are useful for example when qpos was unchanged but qvel was changed (usually in the context of finite differencing). Then there is no point repeating the computations that only -depend on qpos. Calling the dynamics with skipstage = mjSTAGE_POS will achieve these savings. +depend on qpos. Calling the dynamics with skipstage = :ref:`mjSTAGE_POS` will achieve these savings. .. _Initialization: @@ -165,8 +165,8 @@ degrees-of-freedom and a given point. Given a body specified by its integer id ( frame (``point``) treated as attached to the body, the Jacobian has both translational (``jacp``) and rotational (``jacr``) components. Passing ``NULL`` for either pointer will skip that part of the computation. Each component is a 3-by-nv matrix. Each row of this matrix is the gradient of the corresponding coordinate of the specified point with -respect to the degrees-of-freedom. The ability to compute end-effector Jacobians efficiently and analytically is one of -the advantages of working in minimal coordinates. +respect to the degrees-of-freedom. The :ref:`pipeline stages` required for Jacobian computations to be +consistenst with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos`. .. _mj_jacBody: @@ -180,6 +180,23 @@ generalized velocities to subtree angular momentum. More precisely if :math:`h` body index ``body`` in ``mjData.subtree_angmom`` (reported by the :ref:`subtreeangmom` sensor) and :math:`\dot q` is the generalized velocity ``mjData.qvel``, then :math:`h = H \dot q`. +.. _mj_geomDistance: + +Returns the smallest signed distance between two geoms and optionally the segment from ``geom1`` to ``geom2``. +Returned distances are bounded from above by ``distmax``. |br| If no collision of distance smaller than ``distmax`` is +found, the function will return ``distmax`` and ``fromto``, if given, will be set to (0, 0, 0, 0, 0, 0). + +.. admonition:: Positive ``distmax`` values + :class: note + + .. TODO: b/339596989 - Improve mjc_Convex. + + For some colliders, a large, positive ``distmax`` will result in an accurate measurement. However, for collision + pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely innacurate. + This is considered a bug to be fixed in a future release. + In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of + `engine_collision_driver.c `__. + .. _mj_mulM: This function multiplies the joint-space inertia matrix stored in mjData.qM by a vector. qM has a custom sparse format diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index f166401b..0b01759a 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -214,6 +214,10 @@ and namespaced appropriately. Detailed examples of models using replicate can be + + + + Results in this model: @@ -227,6 +231,13 @@ and namespaced appropriately. Detailed examples of models using replicate can be + + + + + + + .. _include: @@ -301,8 +312,8 @@ adjust it properly through the XML. setting of solimp determines a single impedance value for all contact dimensions, which is then modulated by this attribute. Settings larger than 1 cause friction forces to be "harder" than normal forces, having the general effect of preventing slip, without increasing the actual friction coefficient. For pyramidal friction cones the situation is - more complex because the pyramidal approximation mixes normal and frictional dimensions within each basis vector; but - the overall effect of this attribute is qualitatively similar. + more complex because the pyramidal approximation mixes normal and frictional dimensions within each basis vector; it + is not recommended to use high impratio values with pyramidal cones. .. _option-gravity: @@ -1088,6 +1099,8 @@ specified with OBJ files and MSH files, as well as explicitly in the XML with th STL files. These mechanism cannot be mixed. So if you have an STL mesh, the only way to add texture coordinates to it is to convert to one of the other supported formats. +.. _legacy-msh-docs: + MSH file format The binary MSH file starts with 4 integers specifying the number of vertex positions (nvertex), vertex normals (nnormal), vertex texture coordinates (ntexcoord), and vertex indices making up the faces (nface), followed by the @@ -2274,7 +2287,8 @@ helps clarify the role of bodies and geoms in MuJoCo. along both axes of the tangent plane. The second number is the torsional friction, acting around the contact normal. The third number is the rolling friction, acting around both axes of the tangent plane. The friction parameters for the contact pair are combined depending on the solmix and priority attributes, as explained in :ref:`Contact - parameters `. + parameters `. See the general :ref:`Contact` section for descriptions of the semantics of this + attribute. .. _body-geom-mass: @@ -4261,11 +4275,15 @@ joint types (slide and hinge) can be used. .. _equality-joint-polycoef: :at:`polycoef`: :at-val:`real(5), "0 1 0 0 0"` - Coefficients a0 ... a4 of the quartic polynomial. If the two joint values are y and x, and their reference positions - (corresponding to the joint values in the initial model configuration) are y0 and x0, the constraint is: - y-y0 = a0 + a1*(x-x0) + a2*(x-x0)^2 + a3*(x-x0)^3 + a4*(x-x0)^4. - Omitting the second joint is equivalent to setting x = x0, in which case the constraint is y = y0 + a0. + Coefficients :math:`a_0 \ldots a_4` of the quartic polynomial. If the joint values of :at:`joint1` and :at:`joint2` + are respectively :math:`y` and :math:`x`, and their reference positions (corresponding to the joint values in the + initial model configuration) are :math:`y_0` and :math:`x_0`, the constraint is: + .. math:: + y-y_0 = a_0 + a_1(x-x_0) + a_2(x-x_0)^2 + a_3(x-x_0)^3 + a_4(x-x_0)^4 + + Omitting :at:`joint2` is equivalent to setting :math:`x = x_0`, in which case the constraint is + :math:`y = y_0 + a_0`. .. _equality-tendon: @@ -4301,7 +4319,7 @@ This element constrains the length of one tendon to be a quartic polynomial of a .. _equality-tendon-polycoef: :at:`polycoef`: :at-val:`real(5), "0 1 0 0 0"` - Same as in the equality/ :ref:`joint ` element above, but applied to tendon lengths instead of joint + Same as in the :ref:`equality/joint ` element above, but applied to tendon lengths instead of joint positions. @@ -4958,15 +4976,16 @@ This element does not have custom attributes. It only has common attributes, whi :el-prefix:`actuator/` |-| **position** (*) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This element creates a position servo. The underlying :el:`general` attributes are set as follows: +This element creates a position servo with an optional first-order filter. The underlying :el:`general` attributes are +set as follows: -========= ======= ========= ========= -Attribute Setting Attribute Setting -========= ======= ========= ========= -dyntype none dynprm 1 0 0 -gaintype fixed gainprm kp 0 0 -biastype affine biasprm 0 -kp -kv -========= ======= ========= ========= +========= =================== ========= ============= +Attribute Setting Attribute Setting +========= =================== ========= ============= +dyntype none or filterexact dynprm timeconst 0 0 +gaintype fixed gainprm kp 0 0 +biastype affine biasprm 0 -kp -kv +========= =================== ========= ============= This element has one custom attribute in addition to the common attributes: @@ -5026,6 +5045,29 @@ This element has one custom attribute in addition to the common attributes: Damping applied by the actuator. When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators`. +.. _actuator-position-dampratio: + +:at:`dampratio`: :at-val:`real, "0"` + Damping applied by the actuator, using damping ratio units. + This attribute is exclusive with :at:`kv` and has similar meaning, but instead of units of force/velocity, the units + are :math:`2 \sqrt{k_p \cdot m}`, corresponding to a harmonic oscillator's + `damping ratio `__. + A value of 1 corresponds to a *critically damped* oscillator, which often produces desirable behavior. + Values smaller or larger than 1 correspond to underdamped and overdamped oscillations, respectively. + The mass :math:`m` is computed at the reference configuration ``mjModel.qpos0``, taking into account joint + :ref:`armature `. + However, passive :ref:`damping ` or :ref:`frictionloss ` in the affected + joints are not taken into account; if they are non-negligible, :at:`dampratio` values smaller than 1 might be + required to achieve desirable motion. + When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators`. + +.. _actuator-position-timeconst: + +:at:`timeconst`: :at-val:`real, "0"` + Time-constant of optional first-order filter. If larger than zero, the actuator uses the :at:`filterexact` + :ref:`dynamics type`, if zero (the default) no filter is used. + + .. _actuator-position-inheritrange: :at:`inheritrange`: :at-val:`real, "0"` @@ -5188,6 +5230,11 @@ This element has one custom attribute in addition to the common attributes: Damping applied by the actuator. When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators`. +.. _actuator-intvelocity-dampratio: + +:at:`dampratio`: :at-val:`real, "0"` + See :ref:`position/dampratio`. + .. _actuator-intvelocity-inheritrange: :at:`inheritrange`: :at-val:`real, "0"` @@ -6720,6 +6767,186 @@ The presence of this sensor in a model triggers a call to :ref:`mj_subtreeVel` d :at:`body`: :at-val:`string, required` Name of the body where the kinematic subtree is rooted. +.. _collision-sensors: + +collision sensors +^^^^^^^^^^^^^^^^^ + +The following 3 sensor types, :ref:`sensor/distance`, :ref:`sensor/normal` and +:ref:`sensor/fromto`, respectively measure the distance, normal direction and line segment of the +smallest signed distance between the surfaces of two geoms using the narrow-phase geom-geom colliders. The collision +computation is always performed, independently of the standard collision :ref:`selection and filtering` +pipeline. These 3 sensors share some common properties: + +.. _collision-sensors-cutoff: + +:at:`cutoff` + For most sensors, the :at:`cutoff` attribute simply defines a clipping operation on sensor values. For collision + sensors, it defines the maximum distance at which collisions will be detected, corresponding to the ``dismax`` + argument of :ref:`mj_geomDistance`. For example, at the default value of 0, only negative distances (corresponding + to geom-geom penetration) will be reported by :ref:`sensor/distance`. + In order to determine collision properties of non-penetrating geom pairs, a positive :at:`cutoff` is required. + + .. admonition:: Positive cutoff values + :class: note + + .. TODO: b/339596989 - Improve mjc_Convex. + + For some colliders, a positive :at:`cutoff` will result in an accurate measurement. However, for collision + pairs which use the general ``mjc_Convex`` collider, the result will be approximate and likely innacurate. + This is considered a bug to be fixed in a future release. + In order to determine whether a geom pair uses ``mjc_Convex``, inspect the table at the top of + `engine_collision_driver.c `__. + +:at:`geom1`, :at:`geom2`, :at:`body1`, :at:`body2` + For all 3 collision sensor types, the two colliding geoms can be specified explicitly using the :at:`geom1` and + :at:`geom2` attributes or implicitly, using :at:`body1`, :at:`body2`. In the latter case the sensor will iterate over + all geoms of the specified body or bodies (mixed specification like :at:`geom1`, :at:`body2` are allowed), and + select the collision with the smallest signed distance. + +sequential sensors + When multiple collision sensors are defined sequentially and have identical attributes (:at:`geom1`, :at:`body1`, + :at:`geom2`, :at:`body2`, :at:`cutoff`), for example when both distance and normal are queried for the same geom + pair, the collision functions will be called once for the whole sensor block, avoiding repeated computation. + +.. _sensor-distance: + +:el-prefix:`sensor/` |-| **distance** (*) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This element creates a sensor that returns the smallest signed distance between the surfaces of two geoms. +See :ref:`collision-sensors` for more details about sensors of this type. + +.. _sensor-distance-cutoff: + +:at:`cutoff` + See :ref:`collision-sensors` for the sematics of this attribute, which is different than for other sensor categories. + If no collision is detected, the distance sensor returns the :at:`cutoff` value, so in this case + :at:`cutoff` acts as a maximum clipping value, in addition to the special semantics. + +.. _sensor-distance-geom1: + +:at:`geom1`: :at-val:`string, optional` + Name of the first geom. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-distance-geom2: + +:at:`geom2`: :at-val:`string, optional` + Name of the second geom. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-distance-body1: + +:at:`body1`: :at-val:`string, optional` + Name of the first body. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-distance-body2: + +:at:`body2`: :at-val:`string, optional` + Name of the second body. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-distance-name: + +.. _sensor-distance-noise: + +.. _sensor-distance-user: + +:at:`name`, :at:`noise`, :at:`user` + See :ref:`CSensor`. + + +.. _sensor-normal: + +:el-prefix:`sensor/` |-| **normal** (*) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This element creates a sensor that returns the normal direction of the smallest signed distance between the surfaces of +two geoms. It is guaranteed to point from the surface of geom1 to the surface of geom2, though note that in the case of +penetration, this direction is generally in the opposite direction to that of the centroids. +See :ref:`collision-sensors` for more details about sensors of this type. + +.. _sensor-normal-cutoff: + +:at:`cutoff` + See :ref:`collision-sensors` for the sematics of this attribute, which is different than for other sensor categories. + If no collision is detected, the :ref:`normal` sensor returns (0, 0, 0), otherwise it returns a + normalized direction vector. For this sensor, :at:`cutoff` does not lead to any clamping. + +.. _sensor-normal-geom1: + +:at:`geom1`: :at-val:`string, optional` + Name of the first geom. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-normal-geom2: + +:at:`geom2`: :at-val:`string, optional` + Name of the second geom. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-normal-body1: + +:at:`body1`: :at-val:`string, optional` + Name of the first body. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-normal-body2: + +:at:`body2`: :at-val:`string, optional` + Name of the second body. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-normal-name: + +.. _sensor-normal-noise: + +.. _sensor-normal-user: + +:at:`name`, :at:`noise`, :at:`user` + See :ref:`CSensor`. + + +.. _sensor-fromto: + +:el-prefix:`sensor/` |-| **fromto** (*) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This element creates a sensor that returns the segment defining the smallest signed distance between the surfaces of two +geoms. The segment is defined by 6 numbers (x1, y1, z1, x2, y2, z2) corresponding to two points in the world frame. +(x1, y1, z1) is on the surface of geom1, (x2, y2, z2) is on the surface of geom2. When this sensor is present and the +:ref:`mjVIS_RANGEFINDER` visualization flag is set, segments will be visualized as rangefinder rays. +See :ref:`collision-sensors` for more details about sensors of this type. + +.. _sensor-fromto-cutoff: + +:at:`cutoff` + See :ref:`collision-sensors` for the sematics of this attribute, which is different than for other sensor categories. + If no collision is detected, the :ref:`fromto` sensor returns 6 zeros. + For this sensor, :at:`cutoff` does not lead to any clamping. + +.. _sensor-fromto-geom1: + +:at:`geom1`: :at-val:`string, optional` + Name of the first geom. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-fromto-geom2: + +:at:`geom2`: :at-val:`string, optional` + Name of the second geom. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-fromto-body1: + +:at:`body1`: :at-val:`string, optional` + Name of the first body. Exactly one of (:at:`geom1`, :at:`body1`) must be specified. + +.. _sensor-fromto-body2: + +:at:`body2`: :at-val:`string, optional` + Name of the second body. Exactly one of (:at:`geom2`, :at:`body2`) must be specified. + +.. _sensor-fromto-name: + +.. _sensor-fromto-noise: + +.. _sensor-fromto-user: + +:at:`name`, :at:`noise`, :at:`user` + See :ref:`CSensor`. .. _sensor-clock: @@ -7891,6 +8118,10 @@ tendon, slidersite, cranksite. .. _default-position-kv: +.. _default-position-dampratio: + +.. _default-position-timeconst: + :el-prefix:`default/` |-| **position** (?) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7951,6 +8182,8 @@ refsite, tendon, slidersite, cranksite. .. _default-intvelocity-kv: +.. _default-intvelocity-dampratio: + :el-prefix:`default/` |-| **intvelocity** (?) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/XMLschema.rst b/doc/XMLschema.rst index cb96f80c..42a4131a 100644 --- a/doc/XMLschema.rst +++ b/doc/XMLschema.rst @@ -705,7 +705,7 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`cranksite` | :ref:`site` | :ref:`refsite` | :ref:`kp` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`kv` | | | | | +| | | | :ref:`kv` | :ref:`dampratio` | :ref:`timeconst` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| actuator |br| |_| |L| | | .. table:: | @@ -737,7 +737,7 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`slidersite` | :ref:`cranksite` | :ref:`site` | :ref:`refsite` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`kp` | :ref:`kv` | | | | +| | | | :ref:`kp` | :ref:`kv` | :ref:`dampratio` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| actuator |br| |_| |L| | | .. table:: | @@ -1163,6 +1163,33 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| sensor |br| |_| |L| | | .. table:: | +| :ref:`distance | \* | :class: mjcf-attributes | +| ` | | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`name` | :ref:`geom1` | :ref:`geom2` | :ref:`body1` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`body2` | :ref:`cutoff` | :ref:`noise` | :ref:`user` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | ++------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| |_| sensor |br| |_| |L| | | .. table:: | +| :ref:`normal | \* | :class: mjcf-attributes | +| ` | | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`name` | :ref:`geom1` | :ref:`geom2` | :ref:`body1` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`body2` | :ref:`cutoff` | :ref:`noise` | :ref:`user` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | ++------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| |_| sensor |br| |_| |L| | | .. table:: | +| :ref:`fromto | \* | :class: mjcf-attributes | +| ` | | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`name` | :ref:`geom1` | :ref:`geom2` | :ref:`body1` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`body2` | :ref:`cutoff` | :ref:`noise` | :ref:`user` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | ++------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| |_| sensor |br| |_| |L| | | .. table:: | | :ref:`clock | \* | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | @@ -1450,7 +1477,9 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`forcerange` | :ref:`gear` | :ref:`cranklength` | :ref:`user` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`group` | :ref:`kp` | :ref:`kv` | | | +| | | | :ref:`group` | :ref:`kp` | :ref:`kv` | :ref:`dampratio` | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`timeconst` | | | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| default |br| |_| |L| | | .. table:: | @@ -1474,6 +1503,8 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`user` | :ref:`group` | :ref:`kp` | :ref:`kv` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`dampratio` | | | | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| default |br| |_| |L| | | .. table:: | | :ref:`damper | ? | :class: mjcf-attributes | diff --git a/doc/changelog.rst b/doc/changelog.rst index 37fa8565..b56a0ec8 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -8,56 +8,94 @@ Upcoming version (not yet released) General ^^^^^^^ +1. Added :ref:`mj_geomDistance` for computing the shortest signed distance between two geoms and optionally a segment + connecting them. Relatedly, added the 3 sensors: :ref:`distance`, :ref:`normal`, + :ref:`fromto`. See the function and sensor documentation for details. Fixes :github:issue:`51`. +2. Improvements to position actuators: + + - Added :ref:`timeconst` attribute to the :ref:`position actuator`. + When set to a positive value, the actuator is made stateful with :at:`filterexact` dynamics. + - Added :ref:`dampratio` to both :el:`position` and :el:`intvelocity` actuators. An + alternative to the :at:`kv` attribute, it provides a convenient way to set actuator damping using natural units. + See attribute documentation for details. + +MJX +^^^ + +3. Add height-field collision support. Fixes :github:issue:`1491`. +4. Add a pre-compiled field ``mesh_convex`` to ``mjx.Model`` so that mesh properties can be vmapped over. + Fixes :github:issue:`1655`. +5. Fix a bug in convex mesh collisions, where erroneous edge contacts were being created even though face + separating axes were found. Fixes :github:issue:`1695`. + +Bug fixes +^^^^^^^^^ + +6. Fixed a bug the could cause collisions to be missed when :ref:`fusestatic` is enabled, as is + often the case for URDF imports. Fixes :github:issue:`1069`, :github:issue:`1577`. +7. Fixed a bug that was causing the visualization of SDF iterations to write outside the size of the vector storing + them. Fixes :github:issue:`1539`. + +Version 3.1.5 (May 7, 2024) +--------------------------- + +General +^^^^^^^ + .. youtube:: 5k0_wsIRAFc :align: right :width: 240px 1. Added the :ref:`replicate` to MJCF, a :ref:`meta-element` which permits to repeat a subtree with incremental translational and rotational offsets. -2. Added ``mjModel.mesh_scale``: the scaling applied to asset vertices, as specified in the +2. Enabled an internal cache in the MuJoCo compiler resulting in recompilation speedup. Currently, processed + textures, hfields, and OBJ meshes are cached. Support for Unity environments is not yet available. +3. Added ``mjModel.mesh_scale``: the scaling applied to asset vertices, as specified in the :ref:`scale` attribute. -3. Added visual properties which are ignored by the native renderer, but can be used by external renderers: +4. Added visual properties which are ignored by the native renderer, but can be used by external renderers: - :ref:`light/bulbradius` attribute and corresponding ``mjModel.light_bulbradius`` field. - :ref:`material/metallic` attribute and corresponding ``mjModel.material_metallic`` field. - :ref:`material/roughness` attribute and corresponding ``mjModel.material_roughness`` field. -4. The type of the ``size`` argument of :ref:`mj_stackAllocNum` and :ref:`mj_stackAllocInt` was changed from ``int`` +5. The type of the ``size`` argument of :ref:`mj_stackAllocNum` and :ref:`mj_stackAllocInt` was changed from ``int`` to ``size_t``. -5. Added support for gmsh format version 2.2 surface meshes in :ref:`flexcomp`. +6. Added support for gmsh format version 2.2 surface meshes in :ref:`flexcomp`. MJX ^^^ .. admonition:: Breaking API changes :class: attention - 6. Removed deprecated ``mjx.device_get_into`` and ``mjx.device_put`` functions as they lack critical new + 7. Removed deprecated ``mjx.device_get_into`` and ``mjx.device_put`` functions as they lack critical new functionality. **Migration:** Use ``mjx.get_data_into`` instead of ``mjx.device_get_into``, and ``mjx.put_data`` instead of ``mjx.device_put``. -7. Added cylinder plane collisions. -8. Added ``efc_type`` to ``mjx.Data`` and ``dim``, ``efc_address`` to ``mjx.Contact``. -9. Added ``geom`` to ``mjx.Contact`` and marked ``geom1``, ``geom2`` deprecated. -10. Added ``ne``, ``nf``, ``nl``, ``nefc``, and ``ncon`` to ``mjx.Data`` to match ``mujoco.MjData``. -11. Given the above added fields, removed ``mjx.get_params``, ``mjx.ncon``, and ``mjx.count_constraints``. -12. Changed the way meshes are organized on device to speed up collision detection when a mesh is replicated for many +8. Added cylinder plane collisions. +9. Added ``efc_type`` to ``mjx.Data`` and ``dim``, ``efc_address`` to ``mjx.Contact``. +10. Added ``geom`` to ``mjx.Contact`` and marked ``geom1``, ``geom2`` deprecated. +11. Added ``ne``, ``nf``, ``nl``, ``nefc``, and ``ncon`` to ``mjx.Data`` to match ``mujoco.MjData``. +12. Given the above added fields, removed ``mjx.get_params``, ``mjx.ncon``, and ``mjx.count_constraints``. +13. Changed the way meshes are organized on device to speed up collision detection when a mesh is replicated for many geoms. -13. Fixed a bug where capsules might be ignored in broadphase colliision checking. -14. Added cylinder collisions using SDFs. -15. Added support for all :ref:`condim `: 1, 3, 4, 6. -16. Add support functions for ``id2name`` and ``name2id``, MJX versions of :ref:`mj_id2name` and :ref:`mj_name2id`. -17. Added support for :ref:`gravcomp` and :ref:`actuatorgravcomp`. -18. Fixed a bug in ``mjx.ray`` for sometimes allowed negative distances for ray-mesh tests. +14. Fixed a bug where capsules might be ignored in broadphase colliision checking. +15. Added cylinder collisions using SDFs. +16. Added support for all :ref:`condim `: 1, 3, 4, 6. +17. Add support functions for ``id2name`` and ``name2id``, MJX versions of :ref:`mj_id2name` and :ref:`mj_name2id`. +18. Added support for :ref:`gravcomp` and :ref:`actuatorgravcomp`. +19. Fixed a bug in ``mjx.ray`` for sometimes allowed negative distances for ray-mesh tests. +20. Added a new `differentiable physics tutorial `__ that demonstrates training locomotion policies with analytical gradients + automatically derived from the MJX physics step. Contribution by :github:user:`Andrew-Luo1`. Bug fixes ^^^^^^^^^ -19. Defaults of lights were not being saved, now fixed. -20. Prevent overwriting of frame names by body names when saving an XML. Bug introduced in 3.1.4. -21. Fixed bug in Python binding of :ref:`mj_saveModel`: ``buffer`` argument was documented as optional but was actually +21. Defaults of lights were not being saved, now fixed. +22. Prevent overwriting of frame names by body names when saving an XML. Bug introduced in 3.1.4. +23. Fixed bug in Python binding of :ref:`mj_saveModel`: ``buffer`` argument was documented as optional but was actually not optional. -22. Fixed bug that prevented memory allocations larger than 2.15 GB. +24. Fixed bug that prevented memory allocations larger than 2.15 GB. Fixes :github:issue:`1606`. Version 3.1.4 (April 10th, 2024) @@ -193,7 +231,7 @@ MJX Python bindings ^^^^^^^^^^^^^^^ -12. Improved the implementation of the :ref:`rollout` module. Note the changes below are breaking, dependent +12. Improved the implementation of the :ref:`rollout` module. Note the changes below are breaking, dependent code will require modification. - Uses :ref:`mjSTATE_FULLPHYSICS` as state spec, enabling divergence detection by inspecting time. diff --git a/doc/computation/index.rst b/doc/computation/index.rst index aebb5046..eb1bf285 100644 --- a/doc/computation/index.rst +++ b/doc/computation/index.rst @@ -29,7 +29,7 @@ Robots as well as humans interact with their environment primarily through physi importance of physics modeling in robotics, machine learning, animation, virtual reality, biomechanics and other fields, there is need for simulation models of contact dynamics that are both physically accurate and computationally efficient. One application of simulation models is to assess candidate estimation and control strategies before deploying them on -physical systems. Another application is to automate the design of those strategies - usually through numerical +physical systems. Another application is to automate the design of those strategies -- usually through numerical optimization that uses simulation in an inner loop. The latter application imposes an additional constraint: the objective function defined with respect to the contact dynamics should be amenable to numerical optimization. The contact model underlying MuJoCo has benefits along these and other relevant dimensions. In the following sections we @@ -50,7 +50,7 @@ for frictional contacts there are differences. If one sees convex models as approximations to LCP, the logical question to ask is how good that approximation is. However we do not see it that way. Instead, we see both LCP models and convex models as different approximations to physical reality, each with its strengths and weaknesses. The immediate consequence of dropping strict complementarity -and replacing it with a cost is that complementarity can be violated - meaning that force and velocity in the contact +and replacing it with a cost is that complementarity can be violated -- meaning that force and velocity in the contact normal direction can be simultaneously positive, and frictional forces may not be maximally dissipative. A related phenomenon is that the only way to initiate slip is to generate some motion in the normal direction. These effects are numerically small yet undesirable. This shortcoming however has little practical relevance, because it is premised on @@ -117,7 +117,7 @@ Inverse dynamics and optimization The objective of inverse dynamics is to recover the applied force and contact force given the position, velocity and acceleration of the multi-joint system. With hard contacts this computation is impossible. Consider pushing against a wall without moving. The contact force cannot be recovered from the kinematics, unless of course we consider the -material deformations - in which case we need a soft contact model. Inverse dynamics are trivial to compute with +material deformations -- in which case we need a soft contact model. Inverse dynamics are trivial to compute with spring-damper models of contact, because in that case the contact force is only a function of position and velocity and does not depend on applied force. But this is also the reason why spring-damper models are undesirable: ignoring the applied force means that an error is introduced at each time step, and so the simulator is perpetually in @@ -125,7 +125,7 @@ error-correction mode, in turn causing instabilities. In contrast, modern contac well as all internal forces) into account when computing the contact force/impulse. But this complicates inversion. The present contact model has a uniquely-defined inverse. The inverse dynamics are in fact easier to compute than the forward dynamics, because the optimization problem becomes diagonal and decomposes into independent optimization -problems over individual contacts - which can be solved analytically. +problems over individual contacts -- which can be solved analytically. Inverse dynamics play a key role in optimization algorithms arising in system identification, estimation and control. They make it possible to treat the sequence of positions (or a parametric representation thereof) as the object being @@ -269,7 +269,7 @@ activation state :math:`w_i` with its own dynamics. The control inputs for all a the force outputs are stored in ``mjData.actuator_force``, and the activation states (if any) are stored in ``mjData.act``. -These three components of an actuator - transmission, activation dynamics, and force generation - determine how the +These three components of an actuator -- transmission, activation dynamics, and force generation -- determine how the actuator works. The user can set them independently for maximum flexibility, or use :ref:`Actuator shortcuts ` which instantiate common actuator types. @@ -736,8 +736,8 @@ properties of quaternions, differentiation with respect to :math:`q` produces ve Among other applications, equality constraints can be used to create "loop joints", i.e., joints that cannot be modeled via the kinematic tree. Gaming engines represent all joints in this way. The same can be done in MuJoCo but is not -recommended - because it leads to both slower and less accurate simulation, effectively turning MuJoCo into a gaming -engine. The only reason to represent joints with equality constraints would be to model soft joints - which can be done +recommended -- because it leads to both slower and less accurate simulation, effectively turning MuJoCo into a gaming +engine. The only reason to represent joints with equality constraints would be to model soft joints -- which can be done via the constraint solver but not via the kinematic tree. There are five types of equality constraints described next. The numbers in the headings correspond to the @@ -846,7 +846,7 @@ at the limit, and negative if the limit is violated. The constraint becomes acti constraint force depends on distance through the solver :ref:`parameters ` described later. It is possible that both the lower and the upper limits for a given joint or tendon become active. In that case they are -both included in the list of scalar constraints, however this situation should be avoided - by increasing the range or +both included in the list of scalar constraints, however this situation should be avoided -- by increasing the range or decreasing the margin. In particular, avoid using narrow ranges to approximate an equality constraint. Instead use an explicit equality constraint, and if some slack is desired make the constraint soft by adjusting the solver parameters. This is more efficient computationally, not only because it involves one scalar constraint instead of two, but also @@ -900,7 +900,8 @@ model definition. * - ``condim`` - Dimensionality of the contact force/torque in the contact frame. |br| It can be 1, 3, 4 or 6. * - ``friction`` - - Vector of friction coefficients with dimensionality ``condim-1``. + - Vector of friction coefficients with dimensionality ``condim-1``. See below for semantics of the specific + coefficients. * - ``margin`` - The distance margin used to determine if the contact should be included in the global contact array ``mjData.contact``. @@ -921,19 +922,23 @@ as defined later. The ``condim`` parameter determines the contact type, and has similar to a joint or tendon limit, but is applied to the distance between two geoms. ``condim = 3`` : 3 for elliptic, 4 for pyramidal - This is a regular frictional contact, which can generate normal force as well as tangential friction force opposing - slip. + This is a regular frictional contact, which can generate normal force as well as a tangential friction force opposing + slip. An interpertation of this number is the slope of a surface above which a flat object will begin to slip + under gravity. ``condim = 4`` : 4 for elliptic, 6 for pyramidal In addition to normal and tangential force, this contact can generate torsional friction torque opposing rotation - around the contact normal. This is useful for modeling soft fingers, and can substantially improve the stability of - simulated grasping. Keep in mind that the torsional (as well as rolling) friction coefficients have different units - from the tangential friction coefficients. + around the contact normal, corresponding to a torque generated by a contacting surface patch. This is useful for + modeling soft fingers, and can substantially improve the stability of simulated grasping. Torsional friction + coefficients have **units of length** which can be interperted as the diameter of the surface contact patch. ``condim = 6`` : 6 for elliptic, 10 for pyramidal This contact can oppose motion in all relative degrees of freedom between the two geoms. In particular it adds - rolling friction, which can be used for example to stop a ball from rolling indefinitely on a plane. It can also be - used to model rolling friction between tires and a road, and in general to stabilize contacts. + rolling friction, which can be used for example to stop a ball from rolling indefinitely on a plane. Rolling friction + in the real world results from energy dissipated by local deformations near the contact point. It can be + used to model rolling friction between tires and a road, and in general to stabilize contacts. Rolling friction + coefficients also have **units of length** which can be interperted as the depth of the local deformation within + which energy is dissipated. Note that condim cannot be 2 or 5. This is because the two tangential directions and the two rolling directions are treated as pairs. The friction coefficients within a pair can be different though, which can be used to model skating @@ -1109,7 +1114,7 @@ and the dual of the dual of a cone is the cone itself. The pyramidal friction co self-dual, but the elliptic one is not. The Huber "norm" is based on the Huber function from robust statistics: it is a quadratic around zero, and transitions -smoothly to a linear function when the absolute value of the argument crosses a threshold - in this case given by the +smoothly to a linear function when the absolute value of the argument crosses a threshold -- in this case given by the friction loss parameters. Setting :math:`\eta = \infty` recovers the quadratic norm; we use this convention for all constraint forces that are not due to friction loss. This is another instance of reverse engineering: we want to obtain interval constraints on the friction loss forces, which is non-trivial because Lagrange duality usually yields @@ -1190,7 +1195,7 @@ the constraints. We are then left with an unconstrained optimization problem ove more efficient algorithms. The reduction is based on the fact that minimization over :math:`y` in :eq:`eq:primal` comes down to finding the nearest -point on the constraint set - which is either a plane or a cone, and can be done analytically. Substituting the result, +point on the constraint set -- which is either a plane or a cone, and can be done analytically. Substituting the result, we obtain the unconstrained problem .. math:: @@ -1296,7 +1301,7 @@ because the forward dynamics need all the quantities that enter into the inverse the analytical formula. This makes it possible to implement an automatic correctness check in MuJoCo. When the flag ``fwdinv`` in ``mjModel.opt.enableflags`` is on, the forward and inverse dynamics are automatically compared at the end of each time step, and the difference is recorded in ``mjData.solver_fwdinv``. Discrepancies indicate that the forward -solver - which is numerical and is usually terminated early - is not converging well. Of course the inverse dynamics are +solver---which is numerical and is usually terminated early---is not converging well. Of course the inverse dynamics are also useful on their own, without computing the forward dynamics first. .. _soAlgorithms: @@ -1348,7 +1353,7 @@ representations of the constraint Jacobian and related matrices. can be up to 5-dimensional given our contact model. Now we optimize the quadratic cost within this ellipsoid. This is an instance of quadratically constrained quadratic programming (QCQP). Since there is only one scalar constraint (however nonlinear it may be), the dual is a scalar optimization problem over the unknown Lagrange multiplier. We - solve this problem with Newton's method applied until convergence - which in practice takes less than 10 iterations, + solve this problem with Newton's method applied until convergence -- which in practice takes less than 10 iterations, and involves small matrices. Overall this algorithm has similar behavior to PGS for pyramidal cones, but it can handle elliptic cones without approximating them. It does more work per contact, however the contact dimensionality is smaller, and these two factors roughly balance each other. @@ -1570,11 +1575,23 @@ Top level pipeline does not support the Runge Kutta integrator. - :ref:`mj_fwdPosition` invokes stages **2-11**, the position-dependent part of the pipeline. +.. _piStages: + Stages ^^^^^^ +Below we describe the pipeline stages and API functions corresponding to each stage. All functions write their outputs +into attributes of :ref:`mjData`. It is informative to compare the list below with the :ref:`mjData` struct definition, +wherein comments above blocks of attributes specify the function that computes them. Note that each stage depends on +the values computed in some or all of the previous stages. + 1. Check the positions and velocities for invalid or unacceptably large real values indicating divergence. If divergence is detected, the state is automatically reset and the corresponding warning is raised: :ref:`mj_checkPos`, :ref:`mj_checkVel` + +Position +'''''''' +The stages below compute quantities that depend on the generalized positions ``mjData.qpos``. + 2. Compute the forward kinematics. This yields the global positions and orientations of all bodies, geoms, sites, cameras and lights. It also normalizes all quaternions: :ref:`mj_kinematics`, :ref:`mj_camLight` 3. Compute the body inertias and joint axes, in global frames centered at the centers of mass of the corresponding @@ -1591,6 +1608,12 @@ Stages 11. Compute the matrices and vectors needed by the constraint solvers: :ref:`mj_projectConstraint` 12. Compute sensor data that only depends on position, and the potential energy if enabled: :ref:`mj_sensorPos`, :ref:`mj_energyPos` + +Velocity +'''''''' +The stages below compute quantities that depend on the generalized velocity ``mjData.qvel``. Due to the sequential +dependence structure of the pipeline, the actual dependence is on both ``qpos`` and ``qvel``. + 13. Compute the tendon, flex edge and actuator velocities: :ref:`mj_fwdVelocity` 14. Compute the body velocities and rates of change of the joint axes, again in the global coordinate frames centered at the subtree centers of mass: :ref:`mj_comVel` @@ -1599,6 +1622,12 @@ Stages (if required by sensors, call :ref:`mj_subtreeVel`): :ref:`mj_sensorVel` 17. Compute the reference constraint acceleration: :ref:`mj_referenceConstraint` 18. Compute the vector of Coriolis, centrifugal and gravitational forces: :ref:`mj_rne` + +Force/acceleration +'''''''''''''''''' +The stages below compute quantities that depend on :ref:`user inputs`. Due to the sequential nature +of the pipeline, the actual dependence is on the entire :ref:`integration state`. + 19. Compute the actuator forces and activation dynamics if defined: :ref:`mj_fwdActuation` 20. Compute the joint acceleration resulting from all forces except for the (still unknown) constraint forces: :ref:`mj_fwdAcceleration` @@ -1615,12 +1644,53 @@ Stages repeats the above sequence three more times, except for the optional computations which are performed only once: one of :ref:`mj_Euler`, :ref:`mj_RungeKutta`, :ref:`mj_implicit` +.. _piConsistency: + +Consistency in ``mjData`` +~~~~~~~~~~~~~~~~~~~~~~~~~ +The MuJoCo computation pipeline is entirely imperative, nothing happens automatically. This leads to behavior which +can seem unexpected to users more familiar with other paradigms. Here are two examples of intended behaviors which can +sometimes be surprising: + +- After setting :ref:`the state`, state-derived quantities do not automatically correspond to the new state. + The required stage or stages must be manually invoked. For example after setting the generalized positions + ``mjData.qpos``, Cartesian positions and orientations will not be consistent with ``qpos`` without first calling + :ref:`mj_kinematics`. +- After an :ref:`mj_step`, which terminates immediately after updating the state, quantities in ``mjData`` correspond + to the *previous* state (or more precisely, the *transition* between the previous and current state). + In particular, all position-dependent sensor values and position-dependent computations like kinematic + :ref:`Jacobians`, will be with respect to the *previous positions*. + + + +.. _piReproducibility: + +Reproducibility +~~~~~~~~~~~~~~~ + +MuJoCo's simulation pipeline is entirely deterministic and reproducible -- if a :ref:`state` in a trajectory is +saved and reloaded and :ref:`mj_step` called again, the resulting next state will be identical. However, there are some +important caveats: + +- Save all the required :ref:`integration state` components. In particular :ref:`warmstart + accelerations` have only a very small effect on the next state, but should be saved if bit-wise equality + is required. +- Any numerical difference between states, no matter how small, will become significant upon integration, especially for + systems with contact. Contact events have high `Lyapunov exponents + `__; this is a property of any rigid-body simulator (and indeed of + `real-world physics `__) and is not MuJoCo-specific. +- Exact reproducibility is only guaranteed within a **single version**, on the **same architecture**. Small numerical + differences are quite common between versioned releases, for example due to code optimizations. This means that when + saving an initial state and an open-loop control sequence, the resulting rolled-out trajectory will be identical + within the same version, but will likely be different between MuJoCo versions or different operating systems. + .. _piInverse: Inverse dynamics ~~~~~~~~~~~~~~~~ -The top-level function :ref:`mj_inverse` invokes the following sequence of computations. +The top-level function :ref:`mj_inverse` invokes the following sequence of computations. The notes above regarding +:ref:`consistency` and :ref:`reproducibility` apply here as well. #. Compute the forward kinematics. #. Compute the body inertias and joint axes. @@ -1647,27 +1717,6 @@ The top-level function :ref:`mj_inverse` invokes the following sequence of compu equals the sum of external and actuation forces. -.. _piReproducibility: - -Reproducibility -~~~~~~~~~~~~~~~ - -MuJoCo's simulation pipeline is entirely deterministic and reproducible -- if a :ref:`state` in a trajectory is -saved and reloaded and :ref:`mj_step` called again, the resulting next state will be identical. However, there are some -important caveats: - -- Save all the required :ref:`integration state` components. In particular :ref:`warmstart - accelerations` have only a very small effect on the next state, but should be saved if bit-wise equality - is required. -- Any numerical difference between states, no matter how small, will become significant upon integration, especially for - systems with contact. Contact events have high `Lyapunov exponents - `__; this is a property of any rigid-body simulator (and indeed of - `real-world physics `__) and is not MuJoCo-specific. -- Exact reproducibility is only guaranteed within a **single version**, on the **same architecture**. Small numerical - differences are quite common between versioned releases, for example due to code optimizations. This means that when - saving an initial state and an open-loop control sequence, the resulting rolled-out trajectory will be identical - within the same version, but will likely be different between MuJoCo versions or different operating systems. - .. _derivatives: Derivatives diff --git a/doc/conf.py b/doc/conf.py index d9ca5bfb..e41542fa 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -111,7 +111,7 @@ html_logo = 'images/banner.svg' SHARED_CSS_VARIABLES = { 'admonition-font-size': '1rem', 'admonition-title-font-size': '1rem', - 'sidebar-item-font-size': '115%', + 'sidebar-item-font-size': '130%', } # font-stack--monospace used in code blocks, Inconsolata fits in 100 chars. diff --git a/doc/css/theme_overrides.css b/doc/css/theme_overrides.css index 5d0bc476..6b607bda 100644 --- a/doc/css/theme_overrides.css +++ b/doc/css/theme_overrides.css @@ -260,6 +260,12 @@ dt .at { margin-left: 0.5em; } +/* Reduce top and bottom margins around displayed KaTeX equations */ +.katex-display { + margin-top: 0.3em; + margin-bottom: 0.3em; +} + details summary { font-weight: 600; } diff --git a/doc/includes/references.h b/doc/includes/references.h index 1be65826..c85c07eb 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -94,7 +94,7 @@ struct mjContact_ { // result of collision detection functions // internal storage used by solver mjtNum mu; // friction of regularized cone, set by mj_makeConstraint - mjtNum H[36]; // cone Hessian, set by mj_updateConstraint + mjtNum H[36]; // cone Hessian, set by mj_constraintUpdate // contact descriptors set by mj_collideXXX int dim; // contact space dimensionality: 1, 3, 4 or 6 @@ -643,6 +643,11 @@ typedef enum mjtSensor_ { // type of sensor mjSENS_SUBTREELINVEL, // 3D linear velocity of subtree mjSENS_SUBTREEANGMOM, // 3D angular momentum of subtree + // sensors for geometric distance; attached to geoms or bodies + mjSENS_GEOMDIST, // signed distance between two geoms + mjSENS_GEOMNORMAL, // normal direction between two geoms + mjSENS_GEOMFROMTO, // segment between two geoms + // global sensors mjSENS_CLOCK, // simulation time @@ -2542,6 +2547,8 @@ void mj_objectVelocity(const mjModel* m, const mjData* d, int objtype, int objid, mjtNum res[6], int flg_local); void mj_objectAcceleration(const mjModel* m, const mjData* d, int objtype, int objid, mjtNum res[6], int flg_local); +mjtNum mj_geomDistance(const mjModel* m, const mjData* d, int geom1, int geom2, + mjtNum distmax, mjtNum fromto[6]); void mj_contactForce(const mjModel* m, const mjData* d, int id, mjtNum result[6]); void mj_differentiatePos(const mjModel* m, mjtNum* qvel, mjtNum dt, const mjtNum* qpos1, const mjtNum* qpos2); @@ -2632,9 +2639,9 @@ void mjv_updateSceneState(const mjModel* m, mjData* d, const mjvOption* opt, mjvSceneState* scnstate); void mjv_addGeoms(const mjModel* m, mjData* d, const mjvOption* opt, const mjvPerturb* pert, int catmask, mjvScene* scn); -void mjv_makeLights(const mjModel* m, mjData* d, mjvScene* scn); -void mjv_updateCamera(const mjModel* m, mjData* d, mjvCamera* cam, mjvScene* scn); -void mjv_updateSkin(const mjModel* m, mjData* d, mjvScene* scn); +void mjv_makeLights(const mjModel* m, const mjData* d, mjvScene* scn); +void mjv_updateCamera(const mjModel* m, const mjData* d, mjvCamera* cam, mjvScene* scn); +void mjv_updateSkin(const mjModel* m, const mjData* d, mjvScene* scn); void mjr_defaultContext(mjrContext* con); void mjr_makeContext(const mjModel* m, mjrContext* con, int fontscale); void mjr_changeFont(int fontscale, mjrContext* con); diff --git a/doc/mjx.rst b/doc/mjx.rst index a2e79d8e..361c9cc4 100644 --- a/doc/mjx.rst +++ b/doc/mjx.rst @@ -75,7 +75,7 @@ an ``mjx.Data``: model = mujoco.MjModel.from_xml_string("...") data = mujoco.MjData(model) mjx_model = mjx.put_model(model) - mjx_data = mjx.put_data(data) + mjx_data = mjx.put_data(model, data) These MJX variants mirror their MuJoCo counterparts but have a few key differences: @@ -100,7 +100,7 @@ Neither ``mjx.Model`` nor ``mjx.Data`` are meant to be constructed manually. An .. code-block:: python model = mujoco.MjModel.from_xml_string("...") - mjx_model = mjx.device_put(model) + mjx_model = mjx.put_model(model) mjx_data = mjx.make_data(model) Using ``mjx.make_data`` may be preferable when constructing batched ``mjx.Data`` structures inside of a ``vmap``. @@ -151,7 +151,7 @@ Minimal example """ model = mujoco.MjModel.from_xml_string(XML) - mjx_model = mjx.device_put(model) + mjx_model = mjx.put_model(model) @jax.vmap def batched_step(vel): @@ -196,7 +196,7 @@ The following features are **fully supported** in MJX: * - :ref:`Actuator Bias ` - ``NONE``, ``AFFINE`` * - :ref:`Geom ` - - ``PLANE``, ``SPHERE``, ``CAPSULE``, ``BOX``, ``MESH`` + - ``PLANE``, ``HFIELD``, ``SPHERE``, ``CAPSULE``, ``BOX``, ``MESH`` are fully implemented. ``ELLIPSOID`` and ``CYLINDER`` are implemented but only collide with other primitives. * - :ref:`Constraint ` - ``EQUALITY``, ``LIMIT_JOINT``, ``CONTACT_FRICTIONLESS``, ``CONTACT_PYRAMIDAL`` * - :ref:`Equality ` @@ -223,7 +223,7 @@ The following features are **in development** and coming soon: * - Category - Feature * - :ref:`Geom ` - - ``SDF``, ``HFIELD``, ``ELLIPSOID``, ``CYLINDER`` + - ``SDF``. Collisions between (``SPHERE``, ``BOX``, ``MESH``, ``HFIELD``) and ``CYLINDER``. Collisions between (``BOX``, ``MESH``, ``HFIELD``) and ``ELLIPSOID``. * - :ref:`Constraint ` - :ref:`Frictionloss `, ``CONTACT_ELLIPTIC``, ``FRICTION_DOF`` * - :ref:`Integrator ` diff --git a/doc/modeling.rst b/doc/modeling.rst index 490affa8..6fbd46af 100644 --- a/doc/modeling.rst +++ b/doc/modeling.rst @@ -31,7 +31,7 @@ Loading models As explained in :ref:`Model instances ` in the Overview chapter, MuJoCo models can be loaded from plain-text XML files in the MJCF or URDF formats, and then compiled into a low-level mjModel. Alternatively a previously saved -mjModel can be loaded directly from a binary MJB file - whose format is not documented but is essentially a copy of the +mjModel can be loaded directly from a binary MJB file -- whose format is not documented but is essentially a copy of the mjModel memory buffer. MJCF and URDF files are loaded with :ref:`mj_loadXML` while MJB files are loaded with :ref:`mj_loadModel`. @@ -45,8 +45,8 @@ XML file has a unique top-level element. This element must be :el:`mujoco` for M Compiling models ~~~~~~~~~~~~~~~~ -Once a high-level mjCModel is created - by loading an MJCF file or a URDF file, or programmatically when such -functionality becomes available - it is compiled into mjModel. Even though loading and compilation are presently +Once a high-level mjCModel is created---by loading an MJCF file or a URDF file, or programmatically when such +functionality becomes available---it is compiled into mjModel. Even though loading and compilation are presently combined in one step, compilation is independent of loading, meaning that the compiler works in the same way regardless of how mjCModel was created. Both the parser and the compiler perform extensive error checking, and abort when the first error is encountered. The resulting error messages contain the row and column number in the XML file, @@ -56,7 +56,7 @@ simulation step of the compiled model is performed and any runtime errors are in (temporarily) setting :ref:`mju_user_error` to point to a function that throws C++ exceptions; the user can implement similar error-interception functionality at runtime if desired. -The entire process of parsing and compilation is very fast - less than a second if the model does not contain large +The entire process of parsing and compilation is very fast -- less than a second if the model does not contain large meshes or actuator lengthranges that need to be computed via simulation. This makes it possible to design models interactively, by re-loading often and visualizing the changes. Note that the :ref:`simulate.cc ` code sample has a keyboard shortcut for re-loading the current model (Ctrl+L). @@ -166,7 +166,7 @@ which overrides the default settings. The cylinder specifies defaults class "mai "sub", even though the latter was specified in the childclass attribute of the body containing the geom. Now we describe the general rules. MuJoCo supports unlimited number of defaults classes, created by possibly nested -:ref:`default ` elements in the XML. Each class has a unique name - which is a required +:ref:`default ` elements in the XML. Each class has a unique name -- which is a required attribute except for the top-level class whose name is "main" if left undefined. Each class also has a complete collection of dummy model elements, with their attributes set as follows. When a defaults class is defined within another defaults class, the child automatically inherits all attribute values from the parent. It can then override @@ -248,7 +248,7 @@ specified by the user, the frame is not rotated. :at:`zaxis`: :at-val:`real(3), optional` The Z axis of the frame. The compiler finds the minimal rotation that maps the vector :math:`(0, 0, 1)` into the vector specified here. This determines the X and Y axes of the frame implicitly. This is useful for geoms with - rotational symmetry around the Z axis, as well as lights - which are oriented along the Z axis of their frame. + rotational symmetry around the Z axis, as well as lights -- which are oriented along the Z axis of their frame. .. _CSolver: @@ -448,33 +448,36 @@ there is nothing to do, but what if their parameters are different? In that case :at:`solmix` and :at:`priority` to decide how to combine them. The combination rules for each contact parameter are as follows: -condim +**condim** If one of the two geoms has higher priority, its condim is used. If both geoms have the same priority, the maximum of the two condims is used. In this way a frictionless geom and a frictional geom form a frictional contact, unless the frictionless geom has higher priority. The latter is desirable in particle systems for example, where we may not want the particles to stick to any objects. -friction +**friction** Recall that contacts can have up to 5 friction coefficients: two tangential, one torsional, two rolling. Each contact in mjData.contact actually has all 5 of them, even if condim is less than 6 and not all coefficients are used. In contrast, geoms have only 3 friction coefficients: tangential (same for both axes), torsional, rolling (same for both axes). Each of these 3D vectors of friction coefficients is expanded into a 5D vector of friction coefficients by - replicating the tangetial and rolling components. The contact friction coefficients are then computed according to - the following rule: if one of the two geoms has higher priority, its friction coefficients are used. Otherwise the - element-wise maximum of each friction coefficient over the two geoms is used. The rationale is similar to taking the - maximum over condim: we want the more frictional geom to win. + replicating the tangetial and rolling components. See the :ref:`Contact` section in the Computation + chapter for an intuitive description of the semantics of tangential, torsional and rolling coefficients. + + The contact friction coefficients are then computed according to the following rule: if one of the two geoms has + higher priority, its friction coefficients are used. Otherwise the **element-wise maximum** of each friction + coefficient over the two geoms is used. + The reason for having 5 coefficients per contact and only 3 per geom is as follows. For a contact pair, we want to allow the most flexible model our solver can handle. As mentioned earlier, anisotropic friction can be exploited to model effects such as skating. This however requires knowing how the two axes of the contact tangent plane are oriented. For a predefined contact pair we know the two geom types in advance, and the corresponding collision - function always generates contact frames oriented in the same way - which we do not describe here but it can be seen + function always generates contact frames oriented in the same way -- which we do not describe here but it can be seen in the visualizer. For individual geoms however, we do not know which other geoms they might collide with and what their geom types might be, so there is no way to know how the contact tangent plane will be oriented when specifying an individual geom. This is why MuJoCo does not allow anisotropic friction in the individual geom specifications, but only in the explicit contact pair specifications. -margin, gap +**margin**, **gap** The maximum of the two geom margins (or gaps respectively) is used. The geom priority is ignored here, because the margin and gap are distance properties and a one-sided specification makes little sense. -solref, solimp +**solref**, **solimp** If one of the two geoms has higher priority, its solref and solimp parameters are used. If both geoms have the same priority, the weighted average is used. The weights are proportional to the solmix attributes, i.e., weight1 = solmix1 / (solmix1 + solmix2) and similarly for weight2. There is one important exception to this weighted averaging @@ -493,7 +496,7 @@ facilitate this process, we provide a mechanism to override some of the solver p the actual model. Once the override is disabled, the simulation reverts to the parameters specified in the model. This mechanism can also be used to implement continuation methods in the context of numerical optimization (such as optimal control or state estimation). This is done by allowing contacts to act from a distance in the early phases of -optimization - so as to help the optimizer find a gradient and get close to a good solution - and reducing this effect +optimization---so as to help the optimizer find a gradient and get close to a good solution---and reducing this effect later to make the final solution physically realistic. The relevant settings here are the :at:`override` attribute of :ref:`flag ` which @@ -556,12 +559,12 @@ general guidelines and observations: threshold is better defined in terms of number of active constraints, which is model and behavior dependent. - The choice between pyramidal and elliptic friction cones is a modeling choice rather than an algorithmic choice, i.e., it leads to a different optimization problem solved with the same algorithms. Elliptic cones correspond more - closely to physical reality. However pyramidal cones can improve the performance of the algorithms - but not + closely to physical reality. However pyramidal cones can improve the performance of the algorithms -- but not necessarily. While the default is pyramidal, we recommend trying the elliptic cones. When contact slip is a problem, the best way to suppress it is to use elliptic cones, large impratio, and the Newton algorithm with very small tolerance. If that is not sufficient, enable the Noslip solver. - The Newton algorithm is the best choice for most models. It has quadratic convergence near the global minimum and - gets there in surprisingly few iterations - usually around 5, and rarely more than 20. It should be used with + gets there in surprisingly few iterations -- usually around 5, and rarely more than 20. It should be used with aggressive tolerance values, say 1e-10, because it is capable of achieving high accuracy without added delay (due to quadratic convergence at the end). The only situation where we have seen it slow down are large models with elliptic cones and many slipping contacts. In that regime the Hessian factorization needs a lot of updates. It may also slow @@ -1314,7 +1317,7 @@ probe away (which is possible because the probe is a mocap body which can move i we can see the indentation made by the probe, and the resulting deformation in the rest of the body. By changing the solref and solimp attributes of the equality constraints that hold the soft object together, one can adjust the behavior of the system making it softer or harder, damped or springy, etc. Note that box, cylinder and ellipsoid objects do not -involve long kinematic chains, and can be simulated at large timesteps - similar to particle and grid, and unlike rope +involve long kinematic chains, and can be simulated at large timesteps -- similar to particle and grid, and unlike rope and cloth. .. _CDeformable: @@ -1403,7 +1406,7 @@ self-collisions; see XML reference. In case of 3D flexes made of tetrahedra, it may be useful to examine how the flex is "triangulated" internally. We have a special visualization mode that peels off the outer layers. Below is an example with the Stanford Bunny. Note how it has smaller tetrahedra on the outside and larger ones on the inside. This mesh design makes sense, because we want the -collision surface to be accurate, but on the inside we just need soft material properties - which require less spatial +collision surface to be accurate, but on the inside we just need soft material properties -- which require less spatial resolution. In order to convert a surface mesh to a tetrahedral mesh, we recommend open tools like the `fTetWild library `__. @@ -1436,7 +1439,7 @@ The flexibility of repeated MCJF sections comes at a price: global settings that the :at:`angle` attribute of :ref:`compiler ` for example, can be defined multiple times. MuJoCo allows this, and uses the last definition encountered in the composite model, after all include elements have been processed. So if model A is defined in degrees and model B is defined in radians, and A is included in B after -the :el:`compiler` element in B, the entire composite model will be treated as if it was defined in degrees - leading +the :el:`compiler` element in B, the entire composite model will be treated as if it was defined in degrees -- leading to undesirable consequences in this case. The user has to make sure that models included in each other are compatible in this sense; local vs. global coordinates is another compatibility requirement. @@ -1469,7 +1472,7 @@ unless there is a specific reason to define it. There can be several such reason is useful for custom computations involving a model element that is identified by its name in the XML (as opposed to relying on a fixed index which can change when the model is edited). - The model file could in principle become more readable by naming certain elements. Keep in mind however that XML - itself has a commenting mechanism, and that mechanism is more suitable for achieving readability - especially since + itself has a commenting mechanism, and that mechanism is more suitable for achieving readability -- especially since most text editors provide syntax highlighting which detects XML comments. .. _CURDF: @@ -1486,7 +1489,9 @@ sub-elements :ref:`compiler `, :ref:`option