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 
Note
This tutorial is currently supported only on Linux with ROS 2 Humble.
Getting Started#
Prerequisite
- Basic understanding of building ROS 2 packages 
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 Creating custom msg and srv files.
Note
You only need to complete the steps up to subsection 6. Confirm msg and srv creation.
Important
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.
- Run - ./build.shinside the directory to build the sample extensions
- Ensure that - ./_build/linux-x86_64/release/omni.app.kit.dev.shworks as expected
- Next, download a sample custom extension which will be used for this tutorial: 
- Extract the - omni.example.cpp.omnigraph_node_rosfolder into- source/extensionsunder the- Kit Extension C++ template folderwhich you cloned in the previous steps.
- Add the following lines at the end of the - deps/kit-sdk-deps.packman.xmlfile, 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 - pathaccording 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.luafile can find the relevant ROS 2 headers and libraries on your system. These are needed for building our custom nodes.
- Run - ./build.shto build our new extension with ROS 2 OmniGraph nodes- Important - Provide the complete paths for the - source_pathunder 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#
For adding the extension and corresponding nodes into Isaac Sim, we need to:
- Source the - install/local_setup.bashof the workspace containing the- tutorial_interfacespackage created above.- Warning - Note that we do not source the ROS 2 installation. Doing so may cause symbol conflicts due to differences in Python versions between the ROS 2 distribution (e.g.: Python 3.10 for Humble) and Isaac Sim (Python 3.11). - source install/local_setup.bash 
- Run Isaac Sim from this terminal. 
- Go to - Window->Extensions, look for the- hamburgersymbol (1) to the right side of the search bar (just above- Third Partytab). Click- Settings(2).
- Click the - +icon under- Extension Search Pathsand 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).
- Your new extensions will now show up under the - Third Partytab (3).
- Enable the - Custom ROS2 OGN Example Extension.- Note - If you see an error such as below it is likely because your custom - tutorial_interfacespackage is not sourced correctly:- Error: libtutorial_interfaces__rosidl_typesupport_c.so: cannot open shared object file: No such file or directory (Additional information may be available by running the process with the LD_DEBUG environment variable set) 
Building the Action Graph and Running the nodes#
Ensure you have followed all the steps in the previous sections.
With the Custom ROS2 OGN Example Extension enabled, we will create an ActionGraph with the new ROS 2 nodes.
- Go to - Window > Graph Editors > Action Graph:
- Hit - Playon the scene and the nodes should start publishing to ROS 2.
- You can verify by opening a new terminal and sourcing your ROS 2 workspace in it. Then, running - ros2 topic listshould show the 2 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.luahandles 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
    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. We use therclROS 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 Incondition is true, this is where the node and publisher is initially created. The message is also published from this function.
 
 
- The OmniGraph nodes are present under 
Summary#
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 Launch to learn how to deploy Isaac Sim via ROS 2 Launch.
 
