Allow tendon springlength attribute to take two values between which the spring produces no force (a deadband).
If given two non-decreasing values, `springlength` specifies a deadband for spring stiffness, inside of which the force is 0 and outside of which force behaves like a regular spring, with the setpoint corresponding to the nearest value. This can be used to create tendons whose limits are enforced by springs rather than constraints, which are cheaper and easier to analyse. See test/engine/testdata/tendon_springlength.xml example model. Spring-limited spatial tendons whose lower range value is 0 are rendered as catenaries. Fixes #520. PiperOrigin-RevId: 484509706 Change-Id: I6698e94ee36168f52d501e83057559805e05172d
This commit is contained in:
committed by
Copybara-Service
parent
3a445d0fdd
commit
893942a729
@@ -679,7 +679,7 @@ TEST_F(UserDataTest, NSensorTooSmall) {
|
||||
EXPECT_THAT(error.data(), HasSubstr("nuser_sensor"));
|
||||
}
|
||||
|
||||
// ------------- test for auto parsing of *limited fields -------------
|
||||
// ------------- test for auto parsing of *limited fields ----------------------
|
||||
|
||||
using LimitedTest = MujocoTest;
|
||||
|
||||
@@ -791,5 +791,59 @@ TEST_F(LimitedTest, ErrorIfForceLimitedMissingOnActuator) {
|
||||
EXPECT_THAT(error.data(), HasSubstr("actuator"));
|
||||
}
|
||||
|
||||
// ------------- tests for tendon springrange ----------------------------------
|
||||
|
||||
using SpringrangeTest = MujocoTest;
|
||||
|
||||
TEST_F(SpringrangeTest, DefaultsPropagate) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<default>
|
||||
<tendon springlength=".2 .5"/>
|
||||
</default>
|
||||
|
||||
<worldbody>
|
||||
<site name="0"/>
|
||||
<site name="1" pos="1 0 0"/>
|
||||
</worldbody>
|
||||
|
||||
<tendon>
|
||||
<spatial>
|
||||
<site site="0"/>
|
||||
<site site="1"/>
|
||||
</spatial>
|
||||
</tendon>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, NotNull()) << error.data();
|
||||
EXPECT_EQ(model->tendon_lengthspring[0], .2);
|
||||
EXPECT_EQ(model->tendon_lengthspring[1], .5);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(SpringrangeTest, InvalidRange) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<site name="0"/>
|
||||
<site name="1" pos="1 0 0"/>
|
||||
</worldbody>
|
||||
|
||||
<tendon>
|
||||
<spatial springlength="1 0">
|
||||
<site site="0"/>
|
||||
<site site="1"/>
|
||||
</spatial>
|
||||
</tendon>
|
||||
</mujoco>
|
||||
)";
|
||||
std::array<char, 1024> error;
|
||||
mjModel* model = LoadModelFromString(xml, error.data(), error.size());
|
||||
ASSERT_THAT(model, IsNull());
|
||||
EXPECT_THAT(error.data(), HasSubstr("invalid springlength in tendon"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace mujoco
|
||||
|
||||
Reference in New Issue
Block a user