Add kv damping attribute to position and intvelocity actuator shortcuts.
PiperOrigin-RevId: 588377097 Change-Id: I8ded2ff982e52ed8673019979e29b706ef65c743
This commit is contained in:
committed by
Copybara-Service
parent
b3ccf67ebf
commit
762371c3e4
+28
-11
@@ -5317,13 +5317,13 @@ This element does not have custom attributes. It only has common attributes, whi
|
||||
|
||||
This element creates a position servo. The underlying :el:`general` attributes are set as follows:
|
||||
|
||||
========= ======= ========= =======
|
||||
========= ======= ========= =========
|
||||
Attribute Setting Attribute Setting
|
||||
========= ======= ========= =======
|
||||
========= ======= ========= =========
|
||||
dyntype none dynprm 1 0 0
|
||||
gaintype fixed gainprm kp 0 0
|
||||
biastype affine biasprm 0 -kp 0
|
||||
========= ======= ========= =======
|
||||
biastype affine biasprm 0 -kp -kv
|
||||
========= ======= ========= =========
|
||||
|
||||
|
||||
This element has one custom attribute in addition to the common attributes:
|
||||
@@ -5377,6 +5377,11 @@ This element has one custom attribute in addition to the common attributes:
|
||||
:at:`kp`: :at-val:`real, "1"`
|
||||
Position feedback gain.
|
||||
|
||||
.. _actuator-position-kv:
|
||||
|
||||
:at:`kv`: :at-val:`real, "0"`
|
||||
Damping applied by the actuator.
|
||||
When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators<geIntegration>`.
|
||||
|
||||
.. _actuator-velocity:
|
||||
|
||||
@@ -5385,7 +5390,9 @@ This element has one custom attribute in addition to the common attributes:
|
||||
|
||||
This element creates a velocity servo. Note that in order create a PD controller, one has to define two actuators: a
|
||||
position servo and a velocity servo. This is because MuJoCo actuators are SISO while a PD controller takes two control
|
||||
inputs (reference position and reference velocity). The underlying :el:`general` attributes are set as follows:
|
||||
inputs (reference position and reference velocity).
|
||||
When using this actuator, it is recommended to use the implicitfast or implicit :ref:`integrators<geIntegration>`.
|
||||
The underlying :el:`general` attributes are set as follows:
|
||||
|
||||
========= ======= ========= =======
|
||||
Attribute Setting Attribute Setting
|
||||
@@ -5456,14 +5463,14 @@ This element creates an integrated-velocity servo. For more information, see the
|
||||
:ref:`Activation clamping <CActRange>` section of the Modeling chapter. The underlying
|
||||
:el:`general` attributes are set as follows:
|
||||
|
||||
========== =========== ========= =======
|
||||
========== =========== ========= =========
|
||||
Attribute Setting Attribute Setting
|
||||
========== =========== ========= =======
|
||||
========== =========== ========= =========
|
||||
dyntype integrator dynprm 1 0 0
|
||||
gaintype fixed gainprm kp 0 0
|
||||
biastype affine biasprm 0 -kp 0
|
||||
biastype affine biasprm 0 -kp -kv
|
||||
actlimited true
|
||||
========== =========== ========= =======
|
||||
========== =========== ========= =========
|
||||
|
||||
This element has one custom attribute in addition to the common attributes:
|
||||
|
||||
@@ -5518,6 +5525,11 @@ This element has one custom attribute in addition to the common attributes:
|
||||
:at:`kp`: :at-val:`real, "1"`
|
||||
Position feedback gain.
|
||||
|
||||
.. _actuator-intvelocity-kv:
|
||||
|
||||
:at:`kv`: :at-val:`real, "0"`
|
||||
Damping applied by the actuator.
|
||||
When using this attribute, it is recommended to use the implicitfast or implicit :ref:`integrators<geIntegration>`.
|
||||
|
||||
.. _actuator-damper:
|
||||
|
||||
@@ -5525,8 +5537,9 @@ This element has one custom attribute in addition to the common attributes:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This element is an active damper which produces a force proportional to both velocity and control: ``F = - kv * velocity
|
||||
* control``, where ``kv`` must be nonnegative. :at:`ctrlrange` is required and must also be nonnegative. The underlying
|
||||
:el:`general` attributes are set as follows:
|
||||
* control``, where ``kv`` must be nonnegative. :at:`ctrlrange` is required and must also be nonnegative.
|
||||
When using this actuator, it is recommended to use the implicitfast or implicit :ref:`integrators<geIntegration>`.
|
||||
The underlying :el:`general` attributes are set as follows:
|
||||
|
||||
=========== ======= ========= =======
|
||||
Attribute Setting Attribute Setting
|
||||
@@ -7680,6 +7693,8 @@ slidersite, cranksite.
|
||||
|
||||
.. _default-position-kp:
|
||||
|
||||
.. _default-position-kv:
|
||||
|
||||
:el-prefix:`default/` |-| **position** (?)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -7736,6 +7751,8 @@ tendon, slidersite, cranksite.
|
||||
|
||||
.. _default-intvelocity-kp:
|
||||
|
||||
.. _default-intvelocity-kv:
|
||||
|
||||
:el-prefix:`default/` |-| **intvelocity** (?)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
+5
-3
@@ -778,7 +778,7 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`jointinparent<actuator-position-jointinparent>` | :ref:`tendon<actuator-position-tendon>` | :ref:`slidersite<actuator-position-slidersite>` | :ref:`cranksite<actuator-position-cranksite>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`site<actuator-position-site>` | :ref:`refsite<actuator-position-refsite>` | :ref:`kp<actuator-position-kp>` | | |
|
||||
| | | | :ref:`site<actuator-position-site>` | :ref:`refsite<actuator-position-refsite>` | :ref:`kp<actuator-position-kp>` | :ref:`kv<actuator-position-kv>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| actuator |br| |_| |L| | | .. table:: |
|
||||
@@ -810,6 +810,8 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`cranksite<actuator-intvelocity-cranksite>` | :ref:`site<actuator-intvelocity-site>` | :ref:`refsite<actuator-intvelocity-refsite>` | :ref:`kp<actuator-intvelocity-kp>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`kv<actuator-intvelocity-kv>` | | | | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| actuator |br| |_| |L| | | .. table:: |
|
||||
| :ref:`damper | \* | :class: mjcf-attributes |
|
||||
@@ -1440,7 +1442,7 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`gear<default-position-gear>` | :ref:`cranklength<default-position-cranklength>` | :ref:`user<default-position-user>` | :ref:`group<default-position-group>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`kp<default-position-kp>` | | | | |
|
||||
| | | | :ref:`kp<default-position-kp>` | :ref:`kv<default-position-kv>` | | | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| default |br| |_| |L| | | .. table:: |
|
||||
@@ -1462,7 +1464,7 @@
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`actrange<default-intvelocity-actrange>` | :ref:`gear<default-intvelocity-gear>` | :ref:`cranklength<default-intvelocity-cranklength>` | :ref:`user<default-intvelocity-user>` | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
| | | | :ref:`group<default-intvelocity-group>` | :ref:`kp<default-intvelocity-kp>` | | | |
|
||||
| | | | :ref:`group<default-intvelocity-group>` | :ref:`kp<default-intvelocity-kp>` | :ref:`kv<default-intvelocity-kv>` | | |
|
||||
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
|
||||
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| |_| default |br| |_| |L| | | .. table:: |
|
||||
|
||||
@@ -12,6 +12,10 @@ General
|
||||
robust for very small or large geom sizes.
|
||||
- Added :ref:`frame<frame>` to MJCF, a :ref:`meta-element<meta-element>` which defines a pure coordinate transformation
|
||||
on its direct children, without requiring a :ref:`body<body>`.
|
||||
- Added the :at:`kv` attribute to the :ref:`position<actuator-position>` and :ref:`intvelocity<actuator-intvelocity>`
|
||||
actuators, for specifying actuator-applied damping. This can be used to implement a PD controller with 0 reference
|
||||
velocity. When using this attribute, it is recommended to use the implicitfast or implicit
|
||||
:ref:`integrators<geIntegration>`.
|
||||
|
||||
Plugins
|
||||
^^^^^^^
|
||||
|
||||
@@ -3876,7 +3876,7 @@ void mjCActuator::Compile(void) {
|
||||
throw mjCError(this, "invalid control range for actuator '%s' (id = %d)", name.c_str(), id);
|
||||
}
|
||||
if (actrange[0]>=actrange[1] && actlimited) {
|
||||
throw mjCError(this, "invalid activation range for actuator '%s' (id = %d)", name.c_str(), id);
|
||||
throw mjCError(this, "invalid actrange for actuator '%s' (id = %d)", name.c_str(), id);
|
||||
}
|
||||
if (actlimited && dyntype == mjDYN_NONE) {
|
||||
throw mjCError(this, "actrange specified but dyntype is 'none' in actuator '%s' (id = %d)",
|
||||
|
||||
@@ -166,16 +166,16 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
"dyntype", "gaintype", "biastype", "dynprm", "gainprm", "biasprm", "actearly"},
|
||||
{"motor", "?", "8", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group"},
|
||||
{"position", "?", "9", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
{"position", "?", "10", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kp"},
|
||||
"kp", "kv"},
|
||||
{"velocity", "?", "9", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kv"},
|
||||
{"intvelocity", "?", "10", "ctrllimited", "forcelimited",
|
||||
{"intvelocity", "?", "11", "ctrllimited", "forcelimited",
|
||||
"ctrlrange", "forcerange", "actrange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kp"},
|
||||
"kp", "kv"},
|
||||
{"damper", "?", "8", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kv"},
|
||||
@@ -379,22 +379,22 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite"},
|
||||
{"position", "*", "19", "name", "class", "group",
|
||||
{"position", "*", "20", "name", "class", "group",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kp"},
|
||||
"kp", "kv"},
|
||||
{"velocity", "*", "19", "name", "class", "group",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kv"},
|
||||
{"intvelocity", "*", "20", "name", "class", "group",
|
||||
{"intvelocity", "*", "21", "name", "class", "group",
|
||||
"ctrllimited", "forcelimited",
|
||||
"ctrlrange", "forcerange", "actrange", "lengthrange",
|
||||
"gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site", "refsite",
|
||||
"kp"},
|
||||
"kp", "kv"},
|
||||
{"damper", "*", "18", "name", "class", "group",
|
||||
"forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
@@ -1895,19 +1895,26 @@ void mjXReader::OneActuator(XMLElement* elem, mjCActuator* pact) {
|
||||
pact->biastype = mjBIAS_NONE;
|
||||
}
|
||||
|
||||
// position servo
|
||||
else if (type=="position") {
|
||||
// clear bias
|
||||
mjuu_zerovec(pact->biasprm, mjNBIAS);
|
||||
|
||||
// position or integrated velocity servo
|
||||
else if (type=="position" || type=="intvelocity") {
|
||||
// explicit attributes
|
||||
ReadAttr(elem, "kp", 1, pact->gainprm, text);
|
||||
pact->biasprm[1] = -pact->gainprm[0];
|
||||
|
||||
if (ReadAttr(elem, "kv", 1, pact->biasprm + 2, text)) {
|
||||
if (pact->biasprm[2] < 0)
|
||||
throw mjXError(elem, "kv cannot be negative");
|
||||
pact->biasprm[2] *= -1;
|
||||
}
|
||||
|
||||
// implied parameters
|
||||
pact->dyntype = mjDYN_NONE;
|
||||
pact->gaintype = mjGAIN_FIXED;
|
||||
pact->biastype = mjBIAS_AFFINE;
|
||||
|
||||
if (type=="intvelocity") {
|
||||
pact->dyntype = mjDYN_INTEGRATOR;
|
||||
pact->actlimited = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// velocity servo
|
||||
@@ -1925,22 +1932,6 @@ void mjXReader::OneActuator(XMLElement* elem, mjCActuator* pact) {
|
||||
pact->biastype = mjBIAS_AFFINE;
|
||||
}
|
||||
|
||||
// integrated velocity
|
||||
else if (type=="intvelocity") {
|
||||
// clear bias
|
||||
mjuu_zerovec(pact->biasprm, mjNBIAS);
|
||||
|
||||
// explicit attributes
|
||||
ReadAttr(elem, "kp", 1, pact->gainprm, text);
|
||||
|
||||
// implied parameters
|
||||
pact->dyntype = mjDYN_INTEGRATOR;
|
||||
pact->gaintype = mjGAIN_FIXED;
|
||||
pact->biastype = mjBIAS_AFFINE;
|
||||
pact->actlimited = 1;
|
||||
pact->biasprm[1] = -pact->gainprm[0];
|
||||
}
|
||||
|
||||
// damper
|
||||
else if (type=="damper") {
|
||||
// clear gain
|
||||
|
||||
+8
-8
@@ -13,7 +13,7 @@
|
||||
|
||||
<default>
|
||||
<default class="translation">
|
||||
<general gainprm="100" biasprm="0 -100 -10" biastype="affine" ctrlrange="-.25 .25"/>
|
||||
<position kp="100" kv="10" ctrlrange="-.25 .25"/>
|
||||
</default>
|
||||
<default class="rotation">
|
||||
<!--
|
||||
@@ -22,7 +22,7 @@
|
||||
Increase this range to pi or bigger in order to see the instabillity.
|
||||
See here for more details https://mujoco.readthedocs.io/en/latest/XMLreference.html#actuator
|
||||
-->
|
||||
<general gainprm=".5" biasprm="0 -.5 -.05" biastype="affine" ctrlrange="-1.571 1.571"/>
|
||||
<position kp=".5" kv=".05" ctrlrange="-1.571 1.571"/>
|
||||
</default>
|
||||
<!--
|
||||
Clamping the total actuator torque at the joints means that the motion produced by the Cartesian
|
||||
@@ -62,11 +62,11 @@
|
||||
</worldbody>
|
||||
|
||||
<actuator>
|
||||
<general name="x" site="end_effector" refsite="reference" gear="1 0 0 0 0 0" class="translation"/>
|
||||
<general name="y" site="end_effector" refsite="reference" gear="0 1 0 0 0 0" class="translation"/>
|
||||
<general name="z" site="end_effector" refsite="reference" gear="0 0 1 0 0 0" class="translation"/>
|
||||
<general name="rx" site="end_effector" refsite="reference" gear="0 0 0 1 0 0" class="rotation"/>
|
||||
<general name="ry" site="end_effector" refsite="reference" gear="0 0 0 0 1 0" class="rotation"/>
|
||||
<general name="rz" site="end_effector" refsite="reference" gear="0 0 0 0 0 1" class="rotation"/>
|
||||
<position name="x" site="end_effector" refsite="reference" gear="1 0 0 0 0 0" class="translation"/>
|
||||
<position name="y" site="end_effector" refsite="reference" gear="0 1 0 0 0 0" class="translation"/>
|
||||
<position name="z" site="end_effector" refsite="reference" gear="0 0 1 0 0 0" class="translation"/>
|
||||
<position name="rx" site="end_effector" refsite="reference" gear="0 0 0 1 0 0" class="rotation"/>
|
||||
<position name="ry" site="end_effector" refsite="reference" gear="0 0 0 0 1 0" class="rotation"/>
|
||||
<position name="rz" site="end_effector" refsite="reference" gear="0 0 0 0 0 1" class="rotation"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
|
||||
@@ -940,7 +940,7 @@ TEST_F(ActRangeTest, ActRangeBad) {
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid activation range"));
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid actrange"));
|
||||
}
|
||||
|
||||
TEST_F(ActRangeTest, ActRangeUndefined) {
|
||||
@@ -960,7 +960,7 @@ TEST_F(ActRangeTest, ActRangeUndefined) {
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid activation range"));
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid actrange"));
|
||||
}
|
||||
|
||||
TEST_F(ActRangeTest, ActRangeNoDyntype) {
|
||||
|
||||
@@ -531,92 +531,6 @@ TEST_F(XMLReaderTest, ReadShellParameter) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, ReadsDamper) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<compiler autolimits="true"/>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" ctrlrange="0 1"/>
|
||||
<general joint="jnt" ctrllimited="true" ctrlrange="0 1" gaintype="affine" biastype="none"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull());
|
||||
EXPECT_THAT(model->actuator_gaintype[0], Eq(mjGAIN_AFFINE));
|
||||
EXPECT_THAT(model->actuator_gaintype[1], Eq(mjGAIN_AFFINE));
|
||||
EXPECT_THAT(model->actuator_biastype[0], Eq(mjBIAS_NONE));
|
||||
EXPECT_THAT(model->actuator_biastype[1], Eq(mjBIAS_NONE));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, RequiresPoisitiveDamping) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="-1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(),
|
||||
HasSubstr("damping coefficient cannot be negative"));
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, RequiresControlRange) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10" limited="true"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid control range"));
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, PositiveControlRange) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="1" ctrlrange="-1 0"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("control range cannot be negative"));
|
||||
}
|
||||
|
||||
TEST_F(XMLReaderTest, ReadsSkinGroups) {
|
||||
static constexpr char xml[] = R"(
|
||||
@@ -779,6 +693,186 @@ TEST_F(ActuatorTest, ReadsByte) {
|
||||
|
||||
using ActuatorParseTest = MujocoTest;
|
||||
|
||||
TEST_F(ActuatorParseTest, ReadsDamper) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" ctrlrange="0 1"/>
|
||||
<general joint="jnt" ctrllimited="true" ctrlrange="0 1" gaintype="affine" biastype="none"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull());
|
||||
EXPECT_THAT(model->actuator_gaintype[0], Eq(mjGAIN_AFFINE));
|
||||
EXPECT_THAT(model->actuator_gaintype[1], Eq(mjGAIN_AFFINE));
|
||||
EXPECT_THAT(model->actuator_biastype[0], Eq(mjBIAS_NONE));
|
||||
EXPECT_THAT(model->actuator_biastype[1], Eq(mjBIAS_NONE));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, DamperRequiresPositiveDamping) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="-1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(),
|
||||
HasSubstr("damping coefficient cannot be negative"));
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, DamperRequiresControlRange) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10" limited="true"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid control range"));
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, DamperPositiveControlRange) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0" range="-10 10"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<damper joint="jnt" kv="1" ctrlrange="-1 0"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("control range cannot be negative"));
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, ReadsPositionIntvelKv) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<position joint="jnt" kv="2"/>
|
||||
<intvelocity joint="jnt" actrange="-1 1" kv="3"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull());
|
||||
EXPECT_THAT(model->actuator_biasprm[0*mjNBIAS + 2], Eq(-2.0));
|
||||
EXPECT_THAT(model->actuator_biasprm[1*mjNBIAS + 2], Eq(-3.0));
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, RequirePositiveKv) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<position joint="jnt" kv="-2"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("kv cannot be negative"));
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, PositionIntvelocityVelocityDefaultsPropagate) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<default>
|
||||
<default class="position">
|
||||
<position kp="3" kv="4"/>
|
||||
</default>
|
||||
<default class="intvelocity">
|
||||
<intvelocity kp="5" kv="6" actrange="-1 1"/>
|
||||
</default>
|
||||
<default class="velocity">
|
||||
<velocity kv="7"/>
|
||||
</default>
|
||||
</default>
|
||||
<worldbody>
|
||||
<body>
|
||||
<geom size="1"/>
|
||||
<joint name="jnt" type="slide" axis="1 0 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<position joint="jnt" class="position"/>
|
||||
<intvelocity joint="jnt" class="intvelocity"/>
|
||||
<velocity joint="jnt" class="velocity"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
EXPECT_EQ(model->actuator_gainprm[0*mjNGAIN + 0], 3.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[0*mjNBIAS + 1], -3.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[0*mjNBIAS + 2], -4.0);
|
||||
EXPECT_EQ(model->actuator_gainprm[1*mjNGAIN + 0], 5.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[1*mjNBIAS + 1], -5.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[1*mjNBIAS + 2], -6.0);
|
||||
EXPECT_EQ(model->actuator_gainprm[2*mjNGAIN + 0], 7.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[2*mjNBIAS + 1], 0.0);
|
||||
EXPECT_EQ(model->actuator_biasprm[2*mjNBIAS + 2], -7.0);
|
||||
for (int i = 0; i < model->nu; i++) {
|
||||
for (int j = 3; j < mjNBIAS; j++) {
|
||||
EXPECT_EQ(model->actuator_biasprm[i*mjNBIAS + j], 0.0);
|
||||
}
|
||||
for (int j = 3; j < mjNGAIN; j++) {
|
||||
EXPECT_EQ(model->actuator_gainprm[i*mjNGAIN + j], 0.0);
|
||||
}
|
||||
}
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ActuatorParseTest, IntvelocityCheckEquivalence) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
@@ -871,7 +965,7 @@ TEST_F(ActuatorParseTest, IntvelocityNoActrangeThrowsError) {
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid activation range for actuator"));
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid actrange for actuator"));
|
||||
}
|
||||
|
||||
TEST_F(ActuatorParseTest, IntvelocityDefaultsPropagate) {
|
||||
|
||||
Reference in New Issue
Block a user