Make MJCF SdfFileFormat plugin create hierarchy reflecting MJCF instead of sibling rigidbodies.
PiperOrigin-RevId: 762117447 Change-Id: Id13f7a4f4e383a0c9e670e5272836f2fb1099830
This commit is contained in:
committed by
Copybara-Service
parent
74cc904edc
commit
76ddc30072
@@ -154,7 +154,6 @@ class ModelWriter {
|
|||||||
ModelWriter(mjSpec *spec, mjModel *model, pxr::SdfAbstractDataRefPtr &data)
|
ModelWriter(mjSpec *spec, mjModel *model, pxr::SdfAbstractDataRefPtr &data)
|
||||||
: spec_(spec), model_(model), data_(data), class_path_("/Bad_Path") {
|
: spec_(spec), model_(model), data_(data), class_path_("/Bad_Path") {
|
||||||
body_paths_ = std::vector<pxr::SdfPath>(model->nbody);
|
body_paths_ = std::vector<pxr::SdfPath>(model->nbody);
|
||||||
body_xforms_ = std::vector<pxr::GfMatrix4d>(model->nbody);
|
|
||||||
}
|
}
|
||||||
~ModelWriter() { mj_deleteModel(model_); }
|
~ModelWriter() { mj_deleteModel(model_); }
|
||||||
|
|
||||||
@@ -165,7 +164,6 @@ class ModelWriter {
|
|||||||
|
|
||||||
// Create the world body.
|
// Create the world body.
|
||||||
body_paths_[kWorldIndex] = WriteWorldBody(kWorldIndex);
|
body_paths_[kWorldIndex] = WriteWorldBody(kWorldIndex);
|
||||||
body_xforms_[kWorldIndex] = pxr::GfMatrix4d().SetIdentity();
|
|
||||||
|
|
||||||
SetLayerMetadata(data_, pxr::SdfFieldKeys->Documentation,
|
SetLayerMetadata(data_, pxr::SdfFieldKeys->Documentation,
|
||||||
"Generated by mujoco model writer.");
|
"Generated by mujoco model writer.");
|
||||||
@@ -198,8 +196,6 @@ class ModelWriter {
|
|||||||
pxr::SdfPath class_path_;
|
pxr::SdfPath class_path_;
|
||||||
// Mapping from Mujoco body id to SdfPath.
|
// Mapping from Mujoco body id to SdfPath.
|
||||||
std::vector<pxr::SdfPath> body_paths_;
|
std::vector<pxr::SdfPath> body_paths_;
|
||||||
// Mapping from Mujoco body id to world space transform.
|
|
||||||
std::vector<pxr::GfMatrix4d> body_xforms_;
|
|
||||||
// Mapping from mesh names to Mesh prim path.
|
// Mapping from mesh names to Mesh prim path.
|
||||||
std::unordered_map<std::string, pxr::SdfPath> mesh_paths_;
|
std::unordered_map<std::string, pxr::SdfPath> mesh_paths_;
|
||||||
|
|
||||||
@@ -248,44 +244,6 @@ class ModelWriter {
|
|||||||
pxr::TfToken body_name;
|
pxr::TfToken body_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
pxr::SdfPath CreateParentIfNotExists(mjsBody *body,
|
|
||||||
const pxr::SdfPath &world_path,
|
|
||||||
pxr::SdfAbstractDataRefPtr &data) {
|
|
||||||
// To allow for easier scene authoring and modification, we want to
|
|
||||||
// place MJCF bodies belonging to the same kinematic chain under some
|
|
||||||
// identity parent Xform prim. This allows users to move the entire
|
|
||||||
// asset.
|
|
||||||
//
|
|
||||||
// We cannot simply recreate the MJCF kinematic tree structure
|
|
||||||
// because in USD it is assumed that children move rigidly with their
|
|
||||||
// parents. This is not true in MJCF if you have joints. We could perhaps
|
|
||||||
// use a more complex heuristic where we evaluate a common tree prefix
|
|
||||||
// in MJCF that is effectively welded together but for now we choose
|
|
||||||
// simplicity.
|
|
||||||
|
|
||||||
// In the trivial case where the parent of body is already the world
|
|
||||||
// body we want to create a parent xform of the same name.
|
|
||||||
// So if the MJCF has a child of the world body called "root" we will
|
|
||||||
// create a parent Xform at /World/root and the actual body will be
|
|
||||||
// created at /World/root/root.
|
|
||||||
mjsBody *last_parent = body;
|
|
||||||
mjsBody *parent = mjs_getParent(body->element);
|
|
||||||
while (mjs_getId(parent->element) != kWorldIndex) {
|
|
||||||
last_parent = parent;
|
|
||||||
parent = mjs_getParent(parent->element);
|
|
||||||
}
|
|
||||||
|
|
||||||
pxr::TfToken last_parent_name = GetValidPrimName(*last_parent->name);
|
|
||||||
pxr::SdfPath parent_xform_path = world_path.AppendChild(last_parent_name);
|
|
||||||
if (!data->HasSpec(parent_xform_path)) {
|
|
||||||
pxr::SdfPath prim_path = CreatePrimSpec(
|
|
||||||
data, world_path, last_parent_name, pxr::UsdGeomTokens->Xform);
|
|
||||||
|
|
||||||
SetPrimKind(data_, prim_path, pxr::KindTokens->component);
|
|
||||||
}
|
|
||||||
return parent_xform_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WriteScaleXformOp(const pxr::SdfPath &prim_path,
|
void WriteScaleXformOp(const pxr::SdfPath &prim_path,
|
||||||
const pxr::GfVec3f &scale) {
|
const pxr::GfVec3f &scale) {
|
||||||
pxr::SdfPath scale_attr_path =
|
pxr::SdfPath scale_attr_path =
|
||||||
@@ -1263,8 +1221,10 @@ class ModelWriter {
|
|||||||
|
|
||||||
void WriteBody(mjsBody *body, bool write_physics) {
|
void WriteBody(mjsBody *body, bool write_physics) {
|
||||||
int body_id = mjs_getId(body->element);
|
int body_id = mjs_getId(body->element);
|
||||||
pxr::SdfPath parent_path =
|
// This should be safe as we process parent bodies before children.
|
||||||
CreateParentIfNotExists(body, body_paths_[kWorldIndex], data_);
|
mjsBody *parent = mjs_getParent(body->element);
|
||||||
|
int parent_id = mjs_getId(parent->element);
|
||||||
|
pxr::SdfPath parent_path = body_paths_[parent_id];
|
||||||
pxr::TfToken body_name = GetValidPrimName(*body->name);
|
pxr::TfToken body_name = GetValidPrimName(*body->name);
|
||||||
|
|
||||||
// Create Xform prim for body.
|
// Create Xform prim for body.
|
||||||
@@ -1272,12 +1232,25 @@ class ModelWriter {
|
|||||||
pxr::UsdGeomTokens->Xform);
|
pxr::UsdGeomTokens->Xform);
|
||||||
// The parent_path will be a component which makes the actual articulated
|
// The parent_path will be a component which makes the actual articulated
|
||||||
// bodies subcomponents.
|
// bodies subcomponents.
|
||||||
SetPrimKind(data_, body_path, pxr::KindTokens->subcomponent);
|
auto kind = parent_id == kWorldIndex ? pxr::KindTokens->component
|
||||||
|
: pxr::KindTokens->subcomponent;
|
||||||
|
SetPrimKind(data_, body_path, kind);
|
||||||
|
|
||||||
// Apply the PhysicsRigidBodyAPI schema if we are writing physics.
|
// Apply the PhysicsRigidBodyAPI schema if we are writing physics.
|
||||||
if (write_physics) {
|
if (write_physics) {
|
||||||
ApplyApiSchema(data_, body_path,
|
ApplyApiSchema(data_, body_path,
|
||||||
pxr::UsdPhysicsTokens->PhysicsRigidBodyAPI);
|
pxr::UsdPhysicsTokens->PhysicsRigidBodyAPI);
|
||||||
|
|
||||||
|
// If the parent is not the world body, but is child of the world body
|
||||||
|
// then we need to apply the articulation root API.
|
||||||
|
if (parent_id != kWorldIndex) {
|
||||||
|
int parent_parent_id =
|
||||||
|
mjs_getId(mjs_getParent(parent->element)->element);
|
||||||
|
if (parent_parent_id == kWorldIndex) {
|
||||||
|
ApplyApiSchema(data_, parent_path,
|
||||||
|
pxr::UsdPhysicsTokens->PhysicsArticulationRootAPI);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create classes if necessary
|
// Create classes if necessary
|
||||||
@@ -1290,17 +1263,15 @@ class ModelWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create XformOp attribute for body transform.
|
// Create XformOp attribute for body transform.
|
||||||
// Make sure to account for the parent since UsdPhysics doesn't support
|
|
||||||
// nested bodies!
|
pxr::SdfPath xform_op_path =
|
||||||
auto parent_xform = body_xforms_[model_->body_parentid[body_id]];
|
CreateAttributeSpec(data_, body_path, kTokens->xformOpTransform,
|
||||||
|
pxr::SdfValueTypeNames->Matrix4d);
|
||||||
// mjModel will have all frames already accounted for so no need to worry
|
// mjModel will have all frames already accounted for so no need to worry
|
||||||
// about them here.
|
// about them here.
|
||||||
body_xforms_[body_id] =
|
auto body_xform = MujocoPosQuatToTransform(&model_->body_pos[body_id * 3],
|
||||||
MujocoPosQuatToTransform(&model_->body_pos[body_id * 3],
|
&model_->body_quat[body_id * 4]);
|
||||||
&model_->body_quat[body_id * 4]) *
|
SetAttributeDefault(data_, xform_op_path, body_xform);
|
||||||
parent_xform;
|
|
||||||
WriteUniformAttribute(body_path, pxr::SdfValueTypeNames->Matrix4d,
|
|
||||||
kTokens->xformOpTransform, body_xforms_[body_id]);
|
|
||||||
|
|
||||||
// Create XformOpOrder attribute for body transform order.
|
// Create XformOpOrder attribute for body transform order.
|
||||||
// For us this is simply the transform we authored above.
|
// For us this is simply the transform we authored above.
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
#include <pxr/usd/usdGeom/primvarsAPI.h>
|
#include <pxr/usd/usdGeom/primvarsAPI.h>
|
||||||
#include <pxr/usd/usdGeom/sphere.h>
|
#include <pxr/usd/usdGeom/sphere.h>
|
||||||
#include <pxr/usd/usdGeom/tokens.h>
|
#include <pxr/usd/usdGeom/tokens.h>
|
||||||
|
#include <pxr/usd/usdPhysics/articulationRootAPI.h>
|
||||||
#include <pxr/usd/usdPhysics/collisionAPI.h>
|
#include <pxr/usd/usdPhysics/collisionAPI.h>
|
||||||
#include <pxr/usd/usdPhysics/meshCollisionAPI.h>
|
#include <pxr/usd/usdPhysics/meshCollisionAPI.h>
|
||||||
#include <pxr/usd/usdPhysics/rigidBodyAPI.h>
|
#include <pxr/usd/usdPhysics/rigidBodyAPI.h>
|
||||||
@@ -116,8 +117,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBasicMeshSources) {
|
|||||||
|
|
||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_VALID(stage, "/mesh_test");
|
EXPECT_PRIM_VALID(stage, "/mesh_test");
|
||||||
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/test_body/tetrahedron");
|
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/tetrahedron");
|
||||||
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/test_body/tetrahedron/Mesh");
|
EXPECT_PRIM_VALID(stage, "/mesh_test/test_body/tetrahedron/Mesh");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestMaterials) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestMaterials) {
|
||||||
@@ -222,7 +223,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestFaceVaryingMeshSourcesSimpleMjcfMesh) {
|
|||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
|
|
||||||
auto mesh = pxr::UsdGeomMesh::Get(
|
auto mesh = pxr::UsdGeomMesh::Get(
|
||||||
stage, SdfPath("/mesh_test/test_body/test_body/tetrahedron/Mesh"));
|
stage, SdfPath("/mesh_test/test_body/tetrahedron/Mesh"));
|
||||||
ASSERT_TRUE(mesh);
|
ASSERT_TRUE(mesh);
|
||||||
pxr::VtArray<int> face_vertex_counts;
|
pxr::VtArray<int> face_vertex_counts;
|
||||||
mesh.GetFaceVertexCountsAttr().Get(&face_vertex_counts);
|
mesh.GetFaceVertexCountsAttr().Get(&face_vertex_counts);
|
||||||
@@ -273,8 +274,8 @@ TEST_F(MjcfSdfFileFormatPluginTest,
|
|||||||
auto stage = pxr::UsdStage::Open(xml_path);
|
auto stage = pxr::UsdStage::Open(xml_path);
|
||||||
EXPECT_THAT(stage, testing::NotNull());
|
EXPECT_THAT(stage, testing::NotNull());
|
||||||
|
|
||||||
auto mesh = pxr::UsdGeomMesh::Get(
|
auto mesh =
|
||||||
stage, SdfPath("/mesh_test/test_body/test_body/mesh/Mesh"));
|
pxr::UsdGeomMesh::Get(stage, SdfPath("/mesh_test/test_body/mesh/Mesh"));
|
||||||
ASSERT_TRUE(mesh);
|
ASSERT_TRUE(mesh);
|
||||||
pxr::VtArray<int> face_vertex_counts;
|
pxr::VtArray<int> face_vertex_counts;
|
||||||
mesh.GetFaceVertexCountsAttr().Get(&face_vertex_counts);
|
mesh.GetFaceVertexCountsAttr().Get(&face_vertex_counts);
|
||||||
@@ -357,9 +358,9 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBody) {
|
|||||||
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
|
pxr::SdfLayerRefPtr layer = LoadLayer(kXml);
|
||||||
|
|
||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
|
|
||||||
EXPECT_PRIM_VALID(stage, "/body_test");
|
EXPECT_PRIM_VALID(stage, "/body_test");
|
||||||
EXPECT_PRIM_VALID(stage, "/body_test/test_body");
|
EXPECT_PRIM_VALID(stage, "/body_test/test_body");
|
||||||
EXPECT_PRIM_VALID(stage, "/body_test/test_body/test_body");
|
|
||||||
EXPECT_PRIM_VALID(stage, "/body_test/test_body/test_body_2");
|
EXPECT_PRIM_VALID(stage, "/body_test/test_body/test_body_2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,10 +382,9 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestBasicParenting) {
|
|||||||
|
|
||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root");
|
EXPECT_PRIM_VALID(stage, "/test/root");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/root");
|
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/root_body_1");
|
EXPECT_PRIM_VALID(stage, "/test/root/root_body_1");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/root_body_2");
|
EXPECT_PRIM_VALID(stage, "/test/root/root_body_2");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/root_body_3");
|
EXPECT_PRIM_VALID(stage, "/test/root/root_body_2/root_body_3");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestJointsDoNotAffectParenting) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestJointsDoNotAffectParenting) {
|
||||||
@@ -412,9 +412,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestJointsDoNotAffectParenting) {
|
|||||||
|
|
||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root");
|
EXPECT_PRIM_VALID(stage, "/test/root");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/root");
|
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/middle");
|
EXPECT_PRIM_VALID(stage, "/test/root/middle");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/root/tet");
|
EXPECT_PRIM_VALID(stage, "/test/root/middle/tet");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestKindAuthoring) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestKindAuthoring) {
|
||||||
@@ -443,9 +442,9 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestKindAuthoring) {
|
|||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_KIND(stage, "/test", pxr::KindTokens->group);
|
EXPECT_PRIM_KIND(stage, "/test", pxr::KindTokens->group);
|
||||||
EXPECT_PRIM_KIND(stage, "/test/root", pxr::KindTokens->component);
|
EXPECT_PRIM_KIND(stage, "/test/root", pxr::KindTokens->component);
|
||||||
EXPECT_PRIM_KIND(stage, "/test/root/root", pxr::KindTokens->subcomponent);
|
|
||||||
EXPECT_PRIM_KIND(stage, "/test/root/middle", pxr::KindTokens->subcomponent);
|
EXPECT_PRIM_KIND(stage, "/test/root/middle", pxr::KindTokens->subcomponent);
|
||||||
EXPECT_PRIM_KIND(stage, "/test/root/tet", pxr::KindTokens->subcomponent);
|
EXPECT_PRIM_KIND(stage, "/test/root/middle/tet",
|
||||||
|
pxr::KindTokens->subcomponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestGeomsPrims) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestGeomsPrims) {
|
||||||
@@ -936,28 +935,23 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsAuthored) {
|
|||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_VALID(stage, "/test/box_site");
|
EXPECT_PRIM_VALID(stage, "/test/box_site");
|
||||||
EXPECT_PRIM_IS_A(stage, "/test/box_site", pxr::UsdGeomCube);
|
EXPECT_PRIM_IS_A(stage, "/test/box_site", pxr::UsdGeomCube);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/box_site", MjcPhysicsSiteAPI);
|
EXPECT_PRIM_API_APPLIED(stage, "/test/box_site", pxr::MjcPhysicsSiteAPI);
|
||||||
|
EXPECT_PRIM_VALID(stage, "/test/ball/sphere_site");
|
||||||
EXPECT_PRIM_VALID(stage, "/test/ball/ball/sphere_site");
|
EXPECT_PRIM_IS_A(stage, "/test/ball/sphere_site", pxr::UsdGeomSphere);
|
||||||
EXPECT_PRIM_IS_A(stage, "/test/ball/ball/sphere_site", pxr::UsdGeomSphere);
|
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/sphere_site",
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/ball/sphere_site",
|
pxr::MjcPhysicsSiteAPI);
|
||||||
MjcPhysicsSiteAPI);
|
EXPECT_PRIM_VALID(stage, "/test/ball/capsule_site");
|
||||||
|
EXPECT_PRIM_IS_A(stage, "/test/ball/capsule_site", pxr::UsdGeomCapsule);
|
||||||
EXPECT_PRIM_VALID(stage, "/test/ball/ball/capsule_site");
|
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/capsule_site",
|
||||||
EXPECT_PRIM_IS_A(stage, "/test/ball/ball/capsule_site", pxr::UsdGeomCapsule);
|
pxr::MjcPhysicsSiteAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/ball/capsule_site",
|
EXPECT_PRIM_VALID(stage, "/test/ball/cylinder_site");
|
||||||
MjcPhysicsSiteAPI);
|
EXPECT_PRIM_IS_A(stage, "/test/ball/cylinder_site", pxr::UsdGeomCylinder);
|
||||||
|
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/cylinder_site",
|
||||||
EXPECT_PRIM_VALID(stage, "/test/ball/ball/cylinder_site");
|
pxr::MjcPhysicsSiteAPI);
|
||||||
EXPECT_PRIM_IS_A(stage, "/test/ball/ball/cylinder_site",
|
EXPECT_PRIM_VALID(stage, "/test/ball/ellipsoid_site");
|
||||||
pxr::UsdGeomCylinder);
|
EXPECT_PRIM_IS_A(stage, "/test/ball/ellipsoid_site", pxr::UsdGeomSphere);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/ball/cylinder_site",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/ellipsoid_site",
|
||||||
MjcPhysicsSiteAPI);
|
pxr::MjcPhysicsSiteAPI);
|
||||||
|
|
||||||
EXPECT_PRIM_VALID(stage, "/test/ball/ball/ellipsoid_site");
|
|
||||||
EXPECT_PRIM_IS_A(stage, "/test/ball/ball/ellipsoid_site", pxr::UsdGeomSphere);
|
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/ball/ball/ellipsoid_site",
|
|
||||||
MjcPhysicsSiteAPI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsPurpose) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsPurpose) {
|
||||||
@@ -965,13 +959,13 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestSitePrimsPurpose) {
|
|||||||
|
|
||||||
auto stage = pxr::UsdStage::Open(layer);
|
auto stage = pxr::UsdStage::Open(layer);
|
||||||
EXPECT_PRIM_PURPOSE(stage, "/test/box_site", pxr::UsdGeomTokens->guide);
|
EXPECT_PRIM_PURPOSE(stage, "/test/box_site", pxr::UsdGeomTokens->guide);
|
||||||
EXPECT_PRIM_PURPOSE(stage, "/test/ball/ball/sphere_site",
|
EXPECT_PRIM_PURPOSE(stage, "/test/ball/sphere_site",
|
||||||
pxr::UsdGeomTokens->guide);
|
pxr::UsdGeomTokens->guide);
|
||||||
EXPECT_PRIM_PURPOSE(stage, "/test/ball/ball/capsule_site",
|
EXPECT_PRIM_PURPOSE(stage, "/test/ball/capsule_site",
|
||||||
pxr::UsdGeomTokens->guide);
|
pxr::UsdGeomTokens->guide);
|
||||||
EXPECT_PRIM_PURPOSE(stage, "/test/ball/ball/cylinder_site",
|
EXPECT_PRIM_PURPOSE(stage, "/test/ball/cylinder_site",
|
||||||
pxr::UsdGeomTokens->guide);
|
pxr::UsdGeomTokens->guide);
|
||||||
EXPECT_PRIM_PURPOSE(stage, "/test/ball/ball/ellipsoid_site",
|
EXPECT_PRIM_PURPOSE(stage, "/test/ball/ellipsoid_site",
|
||||||
pxr::UsdGeomTokens->guide);
|
pxr::UsdGeomTokens->guide);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -981,9 +975,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsToggleSdfFormatArg) {
|
|||||||
// Test that the default is no physics.
|
// Test that the default is no physics.
|
||||||
auto stage_no_physics = pxr::UsdStage::Open(xml_path);
|
auto stage_no_physics = pxr::UsdStage::Open(xml_path);
|
||||||
EXPECT_THAT(stage_no_physics, testing::NotNull());
|
EXPECT_THAT(stage_no_physics, testing::NotNull());
|
||||||
EXPECT_PRIM_VALID(stage_no_physics, "/mesh_test/test_body/test_body");
|
EXPECT_PRIM_VALID(stage_no_physics, "/mesh_test/test_body");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage_no_physics,
|
EXPECT_PRIM_API_NOT_APPLIED(stage_no_physics, "/mesh_test/test_body",
|
||||||
"/mesh_test/test_body/test_body",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
|
|
||||||
// Then test that the physics flag enables physics.
|
// Then test that the physics flag enables physics.
|
||||||
@@ -992,8 +985,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsToggleSdfFormatArg) {
|
|||||||
auto stage_with_physics = pxr::UsdStage::Open(xml_path_physics_flag);
|
auto stage_with_physics = pxr::UsdStage::Open(xml_path_physics_flag);
|
||||||
EXPECT_THAT(stage_with_physics, testing::NotNull());
|
EXPECT_THAT(stage_with_physics, testing::NotNull());
|
||||||
|
|
||||||
EXPECT_PRIM_VALID(stage_with_physics, "/mesh_test/test_body/test_body");
|
EXPECT_PRIM_VALID(stage_with_physics, "/mesh_test/test_body");
|
||||||
EXPECT_PRIM_API_APPLIED(stage_with_physics, "/mesh_test/test_body/test_body",
|
EXPECT_PRIM_API_APPLIED(stage_with_physics, "/mesh_test/test_body",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,23 +1012,21 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsRigidBody) {
|
|||||||
EXPECT_THAT(stage, testing::NotNull());
|
EXPECT_THAT(stage, testing::NotNull());
|
||||||
EXPECT_PRIM_VALID(stage, "/physics_test");
|
EXPECT_PRIM_VALID(stage, "/physics_test");
|
||||||
EXPECT_PRIM_VALID(stage, "/physics_test/test_body");
|
EXPECT_PRIM_VALID(stage, "/physics_test/test_body");
|
||||||
EXPECT_PRIM_VALID(stage, "/physics_test/test_body/test_body");
|
|
||||||
// USD does not allow nested rigidbodies so we put them as siblings to the
|
|
||||||
// first body in the hierarchy.
|
|
||||||
EXPECT_PRIM_VALID(stage, "/physics_test/test_body/test_body_2");
|
EXPECT_PRIM_VALID(stage, "/physics_test/test_body/test_body_2");
|
||||||
|
|
||||||
// The parent containing the body should not have the RigidBodyAPI applied.
|
EXPECT_PRIM_API_APPLIED(stage, "/physics_test/test_body",
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/physics_test/test_body",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
|
||||||
|
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/physics_test/test_body/test_body",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
|
EXPECT_PRIM_API_APPLIED(stage, "/physics_test/test_body",
|
||||||
|
pxr::UsdPhysicsArticulationRootAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/physics_test/test_body/test_body_2",
|
EXPECT_PRIM_API_APPLIED(stage, "/physics_test/test_body/test_body_2",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
|
|
||||||
|
// Only the root body should have the articulation API applied.
|
||||||
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/physics_test/test_body/test_body_2",
|
||||||
|
pxr::UsdPhysicsArticulationRootAPI);
|
||||||
|
|
||||||
// Geoms should not have RigidBodyAPI applied either.
|
// Geoms should not have RigidBodyAPI applied either.
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage,
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/physics_test/test_body/test_geom",
|
||||||
"/physics_test/test_body/test_body/test_geom",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage,
|
EXPECT_PRIM_API_NOT_APPLIED(stage,
|
||||||
"/physics_test/test_body/test_body_2/test_geom_2",
|
"/physics_test/test_body/test_body_2/test_geom_2",
|
||||||
@@ -1093,22 +1084,22 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsColliders) {
|
|||||||
//
|
//
|
||||||
// ground [collider]
|
// ground [collider]
|
||||||
//
|
//
|
||||||
// body_0/body_0 [rigidbody]
|
// body_0 [rigidbody]
|
||||||
// body_0/body_0/body_0_col [collider]
|
// body_0/body_0_col [collider]
|
||||||
//
|
//
|
||||||
// body_0/body_0_0 [rigidbody] <-- USD reparents nested rigid bodies
|
// body_0/body_0_0 [rigidbody]
|
||||||
// body_0/body_0/body_0_0/body_0_0_col [collider]
|
// body_0/body_0_0/body_0_0_col [collider]
|
||||||
//
|
//
|
||||||
// body_1/body_1 [rigidbody]
|
// body_1 [rigidbody]
|
||||||
// body_1/body_1/body_1_col_0 [collider]
|
// body_1/body_1_col_0 [collider]
|
||||||
// body_1/body_1/body_1_col_1 [collider]
|
// body_1/body_1_col_1 [collider]
|
||||||
//
|
//
|
||||||
// body_2/body_2 [rigidbody]
|
// body_2 [rigidbody]
|
||||||
// body_2/body_2/body_2_nocol []
|
// body_2/body_2_nocol []
|
||||||
//
|
//
|
||||||
// body_3/body_3 [rigidbody]
|
// body_3 [rigidbody]
|
||||||
// body_3/body_3/body_3_col [] <-- Intermediate prim for mesh instancing
|
// body_3/body_3_col [] <-- Intermediate prim for mesh instancing
|
||||||
// body_3/body_3/body_3_col/Mesh [collider, mesh collider]
|
// body_3/body_3_col/Mesh [collider, mesh collider]
|
||||||
|
|
||||||
// ground [collider] (Static collider)
|
// ground [collider] (Static collider)
|
||||||
EXPECT_PRIM_VALID(stage, "/test/ground");
|
EXPECT_PRIM_VALID(stage, "/test/ground");
|
||||||
@@ -1116,19 +1107,6 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsColliders) {
|
|||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/ground", pxr::UsdPhysicsCollisionAPI);
|
EXPECT_PRIM_API_APPLIED(stage, "/test/ground", pxr::UsdPhysicsCollisionAPI);
|
||||||
|
|
||||||
// body_0/body_0 [rigidbody]
|
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_0/body_0");
|
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_0/body_0",
|
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
|
||||||
// body_0/body_0/body_0_col [collider]
|
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_0/body_0/body_0_col");
|
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_0/body_0/body_0_col",
|
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0/body_0_col",
|
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
|
||||||
|
|
||||||
// body_0/body_0_0 [rigidbody] (Nested body - reparented)
|
// body_0/body_0_0 [rigidbody] (Nested body - reparented)
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_0/body_0_0");
|
EXPECT_PRIM_VALID(stage, "/test/body_0/body_0_0");
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0_0",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0_0",
|
||||||
@@ -1142,61 +1120,58 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsColliders) {
|
|||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0_0/body_0_0_col",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_0/body_0_0/body_0_0_col",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
|
|
||||||
// body_1/body_1 [rigidbody]
|
// body_1 [rigidbody]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_1/body_1");
|
EXPECT_PRIM_VALID(stage, "/test/body_1");
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1/body_1",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1", pxr::UsdPhysicsRigidBodyAPI);
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1",
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1/body_1",
|
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
// body_1/body_1/body_1_col_0 [collider]
|
// body_1/body_1_col_0 [collider]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_1/body_1/body_1_col_0");
|
EXPECT_PRIM_VALID(stage, "/test/body_1/body_1_col_0");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1/body_1/body_1_col_0",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1/body_1_col_0",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1/body_1/body_1_col_0",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1/body_1_col_0",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
// body_1/body_1/body_1_col_1 [collider]
|
// body_1/body_1_col_1 [collider]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_1/body_1/body_1_col_1");
|
EXPECT_PRIM_VALID(stage, "/test/body_1/body_1_col_1");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1/body_1/body_1_col_1",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_1/body_1_col_1",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1/body_1/body_1_col_1",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_1/body_1_col_1",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
|
|
||||||
// body_2/body_2 [rigidbody]
|
// body_2 [rigidbody]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_2/body_2");
|
EXPECT_PRIM_VALID(stage, "/test/body_2");
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_2/body_2",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_2", pxr::UsdPhysicsRigidBodyAPI);
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2",
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2/body_2",
|
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
// body_2/body_2/body_2_nocol [] (No physics APIs applied)
|
// body_2/body_2_nocol [] (No physics APIs applied)
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_2/body_2/body_2_nocol");
|
EXPECT_PRIM_VALID(stage, "/test/body_2/body_2_nocol");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2/body_2/body_2_nocol",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2/body_2_nocol",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2/body_2/body_2_nocol",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_2/body_2_nocol",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
|
|
||||||
// body_3/body_3 [rigidbody]
|
// body_3 [rigidbody]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_3/body_3");
|
EXPECT_PRIM_VALID(stage, "/test/body_3");
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3/body_3",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3", pxr::UsdPhysicsRigidBodyAPI);
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3",
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3",
|
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
// body_3/body_3/body_3_col [] (Intermediate prim for mesh instancing)
|
// body_3/body_3_col [] (Intermediate prim for mesh instancing)
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_3/body_3/body_3_col");
|
EXPECT_PRIM_VALID(stage, "/test/body_3/body_3_col");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3/body_3_col",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3_col",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3/body_3_col",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3_col",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
// body_3/body_3/body_3_col/Mesh [collider, mesh collider]
|
// body_3/body_3_col/Mesh [collider, mesh collider]
|
||||||
EXPECT_PRIM_VALID(stage, "/test/body_3/body_3/body_3_col/Mesh");
|
EXPECT_PRIM_VALID(stage, "/test/body_3/body_3_col/Mesh");
|
||||||
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3/body_3_col/Mesh",
|
EXPECT_PRIM_API_NOT_APPLIED(stage, "/test/body_3/body_3_col/Mesh",
|
||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3/body_3/body_3_col/Mesh",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3/body_3_col/Mesh",
|
||||||
pxr::UsdPhysicsCollisionAPI);
|
pxr::UsdPhysicsCollisionAPI);
|
||||||
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3/body_3/body_3_col/Mesh",
|
EXPECT_PRIM_API_APPLIED(stage, "/test/body_3/body_3_col/Mesh",
|
||||||
pxr::UsdPhysicsMeshCollisionAPI);
|
pxr::UsdPhysicsMeshCollisionAPI);
|
||||||
ExpectAttributeEqual(
|
ExpectAttributeEqual(stage,
|
||||||
stage, "/test/body_3/body_3/body_3_col/Mesh.physics:approximation",
|
"/test/body_3/body_3_col/Mesh.physics:approximation",
|
||||||
pxr::UsdPhysicsTokens->convexHull);
|
pxr::UsdPhysicsTokens->convexHull);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
Reference in New Issue
Block a user