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:
Yuval Tassa
2024-09-09 11:34:35 -07:00
committed by Copybara-Service
parent 4862b9e765
commit be00fafc43
5 changed files with 42 additions and 82 deletions
+4 -3
View File
@@ -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:
+4 -3
View File
@@ -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:
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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.