Add a test for equivalence of different solvers.

PiperOrigin-RevId: 845777469
Change-Id: I76a162b71bea349cca3472001360181654a5d571
This commit is contained in:
Yuval Tassa
2025-12-17 08:20:43 -08:00
committed by Copybara-Service
parent e95f46f84a
commit 47e35e632f
4 changed files with 627 additions and 4 deletions
+116 -4
View File
@@ -33,8 +33,8 @@ using ::std::max;
using SolverTest = MujocoTest;
static const char* const kModelPath =
"testdata/model.xml";
static const char* const kModelPath = "engine/testdata/solver/model.xml";
static const char* const kHumanoidPath = "engine/testdata/solver/humanoid.xml";
// compare accelerations produced by CG solver with and without islands
TEST_F(SolverTest, IslandsEquivalent) {
@@ -121,8 +121,9 @@ TEST_F(SolverTest, IslandsEquivalentForward) {
mjModel* model = mj_loadXML(xml_path.c_str(), nullptr, error, sizeof(error));
ASSERT_THAT(model, NotNull()) << error;
int nv = model->nv;
model->opt.tolerance = 0; // set tolerance to 0
model->opt.ls_tolerance = 0; // set ls_tolerance to 0
// set tolerance to 0 so opt.iterations are always run
model->opt.tolerance = 0;
mjData* data_island = mj_makeData(model);
mjData* data_noisland = mj_makeData(model);
@@ -174,5 +175,116 @@ TEST_F(SolverTest, IslandsEquivalentForward) {
mj_deleteModel(model);
}
TEST_F(SolverTest, SolversEquivalent) {
struct SolverTolerances {
double newton;
double cg;
double pgs_pyramidal;
double pgs_elliptic;
};
// Base relative tolerances are factor of 10 above failure thresholds
// on Linux, clang, x86-64 (i.e., test just passes with tol_multiplier = 1)
// TODO: Get float32 tolerances
const struct {
const char* path;
SolverTolerances tolerances;
} kConfigs[] = {
{.path = kModelPath,
.tolerances =
{
.newton = 1e-15,
.cg = 1e-7,
.pgs_pyramidal = 1e-14,
.pgs_elliptic = 1e-3,
}},
{.path = kHumanoidPath,
.tolerances =
{
.newton = 1e-15,
.cg = 1e-7,
.pgs_pyramidal = 1e-6,
.pgs_elliptic = 1e-9,
}},
};
for (const auto& config : kConfigs) {
const std::string xml_path = GetTestDataFilePath(config.path);
char error[1024];
mjModel* model =
mj_loadXML(xml_path.c_str(), nullptr, error, sizeof(error));
ASSERT_THAT(model, NotNull()) << error;
model->opt.tolerance = 0; // set tolerance to 0
model->opt.iterations = 500; // set iterations to 500
model->opt.disableflags |= mjDSBL_WARMSTART; // disable warmstart
int nv = model->nv;
mjData* data = mj_makeData(model);
mjData* data_truth = mj_makeData(model);
for (mjtCone cone : {mjCONE_PYRAMIDAL, mjCONE_ELLIPTIC}) {
model->opt.cone = cone;
// use Newton Dense as ground truth
model->opt.solver = mjSOL_NEWTON;
model->opt.jacobian = mjJAC_DENSE;
mj_resetDataKeyframe(model, data_truth, 0);
mj_forward(model, data_truth);
mjtNum scale = mju_norm(data_truth->qfrc_constraint, nv);
for (mjtSolver solver : {mjSOL_NEWTON, mjSOL_CG, mjSOL_PGS}) {
double rtol;
switch (solver) {
case mjSOL_NEWTON:
rtol = config.tolerances.newton;
break;
case mjSOL_CG:
rtol = config.tolerances.cg;
break;
case mjSOL_PGS:
rtol = cone == mjCONE_PYRAMIDAL ? config.tolerances.pgs_pyramidal
: config.tolerances.pgs_elliptic;
break;
}
// increase base tolerance to avoid test flakiness
double tol_multiplier = 1e2;
double tolerance = scale * rtol * tol_multiplier;
for (mjtJacobian jacobian : {mjJAC_DENSE, mjJAC_SPARSE}) {
model->opt.solver = solver;
model->opt.jacobian = jacobian;
mj_resetDataKeyframe(model, data, 0);
mj_forward(model, data);
const char* cone_str =
(cone == mjCONE_PYRAMIDAL ? "pyramidal" : "elliptic");
const char* solver_str =
(solver == mjSOL_NEWTON ? "Newton"
: (solver == mjSOL_CG ? "CG" : "PGS"));
const char* jacobian_str =
(jacobian == mjJAC_DENSE ? "dense" : "sparse");
EXPECT_THAT(AsVector(data->qfrc_constraint, nv),
Pointwise(DoubleNear(tolerance),
AsVector(data_truth->qfrc_constraint, nv)))
<< "model: " << config.path << "\n"
<< "cone: " << cone_str << "\n"
<< "solver: " << solver_str << "\n"
<< "jacobian: " << jacobian_str << "\n"
<< "tolerance: " << tolerance;
}
}
}
mj_deleteData(data_truth);
mj_deleteData(data);
mj_deleteModel(model);
}
}
} // namespace
} // namespace mujoco
+217
View File
@@ -0,0 +1,217 @@
<mujoco model="Humanoid">
<option timestep="0.005" cone="elliptic" impratio="3" solver="PGS">
<flag island="disable" warmstart="disable"/>
</option>
<visual>
<map force="0.1" zfar="30"/>
<rgba haze="0.15 0.25 0.35 1"/>
<global offwidth="2560" offheight="1440" elevation="-20" azimuth="120"/>
</visual>
<statistic center="0 0 0.7"/>
<asset>
<texture type="skybox" builtin="gradient" rgb1=".3 .5 .7" rgb2="0 0 0" width="32" height="512"/>
<texture name="body" type="cube" builtin="flat" mark="cross" width="128" height="128" rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" markrgb="1 1 1"/>
<material name="body" texture="body" texuniform="true" rgba="0.8 0.6 .4 1"/>
<texture name="grid" type="2d" builtin="checker" width="512" height="512" rgb1=".1 .2 .3" rgb2=".2 .3 .4"/>
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<motor ctrlrange="-1 1" ctrllimited="true"/>
<default class="body">
<!-- geoms -->
<geom type="capsule" condim="1" friction=".7" solimp=".9 .99 .003" solref=".015 1" material="body" group="1"/>
<default class="thigh">
<geom size=".06"/>
</default>
<default class="shin">
<geom fromto="0 0 0 0 0 -.3" size=".049"/>
</default>
<default class="foot">
<geom size=".027"/>
<default class="foot1">
<geom fromto="-.07 -.01 0 .14 -.03 0"/>
</default>
<default class="foot2">
<geom fromto="-.07 .01 0 .14 .03 0"/>
</default>
</default>
<default class="arm_upper">
<geom size=".04"/>
</default>
<default class="arm_lower">
<geom size=".031"/>
</default>
<default class="hand">
<geom type="sphere" size=".04"/>
</default>
<!-- joints -->
<joint type="hinge" damping=".2" stiffness="1" armature=".01" limited="true" solimplimit="0 .99 .01"/>
<default class="joint_big">
<joint damping="5" stiffness="10"/>
<default class="hip_x">
<joint range="-30 10"/>
</default>
<default class="hip_z">
<joint range="-60 35"/>
</default>
<default class="hip_y">
<joint axis="0 1 0" range="-150 20"/>
</default>
<default class="joint_big_stiff">
<joint stiffness="20"/>
</default>
</default>
<default class="knee">
<joint pos="0 0 .02" axis="0 -1 0" range="-160 2"/>
</default>
<default class="ankle">
<joint range="-50 50"/>
<default class="ankle_y">
<joint pos="0 0 .08" axis="0 1 0" stiffness="6"/>
</default>
<default class="ankle_x">
<joint pos="0 0 .04" stiffness="3"/>
</default>
</default>
<default class="shoulder">
<joint range="-85 60"/>
</default>
<default class="elbow">
<joint range="-100 50" stiffness="0"/>
</default>
</default>
</default>
<worldbody>
<geom name="floor" size="0 0 .05" type="plane" material="grid" condim="3"/>
<light name="spotlight" mode="targetbodycom" target="torso" diffuse=".8 .8 .8" specular="0.3 0.3 0.3" pos="0 -6 4" cutoff="30"/>
<light name="top" pos="0 0 2" mode="trackcom"/>
<body name="torso" pos="0 0 1.282" childclass="body">
<camera name="back" pos="-3 0 1" xyaxes="0 -1 0 1 0 2" mode="trackcom"/>
<camera name="side" pos="0 -3 1" xyaxes="1 0 0 0 1 2" mode="trackcom"/>
<freejoint name="root"/>
<geom name="torso" fromto="0 -.07 0 0 .07 0" size=".07"/>
<geom name="waist_upper" fromto="-.01 -.06 -.12 -.01 .06 -.12" size=".06"/>
<body name="head" pos="0 0 .19">
<geom name="head" type="sphere" size=".09"/>
<camera name="egocentric" pos=".09 0 0" xyaxes="0 -1 0 .1 0 1" fovy="80"/>
</body>
<body name="waist_lower" pos="-.01 0 -.26">
<geom name="waist_lower" fromto="0 -.06 0 0 .06 0" size=".06"/>
<joint name="abdomen_z" pos="0 0 .065" axis="0 0 1" range="-45 45" class="joint_big_stiff"/>
<joint name="abdomen_y" pos="0 0 .065" axis="0 1 0" range="-75 30" class="joint_big"/>
<body name="pelvis" pos="0 0 -.165">
<joint name="abdomen_x" pos="0 0 .1" axis="1 0 0" range="-35 35" class="joint_big"/>
<geom name="butt" fromto="-.02 -.07 0 -.02 .07 0" size=".09"/>
<body name="thigh_right" pos="0 -.1 -.04">
<joint name="hip_x_right" axis="1 0 0" class="hip_x"/>
<joint name="hip_z_right" axis="0 0 1" class="hip_z"/>
<joint name="hip_y_right" class="hip_y"/>
<geom name="thigh_right" fromto="0 0 0 0 .01 -.34" class="thigh"/>
<body name="shin_right" pos="0 .01 -.4">
<joint name="knee_right" class="knee"/>
<geom name="shin_right" class="shin"/>
<body name="foot_right" pos="0 0 -.39">
<joint name="ankle_y_right" class="ankle_y"/>
<joint name="ankle_x_right" class="ankle_x" axis="1 0 .5"/>
<geom name="foot1_right" class="foot1"/>
<geom name="foot2_right" class="foot2"/>
</body>
</body>
</body>
<body name="thigh_left" pos="0 .1 -.04">
<joint name="hip_x_left" axis="-1 0 0" class="hip_x"/>
<joint name="hip_z_left" axis="0 0 -1" class="hip_z"/>
<joint name="hip_y_left" class="hip_y"/>
<geom name="thigh_left" fromto="0 0 0 0 -.01 -.34" class="thigh"/>
<body name="shin_left" pos="0 -.01 -.4">
<joint name="knee_left" class="knee"/>
<geom name="shin_left" fromto="0 0 0 0 0 -.3" class="shin"/>
<body name="foot_left" pos="0 0 -.39">
<joint name="ankle_y_left" class="ankle_y"/>
<joint name="ankle_x_left" class="ankle_x" axis="-1 0 -.5"/>
<geom name="foot1_left" class="foot1"/>
<geom name="foot2_left" class="foot2"/>
</body>
</body>
</body>
</body>
</body>
<body name="upper_arm_right" pos="0 -.17 .06">
<joint name="shoulder1_right" axis="2 1 1" class="shoulder"/>
<joint name="shoulder2_right" axis="0 -1 1" class="shoulder"/>
<geom name="upper_arm_right" fromto="0 0 0 .16 -.16 -.16" class="arm_upper"/>
<body name="lower_arm_right" pos=".18 -.18 -.18">
<joint name="elbow_right" axis="0 -1 1" class="elbow"/>
<geom name="lower_arm_right" fromto=".01 .01 .01 .17 .17 .17" class="arm_lower"/>
<body name="hand_right" pos=".18 .18 .18">
<geom name="hand_right" zaxis="1 1 1" class="hand"/>
</body>
</body>
</body>
<body name="upper_arm_left" pos="0 .17 .06">
<joint name="shoulder1_left" axis="-2 1 -1" class="shoulder"/>
<joint name="shoulder2_left" axis="0 -1 -1" class="shoulder"/>
<geom name="upper_arm_left" fromto="0 0 0 .16 .16 -.16" class="arm_upper"/>
<body name="lower_arm_left" pos=".18 .18 -.18">
<joint name="elbow_left" axis="0 -1 -1" class="elbow"/>
<geom name="lower_arm_left" fromto=".01 -.01 .01 .17 -.17 .17" class="arm_lower"/>
<body name="hand_left" pos=".18 -.18 .18">
<geom name="hand_left" zaxis="1 -1 1" class="hand"/>
</body>
</body>
</body>
</body>
</worldbody>
<contact>
<exclude body1="waist_lower" body2="thigh_right"/>
<exclude body1="waist_lower" body2="thigh_left"/>
</contact>
<tendon>
<fixed name="hamstring_right" limited="true" range="-0.3 2">
<joint joint="hip_y_right" coef=".5"/>
<joint joint="knee_right" coef="-.5"/>
</fixed>
<fixed name="hamstring_left" limited="true" range="-0.3 2">
<joint joint="hip_y_left" coef=".5"/>
<joint joint="knee_left" coef="-.5"/>
</fixed>
</tendon>
<actuator>
<motor name="abdomen_z" gear="40" joint="abdomen_z"/>
<motor name="abdomen_y" gear="40" joint="abdomen_y"/>
<motor name="abdomen_x" gear="40" joint="abdomen_x"/>
<motor name="hip_x_right" gear="40" joint="hip_x_right"/>
<motor name="hip_z_right" gear="40" joint="hip_z_right"/>
<motor name="hip_y_right" gear="120" joint="hip_y_right"/>
<motor name="knee_right" gear="80" joint="knee_right"/>
<motor name="ankle_y_right" gear="20" joint="ankle_y_right"/>
<motor name="ankle_x_right" gear="20" joint="ankle_x_right"/>
<motor name="hip_x_left" gear="40" joint="hip_x_left"/>
<motor name="hip_z_left" gear="40" joint="hip_z_left"/>
<motor name="hip_y_left" gear="120" joint="hip_y_left"/>
<motor name="knee_left" gear="80" joint="knee_left"/>
<motor name="ankle_y_left" gear="20" joint="ankle_y_left"/>
<motor name="ankle_x_left" gear="20" joint="ankle_x_left"/>
<motor name="shoulder1_right" gear="20" joint="shoulder1_right"/>
<motor name="shoulder2_right" gear="20" joint="shoulder2_right"/>
<motor name="elbow_right" gear="40" joint="elbow_right"/>
<motor name="shoulder1_left" gear="20" joint="shoulder1_left"/>
<motor name="shoulder2_left" gear="20" joint="shoulder2_left"/>
<motor name="elbow_left" gear="40" joint="elbow_left"/>
</actuator>
<keyframe>
<key qpos="-0.582713 -0.00241236 0.336233 0.301002 -0.748049 -0.0734037 0.586883 -0.0516 -0.202 0.23 -0.24 -0.007 -0.34 -1.76 -0.466 -0.0415 -0.08 -0.01 -0.37 -0.685 -0.35 -0.09 0.109 -0.067 -0.7 -0.05 0.12 0.16"
qvel="0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" />
</keyframe>
</mujoco>
+186
View File
@@ -0,0 +1,186 @@
<mujoco>
<option jacobian="dense" density="1.225" viscosity="1.8e-5" wind="0 0 1">
<flag fwdinv="enable" energy="enable" island="enable"/>
</option>
<asset>
<mesh name="icosahedron" scale=".05 .05 .05"
vertex="0 1 1.618
0 -1 1.618
0 1 -1.618
0 -1 -1.618
1 1.618 0
-1 1.618 0
1 -1.618 0
-1 -1.618 0
1.618 0 1
1.618 0 -1
-1.618 0 1
-1.618 0 -1"/>
<hfield name="hfield" nrow="3" ncol="3" size=".2 .2 .03 .03"
elevation="1 0 1
0 1 0
1 0 1"/>
<texture builtin="gradient" height="100" rgb1="1 1 1" rgb2="0 0 0" type="skybox" width="100"/>
<texture name="grid" type="cube" builtin="checker" width="32" height="32" rgb1=".1 .2 .3" rgb2="1 1 1"/>
<material name="grid" texture="grid" texrepeat="1 1" texuniform="true" reflectance=".2"/>
</asset>
<default>
<site rgba=".5 .5 .5 .5"/>
<joint armature="1" damping="10"/>
<general ctrllimited="true" ctrlrange="-1 1"/>
<default class="hip0">
<joint springref="30" stiffness="60"/>
</default>
<default class="hip1">
<joint limited="true" range="-60 60" stiffness="10"/>
</default>
<default class="wheel">
<joint damping=".1" armature=".1"/>
</default>
</default>
<worldbody>
<light pos="0 0 3"/>
<geom name="floor" type="plane" size="4 4 .1" margin="0.01" gap="0.005"/>
<geom type="hfield" hfield="hfield" pos="-.4 .6 .05" rgba="0 0 1 1"/>
<body name="head" pos="0 0 .7" gravcomp="0.5">
<geom type="ellipsoid" size=".2 .2 .4" density="200" material="grid"/>
<site name="head" pos="0 0 .4" size=".1 .1 .05" type="box"/>
<site name="anchor0" pos="0 .2 0"/>
<site name="anchor_knee" pos="-.16 -.16 0"/>
<site name="rf" pos="0 0 -0.41" zaxis="0 0 -1"/>
<freejoint/>
<body euler="0 0 0" pos=".2 0 -.2">
<joint name="hipz_0" class="hip1" axis="0 0 1"/>
<joint name="hipy_0" class="hip0" axis="0 1 0"/>
<geom type="capsule" size=".05" rgba="1 0 0 1" fromto="0 0 0 .3 0 0"/>
<body pos=".3 0 0">
<site name="knee"/>
<geom type="capsule" size=".05" rgba="1 0 0 1" fromto="0 0 0 .1 0 -.3"/>
<body pos=".1 0 -.3">
<joint name="wheel_0" type="ball" class="wheel"/>
<site name="wheel_0" type="box" size=".1 .1 .1"/>
<geom name="wheel_0" size=".1 .2 .1" rgba="0 1 0 1" type="ellipsoid"/>
</body>
</body>
</body>
<body euler="0 0 120" pos="-.15 .2 -.2">
<joint name="hipz_1" class="hip1" axis="0 0 1"/>
<joint name="hipy_1" class="hip0" axis="0 1 0"/>
<geom type="box" size=".05" rgba="1 0 0 1" fromto="0 0 0 .3 0 0"/>
<geom type="box" size=".05" rgba="1 0 0 1" fromto=".3 0 0 .4 0 -.3"/>
<body pos=".45 0 -.3">
<joint name="wheel_1" axis="1 0 0" class="wheel"/>
<geom size=".1" rgba="0 1 0 1" type="cylinder" fromto="0 0 0 .03 0 0"/>
<site name="wheel_1" type="box" size=".02 .11 .11" pos=".015 0 0"/>
</body>
</body>
<body euler="0 0 240" pos="-.15 -.2 -.2">
<joint name="hipz_2" class="hip1" axis="0 0 1"/>
<joint name="hipy_2" class="hip0" axis="0 1 0"/>
<geom type="capsule" size=".05" rgba="1 0 0 1" fromto="0 0 0 .3 0 0"/>
<geom type="capsule" size=".05" rgba="1 0 0 1" fromto=".3 0 0 .4 0 -.3"/>
<site name="knee_2" pos=".3 0 .05"/>
<body pos=".45 0 -.3">
<joint name="wheel_2" axis="1 0 0" class="wheel"/>
<geom size=".1" rgba="0 1 0 1" type="cylinder" fromto="0 0 0 .03 0 0" margin="0.01"/>
<site name="wheel_2" size=".13" rgba="0 0 0 0.1" type="cylinder" fromto="-.01 0 0 .04 0 0"/>
</body>
</body>
</body>
<body pos="-.33 0 1">
<joint name="slider" type="slide" axis="0 0 1" limited="true" range="-.2 .5"/>
<joint type="hinge" axis="0 1 0"/>
<geom type="mesh" mesh="icosahedron" size=".1" rgba="0 0 1 1"/>
</body>
<body name="cylinder" pos="-.5 .3 .7">
<freejoint/>
<geom name="wrapping" type="cylinder" size=".04" fromto="-.1 -.2 0 .1 .4 0"/>
<site name="cylinder"/>
</body>
<site name="sidesite" pos="-.5 .4 1"/>
<body pos="-.3 .6 .8">
<freejoint/>
<geom type="box" size=".05 .05 .05" rgba="0 0 1 1"/>
<site name="anchor1" pos=".05 .05 .05"/>
</body>
<body pos="-.6 .4 .8">
<freejoint/>
<geom type="box" size=".05 .05 .05" rgba="0 0 1 1"/>
<site name="anchor2" pos=".05 .05 .05"/>
</body>
<body name="tumbling" pos="-.2 .3 1">
<freejoint/>
<geom type="box" size=".025 .01 0.0001" pos=".025 0 0" euler="20 0 0" mass="1e-4" fluidshape="ellipsoid"/>
<geom type="box" size=".025 .01 0.0001" pos="-.025 0 0" euler="-19 0 0" mass="1e-4" fluidshape="ellipsoid"/>
</body>
<body pos="-.2 .3 .8">
<geom type="sdf" mesh="icosahedron" size=".1" rgba="0 0 1 1"/>
</body>
</worldbody>
<equality>
<weld body1="world" body2="cylinder"/>
</equality>
<tendon>
<spatial name="spatial" limited="true" range="0 .7" rgba="1 0 1 1">
<site site="anchor0"/>
<site site="anchor1"/>
<geom geom="wrapping" sidesite="sidesite"/>
<site site="anchor2"/>
</spatial>
<spatial name="knee" limited="true" range=".4 .5" rgba="1 0 1 1" armature="0.1">
<site site="anchor_knee"/>
<site site="knee_2"/>
</spatial>
<fixed name="fixed">
<joint joint="hipy_0" coef="1"/>
<joint joint="hipy_1" coef="1"/>
</fixed>
</tendon>
<actuator>
<motor tendon="fixed" gear="100"/>
<motor tendon="spatial" gear="10"/>
<motor joint="hipy_2" gear="100"/>
<position joint="hipz_1" kp="100"/>
<position joint="hipz_2" kp="100"/>
<velocity joint="wheel_2" kv="1"/>
<intvelocity joint="hipz_0" kp="100" actrange="-1 1"/>
<general site="wheel_0" gear="0 0 0 0 10 0" dyntype="filter" dynprm="1"/>
<general joint="wheel_1" biastype="affine" dyntype="integrator" dynprm="1" biasprm="0 -1"/>
<general joint="hipy_1" actearly="true" dyntype="filterexact" dynprm="0.9" gear="12.1" />
</actuator>
<sensor>
<framepos objtype="site" objname="wheel_0" reftype="site" refname="wheel_2"/>
<rangefinder site="rf"/>
<gyro site="wheel_2"/>
<touch site="wheel_1"/>
<force site="knee"/>
<torque site="knee"/>
<force site="cylinder"/>
<torque site="cylinder"/>
<jointlimitfrc joint="slider"/>
<accelerometer site="head"/>
<subtreeangmom body="head"/>
</sensor>
<keyframe>
<key name="start"
qpos="0.0133625 -0.013799 0.659429 0.999776 0.019159 0.00902704 0.000572574 -0.00776575 0.0983289 0.999861 -0.00869796 -0.0141805 0.000912197 0.00700633 0.0930296 0.00637469 -0.00313231 0.119692 0.0051478 -0.0469067 0 -0.500224 0.300659 0.69913 1 -0.000367766 -0.000265698 -0.000109715 -0.319851 0.525628 0.702735 0.29858 0.698263 -0.0490604 -0.648746 -0.579432 0.4206 0.749601 0.900145 -0.208463 0.346664 -0.161576 -0.200033 0.300084 0.976421 0.878429 -0.00171382 0.00127086 -0.477867"
qvel="0.508861 -0.243772 -0.327162 0.549686 1.13746 0.0282475 -0.0865243 1.06414 -0.239958 -0.532111 -0.00133789 -0.0654491 0.533148 -0.253161 0.122149 0.824764 0.723529 -0.674175 0 -0.00154509 -0.00568917 0.00479921 0.00541817 0.00115895 0.00317796 -0.160161 -0.599488 -1.38103 14.9789 -1.05454 -13.9252 -0.31223 -0.0102486 -0.405851 5.43992 -4.71514 0.114928 -0.00123758 0.000187845 -0.244109 -0.190199 0.0697975 -16.3286"/>
</keyframe>
<custom>
<numeric name="numeric" data="1 2 3"/>
<text name="text" data="abc"/>
<tuple name="tuple">
<element objtype="body" objname="cylinder" prm="1"/>
<element objtype="joint" objname="hipz_0" prm="2"/>
</tuple>
</custom>
</mujoco>
+108
View File
@@ -0,0 +1,108 @@
<mujoco model="Mixed convex objects">
<statistic extent="1.5" meansize=".05"/>
<visual>
<rgba haze="0.15 0.25 0.35 1"/>
<map shadowscale="0.5" zfar="40" force="0.01"/>
</visual>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="64" height="64"/>
<texture name="texplane" type="2d" builtin="checker" rgb1=".2 .3 .4" rgb2=".1 0.15 0.2" width="512" height="512" mark="cross" markrgb=".8 .8 .8"/>
<material name="matplane" reflectance="0.3" texture="texplane" texrepeat="1 1" texuniform="true"/>
<mesh name="icosahedron" scale=".05 .05 .05"
vertex="0 1 1.618
0 -1 1.618
0 1 -1.618
0 -1 -1.618
1 1.618 0
-1 1.618 0
1 -1.618 0
-1 -1.618 0
1.618 0 1
1.618 0 -1
-1.618 0 1
-1.618 0 -1"/>
<mesh name="meshbox" scale=".05 .05 .05"
vertex="-1 -1 -1
1 -1 -1
1 1 -1
1 1 1
1 -1 1
-1 1 -1
-1 1 1
-1 -1 1"/>
<hfield name="hfield" nrow="5" ncol="5" size=".53 .53 .03 .03"
elevation="1 0 1 0 1
0 2 0 2 0
1 0 1 0 1
0 2 0 2 0
1 0 1 0 1"/>
</asset>
<default>
<geom solref="2e-3 1" size=".05 .15 .07"/>
</default>
<option timestep="1e-3" solver="PGS"/>
<worldbody>
<light directional="true" diffuse=".4 .4 .4" specular="0.1 0.1 0.1" pos="0 0 5" castshadow="false"/>
<light diffuse=".6 .6 .6" specular="0.2 0.2 0.2" pos="0 0 4"/>
<geom type="plane" size="3 3 .01"/>
<geom type="hfield" hfield="hfield" rgba=".5 .5 .5 .2"/>
<replicate count="4" euler="0 0 90">
<geom type="hfield" hfield="hfield" zaxis="1 0 0" pos="-.5 0 .5" rgba=".5 .5 .5 .2"/>
</replicate>
<replicate count="15" euler="0 0 60" offset="0 0 .15">
<body pos="-.3 -.3 .3" euler="10 20 30">
<freejoint/>
<geom type="ellipsoid"/>
</body>
</replicate>
<replicate count="15" euler="0 0 60" offset="0 0 .15">
<body pos="-.3 -.3 1" euler="10 20 30">
<freejoint/>
<geom type="box"/>
</body>
</replicate>
<replicate count="15" euler="0 0 60" offset="0 0 .15">
<body pos="-.3 -.3 .6" euler="10 20 30">
<freejoint/>
<geom type="capsule"/>
</body>
</replicate>
<replicate count="15" euler="0 0 60" offset="0 0 .15">
<body pos="-.3 .3 .3" euler="10 20 30">
<freejoint/>
<geom type="cylinder"/>
</body>
</replicate>
<replicate count="20" euler="0 0 60" offset="0 0 .15">
<body pos="-.15 .15 .3" euler="10 20 30">
<freejoint/>
<geom type="mesh" mesh="icosahedron"/>
</body>
</replicate>
<replicate count="20" euler="0 0 60" offset="0 0 .15">
<body pos=".15 -.15 .3" euler="10 20 30">
<freejoint/>
<geom type="mesh" mesh="meshbox"/>
</body>
</replicate>
<replicate count="15" euler="0 0 60" offset="0 0 .15">
<body pos=".05 0 .3" euler="10 20 30">
<freejoint/>
<geom type="sphere"/>
</body>
</replicate>
</worldbody>
</mujoco>