Add support for mjcPhysics keyframes to USD interop.

PiperOrigin-RevId: 778552679
Change-Id: I04026599f7a2836e3fe1cf0d553bcc86a5795f98
This commit is contained in:
Sam Haves
2025-07-02 10:16:42 -07:00
committed by Copybara-Service
parent 072b327430
commit 1d613b9b9a
7 changed files with 236 additions and 10 deletions
@@ -48,6 +48,7 @@
#include <pxr/usd/usd/prim.h>
#include <pxr/usd/usd/primRange.h> // IWYU pragma: keep, used for TraverseAll
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usd/timeCode.h>
#include <pxr/usd/usdGeom/capsule.h>
#include <pxr/usd/usdGeom/cube.h>
#include <pxr/usd/usdGeom/cylinder.h>
@@ -1993,6 +1994,38 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestPhysicsUnsupportedJoint) {
EXPECT_PRIM_INVALID(stage, "/test/parent/ball_joint");
}
TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsKeyframe) {
static constexpr char xml[] = R"(
<mujoco model="test">
<worldbody>
<frame name="frame"/>
<body name="body">
<joint/>
<geom size="0.1"/>
</body>
</worldbody>
<keyframe>
<key name="home" qpos="1"/>
<key time="1" qpos="2"/>
<key time="2" qpos="3"/>
</keyframe>
</mujoco>)";
auto stage = OpenStageWithPhysics(xml);
EXPECT_PRIM_VALID(stage, "/test/Keyframes/home");
EXPECT_PRIM_VALID(stage, "/test/Keyframes/Keyframe");
ExpectAttributeEqual(stage, "/test/Keyframes/home.mjc:qpos",
pxr::VtDoubleArray({1}));
// Check time samples are correctly authored.
ExpectAttributeEqual(stage, "/test/Keyframes/Keyframe.mjc:qpos",
pxr::VtDoubleArray({2}), pxr::UsdTimeCode(1.0));
ExpectAttributeEqual(stage, "/test/Keyframes/Keyframe.mjc:qpos",
pxr::VtDoubleArray({3}), pxr::UsdTimeCode(2.0));
}
} // namespace
} // namespace usd
} // namespace mujoco
+3 -1
View File
@@ -30,6 +30,7 @@
#include <pxr/usd/usd/common.h>
#include <pxr/usd/usd/modelAPI.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usd/timeCode.h>
#include <pxr/usd/usdGeom/mesh.h>
#include <pxr/usd/usdGeom/primvarsAPI.h>
namespace mujoco {
@@ -59,7 +60,8 @@ pxr::UsdStageRefPtr OpenStageWithPhysics(const std::string& xml) {
template <>
void ExpectAttributeEqual<pxr::SdfAssetPath>(pxr::UsdStageRefPtr stage,
pxr::SdfPath path,
const pxr::SdfAssetPath& value) {
const pxr::SdfAssetPath& value,
const pxr::UsdTimeCode time) {
auto attr = stage->GetAttributeAtPath(path);
EXPECT_TRUE(attr.IsValid());
pxr::SdfAssetPath attr_value;
+12 -9
View File
@@ -26,6 +26,7 @@
#include <pxr/usd/usd/common.h>
#include <pxr/usd/usd/modelAPI.h>
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usd/timeCode.h>
#define EXPECT_PRIM_VALID(stage, path) \
EXPECT_TRUE((stage)->GetPrimAtPath(SdfPath(path)).IsValid());
@@ -101,20 +102,22 @@ pxr::SdfLayerRefPtr LoadLayer(
pxr::UsdStageRefPtr OpenStageWithPhysics(const std::string& xml);
template <typename T>
void ExpectAttributeEqual(pxr::UsdStageRefPtr stage, pxr::SdfPath path,
const T& value) {
void ExpectAttributeEqual(
pxr::UsdStageRefPtr stage, pxr::SdfPath path, const T& value,
const pxr::UsdTimeCode time = pxr::UsdTimeCode::Default()) {
auto attr = stage->GetAttributeAtPath(pxr::SdfPath(path));
EXPECT_TRUE(attr.IsValid()) << "Attribute " << path << " is not valid";
T attr_value;
attr.Get(&attr_value);
attr.Get(&attr_value, time);
EXPECT_EQ(attr_value, value) << "Attribute " << path << " has value "
<< attr_value << ". Expected: " << value;
}
template <typename T>
void ExpectAttributeEqual(pxr::UsdStageRefPtr stage, const char* path,
const T& value) {
ExpectAttributeEqual(stage, pxr::SdfPath(path), value);
void ExpectAttributeEqual(
pxr::UsdStageRefPtr stage, const char* path, const T& value,
const pxr::UsdTimeCode time = pxr::UsdTimeCode::Default()) {
ExpectAttributeEqual(stage, pxr::SdfPath(path), value, time);
}
// Specialization for SdfAssetPath, so that we can compare only the asset path
@@ -122,9 +125,9 @@ void ExpectAttributeEqual(pxr::UsdStageRefPtr stage, const char* path,
// Otherwise the default operator== would fail because it tests for equality of
// the asset path AND the resolved path.
template <>
void ExpectAttributeEqual<pxr::SdfAssetPath>(pxr::UsdStageRefPtr stage,
pxr::SdfPath,
const pxr::SdfAssetPath& value);
void ExpectAttributeEqual<pxr::SdfAssetPath>(
pxr::UsdStageRefPtr stage, pxr::SdfPath, const pxr::SdfAssetPath& value,
pxr::UsdTimeCode time);
void ExpectAttributeHasConnection(pxr::UsdStageRefPtr stage, const char* path,
const char* connection_path);