Preparation for MIMO actuators: split actuator counts: nu (inputs), nactuator (objects), nout (outputs).
An actuator now owns a block of consecutive controls (actuator_ctrladr/ctrlnum, width defined by the actuator type) and a block of consecutive force outputs (actuator_outadr/outnum, width defined by the transmission type). Force outputs are the scalars of actuation space: one force, length, velocity and moment row each. nout = dim(actuator_force) is derived from transmission types; all current types have width 1, so all three counts coincide for every existing model and behavior is bit-exact. Array re-keying: ctrlrange/ctrllimited by nu; forcerange/forcelimited/gear/ acc0/length0/lengthrange and the moment row structure by nout; everything else per actuator. The mjModel actuator block is re-sorted by size key. Layout-breaking, not behavior-breaking: saved .mjb files are invalidated (size list changed) and recompilation is required. PiperOrigin-RevId: 948351772 Change-Id: Icbc196ffa083cb1eaa6f1a3710869c89d8f62540
This commit is contained in:
committed by
Copybara-Service
parent
06f12a9372
commit
d507e92198
@@ -31,6 +31,11 @@ General
|
||||
error instead of the generic "could not decode content" message.
|
||||
- Added support for resource writing via :ref:`mju_writeResource` and the ``write`` callback in :ref:`mjpResourceProvider`.
|
||||
- Added support for :ref:`multiccd <coMultiCCD>` with arbitrarily large meshes.
|
||||
- Refactored actuator infrastructure in preparation for MIMO (multi-input multi-output) actuator support. Each actuator
|
||||
now has ``ctrlnum`` (number of controls) and ``outnum`` (number of force outputs). The total counts
|
||||
``nu = sum(ctrlnum)`` and ``nout = sum(outnum)`` dimension ``mjData.ctrl`` and ``mjData.actuator_force``,
|
||||
respectively, ``nactuator`` is the number of actuators. For existing actuators ``ctrnum = outnum = 1``, so
|
||||
``nactuator == nu == nout`` and existing code is unaffected.
|
||||
|
||||
.. admonition:: Breaking API changes
|
||||
:class: attention
|
||||
|
||||
+34
-27
@@ -262,12 +262,21 @@ detailed summary of the :ref:`simulation pipeline <Pipeline>` is given at the en
|
||||
Actuation model
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
MuJoCo provides a flexible actuator model. All actuators are single-input-single-output (SISO). The input to actuator
|
||||
:math:`i` is a scalar control :math:`u_i` specified by the user. The output is a scalar force :math:`p_i` which is
|
||||
mapped to joint coordinates by a vector of moment arms determined by the transmission. An actuator can also have
|
||||
activation state :math:`w_i` with its own dynamics. The control inputs for all actuators are stored in ``mjData.ctrl``,
|
||||
the force outputs are stored in ``mjData.actuator_force``, and the activation states (if any) are stored in
|
||||
``mjData.act``.
|
||||
MuJoCo provides a flexible actuator model. Most actuators are single-input-single-output (SISO): the input to
|
||||
actuator :math:`i` is a scalar control :math:`u_i` specified by the user, and the output is a scalar force
|
||||
:math:`p_i`, which is mapped to joint coordinates by a vector of moment arms determined by the transmission. An
|
||||
actuator can also have activation state :math:`w_i` with its own dynamics. The control inputs for all actuators are
|
||||
stored in ``mjData.ctrl``, the force outputs are stored in ``mjData.actuator_force``, and the activation states (if
|
||||
any) are stored in ``mjData.act``.
|
||||
|
||||
More generally, an actuator can have several control inputs, several force outputs, or both. For example, a servo
|
||||
which accepts both a position setpoint and a velocity setpoint has two inputs and one output. The number of inputs
|
||||
is a property of the actuator type, and the number of outputs is a property of its transmission; neither is
|
||||
specified directly by the user. Since the number of inputs and the number of outputs can vary per actuator, the model
|
||||
has three separate counts: the number of actuators ``nactuator``, the total number of controls ``nu``, and the total
|
||||
number of force outputs ``nout``. In a model where all actuators are SISO, all three are equal. Note that outputs are
|
||||
counted in actuation space, before the mapping to joint coordinates: a tendon actuator with a single force output can
|
||||
move many joints.
|
||||
|
||||
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
|
||||
@@ -278,11 +287,13 @@ actuator works. The user can set them independently for maximum flexibility, or
|
||||
Transmission
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Each actuator has a scalar length :math:`l_i(q)` defined by the type of transmission and its parameters. The gradient
|
||||
:math:`\nabla l_i` is an :math:`\nv`-dimensional vector of moment arms. It determines the mapping from scalar
|
||||
actuator force to joint force. The transmission properties are determined by the MuJoCo object to which the actuator
|
||||
is attached; the possible attachment object types are :at:`joint`, :at:`tendon`, :at:`jointinparent`,
|
||||
:at:`slider-crank`, :at:`site`, and :at:`body`.
|
||||
The transmission attaches the actuator to the rest of the system. Each force output of the actuator has a scalar
|
||||
length :math:`l_k(q)`, defined by the type of transmission and its parameters, for example the
|
||||
:ref:`gear<actuator-general-gear>` vector. The gradient :math:`\nabla l_k` is an :math:`\nv`-dimensional vector of
|
||||
moment arms; it determines the mapping from the scalar output force to joint forces. The number of force outputs is
|
||||
likewise determined by the transmission; all the types listed below define a single output. The transmission
|
||||
properties are determined by the MuJoCo object to which the actuator is attached; the possible attachment object
|
||||
types are :at:`joint`, :at:`tendon`, :at:`jointinparent`, :at:`slider-crank`, :at:`site`, and :at:`body`.
|
||||
|
||||
:at:`joint` and :at:`tendon`
|
||||
The :at:`joint` and :at:`tendon` transmission types act as expected and correspond to the actuator applying forces or
|
||||
@@ -369,14 +380,10 @@ diverge for :math:`\texttt{t} < h`, while exactly-integrated filters are stable
|
||||
Force generation
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Each actuator generates a scalar force :math:`p_i` which is some function
|
||||
|
||||
.. math::
|
||||
p_i \left( u_i, w_i, l_i, \dot{l}_i \right)
|
||||
|
||||
Similarly to activation dynamics, the force generation mechanism is actuator-specific and cannot interact with the
|
||||
other actuators in the model. Currently the force is affine in the activation state when present, and in the control
|
||||
otherwise:
|
||||
Each actuator generates a scalar force for each of its outputs, as a function of its controls, activation states,
|
||||
and lengths and velocities. Similarly to activation dynamics, force generation is actuator-specific: the inputs and
|
||||
outputs of a single actuator can interact, but different actuators cannot affect each other. For SISO actuators the
|
||||
force is affine in the activation state when present, and in the control otherwise:
|
||||
|
||||
.. math::
|
||||
p_i = (a w_i \; \text{or} \; a u_i) + b_0 + b_1 l_i + b_2 \dot{l}_i
|
||||
@@ -384,17 +391,17 @@ otherwise:
|
||||
Here :math:`a` is an actuator-specific gain parameter and :math:`b_0, b_1, b_2` are actuator-specific bias
|
||||
parameters, stored in ``mjModel.actuator_gainprm`` and ``mjModel.actuator_biasprm`` respectively. Different settings
|
||||
of the gain and bias parameters can be used to model direct force control as well as position and velocity servos -in
|
||||
which case the control/activation has the meaning of reference position or velocity. One can also compute custom gain
|
||||
and bias terms by installing the callbacks :ref:`mjcb_act_gain` and :ref:`mjcb_act_bias` and setting the gain and
|
||||
bias type to "user". Note that affine force generation makes it possible to infer the controls/activations from the
|
||||
applied force computed in inverse dynamics, using the pseudo-inverse of the matrix of moment arms. However some of
|
||||
the actuators used in the real world are not affine (especially those that have embedded low-level controllers), so
|
||||
we are considering extensions to the above model.
|
||||
which case the control/activation has the meaning of reference position or velocity. Multi-input actuator types
|
||||
define their own force laws. One can also compute custom gain and bias terms for SISO actuators by installing the
|
||||
callbacks :ref:`mjcb_act_gain` and :ref:`mjcb_act_bias` and setting the gain and bias type to "user". Note that
|
||||
affine force generation makes it possible to infer the controls/activations from the applied force computed in
|
||||
inverse dynamics, using the pseudo-inverse of the matrix of moment arms.
|
||||
|
||||
Putting all this together, the net force in generalized coordinates contributed by all actuators is
|
||||
Putting all this together, the net force in generalized coordinates contributed by all actuators is the sum over all
|
||||
force outputs
|
||||
|
||||
.. math::
|
||||
\sum_i \nabla l_i(q) \; p_i \left(u_i, w_i, l_i(q), \dot{l}_i(q, v) \right)
|
||||
\sum_k \nabla l_k(q) \; p_k
|
||||
|
||||
This quantity is stored in ``mjData.qfrc_actuator``. It is added to the applied force vector :math:`\tau`, together
|
||||
with any user-defined forces in joint or Cartesian coordinates (which are stored in ``mjData.qfrc_applied`` and
|
||||
|
||||
+43
-37
@@ -215,9 +215,9 @@ typedef struct mjData_ {
|
||||
mjtNum* wrap_xpos; // Cartesian 3D points in all paths (nwrap x 6)
|
||||
|
||||
// computed by mj_fwdPosition/mj_transmission
|
||||
mjtNum* actuator_length; // actuator lengths (nu x 1)
|
||||
int* moment_rownnz; // number of non-zeros in actuator_moment row (nu x 1)
|
||||
int* moment_rowadr; // row start address in colind array (nu x 1)
|
||||
mjtNum* actuator_length; // actuator lengths, one per force output (nout x 1)
|
||||
int* moment_rownnz; // number of non-zeros in actuator_moment row (nout x 1)
|
||||
int* moment_rowadr; // row start address in colind array (nout x 1)
|
||||
int* moment_colind; // column indices in sparse Jacobian (nJmom x 1)
|
||||
mjtNum* actuator_moment; // actuator moments (nJmom x 1)
|
||||
|
||||
@@ -244,7 +244,7 @@ typedef struct mjData_ {
|
||||
// computed by mj_fwdVelocity
|
||||
mjtNum* flexedge_velocity; // flex edge velocities (nflexedge x 1)
|
||||
mjtNum* ten_velocity; // tendon velocities (ntendon x 1)
|
||||
mjtNum* actuator_velocity; // actuator velocities (nu x 1)
|
||||
mjtNum* actuator_velocity; // actuator velocities, one per force output (nout x 1)
|
||||
|
||||
// computed by mj_fwdVelocity/mj_comVel
|
||||
mjtNum* cvel; // com-based velocity (rot:lin) (nbody x 6)
|
||||
@@ -277,8 +277,8 @@ typedef struct mjData_ {
|
||||
//-------------------- POSITION, VELOCITY, CONTROL/ACCELERATION dependent
|
||||
|
||||
// computed by mj_fwdActuation
|
||||
mjtNum* actuator_force; // actuator force in actuation space (nu x 1)
|
||||
mjtNum* qfrc_actuator; // actuator force (nv x 1)
|
||||
mjtNum* actuator_force; // actuator force in actuation space (nout x 1)
|
||||
mjtNum* qfrc_actuator; // actuator force in joint space (nv x 1)
|
||||
|
||||
// computed by mj_fwdAcceleration
|
||||
mjtNum* qfrc_smooth; // net unconstrained force (nv x 1)
|
||||
@@ -557,7 +557,9 @@ typedef struct mjModel_ {
|
||||
// sizes needed at mjModel construction
|
||||
mjtSize nq; // number of generalized coordinates = dim(qpos)
|
||||
mjtSize nv; // number of degrees of freedom = dim(qvel)
|
||||
mjtSize nu; // number of actuators/controls = dim(ctrl)
|
||||
mjtSize nu; // number of scalar controls = dim(ctrl)
|
||||
mjtSize nactuator; // number of actuators
|
||||
mjtSize nout; // number of force outputs, derived from transmission type
|
||||
mjtSize na; // number of activation states = dim(act)
|
||||
mjtSize nbody; // number of bodies
|
||||
mjtSize nbvh; // number of total bounding volumes in all bodies
|
||||
@@ -1072,37 +1074,41 @@ typedef struct mjModel_ {
|
||||
mjtNum* wrap_prm; // divisor, joint coef, or site id (nwrap x 1)
|
||||
|
||||
// actuators
|
||||
int* actuator_trntype; // transmission type (mjtTrn) (nu x 1)
|
||||
int* actuator_dyntype; // dynamics type (mjtDyn) (nu x 1)
|
||||
int* actuator_gaintype; // gain type (mjtGain) (nu x 1)
|
||||
int* actuator_biastype; // bias type (mjtBias) (nu x 1)
|
||||
int* actuator_trnid; // transmission id: joint, tendon, site (nu x 2)
|
||||
mjtNum* actuator_damping; // linear damping coefficient (nu x 1)
|
||||
mjtNum* actuator_dampingpoly; // high-order damping coefficients (nu x mjNPOLY)
|
||||
mjtNum* actuator_armature; // armature added to target (joint, tendon) (nu x 1)
|
||||
int* actuator_actadr; // first activation address; -1: stateless (nu x 1)
|
||||
int* actuator_actnum; // number of activation variables (nu x 1)
|
||||
int* actuator_group; // group for visibility (nu x 1)
|
||||
int* actuator_history; // history buffer: [nsample, interp] (nu x 2)
|
||||
int* actuator_historyadr; // address in history buffer; -1: none (nu x 1)
|
||||
mjtNum* actuator_delay; // delay time in seconds; 0: no delay (nu x 1)
|
||||
int* actuator_trntype; // transmission type (mjtTrn) (nactuator x 1)
|
||||
int* actuator_dyntype; // dynamics type (mjtDyn) (nactuator x 1)
|
||||
int* actuator_gaintype; // gain type (mjtGain) (nactuator x 1)
|
||||
int* actuator_biastype; // bias type (mjtBias) (nactuator x 1)
|
||||
int* actuator_ctrladr; // address of first control (nactuator x 1)
|
||||
int* actuator_ctrlnum; // number of controls (nactuator x 1)
|
||||
int* actuator_outadr; // address of first force output (nactuator x 1)
|
||||
int* actuator_outnum; // number of force outputs, from trntype (nactuator x 1)
|
||||
int* actuator_actadr; // first activation address; -1: stateless (nactuator x 1)
|
||||
int* actuator_actnum; // number of activation variables (nactuator x 1)
|
||||
int* actuator_trnid; // transmission id: joint, tendon, site (nactuator x 2)
|
||||
mjtNum* actuator_cranklength; // crank length for slider-crank (nactuator x 1)
|
||||
mjtNum* actuator_dynprm; // dynamics parameters (nactuator x mjNDYN)
|
||||
mjtNum* actuator_gainprm; // gain parameters (nactuator x mjNGAIN)
|
||||
mjtNum* actuator_biasprm; // bias parameters (nactuator x mjNBIAS)
|
||||
mjtBool* actuator_actlimited; // is activation limited (nactuator x 1)
|
||||
mjtNum* actuator_actrange; // range of activations (nactuator x 2)
|
||||
mjtBool* actuator_actearly; // step activation before force (nactuator x 1)
|
||||
int* actuator_history; // history buffer: [nsample, interp] (nactuator x 2)
|
||||
int* actuator_historyadr; // address in history buffer; -1: none (nactuator x 1)
|
||||
mjtNum* actuator_delay; // delay time; 0: no delay (nactuator x 1)
|
||||
mjtNum* actuator_damping; // linear damping coefficient (nactuator x 1)
|
||||
mjtNum* actuator_dampingpoly; // high-order damping coefficients (nactuator x mjNPOLY)
|
||||
mjtNum* actuator_armature; // armature added to target (joint, tendon) (nactuator x 1)
|
||||
int* actuator_group; // group for visibility (nactuator x 1)
|
||||
mjtNum* actuator_user; // user data (nactuator x nuser_actuator)
|
||||
int* actuator_plugin; // plugin instance id; -1: not a plugin (nactuator x 1)
|
||||
mjtBool* actuator_ctrllimited; // is control limited (nu x 1)
|
||||
mjtBool* actuator_forcelimited;// is force limited (nu x 1)
|
||||
mjtBool* actuator_actlimited; // is activation limited (nu x 1)
|
||||
mjtNum* actuator_dynprm; // dynamics parameters (nu x mjNDYN)
|
||||
mjtNum* actuator_gainprm; // gain parameters (nu x mjNGAIN)
|
||||
mjtNum* actuator_biasprm; // bias parameters (nu x mjNBIAS)
|
||||
mjtBool* actuator_actearly; // step activation before force (nu x 1)
|
||||
mjtNum* actuator_ctrlrange; // range of controls (nu x 2)
|
||||
mjtNum* actuator_forcerange; // range of forces (nu x 2)
|
||||
mjtNum* actuator_actrange; // range of activations (nu x 2)
|
||||
mjtNum* actuator_gear; // scale length and transmitted force (nu x 6)
|
||||
mjtNum* actuator_cranklength; // crank length for slider-crank (nu x 1)
|
||||
mjtNum* actuator_acc0; // acceleration from unit force in qpos0 (nu x 1)
|
||||
mjtNum* actuator_length0; // actuator length in qpos0 (nu x 1)
|
||||
mjtNum* actuator_lengthrange; // feasible actuator length range (nu x 2)
|
||||
mjtNum* actuator_user; // user data (nu x nuser_actuator)
|
||||
int* actuator_plugin; // plugin instance id; -1: not a plugin (nu x 1)
|
||||
mjtNum* actuator_gear; // scale length and transmitted force (nout x 6)
|
||||
mjtBool* actuator_forcelimited;// is force limited (nout x 1)
|
||||
mjtNum* actuator_forcerange; // range of forces (nout x 2)
|
||||
mjtNum* actuator_acc0; // acceleration from unit force in qpos0 (nout x 1)
|
||||
mjtNum* actuator_length0; // actuator length in qpos0 (nout x 1)
|
||||
mjtNum* actuator_lengthrange; // feasible actuator length range (nout x 2)
|
||||
|
||||
// sensors
|
||||
int* sensor_type; // sensor type (mjtSensor) (nsensor x 1)
|
||||
@@ -1174,7 +1180,7 @@ typedef struct mjModel_ {
|
||||
int* name_excludeadr; // exclude name pointers (nexclude x 1)
|
||||
int* name_eqadr; // equality constraint name pointers (neq x 1)
|
||||
int* name_tendonadr; // tendon name pointers (ntendon x 1)
|
||||
int* name_actuatoradr; // actuator name pointers (nu x 1)
|
||||
int* name_actuatoradr; // actuator name pointers (nactuator x 1)
|
||||
int* name_sensoradr; // sensor name pointers (nsensor x 1)
|
||||
int* name_numericadr; // numeric name pointers (nnumeric x 1)
|
||||
int* name_textadr; // text name pointers (ntext x 1)
|
||||
|
||||
Reference in New Issue
Block a user