Skip to content

Commit 14972d2

Browse files
havesscopybara-github
authored andcommitted
Add mj_loadUSD function. Change simulate to use that instead of manual spec compilation.
PiperOrigin-RevId: 780608874 Change-Id: I333238c756fe76b371518a7cdf9452b93da3540a
1 parent e507e31 commit 14972d2

File tree

8 files changed

+121
-48
lines changed

8 files changed

+121
-48
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ if(MUJOCO_BUILD_EXAMPLES)
202202
endif()
203203

204204
if(MUJOCO_WITH_USD)
205+
target_compile_definitions(mujoco PUBLIC mjUSEUSD)
205206
add_subdirectory(src/experimental/usd)
206207
endif()
207208

include/mujoco/experimental/usd/usd.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
#include <mujoco/mujoco.h>
1919
#include <pxr/usd/usd/common.h>
2020

21+
// Given a USD file parse to a spec, then compile and return the low-level model.
22+
//
23+
// Particular care is taken for physics data to be lossless but visual
24+
// data such as materials may be lossy.
25+
MJAPI mjModel* mj_loadUSD(const char* filename, const mjVFS* vfs, char* error, int error_sz);
26+
2127
// Given a USD stage, this function will do a best effort conversion to
2228
// mjSpec.
2329
//

simulate/CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ if(SIMULATE_BUILD_EXECUTABLE)
177177
if (MUJOCO_WITH_USD)
178178
target_link_libraries(
179179
simulate
180-
mujoco::usd
181180
mujoco::usd::mjcf
182181
)
183182
endif()
@@ -249,7 +248,7 @@ if(SIMULATE_BUILD_EXECUTABLE)
249248
)
250249

251250
if (MUJOCO_WITH_USD)
252-
target_compile_definitions(simulate PUBLIC SIMULATE_WITH_USD)
251+
target_compile_definitions(simulate PUBLIC mjUSEUSD)
253252

