Add mjtState enum and related mj_stateSize, mj_getState and mj_setState functions.

PiperOrigin-RevId: 539667943
Change-Id: I14c34be8ce4c287e529380257b5c5bffc3ab45ce
This commit is contained in:
Yuval Tassa
2023-06-12 08:55:58 -07:00
committed by Copybara-Service
parent 84c33e53df
commit f67e359532
16 changed files with 520 additions and 41 deletions
+12
View File
@@ -346,6 +346,18 @@ Data
The enums below are defined in `mjdata.h <https://github.com/deepmind/mujoco/blob/main/include/mujoco/mjdata.h>`_.
.. _mjtState:
mjtState
~~~~~~~~
State component elements as integer bitflags and several convenient combinations of these flags. Used by
:ref:`mj_getState`, :ref:`mj_setState` and :ref:`mj_stateSize`.
.. mujoco-include:: mjtState
.. _mjtWarning:
mjtWarning
+30
View File
@@ -151,6 +151,36 @@ These are support functions that need access to :ref:`mjModel` and :ref:`mjData`
not need such access. Support functions are called within the simulator but some of them can also be useful for custom
computations, and are documented in more detail below.
.. _mj_stateSize:
mj_stateSize
~~~~~~~~~~~~
.. mujoco-include:: mj_stateSize
Returns the number of :ref:`mjtNum` |-| s required for a given state specification. The bits of the integer ``spec``
correspond to element fields of :ref:`mjtState`.
.. _mj_getState:
mj_getState
~~~~~~~~~~~
.. mujoco-include:: mj_getState
Copy concatenated state components specified by ``spec`` from ``d`` into ``state``. The bits of the integer
``spec`` correspond to element fields of :ref:`mjtState`. Fails with :ref:`mju_error` if ``spec`` is invalid.
.. _mj_setState:
mj_setState
~~~~~~~~~~~
.. mujoco-include:: mj_setState
Copy concatenated state components specified by ``spec`` from ``state`` into ``d``. The bits of the integer
``spec`` correspond to element fields of :ref:`mjtState`. Fails with :ref:`mju_error` if ``spec`` is invalid.
.. _mj_addContact:
mj_addContact
+15
View File
@@ -96,6 +96,21 @@ These are support functions that need access to :ref:`mjModel` and :ref:`mjData`
not need such access. Support functions are called within the simulator but some of them can also be useful for custom
computations, and are documented in more detail below.
.. _mj_stateSize:
Returns the number of :ref:`mjtNum` |-| s required for a given state specification. The bits of the integer ``spec``
correspond to element fields of :ref:`mjtState`.
.. _mj_getState:
Copy concatenated state components specified by ``spec`` from ``d`` into ``state``. The bits of the integer
``spec`` correspond to element fields of :ref:`mjtState`. Fails with :ref:`mju_error` if ``spec`` is invalid.
.. _mj_setState:
Copy concatenated state components specified by ``spec`` from ``state`` into ``d``. The bits of the integer
``spec`` correspond to element fields of :ref:`mjtState`. Fails with :ref:`mju_error` if ``spec`` is invalid.
.. _mj_mulJacVec:
This function multiplies the constraint Jacobian mjData.efc_J by a vector. Note that the Jacobian can be either dense or
+2
View File
@@ -63,6 +63,8 @@ Simulate
General
^^^^^^^
- Added :ref:`mj_getState` and :ref:`mj_setState` for getting and setting the simulation state as a concatenated vector
of floating point numbers. See the :ref:`State<geState>` section for details.
- Added :ref:`mjContact.solreffriction<mjContact>`, allowing different :ref:`solref<CSolver>` parameters for the normal
and frictional axes of contacts when using :ref:`elliptic friction cones<option-cone>`. This attribute is required
for elastic frictional collisions, see associated
+49 -37
View File
@@ -569,41 +569,60 @@ Fast implicit-in-velocity (``implicitfast``)
.. _geState:
The **state**
~~~~~~~~~~~~~
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:
well-defined internal state which, together with the :ref:`deterministic computational pipeline<piReproducibility>`,
means that operations like resetting the state and computing dynamics derivatives are also well-defined.
The state is entirely encapsulated in the :ref:`mjData` struct and consists of several components. The components are
enumerated in :ref:`mjtState` as bit flags, along with several common combinations, corresponding to the groupings
below. Concatenated state vectors can be conveniently read from and written into :ref:`mjData` using :ref:`mj_getState`
and :ref:`mj_setState`, respectively.
.. _gePhysicsState:
Physics state
^^^^^^^^^^^^^
The *physics state* contains all quantities which are time-integrated during stepping.
These are ``mjData.{qpos, qvel, act, time}``:
The *physics state* (:ref:`mjSTATE_PHYSICS<mjtState>`) contains the main quantities which are time-integrated during
stepping. These are ``mjData.{qpos, qvel, act}``:
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.
Position: ``qpos``
The configuration in generalized coodinates, denoted above as :math:`q`.
Actuator activations: ``act``
Velocity: ``qvel``
The generalized velocities, denoted above as :math:`v`.
Actuator activation: ``act``
``mjData.act`` contains the internal states of stateful actuators, denoted above as :math:`w`.
.. _geFullPhysics:
Full physics state
^^^^^^^^^^^^^^^^^^
The *full physics state* (:ref:`mjSTATE_FULLPHYSICS<mjtState>`) contains the physics state and two additional
components:
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
The simulation time is given by the scalar ``mjData.time``. Since physics is time-invariant, it is
excluded from the *physics state*; exceptions include time-dependent user callbacks and plugins (e.g., an open-loop
controller), in which case time should be included.
Plugin state: ``plugin_state``
``mjData.plugin_state`` are states declared by :ref:`engine plugins<exPlugin>`. Please see the :ref:`exPluginState`
section for more details.
.. _geInput:
User inputs
^^^^^^^^^^^
These input fields are set by the user and affect the physics simulation, but are untouched by the simulator. All input
fields except for MoCap poses default to 0.
Controls: ``ctrl``
These input fields (:ref:`mjSTATE_USER<mjtState>`) are set by the user and affect the physics simulation, but are
untouched by the simulator. All input fields except for MoCap poses default to 0.
Control: ``ctrl``
Controls are defined by the :ref:`actuator<actuator>` section of the XML. ``mjData.ctrl`` values either produce
generalized forces directly (stateless actuators), or affect the actuator activations in ``mjData.act``, which then
produce forces.
@@ -627,8 +646,8 @@ User data: ``userdata``
.. _geWarmstart:
Warmstart accelerations
^^^^^^^^^^^^^^^^^^^^^^^
Warmstart acceleration
^^^^^^^^^^^^^^^^^^^^^^
``qacc_warmstart``
``mjData.qacc_warmstart`` are accelerations used to warmstart the constraint solver, saved from the previous step.
@@ -642,34 +661,27 @@ Warmstart accelerations
<https://en.wikipedia.org/wiki/Lyapunov_exponent>`__ when time-stepping, quickly leading to divergent trajectories
for different warmstarts.
.. _gePlugin:
Plugin state
^^^^^^^^^^^^
``plugin_state``
``mjData.plugin_state`` are states declared by :ref:`engine plugins<exPlugin>`. Please see the :ref:`exPluginState`
section for more details.
.. _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.
|br| When saving the integration state in order to reload it elsewhere, it is sensible to avoid saving unused fields
that always remain in their default values. Specifically, ``xfrc_applied`` can be quite large (``6 x nbody``) yet is
often unused.
The *integration state* (:ref:`mjSTATE_INTEGRATION<mjtState>`) is the union of all the above :ref:`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 :ref:`mjData` fields are functions of the integration state.
Note that the full integration state as given by :ref:`mjSTATE_INTEGRATION<mjtState>` is maximalist and includes fields
which are often unused. If a small state size is desired, it might be sensible to avoid saving unused fields.
In particular `xfrc_applied`` can be quite large (``6 x nbody``) yet is often unused.
.. _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
The *simulation state* is the entirety of the :ref:`mjData` struct and associated memory buffer. This state includes
all derived quantities computed during dynamics computation. Because the :ref:`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``.
using :ref:`mj_copyData`.
.. _Constraint:
@@ -1591,7 +1603,7 @@ MuJoCo's simulation pipeline is entirely deterministic and reproducible -- if a
saved and reloaded and :ref:`mj_step` called again, the resulting next state will be identical. However, there are some
important caveats:
- Save all the required :ref:`integration state<IntegrationState>` components. In particular :ref:`warmstart
- Save all the required :ref:`integration state<geIntegrationState>` components. In particular :ref:`warmstart
accelerations<geWarmstart>` have only a very small effect on the next state, but should be saved if bit-wise equality
is required.
- Any numerical difference between states, no matter how small, will become significant upon integration, especially for
+26
View File
@@ -16,6 +16,29 @@
// Error: C reference not found
// NOLINTBEGIN
typedef enum mjtState_ { // state elements
mjSTATE_TIME = 1<<0, // time
mjSTATE_QPOS = 1<<1, // position
mjSTATE_QVEL = 1<<2, // velocity
mjSTATE_ACT = 1<<3, // actuator activation
mjSTATE_WARMSTART = 1<<4, // acceleration used for warmstart
mjSTATE_CTRL = 1<<5, // control
mjSTATE_QFRC_APPLIED = 1<<6, // applied generalized force
mjSTATE_XFRC_APPLIED = 1<<7, // applied Cartesian force/torque
mjSTATE_MOCAP_POS = 1<<8, // positions of mocap bodies
mjSTATE_MOCAP_QUAT = 1<<9, // orientations of mocap bodies
mjSTATE_USERDATA = 1<<10, // user data
mjSTATE_PLUGIN = 1<<11, // plugin state
mjNSTATE = 12, // number of state elements
// convenience values for commonly used state specifications
mjSTATE_PHYSICS = mjSTATE_QPOS | mjSTATE_QVEL | mjSTATE_ACT,
mjSTATE_FULLPHYSICS = mjSTATE_PHYSICS | mjSTATE_TIME | mjSTATE_PLUGIN,
mjSTATE_USER = mjSTATE_CTRL | mjSTATE_QFRC_APPLIED | mjSTATE_XFRC_APPLIED |
mjSTATE_MOCAP_POS | mjSTATE_MOCAP_QUAT | mjSTATE_USERDATA,
mjSTATE_INTEGRATION = mjSTATE_FULLPHYSICS | mjSTATE_USER | mjSTATE_WARMSTART
} mjtState;
typedef enum mjtWarning_ { // warning types
mjWARN_INERTIA = 0, // (near) singular inertia matrix
mjWARN_CONTACTFULL, // too many contacts in contact list
@@ -2176,6 +2199,9 @@ void mj_projectConstraint(const mjModel* m, mjData* d);
void mj_referenceConstraint(const mjModel* m, mjData* d);
void mj_constraintUpdate(const mjModel* m, mjData* d, const mjtNum* jar,
mjtNum cost[1], int flg_coneHessian);
int mj_stateSize(const mjModel* m, unsigned int spec);
void mj_getState(const mjModel* m, const mjData* d, mjtNum* state, unsigned int spec);
void mj_setState(const mjModel* m, mjData* d, const mjtNum* state, unsigned int spec);
int mj_addContact(const mjModel* m, mjData* d, const mjContact* con);
int mj_isPyramidal(const mjModel* m);
int mj_isSparse(const mjModel* m);