Add <dcmotor> actuator and related docs and tests.

PiperOrigin-RevId: 892927987
Change-Id: I38ed6412801341ba03ddf5fe7b93a6081df24d37
This commit is contained in:
Yuval Tassa
2026-04-01 07:49:53 -07:00
committed by Copybara-Service
parent 6da210c794
commit 70a7647ad9
31 changed files with 3994 additions and 55 deletions
+9
View File
@@ -4658,6 +4658,15 @@ Set actuator to muscle; return error if any.a
Set actuator to active adhesion; return error if any.
.. _mjs_setToDCMotor:
`mjs_setToDCMotor <#mjs_setToDCMotor>`__
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. mujoco-include:: mjs_setToDCMotor
Set actuator to DC motor; return error if any.
.. _AddAssets:
Assets
+219
View File
@@ -6323,6 +6323,174 @@ This element has a subset of the common attributes and two custom attributes.
to the target body.
.. _actuator-dcmotor:
:el-prefix:`actuator/` |-| **dcmotor** |*|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This element creates a DC motor actuator. Note that :el:`dcmotor` is quite different from the :ref:`general actuation
model<geActuation>`. Unlike the general model where the components of force generation are independent affine functions
mapping from control to force, :el:`dcmotor` relies on highly coupled physical dynamics. See the `DC motor technical
note <_static/dcmotor.pdf>`__ for complete mathematical formulations and parameter semantics, but we include a few
important notes here:
- Note that while :ref:`resistance<actuator-dcmotor-resistance>`, :ref:`motorconst<actuator-dcmotor-motorconst>` and
:ref:`nominal<actuator-dcmotor-nominal>` are each optional, some combination of them is required.
See Section 2.1 of the `technical note <_static/dcmotor.pdf>`__.
- The control :ref:`input<actuator-dcmotor-input>` semantic is either the voltage applied to the motor terminals, or a
position or velocity target for a PID :ref:`controller<actuator-dcmotor-controller>`.
- Optional features include electrical dynamics (:ref:`inductance<actuator-dcmotor-inductance>`),
:ref:`cogging torque<actuator-dcmotor-cogging>`, :ref:`thermal resistance variation<actuator-dcmotor-thermal>`, and
:ref:`LuGre<actuator-dcmotor-lugre>` friction.
The underlying :el:`general` attributes are set to the :el:`dcmotor` type, and their associated parameter arrays are
computed internally:
========= ======= ========= ========
Attribute Setting Attribute Setting
========= ======= ========= ========
dyntype dcmotor dynprm computed
gaintype dcmotor gainprm computed
biastype dcmotor biasprm computed
========= ======= ========= ========
This element has the following custom attributes in addition to the common attributes:
.. _actuator-dcmotor-name:
.. _actuator-dcmotor-class:
.. _actuator-dcmotor-group:
.. _actuator-dcmotor-delay:
.. _actuator-dcmotor-nsample:
.. _actuator-dcmotor-interp:
.. _actuator-dcmotor-ctrllimited:
.. _actuator-dcmotor-ctrlrange:
.. _actuator-dcmotor-lengthrange:
.. _actuator-dcmotor-gear:
.. _actuator-dcmotor-damping:
.. _actuator-dcmotor-armature:
.. _actuator-dcmotor-cranklength:
.. _actuator-dcmotor-joint:
.. _actuator-dcmotor-jointinparent:
.. _actuator-dcmotor-tendon:
.. _actuator-dcmotor-cranksite:
.. _actuator-dcmotor-slidersite:
.. _actuator-dcmotor-site:
.. _actuator-dcmotor-refsite:
.. _actuator-dcmotor-user:
.. |actuator/dcmotor attrib list| replace::
:at:`name`, :at:`class`, :at:`group`, :at:`nsample`, :at:`interp`, :at:`delay`, :at:`ctrllimited`, :at:`ctrlrange`,
:at:`lengthrange`, :at:`gear`, :at:`damping`, :at:`armature`, :at:`cranklength`, :at:`joint`, :at:`jointinparent`,
:at:`tendon`, :at:`cranksite`, :at:`slidersite`, :at:`site`, :at:`refsite`, :at:`user`
|actuator/dcmotor attrib list|
Same as in actuator/ :ref:`general <actuator-general>`.
.. _actuator-dcmotor-resistance:
:at:`resistance`: :at-val:`real, optional`
Terminal resistance :math:`R` in Ohm. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-motorconst:
:at:`motorconst`: :at-val:`real(2), optional`
Motor constants, defined as :at:`motorconst` = ":at-val:`Kt` :at-val:`Ke`" (N·m/A, equivalently V·s/rad).
:at-val:`Kt` is the torque constant and :at-val:`Ke` the back-EMF constant; they can differ when magnetic saturation
is present. If both are positive, the effective constant is :math:`K = \sqrt{K_t K_e}` (geometric mean). If only one
is positive, :math:`K` equals that value; a single value is interpreted as :math:`K_t = K_e`. If your datasheet gives
the speed constant :math:`K_v` in rad/(V·s), use :math:`K_e = 1/K_v`. (see `tech note <_static/dcmotor.pdf>`__ for
details)
.. _actuator-dcmotor-nominal:
:at:`nominal`: :at-val:`real(3), optional`
Nominal operating point, defined as :at:`nominal` = ":at-val:`voltage` :at-val:`stall_torque`
:at-val:`no_load_speed`". The compiler derives :math:`K =` :at-val:`voltage` / :at-val:`no_load_speed` and :math:`R =
K` · :at-val:`voltage` / :at-val:`stall_torque`. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-inductance:
:at:`inductance`: :at-val:`real(2), "0 0"`
Electrical dynamics, defined as :at:`inductance` = ":at-val:`L` :at-val:`timeconst`" (Henry, seconds). These are
alternative specifications: :at-val:`L` is the winding inductance and :at-val:`timeconst` :math:`= L/R` is the
electrical time constant. Specify one; if both are given, :at-val:`L` takes precedence. If both are 0 (the default),
no electrical dynamics are modeled and the current is computed algebraically. Adds one activation variable for
armature current. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-thermal:
:at:`thermal`: :at-val:`real(6), "0 0 0 0 0 0"`
Thermal model, defined as :at:`thermal` = ":at-val:`resistance` :at-val:`capacitance` :at-val:`timeconst`
:at-val:`tempcoef` :at-val:`reftemp` :at-val:`ambient`" (K/W, J/K, s, 1/K, °C, °C). The first three sub-values
specify the thermal time constant: :at-val:`timeconst` = :at-val:`resistance` :math:`\times` :at-val:`capacitance`.
Specify either :at-val:`timeconst` directly, or :at-val:`resistance` and :at-val:`capacitance`; if all three are
given, :at-val:`timeconst` takes precedence. If all are 0 (the default), thermal modeling is disabled. Adds one
activation variable for winding temperature. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-saturation:
:at:`saturation`: :at-val:`real(4), "0 0 0 0"`
Limits on the actuator, defined as :at:`saturation` = ":at-val:`torque` :at-val:`current` :at-val:`voltage`
:at-val:`current_rate`". :at-val:`torque` and :at-val:`current` are alternative specifications of the maximum
continuous torque: if :at-val:`current` is given, :at-val:`torque` :math:`= K \cdot` :at-val:`current`; if both are
given, :at-val:`torque` takes precedence. Sets :at:`forcerange` to [:math:`-\tau_{\max},\, \tau_{\max}`].
:at-val:`voltage` sets the maximum voltage :math:`V_{\max}`. :at-val:`current_rate` sets the maximum rate of change
of current :math:`(di/dt)_{\max}` (requires :ref:`inductance<actuator-dcmotor-inductance>`). A value of 0 (the
default) for any sub-value disables the respective limit. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-cogging:
:at:`cogging`: :at-val:`real(3), "0 0 0"`
Cogging torque, defined as :at:`cogging` = ":at-val:`amplitude` :at-val:`poles` :at-val:`phase`" (N·m, integer, rad).
Adds a position-dependent torque :math:`= \textsf{amplitude} \cdot \sin(\textsf{poles} \cdot \theta +
\textsf{phase})`. Disabled when :at-val:`amplitude` = 0 (the default).
(see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-lugre:
:at:`lugre`: :at-val:`real(6), "0 0 0 0 0 0"`
LuGre friction, defined as :at:`lugre` = ":at-val:`stiffness` :at-val:`damping` :at-val:`viscous` :at-val:`coulomb`
:at-val:`static` :at-val:`stribeck`" (N·m/rad, N·m·s/rad, N·m·s/rad, N·m, N·m, rad/s). Disabled when
:at-val:`stiffness` = 0 (the default). Adds one activation variable for bristle deflection. Note that the
:at-val:`viscous` coefficient is mapped directly to the actuator :ref:`damping<actuator-general-damping>` array
(specifically the linear term, :at-val:`damping[0]`). If both are specified, their values are summed.
(see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-input:
:at:`input`: :at-val:`[voltage, position, velocity], "voltage"`
Specifies the input signal semantics. In "voltage" mode, the control directly sets applied motor voltage. In
"position" or "velocity" modes, the PID :ref:`controller<actuator-dcmotor-controller>` uses the control as a
reference setpoint relative to the joint trajectory. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-dcmotor-controller:
:at:`controller`: :at-val:`real(5), "0 0 0 0 0"`
PID controller parameters, defined as :at:`controller` = ":at-val:`kp` :at-val:`ki` :at-val:`kd`
:at-val:`slewmax` :at-val:`Imax`". Depending on the :at:`input` mode, the controller stabilizes either position or
velocity. If the :at:`input` mode is voltage, the controller is ignored. A value of 0 (the default) disables the
respective feature: :at-val:`slewmax` = 0 means no slew-rate limiting, :at-val:`Imax` = 0 means no anti-windup
clamping. (see `tech note <_static/dcmotor.pdf>`__ for details)
.. _actuator-plugin:
:el-prefix:`actuator/` |-| **plugin** |?|
@@ -9887,6 +10055,57 @@ refsite, tendon, slidersite, cranksite.
All :ref:`adhesion <actuator-adhesion>` attributes are available here except: name, class, body.
.. _default-dcmotor:
.. _default-dcmotor-ctrllimited:
.. _default-dcmotor-ctrlrange:
.. _default-dcmotor-gear:
.. _default-dcmotor-damping:
.. _default-dcmotor-armature:
.. _default-dcmotor-cranklength:
.. _default-dcmotor-user:
.. _default-dcmotor-group:
.. _default-dcmotor-delay:
.. _default-dcmotor-nsample:
.. _default-dcmotor-interp:
.. _default-dcmotor-motorconst:
.. _default-dcmotor-resistance:
.. _default-dcmotor-nominal:
.. _default-dcmotor-saturation:
.. _default-dcmotor-inductance:
.. _default-dcmotor-cogging:
.. _default-dcmotor-controller:
.. _default-dcmotor-input:
.. _default-dcmotor-thermal:
.. _default-dcmotor-lugre:
:el-prefix:`default/` |-| **dcmotor** |?|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All :ref:`dcmotor <actuator-dcmotor>` attributes are available here except: name, class, joint, jointinparent, site,
refsite, tendon, slidersite, cranksite.
.. _custom:
**custom** |*|
+168
View File
@@ -2984,6 +2984,105 @@
:ref:`gain<actuator-adhesion-gain>`
.. dropdown:: :ref:`dcmotor<actuator-dcmotor>` |*|
.. grid:: 2 3 4 4
:gutter: 0
.. grid-item::
:ref:`name<actuator-dcmotor-name>`
.. grid-item::
:ref:`class<actuator-dcmotor-class>`
.. grid-item::
:ref:`group<actuator-dcmotor-group>`
.. grid-item::
:ref:`nsample<actuator-dcmotor-nsample>`
.. grid-item::
:ref:`interp<actuator-dcmotor-interp>`
.. grid-item::
:ref:`delay<actuator-dcmotor-delay>`
.. grid-item::
:ref:`ctrllimited<actuator-dcmotor-ctrllimited>`
.. grid-item::
:ref:`ctrlrange<actuator-dcmotor-ctrlrange>`
.. grid-item::
:ref:`lengthrange<actuator-dcmotor-lengthrange>`
.. grid-item::
:ref:`gear<actuator-dcmotor-gear>`
.. grid-item::
:ref:`damping<actuator-dcmotor-damping>`
.. grid-item::
:ref:`armature<actuator-dcmotor-armature>`
.. grid-item::
:ref:`cranklength<actuator-dcmotor-cranklength>`
.. grid-item::
:ref:`user<actuator-dcmotor-user>`
.. grid-item::
:ref:`joint<actuator-dcmotor-joint>`
.. grid-item::
:ref:`jointinparent<actuator-dcmotor-jointinparent>`
.. grid-item::
:ref:`tendon<actuator-dcmotor-tendon>`
.. grid-item::
:ref:`slidersite<actuator-dcmotor-slidersite>`
.. grid-item::
:ref:`cranksite<actuator-dcmotor-cranksite>`
.. grid-item::
:ref:`site<actuator-dcmotor-site>`
.. grid-item::
:ref:`refsite<actuator-dcmotor-refsite>`
.. grid-item::
:ref:`motorconst<actuator-dcmotor-motorconst>`
.. grid-item::
:ref:`resistance<actuator-dcmotor-resistance>`
.. grid-item::
:ref:`nominal<actuator-dcmotor-nominal>`
.. grid-item::
:ref:`saturation<actuator-dcmotor-saturation>`
.. grid-item::
:ref:`inductance<actuator-dcmotor-inductance>`
.. grid-item::
:ref:`cogging<actuator-dcmotor-cogging>`
.. grid-item::
:ref:`controller<actuator-dcmotor-controller>`
.. grid-item::
:ref:`thermal<actuator-dcmotor-thermal>`
.. grid-item::
:ref:`lugre<actuator-dcmotor-lugre>`
.. grid-item::
:ref:`input<actuator-dcmotor-input>`
.. dropdown:: :ref:`plugin<actuator-plugin>` |*|
.. grid:: 2 3 4 4
@@ -6146,6 +6245,75 @@
:ref:`delay<default-adhesion-delay>`
.. dropdown:: :ref:`dcmotor<default-dcmotor>` :octicon:`dot`
.. grid:: 2 3 4 4
:gutter: 0
.. grid-item::
:ref:`ctrllimited<default-dcmotor-ctrllimited>`
.. grid-item::
:ref:`ctrlrange<default-dcmotor-ctrlrange>`
.. grid-item::
:ref:`gear<default-dcmotor-gear>`
.. grid-item::
:ref:`damping<default-dcmotor-damping>`
.. grid-item::
:ref:`armature<default-dcmotor-armature>`
.. grid-item::
:ref:`cranklength<default-dcmotor-cranklength>`
.. grid-item::
:ref:`user<default-dcmotor-user>`
.. grid-item::
:ref:`group<default-dcmotor-group>`
.. grid-item::
:ref:`nsample<default-dcmotor-nsample>`
.. grid-item::
:ref:`interp<default-dcmotor-interp>`
.. grid-item::
:ref:`delay<default-dcmotor-delay>`
.. grid-item::
:ref:`motorconst<default-dcmotor-motorconst>`
.. grid-item::
:ref:`resistance<default-dcmotor-resistance>`
.. grid-item::
:ref:`nominal<default-dcmotor-nominal>`
.. grid-item::
:ref:`saturation<default-dcmotor-saturation>`
.. grid-item::
:ref:`inductance<default-dcmotor-inductance>`
.. grid-item::
:ref:`cogging<default-dcmotor-cogging>`
.. grid-item::
:ref:`controller<default-dcmotor-controller>`
.. grid-item::
:ref:`input<default-dcmotor-input>`
.. grid-item::
:ref:`thermal<default-dcmotor-thermal>`
.. grid-item::
:ref:`lugre<default-dcmotor-lugre>`
.. dropdown:: :ref:`custom<custom>` |*|
BIN
View File
Binary file not shown.
+3
View File
@@ -8,6 +8,9 @@ Upcoming version (not yet released)
General
^^^^^^^
- Added the :ref:`dcmotor<actuator-dcmotor>` actuator for modeling DC motors. Supports optional
electrical dynamics (inductance), cogging torque, thermal resistance variation, and LuGre friction. See the
`technical note <_static/dcmotor.pdf>`__ for more details.
- Actuators with joint or tendon transmissions can now contribute
:ref:`damping<actuator-general-damping>` and :ref:`armature<actuator-general-armature>` to their transmission target.
These are applied during the passive force and inertia computations, respectively, and are scaled by gear\ :sup:`2`
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
# Copyright 2026 DeepMind Technologies Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
pdflatex -interaction=nonstopmode -jobname=dcmotor dcmotor.tex 2>&1 | grep -E '(Error|Output written)' && \
bibtex dcmotor 2>&1 | grep -v '^$' && \
pdflatex -interaction=nonstopmode -jobname=dcmotor dcmotor.tex 2>&1 | grep -E '(Error|Output written)' && \
pdflatex -interaction=nonstopmode -jobname=dcmotor dcmotor.tex 2>&1 | grep -E '(Error|Output written)' && \
rm -f *.{aux,log,out,bbl,blg} && \
mv dcmotor.pdf ../_static/
File diff suppressed because it is too large Load Diff
+82
View File
@@ -0,0 +1,82 @@
@article{dewit95,
author = {Canudas de Wit, C. and Olsson, H. and {\AA}str{\"o}m, K. J. and Lischinsky, P.},
title = {{A New Model for Control of Systems with Friction}},
journal = {IEEE Transactions on Automatic Control},
volume = {40},
number = {3},
pages = {419--425},
year = {1995},
month = mar,
}
@article{lugre_revisited,
author = {{\AA}str{\"o}m, K. J. and Canudas de Wit, C.},
title = {{Revisiting the LuGre Friction Model}},
journal = {IEEE Control Systems Magazine},
volume = {28},
number = {6},
pages = {101--114},
year = {2008},
month = dec,
}
@techreport{dahl68,
author = {Dahl, P.},
title = {{A Solid Friction Model}},
institution = {The Aerospace Corporation},
address = {El Segundo, CA},
number = {TOR-0158(3107-18)-1},
year = {1968},
}
@book{hughes2019,
author = {Hughes, Austin and Drury, Bill},
title = {{Electric Motors and Drives: Fundamentals, Types and Applications}},
edition = {5th},
publisher = {Newnes},
year = {2019},
}
@book{tedrake2024,
author = {Tedrake, Russ},
title = {{Underactuated Robotics: Algorithms for Walking, Running,
Swimming, Flying, and Manipulation}},
publisher = {MIT},
year = {2024},
note = {Course notes for MIT 6.832, \url{https://underactuated.mit.edu}},
}
@article{isaaclab2025,
author = {Mittal, Mayank and Yu, Calvin and Yu, Qinxi and Liu, Jingzhou
and Rudin, Nikita and Hoeller, David and Yuan, Jia Lin
and Singh, Ritvik and Guo, Yunrong and Mazhar, Hammad
and Mandlekar, Ajay and Babich, Buck and State, Gavriel
and Hutter, Marco and Garg, Animesh},
title = {{Isaac Lab: A Unified and Modular Framework for Robot Learning}},
journal = {arXiv preprint arXiv:2502.11048},
year = {2025},
}
@article{stribeck1902,
author = {Stribeck, R.},
title = {{Die wesentlichen Eigenschaften der Gleit- und Rollenlager}},
journal = {Zeitschrift des Vereines Deutscher Ingenieure},
volume = {46},
pages = {1341--1348, 1432--1438, 1463--1470},
year = {1902},
}
@misc{maxon_formulas,
author = {{Maxon Motor AG}},
title = {{Key Information on Maxon DC Motors and Maxon EC Motors}},
howpublished = {\url{https://www.maxongroup.com}},
year = {2024},
note = {{Maxon} Academy Technical Notes},
}
@misc{simscape_dcmotor,
author = {{MathWorks}},
title = {{DC Motor --- Simscape Electrical Block Reference}},
howpublished = {\url{https://www.mathworks.com/help/sps/ref/dcmotor.html}},
year = {2024},
}
+8 -1
View File
@@ -635,19 +635,22 @@ typedef enum mjtDyn_ { // type of actuator dynamics
mjDYN_INTEGRATOR, // integrator: da/dt = u
mjDYN_FILTER, // linear filter: da/dt = (u-a) / tau
mjDYN_FILTEREXACT, // linear filter: da/dt = (u-a) / tau, with exact integration
mjDYN_MUSCLE, // piece-wise linear filter with two time constants
mjDYN_MUSCLE, // piecewise linear filter with two time constants
mjDYN_DCMOTOR, // DC motor electrical dynamics
mjDYN_USER // user-defined dynamics type
} mjtDyn;
typedef enum mjtGain_ { // type of actuator gain
mjGAIN_FIXED = 0, // fixed gain
mjGAIN_AFFINE, // const + kp*length + kv*velocity
mjGAIN_MUSCLE, // muscle FLV curve computed by mju_muscleGain()
mjGAIN_DCMOTOR, // DC motor gain: K or K/R
mjGAIN_USER // user-defined gain type
} mjtGain;
typedef enum mjtBias_ { // type of actuator bias
mjBIAS_NONE = 0, // no bias
mjBIAS_AFFINE, // const + kp*length + kv*velocity
mjBIAS_MUSCLE, // muscle passive force computed by mju_muscleBias()
mjBIAS_DCMOTOR, // DC motor bias: back-EMF, cogging, LuGre friction
mjBIAS_USER // user-defined bias type
} mjtBias;
typedef enum mjtObj_ { // type of MujoCo object
@@ -3659,6 +3662,10 @@ const char* mjs_setToMuscle(mjsActuator* actuator, double timeconst[2], double t
double range[2], double force, double scale, double lmin,
double lmax, double vmax, double fpmax, double fvmax);
const char* mjs_setToAdhesion(mjsActuator* actuator, double gain);
const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double resistance,
double nominal[3], double saturation[4], double inductance[2],
double cogging[3], double controller[5], double thermal[6],
double lugre[6], int input_mode);
mjsMesh* mjs_addMesh(mjSpec* s, const mjsDefault* def);
mjsHField* mjs_addHField(mjSpec* s);
mjsSkin* mjs_addSkin(mjSpec* s);