- Add floating changes to changelog.

- Add sections about the state and derivatives to the Computation chapter.

PiperOrigin-RevId: 459032736
Change-Id: I0b69401688f24c84d5747f1b49980e38e19a54a3
This commit is contained in:
Yuval Tassa
2022-07-05 02:17:32 -07:00
committed by Copybara-Service
parent 6d01627c0b
commit d3a86bb748
7 changed files with 240 additions and 56 deletions
+12
View File
@@ -6579,6 +6579,18 @@ mju_sigmoid
Sigmoid function over 0<=x<=1 constructed from half-quadratics.
mjd_transitionFD
~~~~~~~~~~~~~~~~
.. code-block:: C
void mjd_transitionFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte centered, mjtNum* A, mjtNum* B);
Finite differenced state-transition and control-transition matrices dx(t+h) = A*dx(t) + B*du(t).
required output matrix dimensions:
A: (2*nv+na x 2*nv+na)
B: (2*nv+na x nu)
.. _Macros:
Macros
+46 -1
View File
@@ -2,8 +2,53 @@
Changelog
=========
Upcoming version (not yet released)
-----------------------------------
General
^^^^^^^
- Added ``mjd_transitionFD`` to compute efficient finite difference approximations of the state-transition and
control-transition matrices, :ref:`see here<derivatives>` for more details.
- Added ``ctrl`` attribute to :ref:`keyframes<keyframe>`.
- Added visualisation groups to skins.
- Added actuator visualisation for ``free`` and ``ball`` joints and for actuators with ``site`` transmission.
- Added visualisation for actuator activations.
- Added ``<intvelocity>`` actuator shortcut for "integrated velocity" actuators, documented :ref:`here <intvelocity>`.
- Added ``<damper>`` actuator shortcut for active-damping actuators, documented :ref:`here <damper>`.
- ``mju_rotVecMat`` and ``mju_rotVecMatT`` now support in-place multiplication.
- ``mjData.ctrl`` values are no longer clamped in-place, remain untouched by the engine.
- Arrays in mjData's buffer now align to 64-byte boundaries rather than 8-byte.
- Add memory poisoning when building with Address Sanitizer (ASAN) and Memory Sanitizer (MSAN). This allows ASAN to
detect reads and writes to regions in ``mjModel.buffer`` and ``mjData.buffer`` that do not lie within an array, and
for MSAN to detect reads from uninitialised fields in ``mjData`` following ``mj_resetData``.
Bug fixes
^^^^^^^^^
- :ref:`Activation clamping <CActRange>` was not being applied in the :ref:`implicit integrator<geIntegration>`.
- Stricter parsing of orientation specifiers. Before this change, a specification that included both ``quat`` and an
:ref:`alternative specifier<COrientation>` e.g., ``<geom ... quat=".1 .2 .3 .4" euler="10 20 30">``, would lead to the
``quat`` being ignored and only ``euler`` being used. After this change a parse error will be thrown.
- Stricter parsing of XML attributes. Before this change an erroneous XML snippet like ``<geom size="1/2 3 4">`` would
have been parsed as ``size="1 0 0"`` and no error would have been thrown. Now throws an error.
- Trying to load a ``NaN`` via XML like ``<geom size="1 NaN 4">``, while allowed for debugging purposes, will now print
a warning.
- Fixed null pointer dereference in ``mj_loadModel``.
- Fixed memory leaks when loading an invalid model from MJB.
- Integer overflows are now avoided when computing ``mjModel`` buffer sizes.
- Added missing warning string for ``mjWARN_BADCTRL``.
Packaging
^^^^^^^^^
- Changed MacOS packaging so that the copy of ``mujoco.framework`` embedded in ``MuJoCo.app`` can be used to build
applications externally.
Version 2.2.0 (May 23, 2022)
-----------------------------
----------------------------
Open Sourcing
^^^^^^^^^^^^^
+120
View File
@@ -507,6 +507,97 @@ Implicit-in-velocity Euler method (implicit)
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.
.. _geState:
The **state**
~~~~~~~~~~~~~
To complete our description of the general framework we will now discuss the notion of *state*. MuJoCo has a compact,
well-defined internal state which, together with the deterministic computational pipeline, means that operations like
resetting the state and computing dynamics derivatives are also well-defined. The state is entirely encapsulated in the
``mjData`` struct and consists of several components:
.. _gePhysicsState:
Physics state
^^^^^^^^^^^^^
| The *physics state* contains all quantities which are time-integrated during stepping.
| They are ``mjData.{qpos, qvel, act, time}``:
Mechanical state: ``qpos`` and ``qvel``
The *mechanical state* of a simulation is given by the generalized position (``mjData.qpos``) and velocity
(``mjData.qvel``) vectors, denoted above as :math:`q` and :math:`v`, respectively.
Actuator activations: ``act``
``mjData.act`` contains the internal states of stateful actuators, denoted above as :math:`w`.
Time: ``time``
The time of the simulation is given by the scalar ``mjData.time``. Since physics is time-invariant, it is
often excluded from the *physics state*; an exception could be a time-dependent user callback (e.g., an open-loop
controller), in which case time should be included.
.. _geInput:
User inputs
^^^^^^^^^^^
These input fields are set by the user and affect the physics simulation, but are untouched by the simulator.
Controls: ``ctrl``
Controls are defined by the :ref:`actuator<actuator>` section of the XML. ``mjData.ctrl`` values either produce
generalized forces directly (stateless actuators), or affects the actuator activations in ``mjData.act``, which then
produce forces.
Auxillary Controls: ``qfrc_applied`` and ``xfrc_applied``
| ``mjData.qfrc_applied`` are directly applied generalised forces.
| ``mjData.xfrc_applied`` are Cartesian wrenches applied to the CoM of individual bodies. This field is used for
example, by the :ref:`native viewer<saSimulate>` to apply mouse perturbations.
| Note that the effects of ``qfrc_applied`` and ``xfrc_applied`` can usually be recreated by appropriate actuator
definitions.
MoCap poses: ``mocap_pos`` and ``mocap_quat``
``mjData.mocap_pos`` and ``mjData.mocap_quat`` are special optional kinematic states :ref:`described here<CMocap>`,
which allow the user to set the positions and orientations of static bodies in real-time, for example when streaming
6D poses from a motion-capture device.
User data: ``userdata``
``mjData.userdata`` acts as a user-defined memory space untouched by the engine. For example it can be used by
callbacks. This is described in more detail in the :ref:`Programming chapter<siSimulation>`.
.. _geWarmstart:
Warmstart accelerations
^^^^^^^^^^^^^^^^^^^^^^^
``qacc_warmstart``
``mjData.qacc_warmstart`` are accelerations used to warmstart the constraint solver, saved from the previous step.
When using a slowly-converging :ref:`constraint solver<Solver>` like PGS, these can speed up simulation by reducing
the number of iterations required for convergence. Note however that the default Newton solver converges so quickly
(usually 2-3 iterations), that warmstarts often have no effect on speed and can be disabled.
Different warmstarts have no preceptible effect on the dynamics but should be saved if perfect numerical
reproducibility is required when loading a non-initial state. Note that even though their effect on physics is
negligible, many physical systems will accumulate small differences `exponentially
<https://en.wikipedia.org/wiki/Lyapunov_exponent>`__ when time-stepping, quickly leading to divergent trajectories
for different warmstarts.
.. _geIntegrationState:
Integration state
^^^^^^^^^^^^^^^^^
The *integration state* is the union of all the above ``mjData`` fields and constitutes the entire set of inputs to
the *forward dynamics*. In the case of *inverse dynamics*, ``mjData.qacc`` is also treated as an input variable. All
other ``mjData`` fields are functions of the integration state.
.. _geSimulationState:
Simulation state: ``mjData``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The *simulation state* is the entirety of the ``mjData`` struct and associated memory buffer. This state includes
all derived quantities computed during dynamics computation. Because the ``mjData`` buffers are preallocated for the
worst case, it is often significantly faster to recompute derived quantities from the *integration state* rather than
using ``mj_copyData``.
.. _Constraint:
Constraint model
@@ -1422,6 +1513,35 @@ The top-level function :ref:`mj_inverse` invokes the following sequence of compu
#. 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.
.. _derivatives:
Derivatives
-----------
MuJoCo's entire computational pipline and uniquely -- its contraint solver -- are analytically differentiable. Writing
efficient implementations of these derivatives is a long term goal of the development team. Analytic derivatives of the
smooth dynamics with respect to velocity are already in place and power the :ref:`implicit integrator<geIntegration>`.
The function ``mjd_transitionFD`` computes state-transition and control-transition Jacobians. Given any valid MuJoCo
model ``mjModel* m`` with an initial :ref:`simulation state<geState>` in ``mjData* d``,
- let :math:`x` denote the *physics state* of the simulation at time :math:`t` -- the concatenation of positions,
velocities and actuator states ``[d->qpos; d->qvel; d->act]``.
- Let :math:`u` denote the vector of controls at time :math:`t`, corresponding to ``d->ctrl``.
- Let :math:`y` denote the physical state of the simulation at time :math:`t+h`, where :math:`h` corresponds to
``m->opt.timstep``.
- The high level function ``mj_step(m, d)`` computes :math:`y(x, u)` -- the next state as a function of
the current state and control.
- ``mjd_transitionFD`` computes the Jacobians :math:`A = \frac{\partial y}{\partial x}` and
:math:`B = \frac{\partial y}{\partial u}` using efficient finite-differencing of ``mj_step``.
These derivatives are efficient by exploiting MuJoCo's configurable computation pipeline so that quantities are not
recomputed when not required. For example when differencing with respect to controls, quantities which depend only on
position and velocity are not recomputed. Additionally, solver warmstarts, quaternions and control clamping are handled
correctly. Both forward and centered differences are supported.
.. _References:
References
+52 -48
View File
@@ -572,13 +572,13 @@ Activation clamping
As described in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo supports actuators
with internal dynamics whose states are called "activations". One useful application of these stateful actuators is the
"integrated-velocity" actuator. Different from the :ref:`pure velocity<velocity>` actuators, which implement direct
feedback on transmission target's velocity, *integrated-velocity* actuators couple an *integrator* with a *position-
feedback* actuator. In this case the semantics of the activation state are "the target of the position actuator", and
the semantics of the control signal are "the velocity of the target of the position actuator". Note that in real robotic
systems this integrated-velocity actuator is the most common implementation of actuators with velocity semantics, rather
than pure feedback on velocity which is often quite unstable (both in real life and in simulation). This actuator type
is implemented by the :ref:`intvelocity<intvelocity>` shortcut.
"integrated-velocity" actuator, implemented by the :ref:`intvelocity<intvelocity>` shortcut. Different from the
:ref:`pure velocity<velocity>` actuators, which implement direct feedback on transmission target's velocity,
*integrated-velocity* actuators couple an *integrator* with a *position-feedback* actuator. In this case the semantics
of the activation state are "the target of the position actuator", and the semantics of the control signal are "the
velocity of the target of the position actuator". Note that in real robotic systems this integrated-velocity actuator is
the most common implementation of actuators with velocity semantics, rather than pure feedback on velocity which is
often quite unstable (both in real life and in simulation).
In the case of integrated-velocity actuators, it is often desirable to *clamp* the activation state, since otherwise the
position target would keep integrating beyond the joint limits, leading to loss of controllabillity. To see the effect
@@ -1223,6 +1223,49 @@ corresponding MJCF can be easily re-created. In our experience though, URDF file
often edited. Thus in practice it is usually sufficient to convert the URDF to MJCF once and after that only work with
the MJCF.
.. _CMocap:
MoCap bodies
~~~~~~~~~~~~
``mocap`` bodies are static children of the world (i.e., have no joints) and their :at:`mocap` attribute is set to
"true". They can be used to input a data stream from a motion capture device into a MuJoCo simulation. Suppose you are
holding a VR controller, or an object instrumented with motion capture markers (e.g. Vicon), and want to have a
simulated object moving in the same way but also interacting with other simulated objects. There is a dilemma here:
virtual objects cannot push on your physical hand, so your hand (and thereby the object you are controlling) can
violate the simulated physics. But at the same time we want the resulting simulation to be reasonable. How do we do
this?
The first step is to define a mocap body in the MJCF model, and implement code that reads the data stream at runtime and
sets mjModel.mocap_pos and mjModel.mocap_quat to the position and orientation received from the motion capture system.
The `simulate.cc <https://github.com/deepmind/mujoco/blob/main/sample/simulate.cc>`_ code sample uses the mouse as a
motion capture device, allowing the user to move mocap bodies around:
|particle|
The key thing to understand about mocap bodies is that the simulator treats them as being fixed. We are causing them
to move from one simulation time step to the next by updating their position and orientation directly, but as far as
the physics model is concerned their position and orientation are constant. So what happens if we make contact with a
regular dynamic body, as in the composite object examples provided with the MuJoCo 2.0 distribution (recall that in
those example we have a capsule probe which is a mocap body that we move with the mouse). A contact between two
regular bodies will experience penetration as well as relative velocity, while contact with a mocap body is missing
the relative velocity component because the simulator does not know that the mocap body itself is moving. So the
resulting contact force is smaller and it takes longer for the contact to push the dynamic object away. Also, in more
complex simulations the fact that we are doing something inconsistent with the physics can cause instabilities.
There is however a better-behaved alternative. In addition to the mocap body, we include a second regular body and
connect it to the mocap body with a weld equality constraint. In the plots below, the pink box is the mocap body and
it is connected to the base of the hand. In the absence of other constraints, the hand tracks the mocap body almost
perfectly (and much better than a spring-damper would) because the constraints are handled implicitly and can produce
large forces without destabilizing the simulation. But if the hand is forced to make contact with the table for example
(right plot) it cannot simultaneously respect the contact constraint and track the mocap body. This is because the
mocap body is free to go through the table. So which constraint wins? That depends on the softness of the weld
constraint realtive to the contact constraint. The corresponding :at:`solref` and :at:`solimp` parameters need to be
adjusted so as to achieve the desired trade-off. See the Modular Prosthetic Limb (MPL) hand model available on the
MuJoCo Forum for an example; the plots below are generated with that model.
|image18| |image19|
.. _Tips:
Tips and tricks
@@ -1351,47 +1394,6 @@ For example if the stack size is just sufficient for the CG solver, the Newton a
When we design models, we usually aim for 50% utilization in the worst-case scenario encountered while exploring the
model. If you only intend to use the CG solver, you can get away with significantly smaller stack allocation.
.. _CMocap:
Motion capture
~~~~~~~~~~~~~~
Mocap bodies are static children of the world (i.e., have no joints) and their :at:`mocap` attribute is set to
"true". They can be used to input a data stream from a motion capture device into a MuJoCo simulation. Suppose you are
holding a VR controller, or an object instrumented with motion capture markers (e.g. Vicon), and want to have a
simulated object moving in the same way but also interacting with other simulated objects. There is a dilemma here:
virtual objects cannot push on your physical hand, so your hand (and thereby the object you are controlling) can
violate the simulated physics. But at the same time we want the resulting simulation to be reasonable. How do we do
this?
The first step is to define a mocap body in the MJCF model, and implement code that reads the data stream at runtime and
sets mjModel.mocap_pos and mjModel.mocap_quat to the position and orientation received from the motion capture system.
The `simulate.cc <https://github.com/deepmind/mujoco/blob/main/sample/simulate.cc>`_ code sample uses the mouse as a
motion capture device, allowing the user to move mocap bodies around.
The key thing to understand about mocap bodies is that the simulator treats them as being fixed. We are causing them
to move from one simulation time step to the next by updating their position and orientation directly, but as far as
the physics model is concerned their position and orientation are constant. So what happens if we make contact with a
regular dynamic body, as in the composite object examples provided with the MuJoCo 2.0 distribution (recall that in
those example we have a capsule probe which is a mocap body that we move with the mouse). A contact between two
regular bodies will experience penetration as well as relative velocity, while contact with a mocap body is missing
the relative velocity component because the simulator does not know that the mocap body itself is moving. So the
resulting contact force is smaller and it takes longer for the contact to push the dynamic object away. Also, in more
complex simulations the fact that we are doing something inconsistent with the physics can cause instabilities.
There is however a better-behaved alternative. In addition to the mocap body, we include a second regular body and
connect it to the mocap body with a weld equality constraint. In the plots below, the pink box is the mocap body and
it is connected to the base of the hand. In the absence of other constraints, the hand tracks the mocap body almost
perfectly (and much better than a spring-damper would) because the constraints are handled implicitly and can produce
large forces without destabilizing the simulation. But if the hand is forced to make contact with the table for example
(right plot) it cannot simultaneously respect the contact constraint and track the mocap body. This is because the
mocap body is free to go through the table. So which constraint wins? That depends on the softness of the weld
constraint realtive to the contact constraint. The corresponding :at:`solref` and :at:`solimp` parameters need to be
adjusted so as to achieve the desired trade-off. See the Modular Prosthetic Limb (MPL) hand model available on the
MuJoCo Forum for an example; the plots below are generated with that model.
|image18| |image19|
.. |image0| image:: images/modeling/impedance.png
:width: 600px
.. |image1| image:: images/modeling/musclemodel.png
@@ -1432,4 +1434,6 @@ MuJoCo Forum for an example; the plots below are generated with that model.
:height: 250px
.. |image19| image:: images/modeling/mocap2.png
:height: 250px
.. |particle| image:: images/models/particle.gif
:width: 270px
.. _simulate.cc: https://github.com/deepmind/mujoco/blob/main/sample/simulate.cc
+5 -5
View File
@@ -340,11 +340,11 @@ illustration of how the new UI framework is intended to be used. Below is a scre
.. youtube:: 0ORsj_E17B0
:align: center
Interaction is done with the mouse; see the built-in help for summary of available commands. Briefly, an object is
selected by left-double-click. The user can then apply forces and torques on the selected object by holding Ctrl and
dragging the mouse. Dragging the mouse alone (without Ctrl) moves the camera. There are keyboard shortcuts for pausing
the simulation, resetting, and re-loading the model file. The latter functionality is very useful while editing the
model in an XML editor.
Interaction is done with the mouse; built-in help with a summary of available commands is available by pressing the 'F1'
key. Briefly, an object is selected by left-double-click. The user can then apply forces and torques on the selected
object by holding Ctrl and dragging the mouse. Dragging the mouse alone (without Ctrl) moves the camera. There are
keyboard shortcuts for pausing the simulation, resetting, and re-loading the model file. The latter functionality is
very useful while editing the model in an XML editor.
The code is quite long yet reasonably commented, so it is best to just read it. Here we provide a high-level overview.
The ``main()`` function initializes both MuJoCo and GLFW, opens a window, and install GLFW callbacks for mouse and
+4 -1
View File
@@ -1085,7 +1085,10 @@ MJAPI mjtNum mju_sigmoid(mjtNum x);
//---------------------- Derivatives ---------------------------------------------------------------
// finite differenced state-transition and control-transition matrices dy = A*dx + B*du
// Finite differenced state-transition and control-transition matrices dx(t+h) = A*dx(t) + B*du(t).
// required output matrix dimensions:
// A: (2*nv+na x 2*nv+na)
// B: (2*nv+na x nu)
MJAPI void mjd_transitionFD(const mjModel* m, mjData* d, mjtNum eps, mjtByte centered,
mjtNum* A, mjtNum* B);
+1 -1
View File
@@ -6931,6 +6931,6 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
),
),
),
doc='finite differenced state-transition and control-transition matrices dy = A*dx + B*du', # pylint: disable=line-too-long
doc='Finite differenced state-transition and control-transition matrices dx(t+h) = A*dx(t) + B*du(t). required output matrix dimensions: A: (2*nv+na x 2*nv+na) B: (2*nv+na x nu)', # pylint: disable=line-too-long
)),
])