Initial open sourcing of MuJoCo.
PiperOrigin-RevId: 450374687 Change-Id: Ie3225a46ce095fc28ae8e63c326a640261f562bb
This commit is contained in:
committed by
Copybara-Service
parent
0e5d062302
commit
1913a02b40
+290
-216
@@ -243,13 +243,13 @@ coordinates, but that effort is rarely justified.
|
||||
Frame orientations
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Several model elements have right-handed spatial frames associated with them. These are all the elements defined in
|
||||
the kinematic tree except for joints. A spatial frame is defined by its position and orientation. Specifying 3D
|
||||
positions is straightforward, but specifying 3D orientations can be challenging. This is why MJCF provides several
|
||||
alternative mechanisms. No matter which mechanism the user chooses, the frame orientation is always represented as a
|
||||
unit quaternion after compilation. Recall that a 3D rotation by angle *a* around axis given by the unit vector (*x, y,
|
||||
z*) corresponds to the quaternion (cos(*a*/2), sin(*a*/2) \* (*x, y, z*)). Also recall that every 3D orientation can
|
||||
be uniquely specified by a single 3D rotation by some angle around some axis.
|
||||
Several model elements have right-handed spatial frames associated with them. These are all the elements defined in the
|
||||
kinematic tree except for joints. A spatial frame is defined by its position and orientation. Specifying 3D positions is
|
||||
straightforward, but specifying 3D orientations can be challenging. This is why MJCF provides several alternative
|
||||
mechanisms. No matter which mechanism the user chooses, the frame orientation is always represented as a unit quaternion
|
||||
after compilation. Recall that a 3D rotation by angle :math:`a` around axis given by the unit vector :math:`(x, y, z)`
|
||||
corresponds to the quaternion :math:`(\cos(a/2), \: \sin(a/2) \cdot (x, y, z))`. Also recall that every 3D orientation
|
||||
can be uniquely specified by a single 3D rotation by some angle around some axis.
|
||||
|
||||
All MJCF elements that have spatial frames allow the five attributes listed below. The frame orientation is specified
|
||||
using at most one of these attributes. The :at:`quat` attribute has a default value corresponding to the null
|
||||
@@ -261,12 +261,12 @@ specified by the user, the frame is not rotated.
|
||||
conversions. Instead it is normalized to unit length and copied into mjModel during compilation. When a model is
|
||||
saved as MJCF, all frame orientations are expressed as quaternions using this attribute.
|
||||
:at:`axisangle`: :at-val:`real(4), optional`
|
||||
These are the quantities (*x, y, z, a*) mentioned above. The last number is the angle of rotation, in degrees or
|
||||
radians as specified by the :at:`angle` attribute of :ref:`compiler <compiler>`. The first three
|
||||
numbers determine a 3D vector which is the rotation axis. This vector is normalized to unit length during
|
||||
compilation, so the user can specify a vector of any non-zero length. Keep in mind that the rotation is right-handed;
|
||||
if the direction of the vector (*x, y, z*) is reversed this will result in the opposite rotation. Changing the sign
|
||||
of *a* can also be used to specify the opposite rotation.
|
||||
These are the quantities :math:`(x, y, z, a)` mentioned above. The last number is the angle of rotation, in degrees
|
||||
or radians as specified by the :at:`angle` attribute of :ref:`compiler <compiler>`. The first three numbers determine
|
||||
a 3D vector which is the rotation axis. This vector is normalized to unit length during compilation, so the user can
|
||||
specify a vector of any non-zero length. Keep in mind that the rotation is right-handed; if the direction of the
|
||||
vector :math:`(x, y, z)` is reversed this will result in the opposite rotation. Changing the sign of :math:`a` can
|
||||
also be used to specify the opposite rotation.
|
||||
:at:`euler`: :at-val:`real(3), optional`
|
||||
Rotation angles around three coordinate axes. The sequence of axes around which these rotations are applied is
|
||||
determined by the :at:`eulerseq` attribute of :ref:`compiler <compiler>` and is the same for the
|
||||
@@ -275,96 +275,110 @@ specified by the user, the frame is not rotated.
|
||||
The first 3 numbers are the X axis of the frame. The next 3 numbers are the Y axis of the frame, which is
|
||||
automatically made orthogonal to the X axis. The Z axis is then defined as the cross-product of the X and Y axes.
|
||||
:at:`zaxis`: :at-val:`real(3), optional`
|
||||
The Z axis of the frame. The compiler finds the minimal rotation that maps the vector (0,0,1) into the vector
|
||||
specified here. This determines the X and Y axes of the frame implicitly. This is useful for geoms with rotational
|
||||
symmetry around the Z axis, as well as lights - which are oriented along the Z axis of their frame.
|
||||
The Z axis of the frame. The compiler finds the minimal rotation that maps the vector :math:`(0, 0, 1)` into the
|
||||
vector specified here. This determines the X and Y axes of the frame implicitly. This is useful for geoms with
|
||||
rotational symmetry around the Z axis, as well as lights - which are oriented along the Z axis of their frame.
|
||||
|
||||
.. _CSolver:
|
||||
|
||||
Solver parameters
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The solver :ref:`Parameters <soParameters>` section of the Computation chapter explained the
|
||||
mathematical and algorithmic meaning of the quantities d, b, k which determine the behavior of the constraints in
|
||||
MuJoCo. Here we explain how to set them. Setting is done indirectly, through the attributes :at:`solref` and
|
||||
:at:`solimp` which are available in all MJCF elements involving constraints. These parameters can be adjusted per
|
||||
constraint, or per defaults class, or left undefined - in which case MuJoCo uses the internal defaults shown below.
|
||||
Note also the override mechanism available in :ref:`option <option>`; it can be used to change all
|
||||
contact-related solver parameters at runtime, so as to experiment interactively with parameter settings or implement
|
||||
continuation methods for numerical optimization.
|
||||
The solver :ref:`Parameters <soParameters>` section of the Computation chapter explained the mathematical and
|
||||
algorithmic meaning of the quantities :math:`d, b, k` which determine the behavior of the constraints in MuJoCo. Here we
|
||||
explain how to set them. Setting is done indirectly, through the attributes :at:`solref` and :at:`solimp` which are
|
||||
available in all MJCF elements involving constraints. These parameters can be adjusted per constraint, or per defaults
|
||||
class, or left undefined - in which case MuJoCo uses the internal defaults shown below. Note also the override mechanism
|
||||
available in :ref:`option <option>`; it can be used to change all contact-related solver parameters at runtime, so as to
|
||||
experiment interactively with parameter settings or implement continuation methods for numerical optimization.
|
||||
|
||||
Here we focus on a single scalar constraint. Using slightly different notation from the Computation chapter, let a1
|
||||
denote the acceleration, v the velocity, r the position or residual (defined as 0 in friction dimensions), k and b the
|
||||
stiffness and damping of the virtual spring used to define the reference acceleration aref = -b*v - k*r. Let d be the
|
||||
constraint impedance, and a0 the acceleration in the absence of constraint force. Our earlier analysis revealed that
|
||||
the dynamics in constraint space are approximately
|
||||
Here we focus on a single scalar constraint. Using slightly different notation from the Computation chapter, let
|
||||
:math:`a_1` denote the acceleration, :math:`v` the velocity, :math:`r` the position or residual (defined as 0 in
|
||||
friction dimensions), :math:`k` and :math:`b` the stiffness and damping of the virtual spring used to define the
|
||||
reference acceleration :math:`a_{\rm ref} = -b v - k r`. Let :math:`d` be the constraint impedance, and :math:`a_0` the
|
||||
acceleration in the absence of constraint force. Our earlier analysis revealed that the dynamics in constraint space are
|
||||
approximately
|
||||
|
||||
a1 + d \* (b v + k r) = (1 - d) \* a0
|
||||
.. math::
|
||||
a_1 + d \cdot (b v + k r) = (1 - d)\cdot a_0
|
||||
|
||||
Again, the parameters that are under the user's control are d, b, k. The remaining quantities are functions of the
|
||||
Again, the parameters that are under the user's control are :math:`d, b, k`. The remaining quantities are functions of the
|
||||
system state and are computed automatically at each time step.
|
||||
|
||||
First we explain the setting of the impedance d. Recall that d must lie between 0 and 1; internally MuJoCo clamps it
|
||||
to the range [:ref:`mjMINIMP mjMAXIMP <glNumeric>`] which is currently set to [0.0001 0.9999]. It
|
||||
causes the solver to interpolate between the unforced acceleration a0 and reference acceleration aref. Small values of
|
||||
d correspond to soft/weak constraints while large values of d correspond to strong/hard constraints. The user can set
|
||||
d to a constant, or take advantage of its interpolating property and make it position-dependent, i.e., a function of r.
|
||||
Position-dependent impedance can be used to model soft contact layers around objects, or define equality constraints
|
||||
that become stronger with larger violation (so as to approximate backlash for example). The shape of the function d(r)
|
||||
is determined by the element-specific parameter vector :at:`solimp`.
|
||||
First we explain the setting of the impedance :math:`d`. Recall that :math:`d` must lie between 0 and 1; internally
|
||||
MuJoCo clamps it to the range [:ref:`mjMINIMP mjMAXIMP <glNumeric>`] which is currently set to [0.0001 0.9999]. It
|
||||
causes the solver to interpolate between the unforced acceleration :math:`a_0` and reference acceleration
|
||||
:math:`a_{\rm ref}`. Small values of :math:`d` correspond to soft/weak constraints while large values of :math:`d`
|
||||
correspond to strong/hard constraints. The user can set :math:`d` to a constant, or take advantage of its interpolating
|
||||
property and make it position-dependent, i.e., a function of :math:`r`. Position-dependent impedance can be used to
|
||||
model soft contact layers around objects, or define equality constraints that become stronger with larger violation (so
|
||||
as to approximate backlash for example). The shape of the function :math:`d(r)` is determined by the element-specific
|
||||
parameter vector :at:`solimp`.
|
||||
|
||||
**solimp :** real(5), "0.9 0.95 0.001 0.5 2"
|
||||
The five numbers are (dmin, dmax, width, midpoint, power). They parameterize the function d(r). Prior to MuJoCo 2.0
|
||||
this attribute had three parameters, plus a global option specifying the shape of the function. In MuJoCo 2.0 we
|
||||
expanded the family of impedance functions while keeping it backward-compatible as follows. The user is allowed to
|
||||
set only the first three parameters, whose defaults are the same as in prior releases. The defaults for the last two
|
||||
parameters then generate the same function which was the default in prior releases (a sigmoid). The new
|
||||
|
||||
The five numbers are (dmin, dmax, width, midpoint, power). They parameterize the function :math:`d(r)`. Prior to
|
||||
MuJoCo 2.0 this attribute had three parameters, plus a global option specifying the shape of the function. In MuJoCo
|
||||
2.0 we expanded the family of impedance functions while keeping it backward-compatible as follows. The user is
|
||||
allowed to set only the first three parameters, whose defaults are the same as in prior releases. The defaults for
|
||||
the last two parameters then generate the same function which was the default in prior releases (a sigmoid). The new
|
||||
parameterization further allows the sigmoid to become shifted and skewed, as shown in the plots below for different
|
||||
values of the additional parameters. The plots actually show two reflected sigmoids, because the impedance function
|
||||
d(r) depends on the absolute value of r. This flexibility was added to allow better control of remote contact forces,
|
||||
and can also be used for other constraints. The power (of the polynomial spline used to generate the function) must
|
||||
be 1 or greater. The midpoint (specifying the inflection point) must be between 0 and 1, and is expressed in units of
|
||||
width. Note that when the power is 1, the function is linear regardless of the midpoint.
|
||||
:math:`d(r)` depends on the absolute value of :math:`r`. This flexibility was added to allow better control of remote
|
||||
contact forces, and can also be used for other constraints. The power (of the polynomial spline used to generate the
|
||||
function) must be 1 or greater. The midpoint (specifying the inflection point) must be between 0 and 1, and is
|
||||
expressed in units of width. Note that when the power is 1, the function is linear regardless of the midpoint.
|
||||
|image0|
|
||||
|
||||
These plots show the impedance d(r) on the vertical axis, as a function of the constraint violation r on the
|
||||
horizontal axis. The quantity r is computed as follows. For equality constraints, r equals the constraint violation
|
||||
which can be either positive or negative. For friction loss or friction dimensions of elliptic cones, r is always 0.
|
||||
For limits, normal directions of elliptic cones and all directions of pyramidal cones, r is the (limit or contact)
|
||||
distance minus the margin at which the constraint becomes active; for contacts this margin is actually margin-gap.
|
||||
Therefore limit and contact constraints are active when the corresponding r is negative.
|
||||
These plots show the impedance :math:`d(r)` on the vertical axis, as a function of the constraint violation :math:`r`
|
||||
on the horizontal axis. The quantity :math:`r` is computed as follows. For equality constraints, :math:`r` equals the
|
||||
constraint violation which can be either positive or negative. For friction loss or friction dimensions of elliptic
|
||||
cones, :math:`r` is always 0. For limits, normal directions of elliptic cones and all directions of pyramidal cones,
|
||||
:math:`r` is the (limit or contact) distance minus the margin at which the constraint becomes active; for contacts
|
||||
this margin is actually margin-gap. Therefore limit and contact constraints are active when the corresponding
|
||||
:math:`r` is negative.
|
||||
|
||||
Next we explain the setting of the stiffness k and damping b. The idea here is to re-parameterize the model in terms of
|
||||
the time constant and damping ratio of the above mass-spring-damper system. By "time constant" we mean the inverse of
|
||||
the natural frequency times the damping ratio. Constraints whose residual is identically 0 have first-order dynamics and
|
||||
the mass-spring-damper analysis does not apply. In that case the time constant is the rate of exponential decay of the
|
||||
constraint velocity, and the damping ratio is ignored. In addition to this format, MuJoCo 2.0 allows a second format
|
||||
where stiffness and damping are specified more directly.
|
||||
Next we explain the setting of the stiffness :math:`k` and damping :math:`b`. The idea here is to re-parameterize the
|
||||
model in terms of the time constant and damping ratio of the above mass-spring-damper system. By "time constant" we mean
|
||||
the inverse of the natural frequency times the damping ratio. Constraints whose residual is identically 0 have first-
|
||||
order dynamics and the mass-spring-damper analysis does not apply. In that case the time constant is the rate of
|
||||
exponential decay of the constraint velocity, and the damping ratio is ignored. In addition to this format, MuJoCo 2.0
|
||||
allows a second format where stiffness and damping are specified more directly.
|
||||
|
||||
**solref :** real(2), "0.02 1"
|
||||
There are two formats for this attribute, determined by the sign of the numbers. If both numbers are positive the
|
||||
specification is considered to be in the (timeconst, dampratio) format which has been available in MuJoCo all along.
|
||||
Otherwise the specification is considered to be in the new (-stiffness, -damping) format introduced in MuJoCo 2.0.
|
||||
We first describe the original format where the two numbers are (timeconst, dampratio). In this case we use a
|
||||
mass-spring-damper model to compute k, b after suitable scaling. Note that the effective stiffness d(r)*k and damping
|
||||
d(r)*b are scaled by the impedance d(r) which is a function of the distance r. Thus we cannot always achieve the
|
||||
specified mass-spring-damper properties, unless we completely undo the scaling by d. But the latter is undesirable
|
||||
because it would ruin the interpolating property, in particular the limit d = 0 would no longer disable the
|
||||
constraint. Instead we scale the stiffness and damping so that the damping ratio remains constant, while the time
|
||||
constant increases when d(r) gets smaller. The scaling formulas are
|
||||
b = 2 / (dmax \* timeconst)
|
||||
k = d(r) / (dmax \* dmax \* timeconst \* timeconst \* dampratio \* dampratio)
|
||||
specification is considered to be in the :math:`(\text{timeconst}, \text{dampratio})` format which has been available
|
||||
in MuJoCo all along. Otherwise the specification is considered to be in the new :math:`(-\text{stiffness}, -
|
||||
\text{damping})`, format introduced in MuJoCo 2.0. We first describe the original format where the two numbers are
|
||||
:math:`(\text{timeconst}, \text{dampratio})`. In this case we use a mass-spring-damper model to compute :math:`k, b`
|
||||
after suitable scaling. Note that the effective stiffness :math:`d(r) \cdot k` and damping :math:`d(r) \cdot b` are
|
||||
scaled by the impedance :math:`d(r)` which is a function of the distance :math:`r`. Thus we cannot always achieve the
|
||||
specified mass-spring-damper properties, unless we completely undo the scaling by :math:`d`. But the latter is
|
||||
undesirable because it would ruin the interpolating property, in particular the limit :math:`d=0` would no longer
|
||||
disable the constraint. Instead we scale the stiffness and damping so that the damping ratio remains constant, while
|
||||
the time constant increases when :math:`d(r)` gets smaller. The scaling formulas are
|
||||
|
||||
.. math::
|
||||
\begin{aligned}
|
||||
b &= 2 / (d_\text{max}\cdot \text{timeconst}) \\
|
||||
k &= d(r) / (d_\text{max}^2 \cdot \text{timeconst}^2 \cdot \text{dampratio}^2) \\
|
||||
\end{aligned}
|
||||
|
||||
The timeconst parameter should be at least two times larger than the simulation time step, otherwise the system can
|
||||
become too stiff relative to the numerical integrator (especially when Euler integration is used) and the simulation
|
||||
can go unstable. This is enforced internally, unless the :at:`refsafe` attribute of
|
||||
:ref:`flag <option-flag>` is set to false. The dampratio parameter would normally be set to 1,
|
||||
corresponding to critical damping. Smaller values result in under-damped or bouncy constraints, while larger values
|
||||
result in over-damped constraints.
|
||||
Next we describe the new format where the two numbers are (-stiffness, -damping). This allows more direct control
|
||||
over restitution in particular. We still apply some scaling so that the same numbers can be used with different
|
||||
impedances, but the scaling no longer depends on r and the two numbers no longer interact. The scaling formulas are
|
||||
b = damping / dmax
|
||||
k = stiffness / (dmax \* dmax)
|
||||
can go unstable. This is enforced internally, unless the :at:`refsafe` attribute of :ref:`flag <option-flag>` is set
|
||||
to false. The :math:`\text{dampratio}` parameter would normally be set to 1, corresponding to critical damping.
|
||||
Smaller values result in under-damped or bouncy constraints, while larger values result in over-damped constraints.
|
||||
Next we describe the new format where the two numbers are :math:`(-\text{stiffness}, -\text{damping})`. This allows
|
||||
more direct control over restitution in particular. We still apply some scaling so that the same numbers can be used
|
||||
with different impedances, but the scaling no longer depends on :math:`r` and the two numbers no longer interact. The
|
||||
scaling formulas are
|
||||
|
||||
.. math::
|
||||
\begin{aligned}
|
||||
b &= \text{damping} / d_\text{max} \\
|
||||
k &= \text{stiffness} / d_\text{max}^2 \\
|
||||
\end{aligned}
|
||||
|
||||
.. _CContact:
|
||||
|
||||
@@ -530,20 +544,18 @@ well as solver statistics per iteration. We can offer the following general guid
|
||||
Actuator shortcuts
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As explained in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo
|
||||
offers a flexible actuator model with transmission, activation dynamics and force generation components that can be
|
||||
specified independently. The full functionality can be accessed via the XML element
|
||||
:ref:`general <general>` which allows the user to create a variety of custom actuators. In addition,
|
||||
MJCF provides shortcuts for configuring common actuators. This is done via the XML elements
|
||||
:ref:`motor <motor>`, :ref:`position <position>`,
|
||||
:ref:`velocity <velocity>`, :ref:`cylinder <cylinder>`,
|
||||
:ref:`muscle <muscle>`. These are *not* separate model elements. Internally MuJoCo supports only one
|
||||
As explained in the :ref:`Actuation model <geActuation>` section of the Computation chapter, MuJoCo offers a flexible
|
||||
actuator model with transmission, activation dynamics and force generation components that can be specified
|
||||
independently. The full functionality can be accessed via the XML element :ref:`general <general>` which allows the user
|
||||
to create a variety of custom actuators. In addition, MJCF provides shortcuts for configuring common actuators. This is
|
||||
done via the XML elements :ref:`motor <motor>`, :ref:`position <position>`, :ref:`velocity <velocity>`, :ref:`cylinder
|
||||
<cylinder>`, :ref:`muscle <muscle>`. These are *not* separate model elements. Internally MuJoCo supports only one
|
||||
actuator type - which is why when an MJCF model is saved all actuators are written as :el:`general`. Shortcuts create
|
||||
general actuators implicitly, set their attributes to suitable values, and expose a subset of attributes with possibly
|
||||
different names. For example, :el:`position` creates a position servo with attribute :at:`kp` which is the servo
|
||||
gain. However :el:`general` does not have an attribute :at:`kp`. Instead the parser adjusts the gain and bias
|
||||
parameters of the general actuator in a coordinated way so as to mimic a position servo. The same effect could have
|
||||
been achieved by using :el:`general` directly, and setting its attributes to certain values as described below.
|
||||
different names. For example, :el:`position` creates a position servo with attribute :at:`kp` which is the servo gain.
|
||||
However :el:`general` does not have an attribute :at:`kp`. Instead the parser adjusts the gain and bias parameters of
|
||||
the general actuator in a coordinated way so as to mimic a position servo. The same effect could have been achieved by
|
||||
using :el:`general` directly, and setting its attributes to certain values as described below.
|
||||
|
||||
Actuator shortcuts also interact with defaults. Recall that the :ref:`default setting <CDefault>` mechanism involves
|
||||
classes, each of which has a complete collection of dummy elements (one of each element type) used to initialize the
|
||||
@@ -561,6 +573,53 @@ defaults class and in the creation of actual model elements. If a given model re
|
||||
create multiple defaults classes, or avoid using defaults for actuators and instead specify all their attributes
|
||||
explicitly.
|
||||
|
||||
.. _CActRange:
|
||||
|
||||
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).
|
||||
|
||||
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
|
||||
of activation clamping, load the example model below:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<mujoco>
|
||||
<default>
|
||||
<joint axis="0 0 1" limited="true" range="-90 90" damping="0.3"/>
|
||||
<geom size=".1 .1 .1" type="box"/>
|
||||
<general gainprm="1" biastype="affine" biasprm="0 -1" dyntype="integrator"/>
|
||||
</default>
|
||||
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint name="joint 1"/>
|
||||
<geom/>
|
||||
</body>
|
||||
<body pos=".3 0 0">
|
||||
<joint name="joint 2"/>
|
||||
<geom/>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
<actuator>
|
||||
<general name="unclamped" joint="joint 1"/>
|
||||
<general name="clamped" actlimited="true" actrange="-1.57 1.57"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
|
||||
Note that the :at:`actrange` attribute is always specified in native units (radians), even though the joint range
|
||||
can be either in degrees (the default) or radians, depending on the :ref:`compiler/angle <compiler>` attribute.
|
||||
|
||||
.. _CLengthRange:
|
||||
|
||||
Actuator length range
|
||||
@@ -637,103 +696,120 @@ the shortcut :ref:`muscle <muscle>` is more convenient. As with all other actuat
|
||||
production mechanism and the transmission are defined independently. Nevertheless, muscles only make (bio)physical
|
||||
sense when attached to tendon or joint transmissions. For concreteness we will assume a tendon transmission here.
|
||||
|
||||
First we discuss length and length scaling. The range of feasible lengths of the transmission (i.e., MuJoCo tendon)
|
||||
will play an important role; see :ref:`Length range <CLengthRange>` section above. In biomechanics, a muscle and a
|
||||
tendon are attached in series and form a muscle-tendon actuator. Our convention is somewhat different: in MuJoCo the
|
||||
entity that has spatial properties (in particular length and velocity) is the tendon, while the muscle is an abstract
|
||||
force-generating mechanism that pulls on the tendon. Thus the tendon length in MuJoCo corresponds to the muscle+tendon
|
||||
length in biomechanics. We assume that the biological tendon is inelastic, with constant length LT, while the
|
||||
biological muscle length LM varies over time. The MuJoCo tendon length is the sum of the biological muscle and tendon
|
||||
lengths:
|
||||
First we discuss length and length scaling. The range of feasible lengths of the transmission (i.e., MuJoCo tendon) will
|
||||
play an important role; see :ref:`Length range <CLengthRange>` section above. In biomechanics, a muscle and a tendon are
|
||||
attached in series and form a muscle-tendon actuator. Our convention is somewhat different: in MuJoCo the entity that
|
||||
has spatial properties (in particular length and velocity) is the tendon, while the muscle is an abstract force-
|
||||
generating mechanism that pulls on the tendon. Thus the tendon length in MuJoCo corresponds to the muscle+tendon length
|
||||
in biomechanics. We assume that the biological tendon is inelastic, with constant length :math:`L_T`, while the
|
||||
biological muscle length :math:`L_M` varies over time. The MuJoCo tendon length is the sum of the biological muscle and
|
||||
tendon lengths:
|
||||
|
||||
actuator_length = LT + LM
|
||||
.. math::
|
||||
\texttt{actuator\_length} = L_T + L_M
|
||||
|
||||
Another important constant is the optimal resting length of the muscle, denoted L0. It equals the length LM at which
|
||||
the muscle generates maximum active force at zero velocity. We do not ask the user to specify L0 and LT directly,
|
||||
because it is difficult to know their numeric values given the spatial complexity of the tendon routing and wrapping.
|
||||
Instead we compute L0 and LT automatically as follows. The length range computation described above already provided
|
||||
the operating range for LT + LM. In addition, we ask the user to specify the operating range for the muscle length LM
|
||||
scaled by the (still unknown) constant L0. This is done with the attribute range; the default scaled range is (0.75,
|
||||
1.05). Now we can compute the two constants, using the fact that the actual and scaled ranges have to map to each
|
||||
other:
|
||||
Another important constant is the optimal resting length of the muscle, denoted :math:`L_0`. It equals the length
|
||||
:math:`L_M` at which the muscle generates maximum active force at zero velocity. We do not ask the user to specify
|
||||
:math:`L_0` and :math:`L_T` directly, because it is difficult to know their numeric values given the spatial complexity
|
||||
of the tendon routing and wrapping. Instead we compute :math:`L_0` and :math:`L_T` automatically as follows. The length
|
||||
range computation described above already provided the operating range for :math:`L_T+L_M`. In addition, we ask the user
|
||||
to specify the operating range for the muscle length :math:`L_M` scaled by the (still unknown) constant :math:`L_0`.
|
||||
This is done with the attribute range; the default scaled range is :math:`(0.75, 1.05)`. Now we can compute the two
|
||||
constants, using the fact that the actual and scaled ranges have to map to each other:
|
||||
|
||||
(actuator_lengthrange[0] - LT) / L0 = range[0]
|
||||
|
||||
(actuator_lengthrange[1] - LT) / L0 = range[1]
|
||||
.. math::
|
||||
\begin{aligned}
|
||||
(\texttt{actuator\_lengthrange[0]} - L_T) / L_0 &= \texttt{range[0]} \\
|
||||
(\texttt{actuator\_lengthrange[1]} - L_T) / L_0 &= \texttt{range[1]} \\
|
||||
\end{aligned}
|
||||
|
||||
At runtime, we compute the scaled muscle length and velocity as:
|
||||
|
||||
L = (actuator_length - LT) / L0
|
||||
|
||||
V = actuator_velocity / L0
|
||||
.. math::
|
||||
\begin{aligned}
|
||||
L &= (\texttt{actuator\_length} - L_T) / L_0 \\
|
||||
V &= \texttt{actuator\_velocity} / L_0 \\
|
||||
\end{aligned}
|
||||
|
||||
The advantage of the scaled quantities is that all muscles behave similarly in that representation. The behavior is
|
||||
captured by the Force-Length-Velocity (FLV) function measured in many experimental papers. We approximate this
|
||||
function as follows:
|
||||
captured by the Force-Length-Velocity (:math:`\text{\small FLV}`) function measured in many experimental papers. We
|
||||
approximate this function as follows:
|
||||
|
||||
|image1|
|
||||
|
||||
The function is in the form:
|
||||
|
||||
FLV(L, V, act) = FL(L)*FV(V)*act + FP(L)
|
||||
.. math::
|
||||
\text{\small FLV}(L, V, \texttt{act}) = F_L(L)\cdot F_V(V)\cdot \texttt{act} + F_P(L)
|
||||
|
||||
Comparing to the general form of a MuJoCo actuator, we see that FL*FV is the actuator gain and FP is the actuator
|
||||
bias. FL is the active force as a function of length, while FV is the active force as a function of velocity. They are
|
||||
multiplied to obtain the overall active force (note the scaling by act which is the actuator activation). FP is the
|
||||
passive force which is always present regardless of activation. The output of the FLV function is the scaled muscle
|
||||
force. We multiply the scaled force by a muscle-specific constant F0 to obtain the actual force:
|
||||
Comparing to the general form of a MuJoCo actuator, we see that :math:`F_L\cdot F_V` is the actuator gain and
|
||||
:math:`F_P` is the actuator bias. :math:`F_L` is the active force as a function of length, while :math:`F_V` is the
|
||||
active force as a function of velocity. They are multiplied to obtain the overall active force (note the scaling by act
|
||||
which is the actuator activation). :math:`F_P` is the passive force which is always present regardless of activation.
|
||||
The output of the :math:`\text{\small FLV}` function is the scaled muscle force. We multiply the scaled force by a
|
||||
muscle-specific constant :math:`F_0` to obtain the actual force:
|
||||
|
||||
actuator_force = - FLV(L, V, act) \* F0
|
||||
.. math::
|
||||
\texttt{actuator\_force} = -\text{\small FLV}(L, V, \texttt{act}) \cdot F_0
|
||||
|
||||
The negative sign is because positive muscle activation generates pulling force. The constant F0 is the peak active
|
||||
force at zero velocity. It is related to the muscle thickness (i.e., physiological cross-sectional area or PCSA). If
|
||||
known, it can be set with the attribute force of element :ref:`muscle <muscle>`. If it is not known, we
|
||||
set it to -1 which is the default. In that case we rely on the fact that larger muscles tend to act on joints that
|
||||
move more weight. The attribute scale defines this relationship as:
|
||||
The negative sign is because positive muscle activation generates pulling force. The constant :math:`F_0` is the peak
|
||||
active force at zero velocity. It is related to the muscle thickness (i.e., physiological cross-sectional area or PCSA).
|
||||
If known, it can be set with the attribute force of element :ref:`muscle <muscle>`. If it is not known, we set it to
|
||||
:math:`-1` which is the default. In that case we rely on the fact that larger muscles tend to act on joints that move
|
||||
more weight. The attribute scale defines this relationship as:
|
||||
|
||||
F0 = scale / actuator_acc0
|
||||
.. math::
|
||||
F_0 = \text{scale} / \texttt{actuator\_acc0}
|
||||
|
||||
The quantity actuator_acc0 is precomputed by the model compiler. It is the norm of the joint acceleration caused by
|
||||
unit force acting on the actuator transmission. Intuitively, scale determines how strong the muscle is "on average"
|
||||
while its actual strength depends on the geometric and inertial properties of the entire model.
|
||||
The quantity :math:`\texttt{actuator\_acc0}` is precomputed by the model compiler. It is the norm of the joint
|
||||
acceleration caused by unit force acting on the actuator transmission. Intuitively, :math:`\text{scale}` determines how
|
||||
strong the muscle is "on average" while its actual strength depends on the geometric and inertial properties of the
|
||||
entire model.
|
||||
|
||||
Thus far we encountered three constants that define the properties of an individual muscle: LT, L0, F0. In addition,
|
||||
the function FLV itself has several parameters illustrated in the above figure: lmin, lmax, vmax, fpmax, fvmax. These
|
||||
are supposed to be the same for all muscles, however different experimental papers suggest different shapes of the FLV
|
||||
function, thus users familiar with that literature may want to adjust them. We provide the MATLAB function
|
||||
`FLV.m <_static/FLV.m>`__ which was used to generate the above figure and shows how we compute the FLV function.
|
||||
Thus far we encountered three constants that define the properties of an individual muscle: :math:`L_T, L_0, F_0`. In
|
||||
addition, the function :math:`\text{\small FLV}` itself has several parameters illustrated in the above figure:
|
||||
:math:`l_\text{min}, l_\text{max}, v_\text{max}, f_\text{pmax}, f_\text{vmax}`. These are supposed to be the same for
|
||||
all muscles, however different experimental papers suggest different shapes of the FLV function, thus users familiar
|
||||
with that literature may want to adjust them. We provide the MATLAB function `FLV.m <_static/FLV.m>`__ which was used to
|
||||
generate the above figure and shows how we compute the :math:`\text{\small FLV}` function.
|
||||
|
||||
Before embarking on a mission to design more accurate FLV functions, consider the fact that the operating range of the
|
||||
muscle has a bigger effect than the shape of the FLV function, and in many cases this parameter is unknown. Below is a
|
||||
graphical illustration:
|
||||
Before embarking on a mission to design more accurate :math:`\text{\small FLV}` functions, consider the fact that the
|
||||
operating range of the muscle has a bigger effect than the shape of the :math:`\text{\small FLV}` function, and in many
|
||||
cases this parameter is unknown. Below is a graphical illustration:
|
||||
|
||||
|image2|
|
||||
|
||||
This figure format is common in the biomechanics literature, showing the operating range of each muscle superimposed
|
||||
on the normalized FL curve (ignore the vertical displacement). Our default range is shown in black. The blue curves
|
||||
are experimental data for two arm muscles. One can find muscles with small range, large range, range spanning the
|
||||
ascending portion of the FL curve, or the descending portion, or some of both. Now suppose you have a model with 50
|
||||
muscles. Do you believe that someone did careful experiments and measured the operating range for every muscle in your
|
||||
model, taking into account all the joints that the muscle spans? If not, then it is better to think of
|
||||
This figure format is common in the biomechanics literature, showing the operating range of each muscle superimposed on
|
||||
the normalized :math:`\text{FL}` curve (ignore the vertical displacement). Our default range is shown in black. The blue
|
||||
curves are experimental data for two arm muscles. One can find muscles with small range, large range, range spanning the
|
||||
ascending portion of the :math:`\text{FL}` curve, or the descending portion, or some of both. Now suppose you have a
|
||||
model with 50 muscles. Do you believe that someone did careful experiments and measured the operating range for every
|
||||
muscle in your model, taking into account all the joints that the muscle spans? If not, then it is better to think of
|
||||
musculo-skeletal models as having the same general behavior as the biological system, while being different in various
|
||||
details - including details that are of great interest to some research community. For most muscle properties which
|
||||
modelers consider constant and known, there is an experimental paper showing that they vary under some conditions.
|
||||
This is not to discourage people from building accurate models, but rather to discourage people from believing too
|
||||
strongly in their models. Modeling in biology is quite different from modeling in physics and engineering... which is
|
||||
why we find it ironic when people in Robotics complain that building accurate robot models is hard.
|
||||
modelers consider constant and known, there is an experimental paper showing that they vary under some conditions. This
|
||||
is not to discourage people from building accurate models, but rather to discourage people from believing too strongly
|
||||
in their models. Modeling in biology is quite different from modeling in physics and engineering... which is why we find
|
||||
it ironic when people in Robotics complain that building accurate robot models is hard.
|
||||
|
||||
Coming back to our muscle model, there is the muscle activation act. This is the state of a first-order nonlinear
|
||||
filter whose input is the control signal. The filter dynamics are:
|
||||
|
||||
d act / dt = (ctrl - act) / tau(ctrl, act)
|
||||
|
||||
.. math::
|
||||
\frac{\partial}{\partial t}\texttt{act} = \frac{\texttt{ctrl} - \texttt{act}}{\tau(\texttt{ctrl}, \texttt{act})}
|
||||
|
||||
Internally the control signal is clamped to [0, 1] even if the actuator does not have a control range specified. There
|
||||
are two time constants specified with the attribute timeconst, namely timeconst = (tau_act, tau_deact) with defaults
|
||||
(0.01, 0.04). The effective time constant tau is then computed at runtime as:
|
||||
are two time constants specified with the attribute timeconst, namely :math:`\text{timeconst} = (\tau_\text{act},
|
||||
\tau_\text{deact})` with defaults :math:`(0.01, 0.04)`. Following `Millard et al. (2013)
|
||||
<https://doi.org/10.1115/1.4023390>`__, the effective time constant :math:`\tau` is then computed at runtime as:
|
||||
|
||||
tau(ctrl, act) = tau_act \* (0.5 + 1.5*act), if ctrl > act
|
||||
|
||||
tau(ctrl, act) = tau_deact / (0.5 + 1.5*act), if ctrl <= act
|
||||
.. math::
|
||||
\tau(\texttt{ctrl}, \texttt{act}) =
|
||||
\begin{cases}
|
||||
\tau_\text{act} \cdot (0.5 + 1.5\cdot\texttt{act}) & \texttt{ctrl} \gt \texttt{act} \\
|
||||
\tau_\text{deact} / (0.5 + 1.5\cdot\texttt{act}) & \texttt{ctrl} \leq \texttt{act}
|
||||
\end{cases}
|
||||
|
||||
Now we summarize the attributes of element :ref:`muscle <muscle>` which users may want to adjust,
|
||||
depending on their familiarity with the biomechanics literature and availability of detailed measurements with regard
|
||||
@@ -747,8 +823,8 @@ scale
|
||||
This can be adjusted separately for each muscle, but it makes more sense to set it once in the
|
||||
:ref:`default <default>` element.
|
||||
force
|
||||
If you know the peak active force F0 of the individual muscles, enter it here. Many experimental papers contain this
|
||||
data.
|
||||
If you know the peak active force :math:`F_0` of the individual muscles, enter it here. Many experimental papers
|
||||
contain this data.
|
||||
range
|
||||
The operating range of the muscle in scaled lengths is also available in some papers. It is not clear how reliable
|
||||
such measurements are (given that muscles act on many joints) but they do exist. Note that the range differs
|
||||
@@ -756,11 +832,11 @@ range
|
||||
timeconst
|
||||
Muscles are composed of slow-twitch and fast-twitch fibers. The typical muscle is mixed, but some muscles have a
|
||||
higher proportion of one or the other fiber type, making them faster or slower. This can be modeled by adjusting the
|
||||
time constants. The vmax parameter of the FLV function should also be adjusted accordingly.
|
||||
time constants. The vmax parameter of the :math:`\text{\small FLV}` function should also be adjusted accordingly.
|
||||
lmin, lmax, vmax, fpmax, fvmax
|
||||
These are the parameters controlling the shape of the FLV function. Advanced users can experiment with them; see
|
||||
MATLAB function `FLV.m <_static/FLV.m>`__. Similar to the scale setting, if you want to change the FLV
|
||||
parameters for all muscles, do so in the :ref:`default <default>` element.
|
||||
These are the parameters controlling the shape of the :math:`\text{\small FLV}` function. Advanced users can
|
||||
experiment with them; see MATLAB function `FLV.m <_static/FLV.m>`__. Similar to the scale setting, if you want to
|
||||
change the :math:`\text{\small FLV}` parameters for all muscles, do so in the :ref:`default <default>` element.
|
||||
Custom model
|
||||
Instead of adjusting the parameters of our muscle model, users can implement a different model, by setting gaintype,
|
||||
biastype and dyntype of a :ref:`general <general>` actuator to "user" and providing callbacks at
|
||||
@@ -777,17 +853,15 @@ simulations. To help MuJoCo users convert OpenSim models, here we summarize the
|
||||
|
||||
The activation dynamics model is identical to OpenSim, including the default time constants.
|
||||
|
||||
The FLV function is not exactly the same, but both MuJoCo and OpenSim approximate the same experimental data, so they
|
||||
are very close. For a description of the OpenSim model and summary of relevant experimental data, see:
|
||||
|
||||
Millard et al, "Flexing computational muscle: modeling and simulation of musculotendon dynamics", J Biomech Eng. 2013
|
||||
Feb;135(2)
|
||||
The :math:`\text{\small FLV}` function is not exactly the same, but both MuJoCo and OpenSim approximate the same
|
||||
experimental data, so they are very close. For a description of the OpenSim model and summary of relevant experimental
|
||||
data, see `Millard et al. (2013) <https://doi.org/10.1115/1.4023390>`__.
|
||||
|
||||
We assume inelastic tendons while OpenSim can model tendon elasticity. We decided not to do that here, because tendon
|
||||
elasticity requires fast-equilibrium assumptions which in turn require various tweaks and are prone to simulation
|
||||
instability. In practice tendons are quite stiff, and their effect can be captured approximately by stretching the FL
|
||||
curve corresponding to the inelastic case (Zajac 89). This can be done in MuJoCo by shortening the muscle operating
|
||||
range.
|
||||
instability. In practice tendons are quite stiff, and their effect can be captured approximately by stretching the
|
||||
:math:`\text{FL}` curve corresponding to the inelastic case (`Zajac (1989)
|
||||
<https://pubmed.ncbi.nlm.nih.gov/2676342/>`__). This can be done in MuJoCo by shortening the muscle operating range.
|
||||
|
||||
Pennation angle (i.e., the angle between the muscle and the line of force) is not modeled in MuJoCo and is assumed to
|
||||
be 0. This effect can be approximated by scaling down the muscle force and also adjusting the operating range.
|
||||
@@ -885,9 +959,9 @@ see the XML model files in the distribution for the complete examples.
|
||||
.. code-block:: xml
|
||||
|
||||
<worldbody>
|
||||
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
|
||||
<geom size=".02" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
<composite type="particle" count="10 10 10" spacing="0.07" offset="0 0 1">
|
||||
<geom size=".02" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
</worldbody>
|
||||
|
||||
The above XML is all it takes to create a system with 1000 particles with initial positions on a 10-10-10 grid, and
|
||||
@@ -908,11 +982,11 @@ simulation at much larger timesteps (this model is stable at 30 ms timestep and
|
||||
.. code-block:: xml
|
||||
|
||||
<composite type="grid" count="20 1 1" spacing="0.045" offset="0 0 1">
|
||||
<joint kind="main" damping="0.001"/>
|
||||
<tendon kind="main" width="0.01"/>
|
||||
<geom size=".02" rgba=".8 .2 .1 1"/>
|
||||
<pin coord="1"/>
|
||||
<pin coord="13"/>
|
||||
<joint kind="main" damping="0.001"/>
|
||||
<tendon kind="main" width="0.01"/>
|
||||
<geom size=".02" rgba=".8 .2 .1 1"/>
|
||||
<pin coord="1"/>
|
||||
<pin coord="13"/>
|
||||
</composite>
|
||||
|
||||
The grid type can create 1D or 2D grids, depending on the :at:`count` attribute. Here we illustrate 1D grids. These
|
||||
@@ -930,10 +1004,10 @@ example; in that case the parent body would be moving, and the first element bod
|
||||
.. code-block:: xml
|
||||
|
||||
<composite type="grid" count="9 9 1" spacing="0.05" offset="0 0 1">
|
||||
<skin material="matcarpet" inflate="0.001" subgrid="3" texcoord="true"/>
|
||||
<geom size=".02"/>
|
||||
<pin coord="0 0"/>
|
||||
<pin coord="8 0"/>
|
||||
<skin material="matcarpet" inflate="0.001" subgrid="3" texcoord="true"/>
|
||||
<geom size=".02"/>
|
||||
<pin coord="0 0"/>
|
||||
<pin coord="8 0"/>
|
||||
</composite>
|
||||
|
||||
A 2D grid can be used to simulate cloth. What it really simulates is a 2D grid of spheres connected with
|
||||
@@ -950,11 +1024,11 @@ absence of textures. When textures are present (left) the benefits of subdivisio
|
||||
.. code-block:: xml
|
||||
|
||||
<body name="B10" pos="0 0 1">
|
||||
<freejoint/>
|
||||
<composite type="rope" count="21 1 1" spacing="0.04" offset="0 0 2">
|
||||
<joint kind="main" damping="0.005"/>
|
||||
<geom type="capsule" size=".01 .015" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
<freejoint/>
|
||||
<composite type="rope" count="21 1 1" spacing="0.04" offset="0 0 2">
|
||||
<joint kind="main" damping="0.005"/>
|
||||
<geom type="capsule" size=".01 .015" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
</body>
|
||||
|
||||
The remaining composite object types create kinematic trees of element bodies, and the parent body becomes the root of
|
||||
@@ -978,12 +1052,12 @@ The loop is similar to a rope but the first and last element bodies are connecte
|
||||
.. code-block:: xml
|
||||
|
||||
<body name="B3_5" pos="0 0 1">
|
||||
<freejoint/>
|
||||
<composite type="cloth" count="9 9 1" spacing="0.05" flatinertia="0.01">
|
||||
<joint kind="main" damping="0.001"/>
|
||||
<skin material="matcarpet" texcoord="true" inflate="0.005" subgrid="2"/>
|
||||
<geom type="capsule" size="0.015 0.01" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
<freejoint/>
|
||||
<composite type="cloth" count="9 9 1" spacing="0.05" flatinertia="0.01">
|
||||
<joint kind="main" damping="0.001"/>
|
||||
<skin material="matcarpet" texcoord="true" inflate="0.005" subgrid="2"/>
|
||||
<geom type="capsule" size="0.015 0.01" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
</body>
|
||||
|
||||
The cloth type is an alternative to a 2D grid, and has somewhat different properties. Similar to rope vs. 1D grid, the
|
||||
@@ -1004,11 +1078,11 @@ some damping for stable integration. The parameters can be found in the XML mode
|
||||
.. code-block:: xml
|
||||
|
||||
<body pos="0 0 1">
|
||||
<freejoint/>
|
||||
<composite type="box" count="7 7 7" spacing="0.04">
|
||||
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
|
||||
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
<freejoint/>
|
||||
<composite type="box" count="7 7 7" spacing="0.04">
|
||||
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
|
||||
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
</body>
|
||||
|
||||
The box type, as well as the cylinder and ellipsoid types below, are used to model soft 3D objects. The element bodies
|
||||
@@ -1036,11 +1110,11 @@ points to the outside, thus creating a thicker shell which is harder to penetrat
|
||||
.. code-block:: xml
|
||||
|
||||
<body pos="0 0 1">
|
||||
<freejoint/>
|
||||
<composite type="ellipsoid" count="5 7 9" spacing="0.05">
|
||||
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
|
||||
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
<freejoint/>
|
||||
<composite type="ellipsoid" count="5 7 9" spacing="0.05">
|
||||
<skin texcoord="true" material="matsponge" rgba=".7 .7 .7 1"/>
|
||||
<geom type="capsule" size=".015 0.05" rgba=".8 .2 .1 1"/>
|
||||
</composite>
|
||||
</body>
|
||||
|
||||
Cylinders and ellipsoids are created in the same way as boxes. The only difference is that the reference positions of
|
||||
@@ -1141,11 +1215,11 @@ Here is an example extension section of a URDF model:
|
||||
.. code-block:: xml
|
||||
|
||||
<robot name="darwin">
|
||||
<mujoco>
|
||||
<compiler meshdir="../mesh/darwin/" balanceinertia="true"/>
|
||||
</mujoco>
|
||||
<link name="MP_BODY">
|
||||
...
|
||||
<mujoco>
|
||||
<compiler meshdir="../mesh/darwin/" balanceinertia="true"/>
|
||||
</mujoco>
|
||||
<link name="MP_BODY">
|
||||
...
|
||||
</robot>
|
||||
|
||||
The above extensions make URDF more usable but still limited. If the user wants to build models taking full advantage of
|
||||
@@ -1179,8 +1253,8 @@ orientation:
|
||||
.. code-block:: xml
|
||||
|
||||
<body>
|
||||
<joint name="J1" type="hinge" pos="0 0 0" axis="0 0 1" armature="0.01"/>
|
||||
<joint name="J2" type="hinge" pos="0 0 0" axis="0 0 1" limited="true" range="-1 1"/>
|
||||
<joint name="J1" type="hinge" pos="0 0 0" axis="0 0 1" armature="0.01"/>
|
||||
<joint name="J2" type="hinge" pos="0 0 0" axis="0 0 1" limited="true" range="-1 1"/>
|
||||
</body>
|
||||
|
||||
Thus the overall rotation of the body relative to its parent is J1+J2. Now define an actuator acting only on J1. The
|
||||
@@ -1249,12 +1323,12 @@ in a visible way, and the energy fluctuates around the initial value instead of
|
||||
.. code-block:: xml
|
||||
|
||||
<worldbody>
|
||||
<geom type="plane" size="1 1 .1"/>
|
||||
<geom type="plane" size="1 1 .1"/>
|
||||
|
||||
<body pos="0 0 1">
|
||||
<freejoint/>
|
||||
<geom type="sphere" size="0.1" solref="-1000 0"/>
|
||||
</body>
|
||||
<body pos="0 0 1">
|
||||
<freejoint/>
|
||||
<geom type="sphere" size="0.1" solref="-1000 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
.. _CSize:
|
||||
|
||||
Reference in New Issue
Block a user