Custom node to randomize visibility based on frame number (or any other condition)

This is my example code

import omni.replicator.core as rep
import omni.graph.core as og
import omni.graph.core.types as ot

frame = 0

@og.create_node_type
def autonode_visibility() -> ot.boolean:
    """Gets visibility for replicator"""
    global frame
    print("FRAME", frame)
    frame += 1
    return frame % 2 == 1

# Register functionality into replicator
def visibility():
	return rep.utils.create_node(f"{og.RUNTIME_MODULE_NAME}.autonode_visibility")
rep.randomizer.register(visibility)

with rep.get.prims(path_pattern="Light$"):
    rep.modify.visibility(rep.randomizer.visibility())

I get errors:

2024-08-28 18:46:49 [32,385ms] [Error] [omni.graph.core.plugin] /Replicator/SDGPipeline/OgnSetVisibility: [/Replicator/SDGPipeline] OmniGraph Error: Number of input values is different from number of input prims
                 (from compute() at line 40 in /home/wojtek/.local/share/ov/pkg/isaac-sim-4.1.0/extscache/omni.replicator.core-1.11.14+106.0.1.lx64.r.cp310/omni/replicator/core/ogn/python/_impl/nodes/OgnSetVisibility.py)

@hclever @jlafleche @pcallender I am trying to enforce different visibility state depending on a condition that is being changed with every frame. This is just a simple example.

I need to have control over what values are produced so I can adjust semantics during data generation. So for visible glasses I want to add a semantic class=glasses, as an example.

Can anyone help to make this work. This would be a very helpful part of knowledge.

cc @dennis.lynch

What type of condition are you checking for? I did something similar sounding so might be able to help.

Here was my solution for toggling visibility.

from typing import Any, Callable, List, Optional, Tuple, Union

import omni.replicator.core as rep
from omni.replicator.core.utils import (
    ReplicatorItem,
    ReplicatorWrapper,
    create_node,
    sequential,
    set_target_prims,
    utils,
)
import omni.graph.core as og


@ReplicatorWrapper
def toggle_visibility(input_prims: Union[ReplicatorItem, List[str]] = None) -> ReplicatorItem:
    """
    Create a node that toggles the visibility of the input prims.
    """

    vis_node = create_node("omni.replicator.core.OgnSetVisibility", node_name="Set Visibility")

    toggle_node = ReplicatorItem(create_node, "omni.graph.action.FlipFlop")

    make_array_node = create_node("omni.graph.nodes.ConstructArray")
    toggle_node.node.get_attribute("outputs:isA").connect(make_array_node.get_attribute("inputs:input0"), True)

    toggle_node.node.get_attribute("outputs:a").connect(vis_node.get_attribute("inputs:execIn"), True)
    toggle_node.node.get_attribute("outputs:b").connect(vis_node.get_attribute("inputs:execIn"), True)

    make_array_node.get_attribute("outputs:array").connect(vis_node.get_attribute("inputs:values"), True)

    if input_prims:
        set_target_prims(vis_node, "inputs:prims", input_prims)

    return toggle_node

Then to make it toggle every 2 frames:

...
with rep.trigger.on_frame(interval=2):
    prims = rep.get.prims(path_pattern="Light$")
    toggle_visibility(prims)

If you just want random visibility then I believe the default behavior of rep.modify.visibility() is random if nothing is passed to it.

1 Like

@josiah7 thanks for the answer. Its not really about the visibility itself. What I am aiming for is learning how to make graph nodes programatically so I can have custom behaviour during randomization. For instance, I would like to implement:

  • My own rep.create method that will generate / instantiate a new custom object (or set of objects grouped together) for each frame.
  • Ability to take the result of a distribution.choice for a particular prim and apply a different semantic based on what was selected for a different prim. Kind of an IF-ELSE statement for variant randomizations.
  • Ability to set a specific variant for a prim based on the variant randomization outcome for a different prim.

What you wrote is a good start, but its based on existing nodes that provide the featureset for toggling bits.

Is there any kind of documentation for this? I have been struggling to find it.

cc @hclever @jlafleche @pcallender

What has helped me is looking at the existing code. I’m using vscode and I have already run the link_app.bat so that the app (in this case isaac_sim) is linked to my project folder. From there it’s easy to search the app code.

When creating new nodes and utilities here is what I do:

  1. Setup your project, make sure the link_app is run and your extension can load in omniverse.
  2. Have vscode open with omniverse and the vscode link extension. (makes testing things easy with vscode link)
  3. Open up a blank graph in omniverse. Let say you want to use the the SetVariant node for something but need to see how it’s used. I first add it to the graph from there I can see what the node name is by hovering over it (sometimes the names don’t match…).
  4. Now in vscode I can search the app folder for this node
  5. Usually this gives a good example of how to use the node and you can even dive deeper into the node implementation itself if you’d like to reverse engineer your own version of it or add new features.

This is how I made the visibility toggle I shared. Searching for OgnSetVisibility brings up the rep.visibility function which provides a good example of it’s use.

I have run into cases where building a replicator function directly has proved too complicated (particularly when you are dealing with control flow). In those cases what I’ve done is first build the graph in omniverse that does what I want it to, then I can come back to the code to match what I’ve built in Omniverse.

Thanks for the very extensive explanation. I have never heard of the link_app.bat and will definitely investigate. So far I have been running scripts from vscode by using the isaac sim vscode extension.

I will get into the weeds and report back.

Thanks!