Minor improvements to dcmotor

PiperOrigin-RevId: 895907301
Change-Id: Ia50a6d06c1ede9894cc71f375db837d104f0211e
This commit is contained in:
Yuval Tassa
2026-04-07 08:10:42 -07:00
committed by Copybara-Service
parent b61d304126
commit 382474bb9d
8 changed files with 114 additions and 57 deletions
+2
View File
@@ -4667,6 +4667,8 @@ Set actuator to active adhesion; return error if any.
Set actuator to DC motor; return error if any. Set actuator to DC motor; return error if any.
*Nullable:* ``motorconst``, ``nominal``, ``saturation``, ``inductance``, ``cogging``, ``controller``, ``thermal``, ``lugre``
.. _AddAssets: .. _AddAssets:
Assets Assets
+22 -24
View File
@@ -6327,17 +6327,16 @@ This element has a subset of the common attributes and two custom attributes.
:el-prefix:`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 This element creates a DC motor actuator. See the `DC motor technical note <_static/dcmotor.pdf>`__ for complete
model<geActuation>`. Unlike the general model where the components of force generation are independent affine functions mathematical formulations and parameter semantics, but we include a few important notes below. Note that :el:`dcmotor`
mapping from control to force, :el:`dcmotor` relies on highly coupled physical dynamics. See the `DC motor technical does not conform to the affine gain / bias structure of the :ref:`general actuation model<geActuation>`, except for
note <_static/dcmotor.pdf>`__ for complete mathematical formulations and parameter semantics, but we include a few the stateless case.
important notes here:
- Note that while :ref:`resistance<actuator-dcmotor-resistance>`, :ref:`motorconst<actuator-dcmotor-motorconst>` and - :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. :ref:`nominal<actuator-dcmotor-nominal>` are each optional, but some combination of them is required.
See Section 2.1 of the `technical note <_static/dcmotor.pdf>`__. 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 - The control :ref:`input<actuator-dcmotor-input>` semantic is either the voltage applied to the motor terminals (the
position or velocity target for a PID :ref:`controller<actuator-dcmotor-controller>`. default), or a position or velocity target for a :ref:`PID controller<actuator-dcmotor-controller>`.
- Optional features include electrical dynamics (:ref:`inductance<actuator-dcmotor-inductance>`), - 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:`cogging torque<actuator-dcmotor-cogging>`, :ref:`thermal resistance variation<actuator-dcmotor-thermal>`, and
:ref:`LuGre<actuator-dcmotor-lugre>` friction. :ref:`LuGre<actuator-dcmotor-lugre>` friction.
@@ -6408,7 +6407,7 @@ This element has the following custom attributes in addition to the common attri
.. _actuator-dcmotor-resistance: .. _actuator-dcmotor-resistance:
:at:`resistance`: :at-val:`real, optional` :at:`resistance`: :at-val:`real, optional`
Terminal resistance :math:`R` in Ohm. (see `tech note <_static/dcmotor.pdf>`__ for details) Terminal resistance :math:`R` in Ohm. (see `tech note <_static/dcmotor.pdf>`__, Sections 1.1 and 2.1)
.. _actuator-dcmotor-motorconst: .. _actuator-dcmotor-motorconst:
@@ -6416,16 +6415,15 @@ This element has the following custom attributes in addition to the common attri
Motor constants, defined as :at:`motorconst` = ":at-val:`Kt` :at-val:`Ke`" (N·m/A, equivalently V·s/rad). 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 :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 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 is positive, :math:`K` equals that value. If a datasheet specifies the speed constant :math:`K_v` in rad/(V·s), use
the speed constant :math:`K_v` in rad/(V·s), use :math:`K_e = 1/K_v`. (see `tech note <_static/dcmotor.pdf>`__ for :math:`K_e = 1/K_v`. (see `tech note <_static/dcmotor.pdf>`__, Sections 1.1 and 2.1)
details)
.. _actuator-dcmotor-nominal: .. _actuator-dcmotor-nominal:
:at:`nominal`: :at-val:`real(3), optional` :at:`nominal`: :at-val:`real(3), optional`
Nominal operating point, defined as :at:`nominal` = ":at-val:`voltage` :at-val:`stall_torque` 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 = :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) K` · :at-val:`voltage` / :at-val:`stall_torque`. (see `tech note <_static/dcmotor.pdf>`__, Sections 1.1 and 2.1)
.. _actuator-dcmotor-inductance: .. _actuator-dcmotor-inductance:
@@ -6434,7 +6432,7 @@ This element has the following custom attributes in addition to the common attri
alternative specifications: :at-val:`L` is the winding inductance and :at-val:`timeconst` :math:`= L/R` is the 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), 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 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) armature current. (see `tech note <_static/dcmotor.pdf>`__, Sections 1.1.1 and 2.2)
.. _actuator-dcmotor-thermal: .. _actuator-dcmotor-thermal:
@@ -6444,7 +6442,7 @@ This element has the following custom attributes in addition to the common attri
specify the thermal time constant: :at-val:`timeconst` = :at-val:`resistance` :math:`\times` :at-val:`capacitance`. 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 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 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) activation variable for winding temperature. (see `tech note <_static/dcmotor.pdf>`__, Sections 1.3 and 2.3)
.. _actuator-dcmotor-saturation: .. _actuator-dcmotor-saturation:
@@ -6455,7 +6453,7 @@ This element has the following custom attributes in addition to the common attri
given, :at-val:`torque` takes precedence. Sets :at:`forcerange` to [:math:`-\tau_{\max},\, \tau_{\max}`]. 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 :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 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) default) for any sub-value disables the respective limit. (see `tech note <_static/dcmotor.pdf>`__, Section 2)
.. _actuator-dcmotor-cogging: .. _actuator-dcmotor-cogging:
@@ -6463,7 +6461,7 @@ This element has the following custom attributes in addition to the common attri
Cogging torque, defined as :at:`cogging` = ":at-val:`amplitude` :at-val:`poles` :at-val:`phase`" (N·m, integer, rad). 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 + Adds a position-dependent torque :math:`= \textsf{amplitude} \cdot \sin(\textsf{poles} \cdot \theta +
\textsf{phase})`. Disabled when :at-val:`amplitude` = 0 (the default). \textsf{phase})`. Disabled when :at-val:`amplitude` = 0 (the default).
(see `tech note <_static/dcmotor.pdf>`__ for details) (see `tech note <_static/dcmotor.pdf>`__, Sections 1.2 and 2.1)
.. _actuator-dcmotor-lugre: .. _actuator-dcmotor-lugre:
@@ -6473,28 +6471,28 @@ This element has the following custom attributes in addition to the common attri
:at-val:`stiffness` = 0 (the default). Adds one activation variable for bristle deflection. Note that the :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 :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. (specifically the linear term, :at-val:`damping[0]`). If both are specified, their values are summed.
(see `tech note <_static/dcmotor.pdf>`__ for details) (see `tech note <_static/dcmotor.pdf>`__, Sections 1.4 and 2.4)
.. _actuator-dcmotor-input: .. _actuator-dcmotor-input:
:at:`input`: :at-val:`[voltage, position, velocity], "voltage"` :at:`input`: :at-val:`[voltage, position, velocity], "voltage"`
Specifies the input signal semantics. In "voltage" mode, the control directly sets applied motor voltage. In 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 "position" or "velocity" modes, the :ref:`PID controller<actuator-dcmotor-controller>` uses the control as a
reference setpoint relative to the joint trajectory. (see `tech note <_static/dcmotor.pdf>`__ for details) reference setpoint relative to the joint trajectory. (see `tech note <_static/dcmotor.pdf>`__, Section 2.5)
.. _actuator-dcmotor-controller: .. _actuator-dcmotor-controller:
:at:`controller`: :at-val:`real(5), "0 0 0 0 0"` :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` 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 :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 velocity. If the :at:`input` mode is voltage, this attribute 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 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) clamping. (see `tech note <_static/dcmotor.pdf>`__, Section 2.5)
.. _actuator-plugin: .. _actuator-plugin:
:el-prefix:`actuator/` |-| **plugin** |?| :el-prefix:`actuator/` |-| **plugin** |?|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Associate this actuator with an :ref:`engine plugin<exPlugin>`. Either :at:`plugin` or :at:`instance` are required. Associate this actuator with an :ref:`engine plugin<exPlugin>`. Either :at:`plugin` or :at:`instance` are required.
+1
View File
@@ -1727,6 +1727,7 @@ MJAPI const char* mjs_setToMuscle(mjsActuator* actuator, double timeconst[2], do
MJAPI const char* mjs_setToAdhesion(mjsActuator* actuator, double gain); MJAPI const char* mjs_setToAdhesion(mjsActuator* actuator, double gain);
// Set actuator to DC motor; return error if any. // Set actuator to DC motor; return error if any.
// Nullable: motorconst, nominal, saturation, inductance, cogging, controller, thermal, lugre
MJAPI const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double resistance, MJAPI const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double resistance,
double nominal[3], double saturation[4], double inductance[2], double nominal[3], double saturation[4], double inductance[2],
double cogging[3], double controller[5], double thermal[6], double cogging[3], double controller[5], double thermal[6],
+8
View File
@@ -10805,6 +10805,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(2,), extents=(2,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='resistance', name='resistance',
@@ -10816,6 +10817,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(3,), extents=(3,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='saturation', name='saturation',
@@ -10823,6 +10825,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(4,), extents=(4,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='inductance', name='inductance',
@@ -10830,6 +10833,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(2,), extents=(2,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='cogging', name='cogging',
@@ -10837,6 +10841,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(3,), extents=(3,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='controller', name='controller',
@@ -10844,6 +10849,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(5,), extents=(5,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='thermal', name='thermal',
@@ -10851,6 +10857,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(6,), extents=(6,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='lugre', name='lugre',
@@ -10858,6 +10865,7 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([
inner_type=ValueType(name='double'), inner_type=ValueType(name='double'),
extents=(6,), extents=(6,),
), ),
nullable=True,
), ),
FunctionParameterDecl( FunctionParameterDecl(
name='input_mode', name='input_mode',
+25 -25
View File
@@ -1125,18 +1125,18 @@ const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double
double nominal[3], double saturation[4], double inductance[2], double nominal[3], double saturation[4], double inductance[2],
double cogging[3], double controller[5], double thermal[6], double cogging[3], double controller[5], double thermal[6],
double lugre[6], int input_mode) { double lugre[6], int input_mode) {
double Kt = motorconst[0]; // torque constant double R = resistance; // electrical resistance
double Ke = motorconst[1]; // back-EMF constant double Kt = motorconst ? motorconst[0] : 0; // torque constant
double R = resistance; // electrical resistance double Ke = motorconst ? motorconst[1] : 0; // back-EMF constant
double vn = nominal[0]; // nominal voltage double vn = nominal ? nominal[0] : 0; // nominal voltage
double tau0 = nominal[1]; // stall torque double tau0 = nominal ? nominal[1] : 0; // stall torque
double omega0 = nominal[2]; // no-load speed double omega0 = nominal ? nominal[2] : 0; // no-load speed
// derive Ke from nominal: omega0 = vn*Ke / (Ke^2 + R*B) // derive Ke from nominal: omega0 = vn*Ke / (Ke^2 + R*B)
if (vn > 0 && Ke <= 0 && omega0 > 0) { if (vn > 0 && Ke <= 0 && omega0 > 0) {
// viscous damping (linear), add lugre sigma2 contribution if any // viscous damping (linear), add lugre sigma2 contribution if any
double B = actuator->damping[0]; double B = actuator->damping[0];
if (lugre[0] > 0) B += lugre[2]; if (lugre && lugre[0] > 0) B += lugre[2];
if (B > 0 && R > 0) { if (B > 0 && R > 0) {
// R known: solve quadratic Ke^2*omega0 - Ke*vn + R*B*omega0 = 0 // R known: solve quadratic Ke^2*omega0 - Ke*vn + R*B*omega0 = 0
@@ -1176,24 +1176,24 @@ const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double
actuator->gainprm[1] = K; actuator->gainprm[1] = K;
// controller parameters: gainprm[4:6] for kp, ki, kd // controller parameters: gainprm[4:6] for kp, ki, kd
actuator->gainprm[4] = controller[0]; // kp actuator->gainprm[4] = controller ? controller[0] : 0; // kp
actuator->gainprm[5] = controller[1]; // ki actuator->gainprm[5] = controller ? controller[1] : 0; // ki
actuator->gainprm[6] = controller[2]; // kd actuator->gainprm[6] = controller ? controller[2] : 0; // kd
// controller parameters: dynprm[7,8] for slewmax, Imax // controller parameters: dynprm[7,8] for slewmax, Imax
actuator->dynprm[7] = controller[3]; // slewmax actuator->dynprm[7] = controller ? controller[3] : 0; // slewmax
actuator->dynprm[8] = controller[4]; // Imax actuator->dynprm[8] = controller ? controller[4] : 0; // Imax
// saturation: [tau_max, i_max, (di/dt)_max, v_max] // saturation: [tau_max, i_max, (di/dt)_max, v_max]
if (saturation[2] > 0) { if (saturation && saturation[2] > 0) {
actuator->dynprm[1] = saturation[2]; // (di/dt)_max actuator->dynprm[1] = saturation[2]; // (di/dt)_max
} }
if (saturation[3] > 0) { if (saturation && saturation[3] > 0) {
actuator->gainprm[7] = saturation[3]; // v_max actuator->gainprm[7] = saturation[3]; // v_max
} }
// saturation -> forcerange // saturation -> forcerange
if (saturation[0] > 0 || saturation[1] > 0) { if (saturation && (saturation[0] > 0 || saturation[1] > 0)) {
double tau_max = saturation[0]; double tau_max = saturation[0];
if (tau_max == 0 && saturation[1] > 0) { if (tau_max == 0 && saturation[1] > 0) {
tau_max = K * saturation[1]; // tau_max = K * i_max tau_max = K * saturation[1]; // tau_max = K * i_max
@@ -1204,34 +1204,34 @@ const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double
} }
// cogging: [amplitude, periodicity, phase] -> biasprm[0:3] // cogging: [amplitude, periodicity, phase] -> biasprm[0:3]
actuator->biasprm[0] = cogging[0]; // amplitude actuator->biasprm[0] = cogging ? cogging[0] : 0; // amplitude
actuator->biasprm[1] = cogging[1]; // periodicity actuator->biasprm[1] = cogging ? cogging[1] : 0; // periodicity
actuator->biasprm[2] = cogging[2]; // phase actuator->biasprm[2] = cogging ? cogging[2] : 0; // phase
// count activation variables: slot order is slew, integral, temperature, bristle, current // count activation variables: slot order is slew, integral, temperature, bristle, current
int actdim = 0; int actdim = 0;
// inductance: [L, te] // inductance: [L, te]
if (inductance[0] < 0) return "DC motor: inductance must be non-negative"; if (inductance && inductance[0] < 0) return "DC motor: inductance must be non-negative";
if (inductance[1] < 0) return "DC motor: electrical time constant must be non-negative"; if (inductance && inductance[1] < 0) return "DC motor: electrical time constant must be non-negative";
double te = inductance[0] > 0 ? inductance[0] / R : inductance[1]; double te = (inductance && inductance[0] > 0) ? inductance[0] / R : (inductance ? inductance[1] : 0);
actuator->dynprm[0] = te; actuator->dynprm[0] = te;
if (te > 0) { if (te > 0) {
actdim++; actdim++;
} }
// controller states: slew rate limiting // controller states: slew rate limiting
if (controller[3] > 0) { // slewmax if (controller && controller[3] > 0) { // slewmax
actdim++; actdim++;
} }
// controller states: integral // controller states: integral
if (controller[1] > 0) { // ki if (controller && controller[1] > 0) { // ki
actdim++; actdim++;
} }
// thermal -> temperature activation // thermal -> temperature activation
if (thermal[0] > 0 || thermal[1] > 0 || thermal[2] > 0) { if (thermal && (thermal[0] > 0 || thermal[1] > 0 || thermal[2] > 0)) {
double RT = thermal[0]; // thermal resistance double RT = thermal[0]; // thermal resistance
double C = thermal[1]; // thermal capacitance double C = thermal[1]; // thermal capacitance
double tth = thermal[2]; // thermal time constant double tth = thermal[2]; // thermal time constant
@@ -1259,7 +1259,7 @@ const char* mjs_setToDCMotor(mjsActuator* actuator, double motorconst[2], double
} }
// lugre: {stiffness, damping, viscous, coulomb, static, stribeck} // lugre: {stiffness, damping, viscous, coulomb, static, stribeck}
if (lugre[0] > 0) { if (lugre && lugre[0] > 0) {
actuator->dynprm[5] = lugre[0]; // stiffness -> sigma0 actuator->dynprm[5] = lugre[0]; // stiffness -> sigma0
actuator->dynprm[6] = lugre[1]; // damping -> sigma1 actuator->dynprm[6] = lugre[1]; // damping -> sigma1
actuator->damping[0] += lugre[2]; // viscous -> sigma2 actuator->damping[0] += lugre[2]; // viscous -> sigma2
+7
View File
@@ -192,6 +192,13 @@ MJAPI const char* mjs_setToMuscle(mjsActuator* actuator, double timeconst[2], do
// Set actuator to adhesion, return error on failure. // Set actuator to adhesion, return error on failure.
MJAPI const char* mjs_setToAdhesion(mjsActuator* actuator, double gain); MJAPI const char* mjs_setToAdhesion(mjsActuator* actuator, double gain);
// Set actuator to DC motor, return error on failure.
MJAPI 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);
//---------------------------------- Add assets ---------------------------------------------------- //---------------------------------- Add assets ----------------------------------------------------
// Add mesh. // Add mesh.
+41
View File
@@ -239,6 +239,47 @@ TEST_F(MujocoTest, DeletePlugin) {
mj_deleteModel(newmodel); mj_deleteModel(newmodel);
} }
TEST_F(MujocoTest, SetToDCMotorNullable) {
mjSpec* spec = mj_makeSpec();
mjsActuator* actuator = mjs_addActuator(spec, 0);
double motorconst[2] = {0.05, 0.05};
double resistance = 2.0;
const char* err = mjs_setToDCMotor(actuator, motorconst, resistance,
nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, 0);
EXPECT_STREQ(err, "");
EXPECT_EQ(actuator->gainprm[0], 2.0);
EXPECT_EQ(actuator->gainprm[1], 0.05);
EXPECT_EQ(actuator->gainprm[4], 0);
EXPECT_EQ(actuator->gainprm[5], 0);
EXPECT_EQ(actuator->gainprm[6], 0);
EXPECT_EQ(actuator->dynprm[7], 0);
EXPECT_EQ(actuator->dynprm[8], 0);
mj_deleteSpec(spec);
}
TEST_F(MujocoTest, SetToDCMotorDeriveKe) {
mjSpec* spec = mj_makeSpec();
mjsActuator* actuator = mjs_addActuator(spec, 0);
double resistance = 2.0;
double nominal[3] = {12.0, 0, 100.0}; // vn=12, omega0=100
const char* err = mjs_setToDCMotor(actuator, nullptr, resistance,
nominal, nullptr, nullptr,
nullptr, nullptr, nullptr,
nullptr, 0);
EXPECT_STREQ(err, "");
EXPECT_EQ(actuator->gainprm[0], 2.0);
EXPECT_NEAR(actuator->gainprm[1], 0.12, 1e-5);
mj_deleteSpec(spec);
}
static constexpr char xml_plugin_1[] = R"( static constexpr char xml_plugin_1[] = R"(
<mujoco model="MuJoCo Model"> <mujoco model="MuJoCo Model">
<worldbody> <worldbody>
+8 -8
View File
@@ -9877,14 +9877,14 @@ std::string mjs_setToCylinder_wrapper(MjsActuator& actuator, double timeconst, d
} }
std::string mjs_setToDCMotor_wrapper(MjsActuator& actuator, const val& motorconst, double resistance, const val& nominal, const val& saturation, const val& inductance, const val& cogging, const val& controller, const val& thermal, const val& lugre, int input_mode) { std::string mjs_setToDCMotor_wrapper(MjsActuator& actuator, const val& motorconst, double resistance, const val& nominal, const val& saturation, const val& inductance, const val& cogging, const val& controller, const val& thermal, const val& lugre, int input_mode) {
UNPACK_VALUE(double, motorconst); UNPACK_NULLABLE_VALUE(double, motorconst);
UNPACK_VALUE(double, nominal); UNPACK_NULLABLE_VALUE(double, nominal);
UNPACK_VALUE(double, saturation); UNPACK_NULLABLE_VALUE(double, saturation);
UNPACK_VALUE(double, inductance); UNPACK_NULLABLE_VALUE(double, inductance);
UNPACK_VALUE(double, cogging); UNPACK_NULLABLE_VALUE(double, cogging);
UNPACK_VALUE(double, controller); UNPACK_NULLABLE_VALUE(double, controller);
UNPACK_VALUE(double, thermal); UNPACK_NULLABLE_VALUE(double, thermal);
UNPACK_VALUE(double, lugre); UNPACK_NULLABLE_VALUE(double, lugre);
return std::string(mjs_setToDCMotor(actuator.get(), motorconst_.data(), resistance, nominal_.data(), saturation_.data(), inductance_.data(), cogging_.data(), controller_.data(), thermal_.data(), lugre_.data(), input_mode)); return std::string(mjs_setToDCMotor(actuator.get(), motorconst_.data(), resistance, nominal_.data(), saturation_.data(), inductance_.data(), cogging_.data(), controller_.data(), thermal_.data(), lugre_.data(), input_mode));
} }