I am trying to start a C++ ROS node from python code. The python code uses the last message of several topics every 50ms. There are about 10k messages per second being sent and rclpy could not handle that, so to improve perfomance I wrote a small C++ node that exposes bindings (using pybind11) to a start_node function to start the C++ node and a get_buffer method that returns the last unserialized message bytes for all topics.

Diagram of the Communication between python and C++

When running colcon build I can find the module at colcon_ws/build/cpp_subscriber/cpp_subscriber.cpython-311-x86_64-linux-gnu.so. ament_python_install_module then makes this module available for all other packages that depend on the cpp_subscriber ROS package.

This works but it creates a package called cpp_subscriber which serves no purpose at all. My goal would be to only have one package for the python code with a build type of ament_cmake that uses ament_python_install_package. The problem is that calling ament_python_install_package does not work on its own, if I remove ament_package() at the bottom, then nothing happens at all, if I leave it in, it will still create two packages. Is there a way to get around this and only end up with a single package?

Currently I have the following CMakeLists.txt for the cpp_subscriber package and simply depend on cpp_subscriber in my python package

cmake_minimum_required(VERSION 3.8)

  add_compile_options(-Wall -Wextra -Wpedantic)

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

# Python magic
find_package(ament_cmake_python REQUIRED)

# It is also possible to include pybind11 as a git submodule
# See: https://pybind11.readthedocs.io/en/stable/compiling.html#find-package-vs-add-subdirectory
find_package(Python3 REQUIRED COMPONENTS Development)
find_package(pybind11 REQUIRED)

# Create Library for subscriber
# Building the rclcpp node separately is easier because
# pybind11 doesn't properly import the rclcpp libraries for some reason
add_library(SubscriberLib SHARED src/subscriber.cpp)
target_link_libraries(SubscriberLib PUBLIC rclcpp::rclcpp)

# Create a python module called cpp_subscriber which links to the SubscriberLib
# This module exposes the functionality for the python script
pybind11_add_module(cpp_subscriber MODULE src/bindings.cpp)
target_link_libraries(cpp_subscriber PUBLIC SubscriberLib)

# ament_python_install_module will throw an error if the file does not exist yet
# even though the copying only happens after the build, to prevent the build from failing
# an empty dummy file gets created
set(PythonModuleName "cpp_subscriber.${Python3_SOABI}.so")
file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/${PythonModuleName})

# Install the cpp_subscriber as a python module

  • $\begingroup$ Not sure if the question is clear to me. You want to start a cpp node, which is now a component, with a python node script, without using a launch file? Is that correct ? $\endgroup$
    – Vishaal
    Commented May 15 at 9:09
  • $\begingroup$ Pretty much yes, I just added more context to the question to hopefully clarify what I am trying to achieve :) $\endgroup$
    – AKORA
    Commented May 25 at 9:11


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.