developer.nvidia.com

Command Palette

Search for a command to run...

ROS 2 Custom C++ OmniGraph Node — Isaac Sim Documentation

Last updated: 12/12/2025

Title: ROS 2 Custom C++ OmniGraph Node#

URL Source: https://docs.isaacsim.omniverse.nvidia.com/latest/ros2_tutorials/tutorial_ros2_omnigraph_cpp_node.html

Published Time: Tue, 21 Oct 2025 19:25:26 GMT

Markdown Content: Learning Objectives#

In this example, you learn how to:

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

Note

This tutorial is supported only on Linux with ROS 2 Humble.

Getting Started#

Prerequisite

Building a Custom Message Package#

To use our custom message with Isaac Sim, you must build the custom message package with ROS 2. 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 Creating custom msg and srv files.

Important

Follow the package and message naming terminologies provided in the official tutorials, they are important when you build your own C++ OmniGraph nodes.

Setting Up Kit Extension C++ Template#

To use the custom ROS 2 OmniGraph nodes, you must build your own extension, which contains the necessary C++ code. We strongly recommend reviewing Omniverse Kit Extension Template C++, the ReadMe provided with the repository is a good starting point for this.

  1. Clone Omniverse Kit Extension Template C++ and switch to the release/107.3.0 branch (in the root folder: git checkout release/107.3.0).

  2. Run ./build.sh inside the directory to build the sample extensions.

  3. Ensure that ./_build/linux-x86_64/release/omni.app.kit.dev.sh works as expected.

  4. Download a sample custom extension, which will be used for this tutorial:

  5. Extract the omni.example.cpp.omnigraph_node_ros folder into source/extensions under the Kit Extension C++ template folder, which you cloned in the previous steps.

  6. Add the following lines at the end of the deps/kit-sdk-deps.packman.xml file, before the </project> closing tag:

<dependency name="system_ros" linkPath="../_build/target-deps/system_ros" tags="${config}"> <source path="<FULL_PATH_TO_THE_ROS_2_INSTALL>" /> </dependency> <dependency name="additional_ros_workspace" linkPath="../_build/target-deps/additional_ros" tags="${config}"> <source path="<FULL_PATH_TO_WORKSPACE_CREATED_ABOVE>/install/tutorial_interfaces" /> </dependency> Update the source `path` according to your local setup. For example:
  • <FULL_PATH_TO_THE_ROS_2_INSTALL>: /opt/ros/humble

    • <FULL_PATH_TO_WORKSPACE_CREATED_ABOVE>: /home/user/ros2_ws

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 your custom nodes.

  1. Run ./build.sh to build your new extension with ROS 2 OmniGraph nodes.

Important

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.

Adding the Extension to Isaac Sim#

To add the extension and corresponding nodes into Isaac Sim:

  1. Source the install/local_setup.bash of the workspace containing the tutorial_interfaces package created above.

Note

We do not source the ROS 2 installation. Doing so can cause symbol conflicts from differences in Python versions between the ROS 2 distributions (for example, Python 3.10 for Humble) and Isaac Sim (Python 3.11). source install/local_setup.bash

  1. Run Isaac Sim from this terminal.

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

  3. 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).

  4. Verify that your extensions are under the Third Party tab (3).

Image 1: Adding extensions to Isaac Sim

  1. Enable the Custom ROS2 OGN Example Extension.

Note

If you observe an error, such as below, it is likely because your custom tutorial_interfaces package is not sourced correctly:

Error: libtutorial_interfaces__rosidl_typesupport_c.so: cannot open shared object file: No such file or directory (Additional information might be available by running the process with the LD_DEBUG environment variable set)

Building the Action Graph and Running the Nodes#

Complete all the steps in the previous sections.

With the Custom ROS2 OGN Example Extension enabled, to create an ActionGraph with the new ROS 2 nodes:

  1. Go to Window > Graph Editors > Action Graph:
  • Search for ROS 2 in the Action Graph tab, drag both the nodes: ROS 2 Publish Custom Message 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.

Image 2: Custom C++ ROS2 OGN Example Extension ActionGraph

  1. Click Play on the scene and the nodes start publishing to ROS 2.

  2. Verify the publishing, by opening a new terminal and sourcing your ROS 2 workspace in it. Then, verify that running ros2 topic list shows the two available topics:

/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

Deeper Dive into Nodes and Extension#

  • The premake5.lua handles building of the extension, review the section, which handles the compiling and linking against the 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 add_ogn_dependencies(ogn)

includedirs { -- System level ROS includes "%{target_deps}/system_ros/include/std_msgs",

"%{target_deps}/system_ros/include/geometry_msgs",

"%{target_deps}/system_ros/include/rosidl_runtime_c",

"%{target_deps}/system_ros/include/rosidl_typesupport_interface",

"%{target_deps}/system_ros/include/rcl",

"%{target_deps}/system_ros/include/rcutils",

"%{target_deps}/system_ros/include/rmw",

"%{target_deps}/system_ros/include/rcl_yaml_param_parser",

-- Additional sourced ROS workspace includes "%{target_deps}/additional_ros/include/tutorial_interfaces", }

libdirs { -- System level ROS libraries "%{target_deps}/system_ros/lib",

-- Additional sourced ROS workspace libraries "%{target_deps}/additional_ros/lib", }

links{ -- 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", }

filter { "system:linux" } linkoptions { "-Wl,--export-dynamic" }

cppdialect "C++17"

  • The OmniGraph nodes are present under plugins/nodes. The rcl ROS 2 API is used for creating and working with the ROS 2 components in the 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.

Summary#

This tutorial covered the following topics:

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

  • Using these nodes with Isaac Sim

Next Steps#

Continue on to the next tutorial in the ROS2 Tutorials series, ROS 2 Launch to learn how to deploy Isaac Sim using ROS 2 Launch.

Links/Buttons:

Related Articles