ROS2: How to use custom message in project where it's declared?

I’ve created C++ ROS2 project with a custom message as explained here: https://github.com/ros2/ros2/wiki/Defining-custom-interfaces-(msg-srv)

I can see the message is generated properly and .h.hpp files are installed.

Now I want to use this custom message in the same project where it’s generated. But I can’t reference the header file of my generated message from the same project.

Here is my CMakeList.txt:

cmake_minimum_required(VERSION 3.5)

project(bridge_test_msgs)

if(NOT WIN32)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -Wall -Wextra -Wpedantic")
endif()

find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_lifecycle REQUIRED)
find_package(rosidl_default_generators REQUIRED)

set(msg_files
  "msg/BridgeTestMessage.msg"
)
rosidl_generate_interfaces(${PROJECT_NAME}
  ${msg_files}
  ADD_LINTER_TESTS
)


include_directories(
  ${rclcpp_INCLUDE_DIRS}
  ${rclcpp_lifecycle_INCLUDE_DIRS}
  ${std_msgs_INCLUDE_DIRS}
#    ${${PROJECT_NAME}_INCLUDE_DIRS}
)

add_executable(my_publisher
    src/my_publisher.cpp
)

target_link_libraries(my_publisher
  ${rclcpp_LIBRARIES}
  ${rclcpp_lifecycle_LIBRARIES}
  ${std_msgs_LIBRARIES}

#        ${PROJECT_NAME}
#        ${PROJECT_NAME}_LIBRARIES
#        ${${PROJECT_NAME}_LIBRARIES}
)
add_dependencies(my_publisher ${PROJECT_NAME})

ament_target_dependencies(my_publisher
        "rclcpp"
        "rclcpp_lifecycle"
        "std_msgs"

        "${PROJECT_NAME}"
)

install(TARGETS
        my_publisher
        DESTINATION bin
)

ament_export_dependencies(rosidl_default_runtime)
ament_package()

Inside src/my_publisher.cpp I have a line:
#include “bridge_test_msgs/msg/bridge_test_message.hpp”

Command ‘ament build’ fails with message:

my_publisher.cpp:7:56: fatal error: bridge_test_msgs/msg/bridge_test_message.hpp: No such file or directory
compilation terminated.
CMakeFiles/my_publisher.dir/build.make:62: recipe for target 'CMakeFiles/my_publisher.dir/src/my_publisher.cpp.o' failed
make[2]: *** [CMakeFiles/my_publisher.dir/src/my_publisher.cpp.o] Error 1
CMakeFiles/Makefile2:288: recipe for target 'CMakeFiles/my_publisher.dir/all' failed
make[1]: *** [CMakeFiles/my_publisher.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2

I can see header file exists:

$ ls install/include/bridge_test_msgs/msg/bridge_test_message.hpp 
-rw-r--r-- 1 mc mc 415 Jun 27 15:00 install/include/bridge_test_msgs/msg/bridge_test_message.hpp

Could you hint me how to reference custom message from the project itself?

1 Like

It’s true that most our message package are pure message packages and thus do not try to include/link against themselves. The trick here is that you need to use the macro rosidl_target_interfaces

rosidl_target_interfaces(MY_TARGET_NAME
      ${PROJECT_NAME} "rosidl_typesupport_cpp")

You can look at the composition demo CMake code for an example.

I agree that this is not well documented and that an addition to https://github.com/ros2/ros2/wiki/Defining-custom-interfaces-(msg-srv) would be valuable

5 Likes

Yeah. That worked for me. Thank you!

For closure: I added this documentation: https://github.com/ros2/ros2_documentation/pull/339

That works. Many thanks : )