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 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 (``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 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 respect to the degrees-of-freedom. The frame with respect to which the Jacobian is computed is centered at the body
consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos` (in center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stages<piForward>` required for Jacobian
that order). computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed
by :ref:`mj_comPos`.
.. _mj_jacBody: .. _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 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 (``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 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 respect to the degrees-of-freedom. The frame with respect to which the Jacobian is computed is centered at the body
consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` and :ref:`mj_comPos` (in center-of-mass but aligned with the world frame. The minimal :ref:`pipeline stages<piForward>` required for Jacobian
that order). computations to be consistent with the current generalized positions ``mjData.qpos`` are :ref:`mj_kinematics` followed
by :ref:`mj_comPos`.
.. _mj_jacBody: .. _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 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 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 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 point defined by the :ref:`pos<body-joint-pos>` attribute. If a body has a ball joint, it cannot have other
hinge). Combining ball joints with slide joints in the same body is allowed. 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 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 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: .. _body-joint-limited:
:at:`limited`: :at-val:`[false, true, auto], "auto"` :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 This attribute specifies if the joint has limits. It interacts with the :ref:`range<body-joint-range>` attribute. If
is "false", joint limits are disabled. If this attribute is "true", joint limits are enabled. If this 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 attribute is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, joint limits will be enabled if range
if range is defined. is defined.
.. _body-joint-actuatorfrcrange: .. _body-joint-actuatorfrcrange:
@@ -2157,9 +2157,9 @@ rotations as unit quaternions.
:at:`actuatorfrclimited`: :at-val:`[false, true, auto], "auto"` :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 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 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 attribute interacts with the :ref:`actuatorfrcrange<body-joint-actuatorfrcrange>` attribute. If this attribute is
clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute is "auto", and "false", actuator force clamping is disabled. If it is "true", actuator force clamping is enabled. If this attribute
:at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if is "auto", and :at:`autolimits` is set in :ref:`compiler <compiler>`, actuator force clamping will be enabled if
:at:`actuatorfrcrange` is defined. :at:`actuatorfrcrange` is defined.
.. _body-joint-actuatorgravcomp: .. _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 expensive pipeline component reported by the profiler. Note that some of these are subtly different for MJX, see
dedicated section :ref:`therein<MjxPerformance>`. 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 :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, 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 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. 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`` :ref:`Numerical Integration<geIntegration>` section. The default recommended choice is the ``implicitfast``
integrator. integrator.
3. :ref:`jacobian<option-jacobian>`: Try switching the Jacobian setting between "dense" and "sparse". These two options 3. :ref:`Constraint Jacobians<option-jacobian>`: Try switching the Jacobian setting between "dense" and "sparse". These
use seperate code paths using dense or sparse algebra, but are otherwise compationally identical, so the faster one two options use seperate code paths using dense or sparse algebra, but are otherwise compationally identical, so the
is always preferred. The default "auto" heuristic does not always make the right choice. 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 4. **Constraint solver:** If the profiler reports that a large chunk of time is spent in the solver, consider the
following: 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 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 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. 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 5. **Collisions:** If the profiler reports that collision detection takes up a large chunk of the computation
time, consider the following steps: time, consider the following steps:
@@ -1684,6 +1683,12 @@ dedicated section :ref:`therein<MjxPerformance>`.
collisions are those involving SDF geometries. collisions are those involving SDF geometries.
- If replacing collision meshes with primitives is not feasible, decimate the meshes as much as possible. Open source - 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. 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: .. _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 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. 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: .. _CRestitution:
Restitution Restitution
+14 -28
View File
@@ -901,14 +901,14 @@ density of water).
Joint coordinates Joint coordinates
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
One of the key distinctions between MuJoCo and gaming engines (such as ODE, Bullet, Havoc, PhysX) is that MuJoCo One of the key distinctions between MuJoCo and gaming engines is that MuJoCo operates in generalized or joint
operates in generalized or joint coordinates, while gaming engines operate in Cartesian coordinates, although Bullet now coordinates, while most gaming engines operate in Cartesian coordinates. The differences between these two approaches
supports generalized coordinates. The differences between these two approaches can be summarized as follows: can be summarized as follows:
Joint coordinates: Joint coordinates:
- Best suited for elaborate kinematic structures such as robots; - 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; - 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 - 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). kinematics, and cannot be manipulated directly (except for root bodies).
@@ -916,7 +916,7 @@ Joint coordinates:
Cartesian coordinates: Cartesian coordinates:
- Best suited for many bodies that bounce off each other, as in molecular dynamics and box stacking; - 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; - 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, - The positions and orientations of the simulated bodies are represented explicitly and can be manipulated directly,
although this can introduce further joint constraint violations. 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 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 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 ``mjData.qpos`` and ``mjData.qvel``, and can therefore be manipulated directly.
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:
.. code:: C 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).
int bodyid = mj_name2id(m, mjOBJ_BODY, "myfloatingbody"); The linear postions of free joints are in the global frame, as are
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
linear velocities. The orientation of a free joint (the quaternion) is also in the global frame. However, the rotational 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 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 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. 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.