2. OmniGraph: Python Scripting

While OmniGraph is intended to be a visual scripting tool, it does have python scripting interfaces. This tutorial will give a simple example of how to script an action graph using Python.

2.1. Getting Started

Prerequisites

  • Review the GUI Tutorial series, especially OmniGraph and Interactive Scripting prior to beginning this tutorial.

  • Review the Core API Tutorial series, especially Hello World to become familiar with the extension workflow via Python.

  • Run the OmniGraph Keyboard Example following Keyboard Inputs.

The layout of the Action Graph is seen in the image below.

OmniGraph Keyboard Input

While you can make the graph above using the GUI exclusively, you can also compose the same graph via Python.

2.2. Code Explained

  1. Make sure the OmniGraph Keyboard example panel is open. Click the Open Containing Folder button on the upper right corner of the panel to open the folder that contains the source code.

  2. Open the file omnigraph_keyboard.py, find the setup_scene() section.

Inside the scene setup, we first add a cube and a ground plane to the scene, and fix the camera view.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    world = self.get_world()
    world.scene.add(
        VisualCuboid(
            prim_path="/Cube",  # The prim path of the cube in the USD stage
            name="cube",  # The unique name used to retrieve the object from the scene later on
            position=np.array([0, 0, 10.0]),  # Using the current stage units which is cms by default.
            scale=np.array([10.0, 10, 10]),  # most arguments accept mainly numpy arrays.
            color=np.array([0, 1.0, 1.0]),  # RGB channels, going from 0-1
        )
    )
    world.scene.add_default_ground_plane()
    set_camera_view(eye=np.array([75, 75, 45]), target=np.array([0, 0, 0]))

To compose the graph, the steps are: Get handle to the graph editor, create the nodes, set the values of any nodes, and then make the connections between the nodes explicitly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    # setup graph
    keys = og.Controller.Keys
    og.Controller.edit(
        {"graph_path": "/controller_graph", "evaluator_name": "execution"},
        {
            keys.CREATE_NODES: [
                ("OnTick", "omni.graph.action.OnTick"),
                ("A", "omni.graph.nodes.ReadKeyboardState"),
                ("D", "omni.graph.nodes.ReadKeyboardState"),
                ("ToDouble1", "omni.graph.nodes.ToDouble"),
                ("ToDouble2", "omni.graph.nodes.ToDouble"),
                ("Negate", "omni.graph.nodes.Multiply"),
                ("DeltaAdd", "omni.graph.nodes.Add"),
                ("SizeAdd", "omni.graph.nodes.Add"),
                ("NegOne", "omni.graph.nodes.ConstantInt"),
                ("CubeWrite", "omni.graph.nodes.WritePrimAttribute"),  # write prim property translate
                ("CubeRead", "omni.graph.nodes.ReadPrimAttribute"),
            ],
            keys.SET_VALUES: [
                ("A.inputs:key", "A"),
                ("D.inputs:key", "D"),
                ("OnTick.inputs:onlyPlayback", True),  # only tick when simulator is playing
                ("NegOne.inputs:value", -1),
                ("CubeWrite.inputs:name", "size"),
                ("CubeWrite.inputs:primPath", "/Cube"),
                ("CubeWrite.inputs:usePath", True),
                ("CubeRead.inputs:name", "size"),
                ("CubeRead.inputs:primPath", "/Cube"),
                ("CubeRead.inputs:usePath", True),
            ],
            keys.CONNECT: [
                ("OnTick.outputs:tick", "CubeWrite.inputs:execIn"),
                ("A.outputs:isPressed", "ToDouble1.inputs:value"),
                ("D.outputs:isPressed", "ToDouble2.inputs:value"),
                ("ToDouble2.outputs:converted", "Negate.inputs:a"),
                ("NegOne.inputs:value", "Negate.inputs:b"),
                ("ToDouble1.outputs:converted", "DeltaAdd.inputs:a"),
                ("Negate.outputs:product", "DeltaAdd.inputs:b"),
                ("DeltaAdd.outputs:sum", "SizeAdd.inputs:a"),
                ("CubeRead.outputs:value", "SizeAdd.inputs:b"),
                ("SizeAdd.outputs:sum", "CubeWrite.inputs:value"),
            ],
        },
    )

Note

For input that are bundle types, such as the “Prim” input inside the WritePrimAttribute node, you may not be able to set their values this way. This is circumvented by allowing users to specify a path or a token to the bundle target. In those cases, make sure the “Use Path” option box is checked.

2.3. Summary

In this tutorial, we introduced scripting OmniGraph via Python.

2.3.1. Further Reading

For more Python Scripting in OmniGraph