66"""
77
88import os
9+ import time
910
1011import xml .etree .ElementTree as ET
1112import numpy as np
@@ -177,8 +178,8 @@ def compare_geoms(compared_geoms, usd_geoms, tol):
177178 assert len (compared_geoms ) == len (usd_geoms )
178179
179180 # Sort geoms by link name for consistent comparison
180- compared_geoms_sorted = sorted (compared_geoms , key = lambda g : (g .link .name , g ._idx ))
181- usd_geoms_sorted = sorted (usd_geoms , key = lambda g : (g .link .name , g ._idx ))
181+ compared_geoms_sorted = sorted (compared_geoms , key = lambda g : (g .link .name , g .idx ))
182+ usd_geoms_sorted = sorted (usd_geoms , key = lambda g : (g .link .name , g .idx ))
182183
183184 for compared_geom , usd_geom in zip (compared_geoms_sorted , usd_geoms_sorted ):
184185 assert compared_geom .type == usd_geom .type
@@ -266,9 +267,20 @@ def build_mjcf_scene(xml_path: str, scale: float):
266267 """
267268 # Create MJCF scene
268269 mjcf_scene = gs .Scene ()
269- mjcf_morph = gs .morphs .MJCF (file = xml_path , scale = scale )
270- mjcf_scene .add_entity (mjcf_morph , material = gs .materials .Rigid (rho = 1000.0 ))
270+
271+ mjcf_scene .add_entity (
272+ gs .morphs .MJCF (
273+ file = xml_path ,
274+ scale = scale ,
275+ convexify = False ,
276+ ),
277+ material = gs .materials .Rigid (
278+ rho = 1000.0 ,
279+ ),
280+ )
281+
271282 mjcf_scene .build ()
283+
272284 return mjcf_scene
273285
274286
@@ -300,18 +312,34 @@ def build_usd_scene(
300312 The USD scene
301313 """
302314 # Create USD scene
303- usd_scene = gs .Scene ()
304- usd_morph = gs .morphs .USD (
305- usd_ctx = UsdContext (usd_file , use_bake_cache = False ),
306- scale = scale ,
307- fixed = fixed ,
315+ scene = gs .Scene ()
316+
317+ kwargs = dict (
318+ morph = gs .morphs .USD (
319+ usd_ctx = UsdContext (
320+ usd_file ,
321+ use_bake_cache = False ,
322+ ),
323+ scale = scale ,
324+ fixed = fixed ,
325+ convexify = False ,
326+ ),
327+ material = gs .materials .Rigid (
328+ rho = 1000.0 ,
329+ ),
330+ vis_mode = vis_mode ,
308331 )
332+
309333 if is_stage :
310- usd_scene .add_stage (usd_morph , vis_mode = vis_mode , material = gs . materials . Rigid ( rho = 1000.0 ) )
334+ scene .add_stage (** kwargs )
311335 else :
312- usd_scene .add_entity (usd_morph , vis_mode = vis_mode , material = gs .materials .Rigid (rho = 1000.0 ))
313- usd_scene .build ()
314- return usd_scene
336+ scene .add_entity (** kwargs )
337+
338+ # Note that it is necessary to build the scene because spatial inertia of some geometries may not be specified.
339+ # In such a case, it will be estimated from the geometry during build (RigidLink._build to be specific).
340+ scene .build ()
341+
342+ return scene
315343
316344
317345def build_mesh_scene (mesh_file : str , scale : float ):
@@ -438,6 +466,7 @@ def box_plane_usd(asset_tmp_path, box_plane_mjcf: ET.ElementTree):
438466 rigid_body_api .GetKinematicEnabledAttr ().Set (False )
439467
440468 stage .Save ()
469+
441470 return usd_file
442471
443472
@@ -864,6 +893,7 @@ def spherical_joint_usd(asset_tmp_path, spherical_joint_mjcf: ET.ElementTree):
864893 joint_prim .CreateLocalPos1Attr ().Set (Gf .Vec3f (0.0 , 0.0 , 0.0 ))
865894
866895 stage .Save ()
896+
867897 return usd_file
868898
869899
@@ -883,10 +913,14 @@ def test_spherical_joint_mjcf_vs_usd(xml_path, spherical_joint_usd, scale, tol):
883913@pytest .mark .parametrize ("model_name" , ["usd/sneaker_airforce" , "usd/RoughnessTest" ])
884914@pytest .mark .skipif (not HAS_USD_SUPPORT , reason = "USD support not available" )
885915def test_usd_visual_parse (model_name , tol ):
886- glb_file = os .path .join (get_hf_dataset (pattern = f"{ model_name } .glb" ), f"{ model_name } .glb" )
887- usd_file = os .path .join (get_hf_dataset (pattern = f"{ model_name } .usdz" ), f"{ model_name } .usdz" )
916+ glb_asset_path = get_hf_dataset (pattern = f"{ model_name } .glb" )
917+ glb_file = os .path .join (glb_asset_path , f"{ model_name } .glb" )
918+ usd_asset_path = get_hf_dataset (pattern = f"{ model_name } .usdz" )
919+ usd_file = os .path .join (usd_asset_path , f"{ model_name } .usdz" )
920+
888921 mesh_scene = build_mesh_scene (glb_file , scale = 1.0 )
889922 usd_scene = build_usd_scene (usd_file , scale = 1.0 , vis_mode = "visual" , is_stage = False )
923+
890924 compare_mesh_scene (mesh_scene , usd_scene , tol = tol )
891925
892926
@@ -897,7 +931,9 @@ def test_usd_visual_parse(model_name, tol):
897931def test_usd_parse_nodegraph (usd_file ):
898932 asset_path = get_hf_dataset (pattern = usd_file )
899933 usd_file = os .path .join (asset_path , usd_file )
934+
900935 usd_scene = build_usd_scene (usd_file , scale = 1.0 , vis_mode = "visual" , is_stage = False )
936+
901937 texture0 = usd_scene .entities [0 ].vgeoms [0 ].vmesh .surface .diffuse_texture
902938 texture1 = usd_scene .entities [0 ].vgeoms [1 ].vmesh .surface .diffuse_texture
903939 assert isinstance (texture0 , gs .textures .ColorTexture )
@@ -914,15 +950,33 @@ def test_usd_parse_nodegraph(usd_file):
914950@pytest .mark .parametrize ("backend" , [gs .cuda ])
915951@pytest .mark .skipif (not HAS_USD_SUPPORT , reason = "USD support not available" )
916952@pytest .mark .skipif (not HAS_OMNIVERSE_KIT_SUPPORT , reason = "omniverse-kit support not available" )
917- def test_usd_bake (usd_file ):
918- asset_path = get_hf_dataset (pattern = os .path .join (os .path .dirname (usd_file ), "*" ), local_dir_use_symlinks = False )
953+ def test_usd_bake (usd_file , tmp_path ):
954+ RETRY_NUM = 3 if "PYTEST_XDIST_WORKER" in os .environ else 0
955+ RETRY_DELAY = 30.0
956+
957+ asset_path = get_hf_dataset (pattern = os .path .join (os .path .dirname (usd_file ), "*" ), local_dir = tmp_path )
919958 usd_file = os .path .join (asset_path , usd_file )
920- usd_scene = build_usd_scene (usd_file , scale = 1.0 , vis_mode = "visual" , is_stage = False , fixed = True )
921-
922- success_count = 0
923- for vgeom in usd_scene .entities [0 ].vgeoms :
924- vmesh = vgeom .vmesh
925- bake_success = vmesh .metadata ["bake_success" ]
926- assert bake_success is None or bake_success
927- success_count += 1 if bake_success else 0
928- assert success_count > 0
959+
960+ # Note that bootstrapping omni-kit by multiple workers concurrently is causing failure.
961+ # There is no easy way to get around this limitation except retrying after some delay...
962+ retry_idx = 0
963+ while True :
964+ usd_scene = build_usd_scene (usd_file , scale = 1.0 , vis_mode = "visual" , is_stage = False , fixed = True )
965+
966+ is_any_baked = False
967+ for vgeom in usd_scene .entities [0 ].vgeoms :
968+ vmesh = vgeom .vmesh
969+ bake_success = vmesh .metadata ["bake_success" ]
970+ try :
971+ assert bake_success is None or bake_success
972+ except AssertionError :
973+ if retry_idx < RETRY_NUM :
974+ usd_scene .destroy ()
975+ print (f"Failed to bake usd. Trying again in { RETRY_DELAY } s..." )
976+ time .sleep (RETRY_DELAY )
977+ break
978+ raise
979+ is_any_baked |= bake_success
980+ else :
981+ assert is_any_baked
982+ break
0 commit comments