isaac-sim / IsaacLab

Unified framework for robot learning built on NVIDIA Isaac Sim
https://isaac-sim.github.io/IsaacLab
Other
1.84k stars 688 forks source link

[Question] Spawn different asset in different environment #186

Open taochenshh opened 8 months ago

taochenshh commented 8 months ago

How can I spawn different assets (for example, objects with different shapes) in different environment using the current version of Orbit?

Mayankm96 commented 7 months ago

Hi,

This is not readily supported. However, it should not be that difficult to make it work.

Currently, all spawners are decorated with clone decorator. This handles cloning a single object into multiple environments. If you do not want to do this, then you can simply remove the decorator and make a custom function that handles spawning over multiple environments.

An example of the pseudo-code:

from omni.isaac.orbit.sim.spawners.from_files import _spawn_from_usd_file

def spawn_from_multiple_usd(
    prim_path: str,
    my_asset_list: list[from_files_cfg.UsdFileCfg],
    translation: tuple[float, float, float] | None = None,
    orientation: tuple[float, float, float, float] | None = None,
) -> Usd.Prim:
        # resolve: {SPAWN_NS}/AssetName
        # note: this assumes that the spawn namespace already exists in the stage
        root_path, asset_path = prim_path.rsplit("/", 1)
        # check if input is a regex expression
        # note: a valid prim path can only contain alphanumeric characters, underscores, and forward slashes
        is_regex_expression = re.match(r"^[a-zA-Z0-9/_]+$", root_path) is None

        # resolve matching prims for source prim path expression
        if is_regex_expression and root_path != "":
            source_prim_paths = find_matching_prim_paths(root_path)
            # if no matching prims are found, raise an error
            if len(source_prim_paths) == 0:
                raise RuntimeError(
                    f"Unable to find source prim path: '{root_path}'. Please create the prim before spawning."
                )
        else:
            source_prim_paths = [root_path]

        # resolve prim paths for spawning
        prim_paths = [f"{source_prim_path}/{asset_path}" for source_prim_path in source_prim_paths]
        # spawn asset from the given usd file
        for prim_path in prim_paths:
            # sample the asset config to load
            cfg = random.choice(my_asset_list)
            # load the asset
            prim = _spawn_from_usd_file(prim_path, cfg.usd_path, cfg, translation, orientation)

        return prim
Mayankm96 commented 6 months ago

Hi guys,

This is still in the works, but we made a minimal example of doing this operation nicely and efficiently. I wanted to share this progress here since it may be blocking some of you.

The attached script has two functions, spawn_multi_object_randomly and spawn_multi_object_randomly_sdf. The former is akin to the pseudo-code I posted above (based on USD APIs), while the latter uses Sdf APIs. With USD APIs, we saw that it takes 45 seconds to create 2048 objects. However, with Sdf APIs, it takes 2.15 seconds for the same number of objects.

The script demonstrates the following:

  1. Spawn different objects in different environments
  2. Randomize the material color of the object in each environment

This is what the output looks like:

random

You can place the script from this zip file inside the directory source/standalone/demos/multi_object.py and execute it as:

./orbit.sh -p source/standalone/demos/multi_object.py --num_envs 2048

You can do all kind of variations of this spawning based on the code here. Hope this helps getting started with it!

EDIT (14.05.2024): Please make sure to set the flag replicate_physics as False in the interactive scene.

melecmat commented 2 months ago

Mass properties randomization

Hi, first of all thanks for the code above, I am relying on this piece of code heavily at the moment.

I wanted to try out randomization of mass distribution through setting center of mass. My code runs in the with Sdf.ChangeBlock(): section of the script above.

def set_random_mass(env_spec, prim_path, box_dimensions, mass_range=(2, 25), sigma_percent=2):
    """
    Sets the mass values as well as the center of mass.
    """
    length_dir = random.gauss(0., box_dimensions[0] * sigma_percent)
    width_dir =  random.gauss(0., box_dimensions[1] * sigma_percent)

    center_of_mass = env_spec.GetAttributeAtPath(prim_path + ".physics:centerOfMass")
    if center_of_mass is None:
        center_of_mass = Sdf.AttributeSpec(env_spec, "physics:centerOfMass", Sdf.ValueTypeNames.Double3)
    center_of_mass.default = Gf.Vec3d(length_dir, width_dir, 0.)
    mass = env_spec.GetAttributeAtPath(prim_path + ".physics:mass")
    if mass is None:
        mass = Sdf.AttributeSpec(env_spec, "physics:mass", Sdf.ValueTypeNames.Double)
    mass.default = random.uniform(*mass_range)

However it does not work. If I run the script without Fabric, I see the values set correctly in the GUI and even the mass debug view. If I then edit any of the values a little bit through GUI, everything starts working. I feel like I must be missing some physics update step after setting the values. Does anyone know what to do here?

Mayankm96 commented 1 month ago

@melecmat Do you call the above method at the spawn time (i.e. before sim.reset() gets called)?

luigiberducci commented 1 month ago

Hi, I am trying the randomization of the center of mass of an articulation through sdf API. However, I am struggling in finding a way to access the mass property of the robot base.

Do you have any suggestions or examples to help me understand how to implement it?

Thanks a lot!

Ashutosh781 commented 1 month ago

@Mayankm96 Hi, I am using the above code to spawn different USD files in different environments for legged robots. I am facing an issue wherein if my USD files have different structure: for example different dof robots, or even just different number of Xforms; the articulation is not initialized properly. I noticed that the InteractiveScene keeps just one object of the articulation class type.

Is there some way to work with the current code to spawn different USD files with different articulations in the environments? Any help or suggestion on this would be really helpful, thanks.

daichi-3110 commented 1 month ago

Hi, I am trying to get position and orientation of these different objects. Can I obtain these object poses like "pos = self.object.data.root_pos_w" ?

Thank you very much

Abdullah-AIST commented 1 week ago

Collision Not working as expected

Solved by setting "replicate_physics" to False in interactive scene cfg

Thank you for the great utility. Unfortunately, collision doesn't seem working properly with some objects floating or penetrating each others. The colliders looks fine. So I wonder where the problem originates?

image image

for reproducing the error: multi_object.zip