Allow partial specification of polycoef attribute of equality constraints.

- Usually the user only wants to tweak `polycoef[1]`, after this change `"0 2"` is equivalent to `"0 2 0 0 0"`.
- Also improve documentation of this attribute.
- Tighten margins of documentation display equations.

PiperOrigin-RevId: 639720742
Change-Id: Ibafa0e093cebe1c1c75bf2e47ff3bd2ad7619414
This commit is contained in:
Yuval Tassa
2024-06-03 03:41:58 -07:00
committed by Copybara-Service
parent 14a3ce5ffa
commit 8fa0fea02d
4 changed files with 58 additions and 8 deletions
+9 -5
View File
@@ -4275,11 +4275,15 @@ joint types (slide and hinge) can be used.
.. _equality-joint-polycoef:
:at:`polycoef`: :at-val:`real(5), "0 1 0 0 0"`
Coefficients a0 ... a4 of the quartic polynomial. If the two joint values are y and x, and their reference positions
(corresponding to the joint values in the initial model configuration) are y0 and x0, the constraint is:
y-y0 = a0 + a1*(x-x0) + a2*(x-x0)^2 + a3*(x-x0)^3 + a4*(x-x0)^4.
Omitting the second joint is equivalent to setting x = x0, in which case the constraint is y = y0 + a0.
Coefficients :math:`a_0 \ldots a_4` of the quartic polynomial. If the joint values of :at:`joint1` and :at:`joint2`
are respectively :math:`y` and :math:`x`, and their reference positions (corresponding to the joint values in the
initial model configuration) are :math:`y_0` and :math:`x_0`, the constraint is:
.. math::
y-y_0 = a_0 + a_1(x-x_0) + a_2(x-x_0)^2 + a_3(x-x_0)^3 + a_4(x-x_0)^4
Omitting :at:`joint2` is equivalent to setting :math:`x = x_0`, in which case the constraint is
:math:`y = y_0 + a_0`.
.. _equality-tendon:
@@ -4315,7 +4319,7 @@ This element constrains the length of one tendon to be a quartic polynomial of a
.. _equality-tendon-polycoef:
:at:`polycoef`: :at-val:`real(5), "0 1 0 0 0"`
Same as in the equality/ :ref:`joint <equality-joint>` element above, but applied to tendon lengths instead of joint
Same as in the :ref:`equality/joint <equality-joint>` element above, but applied to tendon lengths instead of joint
positions.
+6
View File
@@ -260,6 +260,12 @@ dt .at {
margin-left: 0.5em;
}
/* Reduce top and bottom margins around displayed KaTeX equations */
.katex-display {
margin-top: 0.3em;
margin-bottom: 0.3em;
}
details summary {
font-weight: 600;
}
+2 -2
View File
@@ -1884,13 +1884,13 @@ void mjXReader::OneEquality(XMLElement* elem, mjsEquality* pequality) {
case mjEQ_JOINT:
ReadAttrTxt(elem, "joint1", name1, true);
ReadAttrTxt(elem, "joint2", name2);
ReadAttr(elem, "polycoef", 5, pequality->data, text);
ReadAttr(elem, "polycoef", 5, pequality->data, text, false, false);
break;
case mjEQ_TENDON:
ReadAttrTxt(elem, "tendon1", name1, true);
ReadAttrTxt(elem, "tendon2", name2);
ReadAttr(elem, "polycoef", 5, pequality->data, text);
ReadAttr(elem, "polycoef", 5, pequality->data, text, false, false);
break;
case mjEQ_FLEX:
+41 -1
View File
@@ -34,8 +34,13 @@
namespace mujoco {
namespace {
std::vector<mjtNum> AsVector(const mjtNum* array, int n) {
return std::vector<mjtNum>(array, array + n);
}
using ::std::string;
using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::Eq;
using ::testing::FloatEq;
using ::testing::HasSubstr;
@@ -834,8 +839,43 @@ TEST_F(XMLReaderTest, IncludeAbsoluteTest) {
mj_deleteModel(model);
}
// ------------------------ test frame parsing ---------------------------------
TEST_F(XMLReaderTest, ParsePolycoef) {
static constexpr char xml[] = R"(
<mujoco>
<worldbody>
<body>
<joint name="0"/>
<geom size="1"/>
</body>
<body>
<joint name="1"/>
<geom size="1"/>
</body>
</worldbody>
<equality>
<joint joint1="0" joint2="1"/>
<joint joint1="0" joint2="1" polycoef="2"/>
<joint joint1="0" joint2="1" polycoef="3 4"/>
<joint joint1="0" joint2="1" polycoef="5 6 7 8 9"/>
</equality>
</mujoco>
)";
std::array<char, 1024> error;
mjModel* m = LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(m, NotNull()) << error.data();
EXPECT_THAT(AsVector(m->eq_data + 0*mjNEQDATA, 5),
ElementsAre(0, 1, 0, 0, 0));
EXPECT_THAT(AsVector(m->eq_data + 1*mjNEQDATA, 5),
ElementsAre(2, 1, 0, 0, 0));
EXPECT_THAT(AsVector(m->eq_data + 2*mjNEQDATA, 5),
ElementsAre(3, 4, 0, 0, 0));
EXPECT_THAT(AsVector(m->eq_data + 3*mjNEQDATA, 5),
ElementsAre(5, 6, 7, 8, 9));
mj_deleteModel(m);
}
// ------------------------ test frame parsing ---------------------------------
TEST_F(XMLReaderTest, ParseFrame) {
static constexpr char xml[] = R"(
<mujoco>