Add <damper> actuator shortcut and related mjGAIN_AFFINE.
**Rationale** A general `mjGAIN_AFFINE` actuator adds the term `force = (c + kp * length + kv * velocity) * ctrl`. The damper shortcut restricts it to `kv * velocity * ctrl` and sets the `ctrllimited` attribute to true. **API** ```xml <actuator> <damper ctrlrange="0 1" kv="1"/> </actuator> ``` * Required attributes: `ctrlrange` (>=0) * Optional attributes: `kv` (>=0) PiperOrigin-RevId: 455366866 Change-Id: I88773abbeccabb6442f215c9fc05e205df63f692
This commit is contained in:
committed by
Copybara-Service
parent
e0b6ba4a13
commit
307cf692e5
@@ -71,13 +71,16 @@ static const char* const kTumblingThinObjectPath =
|
||||
"engine/testdata/derivative/tumbling_thin_object.xml";
|
||||
static const char* const kDampedActuatorsPath =
|
||||
"engine/testdata/derivative/damped_actuators.xml";
|
||||
static const char* const kDamperActuatorsPath =
|
||||
"engine/testdata/damper.xml";
|
||||
|
||||
// compare analytic and finite-difference d_smooth/d_qvel
|
||||
TEST_F(DerivativeTest, SmoothDvel) {
|
||||
// run test on all models
|
||||
for (const char* local_path : {kEnergyConservingPendulumPath,
|
||||
kTumblingThinObjectPath,
|
||||
kDampedActuatorsPath}) {
|
||||
kDampedActuatorsPath,
|
||||
kDamperActuatorsPath}) {
|
||||
const std::string xml_path = GetTestDataFilePath(local_path);
|
||||
mjModel* model = mj_loadXML(xml_path.c_str(), nullptr, nullptr, 0);
|
||||
mjData* data = mj_makeData(model);
|
||||
@@ -88,6 +91,9 @@ TEST_F(DerivativeTest, SmoothDvel) {
|
||||
|
||||
// take 100 steps so we have some velocities, then call forward
|
||||
mj_resetData(model, data);
|
||||
if (model->nu) {
|
||||
data->ctrl[0]=0.1;
|
||||
}
|
||||
for (int i=0; i<100; i++) {
|
||||
mj_step(model, data);
|
||||
}
|
||||
|
||||
@@ -89,6 +89,43 @@ TEST_F(ForwardTest, ActLimited) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
// --------------------------- damping actuator --------------------------------
|
||||
|
||||
TEST_F(ForwardTest, DamperDampens) {
|
||||
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>
|
||||
<motor joint="jnt"/>
|
||||
<damper joint="jnt" kv="1000" ctrlrange="0 100"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
)";
|
||||
mjModel* model = LoadModelFromString(xml);
|
||||
mjData* data = mj_makeData(model);
|
||||
|
||||
// move the joint
|
||||
data->ctrl[0] = 100.0;
|
||||
data->ctrl[1] = 0.0;
|
||||
for (int i=0; i<100; i++)
|
||||
mj_step(model, data);
|
||||
|
||||
// stop the joint with damping
|
||||
data->ctrl[0] = 0.0;
|
||||
data->ctrl[1] = 100.0;
|
||||
for (int i=0; i<1000; i++)
|
||||
mj_step(model, data);
|
||||
|
||||
EXPECT_LE(data->qvel[0], std::numeric_limits<double>::epsilon());
|
||||
mj_deleteData(data);
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
// --------------------------- implicit integrator -----------------------------
|
||||
|
||||
using ImplicitIntegratorTest = MujocoTest;
|
||||
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
<mujoco>
|
||||
<worldbody>
|
||||
<geom type="plane" size="1 1 .01"/>
|
||||
<light pos="0 0 2"/>
|
||||
<body pos="0 0 .3">
|
||||
<joint name="hinge" axis="0 1 0"/>
|
||||
<geom type="capsule" size=".01" fromto="0 0 0 .2 0 0"/>
|
||||
<geom size=".03" pos=".2 0 0"/>
|
||||
</body>
|
||||
</worldbody>
|
||||
|
||||
<actuator>
|
||||
<damper name="damper" joint="hinge" kv="10" ctrlrange="0 1"/>
|
||||
</actuator>
|
||||
</mujoco>
|
||||
Reference in New Issue
Block a user