Polynomial stiffness and damping https://youtu.be/aKa3ZlEF9_Y
PiperOrigin-RevId: 884607673 Change-Id: If8088dbf37fed1055304778a7eb84dec52cba920
This commit is contained in:
committed by
Copybara-Service
parent
aec1b45dce
commit
efae9157a7
@@ -492,6 +492,11 @@ to change.
|
||||
- 10
|
||||
- The maximal number of real-valued parameters used to define the bias of each actuator.
|
||||
Determines the size of ``mjModel.actuator_biasprm``.
|
||||
* - ``mjNPOLY``
|
||||
- 2
|
||||
- The number of nonlinear polynomial coefficients for joint and tendon stiffness and damping.
|
||||
Determines the size of ``mjModel.{jnt,tendon}_{stiffness,damping}poly``. See
|
||||
:ref:`polynomial forces<gePolynomial>`.
|
||||
* - ``mjNFLUID``
|
||||
- 12
|
||||
- The number of per-geom fluid interaction parameters required by the ellipsoidal model.
|
||||
|
||||
+41
-13
@@ -2268,9 +2268,14 @@ rotations as unit quaternions.
|
||||
|
||||
.. _body-joint-stiffness:
|
||||
|
||||
:at:`stiffness`: :at-val:`real, "0"`
|
||||
Joint stiffness. If this value is positive, a spring will be created with equilibrium position given by springref
|
||||
below. The spring force is computed along with the other passive forces.
|
||||
:at:`stiffness`: :at-val:`real, "0 0 0"`
|
||||
Joint stiffness coefficients :math:`a, b, c`. A positive :math:`a` produces the standard restorative linear spring
|
||||
force :math:`f = -a x`, where :math:`x` is the joint displacement from equilibrium given by
|
||||
:ref:`springref<body-joint-springref>`.
|
||||
|
||||
If the optional second and third components are set, they define a nonlinear
|
||||
polynomial spring force :math:`f(x) = -(a x + b x^2 + c x^3)`.
|
||||
See :ref:`Polynomial forces<gePolynomial>` for details.
|
||||
|
||||
.. _body-joint-range:
|
||||
|
||||
@@ -2373,12 +2378,18 @@ rotations as unit quaternions.
|
||||
|
||||
.. _body-joint-damping:
|
||||
|
||||
:at:`damping`: :at-val:`real, "0"`
|
||||
Damping applied to all degrees of freedom created by this joint. Unlike friction loss which is computed by the
|
||||
constraint solver, damping is simply a force linear in velocity. It is included in the passive forces. Despite this
|
||||
simplicity, larger damping values can make numerical integrators unstable, which is why our Euler integrator handles
|
||||
:at:`damping`: :at-val:`real, "0 0 0"`
|
||||
Damping coefficients :math:`a, b, c`.
|
||||
A positive :math:`a` produces the standard dissipative linear damping force :math:`f(v) = -a v`,
|
||||
where :math:`v` is the joint velocity. Despite its simplicity,
|
||||
larger damping values can make numerical integrators unstable, which is why our Euler integrator handles
|
||||
damping implicitly. See :ref:`Integration <geIntegration>` in the Computation chapter.
|
||||
|
||||
If the optional second and third components are set, they define a nonlinear polynomial damping force
|
||||
:math:`f(v) = -(a v + b v |v| + c v^3)`.
|
||||
Note the anti-symmetrization of the quadratic term, ensuring that the force is an odd function of
|
||||
velocity. See :ref:`Polynomial forces<gePolynomial>` for details.
|
||||
|
||||
.. _body-joint-frictionloss:
|
||||
|
||||
:at:`frictionloss`: :at-val:`real, "0"`
|
||||
@@ -5025,15 +5036,32 @@ length X, as in the clip on the right of `this example model
|
||||
|
||||
.. _tendon-spatial-stiffness:
|
||||
|
||||
:at:`stiffness`: :at-val:`real, "0"`
|
||||
Stiffness coefficient. A positive value generates a spring force (linear in position) acting along the tendon.
|
||||
.. youtube:: aKa3ZlEF9_Y
|
||||
:aspect: 2:1
|
||||
:align: right
|
||||
:width: 35%
|
||||
|
||||
:at:`stiffness`: :at-val:`real, "0 0 0"`
|
||||
Tendon stiffness coefficients :math:`a, b, c`. A positive :math:`a` generates a linear spring force
|
||||
:math:`f(x) = -a x`, acting along the tendon. Here :math:`x` is the tendon displacement
|
||||
defined by :ref:`springlength<tendon-spatial-springlength>`.
|
||||
|
||||
If the optional second and third components are set, they define a nonlinear polynomial spring force
|
||||
:math:`f(x) = -(a x + b x^2 + c x^3)`. See :ref:`Polynomial forces<gePolynomial>` for details.
|
||||
|
||||
The clip on the right is of
|
||||
`this model <https://github.com/google-deepmind/mujoco/blob/main/test/engine/testdata/passive/poly_stiffness.xml>`__.
|
||||
|
||||
.. _tendon-spatial-damping:
|
||||
|
||||
:at:`damping`: :at-val:`real, "0"`
|
||||
Damping coefficient. A positive value generates a damping force (linear in velocity) acting along the tendon. Unlike
|
||||
joint damping which is integrated implicitly by the Euler method, tendon damping is not integrated implicitly, thus
|
||||
joint damping should be used if possible.
|
||||
:at:`damping`: :at-val:`real, "0 0 0"`
|
||||
Damping coefficients :math:`a, b, c`.
|
||||
A positive :math:`a` produces the standard dissipative linear damping force :math:`f(v) = -a v`.
|
||||
|
||||
If the optional second and third components are set, they define a nonlinear polynomial damping force
|
||||
:math:`f(v) = -(a v + b v |v| + c v^3)`.
|
||||
Note the anti-symmetrization of the quadratic term, ensuring that the force is an odd function of
|
||||
velocity. See :ref:`Polynomial forces<gePolynomial>` for details.
|
||||
|
||||
.. image:: images/XMLreference/tendon_armature.gif
|
||||
:width: 30%
|
||||
|
||||
+28
-2
@@ -5,10 +5,35 @@ Changelog
|
||||
Upcoming version (not yet released)
|
||||
-----------------------------------
|
||||
|
||||
General
|
||||
^^^^^^^
|
||||
|
||||
.. youtube:: aKa3ZlEF9_Y
|
||||
:align: right
|
||||
:width: 35%
|
||||
|
||||
- Stiffness in :ref:`joints<body-joint-stiffness>` and :ref:`tendons<tendon-spatial-stiffness>` and damping in
|
||||
:ref:`joints<body-joint-damping>` and :ref:`tendons<tendon-spatial-damping>` now support nonlinear polynomial
|
||||
:ref:`force profiles<gePolynomial>`. New ``mjModel`` arrays (``jnt_stiffnesspoly``, ``tendon_stiffnesspoly``,
|
||||
``dof_dampingpoly``, ``tendon_dampingpoly``) hold higher-order coefficients. The existing scalar arrays
|
||||
(``jnt_stiffness``, ``dof_damping``, etc.) continue to hold the linear coefficient and are unchanged.
|
||||
The polynomial order is defined by the new constant :ref:`mjNPOLY<glNumericSizes>`. A future breaking C-API change
|
||||
may unify the linear and higher-order coefficients into a single array.
|
||||
|
||||
.. admonition:: Breaking API changes
|
||||
:class: attention
|
||||
|
||||
- The ``mjs`` layer fields ``stiffness`` and ``damping`` in :ref:`mjsJoint` and :ref:`mjsTendon` have
|
||||
been widened from ``mjtNum`` scalars to ``mjtNum[mjNPOLY+1]`` arrays. The first element is the linear coefficient
|
||||
(previously the scalar), and subsequent elements are the higher-order :ref:`polynomial<gePolynomial>` coefficients.
|
||||
|
||||
**Migration:** Replace assignments like ``joint.stiffness = val`` with ``joint.stiffness[0] = val``.
|
||||
|
||||
|
||||
Bug fixes
|
||||
^^^^^^^^^
|
||||
- Compiler now correctly accounts for negative scaling when loading user specified mesh data.
|
||||
|
||||
- The compiler now correctly accounts for negative scaling when loading user specified mesh data.
|
||||
|
||||
Version 3.6.0 (March 10, 2026)
|
||||
------------------------------
|
||||
@@ -195,7 +220,8 @@ Version 3.4.0 (December 5, 2025)
|
||||
General
|
||||
^^^^^^^
|
||||
|
||||
.. youtube:: vct493lGQ8Q
|
||||
.. youtube:: aKa3ZlEF9_Y
|
||||
:aspect: 2:1
|
||||
:align: right
|
||||
:width: 35%
|
||||
|
||||
|
||||
@@ -423,6 +423,59 @@ MuJoCo can compute three types of passive forces:
|
||||
- Gravity compensation forces. See the body :ref:`gravcomp<body-gravcomp>` attribute for details.
|
||||
- Fluid forces exerted by the surrounding medium. See the :doc:`Fluid forces <fluid>` chapter for details.
|
||||
|
||||
.. _gePolynomial:
|
||||
|
||||
Polynomial forces
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Nonlinear stiffness (:ref:`joints<body-joint-stiffness>`, :ref:`tendons<tendon-spatial-stiffness>`) and
|
||||
damping (:ref:`joints<body-joint-damping>`, :ref:`tendons<tendon-spatial-damping>`) are defined by polynomials
|
||||
:math:`f` of order :ref:`mjNPOLY + 1<glNumericSizes>`. The actual force applied to the system is :math:`-f`, meaning
|
||||
that sign-preserving functions yield a restorative (stiffness) or dissipative (damping) force.
|
||||
|
||||
The stiffness polynomial takes the standard form (where :math:`x` is displacement):
|
||||
|
||||
.. math::
|
||||
f(x) = a x + b x^2 + c x^3 + \dots
|
||||
|
||||
The damping polynomial takes the anti-symmetrized form (where :math:`v` is velocity):
|
||||
|
||||
.. math::
|
||||
f(v) = a v + b v |v| + c v^3 + \dots
|
||||
|
||||
**Anti-symmetrization**
|
||||
The damping polynomial uses anti-symmetrized even-powered monomials (e.g., :math:`v^2 \rightarrow v|v|`) so that the
|
||||
function is odd: :math:`f(-v) = -f(v)`. This guarantees the force reverses direction with velocity. This formulation
|
||||
is also physically motivated, as some natural forms of damping (like fluid drag) display an anti-symmetric quadratic
|
||||
profile.
|
||||
|
||||
In contrast, asymmetric (or rather, non-anti-symmetric) stiffness profiles are physically common (e.g., biological
|
||||
fascia), making the standard polynomial form and its Taylor-series convenience more appropriate.
|
||||
|
||||
**Sign-preservation**
|
||||
In both cases, sensible choices of coefficients often satisfy the **sign-preservation** condition
|
||||
:math:`z \cdot f(z) \geq 0`. This condition is equivalent to requiring that the integral of :math:`f` (Potential
|
||||
Energy for stiffness and Dissipation for damping) is globally convex with a minimum at the origin.
|
||||
|
||||
- For stiffness, violations of the condition create repulsive forces and/or multiple equilibria.
|
||||
- For damping, violations create non-dissipative forces that inject mechanical energy into the system.
|
||||
|
||||
The sign-preservation condition is not enforced by the compiler; it is the user's responsibility to ensure it is
|
||||
satisfied. The analytical conditions on the coefficients for orders up to 3 are:
|
||||
|
||||
.. math::
|
||||
\begin{aligned}
|
||||
\textrm{Standard:} \qquad & a \geq 0, \qquad c \geq 0, \qquad b^2 \leq 4 a c \\
|
||||
\textrm{Anti-symmetrized:} \qquad & a \geq 0, \qquad c \geq 0, \qquad b < 0 \implies b^2 \leq 4 a c
|
||||
\end{aligned}
|
||||
|
||||
**mjModel fields**
|
||||
Although MJCF accepts the coefficients as a single array (as does the :ref:`mjs layer<mjsJoint>`),
|
||||
the linear coefficient in ``mjModel`` is stored separately from the higher-order ones.
|
||||
For example, if :ref:`joint/stiffness<body-joint-stiffness>` = "a b c",
|
||||
then ``jnt_stiffness[i] = a``, ``jnt_stiffnesspoly[i*mjNPOLY] = b`` and ``jnt_stiffnesspoly[i*mjNPOLY + 1] = c``.
|
||||
A future breaking change of the C-API may unify the linear and higher-order coefficients into a single array.
|
||||
|
||||
.. _geIntegration:
|
||||
|
||||
Numerical integration
|
||||
|
||||
@@ -1179,7 +1179,8 @@ struct mjModel_ {
|
||||
mjtNum* jnt_solimp; // constraint solver impedance: limit (njnt x mjNIMP)
|
||||
mjtNum* jnt_pos; // local anchor position (njnt x 3)
|
||||
mjtNum* jnt_axis; // local joint axis (njnt x 3)
|
||||
mjtNum* jnt_stiffness; // stiffness coefficient (njnt x 1)
|
||||
mjtNum* jnt_stiffness; // linear stiffness coefficient (njnt x 1)
|
||||
mjtNum* jnt_stiffnesspoly; // high-order stiffness coefficients (njnt x mjNPOLY)
|
||||
mjtNum* jnt_range; // joint limits (njnt x 2)
|
||||
mjtNum* jnt_actfrcrange; // range of total actuator force (njnt x 2)
|
||||
mjtNum* jnt_margin; // min distance for limit detection (njnt x 1)
|
||||
@@ -1196,7 +1197,8 @@ struct mjModel_ {
|
||||
mjtNum* dof_solimp; // constraint solver impedance:frictionloss (nv x mjNIMP)
|
||||
mjtNum* dof_frictionloss; // dof friction loss (nv x 1)
|
||||
mjtNum* dof_armature; // dof armature inertia/mass (nv x 1)
|
||||
mjtNum* dof_damping; // damping coefficient (nv x 1)
|
||||
mjtNum* dof_damping; // linear damping coefficient (nv x 1)
|
||||
mjtNum* dof_dampingpoly; // high-order damping coefficients (nv x mjNPOLY)
|
||||
mjtNum* dof_invweight0; // diag. inverse inertia in qpos0 (nv x 1)
|
||||
mjtNum* dof_M0; // diag. inertia in qpos0 (nv x 1)
|
||||
mjtNum* dof_length; // linear: 1; angular: approx. length scale (nv x 1)
|
||||
@@ -1501,8 +1503,10 @@ struct mjModel_ {
|
||||
mjtNum* tendon_range; // tendon length limits (ntendon x 2)
|
||||
mjtNum* tendon_actfrcrange; // range of total actuator force (ntendon x 2)
|
||||
mjtNum* tendon_margin; // min distance for limit detection (ntendon x 1)
|
||||
mjtNum* tendon_stiffness; // stiffness coefficient (ntendon x 1)
|
||||
mjtNum* tendon_damping; // damping coefficient (ntendon x 1)
|
||||
mjtNum* tendon_stiffness; // linear stiffness coefficient (ntendon x 1)
|
||||
mjtNum* tendon_stiffnesspoly; // high-order stiffness coefficients (ntendon x mjNPOLY)
|
||||
mjtNum* tendon_damping; // linear damping coefficient (ntendon x 1)
|
||||
mjtNum* tendon_dampingpoly; // high-order damping coefficients (ntendon x mjNPOLY)
|
||||
mjtNum* tendon_armature; // inertia associated with tendon velocity (ntendon x 1)
|
||||
mjtNum* tendon_frictionloss; // loss due to friction (ntendon x 1)
|
||||
mjtNum* tendon_lengthspring; // spring resting length range (ntendon x 2)
|
||||
@@ -2057,7 +2061,7 @@ typedef struct mjsJoint_ { // joint specification
|
||||
int align; // align free joint with body com (mjtAlignFree)
|
||||
|
||||
// stiffness
|
||||
double stiffness; // stiffness coefficient
|
||||
double stiffness[mjNPOLY+1]; // stiffness coefficients
|
||||
double springref; // spring reference value: qpos_spring
|
||||
double springdamper[2]; // timeconst, dampratio
|
||||
|
||||
@@ -2072,7 +2076,7 @@ typedef struct mjsJoint_ { // joint specification
|
||||
|
||||
// dof properties
|
||||
double armature; // armature inertia (mass for slider)
|
||||
double damping; // damping coefficient
|
||||
double damping[mjNPOLY+1]; // damping coefficients
|
||||
double frictionloss; // friction loss
|
||||
mjtNum solref_friction[mjNREF]; // solver reference: dof friction
|
||||
mjtNum solimp_friction[mjNIMP]; // solver impedance: dof friction
|
||||
@@ -2390,9 +2394,9 @@ typedef struct mjsTendon_ { // tendon specification
|
||||
mjsElement* element; // element type
|
||||
|
||||
// stiffness, damping, friction, armature
|
||||
double stiffness; // stiffness coefficient
|
||||
double stiffness[mjNPOLY+1]; // stiffness coefficients
|
||||
double springlength[2]; // spring resting length; {-1, -1}: use qpos_spring
|
||||
double damping; // damping coefficient
|
||||
double damping[mjNPOLY+1]; // damping coefficients
|
||||
double frictionloss; // friction loss
|
||||
mjtNum solref_friction[mjNREF]; // solver reference: tendon friction
|
||||
mjtNum solimp_friction[mjNIMP]; // solver impedance: tendon friction
|
||||
|
||||
Reference in New Issue
Block a user