254253
# Add support to RPATH for the samples.
255254
target_add_rpath(

simulate/main.cc

Lines changed: 4 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,8 @@
2525
#include <string>
2626
#include <thread>
2727

28-
#if defined(SIMULATE_WITH_USD)
28+
#if defined(mjUSEUSD)
2929
#include <mujoco/experimental/usd/usd.h>
30-
#include <pxr/pxr.h>
31-
#include <pxr/usd/usd/common.h>
32-
#include <pxr/usd/usd/stage.h>
3330
#endif
3431
#include <mujoco/mujoco.h>
3532
#include "glfw_adapter.h"
@@ -244,34 +241,10 @@ mjModel* LoadModel(const char* file, mj::Simulate& sim) {
244241
if (!mnew) {
245242
mju::strcpy_arr(loadError, "could not load binary model");
246243
}
247-
#if defined(SIMULATE_WITH_USD)
244+
#if defined(mjUSEUSD)
248245
} else if (extension == ".usda" || extension == ".usd" ||
249246
extension == ".usdc" || extension == ".usdz" ) {
250-
auto stage = pxr::UsdStage::Open(filename);
251-
if (!stage) {
252-
mju::strcpy_arr(loadError, "could not open USD stage");
253-
} else {
254-
mjSpec* spec = mj_parseUSDStage(stage);
255-
if (!spec) {
256-
mju::strcpy_arr(loadError, "could not parse USD stage to mjSpec");
257-
} else {
258-
mjModel* model = mj_compile(spec, nullptr);
259-
if (!model) {
260-
mju::strcpy_arr(loadError,
261-
"could not compile USD parsed mjSpec to mjModel:\n");
262-
mju::strcat_arr(loadError, mjs_getError(spec));
263-
} else {
264-
// handle compile warning
265-
if (mjs_isWarning(spec)) {
266-
mju::strcpy_arr(
267-
loadError,
268-
"warning while compiling USD parsed mjSpec to mjModel:\n");
269-
mju::strcat_arr(loadError, mjs_getError(spec));
270-
}
271-
}
272-
mnew = model;
273-
}
274-
}
247+
mnew = mj_loadUSD(filename, nullptr, loadError, kErrorLength);
275248
#endif
276249
} else {
277250
mnew = mj_loadXML(filename, nullptr, loadError, kErrorLength);
@@ -537,7 +510,7 @@ int main(int argc, char** argv) {
537510
// scan for libraries in the plugin directory to load additional plugins
538511
scanPluginLibraries();
539512

540-
#if defined(SIMULATE_WITH_USD)
513+
#if defined(mjUSEUSD)
541514
// If USD is used, print the version.
542515
std::printf("OpenUSD version v%d.%02d\n", PXR_MINOR_VERSION, PXR_PATCH_VERSION);
543516
#endif

src/experimental/usd/CMakeLists.txt

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
# Plugin target names (used for library and plugInfo.json)
1717
set(MJCF_PLUGIN_TARGET_NAME usdMjcf)
1818
set(MJC_PHYSICS_PLUGIN_TARGET_NAME mjcPhysics)
19-
set(MJ_USD_TARGET_NAME mj_usd)
2019

2120
# Installation directory for USD plugins
2221
set(MJ_USD_INSTALL_DIR_LIB ${CMAKE_INSTALL_LIBDIR}/mujocoUsd)
@@ -187,14 +186,12 @@ set_target_properties(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PROPERTIES
187186
${DEFAULT_CXX_VISIBILITY_PROPS}
188187
)
189188
target_include_directories(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PUBLIC
190-
"${CMAKE_CURRENT_SOURCE_DIR}/mjcPhysics"
189+
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../../include>
191190
)
192191

193192
## mj_usd
194193

195-
add_library(${MJ_USD_TARGET_NAME} SHARED)
196-
add_library(mujoco::usd ALIAS ${MJ_USD_TARGET_NAME})
197-
target_sources(${MJ_USD_TARGET_NAME} PRIVATE
194+
target_sources(mujoco PRIVATE
198195
kinematic_tree.cc
199196
kinematic_tree.h
200197
layer_sink.cc
@@ -212,8 +209,6 @@ if (USD_DIR)
212209

213210
target_link_libraries(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE
214211
${OPENUSD_CORE_LIBS}
215-
mujoco
216-
tinyxml2
217212
)
218213

219214
target_link_libraries(${MJCF_PLUGIN_TARGET_NAME} PRIVATE
@@ -223,10 +218,8 @@ if (USD_DIR)
223218
${MJC_PHYSICS_PLUGIN_TARGET_NAME}
224219
)
225220

226-
target_link_libraries(${MJ_USD_TARGET_NAME} PUBLIC
221+
target_link_libraries(mujoco PUBLIC
227222
${OPENUSD_CORE_LIBS}
228-
mujoco
229-
tinyxml2
230223
${MJC_PHYSICS_PLUGIN_TARGET_NAME}
231224
)
232225
elseif (HOUDINI_HFS_DIR)
@@ -237,11 +230,9 @@ elseif (HOUDINI_HFS_DIR)
237230
# so we need to manually link all the required libraries.
238231
configure_houdini_target(${MJC_PHYSICS_PLUGIN_TARGET_NAME} PRIVATE PRIVATE)
239232
configure_houdini_target(${MJCF_PLUGIN_TARGET_NAME} PRIVATE PRIVATE)
240-
configure_houdini_target(${MJ_USD_TARGET_NAME} PUBLIC PUBLIC)
241233

242234
# Re-add inter-plugin dependencies after Houdini-specific linking
243235
target_link_libraries(${MJCF_PLUGIN_TARGET_NAME} PRIVATE ${MJC_PHYSICS_PLUGIN_TARGET_NAME})
244-
target_link_libraries(${MJ_USD_TARGET_NAME} PUBLIC ${MJC_PHYSICS_PLUGIN_TARGET_NAME})
245236

246237
endif()
247238

@@ -272,6 +263,6 @@ install(FILES
272263
install(TARGETS
273264
${MJCF_PLUGIN_TARGET_NAME}
274265
${MJC_PHYSICS_PLUGIN_TARGET_NAME}
275-
${MJ_USD_TARGET_NAME}
266+
EXPORT ${PROJECT_NAME}
276267
LIBRARY DESTINATION ${MJ_USD_INSTALL_DIR_LIB}
277268
)

src/experimental/usd/layer_sink.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@
4141

4242
PXR_NAMESPACE_OPEN_SCOPE
4343
TF_DEFINE_PRIVATE_TOKENS(_layer_sink_tokens,
44-
((xformOpTransform,
45-
"xformOp:transform:mujoco"))(Xform));
44+
((xformOpTransform, "xformOp:transform:mujoco")));
4645
PXR_NAMESPACE_CLOSE_SCOPE
4746

4847
namespace {

src/xml/xml_api.cc

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#include "xml/xml.h"
3535
#include "xml/xml_native_reader.h"
3636
#include "xml/xml_util.h"
37+
#if defined(mjUSEUSD)
38+
#include <mujoco/experimental/usd/usd.h>
39+
#include <pxr/usd/usd/stage.h>
40+
#endif
3741

3842
//---------------------------------- Globals -------------------------------------------------------
3943

@@ -126,7 +130,36 @@ mjModel* mj_loadXML(const char* filename, const mjVFS* vfs,
126130
return m;
127131
}
128132

133+
#if defined(mjUSEUSD)
134+
// parse USD file, compile it, and return low-level model.
135+
// if vfs is not NULL, look up files in vfs before reading from disk
136+
// error can be NULL; otherwise assumed to have size error_sz
137+
mjModel* mj_loadUSD(const char* filename, const mjVFS* vfs, char* error, int error_sz) {
138+
auto stage = pxr::UsdStage::Open(filename);
139+
140+
if (stage == nullptr) {
141+
mjCopyError(error, "Failed to load USD stage from file.", error_sz);
142+
return nullptr;
143+
}
144+
145+
// Parse USD into mjSpec.
146+
std::unique_ptr<mjSpec, std::function<void(mjSpec*)> > spec(
147+
mj_parseUSDStage(stage),
148+
[](mjSpec* s) {
149+
mj_deleteSpec(s);
150+
});
129151

152+
// Compile new model.
153+
mjModel* m = mj_compile(spec.get(), vfs);
154+
if (!m) {
155+
mjCopyError(error, mjs_getError(spec.get()), error_sz);
156+
return nullptr;
157+
}
158+
159+
GetGlobalModel().Set(spec.release());
160+
return m;
161+
}
162+
#endif
130163

131164
// update XML data structures with info from low-level model, save as MJCF
132165
// returns 1 if successful, 0 otherwise
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#usda 1.0
2+
(
3+
endTimeCode = 1
4+
framesPerSecond = 24
5+
metersPerUnit = 1
6+
startTimeCode = 1
7+
timeCodesPerSecond = 24
8+
upAxis = "Y"
9+
)
10+
11+
def Xform "World"
12+
{
13+
def Xform "Axle" (
14+
prepend apiSchemas = ["PhysicsRigidBodyAPI", "PhysicsArticulationRootAPI"]
15+
)
16+
{
17+
matrix4d xformOp:transform:set_initial_pos = ( (1, 0, 0, 0), (0, 0.9999197811020019, -0.012666150201413267, 0), (0, 0.012666150201413267, 0.9999197811020019, 0), (0, 0.012296309694647789, 0.970723032951355, 1) )
18+
uniform token[] xformOpOrder = ["xformOp:transform:set_initial_pos"]
19+
20+
def Xform "Rod" (
21+
prepend apiSchemas = ["PhysicsRigidBodyAPI"]
22+
)
23+
{
24+
matrix4d xformOp:transform:set_initial_rod_pos = ( (1, 0, 0, 0), (0, 0.3255001489278845, 0.9455419890453967, 0), (0, -0.9455419890453967, 0.3255001489278845, 0), (0, 0.47277099452269833, -0.1627500744639423, 1) )
25+
uniform token[] xformOpOrder = ["xformOp:transform:set_initial_rod_pos"]
26+
27+
def Cylinder "Geometry" (
28+
prepend apiSchemas = ["PhysicsCollisionAPI"]
29+
)
30+
{
31+
token axis = "Z"
32+
float3[] extent = [(-0.01, -0.01, -0.5), (0.01, 0.01, 0.5)]
33+
double height = 1
34+
double radius = 0.01
35+
matrix4d xformOp:transform = ( (1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, -0.03546595561524429, 1) )
36+
uniform token[] xformOpOrder = ["xformOp:transform"]
37+
}
38+
39+
def PhysicsRevoluteJoint "HingeJoint" (
40+
prepend apiSchemas = ["PhysicsActuatorAPI"]
41+
)
42+
{
43+
rel physics:body0 = </World/Axle>
44+
rel physics:body1 = </World/Axle/Rod>
45+
point3f physics:localPos0 = (0, 0, 0)
46+
point3f physics:localPos1 = (0, 0, 0.5)
47+
quatf physics:localRot0 = (0, 1, 0, 0)
48+
quatf physics:localRot1 = (0, 1, 0, 0)
49+
}
50+
}
51+
52+
def Cylinder "Geometry" (
53+
prepend apiSchemas = ["PhysicsCollisionAPI"]
54+
)
55+
{
56+
token axis = "Z"
57+
float3[] extent = [(-0.01, -0.01, -0.1), (0.01, 0.01, 0.1)]
58+
double height = 0.2
59+
double radius = 0.01
60+
matrix4d xformOp:transform = ( (0, 0, -1, 0), (0, 1, -0, 0), (1, 0, -0, 0), (0, 0, -0, 1) )
61+
uniform token[] xformOpOrder = ["xformOp:transform"]
62+
}
63+
64+
def PhysicsFixedJoint "FixedJoint"
65+
{
66+
rel physics:body0 = None
67+
rel physics:body1 = </World/Axle>
68+
}
69+
}
70+
}
71+

0 commit comments

Comments
 (0)