From 2cb601c98d88acb2ccf4386991056c72a700e100 Mon Sep 17 00:00:00 2001 From: Yuval Tassa Date: Wed, 14 Aug 2024 03:10:28 -0700 Subject: [PATCH] Improve documentation w.r.t smoothness, differentiability and finite-differencing. PiperOrigin-RevId: 662848709 Change-Id: Icb7dc03a2c53d43d0d3a9e4ac95d963e5bc6853c --- doc/APIreference/functions.rst | 26 ++++++++++++++++++------ doc/APIreference/functions_override.rst | 27 +++++++++++++++++++------ doc/computation/index.rst | 15 ++++++++------ doc/modeling.rst | 22 ++++++++++++++------ 4 files changed, 66 insertions(+), 24 deletions(-) diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index 23561a19..f93a31b7 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -2589,7 +2589,7 @@ mjd_transitionFD .. mujoco-include:: mjd_transitionFD -Finite-differenced discrete-time transition matrices. +Compute finite-differenced discrete-time transition matrices. Letting :math:`x, u` denote the current :ref:`state` and :ref:`control` vector in an mjData instance, and letting :math:`y, s` denote the next state and sensor @@ -2610,12 +2610,26 @@ These matrices and their dimensions are: - All outputs are optional (can be NULL). - ``eps`` is the finite-differencing epsilon. - ``flg_centered`` denotes whether to use forward (0) or centered (1) differences. -- Accuracy can be somewhat improved if solver :ref:`iterations` are set to a - fixed (small) value and solver :ref:`tolerance` is set to 0. This insures that - all calls to the solver will perform exactly the same number of iterations. +- The Runge-Kutta integrator (:ref:`mjINT_RK4`) is not supported. -.. attention:: - - The Runge-Kutta 4th-order integrator (``mjINT_RK4``) is not supported. +.. admonition:: Improving speed and accuracy + :class: tip + + warmstart + If warm-starts are not :ref:`disabled`, the warm-start accelerations + ``mjData.qacc_warmstart`` which are present at call-time are loaded at the start of every relevant pipeline call, + to preserve determinism. If solver computations are an expensive part of the simulation, the following trick can + lead to significant speed-ups: First call :ref:`mj_forward` to let the solver converge, then reduce :ref:`solver + iterations` significantly, then call :ref:`mjd_transitionFD`, finally, restore the original + value of :ref:`iterations`. Because we are already near the solution, few iteration are required + to find the new minimum. This is especially true for the :ref:`Newton` solver, where the required + number of iteration for convergence near the minimum can be as low as 1. + + tolerance + Accuracy can be improved if solver :ref:`tolerance` is set to 0. This means that all calls to + the solver will perform exactly the same number of iterations, preventing numerical errors due to early + termination. Of course, this means that :ref:`solver iterations` should be small, to not tread + water at the minimum. This method and the one described above can and should be combined. .. _mjd_inverseFD: diff --git a/doc/APIreference/functions_override.rst b/doc/APIreference/functions_override.rst index 35e651e7..4e7b6b50 100644 --- a/doc/APIreference/functions_override.rst +++ b/doc/APIreference/functions_override.rst @@ -567,7 +567,7 @@ outputs of derivative functions are the trailing rather than leading arguments. .. _mjd_transitionFD: -Finite-differenced discrete-time transition matrices. +Compute finite-differenced discrete-time transition matrices. Letting :math:`x, u` denote the current :ref:`state` and :ref:`control` vector in an mjData instance, and letting :math:`y, s` denote the next state and sensor @@ -588,12 +588,27 @@ These matrices and their dimensions are: - All outputs are optional (can be NULL). - ``eps`` is the finite-differencing epsilon. - ``flg_centered`` denotes whether to use forward (0) or centered (1) differences. -- Accuracy can be somewhat improved if solver :ref:`iterations` are set to a - fixed (small) value and solver :ref:`tolerance` is set to 0. This insures that - all calls to the solver will perform exactly the same number of iterations. +- The Runge-Kutta integrator (:ref:`mjINT_RK4`) is not supported. + +.. admonition:: Improving speed and accuracy + :class: tip + + warmstart + If warm-starts are not :ref:`disabled`, the warm-start accelerations + ``mjData.qacc_warmstart`` which are present at call-time are loaded at the start of every relevant pipeline call, + to preserve determinism. If solver computations are an expensive part of the simulation, the following trick can + lead to significant speed-ups: First call :ref:`mj_forward` to let the solver converge, then reduce :ref:`solver + iterations` significantly, then call :ref:`mjd_transitionFD`, finally, restore the original + value of :ref:`iterations`. Because we are already near the solution, few iteration are required + to find the new minimum. This is especially true for the :ref:`Newton` solver, where the required + number of iteration for convergence near the minimum can be as low as 1. + + tolerance + Accuracy can be improved if solver :ref:`tolerance` is set to 0. This means that all calls to + the solver will perform exactly the same number of iterations, preventing numerical errors due to early + termination. Of course, this means that :ref:`solver iterations` should be small, to not tread + water at the minimum. This method and the one described above can and should be combined. -.. attention:: - - The Runge-Kutta 4th-order integrator (``mjINT_RK4``) is not supported. .. _mjd_inverseFD: diff --git a/doc/computation/index.rst b/doc/computation/index.rst index 06e0da68..8d00a459 100644 --- a/doc/computation/index.rst +++ b/doc/computation/index.rst @@ -1722,20 +1722,23 @@ The top-level function :ref:`mj_inverse` invokes the following sequence of compu Derivatives ----------- -MuJoCo's entire computational pipline including its constraint solver are analytically differentiable. Writing -efficient implementations of these derivatives is a long term goal of the development team. Analytic derivatives of the -smooth dynamics (excluding constraints) with respect to velocity are already computed and enable the two +MuJoCo's entire computational pipline including its constraint solver are analytically differentiable in principle. +Writing efficient implementations of these derivatives is a long term goal of the development team. Analytic derivatives +of the smooth dynamics (excluding constraints) with respect to velocity are already computed and enable the two :ref:`implicit integrators`. +Note that the default value of the :ref:`solver impedance` is such that contacts are *not* +differentiable by default, and needs to be :ref:`set to 0` in order for contact-force onset to be smooth. + Two functions are currently available which use efficient finite-differencing in order to compute dynamics Jacobians: :ref:`mjd_transitionFD`: Computes state-transition and control-transition Jacobians for the discrete-time forward dynamics (:ref:`mj_step`). - See :ref:`API documentation`. + See :ref:`documentation`. :ref:`mjd_inverseFD`: - Computes Jacobians for the continuous-time inverse dynamics (:ref:`mj_inverse`). - See :ref:`API documentation`. + Computes Jacobians for the continuous or discrete-time inverse dynamics (:ref:`mj_inverse`). + See :ref:`documentation`. These derivatives are made efficient by exploiting MuJoCo's configurable computation pipeline so that quantities are not recomputed when not required. For example when differencing with respect to controls, quantities which depend only on diff --git a/doc/modeling.rst b/doc/modeling.rst index 325317f1..41b09598 100644 --- a/doc/modeling.rst +++ b/doc/modeling.rst @@ -347,8 +347,15 @@ of the function :math:`d(r)` is determined by the element-specific parameter vec For friction loss or friction dimensions of elliptic cones, the violation :math:`r` is identically zero, so only :math:`d(0)` affects these constraints, all other :at:`solimp` values are ignored. - .. tip:: - For completely smooth dynamics, limits and contacts should have :math:`d_0=0`. + .. _solimp0: + + .. admonition:: Smoothness and differentiability + :class: tip + + For completely smooth (differentiable) dynamics, limits and contacts should have :math:`d_0=0` (``solimp[0]=0``). + Specifically for contacts, the :ref:`mixing rules` of geom-associated solver parameters should be kept + in mind. See also discussion of derivatives in the :ref:`Computation chapter` and in the + :ref:`mjd_transitionFD` documentation. .. _CSolverReference: @@ -485,11 +492,14 @@ are as follows: **margin**, **gap** The maximum of the two geom margins (or gaps respectively) is used. The geom priority is ignored here, because the margin and gap are distance properties and a one-sided specification makes little sense. + +.. _solmixing: + **solref**, **solimp** - If one of the two geoms has higher priority, its solref and solimp parameters are used. If both geoms have the same - priority, the weighted average is used. The weights are proportional to the solmix attributes, i.e., weight1 = - solmix1 / (solmix1 + solmix2) and similarly for weight2. There is one important exception to this weighted averaging - rule. If solref for either geom is non-positive, i.e., it relies on the direct format, + If one of the two geoms has higher :ref:`priority`, its solref and solimp parameters are used. If + both geoms have the same priority, the weighted average is used. The weights are proportional to the solmix + attributes, i.e., weight1 = solmix1 / (solmix1 + solmix2) and similarly for weight2. There is one important exception + to this weighted averaging rule. If solref for either geom is non-positive, i.e., it relies on the direct format, then the element-wise minimum is used regardless of solmix. This is because averaging solref parameters in different formats would be meaningless.