Make sure we never apply the ArticulationRoot API more than once.
PiperOrigin-RevId: 779185190 Change-Id: If441d0e2ba24191883839977b46864db2b4b8204
This commit is contained in:
committed by
Copybara-Service
parent
85ad1eec91
commit
21a852504c
@@ -18,6 +18,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -231,6 +232,8 @@ class ModelWriter {
|
|||||||
std::vector<pxr::SdfPath> joint_paths_;
|
std::vector<pxr::SdfPath> joint_paths_;
|
||||||
// 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_;
|
||||||
|
// Set of body ids that have had the articulation root API applied.
|
||||||
|
std::unordered_set<int> articulation_roots_;
|
||||||
// Whether to write physics data.
|
// Whether to write physics data.
|
||||||
bool write_physics_ = false;
|
bool write_physics_ = false;
|
||||||
|
|
||||||
@@ -1998,9 +2001,13 @@ class ModelWriter {
|
|||||||
// then we need to apply the articulation root API.
|
// then we need to apply the articulation root API.
|
||||||
if (parent_id != kWorldIndex) {
|
if (parent_id != kWorldIndex) {
|
||||||
int parent_parent_id = mjs_getId(mjs_getParent(parent->element)->element);
|
int parent_parent_id = mjs_getId(mjs_getParent(parent->element)->element);
|
||||||
if (parent_parent_id == kWorldIndex) {
|
// We guard against applying the API more than once, which can happen when
|
||||||
|
// there are multiple children.
|
||||||
|
if (parent_parent_id == kWorldIndex &&
|
||||||
|
articulation_roots_.find(parent_id) == articulation_roots_.end()) {
|
||||||
ApplyApiSchema(data_, parent_path,
|
ApplyApiSchema(data_, parent_path,
|
||||||
pxr::UsdPhysicsTokens->PhysicsArticulationRootAPI);
|
pxr::UsdPhysicsTokens->PhysicsArticulationRootAPI);
|
||||||
|
articulation_roots_.insert(parent_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
#include <pxr/usd/sdf/assetPath.h>
|
#include <pxr/usd/sdf/assetPath.h>
|
||||||
#include <pxr/usd/sdf/declareHandles.h>
|
#include <pxr/usd/sdf/declareHandles.h>
|
||||||
#include <pxr/usd/sdf/fileFormat.h>
|
#include <pxr/usd/sdf/fileFormat.h>
|
||||||
|
#include <pxr/usd/sdf/listOp.h>
|
||||||
#include <pxr/usd/sdf/path.h>
|
#include <pxr/usd/sdf/path.h>
|
||||||
#include <pxr/usd/sdf/schema.h>
|
#include <pxr/usd/sdf/schema.h>
|
||||||
#include <pxr/usd/usd/common.h>
|
#include <pxr/usd/usd/common.h>
|
||||||
@@ -49,6 +51,7 @@
|
|||||||
#include <pxr/usd/usd/primRange.h> // IWYU pragma: keep, used for TraverseAll
|
#include <pxr/usd/usd/primRange.h> // IWYU pragma: keep, used for TraverseAll
|
||||||
#include <pxr/usd/usd/stage.h>
|
#include <pxr/usd/usd/stage.h>
|
||||||
#include <pxr/usd/usd/timeCode.h>
|
#include <pxr/usd/usd/timeCode.h>
|
||||||
|
#include <pxr/usd/usd/tokens.h>
|
||||||
#include <pxr/usd/usdGeom/capsule.h>
|
#include <pxr/usd/usdGeom/capsule.h>
|
||||||
#include <pxr/usd/usdGeom/cube.h>
|
#include <pxr/usd/usdGeom/cube.h>
|
||||||
#include <pxr/usd/usdGeom/cylinder.h>
|
#include <pxr/usd/usdGeom/cylinder.h>
|
||||||
@@ -1131,6 +1134,45 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsToggleSdfFormatArg) {
|
|||||||
pxr::UsdPhysicsRigidBodyAPI);
|
pxr::UsdPhysicsRigidBodyAPI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MjcfSdfFileFormatPluginTest, TestArticulationRootAppliedOnce) {
|
||||||
|
static constexpr char kXml[] = R"(
|
||||||
|
<mujoco model="physics_test">
|
||||||
|
<worldbody>
|
||||||
|
<body name="parent" pos="0 0 0">
|
||||||
|
<geom name="parent_geom" type="sphere" size="1"/>
|
||||||
|
<body name="child_1" pos="1 0 0">
|
||||||
|
<geom name="child_1_geom" type="sphere" size="1"/>
|
||||||
|
</body>
|
||||||
|
<body name="child_2" pos="2 0 0">
|
||||||
|
<geom name="child_2_geom" type="sphere" size="1"/>
|
||||||
|
</body>
|
||||||
|
</body>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
|
||||||
|
pxr::SdfFileFormat::FileFormatArguments args;
|
||||||
|
args["usdMjcfToggleUsdPhysics"] = "true";
|
||||||
|
pxr::SdfLayerRefPtr layer = LoadLayer(kXml, args);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
// stage because duplicates are removed. So we need to check the SdfLayer
|
||||||
|
// directly to see the problem.
|
||||||
|
auto primSpec = layer->GetPrimAtPath(pxr::SdfPath("/physics_test/parent"));
|
||||||
|
EXPECT_TRUE(primSpec);
|
||||||
|
|
||||||
|
pxr::VtValue apiSchemasValue = primSpec->GetInfo(pxr::UsdTokens->apiSchemas);
|
||||||
|
const pxr::SdfTokenListOp& listOp =
|
||||||
|
apiSchemasValue.UncheckedGet<pxr::SdfTokenListOp>();
|
||||||
|
const pxr::SdfTokenListOp::ItemVector& prependedItems =
|
||||||
|
listOp.GetPrependedItems();
|
||||||
|
|
||||||
|
int count = std::count(prependedItems.begin(), prependedItems.end(),
|
||||||
|
pxr::UsdPhysicsTokens->PhysicsArticulationRootAPI);
|
||||||
|
EXPECT_EQ(count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsRigidBody) {
|
TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsRigidBody) {
|
||||||
static constexpr char kXml[] = R"(
|
static constexpr char kXml[] = R"(
|
||||||
<mujoco model="physics_test">
|
<mujoco model="physics_test">
|
||||||
|
|||||||
Reference in New Issue
Block a user