diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index d7d87848..60fa14a1 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -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` 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` 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: diff --git a/doc/APIreference/functions_override.rst b/doc/APIreference/functions_override.rst index b8b0d0d0..447a0a05 100644 --- a/doc/APIreference/functions_override.rst +++ b/doc/APIreference/functions_override.rst @@ -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` 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` 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: diff --git a/doc/XMLreference.rst b/doc/XMLreference.rst index ab3a397e..0491cb47 100644 --- a/doc/XMLreference.rst +++ b/doc/XMLreference.rst @@ -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` 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 `, joint limits will be enabled - if range is defined. + This attribute specifies if the joint has limits. It interacts with the :ref:`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 `, 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 `, actuator force clamping will be enabled if + attribute interacts with the :ref:`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 `, actuator force clamping will be enabled if :at:`actuatorfrcrange` is defined. .. _body-joint-actuatorgravcomp: diff --git a/doc/modeling.rst b/doc/modeling.rst index 41b09598..f0d3a0e6 100644 --- a/doc/modeling.rst +++ b/doc/modeling.rst @@ -1649,17 +1649,17 @@ by the :ref:`testspeed` 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`. -1. :ref:`timestep`: Try to increase the simulation timestep. As explained at the end of the +1. :ref:`Timestep`: Try to increase the simulation timestep. As explained at the end of the :ref:`Numerical Integration` 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`: Choose your integrator according to the recommendations at the end of the +2. :ref:`Integrator`: Choose your integrator according to the recommendations at the end of the :ref:`Numerical Integration` section. The default recommended choice is the ``implicitfast`` integrator. -3. :ref:`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`: 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`. 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`. 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`: Elliptic cones are more accurate and better at preventing slip with high + :ref:`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 ` 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 diff --git a/doc/overview.rst b/doc/overview.rst index f9c0797b..3bdf68a7 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -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` +attribute.