Imported MJCF not working when spawning multiple istances #2113
Replies: 3 comments 1 reply
-
Thanks for posting this. Have you reviewed the doc on instanceable assets and ensured that the robot is in instanceable format? A more detailed review of this can be found in this doc. |
Beta Was this translation helpful? Give feedback.
-
I also have the same issue... I don't think the problem is because it's not an instanceable asset, as I've set it to be instanceable when I convert it. I have a minimal reproducible environment on a branch in my fork, for a minimal simple gripper MJCF model. First I convert the MJCF XML to USD with: python scripts/tools/convert_mjcf.py simple_gripper.xml simple_gripper.usd --fix-base --import-sites --make-instanceable I added the Then I've adapted When I run However, when the training script is run (e.g. |
Beta Was this translation helpful? Give feedback.
-
Possible Solution to Fix this Issue
def undo_instanceable_xforms(asset_usd_path, source_prim_path, save_as_path=None):
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
while len(prims) > 0:
prim = prims.pop(0)
print(prim)
if prim.IsInstance():
print("This is instanceable!")
prim.SetInstanceable(False)
children_prims = prim.GetChildren()
prims = prims + children_prims
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path)
# TODO: Currently not adding the geometry to the newly created Xform.
def create_parent_xforms(asset_usd_path, source_prim_path, save_as_path=None):
""" Adds a new UsdGeom.Xform prim for each Mesh/Geometry prim under source_prim_path.
Moves material assignment to new parent prim if any exists on the Mesh/Geometry prim.
Args:
asset_usd_path (str): USD file path for asset
source_prim_path (str): USD path of root prim
save_as_path (str): USD file path for modified USD stage. Defaults to None, will save in same file.
"""
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
# edits = Usd.NamespaceEditor(stage)
edits = Sdf.BatchNamespaceEdit()
while len(prims) > 0:
prim = prims.pop(0)
print(prim)
if prim.GetTypeName() in ["Mesh", "Capsule", "Sphere", "Box", "Cone", "Torus", "Plane", "Cylinder", "Disk"]:
new_xform = UsdGeom.Xform.Define(stage, str(prim.GetPath()) + "_xform")
print(prim, new_xform)
edits.Add(Sdf.NamespaceEdit.Reparent(prim.GetPath(), new_xform.GetPath(), 4))
# edits.MovePrimAtPath(prim.GetPath(), str(new_xform.GetPath()) + str(prim.GetName()))
# edits.ApplyEdits()
continue
children_prims = prim.GetChildren()
prims = prims + children_prims
stage.GetRootLayer().Apply(edits)
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path)
def convert_asset_instanceable(asset_usd_path, source_prim_path, save_as_path=None, create_xforms=False):
""" Makes all mesh/geometry prims instanceable.
Can optionally add UsdGeom.Xform prim as parent for all mesh/geometry prims.
Makes a copy of the asset USD file, which will be used for referencing.
Updates asset file to convert all parent prims of mesh/geometry prims to reference cloned USD file.
Args:
asset_usd_path (str): USD file path for asset
source_prim_path (str): USD path of root prim
save_as_path (str): USD file path for modified USD stage. Defaults to None, will save in same file.
create_xforms (bool): Whether to add new UsdGeom.Xform prims to mesh/geometry prims.
"""
undo_instanceable_xforms(asset_usd_path, source_prim_path, save_as_path)
asset_usd_path = save_as_path
if create_xforms:
create_parent_xforms(asset_usd_path, source_prim_path, save_as_path)
asset_usd_path = save_as_path
instance_usd_path = ".".join(asset_usd_path.split(".")[:-1]) + "_meshes.usd"
omni.client.copy(asset_usd_path, instance_usd_path)
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
while len(prims) > 0:
prim = prims.pop(0)
if prim:
if prim.GetTypeName() in ["Mesh", "Capsule", "Sphere", "Cube", "Cone", "Cylinder", "Disk", "Plane", "Torus"]:
parent_prim = prim.GetParent()
if parent_prim and not parent_prim.IsInstance():
parent_prim.GetReferences().AddReference(assetPath=instance_usd_path, primPath=str(parent_prim.GetPath()))
parent_prim.SetInstanceable(True)
continue
children_prims = prim.GetChildren()
prims = prims + children_prims
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path) Final Note from pxr import Usd, UsdGeom, Sdf, UsdShade
import omni
# TODO: Currently not adding the geometry to the newly created Xform.
def create_parent_xforms(asset_usd_path, source_prim_path, save_as_path=None):
""" Adds a new UsdGeom.Xform prim for each Mesh/Geometry prim under source_prim_path.
Moves material assignment to new parent prim if any exists on the Mesh/Geometry prim.
Args:
asset_usd_path (str): USD file path for asset
source_prim_path (str): USD path of root prim
save_as_path (str): USD file path for modified USD stage. Defaults to None, will save in same file.
"""
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
# edits = Usd.NamespaceEditor(stage)
edits = Sdf.BatchNamespaceEdit()
while len(prims) > 0:
prim = prims.pop(0)
print(prim)
if prim.GetTypeName() in ["Mesh", "Capsule", "Sphere", "Box", "Cone", "Torus", "Plane", "Cylinder", "Disk"]:
new_xform = UsdGeom.Xform.Define(stage, str(prim.GetPath()) + "_xform")
print(prim, new_xform)
edits.Add(Sdf.NamespaceEdit.Reparent(prim.GetPath(), new_xform.GetPath(), 4))
# edits.MovePrimAtPath(prim.GetPath(), str(new_xform.GetPath()) + str(prim.GetName()))
# edits.ApplyEdits()
continue
children_prims = prim.GetChildren()
prims = prims + children_prims
stage.GetRootLayer().Apply(edits)
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path)
# if save_as_path is None:
# stage.GetRootLayer().Save()
# else:
# stage.GetRootLayer().Export(save_as_path)
def undo_instanceable_xforms(asset_usd_path, source_prim_path, save_as_path=None):
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
while len(prims) > 0:
prim = prims.pop(0)
print(prim)
if prim.IsInstance():
print("This is instanceable!")
prim.SetInstanceable(False)
children_prims = prim.GetChildren()
prims = prims + children_prims
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path)
# if save_as_path is None:
# stage.GetRootLayer().Save()
# else:
# stage.GetRootLayer().Export(save_as_path)
def convert_asset_instanceable(asset_usd_path, source_prim_path, save_as_path=None, create_xforms=False):
""" Makes all mesh/geometry prims instanceable.
Can optionally add UsdGeom.Xform prim as parent for all mesh/geometry prims.
Makes a copy of the asset USD file, which will be used for referencing.
Updates asset file to convert all parent prims of mesh/geometry prims to reference cloned USD file.
Args:
asset_usd_path (str): USD file path for asset
source_prim_path (str): USD path of root prim
save_as_path (str): USD file path for modified USD stage. Defaults to None, will save in same file.
create_xforms (bool): Whether to add new UsdGeom.Xform prims to mesh/geometry prims.
"""
undo_instanceable_xforms(asset_usd_path, source_prim_path, save_as_path)
asset_usd_path = save_as_path
if create_xforms:
create_parent_xforms(asset_usd_path, source_prim_path, save_as_path)
asset_usd_path = save_as_path
instance_usd_path = ".".join(asset_usd_path.split(".")[:-1]) + "_meshes.usd"
omni.client.copy(asset_usd_path, instance_usd_path)
omni.usd.get_context().open_stage(asset_usd_path)
stage = omni.usd.get_context().get_stage()
prims = [stage.GetPrimAtPath(source_prim_path)]
while len(prims) > 0:
prim = prims.pop(0)
if prim:
if prim.GetTypeName() in ["Mesh", "Capsule", "Sphere", "Cube", "Cone", "Cylinder", "Disk", "Plane", "Torus"]:
if not prim.IsInstance():
# prim.GetReferences().AddReference(assetPath=instance_usd_path, primPath=str(prim.GetPath()))
prim.SetInstanceable(True)
# parent_prim = prim.GetParent()
# if parent_prim and not parent_prim.IsInstance():
# parent_prim.GetReferences().AddReference(assetPath=instance_usd_path, primPath=str(parent_prim.GetPath()))
# parent_prim.SetInstanceable(True)
# continue
children_prims = prim.GetChildren()
prims = prims + children_prims
if save_as_path is None:
omni.usd.get_context().save_stage()
else:
omni.usd.get_context().save_as_stage(save_as_path)
convert_asset_instanceable(
asset_usd_path="path_to_flattened_usd_file",
source_prim_path="/source/prim",
save_as_path="path_to_where_you_wanna_save_it"
) |
Beta Was this translation helpful? Give feedback.
-
Hi,
I've imported a mjcf description of a robot using the conversion scripts given on the IsaacLab repo with the --import-sites and --make-instanceable flags. But when I want to load multiple envs with this robot, only env_0 starts to perform the commanded movements, but the others are frozen. Here's the link to the mjcf model that I am using: https://github.com/srl-ethz/faive_gym_oss/tree/main/assets/faive_hand_p0. I also tried other more simplified mjcf files and converted it to usd, but the same problem occurs there.
Has someone an idea how to fix this issue?
Thanks in advance!
Beta Was this translation helpful? Give feedback.
All reactions