Various documentation improvements.
- Replace two "below" instances in `XMLreference.rst` with proper links (there are many more that need fixing). - Discuss friction cones and 32-bit floats in Performance Tuning. - Delete Damping subsection in Tips and Tricks, no longer relevant after the introduction of the implicit/fast integrators. - Simplify discussion of free bodies, mention free joint alignment. - Clarify frame used by kinematic Jacobians. PiperOrigin-RevId: 672615057 Change-Id: Ib59b71e3c09cdd13415519fc4a964131b155718f
This commit is contained in:
committed by
Copybara-Service
parent
4862b9e765
commit
be00fafc43
@@ -322,9 +322,10 @@ degrees-of-freedom and a given point. Given a body specified by its integer id (
|
||||
frame (``point``) treated as attached to the body, the Jacobian has both translational (``jacp``) and rotational
|
||||
(``jacr``) components. Passing ``NULL`` for either pointer will skip that part of the computation. Each component is a
|
||||
3-by-nv matrix. Each row of this matrix is the gradient of the corresponding coordinate of the specified point with
|
||||
respect to the degrees-of-freedom. The :ref:`pipeline stages<piStages>` required for Jacobian computations to be
|
||||
consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos` (in
|
||||
that order).
|
||||
respect to the degrees-of-freedom. The frame with respect to which the Jacobian is computed is centered at the body
|
||||
center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stages<piForward>` required for Jacobian
|
||||
computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed
|
||||
by :ref:`mj_comPos`.
|
||||
|
||||
.. _mj_jacBody:
|
||||
|
||||
|
||||
@@ -191,9 +191,10 @@ degrees-of-freedom and a given point. Given a body specified by its integer id (
|
||||
frame (``point``) treated as attached to the body, the Jacobian has both translational (``jacp``) and rotational
|
||||
(``jacr``) components. Passing ``NULL`` for either pointer will skip that part of the computation. Each component is a
|
||||
3-by-nv matrix. Each row of this matrix is the gradient of the corresponding coordinate of the specified point with
|
||||
respect to the degrees-of-freedom. The :ref:`pipeline stages<piStages>` required for Jacobian computations to be
|
||||
consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos` (in
|
||||
that order).
|
||||
respect to the degrees-of-freedom. The frame with respect to which the Jacobian is computed is centered at the body
|
||||
center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stages<piForward>` required for Jacobian
|
||||
computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed
|
||||
by :ref:`mj_comPos`.
|
||||
|
||||
.. _mj_jacBody:
|
||||
|
||||
|
||||
@@ -2066,8 +2066,8 @@ rotations as unit quaternions.
|
||||
The **ball** type creates a ball joint with three rotational degrees of freedom. The rotation is represented as a
|
||||
unit quaternion. The quaternion (1,0,0,0) corresponds to the initial configuration in which the model is defined. Any
|
||||
other quaternion is interpreted as a 3D rotation relative to this initial configuration. The rotation is around the
|
||||
point defined by the pos attribute below. If a body has a ball joint, it cannot have other rotational joints (ball or
|
||||
hinge). Combining ball joints with slide joints in the same body is allowed.
|
||||
point defined by the :ref:`pos<body-joint-pos>` attribute. If a body has a ball joint, it cannot have other
|
||||
rotational joints (ball or hinge). Combining ball joints with slide joints in the same body is allowed.
|
||||
|
||||
The **slide** type creates a sliding or prismatic joint with one translational degree of freedom. Such joints are
|
||||
defined by a position and a sliding direction. For simulation purposes only the direction is needed; the joint
|
||||
@@ -2139,10 +2139,10 @@ rotations as unit quaternions.
|
||||
.. _body-joint-limited:
|
||||
|
||||
:at:`limited`: :at-val:`[false, true, auto], "auto"`
|
||||
This attribute specifies if the joint has limits. It interacts with the range attribute below. If this attribute
|
||||
is "false", joint limits are disabled. If this attribute is "true", joint limits are enabled. If this
|
||||
attribute is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, joint limits will be enabled
|
||||
if range is defined.
|
||||
This attribute specifies if the joint has limits. It interacts with the :ref:`range<body-joint-range>` attribute. If
|
||||
this attribute is "false", joint limits are disabled. If this attribute is "true", joint limits are enabled. If this
|
||||
attribute is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, joint limits will be enabled if range
|
||||
is defined.
|
||||
|
||||
.. _body-joint-actuatorfrcrange:
|
||||
|
||||
@@ -2157,9 +2157,9 @@ rotations as unit quaternions.
|
||||
:at:`actuatorfrclimited`: :at-val:`[false, true, auto], "auto"`
|
||||
This attribute specifies whether actuator forces acting on the joint should be clamped. See :ref:`CForceRange` for
|
||||
details. It is available only for scalar joints (hinge and slider) and ignored for ball and free joints. |br| This
|
||||
attribute interacts with the actuatorfrcrange attribute below. If this attribute is "false", actuator force
|
||||
clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute is "auto", and
|
||||
:at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if
|
||||
attribute interacts with the :ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` attribute. If this attribute is
|
||||
"false", actuator force clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute
|
||||
is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if
|
||||
:at:`actuatorfrcrange` is defined.
|
||||
|
||||
.. _body-joint-actuatorgravcomp:
|
||||
|
||||
+11
-39
@@ -1649,17 +1649,17 @@ by the :ref:`testspeed<saTestspeed>` utility. When embarking on the more elabora
|
||||
expensive pipeline component reported by the profiler. Note that some of these are subtly different for MJX, see
|
||||
dedicated section :ref:`therein<MjxPerformance>`.
|
||||
|
||||
1. :ref:`timestep<option-timestep>`: Try to increase the simulation timestep. As explained at the end of the
|
||||
1. :ref:`Timestep<option-timestep>`: Try to increase the simulation timestep. As explained at the end of the
|
||||
:ref:`Numerical Integration<geIntegration>` section, the timestep is the single most important parameter in any
|
||||
model. The default value is chosen for stability rather than efficiency, and can often be increased. At some point,
|
||||
increasing it further will cause diveregence, so the optimal timestep is the largest timestep at which divergence
|
||||
never happens or is very rare. The actual value is model-dependent.
|
||||
2. :ref:`integrator<option-integrator>`: Choose your integrator according to the recommendations at the end of the
|
||||
2. :ref:`Integrator<option-integrator>`: Choose your integrator according to the recommendations at the end of the
|
||||
:ref:`Numerical Integration<geIntegration>` section. The default recommended choice is the ``implicitfast``
|
||||
integrator.
|
||||
3. :ref:`jacobian<option-jacobian>`: Try switching the Jacobian setting between "dense" and "sparse". These two options
|
||||
use seperate code paths using dense or sparse algebra, but are otherwise compationally identical, so the faster one
|
||||
is always preferred. The default "auto" heuristic does not always make the right choice.
|
||||
3. :ref:`Constraint Jacobians<option-jacobian>`: Try switching the Jacobian setting between "dense" and "sparse". These
|
||||
two options use seperate code paths using dense or sparse algebra, but are otherwise compationally identical, so the
|
||||
faster one is always preferred. The default "auto" heuristic does not always make the right choice.
|
||||
4. **Constraint solver:** If the profiler reports that a large chunk of time is spent in the solver, consider the
|
||||
following:
|
||||
|
||||
@@ -1670,7 +1670,6 @@ dedicated section :ref:`therein<MjxPerformance>`.
|
||||
or, equivalently, increasing the solver's termination tolerance. In particular for the Newton solver, which
|
||||
typically acheives numerical convergence in 2-3 (expensive) iterations, the last iteration increases the precision
|
||||
to a level that has no noticable effect, and can be skipped.
|
||||
|
||||
5. **Collisions:** If the profiler reports that collision detection takes up a large chunk of the computation
|
||||
time, consider the following steps:
|
||||
|
||||
@@ -1684,6 +1683,12 @@ dedicated section :ref:`therein<MjxPerformance>`.
|
||||
collisions are those involving SDF geometries.
|
||||
- If replacing collision meshes with primitives is not feasible, decimate the meshes as much as possible. Open source
|
||||
tools like trimesh, Blender, MeshLab and CoACD are very useful in this regard.
|
||||
6. :ref:`Friction cones<option-cone>`: Elliptic cones are more accurate and better at preventing slip with high
|
||||
:ref:`impratio<option-impratio>`, but are more expensive. If accurate friction is not important, try switching
|
||||
to pyramidal cones.
|
||||
7. Compile MuJoCo with 32-bit floating point precision (rather than the default 64). For large models running in
|
||||
multi-threaded mode, where memory access is more expensive than computation, this can lead to (up to) 2x performance
|
||||
improvement. See :ref:`mjtNum` for more information.
|
||||
|
||||
.. _CSlippage:
|
||||
|
||||
@@ -1774,39 +1779,6 @@ limits, the equality constraint approach will generate a softer transition betwe
|
||||
regime. It will also be active all the time, which is convenient in user code that needs the constraint violation or
|
||||
constraint force as input.
|
||||
|
||||
.. _CDamping:
|
||||
|
||||
Damping
|
||||
~~~~~~~
|
||||
|
||||
Damping generates a force proportional to velocity and opposite to it. In a physical system damping always increases
|
||||
stability. But this is only because the Universe is equipped with an ideal continuous-time integrator which does not
|
||||
accumulate errors due to time discretization. In a computer simulation where time is discretized, large damping can
|
||||
destabilize the system because of integration errors. This was already discussed in the
|
||||
:ref:`Computation <gePassive>` chapter.
|
||||
|
||||
The standard approach to reducing integration errors is to reduce the timestep or use the Runge-Kutta integrator, both
|
||||
of which are effective but slow down the simulation. An alternative approach is to put all damping in the joints and
|
||||
use the Euler integrator. In that case damping forces are integrated implicitly -- meaning that the inertia matrix is
|
||||
adjusted and re-factorized internally as part of the velocity update, in a way transparent to the user. Implicit
|
||||
integration is much more stable than explicit integration, allowing substantially larger time steps. Note that the
|
||||
Runge-Kutta integrator is explicit, and so is Euler except for the way it treats damping forces. Ideally we would have
|
||||
a fully implicit integrator, but there is no publicly available physics engine that currently has such an integrator.
|
||||
It is on our todo list for a future MuJoCo release.
|
||||
|
||||
Given this state of affairs, joint damping is better behaved than damping in tendons or actuators, because the latter
|
||||
are not integrated implicitly. Now consider a velocity servo producing force:
|
||||
|
||||
::
|
||||
|
||||
force = gain * (desired_velocity - current_velocity)
|
||||
|
||||
This can be modeled as a velocity actuator, however such an actuator adds damping to the system and could cause
|
||||
instability when the gain is high. Instead we could split the above force in two terms. For the first term, define a
|
||||
motor which generates force = gain \* desired_velocity, by treating desired_velocity as the control signal. For the
|
||||
second term, add damping in the joint, with damping coefficient equal to the above servo gain. Now the overall force is
|
||||
the same yet the damping component of the force is integrated implicitly.
|
||||
|
||||
.. _CRestitution:
|
||||
|
||||
Restitution
|
||||
|
||||
+14
-28
@@ -901,14 +901,14 @@ density of water).
|
||||
Joint coordinates
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
One of the key distinctions between MuJoCo and gaming engines (such as ODE, Bullet, Havoc, PhysX) is that MuJoCo
|
||||
operates in generalized or joint coordinates, while gaming engines operate in Cartesian coordinates, although Bullet now
|
||||
supports generalized coordinates. The differences between these two approaches can be summarized as follows:
|
||||
One of the key distinctions between MuJoCo and gaming engines is that MuJoCo operates in generalized or joint
|
||||
coordinates, while most gaming engines operate in Cartesian coordinates. The differences between these two approaches
|
||||
can be summarized as follows:
|
||||
|
||||
Joint coordinates:
|
||||
|
||||
- Best suited for elaborate kinematic structures such as robots;
|
||||
- Joints add degrees of freedom among bodies that would be welded together by default;
|
||||
- Joints **add** degrees of freedom among bodies that would be welded together by default;
|
||||
- Joint constraints are implicit in the representation and cannot be violated;
|
||||
- The positions and orientations of the simulated bodies are obtained from the generalized coordinates via forward
|
||||
kinematics, and cannot be manipulated directly (except for root bodies).
|
||||
@@ -916,7 +916,7 @@ Joint coordinates:
|
||||
Cartesian coordinates:
|
||||
|
||||
- Best suited for many bodies that bounce off each other, as in molecular dynamics and box stacking;
|
||||
- Joints remove degrees of freedom among bodies that would be free-floating by default;
|
||||
- Joints **remove** degrees of freedom among bodies that would be free-floating by default;
|
||||
- Joint constraints are enforced numerically and can be violated;
|
||||
- The positions and orientations of the simulated bodies are represented explicitly and can be manipulated directly,
|
||||
although this can introduce further joint constraint violations.
|
||||
@@ -935,31 +935,17 @@ necessarily unique) set of joint coordinates for which the forward kinematics pl
|
||||
|
||||
The situation is different for floating bodies, i.e., bodies that are connected to the world with a free joint. The
|
||||
positions and orientations as well as the linear and angular velocities of such bodies are explicitly represented in
|
||||
``mjData.qpos`` and ``mjData.qvel``, and can therefore be manipulated directly. The general approach is to find the
|
||||
addresses in qpos and qvel where the body's data are. Of course qpos and qvel represents joints and not bodies, so you
|
||||
need the corresponding joint addresses. Suppose the body was named "myfloatingbody" in the XML. The necessary addresses
|
||||
can be obtained as:
|
||||
``mjData.qpos`` and ``mjData.qvel``, and can therefore be manipulated directly.
|
||||
|
||||
.. code:: C
|
||||
|
||||
int bodyid = mj_name2id(m, mjOBJ_BODY, "myfloatingbody");
|
||||
int qposadr = -1, qveladr = -1;
|
||||
|
||||
// make sure we have a floating body: it has a single free joint
|
||||
if (bodyid >= 0 && m->body_jntnum[bodyid] == 1 && m->jnt_type[m->body_jntadr[bodyid]] == mjJNT_FREE) {
|
||||
// extract the addresses from the joint specification
|
||||
qposadr = m->jnt_qposadr[m->body_jntadr[bodyid]];
|
||||
qveladr = m->jnt_dofadr[m->body_jntadr[bodyid]];
|
||||
}
|
||||
|
||||
Now if everything went well (i.e., "myfloatingbody" was indeed a floating body), qposadr and qveladr are the addresses
|
||||
in qpos and qvel where the data for our floating body/joint lives. The position data is 7 numbers (3D position followed
|
||||
by unit quaternion) while the velocity data is 6 numbers (3D linear velocity followed by 3D angular velocity). These
|
||||
numbers can now be set to the desired pose and velocity of the body.
|
||||
|
||||
The semantics of free joints are as follows. The linear postions of free joints are in the global frame, as are
|
||||
The semantics of free joints are as follows. The position data is 7 numbers (3D position followed
|
||||
by unit quaternion) while the velocity data is 6 numbers (3D linear velocity followed by 3D angular velocity).
|
||||
The linear postions of free joints are in the global frame, as are
|
||||
linear velocities. The orientation of a free joint (the quaternion) is also in the global frame. However, the rotational
|
||||
velocities of a free joint are in the local body frame. This is not so much a design decision but rather correct
|
||||
use of the topology of quaternions. Angular velocities live in the quaternion tangent space, which is defined locally
|
||||
for a certain orientation, so frame-local angular velocities are a natural parameterization.
|
||||
for a certain orientation, so frame-local angular velocities are the natural parameterization.
|
||||
Accelerations are defined in the same space as the corresponding velocities.
|
||||
|
||||
Free joints are always defined in the body frame, yet it is computationally favorable to align this frame with the
|
||||
body's inertia. Read more about this option in the documentation of the :ref:`freejoint/align<body-freejoint-align>`
|
||||
attribute.
|
||||
|
||||
Reference in New Issue
Block a user