diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 84646f60..75f7965d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -219,7 +219,7 @@ jobs: working-directory: python/dist run: > source ${{ matrix.tmpdir }}/venv/bin/activate && - pip install --no-deps --no-index mujoco-*.whl + pip install --no-index mujoco-*.whl - name: Test Python bindings if: ${{ runner.os != 'Windows' }} shell: bash @@ -228,23 +228,56 @@ jobs: run: > source ${{ matrix.tmpdir }}/venv/bin/activate && pytest -v --pyargs mujoco + - name: Package MJX + if: ${{ runner.os != 'Windows' }} + shell: bash + working-directory: mjx + run: + source ${{ matrix.tmpdir }}/venv/bin/activate && + python -m build . + - name: Install MJX + if: ${{ runner.os != 'Windows' }} + shell: bash + working-directory: mjx + run: + source ${{ matrix.tmpdir }}/venv/bin/activate && + pip install --require-hashes -r requirements.txt && + pip install --no-index dist/mujoco_mjx-*.whl + - name: Test MJX + if: ${{ runner.os != 'Windows' }} + shell: bash + run: + source ${{ matrix.tmpdir }}/venv/bin/activate && + pytest -n auto -v --pyargs mujoco.mjx - name: Notify team chat shell: bash env: - GCHAT_API: ${{ secrets.GCHAT_API }} - JOB_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/\ - ${{ github.run_id }}" - if: ${{ failure() && github.event_name == 'push' && env.GCHAT_API != '' }} - run: > - curl - "$GCHAT_API&threadKey=$GITHUB_SHA&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD" - -X POST - -H "Content-Type: application/json" - -d "{ - 'text': '<$JOB_URL|*FAILURE*>: - job \`${{ matrix.os }}${{ matrix.additional_label }}\` - commit \`$(echo $GITHUB_SHA | head -c6)\`\n - \`\`\`Author: ${{ github.event.head_commit.author.name }} - <${{ github.event.head_commit.author.email }}> - \n\n${{ github.event.head_commit.message }}\`\`\` - '}" + GCHAT_API_URL: ${{ secrets.GCHAT_API }} + JOB_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + CHATMSG_AUTHOR_NAME: ${{ github.event.head_commit.author.name }} + CHATMSG_AUTHOR_EMAIL: ${{ github.event.head_commit.author.email }} + CHATMSG_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + CHATMSG_JOB_ID: ${{ matrix.os }}${{ matrix.additional_label }} + if: ${{ failure() && github.event_name == 'push' && env.GCHAT_API_URL != '' }} + run: | + CHATMSG="$(cat <<-'EOF' | python3 + import json + import os + env = lambda x: os.getenv(x, '') + data = dict( + result=env('JOB_URL'), + job=env('CHATMSG_JOB_ID'), + commit=env('GITHUB_SHA')[:6], + name=env('CHATMSG_AUTHOR_NAME').replace('```', ''), + email=env('CHATMSG_AUTHOR_EMAIL'), + msg=env('CHATMSG_COMMIT_MESSAGE').replace('```', '') + ) + text = '<{result}|*FAILURE*>: job `{job}` commit `{commit}`\n```Author: {name}<{email}>\n\n{msg}```'.format(**data) + print(json.dumps({'text' : text})) + EOF + )" && + + curl "$GCHAT_API_URL&threadKey=$GITHUB_SHA&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD" \ + -X POST \ + -H "Content-Type: application/json" \ + --data-raw "${CHATMSG}" diff --git a/README.md b/README.md index 62eafb7e..21a3cb81 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,10 @@ running on Google Colab: - For a more advanced example, see the LQR tutorial which creates an LQR controller to balance a humanoid on one leg using MuJoCo's dynamics derivatives: [![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 MJX tutorial provides usage examples of + [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) ## Installation diff --git a/doc/APIreference/APIglobals.rst b/doc/APIreference/APIglobals.rst index 467bca5e..6f821776 100644 --- a/doc/APIreference/APIglobals.rst +++ b/doc/APIreference/APIglobals.rst @@ -498,7 +498,7 @@ shown in the table below. Their names are in the format ``mjKEY_XXX``. They corr - Maximum number of UI sections. Defined in `mjui.h `_. * - ``mjMAXUIITEM`` - - 80 + - 200 - Maximum number of items per UI section. Defined in `mjui.h `_. * - ``mjMAXUITEXT`` diff --git a/doc/APIreference/APItypes.rst b/doc/APIreference/APItypes.rst index d2a812d6..684e810b 100644 --- a/doc/APIreference/APItypes.rst +++ b/doc/APIreference/APItypes.rst @@ -34,6 +34,8 @@ MuJoCo defines a large number of types: - Structs used by :ref:`engine plugins`. - Several :ref:`tyFunction` for user-defined callbacks. +- :ref:`tyNotes` regarding specific data structures that require detailed description. + .. _tyPrimitive: @@ -909,6 +911,7 @@ This structure contains the custom OpenGL rendering context, with the ids of all User Interface ^^^^^^^^^^^^^^ +For a high-level description of the UI framework, see :ref:`UI`. The names of these struct types are prefixed with ``mjui``, except for the main :ref:`mjUI` struct itself. @@ -917,7 +920,9 @@ The names of these struct types are prefixed with ``mjui``, except for the main mjuiState ~~~~~~~~~ -This structure contains the keyboard and mouse state used by the UI framework. +This C struct represents the global state of the window, keyboard and mouse, input event descriptors, and all window +rectangles (including the visible UI rectangles). There is only one ``mjuiState`` per application, even if there are +multiple UIs. This struct would normally be defined as a global variable. .. mujoco-include:: mjuiState @@ -967,7 +972,9 @@ This structure defines one section of the UI. mjuiDef ~~~~~~~ -This structure defines one entry in the definition table used for simplified UI construction. +This structure defines one entry in the definition table used for simplified UI construction. It contains everything +needed to define one UI item. Some translation is performed by the helper functions, so that multiple mjuiDefs can be +defined as a static table. .. mujoco-include:: mjuiDef @@ -977,7 +984,12 @@ This structure defines one entry in the definition table used for simplified UI mjUI ~~~~ -This structure defines the entire UI. +This C struct represents an entire UI. The same application could have multiple UIs, for example on the left and the +right of the window. This would normally be defined as a global variable. As explained earlier, it contains static +allocation for a maximum number of supported UI sections (:ref:`mjuiSection`) each with a maximum number +of supported items (:ref:`mjuiItem`). It also contains the color and spacing themes, enable/disable +callback, virtual window descriptor, text edit state, mouse focus. Some of these fields are set only once when the UI +is initialized, others change at runtime. .. mujoco-include:: mjUI diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index 09622ed0..afa607d1 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -392,7 +392,9 @@ mj_objectAcceleration .. mujoco-include:: mj_objectAcceleration -Compute object 6D acceleration (rot:lin) in object-centered frame, world/local orientation. +Compute object 6D acceleration (rot:lin) in object-centered frame, world/local orientation. If acceleration or force +sensors are not present in the model, :ref:`mj_rnePostConstraint` must be manually called in order to calculate +:ref:`mjData`.cacc -- the total body acceleration, including contributions from the constraint solver. .. _mj_contactForce: @@ -803,7 +805,7 @@ mj_passive .. mujoco-include:: mj_passive -Compute qfrc_passive from spring-dampers, viscosity and density. +Compute qfrc_passive from spring-dampers, gravity compensation and fluid forces. .. _mj_subtreeVel: @@ -812,7 +814,10 @@ mj_subtreeVel .. mujoco-include:: mj_subtreeVel -subtree linear velocity and angular momentum +Sub-tree linear velocity and angular momentum: compute ``subtree_linvel``, ``subtree_angmom``. +This function is triggered automatically if the subtree :ref:`velocity` or +:ref:`momentum` sensors are present in the model. +It is also triggered for :ref:`user sensors` of :ref:`stage` "vel". .. _mj_rne: @@ -821,7 +826,8 @@ mj_rne .. mujoco-include:: mj_rne -RNE: compute M(qpos)*qacc + C(qpos,qvel); flg_acc=0 removes inertial term. +Recursive Newton Euler: compute :math:`M(q) \ddot q + C(q,\dot q)`. ``flg_acc=0`` removes the inertial term (i.e. +assumes :math:`\ddot q = 0`). .. _mj_rnePostConstraint: @@ -830,7 +836,21 @@ mj_rnePostConstraint .. mujoco-include:: mj_rnePostConstraint -RNE with complete data: compute cacc, cfrc_ext, cfrc_int. +Recursive Newton Euler with final computed forces and accelerations. +Computes three body-level ``nv x 6`` arrays, all defined in the subtreecom-based +:ref:`c-frame` and arranged in ``[rotation(3), translation(3)]`` order. + +- ``cacc``: Body acceleration, required for :ref:`mj_objectAcceleration`. +- ``cfrc_int``: Interaction force with the parent body. +- ``cfrc_ext``: External force acting on the body. + +This function is triggered automatically if the following sensors are present in the model: +:ref:`accelerometer`, :ref:`force`, :ref:`torque`, +:ref:`framelinacc`, :ref:`frameangacc`. +It is also triggered for :ref:`user sensors` of :ref:`stage` "acc". + +The computed force arrays ``cfrc_int`` and ``cfrc_ext`` currently suffer from a know bug, they do not take into account +the effect of spatial tendons, see :github:issue:`832`. .. _mj_collision: @@ -884,8 +904,8 @@ mj_constraintUpdate .. mujoco-include:: mj_constraintUpdate -Compute efc_state, efc_force, qfrc_constraint, and (optionally) cone Hessians. If cost is not NULL, set \*cost = s(jar) -where jar = Jac*qacc-aref. +Compute ``efc_state``, ``efc_force``, ``qfrc_constraint``, and (optionally) cone Hessians. +If ``cost`` is not ``NULL``, set ``*cost = s(jar)`` where ``jar = Jac*qacc - aref``. .. _Raycollisions: @@ -1945,6 +1965,8 @@ Find first rectangle containing mouse, -1: not found. UI framework ^^^^^^^^^^^^ +For a high-level description of the UI framework, see :ref:`UI`. + .. _mjui_themeSpacing: mjui_themeSpacing @@ -1970,7 +1992,12 @@ mjui_add .. mujoco-include:: mjui_add -Add definitions to UI. +This is the helper function used to construct a UI. The second argument points to an array of :ref:`mjuiDef` structs, +each corresponding to one item. The last (unused) item has its type set to -1, to mark termination. The items are added +after the end of the last used section. There is also another version of this function +(:ref:`mjui_addToSection`) which adds items to a specified section instead of adding them at the end +of the UI. Keep in mind that there is a maximum preallocated number of sections and items per section, given by +:ref:`mjMAXUISECT` and :ref:`mjMAXUIITEM`. Exceeding these maxima results in low-level errors. .. _mjui_addToSection: @@ -1997,7 +2024,12 @@ mjui_update .. mujoco-include:: mjui_update -Update specific section/item; -1: update all. +This is the main UI update function. It needs to be called whenever the user data (pointed to by the item data pointers) +changes, or when the UI state itself changes. It is normally called by a higher-level function implemented by the user +(``UiModify`` in :ref:`simulate.cc `) which also recomputes the layout of all rectangles and associated +auxiliary buffers. The function updates the pixels in the offscreen OpenGL buffer. To perform minimal updates, the user +specifies the section and the item that was modified. A value of -1 means all items and/or sections need to be updated +(which is needed following major changes.) .. _mjui_event: @@ -2006,7 +2038,10 @@ mjui_event .. mujoco-include:: mjui_event -Handle UI event, return pointer to changed item, NULL if no change. +This function is the low-level event handler. It makes the necessary changes in the UI and returns a pointer to the item +that received the event (or ``NULL`` if no valid event was recorded). This is normally called within the event handler +implemented by the user (``UiEvent`` in :ref:`simulate.cc `), and then some action is taken by user code +depending on which UI item was modified and what the state of that item is after the event is handled. .. _mjui_render: @@ -2015,7 +2050,9 @@ mjui_render .. mujoco-include:: mjui_render -Copy UI image to current buffer. +This function is called in the screen refresh loop. It copies the offscreen OpenGL buffer to the window framebuffer. If +there are multiple UIs in the application, it should be called once for each UI. Thus ``mjui_render`` is called all the +time, while :ref:`mjui_update` is called only when changes in the UI take place. .. _Errorandmemory: diff --git a/doc/APIreference/functions_override.rst b/doc/APIreference/functions_override.rst index 98241ae5..b81199f5 100644 --- a/doc/APIreference/functions_override.rst +++ b/doc/APIreference/functions_override.rst @@ -2,10 +2,6 @@ This file contains each section text along with function doc overrides. By default the docs use the function doc pulled from the header files. -.. _Activation: - -The functions in this section are maintained for backward compatibility with the now-removed activation mechanism. - .. _Virtualfilesystem: Virtual file system (VFS) enables the user to load all necessary files in memory, including MJB binary model files, XML @@ -90,10 +86,40 @@ Solve linear system :math:`M x = y` using factorization: :math:`x = (L^T D L)^{- Half of linear solve: :math:`x = \sqrt{D^{-1}} (L^T)^{-1} y` +.. _mj_subtreeVel: + +Sub-tree linear velocity and angular momentum: compute ``subtree_linvel``, ``subtree_angmom``. +This function is triggered automatically if the subtree :ref:`velocity` or +:ref:`momentum` sensors are present in the model. +It is also triggered for :ref:`user sensors` of :ref:`stage` "vel". + +.. _mj_rne: + +Recursive Newton Euler: compute :math:`M(q) \ddot q + C(q,\dot q)`. ``flg_acc=0`` removes the inertial term (i.e. +assumes :math:`\ddot q = 0`). + +.. _mj_rnePostConstraint: + +Recursive Newton Euler with final computed forces and accelerations. +Computes three body-level ``nv x 6`` arrays, all defined in the subtreecom-based +:ref:`c-frame` and arranged in ``[rotation(3), translation(3)]`` order. + +- ``cacc``: Body acceleration, required for :ref:`mj_objectAcceleration`. +- ``cfrc_int``: Interaction force with the parent body. +- ``cfrc_ext``: External force acting on the body. + +This function is triggered automatically if the following sensors are present in the model: +:ref:`accelerometer`, :ref:`force`, :ref:`torque`, +:ref:`framelinacc`, :ref:`frameangacc`. +It is also triggered for :ref:`user sensors` of :ref:`stage` "acc". + +The computed force arrays ``cfrc_int`` and ``cfrc_ext`` currently suffer from a know bug, they do not take into account +the effect of spatial tendons, see :github:issue:`832`. + .. _mj_constraintUpdate: -Compute efc_state, efc_force, qfrc_constraint, and (optionally) cone Hessians. If cost is not NULL, set \*cost = s(jar) -where jar = Jac*qacc-aref. +Compute ``efc_state``, ``efc_force``, ``qfrc_constraint``, and (optionally) cone Hessians. +If ``cost`` is not ``NULL``, set ``*cost = s(jar)`` where ``jar = Jac*qacc - aref``. .. _Support: @@ -154,6 +180,12 @@ This function can be used to apply a Cartesian force and torque to a point on a mjData.qfrc_applied of all applied forces. Note that the function requires a pointer to this vector, because sometimes we want to add the result to a different vector. +.. _mj_objectAcceleration: + +Compute object 6D acceleration (rot:lin) in object-centered frame, world/local orientation. If acceleration or force +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_differentiatePos: This function subtracts two vectors in the format of qpos (and divides the result by dt), while respecting the @@ -218,6 +250,43 @@ of how to use these functions. .. _UIframework: +For a high-level description of the UI framework, see :ref:`UI`. + +.. _mjui_add: + +This is the helper function used to construct a UI. The second argument points to an array of :ref:`mjuiDef` structs, +each corresponding to one item. The last (unused) item has its type set to -1, to mark termination. The items are added +after the end of the last used section. There is also another version of this function +(:ref:`mjui_addToSection`) which adds items to a specified section instead of adding them at the end +of the UI. Keep in mind that there is a maximum preallocated number of sections and items per section, given by +:ref:`mjMAXUISECT` and :ref:`mjMAXUIITEM`. Exceeding these maxima results in low-level errors. + +.. _mjui_update: + +This is the main UI update function. It needs to be called whenever the user data (pointed to by the item data pointers) +changes, or when the UI state itself changes. It is normally called by a higher-level function implemented by the user +(``UiModify`` in :ref:`simulate.cc `) which also recomputes the layout of all rectangles and associated +auxiliary buffers. The function updates the pixels in the offscreen OpenGL buffer. To perform minimal updates, the user +specifies the section and the item that was modified. A value of -1 means all items and/or sections need to be updated +(which is needed following major changes.) + +.. _mjui_event: + +This function is the low-level event handler. It makes the necessary changes in the UI and returns a pointer to the item +that received the event (or ``NULL`` if no valid event was recorded). This is normally called within the event handler +implemented by the user (``UiEvent`` in :ref:`simulate.cc `), and then some action is taken by user code +depending on which UI item was modified and what the state of that item is after the event is handled. + + +.. _mjui_render: + +This function is called in the screen refresh loop. It copies the offscreen OpenGL buffer to the window framebuffer. If +there are multiple UIs in the application, it should be called once for each UI. Thus ``mjui_render`` is called all the +time, while :ref:`mjui_update` is called only when changes in the UI take place. + + + + .. _Errorandmemory: .. _Standardmath: diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index afb6e339..1a168853 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -920,6 +920,11 @@ documented below. The radius of the capsules used to render slider-crank mechanisms. The second part of the mechanism is automatically scaled relative to this setting. +.. _visual-scale-frustum: + +:at:`frustum`: :at-val:`real, "10"` + The distance of the zfar plane from the camera pinhole for rendering the frustum. + .. _visual-rgba: @@ -1046,6 +1051,11 @@ disables the rendering of the corresponding object. Color used to render the crank of slide-crank mechanisms, in model configurations where the specified rod length cannot be maintained, i.e., it is "broken". +.. _visual-rgba-frustum: + +:at:`frustum`: :at-val:`real(4), "1 1 0 0.2"` + Color used to render the camera frustum. + .. _asset: @@ -1072,9 +1082,9 @@ file. color in GL_MODULATE mode. The texture data can be loaded from PNG files, with provisions for loading cube and skybox textures. Alternatively the data can be generated by the compiler as a procedural texture. Because different texture types require different parameters, only a subset of the attributes below are used for any given texture. -| MuJoCo 2.0 introduced a second file format for loading textures, in addition to PNG. If the file name extension is +| A second file format is supported for loading textures, in addition to PNG. If the file name extension is different from .png or .PNG, or if the ``content_type`` attribute is set to ``image/vnd.mujoco.texture``, then MuJoCo - assumes that the texture is in the new format. This is a custom binary file format, containing the following data: + assumes that the texture is in this format. This is a custom binary file format, containing the following data: .. code:: Text @@ -1387,7 +1397,7 @@ attribute of the :ref:`compiler ` element which controls the automatic appearance (including texture mapping) is controlled by the :at:`material` and :at:`rgba` attributes of the referencing geom, similarly to height fields. -Starting with MuJoCo 2.0, meshes can have explicit texture coordinates instead of relying on the automated texture +Meshes can have explicit texture coordinates instead of relying on the automated texture mapping mechanism. When provided, these explicit coordinates have priority. Note that texture coordinates can be specified with OBJ files and MSH files, as well as explicitly in the XML with the :at:`texcoord` attribute, but not via STL files. These mechanism cannot be mixed. So if you have an STL mesh, the only way to add texture coordinates to it is @@ -1421,17 +1431,17 @@ specified as OBJ or XML and an error message is returned. The size of the mesh is determined by the 3D coordinates of the vertex data in the mesh file, multiplied by the components of the :at:`scale` attribute below. Scaling is applied separately for each coordinate axis. Note that negative scaling values can be used to flip the mesh; this is a legitimate operation. The size parameters of the -referening geoms are ignored, similarly to height fields. As of MuJoCo 2.0 we also provide a mechanism to translate and -rotate the 3D coordinates, using the attributes refpos and refquat. +referening geoms are ignored, similarly to height fields. We also provide a mechanism to translate and +rotate the 3D coordinates, using the attributes :ref:`refpos` and :ref:`refquat`. -Another new feature in MuJoCo 2.0 is that a mesh can be defined without faces (a point cloud essentially). In that case +A mesh can also be defined without faces (a point cloud essentially). In that case the convex hull is constructed automatically, even if the compiler attribute convexhull is false. This makes it easy to construct simple shapes directly in the XML. For example, a pyramid can be created as: .. code-block:: xml - + Positioning and orienting is complicated by the fact that vertex data are often designed relative to coordinate frames @@ -1869,6 +1879,12 @@ adjust it properly through the XML. :at:`sdf_initpoints`: :at-val:`int, "40"` Number of starting points used for fining contacts with Signed Distance Field collisions. +.. _option-actuatorgroupdisable: + +:at:`actuatorgroupdisable`: :at-val:`int(30), ""` + List of actuator groups to disable. Actuators whose :ref:`group` is in this list will produce + no force. If they are stateful, their activation states will not be integrated. Internally this list is + implemented as an integer bitfield, so values must be in the range ``0 <= group <= 30``. .. _option-flag: @@ -2161,10 +2177,10 @@ This element creates a joint. As explained in :ref:`Kinematic tree `, a j between the body where it is defined and the body's parent. If multiple joints are defined in the same body, the corresponding spatial transformations (of the body frame relative to the parent frame) are applied in order. If no joints are defined, the body is welded to its parent. Joints cannot be defined in the world body. At runtime the -positions and orientations of all joints defined in the model are stored in the vector mjData.qpos, in the order in -which the appear in the kinematic tree. The linear and angular velocities are stored in the vector mjData.qvel. These -two vectors have different dimensionality when free or ball joints are used, because such joints represent rotations as -unit quaternions. +positions and orientations of all joints defined in the model are stored in the vector ``mjData.qpos``, in the order in +which the appear in the kinematic tree. The linear and angular velocities are stored in the vector ``mjData.qvel``. +These two vectors have different dimensionality when free or ball joints are used, because such joints represent +rotations as unit quaternions. .. _body-joint-name: @@ -2211,7 +2227,8 @@ unit quaternions. .. _body-joint-pos: :at:`pos`: :at-val:`real(3), "0 0 0"` - Position of the joint, specified in the frame of the parent body. For free joints this attribute is ignored. + Position of the joint, specified in the frame of the body where the joint is defined. + For free joints this attribute is ignored. .. _body-joint-axis: @@ -2654,7 +2671,7 @@ helps clarify the role of bodies and geoms in MuJoCo. .. _body-geom-pos: :at:`pos`: :at-val:`real(3), "0 0 0"` - Position of the geom, specified in the frame of the parent body. + Position of the geom, specified in the frame of the body where the geom is defined. .. _body-geom-quat: @@ -2698,8 +2715,8 @@ helps clarify the role of bodies and geoms in MuJoCo. :at:`fluidshape`: :at-val:`[none, ellipsoid], "none"` "ellipsoid" activates the geom-level fluid interaction model based on an ellipsoidal approximation of the geom - shape. When active, the model based on :ref:`body inertia sizes ` is disabled for the parent body. - See section on :ref:`ellipsoid-based` fluid interaction model for details. + shape. When active, the model based on :ref:`body inertia sizes ` is disabled for the body in which the + geom is defined. See section on :ref:`ellipsoid-based` fluid interaction model for details. .. _body-geom-fluidcoef: @@ -2879,15 +2896,15 @@ and the +Y axis points up. Thus the frame position and orientation are the key a :at:`mode`: :at-val:`[fixed, track, trackcom, targetbody, targetbodycom], "fixed"` This attribute specifies how the camera position and orientation in world coordinates are computed in forward kinematics (which in turn determine what the camera sees). "fixed" means that the position and orientation specified - below are fixed relative to the parent (i.e., the body where the camera is defined). "track" means that the camera - position is at a constant offset from the parent in world coordinates, while the camera orientation is constant in - world coordinates. These constants are determined by applying forward kinematics in qpos0 and treating the camera as - fixed. Tracking can be used for example to position a camera above a body, point it down so it sees the body, and - have it always remain above the body no matter how the body translates and rotates. "trackcom" is similar to "track" - but the constant spatial offset is defined relative to the center of mass of the kinematic subtree starting at the - parent body. This can be used to keep an entire mechanism in view. Note that the subtree center of mass for the world - body is the center of mass of the entire model. So if a camera is defined in the world body in mode "trackcom", it - will track the entire model. "targetbody" means that the camera position is fixed in the parent body, while the + below are fixed relative to the the body where the camera is defined. "track" means that the camera position is at a + constant offset from the body in world coordinates, while the camera orientation is constant in world coordinates. + These constants are determined by applying forward kinematics in qpos0 and treating the camera as fixed. Tracking can + be used for example to position a camera above a body, point it down so it sees the body, and have it always remain + above the body no matter how the body translates and rotates. "trackcom" is similar to "track" but the constant + spatial offset is defined relative to the center of mass of the kinematic subtree starting at the body in which the + camera is defined. This can be used to keep an entire mechanism in view. Note that the subtree center of mass for the + world body is the center of mass of the entire model. So if a camera is defined in the world body in mode "trackcom", + it will track the entire model. "targetbody" means that the camera position is fixed in the body frame, while the camera orientation is adjusted so that it always points towards the targeted body (which is specified with the target attribute below). This can be used for example to model an eye that fixates a moving object; the object will be the target, and the camera/eye will be defined in the body corresponding to the head. "targetbodycom" is the same as @@ -2965,6 +2982,8 @@ and the +Y axis points up. Thus the frame position and orientation are the key a :at:`quat`, :at:`axisangle`, :at:`xyaxes`, :at:`zaxis`, :at:`euler` Orientation of the camera frame. See :ref:`COrientation`. + Note that specifically for cameras, the :at:`xyaxes` attribute is semantically convenient as the X and Y axes + correspond to the directions "right" and "up" in pixel space, respectively. .. _body-camera-user: @@ -3636,11 +3655,6 @@ saving the XML: -.. _body-flexcomp-class: - -:at:`class`: :at-val:`string, optional` - Defaults class for setting unspecified attributes. - .. _body-flexcomp-name: :at:`name`: :at-val:`string, required` @@ -3689,12 +3703,13 @@ saving the XML: **gmsh** is similar to mesh, but it loads a `GMSH file `__ in format 4.1 (ascii or binary). The file extension can be anything; the parser recognizes the format by examining the file header. This is a very rich file format, allowing all kinds of elements with different dimensionality and - topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes. - Only the Nodes and Elements sections of the GMHS file are processed, and used to populate the point and element data - of the flexcomp. The parser will generate an error if the GMSH file contains meshes that are not supported by MuJoCo. - :at:`dim` is automatically set to the dimensionality specified in the GMSH file. Presently this is the only mechanism - to load a large tetrahedral mesh in MuJoCo and generate a corresponding soft entity. If such a mesh is available in a - different file format, use the freely available `GMSH software `__ to convert it to GMSH 4.1. + topology. MuJoCo only supports GMSH element types 1, 2, 4 which happen to correspond to our 1D, 2D and 3D flexes and + assumes that the nodes are specified in a single block. Only the Nodes and Elements sections of the GMHS file are + processed, and used to populate the point and element data of the flexcomp. The parser will generate an error if the + GMSH file contains meshes that are not supported by MuJoCo. :at:`dim` is automatically set to the dimensionality + specified in the GMSH file. Presently this is the only mechanism to load a large tetrahedral mesh in MuJoCo and + generate a corresponding soft entity. If such a mesh is available in a different file format, use the freely + available `GMSH software `__ to convert it to GMSH 4.1. **direct** allows the user to specify the point and element data of the flexcomp directly in the XML. Note that flexcomp will still generate moving bodies automatically, as well as automate other settings; so it still provides @@ -3715,21 +3730,18 @@ saving the XML: .. _body-flexcomp-point: :at:`point`: :at-val:`real(3*npoint), optional` - The 3D coordinates of the points. This attribute is only used with type **direct**. All other flexcomp types generate their own points. The points are used to construct bodies and vertices as explained earlier. .. _body-flexcomp-element: :at:`element`: :at-val:`int((dim+1)*npoint), optional` - The zero-based point ids forming each flex elements. This attribute is only used with type **direct**. All other flexcomp types generate their own elements. This data is passed through to the automatically-generated flex. .. _body-flexcomp-texcoord: :at:`texcoord`: :at-val:`real(2*npoint), optional` - Texture coordinates of each point, passed through to the automatically-generated flex. Note that flexcomp does not generate texture coordinates automatically, except for 2D grids. For all other types, the user can specify explicit texture coordinates here, even if the points themselves were generated automatically. This requires understanding of @@ -3779,7 +3791,6 @@ saving the XML: .. _body-flexcomp-euler: :at:`axisangle`, :at:`xyaxes`, :at:`zaxis`, :at:`euler` - Alternative specification of rotation, that can be used instead of :at:`quat`. .. _body-flexcomp-scale: @@ -3795,9 +3806,8 @@ saving the XML: .. _body-flexcomp-flatskin: :at:`radius`, :at:`material`, :at:`rgba`, :at:`group`, :at:`flatskin` - -These attributes are directly passed through to the automatically-generated :ref:`flex` object and have -the same meaning. + These attributes are directly passed through to the automatically-generated :ref:`flex` object and + have the same meaning. .. _flexcomp-contact: @@ -3818,10 +3828,12 @@ the same meaning. .. _flexcomp-contact-margin: .. _flexcomp-contact-gap: -:at:`internal`, :at:`selfcollide`, :at:`activelayers`, :at:`contype`, :at:`conaffinity`, :at:`condim`, :at:`priority`, -:at:`friction`, :at:`solmix`, :at:`solimp`, :at:`margin`, :at:`gap` +.. |body/flexcomp/contact attrib list| replace:: + :at:`internal`, :at:`selfcollide`, :at:`activelayers`, :at:`contype`, :at:`conaffinity`, :at:`condim`, + :at:`priority`, :at:`friction`, :at:`solmix`, :at:`solimp`, :at:`margin`, :at:`gap` -Same as in :ref:`flex/contact`. All attributes are passed through to the automatically-generated flex. +|body/flexcomp/contact attrib list| + Same as in :ref:`flex/contact`. All attributes are passed through to the automatically-generated flex. .. _flexcomp-edge: @@ -4119,7 +4131,7 @@ cases, the user will specify a :el:`flexcomp` which will then automatically cons .. _flex-edge: :el-prefix:`flex/` |-| **edge** (?) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +''''''''''''''''''''''''''''''''''' This element adjusts the passive or constraint properties of all edges of the flex. A flex edge can have a damping passive force and an :ref:`equality constraint` associated with it, resulting in edge constraint forces. @@ -4141,7 +4153,7 @@ these mechanisms to be combined as desired. .. _flex-contact: :el-prefix:`flex/` |-| **contact** (?) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +'''''''''''''''''''''''''''''''''''''' This element adjusts the contact properties of the flex. It is mostly identical to geom contact properties, with some extensions specific to flexes. @@ -4225,7 +4237,7 @@ Finally, the skin can be inflated by applying an offset to each vertex position Skins are one-sided for rendering purposes; this is because back-face culling is needed to avoid shading and aliasing artifacts. When the skin is a closed 3D shape this does not matter because the back sides cannot be seen. But if the skin is a 2D object, we have to specify both sides and offset them slightly to avoid artifacts. Note that the -composite objects introduced in MuJoCo 2.0 generate skins automatically. So one can save an XML model with a composite +composite objects generate skins automatically. So one can save an XML model with a composite object, and obtain an elaborate example of how a skin is specified in the XML. Similar to meshes, skins can be specified directly in the XML via attributes documented later, or loaded from a binary @@ -4475,11 +4487,12 @@ of the other body, without any joint elements in the child body. .. _equality-weld-torquescale: :at:`torquescale`: :at-val:`real, "1"` - Relative torque-to-force ratio. This ratio is used by the weld to scale how much it "cares" about rotational - displacements vs. translational displacements. Setting this value to 0 makes the :el:`weld` behave like a - :el:`connect` constraint. Note that this value has units of length and can therefore be interpreted as follows. - Imagining that the weld is implemented by a patch of glue sticking the two bodies together, :at:`torquescale` can be - interpreted as the diameter of this glue patch. + A constant that scales the angular residual (angular constraint violation). Notionally in units of + :math:`\textrm{torque}/\textrm{force}=\textrm{length}`. Intuitively this coefficient defines how much the weld + "cares" about rotational displacements vs. translational displacements. Setting this value to 0 makes the :el:`weld` + behave like a :el:`connect` constraint. Note that this value has units of length and can therefore be understood as + follows. Imagining that the weld is implemented by a flat patch of glue sticking the two bodies together, + :at:`torquescale` can be interpreted as the diameter of this glue patch. .. _equality-joint: @@ -4623,7 +4636,7 @@ has multiple obstacle geoms they must be separated by sites - so as to avoid the tendon level. This example illustrates a multi-branch tendon acting as a finger extensor, with a counter-weight instead of an actuator: `tendon.xml <_static/tendon.xml>`__. -MuJoCo 2.0 introduced a second form of wrapping, where the tendon is constrained to pass through a geom rather than +A second form of wrapping is where the tendon is constrained to pass *through* a geom rather than wrap around it. This is enabled automatically when a sidesite is specified and its position is inside the volume of the obstacle geom. @@ -4871,7 +4884,7 @@ multiplied by the corresponding coef value, and added up to obtain the tendon le ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This is a grouping element for actuator definitions. Recall the discussion of MuJoCo's :ref:`Actuation model -` in the Computation chapter, and the :ref:`Actuator shortcuts ` discussed earlier in this +` in the Computation chapter, and the :ref:`Actuator shortcuts ` discussed earlier in this chapter. The first 13 attributes of all actuator-related elements below are the same, so we document them only once, under the :el:`general` actuator. @@ -5144,7 +5157,7 @@ specify them independently. :el-prefix:`actuator/` |-| **motor** (*) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This and the next three elements are the :ref:`Actuator shortcuts ` discussed earlier. When a +This and the next three elements are the :ref:`Actuator shortcuts ` discussed earlier. When a such shortcut is encountered, the parser creates a :el:`general` actuator and sets its dynprm, gainprm and biasprm attributes to the internal defaults shown above, regardless of any default settings. It then adjusts dyntype, gaintype and biastype depending on the shortcut, parses any custom attributes (beyond the common ones), and translates them @@ -5805,9 +5818,9 @@ Associate this actuator with an :ref:`engine plugin`. Either :at:`plug .. _actuator-plugin-user: -.. |actuator/plugin attrib list| replace:: :at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited` - :at:`ctrlrange`, :at:`forcerange`, :at:`lengthrange`, :at:`gear`, :at:`cranklength`, :at:`joint`, :at:`jointinparent` - :at:`site`, :at:`tendon`, :at:`cranksite`, :at:`slidersite`, :at:`user` +.. |actuator/plugin attrib list| replace:: :at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, + :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`, :at:`lengthrange`, :at:`gear`, :at:`cranklength`, + :at:`joint`, :at:`jointinparent`, :at:`site`, :at:`tendon`, :at:`cranksite`, :at:`slidersite`, :at:`user` |actuator/plugin attrib list| Same as in actuator/ :ref:`general `. @@ -5867,6 +5880,8 @@ This element creates a 3-axis accelerometer. The sensor is mounted at a site, an as the site frame. This sensor outputs three numbers, which are the linear acceleration of the site (including gravity) in local coordinates. +The presence of this sensor in a model triggers a call to :ref:`mj_rnePostConstraint` during sensor computation. + .. _sensor-accelerometer-name: .. _sensor-accelerometer-noise: @@ -5947,6 +5962,8 @@ the child body, and the force points from the child towards the parent. The comp forces acting on the system, including contacts as well as external perturbations. Using this sensor often requires creating a dummy body welded to its parent (i.e., having no joint elements). +The presence of this sensor in a model triggers a call to :ref:`mj_rnePostConstraint` during sensor computation. + .. _sensor-force-name: .. _sensor-force-noise: @@ -5976,6 +5993,8 @@ creating a dummy body welded to its parent (i.e., having no joint elements). This element creates a 3-axis torque sensor. This is similar to the :ref:`force ` sensor above, but measures torque rather than force. +The presence of this sensor in a model triggers a call to :ref:`mj_rnePostConstraint` during sensor computation. + .. _sensor-torque-name: .. _sensor-torque-noise: @@ -6779,6 +6798,8 @@ coordinates. This element creates a sensor that returns the 3D linear acceleration of the spatial frame of the object, in global coordinates. +The presence of this sensor in a model triggers a call to :ref:`mj_rnePostConstraint` during sensor computation. + .. _sensor-framelinacc-name: .. _sensor-framelinacc-noise: @@ -6809,6 +6830,8 @@ coordinates. This element creates a sensor that returns the 3D angular acceleration of the spatial frame of the object, in global coordinates. +The presence of this sensor in a model triggers a call to :ref:`mj_rnePostConstraint` during sensor computation. + .. _sensor-frameangacc-name: .. _sensor-frameangacc-noise: @@ -6864,6 +6887,8 @@ global coordinates. This element creates sensor that returns the linear velocity of the center of mass of the kinematic subtree rooted at a specified body, in global coordinates. +The presence of this sensor in a model triggers a call to :ref:`mj_subtreeVel` during sensor computation. + .. _sensor-subtreelinvel-name: .. _sensor-subtreelinvel-noise: @@ -6889,6 +6914,8 @@ specified body, in global coordinates. This element creates sensor that returns the angular momentum around the center of mass of the kinematic subtree rooted at a specified body, in global coordinates. +The presence of this sensor in a model triggers a call to :ref:`mj_subtreeVel` during sensor computation. + .. _sensor-subtreeangmom-name: .. _sensor-subtreeangmom-noise: @@ -6931,12 +6958,15 @@ This element creates sensor that returns the simulation time. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This element creates a user sensor. MuJoCo does not know how to compute the output of this sensor. Instead the user -should install the callback :ref:`mjcb_sensor` which is expected to fill in the sensor data in mjData.sensordata. The -specification in the XML is used to allocate space for this sensor, and also determine which MuJoCo object it is +should install the callback :ref:`mjcb_sensor` which is expected to fill in the sensor data in ``mjData.sensordata``. +The specification in the XML is used to allocate space for this sensor, and also determine which MuJoCo object it is attached to and what stage of computation it needs before the data can be computed. Note that the MuJoCo object -referenced here can be a tuple, which in turn can reference a custom collection of MuJoCo objects - for example several +referenced here can be a tuple, which in turn can reference a custom collection of MuJoCo objects -- for example several bodies whose center of mass is of interest. +If a user sensor is of :ref:`stage` "vel" or "acc", then :ref:`mj_subtreeVel` or +:ref:`mj_rnePostConstraint` will be triggered, respectively. + .. _sensor-user-name: .. _sensor-user-noise: @@ -7009,7 +7039,7 @@ Ascociate this sensor with an :ref:`engine plugin`. Either :at:`plugin .. _sensor-plugin-user: -.. |sensor/plugin attrib list| replace:: :at:`name`, :at:`cutoff`, :at:`objtype`, :at:`objname`, :at:`reftype` +.. |sensor/plugin attrib list| replace:: :at:`name`, :at:`cutoff`, :at:`objtype`, :at:`objname`, :at:`reftype`, :at:`refname`, :at:`user` |sensor/plugin attrib list| @@ -7514,7 +7544,7 @@ if omitted. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This and the next three elements set the attributes of the :ref:`general ` element using -:ref:`Actuator shortcuts `. It does not make sense to use more than one such shortcut in the same defaults +:ref:`Actuator shortcuts `. It does not make sense to use more than one such shortcut in the same defaults class, because they set the same underlying attributes, replacing any previous settings. All :ref:`motor ` attributes are available here except: name, class, joint, jointinparent, site, tendon, slidersite, cranksite. diff --git a/doc/XMLschema.rst b/doc/XMLschema.rst index 149ebc74..84b5aff4 100644 --- a/doc/XMLschema.rst +++ b/doc/XMLschema.rst @@ -109,6 +109,8 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`framelength` | :ref:`framewidth` | :ref:`constraint` | :ref:`slidercrank` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +| | | | :ref:`frustum` | | | | | +| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| visual |br| |_| |L| | | .. table:: | | :ref:`rgba | ? | :class: mjcf-attributes | @@ -124,7 +126,7 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`contacttorque` | :ref:`contactgap` | :ref:`rangefinder` | :ref:`constraint` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`slidercrank` | :ref:`crankbroken` | | | | +| | | | :ref:`slidercrank` | :ref:`crankbroken` | :ref:`frustum` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | mujoco |br| |L| | | *no attributes* | @@ -228,7 +230,7 @@ | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | | :ref:`iterations` | :ref:`ls_iterations` | :ref:`noslip_iterations` | :ref:`mpr_iterations` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`sdf_iterations` | :ref:`sdf_initpoints` | | | | +| | | | :ref:`sdf_iterations` | :ref:`sdf_initpoints` | :ref:`actuatorgroupdisable` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_| option |br| |_| |L| | | .. table:: | @@ -485,19 +487,17 @@ | :ref:`flexcomp | \* | :class: mjcf-attributes | | ` | | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`name` | :ref:`class` | :ref:`type` | :ref:`group` | | +| | | | :ref:`name` | :ref:`type` | :ref:`group` | :ref:`dim` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`dim` | :ref:`count` | :ref:`spacing` | :ref:`radius` | | +| | | | :ref:`count` | :ref:`spacing` | :ref:`radius` | :ref:`rigid` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`rigid` | :ref:`mass` | :ref:`inertiabox` | :ref:`scale` | | +| | | | :ref:`mass` | :ref:`inertiabox` | :ref:`scale` | :ref:`file` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`file` | :ref:`point` | :ref:`element` | :ref:`texcoord` | | +| | | | :ref:`point` | :ref:`element` | :ref:`texcoord` | :ref:`material` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`material` | :ref:`rgba` | :ref:`flatskin` | :ref:`pos` | | +| | | | :ref:`rgba` | :ref:`flatskin` | :ref:`pos` | :ref:`quat` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`quat` | :ref:`axisangle` | :ref:`xyaxes` | :ref:`zaxis` | | -| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | -| | | | :ref:`euler` | | | | | +| | | | :ref:`axisangle` | :ref:`xyaxes` | :ref:`zaxis` | :ref:`euler` | | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | |_2| flexcomp |br| |_2| |L| | | .. table:: | diff --git a/doc/_static/gyroscopic.xml b/doc/_static/gyroscopic.xml new file mode 100644 index 00000000..61568bc5 --- /dev/null +++ b/doc/_static/gyroscopic.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/doc/_static/pendulum.xml b/doc/_static/pendulum.xml new file mode 100644 index 00000000..ce15d1df --- /dev/null +++ b/doc/_static/pendulum.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/changelog.rst b/doc/changelog.rst index 151c6ebf..25d866a4 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -2,13 +2,90 @@ Changelog ========= -Upcoming version (not yet released) ------------------------------------ +Version 3.0.1 (November 15, 2023) +--------------------------------- + +General +^^^^^^^ +1. Added sub-terms of total passive forces in ``mjData.qfrc_passive`` to :ref:`mjData`: + ``qfrc_{spring, damper, gravcomp, fluid}``. The sum of these vectors equals ``qfrc_passive``. + +.. youtube:: H9qG9Zf2W44 + :align: right + :width: 240px + +2. Added :ref:`actuatorgroupdisable` attribute and associated + :ref:`mjOption.disableactuator` integer bitfield, which can be used to disable sets of actuators at runtime + according to their :ref:`group`. Fixes :github:issue:`1092`. See :ref:`CActDisable`. + + - The first 6 actuator groups are toggleable in the :ref:`simulate` viewer. See `example model + `__ + and associated screen-capture on the right. + +3. Increased ``mjMAXUIITEM`` (maximum number of UI elements per section in Simulate) to 200. + +MJX +^^^ +4. Added support for Newton solver (``mjSOL_NEWTON`` in :ref:`mjtSolver`). The Newton solver significantly speeds up + simulation on GPU: + + .. list-table:: Steps-per-second, Conjugate Gradient vs. Newton on A100 + :header-rows: 1 + :align: left + + * - Model + - CG + - Newton + - Speedup + * - `Humanoid `__ + - 640,000 + - 1,020,000 + - **1.6 x** + * - `Barkour v0 `__ + - 1,290,000 + - 1,750,000 + - **1.35 x** + * - `Shadow Hand `__ + - 215,000 + - 270,000 + - **1.25 x** + + Humanoid is the standard MuJoCo humanoid, + `Google Barkour `__ and the Shadow Hand + are both available in the :ref:`MuJoCo Menagerie`. +5. Added support for joint equality constraints (``mjEQ_JOINT`` in :ref:`mjtEq`). +6. Fixed bug where mixed ``jnt_limited`` joints were not being constrained correctly. +7. Made ``device_put`` type validation more verbose (fixes :github:issue:`1113`). +8. Removed empty EFC rows from ``MJX``, for joints with no limits (fixes :github:issue:`1117`). +9. Fixed bug in ``scan.body_tree`` that led to incorrect smooth dynamics for some kinematic tree layouts. + +Python bindings +^^^^^^^^^^^^^^^ + +10. Fix the macOS ``mjpython`` launcher to work with the Python interpreter from Apple Command Line Tools. +11. Fixed a crash when copying instances of ``mujoco.MjData`` for models that use plugins. Introduced a ``model`` + attribute to ``MjData`` which is reference to the model that was used to create that ``MjData`` instance. + +Simulate +^^^^^^^^ +12. :ref:`simulate`: correct handling of "Pause update", "Fullscreen" and "VSync" buttons. + +Documentation +^^^^^^^^^^^^^ + +.. youtube:: cE3s_IfO4g4 + :align: right + :width: 240px + +13. Added cell to the `tutorial colab `__ providing an + example of procedural camera control: +14. Added documentation for the :ref:`UI` framework. +15. Fixed typos and supported fields in docs (fixes :github:issue:`1105` and :github:issue:`1106`). + Bug fixes ^^^^^^^^^ - -1. Fix in simulate: correct handling of "Pause update", "Fullscreen" and "VSync" buttons. +16. Fixed bug relating to welds modified with :ref:`torquescale`. Version 3.0.0 (October 18, 2023) -------------------------------- diff --git a/doc/computation/index.rst b/doc/computation/index.rst index 7753555f..ca7c9e98 100644 --- a/doc/computation/index.rst +++ b/doc/computation/index.rst @@ -143,47 +143,59 @@ Our notation is summarized in the table below. Additional notation specific to c When available, we also show the fields of main data structures :ref:`mjModel` and :ref:`mjData` corresponding to the mathematical notation. -+-----------------+----------------+----------------+----------------------+ -| Symbol | Size | Description | MuJoCo field | -+=================+================+================+======================+ -| :math:`n_Q` | | number of | ``mjModel.nq`` | -| | | position | | -| | | coordinates | | -+-----------------+----------------+----------------+----------------------+ -| :math:`n_V` | | number of | ``mjModel.nv`` | -| | | degrees of | | -| | | freedom | | -+-----------------+----------------+----------------+----------------------+ -| :math:`n_C` | | number of | ``mjData.nefc`` | -| | | active | | -| | | constraints | | -+-----------------+----------------+----------------+----------------------+ -| :math:`q` | :math:`n_Q` | joint position | ``mjData.qpos`` | -+-----------------+----------------+----------------+----------------------+ -| :math:`v` | :math:`n_V` | joint velocity | ``mjData.qvel`` | -+-----------------+----------------+----------------+----------------------+ -| :math:`\tau` | :math:`n_V` | applied force: | | -| | | passive, | | -| | | actuation, | | -| | | external | | -+-----------------+----------------+----------------+----------------------+ -| :math:`c(q, v)` | :math:`n_V` | bias force: | ``mjData.qfrc_bias`` | -| | | Coriolis, | | -| | | centrifugal, | | -| | | gravitational | | -+-----------------+----------------+----------------+----------------------+ -| :math:`M(q)` | :math:`n_V | inertia in | ``mjData.qM`` | -| | \times n_V` | joint space | | -+-----------------+----------------+----------------+----------------------+ -| :math:`J(q)` | :math:`n_C | constraint | ``mjData.efc_J`` | -| | \times n_V` | Jacobian | | -+-----------------+----------------+----------------+----------------------+ -| :math:`r(q)` | :math:`n_C` | constraint | ``mjData.efc_pos`` | -| | | residual | | -+-----------------+----------------+----------------+----------------------+ -| :math:`f(q, v, | :math:`n_C` | constraint | ``mjData.efc_force`` | -| \tau)` | | force | | -+-----------------+----------------+----------------+----------------------+ +.. list-table:: + :widths: 2 2 7 4 + :header-rows: 1 + + * - Symbol + - Size + - Description + - MuJoCo field + * - :math:`n_Q` + - + - number of position coordinates + - ``mjModel.nq`` + * - :math:`n_V` + - + - number of degrees of freedom + - ``mjModel.nv`` + * - :math:`n_C` + - + - number of active constraints + - ``mjData.nefc`` + * - :math:`q` + - :math:`n_Q` + - joint position + - ``mjData.qpos`` + * - :math:`v` + - :math:`n_V` + - joint velocity + - ``mjData.qvel`` + * - :math:`\tau` + - :math:`n_V` + - applied force: passive, actuation, external + - ``mjData.qfrc_passive`` + ``mjData.qfrc_actuator`` + ``mjData.qfrc_applied`` + * - :math:`c(q, v)` + - :math:`n_V` + - bias force: Coriolis, centrifugal, gravitational + - ``mjData.qfrc_bias`` + * - :math:`M(q)` + - :math:`n_V \times n_V` + - inertia in joint space + - ``mjData.qM`` + * - :math:`J(q)` + - :math:`n_C \times n_V` + - constraint + Jacobian + - ``mjData.efc_J`` + * - :math:`r(q)` + - :math:`n_C` + - constraint residual + - ``mjData.efc_pos`` + * - :math:`f(q, v,\tau)` + - :math:`n_C` + - constraint force + - ``mjData.efc_force`` All model elements are enumerated at compile time and assembled into the above system-level vectors and matrices. In our earlier arm model :ref:`example ` the model has :math:`n_V = 13` degrees of freedom: 3 for the ball joint, one @@ -259,7 +271,7 @@ the force outputs are stored in ``mjData.actuator_force``, and the activation st 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. +` which instantiate common actuator types. .. _geTransmission: @@ -304,8 +316,8 @@ is attached; the possible attachment object types are :at:`joint`, :at:`tendon`, .. _geActivation: -Activation dynamics -^^^^^^^^^^^^^^^^^^^ +Stateful actuators +^^^^^^^^^^^^^^^^^^ Some actuators such as pneumatic and hydraulic cylinders as well as biological muscles have an internal state called "activation". This is a true dynamic state, beyond the joint positions :math:`q` and velocities :math:`v`. Including @@ -321,27 +333,33 @@ independent of the other actuators. The activation types currently implemented a .. math:: \begin{aligned} \text{integrator}: & & \dot{w}_i &= u_i \\ - \text{filter}: & & \dot{w}_i &= (u_i - w_i) / t \\ - \text{filterexact}: & & \dot{w}_i &= (u_i - w_i) / t \\ + \text{filter}: & & \dot{w}_i &= (u_i - w_i) / \texttt{t} \\ + \text{filterexact}: & & \dot{w}_i &= (u_i - w_i) / \texttt{t} \\ + \text{muscle}: & & \dot{w}_i &= \textrm{muscle}(u_i, w_i, l_i, \dot{l}_i) \end{aligned} -where :math:`t` is an actuator-specific time constant stored in ``mjModel.actuator_dynprm``. In addition the type can -be "user", in which case :math:`w_i` is computed by the user-defined callback :ref:`mjcb_act_dyn`. The type can also -be "none" which corresponds to a regular actuator with no activation state. The dimensionality of :math:`w` equals +where :math:`\texttt{t}` is an actuator-specific time-constant stored in ``mjModel.actuator_dynprm``. In addition, the +type can be "user", in which case :math:`w_i` is computed by the user-defined callback :ref:`mjcb_act_dyn`. The type can +also be "none" which corresponds to a regular actuator with no activation state. The dimensionality of :math:`w` equals the number of actuators whose activation type is different from "none". +For more information regarding muscle activation dynamics, see :ref:`CMuscle`. + For ``filterexact`` activation dynamics, Euler integration of :math:`\dot{w}` is replaced with the analytic integral: .. math:: \begin{aligned} - \text{filter}: & & w_{i+1} &= w_i + h (u_i - w_i) / t \\ - \text{filterexact}: & & w_{i+1} &= w_i + (u_i - w_i) (1 - e^{-h / t}) \\ + \text{filter}: & & w_{i+1} &= w_i + h (u_i - w_i) / \texttt{t} \\ + \text{filterexact}: & & w_{i+1} &= w_i + (u_i - w_i) (1 - e^{-h / \texttt{t}}) \\ \end{aligned} -The two expressions converge to the same value in the :math:`h \rightarrow 0` limit. +The two expressions converge to the same value in the :math:`h \rightarrow 0` limit. Note that Euler-integrated filters +diverge for :math:`\texttt{t} < h`, while exactly-integrated filters are stable for any positive :math:`\texttt{t}`. -Note that Euler-integrated filters diverge for :math:`t < h`, while exactly-integrated filters are stable for any -:math:`t > 0`. +:ref:`actearly`: + If the :ref:`actearly` attribute is set to "true", ``mjData.actuator_force`` is computed + based on :math:`w_{i+1}` (the next activation), reducing the delay between changes to :math:`u` and their effects on + the acceleration by one time step (so the total dynamics are second-order rather than third order). .. _geActuatorForce: @@ -379,10 +397,6 @@ This quantity is stored in ``mjData.qfrc_actuator``. It is added to the applied with any user-defined forces in joint or Cartesian coordinates (which are stored in ``mjData.qfrc_applied`` and ``mjData.xfrc_applied`` respectively). -Optionally, the :ref:`actearly` attribute on an actuator computes ``mjData.qfrc_actuator`` -based on the value of :math:`w_{i+1}` after integration, reducing the delay between changes to :math:`u` and -:math:`t`. - .. _gePassive: Passive forces @@ -526,29 +540,48 @@ Fast implicit-in-velocity (``implicitfast``) derivatives are also the main source of asymmetry of :math:`D`, by dropping them and symmetrizing, we can use the faster Cholesky rather than LU decomposition. - .. tip:: - The implicitfast integrator has similar computational cost to Euler, yet provides increased stability, and is - therefore a strict improvement. It is the recommended integrator and will become the default in a future version. - 4th-order Runge-Kutta (``RK4``) One advantage of our continuous-time formulation is that we can use higher order integrators such as Runge-Kutta or multistep methods. The only such integrator currently implemented is the fixed-step `4th-order Runge-Kutta method - `_, though users - can easily implement other integrators by calling :ref:`mj_forward` and integrating accelerations themselves. We have - observed that for energy-conserving systems (`example - `_) RK4 - is qualitatively better than the single-step methods, both in terms of stability and accuracy, even when the timestep - is decreased by a factor of 4 (so the computational effort is identical). In the presence of large velocity- - dependent forces, if the chosen single-step method integrates those forces implicitly, single-step methods can be - significantly more stable than RK4. + `__, though + users can easily implement other integrators by calling :ref:`mj_forward` and integrating accelerations themselves. + We have observed that for energy-conserving systems (`example <../_static/pendulum.xml>`__), RK4 is qualitatively + better than the single-step methods, both in terms of stability and accuracy, even when the timestep is decreased by + a factor of 4 (so the computational effort is identical). In the presence of large velocity- dependent forces, if the + chosen single-step method integrates those forces implicitly, single-step methods can be significantly more stable + than RK4. -.. note:: - The accuracy and stability of all integrators can be improved by reducing the time step :math:`h` which is stored in - ``mjModel.opt.timestep``. Of course this also slows down the simulation. The time step is perhaps the most important - parameter that the user can adjust. If it is too large, the simulation will become unstable. If it is too small, CPU - time will be wasted without meaningful improvement in accuracy. There is always a comfortable range where the time - step is "just right", but that range is model-dependent. +.. admonition:: Choosing timestep and integrator + :class: tip + :ref:`timestep` + The accuracy and stability of all integrators can be improved by reducing the time step :math:`h`. + Of course a smaller time step also slows down the simulation. The time step is perhaps the single most important + parameter that the user can adjust. If it is too large, the simulation will become unstable. If it is too small, CPU + time will be wasted without meaningful improvement in accuracy. There is always a comfortable range where the time + step is "just right", but that range is model-dependent. + + :ref:`integrator` + Summary: The recommended integrator is ``implicitfast`` which usually has the best tradeoff of stabillity and + performance. + + **Euler**: + Use ``Euler`` for compatibillity with older models and :ref:`MJX`. Specifically for MJX, + setting the :ref:`eulerdamp` disable flag can :ref:`improve performance`. + **implicitfast**: + The ``implicitfast`` integrator has similar computational cost to ``Euler``, yet provides + increased stability, and is therefore a strict improvement. It is the recommended integrator for most models. + **implicit**: + The benefit over ``implicitfast`` is the implicit integration of Coriolis and centripetal forces, including + gyroscopic forces. The most common case where integrating such forces implicitly leads to noticable improvement is + when free objects with assymetric inertia are spinning quickly. `gyroscopic.xml <../_static/gyroscopic.xml>`__ + shows an ellipsoid rolling on an inclined plane which quickly diverges with ``implicitfast`` but is stable with + ``implicit``. + **RK4**: + This integrator is best for systems which are energy conserving, or almost energy-conserving. `pendulum.xml + <../_static/pendulum.xml>`__ shows a complicated pendulum mechanism which diverges quickly using ``Euler`` or + ``implicitfast`` yet conserves energy well under ``RK4``. Note that under ``implicit``, this model doesn't diverge + but rather loses energy. .. _geState: @@ -850,33 +883,25 @@ spatial frame and normal distance are given by the collision detector. In addition to the above quantities which are computed online, each contact has several parameters obtained from the model definition. -+---------------------------+-----------------------------------+ -| Parameter | Description | -+===========================+===================================+ -| ``condim`` | Dimensionality of the contact | -| | force/torque in the contact | -| | frame. It can be 1, 3, 4 or 6. | -+---------------------------+-----------------------------------+ -| ``friction`` | Vector of friction coefficients, | -| | with dimensionality ``condim-1``. | -+---------------------------+-----------------------------------+ -| ``margin`` | The distance margin used to | -| | determine if the contact should | -| | be included in the global contact | -| | array ``mjData.contact``. | -+---------------------------+-----------------------------------+ -| ``gap`` | For custom computations it is | -| | sometimes convenient to include | -| | contacts in ``mjData.contact`` | -| | but not generate contact forces. | -| | This is what ``gap`` does: | -| | contact forces are generated only | -| | when the normal distance is below | -| | margin-gap. | -+---------------------------+-----------------------------------+ -| ``solref`` and ``solimp`` | :ref:`Solver ` | -| | parameters explained later. | -+---------------------------+-----------------------------------+ +.. list-table:: + :widths: 1 5 + :header-rows: 1 + + * - Parameter + - Description + * - ``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``. + * - ``margin`` + - The distance margin used to determine if the contact should be included in the global contact array + ``mjData.contact``. + * - ``gap`` + - For custom computations it is sometimes convenient to include contacts in ``mjData.contact`` but not generate + contact forces. This is what ``gap`` does: contact forces are generated only when the normal distance is below + (margin - gap). + * - ``solref`` and ``solimp`` + - :ref:`Solver ` parameters, explained later. The contact friction cone can be either elliptic or pyramidal. This is a global setting determined by the choice of constraint solver: the elliptic solvers work with elliptic cones, while the pyramidal solvers work with pyramidal cones, @@ -967,11 +992,11 @@ to be solved numerically. In inverse dynamics, the problem becomes diagonal and The primal formulation is based on a generalization of the Gauss principle of least constraint. In its basic form, the Gauss principle states that if we have unconstrained dynamics :math:`M \dot{v} = \tau` and impose acceleration -constraint :math:`J \dot{v} = a^*`, the resulting acceleration will be +constraint :math:`J \dot{v} = \ar`, the resulting acceleration will be .. math:: \dot{v} = \arg \min_x \left\| x-M^{-1} \tau \right\|^2_M \\ - \textrm{subject to} \; J x = a^* + \textrm{subject to} \; J x = \ar where the weighted :math:`L_2` norm is the usual :math:`\|x\|^2_M = x^T M x`. Thus the constraint causes the smallest possible deviation from the unconstrained acceleration :math:`M^{-1}\tau`, where the metric for measuring deviations in @@ -981,58 +1006,55 @@ will be done by generalizing both the cost function and the constraints in the G We will use the following notation beyond the notation introduced earlier: -+----------------------+----------------------+----------------------+ -| Symbol | Size | Description | -+======================+======================+======================+ -| :math:`z` | :math:`n_C` | constraint | -| | | deformations | -+----------------------+----------------------+----------------------+ -| :math:`\omega` | :math:`n_C` | velocity of | -| | | constraint | -| | | deformations | -+----------------------+----------------------+----------------------+ -| :math:`d` | :math:`n_C` | constraint impedance | -+----------------------+----------------------+----------------------+ -| :math:`b` | :math:`n_C` | virtual constraint | -| | | damping | -+----------------------+----------------------+----------------------+ -| :math:`k` | :math:`n_C` | virtual constraint | -| | | stiffness | -+----------------------+----------------------+----------------------+ -| :math:`A(q)` | :math:`n_C \times | inverse inertia in | -| | n_C` | constraint space | -+----------------------+----------------------+----------------------+ -| :math:`R(q)` | :math:`n_C \times | diagonal regularizer | -| | n_C` | in constraint space | -+----------------------+----------------------+----------------------+ -| :math:`a^*(q,v)` | :math:`n_C` | reference | -| | | acceleration in | -| | | constraint space | -+----------------------+----------------------+----------------------+ -| :math:`a^0(q, v, | :math:`n_C` | unconstrained | -| \tau)` | | acceleration in | -| | | constraint space | -+----------------------+----------------------+----------------------+ -| :math:`a^1(q, v, | :math:`n_C` | constrained | -| \dot{v})` | | acceleration in | -| | | constraint space | -+----------------------+----------------------+----------------------+ -| :math:`\mathcal{K} | | product of all | -| (q)` | | contact friction | -| | | cones | -+----------------------+----------------------+----------------------+ -| :math:`\eta` | | upper bounds on | -| | | friction loss forces | -+----------------------+----------------------+----------------------+ -| :math:`\Omega(q)` | | convex set of | -| | | admissible | -| | | constraint forces | -+----------------------+----------------------+----------------------+ -| :math:`\mathcal{E}, | | index sets for | -| \mathcal{F}, | | Equality, Friction | -| \mathcal{C}` | | loss, Contact | -| | | constraints | -+----------------------+----------------------+----------------------+ +.. list-table:: + :widths: 1 1 4 + :header-rows: 1 + + * - Symbol + - Size + - Description + * - :math:`z` + - :math:`n_C` + - constraint deformations + * - :math:`\omega` + - :math:`n_C` + - velocity of constraint deformations + * - :math:`k` + - :math:`n_C` + - virtual constraint stiffness + * - :math:`b` + - :math:`n_C` + - virtual constraint damping + * - :math:`d` + - :math:`n_C` + - constraint impedance + * - :math:`A(q)` + - :math:`n_C \times n_C` + - inverse inertia in constraint space + * - :math:`R(q)` + - :math:`n_C \times n_C` + - diagonal regularizer in constraint space + * - :math:`\ar` + - :math:`n_C` + - reference acceleration in constraint space + * - :math:`\au(q, v, \tau)` + - :math:`n_C` + - unconstrained acceleration in constraint space + * - :math:`\ac(q, v, \dot{v})` + - :math:`n_C` + - constrained acceleration in constraint space + * - :math:`\mathcal{K}(q)` + - + - product of all contact friction cones + * - :math:`\eta` + - + - upper bounds on friction loss forces + * - :math:`\Omega(q)` + - + - convex set of admissible constraint forces + * - :math:`\mathcal{E}, \mathcal{F}, \mathcal{C}` + - + - index sets for Equality, Friction loss, Contact constraints The index sets will be used to refer to parts of vectors and matrices. For example, :math:`J_\mathcal{C}` is the sub-matrix of all rows of the Jacobian that correspond to contact constraints. @@ -1048,7 +1070,7 @@ explain what it means and why it makes sense. That problem is .. math:: (\dot{v}, \dot{\omega}) = \arg \min_{(x, y)} \left\|x-M^{-1}(\tau-c)\right\|^2_M + - \left\|y-a^*\right\|^{\text{Huber}(\eta)}_{R^{-1}} \\ + \left\|y-\ar\right\|^{\text{Huber}(\eta)}_{R^{-1}} \\ \textrm{subject to} \; J_\mathcal{E} x_\mathcal{E} - y_\mathcal{E} = 0, \; J_\mathcal{F} x_\mathcal{F} - y_\mathcal{F} = 0, \; @@ -1056,15 +1078,15 @@ explain what it means and why it makes sense. That problem is :label: eq:primal The new players here are the diagonal regularizer :math:`R > 0` which makes the constraints soft, and the reference -acceleration :math:`a^*` which stabilizes the constraints. The latter is similar in spirit to Baumgarte stabilization, +acceleration :math:`\ar` which stabilizes the constraints. The latter is similar in spirit to Baumgarte stabilization, but instead of adding a constraint force directly, it modifies the optimization problem whose solution is the constraint -force. Since this problem is itself constrained, the relation between :math:`a^*` and :math:`f` is generally non-linear. -The quantities :math:`R` and :math:`a^*` are computed from the solver :ref:`parameters ` as described +force. Since this problem is itself constrained, the relation between :math:`\ar` and :math:`f` is generally non-linear. +The quantities :math:`R` and :math:`\ar` are computed from the solver :ref:`parameters ` as described later. For now we assume they are given. The optimization variable :math:`x` stands for acceleration as in the Gauss principle, while :math:`y` is a slack variable in constraint space. It is needed to model soft constraints. If we forced the solution to reach -:math:`y = a^*`, which we could do by taking the limit :math:`R \to 0`, we would obtain a hard constraint model. This +:math:`y = \ar`, which we could do by taking the limit :math:`R \to 0`, we would obtain a hard constraint model. This limit is not allowed in MuJoCo, but nevertheless one can construct models that are phenomenologically hard. The symbol :math:`\mathcal{K}^*` denotes the dual to the friction cone. It is motivated by mathematical reverse @@ -1095,7 +1117,7 @@ constraint space (which the constraint force aims to prevent), there is no posit \tilde{q} &= {q \brack z}, & \tilde{v} &= {v \brack \omega}, & \tilde{c} &= {c \brack 0}, \\ - \tilde{\tau} &= {\tau \brack {R^{-1} a^*}}, & + \tilde{\tau} &= {\tau \brack {R^{-1} \ar}}, & \tilde{M} &= \left[\begin{array}{cc} M & 0 \\ 0 & R^{-1} @@ -1114,20 +1136,20 @@ Unpacking all the tildes yields the explicit form of the original and the deform .. math:: \begin{aligned} M \dot{v} + c &= \tau +J^T f \\ - \dot{\omega} &= a^* - R f \\ + \dot{\omega} &= \ar - R f \\ \end{aligned} -Thus :math:`R` has the meaning of inverse deformation inertia, while :math:`a^*` has the meaning of unforced deformation +Thus :math:`R` has the meaning of inverse deformation inertia, while :math:`\ar` has the meaning of unforced deformation acceleration. Does MuJoCo keep these deformation variables as part of the system state and integrate their dynamics together with the joint positions and velocities? No, although such an option may be worth providing in the future. Recall that we defined -the functional dependence of the regularizer and the reference acceleration as :math:`R(q)` and :math:`a^*(q, v)`. This +the functional dependence of the regularizer and the reference acceleration as :math:`R(q)` and :math:`\ar(q, v)`. This makes problem :eq:`eq:primal` dependent only on :math:`(q, v, \tau)`, and so the original dynamics are not actually affected by the deformation dynamics. Since the general constraint model we developed up to now makes no assumptions -about how :math:`R` and :math:`a^*` are computed, our choice is consistent and improves simulator efficiency. +about how :math:`R` and :math:`\ar` are computed, our choice is consistent and improves simulator efficiency. Nevertheless, given that these quantities turned out to be related to the deformation dynamics, it may be more natural -to define them as :math:`R(z)` and :math:`a^* (z, \omega)` and simulate the entire augmented system. Below we clarify +to define them as :math:`R(z)` and :math:`\ar (z, \omega)` and simulate the entire augmented system. Below we clarify some of the benefits of such a simulation. When do the deformation dynamics "track" the original dynamics exactly? One can verify that this happens when the @@ -1159,7 +1181,7 @@ we obtain the unconstrained problem .. math:: \dot{v} = \arg \min_{x} \left\|x-M^{-1}(\tau-c)\right\|^2_M + - s \left( J x - a^* \right) + s \left( J x - \ar \right) :label: eq:reduced The function :math:`s(\cdot)` plays the role of a soft-constraint penalty. It can be shown to be convex and @@ -1169,7 +1191,7 @@ Another appealing feature of the reduced formulation is that the inverse dynamic above problem is unconstrained and convex, the unique global minimum makes the gradient vanish. This yields the identity .. math:: - M \dot{v} + c = \tau - J^T \nabla s \left( J \dot{v} - a^* \right) + M \dot{v} + c = \tau - J^T \nabla s \left( J \dot{v} - \ar \right) which is the analytical inverse dynamics in the presence of soft constraints. Comparing to the equations of motion :eq:`eq:motion`, we see that the constraint forces :math:`f` are given by the negative gradient of the function @@ -1191,7 +1213,7 @@ Lagrange dual to the primal problem defined above is .. math:: f = \arg\min_\lambda \frac{1}{2} \lambda^{T} \left( A+R \right) \lambda + - \lambda^T \left( a^0 - a^* \right) \\ + \lambda^T \left( \au - \ar \right) \\ \text{subject to} \; \lambda \in \Omega :label: eq:dual @@ -1203,7 +1225,7 @@ where the inverse inertia in constraint space is and the unconstrained acceleration in constraint space is .. math:: - a^0 = J M^{-1} (\tau-c) + \dot{J} v + \au = J M^{-1} (\tau-c) + \dot{J} v The constraint set :math:`\Omega` is as follows. :math:`\lambda_\mathcal{E}` is unconstrained, because it is the Lagrange multiplier for an equality constraint in the primal problem. For friction loss we have the box constraint @@ -1218,28 +1240,28 @@ problem are described later. As mentioned earlier, MuJoCo's constraint model has uniquely-defined inverse dynamics, and we already saw one way to derive it in the reduced formulation above. Here we derive it again from the dual formulation. Recall that in inverse dynamics we have access to :math:`(q, v, \dot{v})` instead of :math:`(q, v, \tau)`, so the unconstrained acceleration -:math:`a^0` is unknown. However we can compute the constrained acceleration +:math:`\au` is unknown. However we can compute the constrained acceleration .. math:: - a^1 = J \dot{v} + \dot{J} v + \ac = J \dot{v} + \dot{J} v Inverse dynamics can now be computed by solving the optimization problem .. math:: f = \arg \min_\lambda \frac{1}{2} \lambda^{T} R \lambda + - \lambda^T \left( a^1 - a^* \right) \\ + \lambda^T \left( \ac - \ar \right) \\ \text{subject to} \; \lambda \in \Omega By comparing the KKT conditions for these two convex optimization problems, one can verify that their solutions coincide when .. math:: - a^1 = a^0 + Af + \ac = \au + Af :label: eq:identity This key identity is essentially Newton's second law projected in constraint space. It is derived by moving the term :math:`c` in the equations of motion :eq:`eq:motion` to the right hand side, multiplying by :math:`J M^{-1}` from the -left, adding :math:`\dot{J} v` to both sides, and substituting the above definitions of :math:`A, a^0, a^1`. In terms of +left, adding :math:`\dot{J} v` to both sides, and substituting the above definitions of :math:`A, \au, \ac`. In terms of implementation, we do not actually compute the acceleration term :math:`\dot{J} v`. This is because our optimization problems depend on differences of constraint-space accelerations, and so this term would cancel out even if we were to compute it. @@ -1316,12 +1338,12 @@ representations of the constraint Jacobian and related matrices. Parameters ~~~~~~~~~~ -Here we explain how the quantities :math:`R, a^*` are computed from model parameters. For the chosen parameterization to -make sense, we first need to understand how these quantities affect the dynamics. We focus on the unconstrained -minimizer of :eq:`eq:dual`, namely +Here we explain how the quantities :math:`R, \ar` are computed from model parameters. For the chosen +parameterization to make sense, we first need to understand how these quantities affect the dynamics. We focus on the +unconstrained minimizer of :eq:`eq:dual`, namely .. math:: - f^+ = (A+R)^{-1} (a^* - a^0) + f^+ = (A+R)^{-1} (\ar - \au) If it happens that :math:`f^+ \in \Omega`, then :math:`f^+ = f` is the actual constraint force generated by our model. We focus on this case because it is common, in the sense that the subset of the constraints in :math:`\Omega` that are @@ -1329,11 +1351,11 @@ active at any given time is usually small, and furthermore it is the only case t Substituting :math:`f^+` in the constraint dynamics :eq:`eq:identity` and rearranging terms yields .. math:: - a^1 = A(A+R)^{-1} a^* + R (A+R)^{-1} a^0 + \ac = A(A+R)^{-1} \ar + R (A+R)^{-1} \au Thus the constrained acceleration interpolates between the unconstrained and the reference acceleration. In particular, -in the limit :math:`R \to 0` we have a hard constraint and :math:`a^1 = a^*`, while in the limit :math:`R \to \infty` we -have have an infinitely soft constraint (i.e., no constraint) and :math:`a^1 = a^0`. It is then natural to introduce a +in the limit :math:`R \to 0` we have a hard constraint and :math:`\ac = \ar`, while in the limit :math:`R \to \infty` we +have have an infinitely soft constraint (i.e., no constraint) and :math:`\ac = \au`. It is then natural to introduce a model parameter which directly controls the interpolation. We call this parameter *impedance* and denote it :math:`d`. It is a vector with dimensionality :math:`n_C` satisfying :math:`0 0` -and stiffness coefficients :math:`k > 0`. The quantities :math:`R, a^*` are then computed by MuJoCo as shown above, and +and stiffness coefficients :math:`k > 0`. The quantities :math:`R, \ar` are then computed by MuJoCo as shown above, and the selected optimization algorithm is applied to solve problem :eq:`eq:dual`. As explained in the :ref:`solver parameters ` section of the Modeling chapter, MuJoCo offers additional automation for setting :math:`d, b, k` so as to achieve critical damping, or model a soft contact layer by varying :math:`d` with distance. @@ -1534,6 +1556,7 @@ The top-level function :ref:`mj_step` invokes the sequence of computations below the subtree centers of mass. #. Compute all passive forces: spring-dampers in joints and tendons, and fluid dynamics forces. #. Compute sensor data that depends on velocity, and the kinetic energy if enabled. + If required by sensors, call :ref:`mj_subtreeVel`. #. Compute the reference constraint acceleration. #. Compute the vector of Coriolis, centrifugal and gravitational forces. #. Compute the actuator forces and activation dynamics if defined. @@ -1541,6 +1564,7 @@ The top-level function :ref:`mj_step` invokes the sequence of computations below #. Compute the constraint forces with the selected solver, and update the joint acceleration so as to account for the constraint forces. This yields the vector ``mjData.qacc`` which is the main output of forward dynamics. #. Compute sensor data that depends on force and acceleration if enabled. + If required by sensors, call :ref:`mj_rnePostConstraint`. #. Check the acceleration for invalid or unacceptably large real values. If divergence is detected, the state is automatically reset and the corresponding warning is raised. #. Compare the results of forward and inverse dynamics, so as to diagnose poor solver convergence in the forward @@ -1567,6 +1591,7 @@ The top-level function :ref:`mj_inverse` invokes the following sequence of compu #. Compute the tendon and actuator velocities. #. Compute the body velocities and joint axes rates of change. #. Compute sensor data that depends on velocity, and the kinetic energy if enabled. + If required by sensors, call :ref:`mj_subtreeVel`. #. Compute all passive forces. #. Compute the reference constraint acceleration. #. If the :ref:`invdiscrete` flag is set and the :ref:`integrator` is not @@ -1574,6 +1599,7 @@ The top-level function :ref:`mj_inverse` invokes the following sequence of compu #. Compute the constraint force. This is done analytically, without using a numerical solver. #. Compute the inverse dynamics for the unconstrained system. #. Compute sensor data that depends on force and acceleration if enabled. + If required by sensors, call :ref:`mj_rnePostConstraint`. #. Compute the vector ``mjData.qfrc_inverse`` by combining all results. This is the main output of inverse dynamics. It equals the sum of external and actuation forces. diff --git a/doc/conf.py b/doc/conf.py index ca6252bc..bc244774 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -191,8 +191,15 @@ favicons = [ # -- Options for katex ------------------------------------------------------ # See: https://sphinxcontrib-katex.readthedocs.io/en/0.4.1/macros.html +# {ar au, ac} are {reference, unconstrained, constrained} acceleration, resp. latex_macros = r""" \def \d #1{\operatorname{#1}} + \def \ar {a_{\rm ref}} + \def \au {a_0} + \def \ac {a_1} + \def \ari {a_{{\rm ref},i}} + \def \aui {a_{0,i}} + \def \aci {a_{1,i}} """ # Translate LaTeX macros to KaTeX and add to options for HTML builder diff --git a/doc/css/theme_overrides.css b/doc/css/theme_overrides.css index 74cedc1b..5d0bc476 100644 --- a/doc/css/theme_overrides.css +++ b/doc/css/theme_overrides.css @@ -19,9 +19,14 @@ body { } /* Make the search bar query text readable in dark theme. */ -body:not([data-theme="light"]) { +body[data-theme="dark"] { --color-sidebar-search-foreground: white; } +@media (prefers-color-scheme: dark) { + body[data-theme="auto"] { + --color-sidebar-search-foreground: white; + } +} .schema-small { font-size: 93%; diff --git a/doc/includes/references.h b/doc/includes/references.h index 3f98f313..da5329cc 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -84,7 +84,7 @@ struct mjContact_ { // result of collision detection functions // contact parameters set by near-phase collision function mjtNum dist; // distance between nearest points; neg: penetration mjtNum pos[3]; // position of contact point: midpoint between geoms - mjtNum frame[9]; // normal is in [0-2] + mjtNum frame[9]; // normal is in [0-2], points from geom[0] to geom[1] // contact parameters set by mj_collideGeoms mjtNum includemargin; // include if dist`__ directory. MJX allows MuJoCo to run on compute @@ -94,7 +96,7 @@ Neither ``mjx.Model`` nor ``mjx.Data`` are meant to be constructed manually. An mjx_model = mjx.device_put(model) mjx_data = mjx.make_data(model) -Using ``mx.make_data`` may be preferable when constructing batched ``mjx.Data`` structures inside of a ``vmap``. +Using ``mjx.make_data`` may be preferable when constructing batched ``mjx.Data`` structures inside of a ``vmap``. .. _MjxFunctions: @@ -186,7 +188,9 @@ The following features are **fully supported** in MJX: * - :ref:`Geom ` - ``PLANE``, ``SPHERE``, ``CAPSULE``, ``BOX``, ``MESH`` * - :ref:`Constraint ` - - ``EQUALITY``, ``FRICTION_DOF``, ``LIMIT_JOINT``, ``CONTACT_PYRAMIDAL`` + - ``EQUALITY``, ``LIMIT_JOINT``, ``CONTACT_PYRAMIDAL`` + * - :ref:`Equality ` + - ``CONNECT``, ``WELD``, ``JOINT`` * - :ref:`Integrator ` - ``EULER``, ``RK4`` * - :ref:`Cone ` @@ -194,7 +198,7 @@ The following features are **fully supported** in MJX: * - :ref:`Condim ` - 3 * - :ref:`Solver ` - - ``CG`` + - ``CG``, ``NEWTON`` * - Fluid Model - :ref:`flInertia` @@ -214,18 +218,22 @@ The following features are **in development** and coming soon: - ``TRN_TENDON`` * - :ref:`Geom ` - ``HFIELD``, ``ELLIPSOID``, ``CYLINDER``, ``SDF`` + * - :ref:`Constraint ` + - ``CONTACT_FRICTIONLESS``, ``CONTACT_ELLIPTIC``, ``FRICTION_DOF`` * - :ref:`Integrator ` - ``IMPLICIT``, ``IMPLICITFAST`` * - :ref:`Cone ` - ``ELLIPTIC`` * - :ref:`Condim ` - 1, 4, 6 - * - :ref:`Solver ` - - ``NEWTON`` * - Fluid Model - :ref:`flEllipsoid` * - :ref:`Tendons ` - :ref:`Spatial `, :ref:`Fixed ` + * - :ref:`Equality ` + - ``TENDON`` + * - :ref:`Sensors ` + - All except ``mjSENS_PLUGIN``, ``mjSENS_USER`` The following features are **unsupported**: @@ -296,10 +304,11 @@ Performance tuning For MJX to perform well, some configuration parameters should be adjusted from their default MuJoCo values: :ref:`option` element - For now, solver must be set to ``CG`` (but Newton is on its way!). The ``iterations`` and ``ls_iterations`` - attributes---which control solver and linesearch iterations, respectively---should be brought down to just low enough - that the simulation remains stable. Accurate solver forces are not so important in reinforcement learning in which - domain randomization is often used to add noise to physics for sim2real. + The ``iterations`` and ``ls_iterations`` attributes---which control solver and linesearch iterations, respectively--- + should be brought down to just low enough that the simulation remains stable. Accurate solver forces are not so + important in reinforcement learning in which domain randomization is often used to add noise to physics for sim-to-real. + The ``NEWTON`` :ref:`Solver ` often delivers reasonable convergence with one solver iteration, and performs + well on GPU. ``CG`` is currently a better choice for TPU. :ref:`contact-pair` element Consider explicitly marking geoms for collision detection to reduce the number of contacts that MJX must consider diff --git a/doc/modeling.rst b/doc/modeling.rst index 8a4d5d0e..7abdb53e 100644 --- a/doc/modeling.rst +++ b/doc/modeling.rst @@ -190,7 +190,7 @@ element, it must be undefined in the active defaults class. A final twist here is actuators. They are different because some of the actuator-related elements are actually shortcuts, and shortcuts interact with the defaults setting mechanism in a non-obvious way. This is explained in the -:ref:`Actuator shortcuts ` section below. +:ref:`Actuator shortcuts ` section below. .. _CFrame: @@ -198,8 +198,8 @@ Coordinate frames ~~~~~~~~~~~~~~~~~ The positions and orientations of all elements defined in the kinematic tree are expressed in local coordinates, -relative to the parent body for bodies, and relative to the body that owns the element for geoms, joints, sites, cameras -and lights. +relative to the parent body for bodies, and relative to the body that contains the element for geoms, joints, sites, +cameras and lights. A related attribute is :ref:`compiler/angle`. It specifies whether angles in the MJCF file are expressed in degrees or radians (after compilation, angles are always expressed in radians). @@ -259,14 +259,14 @@ available in :ref:`option