ros_logo ROS

Warning

This feature is experimental and subject to breaking changes. See the Conan stability section for more information.

Conan provides integration for your Robot Operating System (ROS) C/C++ based projects. This will allow you to consume Conan packages inside your ROS package projects. The Conan packages can be installed and used in CMake with the help of the ROSEnv generator created for the purpose.

It provides a clean integration that requires no Conan-specific modifications in your CMakeLists.txt.

Important

This integration supports ROS2, it has been developed using its Humble version and the aim is to support newer versions going forward. If you have any issues with other ROS versions, please let us know by opening an issue in our GitHub repository.

Note

Pre-requisites to run the example:

  1. In order to run the example, it is exepected that you have an Ubuntu environment (22.04 LTS preferred) with ROS2 Humble version installed. You can use the Docker image osrf/ros:humble-desktop instead as well.

  2. The files for this example can be found at our examples repository. Clone it like so to get started:

    $ git clone https://github.com/conan-io/examples2.git && cd examples2/examples/tools/ros/rosenv
    

Consuming Conan packages using the ROSEnv generator

Imagine we have a ROS C++ package called str_printer that uses some functionality from the third party string formatting library fmt to print fancy strings.

We have the following project structure:

$  tree /f
workspace
├───str_printer
│      CMakeLists.txt
│      conanfile.txt
│      package.xml
│   ├───include
│      └──str_printer
│            str_printer.h
│   └───src
│          str_printer.cpp
└───consumer
       CMakeLists.txt
       package.xml
    └───src
           main.cpp

Where:

  • The str_printer is a ROS package that implements a function and depends on the fmt Conan package.

  • The consumer is also a ROS package that depends on the str_printer ROS package and uses its functionality in a final executable.

The only difference in the str_printer package with respect to a normal ROS package is that it includes a conanfile.txt file. This is the file used by Conan to install the required dependencies and generate the files needed to perform the build.

str_printer/conanfile.txt
 [requires]
 fmt/11.0.2

 [generators]
 CMakeDeps
 CMakeToolchain
 ROSEnv

In this case, we will install the 11.0.2 version of fmt and Conan will generate files for CMake and ROS so we can build the str_printer package later.

To install the fmt library using Conan we should do the following:

$ cd workspace
$ conan install str_printer/conanfile.txt --build missing --output-folder install/conan
======== Computing dependency graph ========
fmt/11.0.2: Not found in local cache, looking in remotes...
fmt/11.0.2: Checking remote: conancenter
fmt/11.0.2: Downloaded recipe revision 5c7438ef4d5d69ab106a41e460ce11f3
Graph root
    conanfile.txt: /home/user/examples2/examples/tools/ros/rosenv/workspace/str_printer/conanfile.txt
Requirements
    fmt/11.0.2#5c7438ef4d5d69ab106a41e460ce11f3 - Downloaded (conancenter)

======== Computing necessary packages ========
Requirements
    fmt/11.0.2#5c7438ef4d5d69ab106a41e460ce11f3:29da3f322a17cc9826b294a7ab191c2f298a9f49#d8d27fde7061f89f7992c671d98ead71 - Download (conancenter)

======== Installing packages ========

-------- Downloading 1 package --------
fmt/11.0.2: Retrieving package 29da3f322a17cc9826b294a7ab191c2f298a9f49 from remote 'conancenter'
fmt/11.0.2: Package installed 29da3f322a17cc9826b294a7ab191c2f298a9f49
fmt/11.0.2: Downloaded package revision d8d27fde7061f89f7992c671d98ead71

======== Finalizing install (deploy, generators) ========
conanfile.txt: Writing generators to /home/user/examples2/examples/tools/ros/rosenv/workspace/install/conan
conanfile.txt: Generator 'CMakeDeps' calling 'generate()'
conanfile.txt: CMakeDeps necessary find_package() and targets for your CMakeLists.txt
    find_package(fmt)
    target_link_libraries(... fmt::fmt)
conanfile.txt: Generator 'CMakeToolchain' calling 'generate()'
conanfile.txt: CMakeToolchain generated: conan_toolchain.cmake
conanfile.txt: Preset 'conan-release' added to CMakePresets.json. Invoke it manually using 'cmake --preset conan-release' if using CMake>=3.23
conanfile.txt: If your CMake version is not compatible with CMakePresets (<3.23) call cmake like: 'cmake <path> -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=/home/danimtb/examples2/examples/tools/ros/rosenv/workspace/install/conan/conan_toolchain.cmake -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release'
conanfile.txt: CMakeToolchain generated: CMakePresets.json
conanfile.txt: CMakeToolchain generated: ../../str_printer/CMakeUserPresets.json
conanfile.txt: Generator 'ROSEnv' calling 'generate()'
conanfile.txt: Generated ROSEnv Conan file: conanrosenv.sh
Use 'source /home/user/examples2/examples/tools/ros/rosenv/workspace/install/conan/conanrosenv.sh' to set the ROSEnv Conan before 'colcon build'
conanfile.txt: Generating aggregated env files
conanfile.txt: Generated aggregated env files: ['conanrosenv.sh']
Install finished successfully

This will download the fmt Conan package to the local cache and generate the CMake and ROS environment files in the conan subfolder of the install directory.

Now we can source our ROS environment, then source the Conan ROSEnv environment, so the conan-installed package are found by CMake, and then we can build the str_printer package as usual with Colcon.

$ source /opt/ros/humble/setup.bash
$ source install/conan/conanrosenv.sh
$ colcon build --packages-select str_printer
Starting >>> str_printer
Finished <<< str_printer [10.8s]

Summary: 1 package finished [12.4s]

Bridging the Conan-provided transitive dependencies to another ROS package

As the consumer ROS package depends on str_printer, the targets of transitive dependencies should be exported. This is done as usual in the str_printers’s CMakeLists.txt using ament_export_dependencies():

str_printer/CMakeLists.txt
 cmake_minimum_required(VERSION 3.8)
 project(str_printer)

 if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
 add_compile_options(-Wall -Wextra -Wpedantic)
 endif()

 # find dependencies
 find_package(ament_cmake REQUIRED)
 find_package(fmt REQUIRED)  # Retrieved with Conan C/C++ Package Manager

 add_library(str_printer src/str_printer.cpp)

 target_include_directories(str_printer PUBLIC
 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/str_printer>
 $<INSTALL_INTERFACE:include>)

 target_compile_features(str_printer PUBLIC c_std_99 cxx_std_17)  # Require C99 and C++17
 ament_target_dependencies(str_printer fmt)

 ament_export_targets(str_printerTargets HAS_LIBRARY_TARGET)
 ament_export_dependencies(fmt)

 install(
 DIRECTORY include/
 DESTINATION include
 )

 install(
 TARGETS str_printer
 EXPORT str_printerTargets
 LIBRARY DESTINATION lib
 ARCHIVE DESTINATION lib
 RUNTIME DESTINATION bin
 INCLUDES DESTINATION include
 )

 ament_package()

To build the consumer ROS package, you can proceed as usual (make sure that you have both the ROS environment and the Conan ROSEnv environment sourced before building as in previous step):

$ colcon build --packages-select consumer
Starting >>> consumer
Finished <<< consumer [7.9s]

Summary: 1 package finished [9.4s]

And after this, our consumer application should be ready to run with just:

$ source install/setup.bash
$ ros2 run consumer main
Hi there! I am using fmt library fetched with Conan C/C++ Package Manager

See also