Add SO3 transmission and native orientation actuator.
https://youtu.be/17XpwnqyCXs New transmission type mjTRN_SO3: a relative orientation, targeting a ball joint or a site+refsite pair. It is the first transmission with more than one force output: its length is the norm of the expmap vector of the relative rotation and its moment axes are the 3 rows of the relative rotational Jacobian, without projecting onto per-actuator gears. New force law mjGAIN_SO3/mjBIAS_SO3: a geodesic PD servo, force = kp * log(q_current^-1 * q_target) - kv * velocity, exact for arbitrary axis combinations with a unique equilibrium at every commanded orientation. Error, moment rows and velocity all live in the child frame (joint or site): the right-difference error is the gradient of the geodesic potential in that frame. The parent-frame (left) error is not: driving child-frame torques with it pumps energy at large angles, settling into steady-spinning limit cycles (the SO3LargeAngleConvergence test). The integrator variant stores the 3D orientation setpoint in act (actnum = 3, re-anchored to a bounded representative at integration time). Exposed in MJCF as <orientation joint=|site=+refsite= kp kv|dampratio>, or via <general gaintype="so3" biastype="so3">. The setpoint input has two charts: an expmap target (3 controls, default) or a quaternion target (4 controls) -- <orientation input="quat">, the first actuator with different input and output widths. The signature is recorded in a new per-actuator field actuator_ctrlspec (mjtCtrlChart), whose meaning is scoped by the gain type the way gain/bias parameters are; ctrlnum is derived from it at compile time and remains the layout authority. An explicit field rather than width inference or a prm slot: width-as-chart cannot express same-width signatures (upcoming servo input subsets), and prm slots are the input_mode pattern this stack retires. The force law normalizes the commanded quaternion, making it scale- and antipodally-invariant. The all-zero ctrl still maps to the identity via mju_normalize4, but it is a degenerate point (a nudge of any component commands a half-turn), so quat inputs reset to the identity quaternion: new mj_resetCtrl sets neutral ctrl values (zero, except qw = 1), called by mj_resetData and the viewers' Clear All. The quat chart is restricted to dyntype 'none': integrating a quaternion setpoint linearly is not meaningful on the manifold. New mjsActuator.ctrlspec field carries the signature through the spec and XML round-trip. Actuator sensors (actuatorpos/vel/frc) now report one value per force output; dim = 3 on an SO3 actuator. As the first actuator with nu != nactuator, this commit also makes the viewers multi-input aware: the control sliders in simulate and studio, which indexed per-actuator arrays by control index (out of bounds on this model class), are generated per control and labeled with the actuator name plus an input suffix ("orient/qw"), via the new introspection helper mj_actuatorInputName -- the single source of truth for input names, extended by each new multi-input type (quaternion components are w-first: qw, qx, qy, qz). Slider ranges now honor a defined ctrlrange even when ctrllimited is false: range is the UI hint, limited is the clamp -- wrapped and expmap setpoints are unbounded but still want finite sliders, while quat components are truly bounded. The rotational demo model is orientation.xml under test/engine/testdata/actuation/, upgraded to a three-way contrast: per-axis wrapped servos vs an expmap-commanded vs a quat-commanded orientation actuator, on identical checker-textured boxes. It is loaded by the mixed-axis contrast and input-name tests, and doubles as the viewer test model (slider groups of 3 independent, 3 grouped, 4 grouped). PiperOrigin-RevId: 951607063 Change-Id: If235dba8e2f2ca72672e7c62531a27e967c6a373
This commit is contained in:
committed by
Copybara-Service
parent
a8545ac7cc
commit
072e963fa0
+113
-2
@@ -5488,6 +5488,8 @@ specify them independently.
|
||||
|
||||
:at:`forcerange`: :at-val:`real(2), "0 0"`
|
||||
Range for clamping the force output. The first value must be no greater than the second value.
|
||||
On :ref:`orientation<actuator-orientation>` actuators the force is a 3D torque, clamped on its norm: the second
|
||||
value bounds the torque magnitude and the first value must be 0.
|
||||
|br| Setting this attribute without specifying :at:`forcelimited` is an error if :at:`autolimits` is "false" in
|
||||
:ref:`compiler <compiler>`.
|
||||
|
||||
@@ -5678,7 +5680,7 @@ specify them independently.
|
||||
|
||||
.. _actuator-general-gaintype:
|
||||
|
||||
:at:`gaintype`: :at-val:`[fixed, affine, muscle, user], "fixed"`
|
||||
:at:`gaintype`: :at-val:`[fixed, affine, muscle, so3, user], "fixed"`
|
||||
The gain and bias together determine the output of the force generation mechanism, which is currently assumed to be
|
||||
affine. As already explained in :ref:`Actuation model <geActuation>`, the general formula is:
|
||||
scalar_force = gain_term \* (act or ctrl) + bias_term.
|
||||
@@ -5691,12 +5693,13 @@ specify them independently.
|
||||
fixed gain_term = gainprm[0]
|
||||
affine gain_term = gain_prm[0] + gain_prm[1]*length + gain_prm[2]*velocity
|
||||
muscle gain_term = mju_muscleGain(...)
|
||||
so3 geodesic orientation servo, computed jointly over 3 force outputs, see :ref:`orientation<actuator-orientation>`
|
||||
user gain_term = mjcb_act_gain(...)
|
||||
======= ===============================
|
||||
|
||||
.. _actuator-general-biastype:
|
||||
|
||||
:at:`biastype`: :at-val:`[none, affine, muscle, user], "none"`
|
||||
:at:`biastype`: :at-val:`[none, affine, muscle, so3, user], "none"`
|
||||
The keywords have the following meaning:
|
||||
|
||||
======= ================================================================
|
||||
@@ -5705,9 +5708,12 @@ specify them independently.
|
||||
none bias_term = 0
|
||||
affine bias_term = biasprm[0] + biasprm[1]*length + biasprm[2]*velocity
|
||||
muscle bias_term = mju_muscleBias(...)
|
||||
so3 damping term of the geodesic orientation servo, see :ref:`orientation<actuator-orientation>`
|
||||
user bias_term = mjcb_act_bias(...)
|
||||
======= ================================================================
|
||||
|
||||
Note that :at:`gaintype` and :at:`biastype` must either both be "so3" or neither.
|
||||
|
||||
.. _actuator-general-dynprm:
|
||||
|
||||
:at:`dynprm`: :at-val:`real(10), "1 0 ... 0"`
|
||||
@@ -5731,6 +5737,13 @@ specify them independently.
|
||||
so the user can enter as many parameters as needed. These defaults are not compatible with muscle actuators; see
|
||||
:ref:`muscle <actuator-muscle>` below.
|
||||
|
||||
.. _actuator-general-input:
|
||||
|
||||
:at:`input`: :at-val:`string, optional`
|
||||
Input signature of the actuator: which controls make up its control block, recorded in
|
||||
``mjModel.actuator_ctrlspec``. Available for gaintype "so3", where it selects the orientation chart: "expmap"
|
||||
(3 controls, the default) or "quat" (4 controls); see :ref:`orientation/input<actuator-orientation-input>`.
|
||||
|
||||
.. _actuator-general-actearly:
|
||||
|
||||
:at:`actearly`: :at-val:`[false, true], "false"`
|
||||
@@ -5939,6 +5952,102 @@ This element has one custom attribute in addition to the common attributes:
|
||||
:ref:`position<actuator-position>` attribute and in the :ref:`default class<default-position-inheritrange>`,
|
||||
saved XMLs always convert it to explicit :at:`ctrlrange` at the actuator.
|
||||
|
||||
.. _actuator-orientation:
|
||||
|
||||
:el-prefix:`actuator/` |-| **orientation** |*|
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. youtube:: 17XpwnqyCXs
|
||||
:align: right
|
||||
:width: 40%
|
||||
|
||||
This element creates an orientation servo: a geodesic PD controller on a relative orientation, targeting a ball
|
||||
:ref:`joint<actuator-general-joint>` or a :ref:`site<actuator-general-site>` with a
|
||||
:ref:`refsite<actuator-general-refsite>`. Unlike per-axis :ref:`position<actuator-position>` servos, the servo acts
|
||||
jointly on the full orientation: the force is :math:`k_p \log(q^{-1} q_{target}) - k_v \omega`, exact for arbitrary axis
|
||||
combinations, with a unique equilibrium at every commanded orientation. The transmission has 3 force outputs; force,
|
||||
error and angular velocity are expressed in the child (joint or site) frame. The commanded orientation is given in the
|
||||
:ref:`input<actuator-orientation-input>` chart: an exponential-map vector (3 controls, the default) or a quaternion (4
|
||||
controls). :ref:`forcerange<actuator-general-forcerange>` clamps the norm of the output torque,
|
||||
preserving its direction; the lower bound must be 0.
|
||||
:ref:`Actuator sensors<sensor-actuatorpos>` report one value per force output. The integrator variant, which
|
||||
stores the orientation setpoint in :ref:`act<siPhysicsState>`, is available via :ref:`general<actuator-general>` with
|
||||
:ref:`dyntype<actuator-general-dyntype>` "integrator" and is expmap-only. The video on the right shows this `example
|
||||
model <https://github.com/google-deepmind/mujoco/blob/main/test/engine/testdata/sensor/actuation/orientation.xml>`__.
|
||||
The underlying :el:`general` attributes are set as follows:
|
||||
|
||||
========= ======= ========= =========
|
||||
Attribute Setting Attribute Setting
|
||||
========= ======= ========= =========
|
||||
dyntype none gainprm kp 0 0
|
||||
gaintype so3 biasprm 0 -kp -kv
|
||||
biastype so3
|
||||
========= ======= ========= =========
|
||||
|
||||
.. _actuator-orientation-ctrlrange:
|
||||
|
||||
:at:`ctrlrange`: :at-val:`real(2), "0 0"`
|
||||
Range for clamping the control input, as described in :ref:`ctrlrange <actuator-general-ctrlrange>`. For this
|
||||
multi-input actuator, the same range limits are replicated and applied independently to each of the 3 (expmap) or 4
|
||||
(quaternion) control inputs in the control block.
|
||||
|
||||
.. _actuator-orientation-forcerange:
|
||||
|
||||
:at:`forcerange`: :at-val:`real(2), "0 0"`
|
||||
Range for clamping the torque output, as described in :ref:`forcerange <actuator-general-forcerange>`. The torque is
|
||||
clamped on its norm, preserving its direction: the second value bounds the torque magnitude and the first value must
|
||||
be 0.
|
||||
|
||||
This element has custom attributes in addition to the common attributes:
|
||||
|
||||
.. _actuator-orientation-name:
|
||||
|
||||
.. _actuator-orientation-class:
|
||||
|
||||
.. _actuator-orientation-group:
|
||||
|
||||
.. _actuator-orientation-nsample:
|
||||
|
||||
.. _actuator-orientation-interp:
|
||||
|
||||
.. _actuator-orientation-delay:
|
||||
|
||||
.. _actuator-orientation-forcelimited:
|
||||
|
||||
.. _actuator-orientation-user:
|
||||
|
||||
.. _actuator-orientation-joint:
|
||||
|
||||
.. _actuator-orientation-site:
|
||||
|
||||
.. _actuator-orientation-refsite:
|
||||
|
||||
.. _actuator-orientation-kp:
|
||||
|
||||
:at:`kp`: :at-val:`real, "1"`
|
||||
Position feedback gain, in units of torque per radian of geodesic error.
|
||||
|
||||
.. _actuator-orientation-kv:
|
||||
|
||||
:at:`kv`: :at-val:`real, "0"`
|
||||
Damping applied by the actuator, per force output.
|
||||
When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators<geIntegration>`.
|
||||
|
||||
.. _actuator-orientation-dampratio:
|
||||
|
||||
:at:`dampratio`: :at-val:`real, "0"`
|
||||
Damping applied by the actuator, using damping ratio units, as for
|
||||
:ref:`position/dampratio<actuator-position-dampratio>`. This attribute is exclusive with :at:`kv`.
|
||||
|
||||
.. _actuator-orientation-input:
|
||||
|
||||
:at:`input`: :at-val:`[expmap, quat], "expmap"`
|
||||
`Chart <https://en.wikipedia.org/wiki/Manifold#Charts>`__ of the commanded orientation. With "expmap" the control
|
||||
block is an exponential-map vector (3 controls, in radians). With "quat" the control block is a quaternion (4
|
||||
controls, :ref:`w-first <siLayout>`); the commanded quaternion is normalized by the servo, making the force scale-
|
||||
and antipodally-invariant, and the control block resets to the identity quaternion. The quat chart requires
|
||||
``dyntype="none"``.
|
||||
|
||||
.. _actuator-velocity:
|
||||
|
||||
:el-prefix:`actuator/` |-| **velocity** |*|
|
||||
@@ -9907,6 +10016,8 @@ if omitted.
|
||||
|
||||
.. _default-general-biasprm:
|
||||
|
||||
.. _default-general-input:
|
||||
|
||||
.. _default-general-actearly:
|
||||
|
||||
:el-prefix:`default/` |-| **general** |?|
|
||||
|
||||
Reference in New Issue
Block a user