Remove physics schema authoring toggle from MJCF SdfFileFormat plugin.

PiperOrigin-RevId: 789321573
Change-Id: Ib29bb426f8598a58f7b34c048b154fa8ada589ef
This commit is contained in:
Sam Haves
2025-07-31 07:05:41 -07:00
committed by Copybara-Service
parent 9f64338b37
commit 4c288c19ac
7 changed files with 158 additions and 237 deletions
@@ -147,17 +147,9 @@ bool UsdMjcfFileFormat::CanRead(const std::string &filePath) const {
bool UsdMjcfFileFormat::ReadImpl(pxr::SdfLayer *layer, mjSpec *spec) const {
auto args = layer->GetFileFormatArguments();
bool toggleUsdPhysics = false;
const auto it =
args.find(UsdMjcfFileFormatTokens->ToggleUsdPhysicsArg.GetString());
if (it != args.end()) {
toggleUsdPhysics = pxr::TfUnstringify<bool>(it->second);
}
auto data = InitData(args);
auto success = mujoco::usd::WriteSpecToData(spec, data, toggleUsdPhysics);
auto success = mujoco::usd::WriteSpecToData(spec, data);
mj_deleteSpec(spec);
if (!success) {
return false;
@@ -34,7 +34,6 @@ PXR_NAMESPACE_OPEN_SCOPE
((Id, "xml")) \
((Version, "1.0")) \
((Target, "usd")) \
((ToggleUsdPhysicsArg, "usdMjcfToggleUsdPhysics"))
// clang-format on
TF_DECLARE_PUBLIC_TOKENS(UsdMjcfFileFormatTokens, USD_MJCF_FILE_FORMAT_TOKENS);
@@ -182,10 +182,7 @@ class ModelWriter {
}
~ModelWriter() { mj_deleteModel(model_); }
void Write(bool write_physics) {
// Set working parameters.
write_physics_ = write_physics;
void Write() {
// Create top level class holder.
class_path_ = CreateClassSpec(data_, pxr::SdfPath::AbsoluteRootPath(),
pxr::TfToken("__class__"));
@@ -211,9 +208,7 @@ class ModelWriter {
WriteMeshes();
WriteMaterials();
WriteBodies();
if (write_physics_) {
WriteActuators();
}
WriteActuators();
WriteKeyframes();
}
@@ -236,8 +231,6 @@ class ModelWriter {
std::unordered_map<std::string, pxr::SdfPath> mesh_paths_;
// Set of body ids that have had the articulation root API applied.
std::unordered_set<int> articulation_roots_;
// Whether to write physics data.
bool write_physics_ = false;
// Given a name index and a parent prim path this returns a
// token such that appending it to the parent prim path does not
@@ -376,26 +369,23 @@ class ModelWriter {
pxr::UsdGeomTokens->Mesh);
mesh_paths_[*mjs_getName(mesh->element)] = subcomponent_path;
if (write_physics_) {
ApplyApiSchema(data_, mesh_path, MjcPhysicsTokens->MjcMeshCollisionAPI);
ApplyApiSchema(data_, mesh_path, MjcPhysicsTokens->MjcMeshCollisionAPI);
pxr::TfToken inertia = MjcPhysicsTokens->legacy;
if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_EXACT) {
inertia = MjcPhysicsTokens->exact;
} else if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_CONVEX) {
inertia = MjcPhysicsTokens->convex;
} else if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_SHELL) {
inertia = MjcPhysicsTokens->shell;
}
WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Token,
MjcPhysicsTokens->mjcInertia, inertia);
WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Int,
MjcPhysicsTokens->mjcMaxhullvert,
mesh->maxhullvert);
pxr::TfToken inertia = MjcPhysicsTokens->legacy;
if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_EXACT) {
inertia = MjcPhysicsTokens->exact;
} else if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_CONVEX) {
inertia = MjcPhysicsTokens->convex;
} else if (mesh->inertia == mjtMeshInertia::mjMESH_INERTIA_SHELL) {
inertia = MjcPhysicsTokens->shell;
}
WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Token,
MjcPhysicsTokens->mjcInertia, inertia);
WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Int,
MjcPhysicsTokens->mjcMaxhullvert, mesh->maxhullvert);
// NOTE: The geometry data taken from the spec is the post-compilation
// data after it has been mjCMesh::Compile'd. So don't be surprised if
// things like user defined vertices have moved due to re-centering to
@@ -1652,16 +1642,15 @@ class ModelWriter {
MjcPhysicsTokens->mjcGroup, geom->group);
if (model_->geom_contype[geom_id] == 0 &&
model_->geom_conaffinity[geom_id] == 0) {
model_->geom_conaffinity[geom_id] == 0) {
// If the geom is purely visual, apply the imageable API.
ApplyApiSchema(data_, geom_path,
MjcPhysicsTokens->MjcImageableAPI);
ApplyApiSchema(data_, geom_path, MjcPhysicsTokens->MjcImageableAPI);
}
// Apply the physics schemas if we are writing physics and the
// geom participates in collisions.
if (write_physics_ && (model_->geom_contype[geom_id] != 0 ||
model_->geom_conaffinity[geom_id] != 0)) {
if (model_->geom_contype[geom_id] != 0 ||
model_->geom_conaffinity[geom_id] != 0) {
ApplyApiSchema(data_, geom_path,
pxr::UsdPhysicsTokens->PhysicsCollisionAPI);
ApplyApiSchema(data_, geom_path, MjcPhysicsTokens->MjcCollisionAPI);
@@ -1822,8 +1811,6 @@ class ModelWriter {
}
void WriteJoints(mjsBody *body) {
if (!write_physics_) return;
int body_id = mjs_getId(body->element);
if (body_id == kWorldIndex) return;
@@ -2224,50 +2211,47 @@ class ModelWriter {
}
}
// Apply the PhysicsRigidBodyAPI schema if we are writing physics.
if (write_physics_) {
// If the body had a mass specified then it must have either inertia or
// fullinertia specified per inertia element XML documentation.
// Therefore it is sufficient to check if the mass is non-zero to see if
// we should set inertial attributes on the body.
//
// Note that if the user has NOT specified any inertial properties then
// we don't want to pull values from the compiled model since coming back
// into Mujoco would take those values instead of computing them
// automatically from the subtree.
if (body->mass > 0) {
// User might have specified the inertia via fullinertia and the
// compiler has extracted all values properly. So leverage those
// instead of doing the computation ourselves here.
ApplyApiSchema(data_, body_path, pxr::UsdPhysicsTokens->PhysicsMassAPI);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float,
pxr::UsdPhysicsTokens->physicsMass,
(float)model_->body_mass[body_id]);
// If the body had a mass specified then it must have either inertia or
// fullinertia specified per inertia element XML documentation.
// Therefore it is sufficient to check if the mass is non-zero to see if
// we should set inertial attributes on the body.
//
// Note that if the user has NOT specified any inertial properties then
// we don't want to pull values from the compiled model since coming back
// into Mujoco would take those values instead of computing them
// automatically from the subtree.
if (body->mass > 0) {
// User might have specified the inertia via fullinertia and the
// compiler has extracted all values properly. So leverage those
// instead of doing the computation ourselves here.
ApplyApiSchema(data_, body_path, pxr::UsdPhysicsTokens->PhysicsMassAPI);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float,
pxr::UsdPhysicsTokens->physicsMass,
(float)model_->body_mass[body_id]);
mjtNum *body_ipos = &model_->body_ipos[body_id * 3];
pxr::GfVec3f inertial_pos(body_ipos[0], body_ipos[1], body_ipos[2]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Point3f,
pxr::UsdPhysicsTokens->physicsCenterOfMass,
inertial_pos);
mjtNum *body_ipos = &model_->body_ipos[body_id * 3];
pxr::GfVec3f inertial_pos(body_ipos[0], body_ipos[1], body_ipos[2]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Point3f,
pxr::UsdPhysicsTokens->physicsCenterOfMass,
inertial_pos);
mjtNum *body_iquat = &model_->body_iquat[body_id * 4];
pxr::GfQuatf inertial_frame(body_iquat[0], body_iquat[1], body_iquat[2],
body_iquat[3]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Quatf,
pxr::UsdPhysicsTokens->physicsPrincipalAxes,
inertial_frame);
mjtNum *body_iquat = &model_->body_iquat[body_id * 4];
pxr::GfQuatf inertial_frame(body_iquat[0], body_iquat[1], body_iquat[2],
body_iquat[3]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Quatf,
pxr::UsdPhysicsTokens->physicsPrincipalAxes,
inertial_frame);
mjtNum *inertia = &model_->body_inertia[body_id * 3];
pxr::GfVec3f diag_inertia(inertia[0], inertia[1], inertia[2]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float3,
pxr::UsdPhysicsTokens->physicsDiagonalInertia,
diag_inertia);
}
ApplyApiSchema(data_, body_path,
pxr::UsdPhysicsTokens->PhysicsRigidBodyAPI);
mjtNum *inertia = &model_->body_inertia[body_id * 3];
pxr::GfVec3f diag_inertia(inertia[0], inertia[1], inertia[2]);
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Float3,
pxr::UsdPhysicsTokens->physicsDiagonalInertia,
diag_inertia);
}
ApplyApiSchema(data_, body_path,
pxr::UsdPhysicsTokens->PhysicsRigidBodyAPI);
// Create classes if necessary
mjsDefault *spec_default = mjs_getDefault(body->element);
@@ -2337,8 +2321,7 @@ class ModelWriter {
namespace mujoco {
namespace usd {
bool WriteSpecToData(mjSpec *spec, pxr::SdfAbstractDataRefPtr &data,
bool write_physics) {
bool WriteSpecToData(mjSpec *spec, pxr::SdfAbstractDataRefPtr &data) {
// Create pseudo root first.
data->CreateSpec(pxr::SdfPath::AbsoluteRootPath(),
pxr::SdfSpecTypePseudoRoot);
@@ -2349,7 +2332,7 @@ bool WriteSpecToData(mjSpec *spec, pxr::SdfAbstractDataRefPtr &data,
return false;
}
ModelWriter(spec, model, data).Write(write_physics);
ModelWriter(spec, model, data).Write();
return true;
}
@@ -25,9 +25,7 @@ namespace usd {
// Args:
// spec: mjSpec built programmatically or via parsed XML.
// data: SdfAbstractDataRefPtr that will be written to.
// write_physics: Whether to write physics data.
bool WriteSpecToData(mjSpec* spec, pxr::SdfAbstractDataRefPtr& data,
bool write_physics);
bool WriteSpecToData(mjSpec* spec, pxr::SdfAbstractDataRefPtr& data);
} // namespace usd
} // namespace mujoco
@@ -110,9 +110,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestClassAuthored) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = OpenStage(kXml);
auto stage = pxr::UsdStage::Open(layer);
EXPECT_PRIM_VALID(stage, "/__class__");
EXPECT_PRIM_VALID(stage, "/__class__/test");
}
@@ -131,9 +130,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBasicMeshSources) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(stage, "/mesh_test");
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/tetrahedron");
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/tetrahedron/Mesh");
@@ -149,7 +146,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsMaterials) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(
stage, "/physics_materials_test/PhysicsMaterials/geom_with_friction");
EXPECT_REL_HAS_TARGET(
@@ -315,8 +312,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestGeomRgba) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(stage, "/test/sphere_red");
ExpectAttributeEqual(stage, "/test/sphere_red.primvars:displayColor",
@@ -388,9 +384,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestFaceVaryingMeshSourcesSimpleMjcfMesh) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
auto mesh = pxr::UsdGeomMesh::Get(
stage, SdfPath("/mesh_test/test_body/tetrahedron/Mesh"));
@@ -525,9 +519,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBody) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(stage, "/body_test");
EXPECT_PRIM_VALID(stage, "/body_test/test_body");
@@ -548,9 +540,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBasicParenting) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(stage, "/test/root");
EXPECT_PRIM_VALID(stage, "/test/root/root_body_1");
EXPECT_PRIM_VALID(stage, "/test/root/root_body_2");
@@ -578,9 +568,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestJointsDoNotAffectParenting) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_VALID(stage, "/test/root");
EXPECT_PRIM_VALID(stage, "/test/root/middle");
EXPECT_PRIM_VALID(stage, "/test/root/middle/tet");
@@ -607,9 +595,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestKindAuthoring) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_PRIM_KIND(stage, "/test", pxr::KindTokens->group);
EXPECT_PRIM_KIND(stage, "/test/root", pxr::KindTokens->component);
EXPECT_PRIM_KIND(stage, "/test/root/middle", pxr::KindTokens->subcomponent);
@@ -633,8 +619,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestAttributesMatchSchemaTypes) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
for (const auto& prim : stage->TraverseAll()) {
ExpectAllAuthoredAttributesMatchSchemaTypes(prim);
@@ -655,8 +640,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestGeomsPrims) {
</mujoco>
)";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
// Note that all sizes are multiplied by 2 because Mujoco uses half sizes.
@@ -702,11 +686,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestGeomsPrims) {
static const pxr::SdfPath kPhysicsScenePrimPath("/test/PhysicsScene");
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimTimestep) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option timestep="0.005"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -715,11 +699,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimTimestep) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCone) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option cone="elliptic"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -728,11 +712,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCone) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimWind) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option wind="1 2 3"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -741,11 +725,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimWind) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimApirate) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option apirate="1.2"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -754,11 +738,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimApirate) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimImpratio) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option impratio="0.8"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -767,11 +751,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimImpratio) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimMagnetic) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option magnetic="1 2 3"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -780,11 +764,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimMagnetic) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimDensity) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option density="1.2"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -793,11 +777,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimDensity) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimViscosity) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option viscosity="0.8"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -806,11 +790,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimViscosity) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_margin) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option o_margin="0.001"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -819,11 +803,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_margin) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_solref) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option o_solref="0.1 0.2"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -832,11 +816,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_solref) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_solimp) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option o_solimp="0.1 0.2 0.3 0.4 0.5"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -845,11 +829,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimO_solimp) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimTolerance) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option tolerance="0.0012"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -858,11 +842,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimTolerance) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimLSTolerance) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option ls_tolerance="0.0034"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -871,11 +855,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimLSTolerance) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimNoslipTolerance) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option noslip_tolerance="0.0056"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -884,11 +868,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimNoslipTolerance) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCCDTolerance) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option ccd_tolerance="0.0078"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -897,11 +881,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCCDTolerance) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimOFriction) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option o_friction="0.1 0.2 0.3 0.4 0.5"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -910,11 +894,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimOFriction) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimIntegrator) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option integrator="RK4"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -923,11 +907,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimIntegrator) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimJacobian) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option jacobian="sparse"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -936,11 +920,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimJacobian) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSolver) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option solver="CG"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(
stage,
@@ -949,11 +933,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSolver) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimIterations) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option iterations="10"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -962,11 +946,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimIterations) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimLSIterations) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option ls_iterations="20"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -975,11 +959,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimLSIterations) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimNoslipIterations) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option noslip_iterations="30"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -988,11 +972,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimNoslipIterations) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCCDIterations) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option ccd_iterations="40"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -1001,11 +985,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimCCDIterations) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSDFInitPoints) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option sdf_initpoints="50"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -1014,11 +998,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSDFInitPoints) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSDFIterations) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option sdf_iterations="60"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -1027,11 +1011,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimSDFIterations) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimGravity) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option gravity="-123 0 0"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -1042,11 +1026,11 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimGravity) {
pxr::UsdPhysicsTokens->physicsGravityDirection),
pxr::GfVec3f(-1.0f, 0.0f, 0.0f));
stage = pxr::UsdStage::Open(LoadLayer(R"(
stage = OpenStage(R"(
<mujoco model="test">
<option gravity="2 3 6"> </option>
</mujoco>
)"));
)");
ExpectAttributeEqual(stage,
kPhysicsScenePrimPath.AppendProperty(
@@ -1059,7 +1043,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimGravity) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimDisableFlags) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option>
<flag
@@ -1083,7 +1067,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimDisableFlags) {
/>
</option>
</mujoco>
)"));
)");
const std::vector<pxr::TfToken> kFlags = {
MjcPhysicsTokens->mjcFlagConstraint,
@@ -1111,7 +1095,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimDisableFlags) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimEnableFlags) {
auto stage = pxr::UsdStage::Open(LoadLayer(R"(
auto stage = OpenStage(R"(
<mujoco model="test">
<option>
<flag
@@ -1124,7 +1108,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsScenePrimEnableFlags) {
/>
</option>
</mujoco>
)"));
)");
// clang-format off
const std::vector<pxr::TfToken> kFlags = {
@@ -1158,9 +1142,7 @@ static constexpr char kSiteXml[] = R"(
)";
TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsAuthored) {
pxr::SdfLayerRefPtr layer = LoadLayer(kSiteXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kSiteXml);
EXPECT_PRIM_VALID(stage, "/test/box_site");
EXPECT_PRIM_IS_A(stage, "/test/box_site", pxr::UsdGeomCube);
EXPECT_PRIM_API_APPLIED(stage, "/test/box_site", pxr::MjcPhysicsSiteAPI);
@@ -1189,9 +1171,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsAuthored) {
}
TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsPurpose) {
pxr::SdfLayerRefPtr layer = LoadLayer(kSiteXml);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kSiteXml);
EXPECT_PRIM_PURPOSE(stage, "/test/box_site", pxr::UsdGeomTokens->guide);
EXPECT_PRIM_PURPOSE(stage, "/test/ball/sphere_site",
pxr::UsdGeomTokens->guide);
@@ -1203,27 +1183,6 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsPurpose) {
pxr::UsdGeomTokens->guide);
}
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsToggleSdfFormatArg) {
std::string xml_path = GetTestDataFilePath(kMeshObjPath);
// Test that the default is no physics.
auto stage_no_physics = pxr::UsdStage::Open(xml_path);
EXPECT_THAT(stage_no_physics, testing::NotNull());
EXPECT_PRIM_VALID(stage_no_physics, "/mesh_test/test_body");
EXPECT_PRIM_API_NOT_APPLIED(stage_no_physics, "/mesh_test/test_body",
pxr::UsdPhysicsRigidBodyAPI);
// Then test that the physics flag enables physics.
std::string xml_path_physics_flag =
xml_path + ":SDF_FORMAT_ARGS:usdMjcfToggleUsdPhysics=true";
auto stage_with_physics = pxr::UsdStage::Open(xml_path_physics_flag);
EXPECT_THAT(stage_with_physics, testing::NotNull());
EXPECT_PRIM_VALID(stage_with_physics, "/mesh_test/test_body");
EXPECT_PRIM_API_APPLIED(stage_with_physics, "/mesh_test/test_body",
pxr::UsdPhysicsRigidBodyAPI);
}
TEST_F(MjcfSdfFileFormatPluginTest, TestArticulationRootAppliedOnce) {
static constexpr char kXml[] = R"(
<mujoco model="physics_test">
@@ -1241,9 +1200,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestArticulationRootAppliedOnce) {
</mujoco>
)";
pxr::SdfFileFormat::FileFormatArguments args;
args["usdMjcfToggleUsdPhysics"] = "true";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml, args);
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);;
// This test is particular in the sense that the authoring mistake, which is
// made on the SdfLayer level, would disappear when we access the COMPOSED
@@ -1280,10 +1237,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsRigidBody) {
</mujoco>
)";
pxr::SdfFileFormat::FileFormatArguments args;
args["usdMjcfToggleUsdPhysics"] = "true";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml, args);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_VALID(stage, "/physics_test");
@@ -1358,10 +1312,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsColliders) {
</mujoco>
)";
pxr::SdfFileFormat::FileFormatArguments args;
args["usdMjcfToggleUsdPhysics"] = "true";
pxr::SdfLayerRefPtr layer = LoadLayer(kXml, args);
auto stage = pxr::UsdStage::Open(layer);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_VALID(stage, "/test");
@@ -1492,7 +1443,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsImageableAPI) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_API_APPLIED(stage, "/test/body/mesh/Mesh",
pxr::MjcPhysicsImageableAPI);
@@ -1522,7 +1473,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsCollisionAPI) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
ExpectAttributeEqual(stage, "/test/body/box.mjc:group", 4);
ExpectAttributeEqual(stage, "/test/body/box.mjc:priority", 2);
@@ -1558,7 +1509,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsMeshCollisionAPI) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
ExpectAttributeEqual(stage, "/test/body/tet_legacy/Mesh.mjc:inertia",
MjcPhysicsTokens->legacy);
@@ -1582,7 +1533,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMassAPIApplied) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/body");
EXPECT_PRIM_VALID(stage, "/test/body/box");
@@ -1602,7 +1553,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMassAPIAppliedToBody) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/body");
EXPECT_PRIM_VALID(stage, "/test/body/box");
@@ -1625,7 +1576,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMassAPIDensity) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
ExpectAttributeEqual(stage, "/test/body/box.physics:density", 1234.0f);
}
@@ -1666,7 +1617,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsActuator) {
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/general");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator);
@@ -1729,7 +1680,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsPositionActuator) {
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/position");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/position", pxr::MjcPhysicsActuator);
@@ -1757,7 +1708,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointActuator) {
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/general");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator);
@@ -1781,7 +1732,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsBodyActuator) {
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/general");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator);
@@ -1809,7 +1760,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsSliderCrankActuator) {
</actuator>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Actuators/general");
EXPECT_PRIM_IS_A(stage, "/test/Actuators/general", pxr::MjcPhysicsActuator);
@@ -1850,7 +1801,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsJointAPI) {
</worldbody>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
const SdfPath joint_path("/test/parent/child/my_joint");
EXPECT_PRIM_API_APPLIED(stage, joint_path, pxr::MjcPhysicsJointAPI);
@@ -1900,7 +1851,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsFloatingAndFixedBaseBody) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
// Test that the fixed_base body has a UsdPhysicsJoint child connected to the
@@ -1941,7 +1892,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsFixedJoint) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_IS_A(stage, "/test/parent/FixedJoint", pxr::UsdPhysicsFixedJoint);
@@ -1987,7 +1938,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsRevoluteJoint) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
// hinge_root doesn't set a type so it's the default: a revolute joint.
@@ -2046,7 +1997,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsPrismaticJoint) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_IS_A(stage, "/test/parent/slide_root",
@@ -2098,7 +2049,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestRadianAnglesAreConvertedToDegrees) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_VALID(stage, "/test/parent/hinge");
@@ -2128,7 +2079,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsJointFrames) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
// Test the hinge joint.
@@ -2220,7 +2171,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsUnsupportedJoint) {
</mujoco>
)";
auto stage = OpenStageWithPhysics(kXml);
auto stage = OpenStage(kXml);
EXPECT_THAT(stage, testing::NotNull());
EXPECT_PRIM_INVALID(stage, "/test/parent/ball_joint");
@@ -2242,7 +2193,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsKeyframe) {
<key time="2" qpos="3"/>
</keyframe>
</mujoco>)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/Keyframes/home");
EXPECT_PRIM_VALID(stage, "/test/Keyframes/Keyframe");
@@ -2277,7 +2228,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestCompilerOptions) {
/>
</mujoco>
)";
auto stage = OpenStageWithPhysics(xml);
auto stage = OpenStage(xml);
EXPECT_PRIM_VALID(stage, "/test/PhysicsScene");
+2 -4
View File
@@ -48,10 +48,8 @@ pxr::SdfLayerRefPtr LoadLayer(
return layer;
}
pxr::UsdStageRefPtr OpenStageWithPhysics(const std::string& xml) {
pxr::SdfFileFormat::FileFormatArguments args;
args["usdMjcfToggleUsdPhysics"] = "true";
pxr::SdfLayerRefPtr layer = LoadLayer(xml, args);
pxr::UsdStageRefPtr OpenStage(const std::string& xml) {
pxr::SdfLayerRefPtr layer = LoadLayer(xml);
auto stage = pxr::UsdStage::Open(layer);
EXPECT_THAT(stage, testing::NotNull());
return stage;
+1 -1
View File
@@ -99,7 +99,7 @@ pxr::SdfLayerRefPtr LoadLayer(
const std::string& xml,
const pxr::SdfFileFormat::FileFormatArguments& args = {});
pxr::UsdStageRefPtr OpenStageWithPhysics(const std::string& xml);
pxr::UsdStageRefPtr OpenStage(const std::string& xml);
template <typename T>
void ExpectAttributeEqual(