Add intvelocity actuator shortcut.
PiperOrigin-RevId: 454899823 Change-Id: I9b5494baacfab5a7d03bd680d0ded06a7790e75e
This commit is contained in:
committed by
Copybara-Service
parent
0e1918782a
commit
6048a55daf
@@ -399,6 +399,19 @@ if present, the parser ignores it. The symbols in the second column of the table
|
||||
| | | | :at:`user` | :at:`group` | :at:`kv` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
+--------------------------+----+------------------------------------------------------------------------------------+
|
||||
| |_2|:el:`intvelocity` | ? | .. table:: |
|
||||
| | | :class: mjcf-attributes |
|
||||
| | | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`ctrlrange` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`forcerange` | :at:`gear` | :at:`cranklength` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`user` | :at:`group` | :at:`kp` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`actrange` | | | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
+--------------------------+----+------------------------------------------------------------------------------------+
|
||||
| |_2|:el:`cylinder` | ? | .. table:: |
|
||||
| | | :class: mjcf-attributes |
|
||||
| | | |
|
||||
@@ -959,6 +972,25 @@ if present, the parser ignores it. The symbols in the second column of the table
|
||||
| | | | :at:`cranksite` | :at:`site` | :at:`kv` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
+--------------------------+----+------------------------------------------------------------------------------------+
|
||||
| |_2|:el:`intvelocity` | \* | .. table:: |
|
||||
| | | :class: mjcf-attributes |
|
||||
| | | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`name` | :at:`class` | :at:`group` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`ctrllimited` | :at:`forcelimited` | :at:`ctrlrange` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`forcerange` | :at:`lengthrange` | :at:`actrange` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`gear` | :at:`cranklength` | :at:`user` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`joint` | :at:`jointinparent` | :at:`tendon` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`slidersite` | :at:`cranksite` | :at:`site` | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
| | | | :at:`kp` | | | |
|
||||
| | | +-------------------------+-------------------------+-------------------------+ |
|
||||
+--------------------------+----+------------------------------------------------------------------------------------+
|
||||
| |_2|:el:`cylinder` | \* | .. table:: |
|
||||
| | | :class: mjcf-attributes |
|
||||
| | | |
|
||||
@@ -2288,6 +2320,14 @@ slidersite, cranksite.
|
||||
All :ref:`velocity <velocity>` attributes are available here except: name, class, joint, jointinparent, site, tendon,
|
||||
slidersite, cranksite.
|
||||
|
||||
.. _default-intvelocity:
|
||||
|
||||
:el-prefix:`default/` **intvelocity** (?)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
All :ref:`intvelocity <intvelocity>` attributes are available here except: name, class, joint, jointinparent, site, tendon,
|
||||
slidersite, cranksite.
|
||||
|
||||
.. _default-cylinder:
|
||||
|
||||
:el-prefix:`default/` **cylinder** (?)
|
||||
@@ -4374,6 +4414,35 @@ This element has one custom attribute in addition to the common attributes:
|
||||
:at:`kv`: :at-val:`real, "1"`
|
||||
Velocity feedback gain.
|
||||
|
||||
.. _intvelocity:
|
||||
|
||||
:el-prefix:`actuator/` **intvelocity** (*)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
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
|
||||
========= =========== ========= =======
|
||||
|
||||
This element has one custom attribute in addition to the common attributes:
|
||||
|
||||
.. |actuator/intvelocity attrib list| replace::
|
||||
:at:`name`, :at:`class`, :at:`group`, :at:`ctrllimited`, :at:`forcelimited`, :at:`ctrlrange`, :at:`forcerange`,
|
||||
:at:`lengthrange`, :at:`gear`, :at:`cranklength`, :at:`joint`, :at:`jointinparent`, :at:`tendon`, :at:`cranksite`,
|
||||
:at:`slidersite`, :at:`site`, :at:`user`
|
||||
|
||||
|actuator/intvelocity attrib list|
|
||||
Same as in actuator/ :ref:`general <general>`.
|
||||
:at:`kp`: :at-val:`real, "1"`
|
||||
Position feedback gain.
|
||||
|
||||
.. _cylinder:
|
||||
|
||||
:el-prefix:`actuator/` **cylinder** (*)
|
||||
|
||||
+18
-14
@@ -548,14 +548,15 @@ As explained in the :ref:`Actuation model <geActuation>` section of the Computat
|
||||
actuator model with transmission, activation dynamics and force generation components that can be specified
|
||||
independently. The full functionality can be accessed via the XML element :ref:`general <general>` which allows the user
|
||||
to create a variety of custom actuators. In addition, MJCF provides shortcuts for configuring common actuators. This is
|
||||
done via the XML elements :ref:`motor <motor>`, :ref:`position <position>`, :ref:`velocity <velocity>`, :ref:`cylinder
|
||||
<cylinder>`, :ref:`muscle <muscle>`. These are *not* separate model elements. Internally MuJoCo supports only one
|
||||
actuator type - which is why when an MJCF model is saved all actuators are written as :el:`general`. Shortcuts create
|
||||
general actuators implicitly, set their attributes to suitable values, and expose a subset of attributes with possibly
|
||||
different names. For example, :el:`position` creates a position servo with attribute :at:`kp` which is the servo gain.
|
||||
However :el:`general` does not have an attribute :at:`kp`. Instead the parser adjusts the gain and bias parameters of
|
||||
the general actuator in a coordinated way so as to mimic a position servo. The same effect could have been achieved by
|
||||
using :el:`general` directly, and setting its attributes to certain values as described below.
|
||||
done via the XML elements :ref:`motor <motor>`, :ref:`position <position>`, :ref:`velocity <velocity>`,
|
||||
:ref:`intvelocity <intvelocity>`, :ref:`cylinder<cylinder>`, and :ref:`muscle <muscle>`. These are *not* separate model
|
||||
elements. Internally MuJoCo supports only one actuator type - which is why when an MJCF model is saved all actuators are
|
||||
written as :el:`general`. Shortcuts create general actuators implicitly, set their attributes to suitable values, and
|
||||
expose a subset of attributes with possibly different names. For example, :el:`position` creates a position servo with
|
||||
attribute :at:`kp` which is the servo gain. However :el:`general` does not have an attribute :at:`kp`. Instead the parser
|
||||
adjusts the gain and bias parameters of the general actuator in a coordinated way so as to mimic a position servo. The
|
||||
same effect could have been achieved by using :el:`general` directly, and setting its attributes to certain values as
|
||||
described below.
|
||||
|
||||
Actuator shortcuts also interact with defaults. Recall that the :ref:`default setting <CDefault>` mechanism involves
|
||||
classes, each of which has a complete collection of dummy elements (one of each element type) used to initialize the
|
||||
@@ -585,7 +586,8 @@ feedback on transmission target's velocity, *integrated-velocity* actuators coup
|
||||
feedback* actuator. In this case the semantics of the activation state are "the target of the position actuator", and
|
||||
the semantics of the control signal are "the velocity of the target of the position actuator". Note that in real robotic
|
||||
systems this integrated-velocity actuator is the most common implementation of actuators with velocity semantics, rather
|
||||
than pure feedback on velocity which is often quite unstable (both in real life and in simulation).
|
||||
than pure feedback on velocity which is often quite unstable (both in real life and in simulation). This actuator type
|
||||
is implemented by the :ref:`intvelocity<intvelocity>` shortcut.
|
||||
|
||||
In the case of integrated-velocity actuators, it is often desirable to *clamp* the activation state, since otherwise the
|
||||
position target would keep integrating beyond the joint limits, leading to loss of controllabillity. To see the effect
|
||||
@@ -597,23 +599,25 @@ of activation clamping, load the example model below:
|
||||
<default>
|
||||
<joint axis="0 0 1" limited="true" range="-90 90" damping="0.3"/>
|
||||
<geom size=".1 .1 .1" type="box"/>
|
||||
<general gainprm="1" biastype="affine" biasprm="0 -1" dyntype="integrator"/>
|
||||
</default>
|
||||
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint name="joint 1"/>
|
||||
<joint name="joint1"/>
|
||||
<geom/>
|
||||
</body>
|
||||
<body pos=".3 0 0">
|
||||
<joint name="joint 2"/>
|
||||
<joint name="joint2"/>
|
||||
<geom/>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
<actuator>
|
||||
<general name="unclamped" joint="joint 1"/>
|
||||
<general name="clamped" actlimited="true" actrange="-1.57 1.57"/>
|
||||
<general name="unclamped" joint="joint1"/>
|
||||
<general name="clamped" joint="joint2" actlimited="true" actrange="-1.57 1.57"/>
|
||||
<general name="unclamped" joint="joint1" gainprm="1" biastype="affine"
|
||||
biasprm="0 -1" dyntype="integrator"/>
|
||||
<intvelocity name="clamped" joint="joint2" actrange="-1.57 1.57"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ PYBIND11_MODULE(_functions, pymodule) {
|
||||
DEF_WITH_OMITTED_PY_ARGS(traits::mj_printSchema,
|
||||
"filename", "buffer", "buffer_sz")(
|
||||
pymodule, [](bool flg_html, bool flg_pad) {
|
||||
constexpr int kBufferSize = 27000;
|
||||
constexpr int kBufferSize = 28000;
|
||||
auto buffer = std::unique_ptr<char[]>(new char[kBufferSize]);
|
||||
const int out_length = InterceptMjErrors(::mj_printSchema)(
|
||||
nullptr, buffer.get(), kBufferSize, flg_html, flg_pad);
|
||||
|
||||
@@ -41,7 +41,7 @@ using tinyxml2::XMLElement;
|
||||
|
||||
//---------------------------------- MJCF schema ---------------------------------------------------
|
||||
|
||||
static const int nMJCF = 158;
|
||||
static const int nMJCF = 160;
|
||||
static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
{"mujoco", "!", "1", "model"},
|
||||
{"<"},
|
||||
@@ -130,6 +130,10 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
{"velocity", "?", "9", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kv"},
|
||||
{"intvelocity", "?", "10", "ctrllimited", "forcelimited",
|
||||
"ctrlrange", "forcerange", "actrange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"kp"},
|
||||
{"cylinder", "?", "12", "ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"gear", "cranklength", "user", "group",
|
||||
"timeconst", "area", "diameter", "bias"},
|
||||
@@ -273,6 +277,12 @@ static const char* MJCF[nMJCF][mjXATTRNUM] = {
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site",
|
||||
"kv"},
|
||||
{"intvelocity", "*", "19", "name", "class", "group",
|
||||
"ctrllimited", "forcelimited",
|
||||
"ctrlrange", "forcerange", "actrange", "lengthrange",
|
||||
"gear", "cranklength", "user",
|
||||
"joint", "jointinparent", "tendon", "slidersite", "cranksite", "site",
|
||||
"kp"},
|
||||
{"cylinder", "*", "21", "name", "class", "group",
|
||||
"ctrllimited", "forcelimited", "ctrlrange", "forcerange",
|
||||
"lengthrange", "gear", "cranklength", "user",
|
||||
@@ -1460,6 +1470,26 @@ 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 = true;
|
||||
pact->biasprm[1] = -pact->gainprm[0];
|
||||
// require actrange
|
||||
if (!ReadAttr(elem, "actrange", 2, pact->actrange, text)) {
|
||||
throw mjXError(elem, "actrange is required for an intvelocity actuator", type.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// cylinder
|
||||
else if (type=="cylinder") {
|
||||
// explicit attributes
|
||||
@@ -1761,11 +1791,12 @@ void mjXReader::Default(XMLElement* section, int parentid) {
|
||||
else if (name=="tendon") OneTendon(elem, &def->tendon);
|
||||
|
||||
// read actuator: general, motor, position, velocity, cylinder
|
||||
else if (name=="general" ||
|
||||
name=="motor" ||
|
||||
name=="position" ||
|
||||
name=="velocity" ||
|
||||
name=="cylinder" ||
|
||||
else if (name=="general" ||
|
||||
name=="motor" ||
|
||||
name=="position" ||
|
||||
name=="velocity" ||
|
||||
name=="intvelocity" ||
|
||||
name=="cylinder" ||
|
||||
name=="muscle") {
|
||||
OneActuator(elem, &def->actuator);
|
||||
}
|
||||
|
||||
@@ -338,5 +338,104 @@ TEST_F(ActuatorTest, ReadsByte) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
// ------------- test intvelocity parsing ---------------------------------------
|
||||
|
||||
using IntegratedVelocityTest = MujocoTest;
|
||||
|
||||
TEST_F(IntegratedVelocityTest, CheckEquivalence) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint name="hinge"/>
|
||||
<geom size="1"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<intvelocity joint="hinge" kp="2.5" actrange="-1.57 1.57"/>
|
||||
<general joint="hinge" actlimited="true" actrange="-1.57 1.57" dyntype="integrator"
|
||||
biastype="affine" gainprm="2.5" biasprm="0 -2.5 0"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, testing::NotNull());
|
||||
// same actlimited
|
||||
EXPECT_EQ(model->actuator_actlimited[0], 1);
|
||||
EXPECT_EQ(model->actuator_actlimited[1], 1);
|
||||
// same dyntype
|
||||
EXPECT_EQ(model->actuator_dyntype[0], mjDYN_INTEGRATOR);
|
||||
EXPECT_EQ(model->actuator_dyntype[1], mjDYN_INTEGRATOR);
|
||||
// same biastype
|
||||
EXPECT_EQ(model->actuator_biastype[0], mjBIAS_AFFINE);
|
||||
EXPECT_EQ(model->actuator_biastype[1], mjBIAS_AFFINE);
|
||||
// same gaintype
|
||||
EXPECT_EQ(model->actuator_gaintype[0], mjGAIN_FIXED);
|
||||
EXPECT_EQ(model->actuator_gaintype[1], mjGAIN_FIXED);
|
||||
// same gainprm
|
||||
EXPECT_DOUBLE_EQ(model->actuator_gainprm[0], 2.5);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_gainprm[mjNGAIN], 2.5);
|
||||
// same biasprm
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[0], 0.0);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[1], -2.5);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[2], 0.0);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[mjNBIAS], 0.0);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[mjNBIAS + 1], -2.5);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[mjNBIAS + 2], 0.0);
|
||||
// same actrange
|
||||
EXPECT_DOUBLE_EQ(model->actuator_actrange[0 + 0], -1.57);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_actrange[0 + 1], 1.57);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_actrange[0 + 2], -1.57);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_actrange[0 + 3], 1.57);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(IntegratedVelocityTest, CheckDefaultsIfNotSpecified) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint name="hinge"/>
|
||||
<geom size="1"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<intvelocity joint="hinge" actrange="-1 1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, testing::NotNull());
|
||||
// check that by default kp = 1
|
||||
EXPECT_DOUBLE_EQ(model->actuator_gainprm[0], 1.0);
|
||||
// check that biasprm is (0, -1, 0)
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[0], 0.0);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[1], -1.0);
|
||||
EXPECT_DOUBLE_EQ(model->actuator_biasprm[2], 0.0);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(IntegratedVelocityTest, NoActrangeThrowsError) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<body>
|
||||
<joint name="hinge"/>
|
||||
<geom size="1"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
<actuator>
|
||||
<intvelocity joint="hinge"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("actrange is required for an intvelocity actuator"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
Reference in New Issue
Block a user