Scatter_2d doesn't have a scale parameter for objects?

I am using scatter_2d inside Script Editor in Isaac Sim. Please use the script below.

# This needs to be run inside Isaac Sim Script Editor not Omniverse Code Script Editor

import omni.replicator.core as rep
from datetime import datetime
from omni.isaac.core.utils.stage import get_current_stage, open_stage

import omni.isaac.core.utils.bounds as bounds_utils
import omni.isaac.core.utils.prims as prims_utils

import numpy as np


# with rep.new_layer():
# Define paths for the character, the props, the environment and the surface where the assets will be scattered in.


FORKLIFT_URL = "omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.1/Isaac/Props/Forklift/forklift.usd"
PALLET_URL = "omniverse://localhost/NVIDIA/Assets/ArchVis/Industrial/Pallets/Pallet_B1.usd"
ENV_URL ="omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.0/Isaac/Samples/Replicator/Stage/full_warehouse_worker_and_anim_cameras.usd"


open_stage(ENV_URL)
stage =get_current_stage()

floor_prims = [x.GetPath() for x in stage.Traverse() if "SM_floor" in x.GetName() and prims_utils.get_prim_type_name(x.GetPath()) == "Xform"]
print('dir floor_prims: ', dir(floor_prims))
bb_cache = bounds_utils.create_bbox_cache()
combined_range_arr = bounds_utils.compute_combined_aabb(bb_cache, prim_paths=floor_prims)

print('combined_range_arr: ', combined_range_arr)

margin = 2
min_x, min_y, min_z, max_x, max_y, max_z = combined_range_arr


def randomize_forklift():
    forklift = rep.create.from_usd(FORKLIFT_URL, semantics=[('class', 'forklift')])
    with forklift:
        rep.physics.collider()
        rep.modify.pose(
            position=rep.distribution.uniform((min_x + margin, min_y + margin, 0), (max_x - margin, max_y - margin, 0)),
            rotation=rep.distribution.uniform((0, 0, -90), (0, 0, 90)),
            #scale=100
        )
    return forklift

# Register randomization

rep.randomizer.register(randomize_forklift)


def scatter_pallets(prim):
    pallets = rep.create.from_usd(PALLET_URL, semantics=[('class', 'pallet')], count=2)
    with pallets:
        rep.physics.collider()
        rep.randomizer.scatter_2d(surface_prims=prim, check_for_collisions=True),
        
    return pallets

# Register randomization

rep.randomizer.register(scatter_pallets)



# Setup camera and attach it to render product
camera = rep.create.camera(
    focus_distance=800,
    # f_stop=0.5,
    f_stop=500,
    #focal_length=613.634
)
render_product = rep.create.render_product(camera, resolution=(640, 480))


timestamp = datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%p")
# Initialize and attach writer
writer = rep.WriterRegistry.get("BasicWriter")
writer.initialize(output_dir="/home/mona/Desktop/Isaac_Sim_Dummy_Out/forklift_warehouse/" + timestamp , rgb=True, bounding_box_2d_tight=True)
writer.attach([render_product])

with rep.trigger.on_frame(num_frames=50):
    forklift = rep.randomizer.randomize_forklift()
    pallets = rep.randomizer.scatter_pallets(forklift)
    with camera:
        rep.modify.pose(position=rep.distribution.uniform((min_x + margin, min_y + margin, 4), (max_x - margin, max_y - margin, 7)),
                        look_at=pallets)

However, it spawns very large pallets. I intend to use scale 0.01 but it seems scatter_2d is not allowing it. How can I fix this problem?

as you can see the pallet is encompassing the warehouse.usd

You would need to use rep.modify.pose. In your case you can pass it in a constant value instead of a distribution.
I would add the following line for your scatter pallet’s functionality: rep.modify.pose(scale=0.01)

Full function:

def scatter_pallets(prim):
    pallets = rep.create.from_usd(PALLET_URL, semantics=[('class', 'pallet')], count=2)
    with pallets:
        rep.physics.collider()
        rep.randomizer.scatter_2d(surface_prims=prim, check_for_collisions=True)
        rep.modify.pose(scale=0.01)

    return pallets
1 Like

so scale=0.01 in what you mentioned using rep.modify.pose, didn’t fix it

# This needs to be run inside Isaac Sim Script Editor not Omniverse Code Script Editor

import omni.replicator.core as rep
from datetime import datetime
from omni.isaac.core.utils.stage import get_current_stage, open_stage

import omni.isaac.core.utils.bounds as bounds_utils
import omni.isaac.core.utils.prims as prims_utils

import numpy as np


# with rep.new_layer():
# Define paths for the character, the props, the environment and the surface where the assets will be scattered in.


FORKLIFT_URL = "omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.1/Isaac/Props/Forklift/forklift.usd"
PALLET_URL = "omniverse://localhost/NVIDIA/Assets/ArchVis/Industrial/Pallets/Pallet_B1.usd"
ENV_URL ="omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.0/Isaac/Samples/Replicator/Stage/full_warehouse_worker_and_anim_cameras.usd"


open_stage(ENV_URL)
stage =get_current_stage()

floor_prims = [x.GetPath() for x in stage.Traverse() if "SM_floor" in x.GetName() and prims_utils.get_prim_type_name(x.GetPath()) == "Xform"]
print('dir floor_prims: ', dir(floor_prims))
bb_cache = bounds_utils.create_bbox_cache()
combined_range_arr = bounds_utils.compute_combined_aabb(bb_cache, prim_paths=floor_prims)

print('combined_range_arr: ', combined_range_arr)

margin = 2
min_x, min_y, min_z, max_x, max_y, max_z = combined_range_arr


def randomize_forklift():
    forklift = rep.create.from_usd(FORKLIFT_URL, semantics=[('class', 'forklift')])
    with forklift:
        rep.physics.collider()
        rep.modify.pose(
            position=rep.distribution.uniform((min_x + margin, min_y + margin, 0), (max_x - margin, max_y - margin, 0)),
            rotation=rep.distribution.uniform((0, 0, -90), (0, 0, 90)),
            #scale=100
        )
    return forklift

# Register randomization

rep.randomizer.register(randomize_forklift)


def scatter_pallets(prim):
    pallets = rep.create.from_usd(PALLET_URL, semantics=[('class', 'pallet')], count=2)
    with pallets:
        rep.physics.collider()
        rep.randomizer.scatter_2d(surface_prims=prim, check_for_collisions=True),
        rep.modify.pose(scale=0.01)
    return pallets

# Register randomization

rep.randomizer.register(scatter_pallets)



# Setup camera and attach it to render product
camera = rep.create.camera(
    focus_distance=800,
    # f_stop=0.5,
    f_stop=500,
    #focal_length=613.634
)
render_product = rep.create.render_product(camera, resolution=(640, 480))


timestamp = datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%p")
# Initialize and attach writer
writer = rep.WriterRegistry.get("BasicWriter")
writer.initialize(output_dir="/home/mona/Desktop/Isaac_Sim_Dummy_Out/forklift_warehouse/" + timestamp , rgb=True, bounding_box_2d_tight=True)
writer.attach([render_product])

with rep.trigger.on_frame(num_frames=50):
    forklift = rep.randomizer.randomize_forklift()
    pallets = rep.randomizer.scatter_pallets(forklift)
    with camera:
        rep.modify.pose(position=rep.distribution.uniform((min_x + margin, min_y + margin, 4), (max_x - margin, max_y - margin, 7)),
                        look_at=pallets)

here’s an example of a produced photo:

Do you know how we can fix the pallet scale problem?

Accidentally added a comma in my answer above. I was still able to change the scale with rep.modify.pose(scale=0.01) here’s a script that runs in Isaac sim, I used a new empty scene.

import omni.replicator.core as rep

pallet_url = "omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.0/Isaac/Props/Pallet/pallet.usd"

plane = rep.create.plane(scale=1)

def scatter_pallets():
	pallets = rep.create.from_usd(pallet_url, count=3)
	with pallets:
		rep.physics.collider()
		rep.modify.pose(scale=0.1)
		rep.randomizer.scatter_2d(surface_prims=plane, check_for_collisions=True)

	return pallets

rep.randomizer.register(scatter_pallets)

with rep.trigger.on_frame(num_frames=10):
	rep.randomizer.scatter_pallets()
1 Like

@kit-nvidia-Jen thanks a lot for your response. I am able to use scale in your example in Isaac Sim but when I use the following code, pallet continues to be encompassing the warehouse and it’s not effective:


# This needs to be run inside Isaac Sim Script Editor not Omniverse Code Script Editor

import omni.replicator.core as rep
from datetime import datetime
from omni.isaac.core.utils.stage import get_current_stage, open_stage

import omni.isaac.core.utils.bounds as bounds_utils
import omni.isaac.core.utils.prims as prims_utils
from omni.isaac.core.utils.bounds import compute_combined_aabb, create_bbox_cache
from omni.isaac.core.utils.rotations import euler_angles_to_quat, quat_to_euler_angles, lookat_to_quatf

from omni.isaac.core.utils import prims
import omni.usd
from pxr import UsdGeom, Usd, Gf, UsdPhysics, PhysxSchema

import random

import numpy as np
import math

import inspect
from collections import OrderedDict


# https://stackoverflow.com/a/52003056
def get_signature(fn):
    params = inspect.signature(fn).parameters
    args = []
    kwargs = OrderedDict()
    for p in params.values():
        if p.default is p.empty:
            args.append(p.name)
        else:
            kwargs[p.name] = p.default
    return args, kwargs


# with rep.new_layer():
# Define paths for the character, the props, the environment and the surface where the assets will be scattered in.


FORKLIFT_URL = "omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.1/Isaac/Props/Forklift/forklift.usd"
PALLET_URL = "omniverse://localhost/NVIDIA/Assets/ArchVis/Industrial/Pallets/Pallet_B1.usd"
ENV_URL ="omniverse://localhost/NVIDIA/Assets/Isaac/2022.2.0/Isaac/Samples/Replicator/Stage/full_warehouse_worker_and_anim_cameras.usd"
SCOPE_NAME = "/MyScope"


open_stage(ENV_URL)
stage =get_current_stage()

# TODO: why can't I use the floor_prims for scatter_2d scatter plane?
floor_prims = [x.GetPath() for x in stage.Traverse() if "SM_floor" in x.GetName() and prims_utils.get_prim_type_name(x.GetPath()) == "Xform"]
print('dir floor_prims: ', dir(floor_prims))
print('type(floor_prims): ', type(floor_prims))
bb_cache = bounds_utils.create_bbox_cache()
combined_range_arr = bounds_utils.compute_combined_aabb(bb_cache, prim_paths=floor_prims)

print('combined_range_arr: ', combined_range_arr)

margin = 2
min_x, min_y, min_z, max_x, max_y, max_z = combined_range_arr


forklift_prim = prims.create_prim(
    prim_path=f"{SCOPE_NAME}/forklift",
    position=(random.uniform(-50, -4), random.uniform(-1, 3), 0),
    orientation=euler_angles_to_quat([0, 0, random.uniform(0, math.pi)]),
    usd_path=FORKLIFT_URL,
    semantic_label="forklift",
)


forklift_tf = omni.usd.get_world_transform_matrix(forklift_prim)
print('forklift_tf: ', forklift_tf)
pallet_offset_tf = Gf.Matrix4d().SetTranslate(Gf.Vec3d(0, random.uniform(-1.2, -2.4), 0))
pallet_pos_gf = (pallet_offset_tf * forklift_tf).ExtractTranslation()
forklift_quat_gf = forklift_tf.ExtractRotation().GetQuaternion()
forklift_quat_xyzw = (forklift_quat_gf.GetReal(), *forklift_quat_gf.GetImaginary())

pallet_prim = prims.create_prim(
    prim_path=f"{SCOPE_NAME}/pallet",
    position=pallet_pos_gf,
    orientation=forklift_quat_xyzw,
    usd_path=PALLET_URL,
    semantic_label="pallet",
)

print('pallet_prim: ', pallet_prim)
print('type of pallet prim: ', type(pallet_prim))

print('dir rep: ', dir(rep))
print('dir rep.get: ', dir(rep.get))
print('dir rep.get.prims: ', dir(rep.get.prims))
print('sig prims: ', get_signature(rep.get.prims))

def randomize_forklift():
    ###forklift = rep.create.from_usd(FORKLIFT_URL, semantics=[('class', 'forklift')])
    forklift = rep.get.prims(semantics=[('class', 'forklift')])
    print('type of rep.get.prims for forklift is: ', type(forklift))
    with forklift:
        rep.physics.collider()
        rep.modify.pose(
            position=rep.distribution.uniform((min_x + margin, min_y + margin, 0), (max_x - margin, max_y - margin, 0)),
            rotation=rep.distribution.uniform((0, 0, -90), (0, 0, 90)),
            # scale=100
        )
    return forklift

# Register randomization

rep.randomizer.register(randomize_forklift)


def scatter_pallets(prim):
    # Calculate the bounds of the prim to create a scatter plane of its size
    bb_cache = create_bbox_cache()
    bbox3d_gf = bb_cache.ComputeLocalBound(prim)
    prim_tf_gf = omni.usd.get_world_transform_matrix(prim)

    # Calculate the bounds of the prim
    bbox3d_gf.Transform(prim_tf_gf)
    range_size = bbox3d_gf.GetRange().GetSize()

    # Get the quaterion of the prim in xyzw format from usd
    prim_quat_gf = prim_tf_gf.ExtractRotation().GetQuaternion()
    prim_quat_xyzw = (prim_quat_gf.GetReal(), *prim_quat_gf.GetImaginary())

    # Create a plane on the pallet to scatter the boxes on
    plane_scale = (range_size[0] * 5, range_size[1] * 5, 1)
    plane_pos_gf = prim_tf_gf.ExtractTranslation() + Gf.Vec3d(0, 0, range_size[2])
    plane_rot_euler_deg = quat_to_euler_angles(np.array(prim_quat_xyzw), degrees=True)
    scatter_plane = rep.create.plane(
        scale=plane_scale, position=plane_pos_gf, rotation=plane_rot_euler_deg, visible=False
    )
    pallets = rep.create.from_usd(PALLET_URL, semantics=[('class', 'pallet')], count=2)
    with pallets:
        rep.physics.collider()
        rep.randomizer.scatter_2d(surface_prims=scatter_plane, check_for_collisions=True)
        rep.modify.pose(scale=0.001)
    return pallets

# Register randomization

rep.randomizer.register(scatter_pallets)



# Setup camera and attach it to render product
camera = rep.create.camera(
    focus_distance=800,
    # f_stop=0.5,
    f_stop=500,
    #focal_length=613.634
)
render_product = rep.create.render_product(camera, resolution=(640, 480))


timestamp = datetime.now().strftime("%Y_%m_%d-%I_%M_%S_%p")
# Initialize and attach writer
writer = rep.WriterRegistry.get("BasicWriter")
writer.initialize(output_dir="/home/mona/Desktop/Isaac_Sim_Dummy_Out/forklift_warehouse/" + timestamp , rgb=True, bounding_box_2d_tight=True)
writer.attach([render_product])

with rep.trigger.on_frame(num_frames=50):
    forklift = rep.randomizer.randomize_forklift()
    # Spawn the pallet in front of the forklift with a random offset on the Y axis
    print('type of forklift: ', type(forklift))
    # forklift = UsdGeom.Xformable(forklift)
    # print('type of forklift: ', type(forklift))

    

    pallets = rep.randomizer.scatter_pallets(pallet_prim)
    # pallets = rep.randomizer.scatter_pallets(floor_prims)

    with camera:
        rep.modify.pose(position=rep.distribution.uniform((min_x + margin, min_y + margin, 4), (max_x - margin, max_y - margin, 7)),
                        look_at=pallets)

Can you please run the above code in Isaac Sim Script Editor?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.