Converting Action Graphs to scripts

Hello All,

Is there a way to convert Action Graphs to scripts ?

Thank you
Sandeep

Hi @quark01 - I do not think it is possible. But you can develop the action graph using scripts. OmniGraph — Omniverse Extensions documentation

I thought you could add the ability to convert the action graph to a script for model migration, or is there a good way to copy the action graph to another robot

Hi @litao_bate - While there isn’t a direct way to convert an Action Graph to a script, you can replicate the logic of an Action Graph in a script using the Omniverse Kit’s Python API. This can be useful for model migration or copying behaviors between robots.

As for copying an Action Graph to another robot, you can do this by duplicating the Action Graph and then changing the target nodes to reference the new robot. Here’s a general process:

  1. Open the Action Graph window (Window > Visual Scripting > Action Graph).
  2. Find the Action Graph you want to copy.
  3. Right-click on the Action Graph and select Duplicate.
  4. In the duplicated Action Graph, find the nodes that reference the original robot.
  5. Change the references in these nodes to point to the new robot.

Remember that the specifics of this process can vary depending on the structure of your Action Graph and the characteristics of your robots.

yes, its possible. but not fun at all.

this, for example, is an action graph with two nodes, one for instantiating the usd files in stage and one for scattering them:

 keys = og.Controller.Keys
        _, _, _, nodes = og.Controller.edit(
            self.graph,
            {
                keys.CREATE_NODES: [
                    ("OgnScatter2D", "omni.replicator.core.OgnScatter2D"),
                    ("OgnSamplePopulation", "omni.replicator.core.OgnSamplePopulation")
                    ],
                keys.CONNECT: [
                    ("OgnSamplePopulation.outputs:prims", "OgnScatter2D.inputs:prims")
                ],
                keys.SET_VALUES: [
                    ("OgnSamplePopulation.inputs:paths", rand_usd_paths),
                    ("OgnSamplePopulation.inputs:mode", 'scene_instance'),
                    ("OgnSamplePopulation.inputs:useCache", False),
                    ("OgnSamplePopulation.inputs:withReplacements", False),
                    ("OgnSamplePopulation.inputs:populationName", f"{self.assets_name}_ScatterPopulation"),
                    ("OgnScatter2D.inputs:surfacePrims", self.surface_prims_path), #surfacePrims are the surfaces to scatter on, must be a list of paths
                    ("OgnScatter2D.inputs:checkForCollisions", self.check_for_collision),
                ]
            },
        )

If you want to also rotate the prims (which must be done before the scattering otherwise you are risking having collisions), it become exponentially more difficult. this graph:

can be built with this:

def init_graph(self, surface_prims_path, rand_usd_paths):
        self.graph = og.Controller.create_graph(
            graph_id = {
                "graph_path" : f"/Root/ScatterGraphs/{self.assets_name}Graph",
                "fc_backing_type" : og.GraphBackingType.GRAPH_BACKING_TYPE_FABRIC_WITHOUT_HISTORY, #TODO: MIGHT NEED TO REMOVE THIS
                "pipeline_stage" : og.GraphPipelineStage.GRAPH_PIPELINE_STAGE_ONDEMAND
            }
            )

        keys = og.Controller.Keys
        _, _, _, nodes = og.Controller.edit(
            self.graph,
            {
                keys.CREATE_NODES: [
                    ("OgnScatter2D", "omni.replicator.core.OgnScatter2D"),
                    ("OgnSamplePopulation", "omni.replicator.core.OgnSamplePopulation"),
                    ("OgnCount1", "omni.replicator.core.OgnCount"),
                    ("OgnCount2", "omni.replicator.core.OgnCount"),
                    ("OgnSampleUniform", "omni.replicator.core.OgnSampleUniform"),
                    ("PerAxisPose", "omni.replicator.core.OgnPerAxisPose"),
                    ("OgnWritePrimAttribute", "omni.replicator.core.OgnWritePrimAttribute"),
                    ],
                keys.CONNECT: [
                    ("OgnSamplePopulation.outputs:prims", "OgnCount1.inputs:prims"),
                    ("OgnCount1.outputs:count", "OgnSampleUniform.inputs:numSamples"),
                    ("OgnSampleUniform.outputs:samples", "PerAxisPose.inputs:fullValues"),

                    ("OgnSamplePopulation.outputs:prims", "OgnCount2.inputs:prims"),
                    ("OgnCount2.outputs:count", "PerAxisPose.inputs:numSamples"),

                    ("OgnSamplePopulation.outputs:prims", "PerAxisPose.inputs:prims"),

                    ("PerAxisPose.outputs:samples", "OgnWritePrimAttribute.inputs:values"),
                    ("OgnSamplePopulation.outputs:prims", "OgnWritePrimAttribute.inputs:prims"),

                    ("OgnSamplePopulation.outputs:exec", "OgnScatter2D.inputs:execIn"),
                    ("OgnSamplePopulation.outputs:exec", "PerAxisPose.inputs:exec"),
                    ("PerAxisPose.outputs:exec", "OgnWritePrimAttribute.inputs:execIn"),

                    ("OgnSamplePopulation.outputs:prims", "OgnScatter2D.inputs:prims"),


                ],
                keys.SET_VALUES: [
                 
                    ("OgnSamplePopulation.inputs:paths", rand_usd_paths),
                    ("OgnSamplePopulation.inputs:mode", 'scene_instance'),
                    ("OgnSamplePopulation.inputs:useCache", False),
                    ("OgnSamplePopulation.inputs:withReplacements", False),
                    ("OgnSamplePopulation.inputs:populationName", f"{self.assets_name}_ScatterPopulation"),

                    ("OgnCount1.inputs:mode", 'prims'),

                    ("OgnSampleUniform.inputs:lower", [0,0,0]),
                    ("OgnSampleUniform.inputs:upper", [0,0,180]),
                    ("OgnSampleUniform.inputs:outputType", "float3[]"),

                    ("OgnCount2.inputs:mode", 'prims'),

                    ("PerAxisPose.inputs:mode", "rotation"),

                    ("OgnWritePrimAttribute.inputs:attribute", "xformOp:rotateXYZ"),
                    ("OgnWritePrimAttribute.inputs:attributeType", "double3"),

                    #("OgnScatter2D.inputs:surfacePrims", surface_prims_path),   #do this in edit graph only
                    ("OgnScatter2D.inputs:checkForCollisions", self.check_for_collision),
                ]
            },
        )