ROS 2 Custom C++ OmniGraph Node

Learning Objectives

In this example we will learn how to

  • Write our custom C++ OmniGraph node to use with Isaac Sim


This tutorial is currently supported only on Linux with ROS 2 Foxy and Humble

Getting Started


Building a Custom Message Package

To use our custom message with Isaac Sim we fist need to build our custom message package with ROS 2. We will follow the custom message sample in the official ROS 2 documentation. The definition of the message is:

geometry_msgs/Point center
float64 radius

Follow the instructions on the ROS 2 Humble Documentation for building the custom humble message package.

You only need to complete the steps up to confirming humble message creation (step 6)

Follow the instructions on the ROS 2 Foxy Documentation for building the custom foxy message package.

You only need to complete the steps up to confirming foxy message creation (step 6)


Please make sure you follow the package and message naming terminologies provided in the official tutorials, they are important when we will build our own C++ OmniGraph nodes.

Setting up Kit Extension C++ Template

In order to use our custom ROS 2 OmniGraph nodes, we will need to build our own extension which contains the necessary C++ code. We strongly recommend spending some time understanding how Omniverse Kit Extension Template C++ works, the ReadMe provided with the repository is a good starting point for this.


  • Clone Omniverse Kit Extension Template C++

  • Run ./ inside the directory to build the sample extensions

  • Ensure that ./_build/linux-x86_64/release/ works as expected

Next, download a sample custom extension which will be used for this tutorial:

  • Extract the custom.ros2_cpp.omnigraph_node folder into source/extensions under the Kit Extension C++ template folder which you cloned in the previous steps.

  • Add the following lines at the end of the deps/kit-sdk-deps.packman.xml file

    <dependency name="system_ros" linkPath="../_build/target-deps/system_ros" tags="${config}">
    <source path="<path_to_your_system_ros_install>" />
    <dependency name="additional_ros_workspace" linkPath="../_build/target-deps/additional_ros" tags="${config}">
    <source path="<path_to_custom_message_ws_created_in_step1>/install/tutorial_interfaces" />

    Adding this ensures that the premake5.lua file can find the relevant ROS 2 headers and libraries on your system. These are needed for building our custom nodes.

  • Run ./ to build our new extension with ROS 2 OmniGraph nodes


Provide the complete paths for the source_path under both the dependencies. This is needed to ensure the extension is built against your local ROS workspace and installation.

Enabling the extension and Running our Nodes

Next, we will load our new extension and try to use the new nodes

  • Source your ROS 2 installation

  • Source the ROS 2 workspace which contains the tutorial_interfaces package which you created in the first step.

  • Run ./_build/linux-x86_64/release/ from the Kit Extension C++ template folder

  • Go to Window->Extensions and search for ROS 2, an extension named Custom ROS2 OGN Example Extension should show up. Enable this extension

  • Search for Action Graph Editor and enable this too (Install and enable if not present)

  • Search for Omnigraph Action Graph extension and enable it.

With the extensions enabled, we wil create an ActionGraph with the new ROS 2 nodes

  • Go to Create->Visual Scripting-> Action Graph
    • Search for ROS 2 in the Action Graph tab, drag both the nodes: ROS 2 Publish Custom Message Node and ROS 2 Publish String in the graph.

    • Search for Playback Tick and drag the node into the graph.

    • Connect Tick from the On Playback Tick node to Exec In for both the ROS 2 nodes.

  • Hit Play on the scene and the nodes should start publishing to ROS 2.

  • You can verify the same by opening a new terminal and sourcing your ROS 2 workspace in it. The 2 topics are:

    /custom_node/my_string # This topic has a string being published
    /custom_node/sphere_msg # This topic has the custom "SphereMsg" created in step 1 being published

Adding the Extension to Isaac Sim

For adding the extension and corresponding nodes into Isaac Sim, we need to:

  1. Source your ROS 2 installation and workspace containing the tutorial_interfaces package.

  2. Run Isaac Sim from this terminal

  3. Go to Window->Extensions, look for the hamburger symbol to the right side of the search bar (just above Third Party tab). Click Settings

  4. Click the + icon under Extension Search Paths and add the path to your built extension in the previous section (your built extensions are under kit-extension-template-cpp/_build/linux-x86_64/release/exts)

  5. Your new extensions will now show up under the Third Party tab. Enable the Custom ROS2 OGN Example Extension

  6. Follow the same steps as the previous section to build an action graph with the new nodes and run it with Isaac Sim

You can follow the same workflow for creating and using your own custom ROS 2 OmniGraph nodes and use them with Isaac Sim

Deeper Dive into Nodes and Extension

  • The premake5.lua handles building of the extension, lets look at the section which handles the compiling and linking against our specified ROS install paths:

# Build the C++ plugin that will be loaded by the extension.
project_ext_plugin(ext, ogn.plugin_project)
    # It is important that you add all subdirectories containing C++ code to this project
    add_files("source", "plugins/"..ogn.module)
    add_files("nodes", "plugins/nodes")

    # Add the standard dependencies all OGN projects have; includes, libraries to link, and required compiler flags

    includedirs {
        # System level ROS includes

        # Additional sourced ROS workspace includes

    libdirs {
        # System level ROS libraries

        # Additional sourced ROS workspace libraries

        #  Minimal ROS 2 C API libs needed for your nodes to work
        "rosidl_runtime_c", "rcutils", "rcl", "rmw",

        # For the simple string message, add the deps
        "std_msgs__rosidl_typesupport_c", "std_msgs__rosidl_generator_c",

        # Add dependencies of the custom message with its libs
        "geometry_msgs__rosidl_typesupport_c", "geometry_msgs__rosidl_typesupport_c",
        "tutorial_interfaces__rosidl_typesupport_c", "tutorial_interfaces__rosidl_generator_c",
  • The OmniGraph nodes are present under plugins/nodes. We use the rcl ROS 2 API for creating and working with the ROS 2 components in our OmniGraph node:
    • In the C++ Node, compute() is called when the Exec In condition is true, this is where the node and publisher is initially created. The message is also published from this function.


This tutorial covered the following topics:

  • Building our own extension which contains ROS 2 C++ OmniGraph nodes

  • Using these nodes with Isaac Sim

Next Steps

Continue on to the next tutorial in our ROS2 Tutorials series, ROS 2 Ackermann Steering.