From 8db4dc2b2c185a4ce0e1afef3d7d0d3e66131686 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sat, 21 Sep 2024 21:19:01 -0700 Subject: [PATCH 01/17] Polish the ROS 1 -> 2 CMake instructions WIP. Progress so far: * Use section headings to CMakeLists.txt steps appear in the TOC * Use modern CMake targets instead of standard CMake variables * Use Active voice and second person perspective * Include links to real examples Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 195 ++++++++++++++---- 1 file changed, 152 insertions(+), 43 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index dcb9e71ac5..b8e45e9cf1 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -17,51 +17,169 @@ Build tool Instead of using ``catkin_make``, ``catkin_make_isolated`` or ``catkin build`` ROS 2 uses the command line tool `colcon `__ to build and install a set of packages. See the :doc:`beginner tutorial <../../Tutorials/Beginner-Client-Libraries/Colcon-Tutorial>` to get started with ``colcon``. -Build system ------------- +Update your ``CMakeLists.txt`` to use *ament_cmake* +--------------------------------------------------- -The build system in ROS 2 is called `ament `__. -Ament is built on CMake: ``ament_cmake`` provides CMake functions to make writing ``CMakeLists.txt`` files easier. +ROS 2 C++ packages use `CMake `__ with convenience functions provided by `ament_cmake `__. +Apply the following changes to use ``ament_cmake`` instead of ``catkin``. -Update the *CMakeLists.txt* to use *ament_cmake* -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Apply the following changes to use ``ament_cmake`` instead of ``catkin``: +Set the build type to ament_cmake +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Add an ```` section to your ``package.xml`` if it does not have one already. +Set the ```` to ``ament_cmake`` (`example `__) -* - Set the build type in the ``package.xml`` file export section: +.. code-block:: xml - .. code-block:: xml + + ament_cmake + - - ament_cmake - +Add a call to ``ament_package()`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* - Replace the ``find_package`` invocation with ``catkin`` and the ``COMPONENTS`` with: +Insert a call to ``ament_package()`` at the bottom of your ``CMakeLists.txt`` (`example `__) - .. code-block:: cmake +.. code-block:: cmake - find_package(ament_cmake REQUIRED) - find_package(component1 REQUIRED) - # ... - find_package(componentN REQUIRED) + # Add this to the bottom of your CMakeLists.txt + ament_package() -* - Move and update the ``catkin_package`` invocation with: +Update ``find_package()`` calls +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Replace the ``find_package(catkin COMPONENTS ...)`` call with individual ``find_package()`` calls: - * - Invoke ``ament_package`` instead but **after** all targets have been registered. +For example, change this: - * - The only valid argument for `ament_package `__ is ``CONFIG_EXTRAS``. - All other arguments are covered by separate functions which all need to be invoked *before* ``ament_package``: +.. code-block:: none + + find_package(catkin REQUIRED COMPONENTS foo bar std_msgs) + find_package(baz REQUIRED) + +To this: + +.. code-block:: cmake + + find_package(ament_cmake REQUIRED) + find_package(foo REQUIRED) + find_package(bar REQUIRED) + find_package(std_msgs REQUIRED) + find_package(baz REQUIRED) + + +Use modern CMake targets +^^^^^^^^^^^^^^^^^^^^^^^^ + +Remove all uses of ``include_directories()``. +Use ``target_include_directories()`` to associate the include directories with the ``my_library`` target (`example `__): + +.. code-block:: cmake + + target_include_directories(my_library PUBLIC + "$" + "$") + +Change all ``target_link_libraries()`` calls to use modern CMake targets. +For example, if your package in ROS 1 looks something like this: + +.. code-block:: none + + target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES}) + +Then change it to something like this: + +.. code-block:: cmake + + target_link_libraries(my_library PUBLIC foo::foo bar::bar ${std_msgs_TARGETS} baz::baz) + +Prefer to use specific modern CMake targets such as ``rclcpp::rclcpp`` whenever possible. +Use ``${package_name_TARGETS}`` if the package you're depending on is a message package such as ``std_msgs``. + +Choose ``PUBLIC`` or ``PRIVATE`` based on how the dependency is used by your library (`example `__). + +* Use ``PUBLIC`` if the dependency is needed by downstream users, for example, a your library's public API uses it. +* Use ``PRIVATE`` if the dependency is used only internally by your library. + +Replace ``catkin_package()`` with various ``ament_cmake`` calls +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Imagine your ``CMakeLists.txt`` has a call to ``catkin_package`` like this: + +.. code-block:: none + + catkin_package( + INCLUDE_DIRS include + LIBRARIES my_library + CATKIN_DEPENDS foo bar std_msgs + DEPENDS baz + ) + + install(TARGETS my_library + ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} + RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} + ) - * Instead of passing ``CATKIN_DEPENDS ...`` call ``ament_export_dependencies(...)`` before. - * Instead of passing ``INCLUDE_DIRS ...`` call ``ament_export_include_directories(...)`` before. - * Instead of passing ``LIBRARIES ...`` call ``ament_export_libraries(...)`` before. + +Replacing ``catkin_package(INCLUDE_DIRS ...)`` +++++++++++++++++++++++++++++++++++++++++++++++ + +If you've used modern CMake targets and ``target_include_directories()``, you don't need to do anything further. +Users of your package won't see a ``your_package_INCLUDE_DIRS`` variable, but your users will get the include directories by depending on your modern CMake targets. + +Replacing ``catkin_package(LIBRARIES ...)`` ++++++++++++++++++++++++++++++++++++++++++++ + +Use ``ament_export_targets()`` and ``install(TARGETS ... EXPORT ...)`` to replace the ``LIBRARIES`` argument. + +Use the ``EXPORT`` keyword when installing your ``my_library`` target (`example `__). + +.. code-block:: cmake + + install(TARGETS my_library EXPORT export_my_package + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin + ) + +The above is a good default for library targets. +If your package used different ``CATKIN_*_DESTINATION`` variables, convert them as follows: + + * ``CATKIN_GLOBAL_BIN_DESTINATION``: ``bin`` + * ``CATKIN_GLOBAL_INCLUDE_DESTINATION``: ``include`` + * ``CATKIN_GLOBAL_LIB_DESTINATION``: ``lib`` + * ``CATKIN_GLOBAL_LIBEXEC_DESTINATION``: ``lib`` + * ``CATKIN_GLOBAL_SHARE_DESTINATION``: ``share`` + * ``CATKIN_PACKAGE_BIN_DESTINATION``: ``lib/${PROJECT_NAME}`` + * ``CATKIN_PACKAGE_INCLUDE_DESTINATION``: ``include/${PROJECT_NAME}`` + * ``CATKIN_PACKAGE_LIB_DESTINATION``: ``lib`` + * ``CATKIN_PACKAGE_SHARE_DESTINATION``: ``share/${PROJECT_NAME}`` + +Add a call to ``ament_export_targets()`` with the same name you gave to the ``EXPORT`` keyword (`example `__). + +.. code-block:: cmake + + ament_export_targets(export_my_package) + + +Replacing ``catkin_package(CATKIN_DEPENDS .. DEPENDS ..)`` +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Use `ament_export_dependencies `__ with all package names that were previously given to ``CATKIN_DEPENDS`` or ``DEPENDS``. + +.. code-block:: cmake + + ament_export_dependencies( + foo + bar + std_msgs + baz + ) + +Generate messages +^^^^^^^^^^^^^^^^^ * Replace the invocation of ``add_message_files``, ``add_service_files`` and ``generate_messages`` with `rosidl_generate_interfaces `__. @@ -87,21 +205,12 @@ Apply the following changes to use ``ament_cmake`` instead of ``catkin``: DEPENDENCIES std_msgs ) -* - Remove any occurrences of the *devel space*. - Related CMake variables like ``CATKIN_DEVEL_PREFIX`` do not exist anymore. +Remove references to the devel space +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Remove any references to the *devel space* such as ``CATKIN_DEVEL_PREFIX``. +There is no equivalent to the *devel space* in ROS 2. - * The ``CATKIN_DEPENDS`` and ``DEPENDS`` arguments are passed to the new function `ament_export_dependencies `__. - * ``CATKIN_GLOBAL_BIN_DESTINATION``: ``bin`` - * ``CATKIN_GLOBAL_INCLUDE_DESTINATION``: ``include`` - * ``CATKIN_GLOBAL_LIB_DESTINATION``: ``lib`` - * ``CATKIN_GLOBAL_LIBEXEC_DESTINATION``: ``lib`` - * ``CATKIN_GLOBAL_SHARE_DESTINATION``: ``share`` - * ``CATKIN_PACKAGE_BIN_DESTINATION``: ``lib/${PROJECT_NAME}`` - * ``CATKIN_PACKAGE_INCLUDE_DESTINATION``: ``include/${PROJECT_NAME}`` - * ``CATKIN_PACKAGE_LIB_DESTINATION``: ``lib`` - * ``CATKIN_PACKAGE_SHARE_DESTINATION``: ``share/${PROJECT_NAME}`` Unit tests ^^^^^^^^^^ From 02148be3bbf0d64deba86765bd7069e921d2e711 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 22 Sep 2024 08:52:31 -0700 Subject: [PATCH 02/17] Consistent headings Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index b8e45e9cf1..20b832ea16 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -124,13 +124,13 @@ Imagine your ``CMakeLists.txt`` has a call to ``catkin_package`` like this: Replacing ``catkin_package(INCLUDE_DIRS ...)`` -++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you've used modern CMake targets and ``target_include_directories()``, you don't need to do anything further. Users of your package won't see a ``your_package_INCLUDE_DIRS`` variable, but your users will get the include directories by depending on your modern CMake targets. Replacing ``catkin_package(LIBRARIES ...)`` -+++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use ``ament_export_targets()`` and ``install(TARGETS ... EXPORT ...)`` to replace the ``LIBRARIES`` argument. @@ -165,7 +165,7 @@ Add a call to ``ament_export_targets()`` with the same name you gave to the ``EX Replacing ``catkin_package(CATKIN_DEPENDS .. DEPENDS ..)`` -++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use `ament_export_dependencies `__ with all package names that were previously given to ``CATKIN_DEPENDS`` or ``DEPENDS``. From c9b10bb3d350016758f8c9b5d34e7f4aa2a5d218 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 18:10:01 -0700 Subject: [PATCH 03/17] Updates down to Testing section Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 152 ++++++++++++------ 1 file changed, 99 insertions(+), 53 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 20b832ea16..543693ee71 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -27,6 +27,13 @@ Apply the following changes to use ``ament_cmake`` instead of ``catkin``. Set the build type to ament_cmake ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Remove any dependencies on ``catkin`` from your package.xml + +.. code-block:: none + + # Remove this! + catkin + Add an ```` section to your ``package.xml`` if it does not have one already. Set the ```` to ``ament_cmake`` (`example `__) @@ -127,7 +134,7 @@ Replacing ``catkin_package(INCLUDE_DIRS ...)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you've used modern CMake targets and ``target_include_directories()``, you don't need to do anything further. -Users of your package won't see a ``your_package_INCLUDE_DIRS`` variable, but your users will get the include directories by depending on your modern CMake targets. +Users will get the include directories by depending on your modern CMake targets. Replacing ``catkin_package(LIBRARIES ...)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -147,15 +154,29 @@ Use the ``EXPORT`` keyword when installing your ``my_library`` target (`example The above is a good default for library targets. If your package used different ``CATKIN_*_DESTINATION`` variables, convert them as follows: - * ``CATKIN_GLOBAL_BIN_DESTINATION``: ``bin`` - * ``CATKIN_GLOBAL_INCLUDE_DESTINATION``: ``include`` - * ``CATKIN_GLOBAL_LIB_DESTINATION``: ``lib`` - * ``CATKIN_GLOBAL_LIBEXEC_DESTINATION``: ``lib`` - * ``CATKIN_GLOBAL_SHARE_DESTINATION``: ``share`` - * ``CATKIN_PACKAGE_BIN_DESTINATION``: ``lib/${PROJECT_NAME}`` - * ``CATKIN_PACKAGE_INCLUDE_DESTINATION``: ``include/${PROJECT_NAME}`` - * ``CATKIN_PACKAGE_LIB_DESTINATION``: ``lib`` - * ``CATKIN_PACKAGE_SHARE_DESTINATION``: ``share/${PROJECT_NAME}`` +.. list-table:: + :header-rows: 1 + + * - **catkin** + - **ament_cmake** + * - CATKIN_GLOBAL_BIN_DESTINATION + - bin + * - CATKIN_GLOBAL_INCLUDE_DESTINATION + - include + * - CATKIN_GLOBAL_LIB_DESTINATION + - lib + * - CATKIN_GLOBAL_LIBEXEC_DESTINATION + - lib + * - CATKIN_GLOBAL_SHARE_DESTINATION + - share + * - CATKIN_PACKAGE_BIN_DESTINATION + - lib/${PROJECT_NAME} + * - CATKIN_PACKAGE_INCLUDE_DESTINATION + - include/${PROJECT_NAME} + * - CATKIN_PACKAGE_LIB_DESTINATION + - lib + * - CATKIN_PACKAGE_SHARE_DESTINATION + - share/${PROJECT_NAME} Add a call to ``ament_export_targets()`` with the same name you gave to the ``EXPORT`` keyword (`example `__). @@ -181,28 +202,53 @@ Use `ament_export_dependencies `__. +If your package contains both C++ code and ROS message, service, or action definitions, then consider splitting it into two packages: + +* A package with only the ROS message, service, and/or action definitions +* A package with the C++ code + +Add the following dependencies to the ``package.xml`` of the package that contains ROS messages: +1. Add a ```` on ``rosidl_default_generators`` (`example `__) - * - The first argument is the ``target_name``. - If you're building just one library it's ``${PROJECT_NAME}`` + .. code-block:: xml - * - Followed by the list of message filenames, relative to the package root. + rosidl_default_generators +2. Add an ```` on ``rosidl_default_runtime`` (`example `__) - * If you will be using the list of filenames multiple times, it is recommended to compose a list of message files and pass the list to the function for clarity. + .. code-block:: xml - * - The final multi-value-keyword argument fpr ``generate_messages`` is ``DEPENDENCIES`` which requires the list of dependent message packages. + rosidl_default_runtime + +3. Add a ```` tag with the group name ``rosidl_interface_packages`` (`example `__) + + +In your ``CMakeLists.txt``, replace the invocation of ``add_message_files``, ``add_service_files`` and ``generate_messages`` with `rosidl_generate_interfaces `__. +The first argument must be ``${PROJECT_NAME}`` due to `this bug `__. + +For example, if your ROS 1 package looks like this: + +.. code-block:: none - .. code-block:: cmake + add_message_files(DIRECTORY msg FILES FooBar.msg Baz.msg) + add_service_files(DIRECTORY srv FILES Ping.srv) + + add_action_files(DIRECTORY action FILES DoPong.action) + generate_messages( + DEPENDENCIES actionlib_msgs std_msgs geometry_msgs + ) + +Then change it to this (`example `__) + +.. code-block:: cmake rosidl_generate_interfaces(${PROJECT_NAME} - ${msg_files} - DEPENDENCIES std_msgs + "msg/FooBar.msg" + "msg/Baz.msg" + "srv/Ping.srv" + "action/DoPong.action" + DEPENDENCIES actionlib_msgs std_msgs geometry_msgs ) Remove references to the devel space @@ -217,36 +263,36 @@ Unit tests If you are using gtest: -Replace ``CATKIN_ENABLE_TESTING`` with ``BUILD_TESTING``. -Replace ``catkin_add_gtest`` with ``ament_add_gtest``. - -.. code-block:: diff - - - if (CATKIN_ENABLE_TESTING) - - find_package(GTest REQUIRED) # or rostest - - include_directories(${GTEST_INCLUDE_DIRS}) - - catkin_add_gtest(${PROJECT_NAME}-some-test src/test/some_test.cpp) - - target_link_libraries(${PROJECT_NAME}-some-test - - ${PROJECT_NAME}_some_dependency - - ${catkin_LIBRARIES} - - ${GTEST_LIBRARIES}) - - endif() - + if (BUILD_TESTING) - + find_package(ament_cmake_gtest REQUIRED) - + ament_add_gtest(${PROJECT_NAME}-some-test src/test/test_something.cpp) - + ament_target_dependencies(${PROJECT_NAME)-some-test - + "rclcpp" - + "std_msgs") - + target_link_libraries(${PROJECT_NAME}-some-test - + ${PROJECT_NAME}_some_dependency) - + endif() - -Add ``ament_cmake_gtest`` to your ``package.xml``. - -.. code-block:: diff - - - rostest - + ament_cmake_gtest +* Replace ``CATKIN_ENABLE_TESTING`` with ``BUILD_TESTING``. +* Replace ``catkin_add_gtest`` with ``ament_add_gtest``. +* Add a ``find_package()`` ``ament_cmake_gtest``` instead of ``GTest`` + +For example, change the following code + +.. code-block:: none + + if (CATKIN_ENABLE_TESTING) + find_package(GTest REQUIRED) + include_directories(${GTEST_INCLUDE_DIRS}) + catkin_add_gtest(my_test src/test/some_test.cpp) + target_link_libraries(my_test + # ... + ${GTEST_LIBRARIES}) + endif() + +.. code-block:: CMake + if (BUILD_TESTING) + find_package(ament_cmake_gtest REQUIRED) + ament_add_gtest(my_test src/test/test_something.cpp) + target_link_libraries(my_test + #... + ) + endif() + +Add ``ament_cmake_gtest`` to your ``package.xml`` (`example `__). + +.. code-block:: xml + ament_cmake_gtest Linters ^^^^^^^ From 8f68e76c4615e34978cfdf75f2d3e5f16f8459a1 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 18:12:43 -0700 Subject: [PATCH 04/17] Active voice in Linters section Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 543693ee71..c38ee8182c 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -297,17 +297,18 @@ Add ``ament_cmake_gtest`` to your ``package.xml`` (`e Linters ^^^^^^^ -In ROS 2 we are working to maintain clean code using linters. -The styles for different languages are defined in our :doc:`Developer Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. +The ROS 2 code style guide is different than ROS 1 :doc:`Developer Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. -If you are starting a project from scratch it is recommended to follow the style guide and turn on the automatic linter unit tests by adding these lines just below ``if(BUILD_TESTING)``: +If you are starting a project from scratch, follow the ROS 2 style guide and turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: .. code-block:: cmake - find_package(ament_lint_auto REQUIRED) - ament_lint_auto_find_test_dependencies() + if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + ament_lint_auto_find_test_dependencies() + endif() -You will also need to add the following dependencies to your ``package.xml``: +Then, add the following dependencies to your ``package.xml``: .. code-block:: xml From c2f5d9e0a710e0b0b90b023e1bf76d27b864531a Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 18:35:24 -0700 Subject: [PATCH 05/17] Proofreading Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index c38ee8182c..e80d80a5e0 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -27,13 +27,19 @@ Apply the following changes to use ``ament_cmake`` instead of ``catkin``. Set the build type to ament_cmake ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Remove any dependencies on ``catkin`` from your package.xml +Remove any dependencies on ``catkin`` from your ``package.xml`` .. code-block:: none # Remove this! catkin +Add a new dependency on ``ament_cmake_ros`` (`example `__): + +.. code-block:: xml + + ament_cmake_ros + Add an ```` section to your ``package.xml`` if it does not have one already. Set the ```` to ``ament_cmake`` (`example `__) @@ -56,7 +62,7 @@ Insert a call to ``ament_package()`` at the bottom of your ``CMakeLists.txt`` (` Update ``find_package()`` calls ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Replace the ``find_package(catkin COMPONENTS ...)`` call with individual ``find_package()`` calls: +Replace the ``find_package(catkin COMPONENTS ...)`` call with individual ``find_package()`` calls (`example `_): For example, change this: @@ -69,7 +75,7 @@ To this: .. code-block:: cmake - find_package(ament_cmake REQUIRED) + find_package(ament_cmake_ros REQUIRED) find_package(foo REQUIRED) find_package(bar REQUIRED) find_package(std_msgs REQUIRED) @@ -79,8 +85,16 @@ To this: Use modern CMake targets ^^^^^^^^^^^^^^^^^^^^^^^^ -Remove all uses of ``include_directories()``. -Use ``target_include_directories()`` to associate the include directories with the ``my_library`` target (`example `__): +Prefer to use per-target CMake functions so that your package can export modern CMake targets. + +If your ``CMakeLists.txt`` uses ``include_directories()``, then delete those calls. + +.. code-block:: none + + # Delete calls to include_directories like this one! + include_directories(include ${catkin_INCLUDE_DIRS}) + +Add a call ``target_include_directories()`` for every library in your pacakage (`example `__). .. code-block:: cmake @@ -89,27 +103,25 @@ Use ``target_include_directories()`` to associate the include directories with t "$") Change all ``target_link_libraries()`` calls to use modern CMake targets. -For example, if your package in ROS 1 looks something like this: +For example, if your package in ROS 1 uses old-style standard CMake variables like this. .. code-block:: none target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES}) -Then change it to something like this: +Then change it to use specific modern CMake targets instead. +Use ``${package_name_TARGETS}`` if the package you're depending on is a message package such as ``std_msgs``. .. code-block:: cmake target_link_libraries(my_library PUBLIC foo::foo bar::bar ${std_msgs_TARGETS} baz::baz) -Prefer to use specific modern CMake targets such as ``rclcpp::rclcpp`` whenever possible. -Use ``${package_name_TARGETS}`` if the package you're depending on is a message package such as ``std_msgs``. - Choose ``PUBLIC`` or ``PRIVATE`` based on how the dependency is used by your library (`example `__). -* Use ``PUBLIC`` if the dependency is needed by downstream users, for example, a your library's public API uses it. -* Use ``PRIVATE`` if the dependency is used only internally by your library. +* Use ``PUBLIC`` if the dependency is needed by downstream users, for example, your library's public API uses it. +* Use ``PRIVATE`` if the dependency is only used internally by your library. -Replace ``catkin_package()`` with various ``ament_cmake`` calls +Replace ``catkin_package()`` with various ament_cmake calls ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Imagine your ``CMakeLists.txt`` has a call to ``catkin_package`` like this: @@ -134,7 +146,7 @@ Replacing ``catkin_package(INCLUDE_DIRS ...)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you've used modern CMake targets and ``target_include_directories()``, you don't need to do anything further. -Users will get the include directories by depending on your modern CMake targets. +Downstream users will get the include directories by depending on your modern CMake targets. Replacing ``catkin_package(LIBRARIES ...)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -188,7 +200,9 @@ Add a call to ``ament_export_targets()`` with the same name you gave to the ``EX Replacing ``catkin_package(CATKIN_DEPENDS .. DEPENDS ..)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Use `ament_export_dependencies `__ with all package names that were previously given to ``CATKIN_DEPENDS`` or ``DEPENDS``. +Downstream users also need to ``find_package()`` dependencies used in your public API. +In ROS 1 this was done with ``CATKIN_DEPENDS`` and ``DEPENDS`` arguments. +Use `ament_export_dependencies `__ to do this in ROS 2. .. code-block:: cmake @@ -261,13 +275,13 @@ There is no equivalent to the *devel space* in ROS 2. Unit tests ^^^^^^^^^^ -If you are using gtest: +If your package uses `gtest `__ then: * Replace ``CATKIN_ENABLE_TESTING`` with ``BUILD_TESTING``. * Replace ``catkin_add_gtest`` with ``ament_add_gtest``. -* Add a ``find_package()`` ``ament_cmake_gtest``` instead of ``GTest`` +* Add a ``find_package()`` for ``ament_cmake_gtest`` instead of ``GTest`` -For example, change the following code +For example, if your ROS 1 package adds tests like this: .. code-block:: none @@ -280,7 +294,10 @@ For example, change the following code ${GTEST_LIBRARIES}) endif() +Then change it to this: + .. code-block:: CMake + if (BUILD_TESTING) find_package(ament_cmake_gtest REQUIRED) ament_add_gtest(my_test src/test/test_something.cpp) @@ -292,6 +309,7 @@ For example, change the following code Add ``ament_cmake_gtest`` to your ``package.xml`` (`example `__). .. code-block:: xml + ament_cmake_gtest Linters @@ -299,13 +317,14 @@ Linters The ROS 2 code style guide is different than ROS 1 :doc:`Developer Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. -If you are starting a project from scratch, follow the ROS 2 style guide and turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: +If you are starting a project from scratch, follow the ROS 2 style guide, and turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: .. code-block:: cmake if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() + # ... endif() Then, add the following dependencies to your ``package.xml``: From f08324d0c242378e272c7ff2a68a17a06f4bea06 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 18:37:55 -0700 Subject: [PATCH 06/17] remove none Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index e80d80a5e0..f8de4cde21 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -29,7 +29,7 @@ Set the build type to ament_cmake Remove any dependencies on ``catkin`` from your ``package.xml`` -.. code-block:: none +.. code-block:: # Remove this! catkin @@ -66,7 +66,7 @@ Replace the ``find_package(catkin COMPONENTS ...)`` call with individual ``find For example, change this: -.. code-block:: none +.. code-block:: find_package(catkin REQUIRED COMPONENTS foo bar std_msgs) find_package(baz REQUIRED) @@ -89,7 +89,7 @@ Prefer to use per-target CMake functions so that your package can export modern If your ``CMakeLists.txt`` uses ``include_directories()``, then delete those calls. -.. code-block:: none +.. code-block:: # Delete calls to include_directories like this one! include_directories(include ${catkin_INCLUDE_DIRS}) @@ -105,7 +105,7 @@ Add a call ``target_include_directories()`` for every library in your pacakage ( Change all ``target_link_libraries()`` calls to use modern CMake targets. For example, if your package in ROS 1 uses old-style standard CMake variables like this. -.. code-block:: none +.. code-block:: target_link_libraries(my_library ${catkin_LIBRARIES} ${baz_LIBRARIES}) @@ -126,7 +126,7 @@ Replace ``catkin_package()`` with various ament_cmake calls Imagine your ``CMakeLists.txt`` has a call to ``catkin_package`` like this: -.. code-block:: none +.. code-block:: catkin_package( INCLUDE_DIRS include @@ -243,7 +243,7 @@ The first argument must be ``${PROJECT_NAME}`` due to `this bug `__ then: For example, if your ROS 1 package adds tests like this: -.. code-block:: none +.. code-block:: if (CATKIN_ENABLE_TESTING) find_package(GTest REQUIRED) From fefc16fa843de2a135d59f11b7d069fbb8d680f7 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 18:52:32 -0700 Subject: [PATCH 07/17] Misc updates to lower section Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 57 ++++++------------- 1 file changed, 17 insertions(+), 40 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index f8de4cde21..27b762dc6d 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -24,6 +24,17 @@ ROS 2 C++ packages use `CMake `__ with convenience functions Apply the following changes to use ``ament_cmake`` instead of ``catkin``. +Require a newer version of CMake +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ROS 2 relies on newer versions of CMake than used by ROS 1. +Find the minimum version of CMake used by the ROS distribution you want to support in `REP 2000 `__, and use that version at the top of your ``CMakeLists.txt``. +For example, `3.14.4 is the minimum recommended support for ROS Humble `__. + +.. code-block:: + + cmake_minimum_required(VERSION 3.14.4) + Set the build type to ament_cmake ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -462,13 +473,13 @@ Replace: Example: Converting an existing ROS 1 package to ROS 2 ------------------------------------------------------ -Let's say that we have simple ROS 1 package called ``talker`` that uses ``roscpp`` in one node, called ``talker``. +Say you have a ROS 1 package called ``talker`` that uses ``roscpp`` in one node, called ``talker``. This package is in a catkin workspace, located at ``~/ros1_talker``. The ROS 1 code ^^^^^^^^^^^^^^ -Here's the directory layout of our catkin workspace: +Your ROS 1 workspace has the following directory layout: .. code-block:: bash @@ -481,7 +492,7 @@ Here's the directory layout of our catkin workspace: ./src/talker/CMakeLists.txt ./src/talker/talker.cpp -Here is the content of those three files: +The files have the following content: ``src/talker/package.xml``: @@ -542,43 +553,10 @@ Here is the content of those three files: return 0; } -Building the ROS 1 code -~~~~~~~~~~~~~~~~~~~~~~~ - -We source an environment setup file (in this case for Noetic using bash), then we -build our package using ``catkin_make install``: - -.. code-block:: bash - - . /opt/ros/noetic/setup.bash - cd ~/ros1_talker - catkin_make install - -Running the ROS 1 node -~~~~~~~~~~~~~~~~~~~~~~ - -If there's not already one running, we start a ``roscore``, first sourcing the -setup file from our ``catkin`` install tree (the system setup file at -``/opt/ros/noetic/setup.bash`` would also work here): - -.. code-block:: bash - - . ~/ros1_talker/install/setup.bash - roscore - -In another shell, we run the node from the ``catkin`` install space using -``rosrun``, again sourcing the setup file first (in this case it must be the one -from our workspace): - -.. code-block:: bash - - . ~/ros1_talker/install/setup.bash - rosrun talker talker - Migrating to ROS 2 ^^^^^^^^^^^^^^^^^^ -Let's start by creating a new workspace in which to work: +Creating a new ROS 2 workspace: .. code-block:: bash @@ -811,10 +789,9 @@ Changing the CMake code ROS 2 relies on a higher version of CMake: -.. code-block:: bash +.. code-block:: - #cmake_minimum_required(VERSION 2.8.3) - cmake_minimum_required(VERSION 3.5) + cmake_minimum_required(VERSION 3.14.4) ROS 2 relies on the C++17 standard. Depending on what compiler you're using, support for C++17 might not be enabled by default. From 1e4abef7e3386b493bfd0512b726c7a84814155d Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 19:56:09 -0700 Subject: [PATCH 08/17] Build system first, assume already using package format 2 Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 348 +++++++++--------- 1 file changed, 173 insertions(+), 175 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 27b762dc6d..6614ff6970 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -498,17 +498,17 @@ The files have the following content: .. code-block:: xml - + + + talker 0.0.0 talker Brian Gerkey Apache-2.0 catkin - roscpp - std_msgs - roscpp - std_msgs + roscpp + std_msgs ``src/talker/CMakeLists.txt``: @@ -556,203 +556,57 @@ The files have the following content: Migrating to ROS 2 ^^^^^^^^^^^^^^^^^^ -Creating a new ROS 2 workspace: +Create a new ROS 2 workspace: .. code-block:: bash mkdir ~/ros2_talker cd ~/ros2_talker -We'll copy the source tree from our ROS 1 package into that workspace, where we can modify it: +Copy the source tree from the ROS 1 package into the ROS 2 workspace, so you can modify it: .. code-block:: bash mkdir src cp -a ~/ros1_talker/src/talker src -Now we'll modify the C++ code in the node. -The ROS 2 C++ library, called ``rclcpp``, provides a different API from that -provided by ``roscpp``. -The concepts are very similar between the two libraries, which makes the changes -reasonably straightforward to make. - -Included headers -~~~~~~~~~~~~~~~~ - -In place of ``ros/ros.h``, which gave us access to the ``roscpp`` library API, we -need to include ``rclcpp/rclcpp.hpp``, which gives us access to the ``rclcpp`` -library API: - -.. code-block:: cpp - - //#include "ros/ros.h" - #include "rclcpp/rclcpp.hpp" +Modify the ``package.xml`` and ``CMakeLists.txt`` to use ``ament_cmake`` first. +This lets you find unmigrated code by attempting to build the package. -To get the ``std_msgs/String`` message definition, in place of -``std_msgs/String.h``, we need to include ``std_msgs/msg/string.hpp``: - -.. code-block:: cpp - - //#include "std_msgs/String.h" - #include "std_msgs/msg/string.hpp" - -Changing C++ library calls +Change the ``package.xml`` ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Instead of passing the node's name to the library initialization call, we do -the initialization, then pass the node name to the creation of the node object: - -.. code-block:: cpp - - // ros::init(argc, argv, "talker"); - // ros::NodeHandle n; - rclcpp::init(argc, argv); - auto node = rclcpp::Node::make_shared("talker"); - -The creation of the publisher and rate objects looks pretty similar, with some -changes to the names of namespace and methods. - -.. code-block:: cpp +ROS 2 packages use CMake functions and macros from ``ament_cmake_ros`` instead of ``catkin``. +Delete the dependency on ``catkin``: - // ros::Publisher chatter_pub = n.advertise("chatter", 1000); - // ros::Rate loop_rate(10); - auto chatter_pub = node->create_publisher("chatter", - 1000); - rclcpp::Rate loop_rate(10); - -To further control how message delivery is handled, a quality of service -(``QoS``) profile could be passed in. -The default profile is ``rmw_qos_profile_default``. -For more details, see the -`design document `__ -and :doc:`concept overview <../../Concepts/Intermediate/About-Quality-of-Service-Settings>`. - -The creation of the outgoing message is different in the namespace: - -.. code-block:: cpp - - // std_msgs::String msg; - std_msgs::msg::String msg; - -In place of ``ros::ok()``, we call ``rclcpp::ok()``: - -.. code-block:: cpp - - // while (ros::ok()) - while (rclcpp::ok()) - -Inside the publishing loop, we access the ``data`` field as before: - -.. code-block:: cpp - - msg.data = ss.str(); - -To print a console message, instead of using ``ROS_INFO()``, we use -``RCLCPP_INFO()`` and its various cousins. -The key difference is that ``RCLCPP_INFO()`` takes a Logger object as the first -argument. - -.. code-block:: cpp - - // ROS_INFO("%s", msg.data.c_str()); - RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); - -Publishing the message is the same as before: - -.. code-block:: cpp - - chatter_pub->publish(msg); - -Spinning (i.e., letting the communications system process any pending -incoming/outgoing messages) is different in that the call now takes the node as -an argument: - -.. code-block:: cpp - - // ros::spinOnce(); - rclcpp::spin_some(node); - -Sleeping using the rate object is unchanged. - -Putting it all together, the new ``talker.cpp`` looks like this: - -.. code-block:: cpp - - #include - // #include "ros/ros.h" - #include "rclcpp/rclcpp.hpp" - // #include "std_msgs/String.h" - #include "std_msgs/msg/string.hpp" - int main(int argc, char **argv) - { - // ros::init(argc, argv, "talker"); - // ros::NodeHandle n; - rclcpp::init(argc, argv); - auto node = rclcpp::Node::make_shared("talker"); - // ros::Publisher chatter_pub = n.advertise("chatter", 1000); - // ros::Rate loop_rate(10); - auto chatter_pub = node->create_publisher("chatter", 1000); - rclcpp::Rate loop_rate(10); - int count = 0; - // std_msgs::String msg; - std_msgs::msg::String msg; - // while (ros::ok()) - while (rclcpp::ok()) - { - std::stringstream ss; - ss << "hello world " << count++; - msg.data = ss.str(); - // ROS_INFO("%s", msg.data.c_str()); - RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); - chatter_pub->publish(msg); - // ros::spinOnce(); - rclcpp::spin_some(node); - loop_rate.sleep(); - } - return 0; - } +.. code-block:: -Changing the ``package.xml`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + catkin` -ROS 2 uses a newer version of ``catkin``, called ``ament_cmake``, which we specify in the -``buildtool_depend`` tag: +Add a new dependency on ``ament_cmake_ros``: .. code-block:: xml - ament_cmake -In our build dependencies, instead of ``roscpp`` we use ``rclcpp``, which provides the C++ API that we use. - -.. code-block:: xml - - - rclcpp +ROS 2 C++ libraries use `rclcpp `__ instead of `roscpp `__. -We make the same addition in the run dependencies and also update from the -``run_depend`` tag to the ``exec_depend`` tag (part of the upgrade to version 2 of the package format): +Delete the dependency on ``roscpp``: -.. code-block:: xml +.. code-block:: - - rclcpp - - std_msgs + + roscpp -In ROS 1, we use ```` to simplify specifying dependencies for both -compile-time and runtime. -We can do the same in ROS 2: +Add a dependency on ``rclcpp``: .. code-block:: xml rclcpp - std_msgs -We also need to tell the build tool what *kind* of package we are, so that it knows how -to build us. -Because we're using ``ament`` and CMake, we add the following lines to declare our -build type to be ``ament_cmake``: + +Add an ```` section to tell colcon the package is an ``ament_cmake`` package instead of a ``catkin`` package. .. code-block:: xml @@ -760,7 +614,7 @@ build type to be ``ament_cmake``: ament_cmake -Putting it all together, our ``package.xml`` now looks like this: +Your ``package.xml`` now looks like this: .. code-block:: xml @@ -771,11 +625,7 @@ Putting it all together, our ``package.xml`` now looks like this: talker Brian Gerkey Apache-2.0 - ament_cmake - - - rclcpp std_msgs @@ -937,6 +787,154 @@ Putting it all together, the new ``CMakeLists.txt`` looks like this: ament_export_dependencies(std_msgs) ament_package() + +Changing C++ code +~~~~~~~~~~~~~~~~~ + +Now we'll modify the C++ code in the node. +The ROS 2 C++ library, called ``rclcpp``, provides a different API from that +provided by ``roscpp``. +The concepts are very similar between the two libraries, which makes the changes +reasonably straightforward to make. + +Included headers +~~~~~~~~~~~~~~~~ + +In place of ``ros/ros.h``, which gave us access to the ``roscpp`` library API, we +need to include ``rclcpp/rclcpp.hpp``, which gives us access to the ``rclcpp`` +library API: + +.. code-block:: cpp + + //#include "ros/ros.h" + #include "rclcpp/rclcpp.hpp" + +To get the ``std_msgs/String`` message definition, in place of +``std_msgs/String.h``, we need to include ``std_msgs/msg/string.hpp``: + +.. code-block:: cpp + + //#include "std_msgs/String.h" + #include "std_msgs/msg/string.hpp" + +Changing C++ library calls +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of passing the node's name to the library initialization call, we do +the initialization, then pass the node name to the creation of the node object: + +.. code-block:: cpp + + // ros::init(argc, argv, "talker"); + // ros::NodeHandle n; + rclcpp::init(argc, argv); + auto node = rclcpp::Node::make_shared("talker"); + +The creation of the publisher and rate objects looks pretty similar, with some +changes to the names of namespace and methods. + +.. code-block:: cpp + + // ros::Publisher chatter_pub = n.advertise("chatter", 1000); + // ros::Rate loop_rate(10); + auto chatter_pub = node->create_publisher("chatter", + 1000); + rclcpp::Rate loop_rate(10); + +To further control how message delivery is handled, a quality of service +(``QoS``) profile could be passed in. +The default profile is ``rmw_qos_profile_default``. +For more details, see the +`design document `__ +and :doc:`concept overview <../../Concepts/Intermediate/About-Quality-of-Service-Settings>`. + +The creation of the outgoing message is different in the namespace: + +.. code-block:: cpp + + // std_msgs::String msg; + std_msgs::msg::String msg; + +In place of ``ros::ok()``, we call ``rclcpp::ok()``: + +.. code-block:: cpp + + // while (ros::ok()) + while (rclcpp::ok()) + +Inside the publishing loop, we access the ``data`` field as before: + +.. code-block:: cpp + + msg.data = ss.str(); + +To print a console message, instead of using ``ROS_INFO()``, we use +``RCLCPP_INFO()`` and its various cousins. +The key difference is that ``RCLCPP_INFO()`` takes a Logger object as the first +argument. + +.. code-block:: cpp + + // ROS_INFO("%s", msg.data.c_str()); + RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); + +Publishing the message is the same as before: + +.. code-block:: cpp + + chatter_pub->publish(msg); + +Spinning (i.e., letting the communications system process any pending +incoming/outgoing messages) is different in that the call now takes the node as +an argument: + +.. code-block:: cpp + + // ros::spinOnce(); + rclcpp::spin_some(node); + +Sleeping using the rate object is unchanged. + +Putting it all together, the new ``talker.cpp`` looks like this: + +.. code-block:: cpp + + #include + // #include "ros/ros.h" + #include "rclcpp/rclcpp.hpp" + // #include "std_msgs/String.h" + #include "std_msgs/msg/string.hpp" + int main(int argc, char **argv) + { + // ros::init(argc, argv, "talker"); + // ros::NodeHandle n; + rclcpp::init(argc, argv); + auto node = rclcpp::Node::make_shared("talker"); + // ros::Publisher chatter_pub = n.advertise("chatter", 1000); + // ros::Rate loop_rate(10); + auto chatter_pub = node->create_publisher("chatter", 1000); + rclcpp::Rate loop_rate(10); + int count = 0; + // std_msgs::String msg; + std_msgs::msg::String msg; + // while (ros::ok()) + while (rclcpp::ok()) + { + std::stringstream ss; + ss << "hello world " << count++; + msg.data = ss.str(); + // ROS_INFO("%s", msg.data.c_str()); + RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); + chatter_pub->publish(msg); + // ros::spinOnce(); + rclcpp::spin_some(node); + loop_rate.sleep(); + } + return 0; + } + + + Building the ROS 2 code ~~~~~~~~~~~~~~~~~~~~~~~ From ed52172688782ba60b7a0048e1765ee37626447f Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 20:09:57 -0700 Subject: [PATCH 09/17] Update instructions, removing unnecessary stuff Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 118 ++++-------------- 1 file changed, 27 insertions(+), 91 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 6614ff6970..dd6d63fb46 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -618,7 +618,8 @@ Your ``package.xml`` now looks like this: .. code-block:: xml - + + talker 0.0.0 @@ -637,21 +638,15 @@ Your ``package.xml`` now looks like this: Changing the CMake code ~~~~~~~~~~~~~~~~~~~~~~~ -ROS 2 relies on a higher version of CMake: +Require a newer version of CMake so that ``ament_cmake`` functions work correctly. .. code-block:: cmake_minimum_required(VERSION 3.14.4) -ROS 2 relies on the C++17 standard. -Depending on what compiler you're using, support for C++17 might not be enabled by default. -Enable C++17 support explicitly by adding this line near the top of the file: - -.. code-block:: cmake - - set(CMAKE_CXX_STANDARD 17) - -The preferred way to work on all platforms is this: +Use a newer C++ standard matching the version used by your target ROS distro in `REP 2000 `__. +If you are using C++17, then set that version with the following snippet. +Add extra compiler checks too because it is a good practice. .. code-block:: cmake @@ -662,102 +657,51 @@ The preferred way to work on all platforms is this: add_compile_options(-Wall -Wextra -Wpedantic) endif() -Using ``catkin``, we specify the packages we want to build against by passing them -as ``COMPONENTS`` arguments when initially finding ``catkin`` itself. -With ``ament_cmake``, we find each package individually, starting with ``ament_cmake``: +Replace the ``find_package(catkin ...)`` call with individual calls for each dependency. .. code-block:: cmake - #find_package(catkin REQUIRED COMPONENTS roscpp std_msgs) find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) -System dependencies can be found as before: - -.. code-block:: cmake - find_package(Boost REQUIRED COMPONENTS system filesystem thread) - -We call ``catkin_package()`` to auto-generate things like CMake configuration -files for other packages that use our package. -Whereas that call happens *before* specifying targets to build, we now call the -analogous ``ament_package()`` *after* the targets: +Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. .. code-block:: cmake - # catkin_package() - # At the bottom of the file: ament_package() -The only directories that need to be manually included are local directories -and dependencies that are not ament packages: - -.. code-block:: cmake - - #include_directories(${catkin_INCLUDE_DIRS}) - include_directories(include ${Boost_INCLUDE_DIRS}) - -A better alternative is to specify include directories for each target -individually, rather than including all the directories for all targets: - -.. code-block:: cmake - - target_include_directories(target PUBLIC include ${Boost_INCLUDE_DIRS}) - -Similar to how we found each dependent package separately, we need to link -each one to the build target. -To link with dependent packages that are ament packages, instead of using -``target_link_libraries()``, ``ament_target_dependencies()`` is a more -concise and more thorough way of handling build flags. -It automatically handles both the include directories defined in -``_INCLUDE_DIRS`` and linking libraries defined in ``_LIBRARIES``. +Delete the call to ``include_directories()``. +Replace it with a call to ``target_include_directories()`` for your package's `include` directory. +Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by depending on modern CMake targets. .. code-block:: cmake - #target_link_libraries(talker ${catkin_LIBRARIES}) - ament_target_dependencies(talker - rclcpp - std_msgs) + target_include_directories(target PUBLIC + "$" + "$") -To link with packages that are not ament packages, such as system dependencies -like ``Boost``, or a library being built in the same ``CMakeLists.txt``, use -``target_link_libraries()``: +Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. .. code-block:: cmake - target_link_libraries(target ${Boost_LIBRARIES}) + target_link_libraries(talker PUBLIC + rclcpp::rclcpp + ${std_msgs_TARGETS}) -For installation, ``catkin`` defines variables like ``CATKIN_PACKAGE_BIN_DESTINATION``. -With ``ament_cmake``, we just give a path relative to the installation root: +Install the ``talker`` executable into a project specific directory so that it is discoverable by tools like ``ros2 run``. .. code-block:: cmake - #install(TARGETS talker - # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) install(TARGETS talker DESTINATION lib/${PROJECT_NAME}) -Optionally, we can install and export the included directories for downstream packages: - -.. code-block:: cmake - - install(DIRECTORY include/ - DESTINATION include) - ament_export_include_directories(include) - -Optionally, we can export dependencies for downstream packages: +The new ``CMakeLists.txt`` looks like this: .. code-block:: cmake - ament_export_dependencies(std_msgs) - -Putting it all together, the new ``CMakeLists.txt`` looks like this: - -.. code-block:: cmake - - #cmake_minimum_required(VERSION 2.8.3) - cmake_minimum_required(VERSION 3.5) + cmake_minimum_required(VERSION 3.14.4) project(talker) if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) @@ -765,26 +709,18 @@ Putting it all together, the new ``CMakeLists.txt`` looks like this: if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() - #find_package(catkin REQUIRED COMPONENTS roscpp std_msgs) find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) - #catkin_package() - #include_directories(${catkin_INCLUDE_DIRS}) - include_directories(include) add_executable(talker talker.cpp) - #target_link_libraries(talker ${catkin_LIBRARIES}) - ament_target_dependencies(talker - rclcpp - std_msgs) - #install(TARGETS talker - # RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) + target_include_directories(target PUBLIC + "$" + "$") + target_link_libraries(talker PUBLIC + rclcpp::rclcpp + ${std_msgs_TARGETS}) install(TARGETS talker DESTINATION lib/${PROJECT_NAME}) - install(DIRECTORY include/ - DESTINATION include) - ament_export_include_directories(include) - ament_export_dependencies(std_msgs) ament_package() From 30582c736f856507588d82f15f17e1b970d9eb2e Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Wed, 25 Sep 2024 20:45:50 -0700 Subject: [PATCH 10/17] Some updates to code changes section Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index dd6d63fb46..130bc5dcbb 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -673,7 +673,7 @@ Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. ament_package() Delete the call to ``include_directories()``. -Replace it with a call to ``target_include_directories()`` for your package's `include` directory. +Replace it with a call to ``target_include_directories()`` for your package's ``include`` directory. Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by depending on modern CMake targets. .. code-block:: cmake @@ -724,33 +724,42 @@ The new ``CMakeLists.txt`` looks like this: ament_package() -Changing C++ code -~~~~~~~~~~~~~~~~~ +Change the C++ code +~~~~~~~~~~~~~~~~~~~ -Now we'll modify the C++ code in the node. -The ROS 2 C++ library, called ``rclcpp``, provides a different API from that -provided by ``roscpp``. -The concepts are very similar between the two libraries, which makes the changes -reasonably straightforward to make. +Modify the C++ code after you have finished modifying the ``package.xml`` and ``CMakeLists.txt``. +The biggest change to make is to move from ``roscpp`` APIs to ``rclcpp`` APIs, but the concepts are similar between the two packages. -Included headers -~~~~~~~~~~~~~~~~ +Change the included headers +~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In place of ``ros/ros.h``, which gave us access to the ``roscpp`` library API, we -need to include ``rclcpp/rclcpp.hpp``, which gives us access to the ``rclcpp`` -library API: +The package needs to include headers from ``rclcpp`` instead of ``roscpp``. + +Remove the include for ``roscpp``: + +.. code-block:: + + // remove this + #include "ros/ros.h" + +Add the include for ``rclcpp``: .. code-block:: cpp - //#include "ros/ros.h" #include "rclcpp/rclcpp.hpp" -To get the ``std_msgs/String`` message definition, in place of -``std_msgs/String.h``, we need to include ``std_msgs/msg/string.hpp``: +ROS 2 messages, services, and actions use lower case header names, and include the type of interface in the name. + +Change the include for the ``String`` message from this: + +.. code-block:: + + #include "std_msgs/String.h" + +to this: .. code-block:: cpp - //#include "std_msgs/String.h" #include "std_msgs/msg/string.hpp" Changing C++ library calls From 50e863b8ae58b90bcf8ad490187a45c03257f7da Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 29 Sep 2024 13:38:15 -0700 Subject: [PATCH 11/17] Undo non-CMake changes to save for another PR Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 335 ++++++++++-------- 1 file changed, 184 insertions(+), 151 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 130bc5dcbb..94ce821651 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -553,176 +553,61 @@ The files have the following content: return 0; } -Migrating to ROS 2 -^^^^^^^^^^^^^^^^^^ - -Create a new ROS 2 workspace: - -.. code-block:: bash - - mkdir ~/ros2_talker - cd ~/ros2_talker - -Copy the source tree from the ROS 1 package into the ROS 2 workspace, so you can modify it: - -.. code-block:: bash - - mkdir src - cp -a ~/ros1_talker/src/talker src - -Modify the ``package.xml`` and ``CMakeLists.txt`` to use ``ament_cmake`` first. -This lets you find unmigrated code by attempting to build the package. - -Change the ``package.xml`` -~~~~~~~~~~~~~~~~~~~~~~~~~~ - -ROS 2 packages use CMake functions and macros from ``ament_cmake_ros`` instead of ``catkin``. -Delete the dependency on ``catkin``: - -.. code-block:: - - - catkin` - -Add a new dependency on ``ament_cmake_ros``: - -.. code-block:: xml - - ament_cmake - -ROS 2 C++ libraries use `rclcpp `__ instead of `roscpp `__. - -Delete the dependency on ``roscpp``: - -.. code-block:: - - - roscpp - -Add a dependency on ``rclcpp``: - -.. code-block:: xml - - rclcpp - - -Add an ```` section to tell colcon the package is an ``ament_cmake`` package instead of a ``catkin`` package. - -.. code-block:: xml - - - ament_cmake - - -Your ``package.xml`` now looks like this: - -.. code-block:: xml - - - - - talker - 0.0.0 - talker - Brian Gerkey - Apache-2.0 - ament_cmake - rclcpp - std_msgs - - ament_cmake - - - - -Changing the CMake code +Building the ROS 1 code ~~~~~~~~~~~~~~~~~~~~~~~ -Require a newer version of CMake so that ``ament_cmake`` functions work correctly. - -.. code-block:: - - cmake_minimum_required(VERSION 3.14.4) - -Use a newer C++ standard matching the version used by your target ROS distro in `REP 2000 `__. -If you are using C++17, then set that version with the following snippet. -Add extra compiler checks too because it is a good practice. - -.. code-block:: cmake - - if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) - endif() - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) - endif() +We source an environment setup file (in this case for Noetic using bash), then we +build our package using ``catkin_make install``: -Replace the ``find_package(catkin ...)`` call with individual calls for each dependency. - -.. code-block:: cmake +.. code-block:: bash - find_package(ament_cmake REQUIRED) - find_package(rclcpp REQUIRED) - find_package(std_msgs REQUIRED) + . /opt/ros/noetic/setup.bash + cd ~/ros1_talker + catkin_make install +Running the ROS 1 node +~~~~~~~~~~~~~~~~~~~~~~ -Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. +If there's not already one running, we start a ``roscore``, first sourcing the +setup file from our ``catkin`` install tree (the system setup file at +``/opt/ros/noetic/setup.bash`` would also work here): -.. code-block:: cmake +.. code-block:: bash - ament_package() + . ~/ros1_talker/install/setup.bash + roscore -Delete the call to ``include_directories()``. -Replace it with a call to ``target_include_directories()`` for your package's ``include`` directory. -Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by depending on modern CMake targets. +In another shell, we run the node from the ``catkin`` install space using +``rosrun``, again sourcing the setup file first (in this case it must be the one +from our workspace): -.. code-block:: cmake - - target_include_directories(target PUBLIC - "$" - "$") +.. code-block:: bash -Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. + . ~/ros1_talker/install/setup.bash + rosrun talker talker -.. code-block:: cmake +Migrating to ROS 2 +^^^^^^^^^^^^^^^^^^ - target_link_libraries(talker PUBLIC - rclcpp::rclcpp - ${std_msgs_TARGETS}) +Let's start by creating a new workspace in which to work: -Install the ``talker`` executable into a project specific directory so that it is discoverable by tools like ``ros2 run``. - -.. code-block:: cmake +.. code-block:: bash - install(TARGETS talker - DESTINATION lib/${PROJECT_NAME}) + mkdir ~/ros2_talker + cd ~/ros2_talker -The new ``CMakeLists.txt`` looks like this: +We'll copy the source tree from our ROS 1 package into that workspace, where we can modify it: -.. code-block:: cmake +.. code-block:: bash - cmake_minimum_required(VERSION 3.14.4) - project(talker) - if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) - endif() - if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) - endif() - find_package(ament_cmake REQUIRED) - find_package(rclcpp REQUIRED) - find_package(std_msgs REQUIRED) - add_executable(talker talker.cpp) - target_include_directories(target PUBLIC - "$" - "$") - target_link_libraries(talker PUBLIC - rclcpp::rclcpp - ${std_msgs_TARGETS}) - install(TARGETS talker - DESTINATION lib/${PROJECT_NAME}) - ament_package() + mkdir src + cp -a ~/ros1_talker/src/talker src +Now we'll modify the C++ code in the node. +The ROS 2 C++ library, called ``rclcpp``, provides a different API from that +provided by ``roscpp``. +The concepts are very similar between the two libraries, which makes the changes +reasonably straightforward to make. Change the C++ code ~~~~~~~~~~~~~~~~~~~ @@ -878,7 +763,155 @@ Putting it all together, the new ``talker.cpp`` looks like this: return 0; } +Change the ``package.xml`` +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +ROS 2 packages use CMake functions and macros from ``ament_cmake_ros`` instead of ``catkin``. +Delete the dependency on ``catkin``: + +.. code-block:: + + + catkin` + +Add a new dependency on ``ament_cmake_ros``: + +.. code-block:: xml + + ament_cmake + +ROS 2 C++ libraries use `rclcpp `__ instead of `roscpp `__. + +Delete the dependency on ``roscpp``: + +.. code-block:: + + + roscpp + +Add a dependency on ``rclcpp``: + +.. code-block:: xml + + rclcpp + + +Add an ```` section to tell colcon the package is an ``ament_cmake`` package instead of a ``catkin`` package. +.. code-block:: xml + + + ament_cmake + + +Your ``package.xml`` now looks like this: + +.. code-block:: xml + + + + + talker + 0.0.0 + talker + Brian Gerkey + Apache-2.0 + ament_cmake + rclcpp + std_msgs + + ament_cmake + + + + +Changing the CMake code +~~~~~~~~~~~~~~~~~~~~~~~ + +Require a newer version of CMake so that ``ament_cmake`` functions work correctly. + +.. code-block:: + + cmake_minimum_required(VERSION 3.14.4) + +Use a newer C++ standard matching the version used by your target ROS distro in `REP 2000 `__. +If you are using C++17, then set that version with the following snippet. +Add extra compiler checks too because it is a good practice. + +.. code-block:: cmake + + if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + +Replace the ``find_package(catkin ...)`` call with individual calls for each dependency. + +.. code-block:: cmake + + find_package(ament_cmake REQUIRED) + find_package(rclcpp REQUIRED) + find_package(std_msgs REQUIRED) + + +Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. + +.. code-block:: cmake + + ament_package() + +Delete the call to ``include_directories()``. +Replace it with a call to ``target_include_directories()`` for your package's ``include`` directory. +Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by depending on modern CMake targets. + +.. code-block:: cmake + + target_include_directories(target PUBLIC + "$" + "$") + +Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. + +.. code-block:: cmake + + target_link_libraries(talker PUBLIC + rclcpp::rclcpp + ${std_msgs_TARGETS}) + +Install the ``talker`` executable into a project specific directory so that it is discoverable by tools like ``ros2 run``. + +.. code-block:: cmake + + install(TARGETS talker + DESTINATION lib/${PROJECT_NAME}) + +The new ``CMakeLists.txt`` looks like this: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.14.4) + project(talker) + if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + endif() + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) + endif() + find_package(ament_cmake REQUIRED) + find_package(rclcpp REQUIRED) + find_package(std_msgs REQUIRED) + add_executable(talker talker.cpp) + target_include_directories(target PUBLIC + "$" + "$") + target_link_libraries(talker PUBLIC + rclcpp::rclcpp + ${std_msgs_TARGETS}) + install(TARGETS talker + DESTINATION lib/${PROJECT_NAME}) + ament_package() Building the ROS 2 code ~~~~~~~~~~~~~~~~~~~~~~~ From c31a35ede94c9d4da2afb2d0c5f5a7a293f85af1 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 29 Sep 2024 13:41:09 -0700 Subject: [PATCH 12/17] Only change CMake code this time Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 94ce821651..d0232d7547 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -609,42 +609,24 @@ provided by ``roscpp``. The concepts are very similar between the two libraries, which makes the changes reasonably straightforward to make. -Change the C++ code -~~~~~~~~~~~~~~~~~~~ +Included headers +~~~~~~~~~~~~~~~~ -Modify the C++ code after you have finished modifying the ``package.xml`` and ``CMakeLists.txt``. -The biggest change to make is to move from ``roscpp`` APIs to ``rclcpp`` APIs, but the concepts are similar between the two packages. - -Change the included headers -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The package needs to include headers from ``rclcpp`` instead of ``roscpp``. - -Remove the include for ``roscpp``: - -.. code-block:: - - // remove this - #include "ros/ros.h" - -Add the include for ``rclcpp``: +In place of ``ros/ros.h``, which gave us access to the ``roscpp`` library API, we +need to include ``rclcpp/rclcpp.hpp``, which gives us access to the ``rclcpp`` +library API: .. code-block:: cpp + //#include "ros/ros.h" #include "rclcpp/rclcpp.hpp" -ROS 2 messages, services, and actions use lower case header names, and include the type of interface in the name. - -Change the include for the ``String`` message from this: - -.. code-block:: - - #include "std_msgs/String.h" - -to this: +To get the ``std_msgs/String`` message definition, in place of +``std_msgs/String.h``, we need to include ``std_msgs/msg/string.hpp``: .. code-block:: cpp + //#include "std_msgs/String.h" #include "std_msgs/msg/string.hpp" Changing C++ library calls From 81944b04d9fdf9e6e15561cfc594bf281952cc83 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 29 Sep 2024 14:31:28 -0700 Subject: [PATCH 13/17] more changes Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index d0232d7547..220836a093 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -844,9 +844,18 @@ Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. ament_package() +Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. + +.. code-block:: cmake + + target_link_libraries(talker PUBLIC + rclcpp::rclcpp + ${std_msgs_TARGETS}) + Delete the call to ``include_directories()``. Replace it with a call to ``target_include_directories()`` for your package's ``include`` directory. -Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by depending on modern CMake targets. +Don't pass variables like ``rclcpp_INCLUDE_DIRS`` into ``target_include_directories()``. +The include directories were already handled by calling ``target_link_libraries()`` with modern CMake targets. .. code-block:: cmake @@ -854,14 +863,6 @@ Don't add other package's ``*_INCLUDE_DIRS`` variables, those will be handled by "$" "$") -Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. - -.. code-block:: cmake - - target_link_libraries(talker PUBLIC - rclcpp::rclcpp - ${std_msgs_TARGETS}) - Install the ``talker`` executable into a project specific directory so that it is discoverable by tools like ``ros2 run``. .. code-block:: cmake From 2f4c02028bd2bc99410317c6000620b9932b489b Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 29 Sep 2024 15:00:56 -0700 Subject: [PATCH 14/17] Misc fixes Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 220836a093..2891ccf86f 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -211,8 +211,8 @@ Add a call to ``ament_export_targets()`` with the same name you gave to the ``EX Replacing ``catkin_package(CATKIN_DEPENDS .. DEPENDS ..)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Downstream users also need to ``find_package()`` dependencies used in your public API. -In ROS 1 this was done with ``CATKIN_DEPENDS`` and ``DEPENDS`` arguments. +Your package's users must ``find_package()`` dependencies used by your package's public API. +In ROS 1 this was done for downstream users with the ``CATKIN_DEPENDS`` and ``DEPENDS`` arguments. Use `ament_export_dependencies `__ to do this in ROS 2. .. code-block:: cmake @@ -326,9 +326,9 @@ Add ``ament_cmake_gtest`` to your ``package.xml`` (`e Linters ^^^^^^^ -The ROS 2 code style guide is different than ROS 1 :doc:`Developer Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. +The ROS 2 code style guide differs from the ROS 1 :doc:`Style Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. -If you are starting a project from scratch, follow the ROS 2 style guide, and turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: +If you choose to follow the ROS 2 style guide, then turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: .. code-block:: cmake @@ -338,7 +338,7 @@ If you are starting a project from scratch, follow the ROS 2 style guide, and tu # ... endif() -Then, add the following dependencies to your ``package.xml``: +Add the following dependencies to your ``package.xml``: .. code-block:: xml From 521ed5dfd11f73fbf8fc2375e9386e031b060945 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Sun, 29 Sep 2024 16:35:38 -0700 Subject: [PATCH 15/17] Misc fixes after running through example Signed-off-by: Shane Loretz --- .../Migrating-CPP-Packages.rst | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index 2891ccf86f..dcb2b5e34a 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -690,10 +690,11 @@ argument. // ROS_INFO("%s", msg.data.c_str()); RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); -Publishing the message is the same as before: +Change the publish call to use the ``->`` operator instead of ``.``. .. code-block:: cpp + // chatter_pub.publish(msg); chatter_pub->publish(msg); Spinning (i.e., letting the communications system process any pending @@ -737,6 +738,7 @@ Putting it all together, the new ``talker.cpp`` looks like this: msg.data = ss.str(); // ROS_INFO("%s", msg.data.c_str()); RCLCPP_INFO(node->get_logger(), "%s\n", msg.data.c_str()); + // chatter_pub.publish(msg); chatter_pub->publish(msg); // ros::spinOnce(); rclcpp::spin_some(node); @@ -760,7 +762,7 @@ Add a new dependency on ``ament_cmake_ros``: .. code-block:: xml - ament_cmake + ament_cmake_ros ROS 2 C++ libraries use `rclcpp `__ instead of `roscpp `__. @@ -817,7 +819,7 @@ Require a newer version of CMake so that ``ament_cmake`` functions work correctl cmake_minimum_required(VERSION 3.14.4) Use a newer C++ standard matching the version used by your target ROS distro in `REP 2000 `__. -If you are using C++17, then set that version with the following snippet. +If you are using C++17, then set that version with the following snippet after the ``project(talker)`` call. Add extra compiler checks too because it is a good practice. .. code-block:: cmake @@ -837,14 +839,14 @@ Replace the ``find_package(catkin ...)`` call with individual calls for each dep find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) - +Delete the call to ``catkin_package()``. Add a call to ``ament_package()`` at the bottom of the ``CMakeLists.txt``. .. code-block:: cmake ament_package() -Use ``target_link_libraries`` to make the ``talker`` target depend on the modern CMake targets provided by ``rclcpp`` and ``std_msgs``. +Make the ``target_link_libraries`` call modern CMake targets provided by ``rclcpp`` and ``std_msgs``. .. code-block:: cmake @@ -853,17 +855,17 @@ Use ``target_link_libraries`` to make the ``talker`` target depend on the modern ${std_msgs_TARGETS}) Delete the call to ``include_directories()``. -Replace it with a call to ``target_include_directories()`` for your package's ``include`` directory. +Add a call to ``target_include_directories()`` below ``add_executable(talker talker.cpp)``. Don't pass variables like ``rclcpp_INCLUDE_DIRS`` into ``target_include_directories()``. -The include directories were already handled by calling ``target_link_libraries()`` with modern CMake targets. +The include directories are already handled by calling ``target_link_libraries()`` with modern CMake targets. .. code-block:: cmake - target_include_directories(target PUBLIC + target_include_directories(talker PUBLIC "$" "$") -Install the ``talker`` executable into a project specific directory so that it is discoverable by tools like ``ros2 run``. +Change the call to ``install()`` so that the ``talker`` executable is installed into a project specific directory. .. code-block:: cmake @@ -886,7 +888,7 @@ The new ``CMakeLists.txt`` looks like this: find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) add_executable(talker talker.cpp) - target_include_directories(target PUBLIC + target_include_directories(talker PUBLIC "$" "$") target_link_libraries(talker PUBLIC From 92246d4a9f94c4d3ff25cbc782409a3003f0e9c5 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Mon, 30 Sep 2024 10:03:56 -0700 Subject: [PATCH 16/17] Clearly link ROS 2 style guide Co-authored-by: Chris Lalancette Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index dcb2b5e34a..cbebf5748c 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -326,7 +326,7 @@ Add ``ament_cmake_gtest`` to your ``package.xml`` (`e Linters ^^^^^^^ -The ROS 2 code style guide differs from the ROS 1 :doc:`Style Guide <../../The-ROS2-Project/Contributing/Developer-Guide>`. +The ROS 2 code :doc:`style guide <../../The-ROS2-Project/Contributing/Developer-Guide>`__ differs from ROS 1. If you choose to follow the ROS 2 style guide, then turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: From 53dc7e6719f5d585b4b3e9c63420dfebe6039730 Mon Sep 17 00:00:00 2001 From: Shane Loretz Date: Mon, 30 Sep 2024 10:08:02 -0700 Subject: [PATCH 17/17] Add member_of_group tag code block Signed-off-by: Shane Loretz --- .../Migrating-from-ROS1/Migrating-CPP-Packages.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst index cbebf5748c..1e42a839bd 100644 --- a/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst +++ b/source/How-To-Guides/Migrating-from-ROS1/Migrating-CPP-Packages.rst @@ -248,6 +248,9 @@ Add the following dependencies to the ``package.xml`` of the package that contai 3. Add a ```` tag with the group name ``rosidl_interface_packages`` (`example `__) + .. code-block:: xml + + rosidl_interface_packages In your ``CMakeLists.txt``, replace the invocation of ``add_message_files``, ``add_service_files`` and ``generate_messages`` with `rosidl_generate_interfaces `__. The first argument must be ``${PROJECT_NAME}`` due to `this bug `__. @@ -326,7 +329,7 @@ Add ``ament_cmake_gtest`` to your ``package.xml`` (`e Linters ^^^^^^^ -The ROS 2 code :doc:`style guide <../../The-ROS2-Project/Contributing/Developer-Guide>`__ differs from ROS 1. +The ROS 2 code :doc:`style guide <../../The-ROS2-Project/Contributing/Developer-Guide>` differs from ROS 1. If you choose to follow the ROS 2 style guide, then turn on automatic linter tests by adding these lines in a ``if(BUILD_TESTING)`` block: