For loop with orchestrator in Replicator

How to wait for orchestrator to finish before making another cycle of the for loop in a script like this:

import omni.replicator.core as rep

SHAPES = ['torus', 'sphere', 'cube']

for shape in SHAPES:
    with rep.new_layer():

        camera = rep.create.camera(
                position=(0,0,1000),
                look_at=(0,0,0)
            )

        sphere_light = rep.create.light(
            light_type="Sphere",
            temperature=rep.distribution.normal(6500, 500),
            intensity=rep.distribution.normal(35000, 5000),
            position=rep.distribution.uniform((-300, -300, -300), (300, 300, 300)),
            scale=rep.distribution.uniform(50, 100),
            count=2
        )

        render_product = rep.create.render_product(camera, (1024, 1024))

        if shape=='torus':
            model = rep.create.torus(semantics=[('class', 'torus')] , position=(0, 0 , 0))
        elif shape=='sphere':
            model = rep.create.sphere(semantics=[('class', 'sphere')], position=(0, 0, 0))
        elif shape== 'cube':
            model = rep.create.cube(semantics=[('class', 'cube')],  position=(0, 0 , 0) )

        with rep.trigger.on_frame(num_frames=10):
            with model:
                    rep.modify.pose(
                        rotation=rep.distribution.uniform((0,-90, 0), (0, 90, 0)),
                    )

        # Initialize and attach writer
        writer = rep.WriterRegistry.get("BasicWriter")

        writer.initialize( output_dir="_output/"+shape, rgb=True)

        writer.attach([render_product])

        rep.orchestrator.run()

To run this script I use the headless method
.\omnicode.code.sh --no-windows --omni/replicator/script=/home/user/test.py

This renders only the cube because it is the last cycle and no new orchestrator.run() is called.

1 Like

I updated the script with a working one, so you can try by yourself.
I realy hope to find a solution to this problem because I think it’s essential for this software to be able to run multiple scenario with one script.

Hello @glonor! I’ve shared your post with the dev team for further assistance.

Hello @WendyGram, is there any update? We are facing the same issue. Basically, the replicator populates all layers and renders them at the same time. What we are hoping to achieve is to render each layer separately without restarting replicator.
Thanks,
Mateusz

1 Like

I encountered into the same issue, too. Here’s my workaround though I don’t know if it’s correct to do it.
To wait for the replicator, the function / script should leverage the async mechanic in python.

  • omni.replicator.core.orchestrator.run_until_complete_async: Render all frames
  • omni.replicator.core.orchestrator.step_async: Render once

Since my modification of nodes are hard to achieve in rep.modifiy, I implement the modification and render 1 frame in a round.

Hope this help :)

Hi, could you please share a working code snippet that implements the workaround you mentioned. It would be really helpful if you could provide a code example similar to the one I shared in my first post that successfully renders the three shapes.

Thank you in advance for your support and contributions.

There you go :)
I run the script in OV UI’s script window

import omni.replicator.core as rep
import asyncio
import time

async def run_replicator(shape):
    with rep.new_layer():

        camera = rep.create.camera(
                position=(0,0,1000),
                look_at=(0,0,0)
            )

        sphere_light = rep.create.light(
            light_type="Sphere",
            temperature=rep.distribution.normal(6500, 500),
            intensity=rep.distribution.normal(35000, 5000),
            position=rep.distribution.uniform((-300, -300, -300), (300, 300, 300)),
            scale=rep.distribution.uniform(50, 100),
            count=2
        )

        render_product = rep.create.render_product(camera, (1024, 1024))

        if shape=='torus':
            model = rep.create.torus(semantics=[('class', 'torus')] , position=(0, 0 , 0))
        elif shape=='sphere':
            model = rep.create.sphere(semantics=[('class', 'sphere')], position=(0, 0, 0))
        elif shape== 'cube':
            model = rep.create.cube(semantics=[('class', 'cube')],  position=(0, 0 , 0) )

        with rep.trigger.on_frame(num_frames=10):
            with model:
                    rep.modify.pose(
                        rotation=rep.distribution.uniform([-90]*3, [90]*3),
                        # rotation=rep.distribution.uniform((0,-90, 0), (0, 90, 0)),
                    )

        # Initialize and attach writer
        writer = rep.WriterRegistry.get("BasicWriter")

        writer.initialize(output_dir="_output/"+shape, rgb=True)

        writer.attach([render_product])
        await rep.orchestrator.run_until_complete_async()

async def main():
    SHAPES = ['torus', 'sphere', 'cube']
    for shape in SHAPES:
        print(f'Run replicator: {shape}')
        start = time.time()
        await run_replicator(shape)
        print(f'Done in {time.time()-start: .2f} secs: {shape}')

asyncio.ensure_future(main())

2 Likes

At first, I tried the headless method, but it didn’t work out. Then, I noticed that you used the UI and decided to try that approach, and finally, it worked. Thank you for your help. I really appreciate it.

I am trying to do a similar thing, but i would like to run omniverse headless. The problem is when i run it headless, that i starts the next run of the for loop, before the rtx renderer starts.

Are there any updates on how to accomplish this when running omniverse in headless mode?

I was able to solve it by removing num_frames and using step_async() + stop() instead of run_until_complete_async()

If I run the script like this, it works for me:


import omni.replicator.core as rep
import asyncio
import time


async def run_replicator(shape):
    with rep.new_layer():

        camera = rep.create.camera(
                position=(0,0,1000),
                look_at=(0,0,0)
            )

        sphere_light = rep.create.light(
            light_type="Sphere",
            temperature=rep.distribution.normal(6500, 500),
            intensity=rep.distribution.normal(35000, 5000),
            position=rep.distribution.uniform((-300, -300, -300), (300, 300, 300)),
            scale=rep.distribution.uniform(50, 100),
            count=2
        )

        render_product = rep.create.render_product(camera, (1024, 1024))

        if shape=='torus':
            model = rep.create.torus(semantics=[('class', 'torus')] , position=(0, 0 , 0))
        elif shape=='sphere':
            model = rep.create.sphere(semantics=[('class', 'sphere')], position=(0, 0, 0))
        elif shape== 'cube':
            model = rep.create.cube(semantics=[('class', 'cube')],  position=(0, 0 , 0) )

        with rep.trigger.on_frame():
            with model:
                    rep.modify.pose(
                        rotation=rep.distribution.uniform([-90]*3, [90]*3),
                        # rotation=rep.distribution.uniform((0,-90, 0), (0, 90, 0)),
                    )

        # Initialize and attach writer
        writer = rep.WriterRegistry.get("BasicWriter")

        writer.initialize(output_dir="_output/"+shape, rgb=True)

        writer.attach([render_product])

        for i in range(10):
            await rep.orchestrator.step_async()

        rep.orchestrator.stop()

async def main():
    SHAPES = ['torus', 'sphere', 'cube']
    for shape in SHAPES:
        print(f'Run replicator: {shape}')
        start = time.time()
        await run_replicator(shape)
        print(f'Done in {time.time()-start: .2f} secs: {shape}')

asyncio.ensure_future(main())

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