Contents
-
Overview
- Package Layout in Workspace
- Converting a rosbuild (Dry) Package to a catkin (Wet) Package
- Difference in rosbuild manifest.xml from catkin package.xml
- Differences in CMakeLists.txt for rosbuild and catkin
- Python
- Migration Help - "Catkinize" Scripts
- Overlaying Dry and Wet Workspaces
- Updating References
Overview
Here we describe how to migrate rosbuild package to catkin, in general.
Package Layout in Workspace
The layout of workspaces is not very different between rosbuild and catkin packages. A few keys things to notice:
Packages no longer contain a manifest.xml file -- this has been superseded by package.xml
my_package/ --> my_package/ manifest.xml --> package.xml
Packages are no longer organized within stacks. Instead, they are grouped into collections of packages called metapackages. The stack.xml file is replaced with a package.xml file which internally indicates it is a metapackage.
my_stack/ --> my_metapackage/
my_package_1/ --> my_package_1/
manifest.xml --> package.xml
...
my_package_n/ --> my_package_n/
manifest.xml --> package.xml
stack.xml --> my_metapackage
package.xml (Internally, a tag indicates it's a metapackage)Packages still contain a CMakeLists.txt file, but the content and format of this file has changed drastically.
Packages no longer contain a Makefile.
Converting a rosbuild (Dry) Package to a catkin (Wet) Package
At a high level, the key steps to convert a ROS stack from rosbuild to catkin packages are:
- Create a catkin workspace to hold your migrated projects
- Move any project to this catkin workspace once all its dependencies are catkinized
- Convert your stack into a metapackage, unless it was a unary rosbuild stack (Unary rosbuild stacks are stacks with just one package, those will become one catkin package)
- create a catkin package in your old stack folder and name it like the stack, this is going to be the metapackage (as an example, see ros_comm/ros_comm)
- add all other packages of the old stack as run_depend tags of the metapackage in the package.xml
- remove the stack.xml, the information from it moves into the package.xml of the metapackage
- What previously was your ‘stack’ folder should now contain only packages and at most one metapackage.
- For each folder containing a manifest.xml file:
- rename the manifest.xml to package.xml
- add a name tag with the name of the package, which should also be the folder name
- If missing, create a CMakeLists.txt file containing a catkin_package() invocation
- Remove the Makefile
- In each CMakeLists.txt:
- If rosbuild macros were used, switch from rosbuild macros to the underlying CMake commands
- Declare how your targets (C++ binaries) shall be installed
- For each c++ executable or library
- add an add_dependencies() call to the targets generating the message headers, e.g. geometry_msgs_gencpp
- For each executable python script in your package
- install the script using cmake (not setup.py) so that they are installed under "lib/PKGNAME" instead of the global "bin" folder
if the script is not only used by rosrun but also within launch files and there being found using "$(find pkgname)path/to/script": install the script for backward compatibility into share (within the same folder hierarchy as it is in source). (See this issue with xacro) You should also create a differently named script which will be used going forward. Such as change xacro.py to xacro and install it into the standard package local path. This will prevent collisions when using rosrun when using the backwards compatible executable.
- If your package contains python packages, create a setup.py declaring the packages and invoke catkin_python_setup() inyour CMakeLists.txt
One confusing aspect of catkin is the multiple source directories and what they hold. The layout of your catkin workspace if you have multiple packages is:
my_workspace/
build/ <-- created by catkin_make
devel/ <-- created by catkin_make
src/
package_1/
package.xml
CMakeLists.txt
src/
code.cpp
...
package_2/
package.xml
CMakeLists.txt
src/
code.cpp
...
...Now when you run catkin_make inside my_workspace, cmake will build your packages and drop the binaries inside of the build directory.
Note that catkin_make will create the build and devel directories and all of the files inside of those two directories. If you want to completely rebuild all of the catkin created files and directories, you can safely delete the build and devel directories. Another call of catkin_make will recreate those.
Difference in rosbuild manifest.xml from catkin package.xml
The manifest.xml and package.xml files serve almost the same role between rosbuild and catkin - providing information about the package and its dependencies. The difference is that some of the information that traditionally went into the manifest.xml file such as export information (e.g. compiler cflags) is now explicit in CMakeLists.txt and handled by CMake rather than by the ROS build system. See catkin/package.xml for more details.
Differences in CMakeLists.txt for rosbuild and catkin
The most significant change between rosbuild and catkin is the differences in the contents of the CMakeLists.txt file that must be provided with each package. The biggest difference is the elimination of rosbuild macros such as rosbuild_add_library which have been replaced by standard CMake functions or by catkin-specific macros. See catkin/CMakeLists.txt for details about the structure and contents of this file.
Below is a quick guide to showing the mapping between rosbuild CMake macros and catkin CMake macros.
Build Macros
rosbuild |
catkin |
rosbuild_init() |
remove |
rosbuild_add_library(...) |
add_library(...) |
rosbuild_add_executable(...) |
add_executable(...) |
rosbuild_add_compile_flags(...) |
set_target_properties(target PROPERTIES COMPILE_FLAGS new_flags) |
rosbuild_remove_compile_flags(...) |
set_target_properties(target PROPERTIES COMPILE_FLAGS new_flags) |
rosbuild_add_link_flags(...) |
set_target_properties(target PROPERTIES LINK_FLAGS new_flags |
rosbuild_remove_link_flags(...) |
set_target_properties(target PROPERTIES LINK_FLAGS new_flags) |
rosbuild_add_boost_directories(...); rosbuild_link_boost(target components) |
find_package(Boost REQUIRED COMPONENTS components); include_directories(${Boost_INCLUDE_DIRS}); target_link_libraries(target ${Boost_LIBRARIES}) |
rosbuild_add_openmp_flags(...) |
find_package(OpenMP), then do other stuff |
rosbuild_invoke_rospack(...) |
DO NOT DO THIS |
rosbuild_find_ros_package(...) |
DO NOT DO THIS |
rosbuild_find_ros_stack() |
DO NOT DO THIS |
rosbuild_check_for_sse(...) |
look around online and find an example of how to find SSE |
rosbuild_include(package module) |
include(module) (might require some initial work to find the path to the module) |
rosbuild_add_lisp_executable() |
no support for this currently |
rosbuild_add_swigpy_library(target lib src1 src2) |
? |
Test Macros
rosbuild |
catkin |
rosbuild_add_gtest(...) |
catkin_add_gtest(...) |
rosbuild_add_gtest_labeled |
if (${LABEL}) |
|
catkin_add_gtest(...) |
|
endif() |
rosbuild_add_gtest_future |
# comment it out |
rosbuild_add_gtest_build_flags |
use set_target_properties on test target |
rosbuild_add_pyunit |
migrate to catkin_add_nosetests(...) |
rosbuild_add_pyunit_labeled |
similar to rosbuild_add_gtest_labeled |
rosbuild_add_pyunit_future |
# comment it out |
rosbuild_add_rostest(...) |
add_rostest(...) |
rosbuild_add_rostest_labeled |
similar to rosbuild_add_gtest_labeled |
rosbuild_add_rostest_future |
# comment it out |
rosbuild_add_roslaunch_check |
? |
rosbuild_declare_test |
add_dependencies(tests <test-target>) |
rosbuild_count_cores |
? |
rosbuild_check_for_display |
? |
rosbuild_check_for_vm |
? |
Note that the "add_rostest" macro is defined in the rostest package.
Message/Service Macros
rosbuild |
catkin |
rosbuild_add_generated_msgs(...) |
add_message_files(DIRECTORY msg FILES ...) |
rosbuild_add_generated_srvs(...) |
add_service_files(DIRECTORY srv FILES ...) |
rosbuild_genmsg() |
generate_messages() (once per CMakeLists.txt) |
rosbuild_gensrv() |
generate_messages() (once per CMakeLists.txt) |
Listing the message files is useful as adding removing files will trigger an automatic reconfigure by cmake.
Version Macros
rosbuild |
catkin |
rosbuild_get_stack_version |
obsolete |
rosbuild_get_package_version |
obsolete |
==== Data Macros====
rosbuild |
catkin |
rosbuild_download_data(url filename [md5sum]) |
? |
rosbuild_download_test_data |
download_test_data |
rosbuild_untar_file |
? |
Special Targets
rosbuild |
catkin |
rosbuild_premsgsrvgen |
? |
rosbuild_precompile |
? |
rosbuild_make_distribution |
? |
Actionlib
rosbuild |
catkin |
include(${actionlib_msgs_PACKAGE_PATH}/cmake/actionbuild.cmake) |
Remove this, Add actionlib_msgs to find_package call |
genaction() |
add_action_files(DIRECTORY msg FILES ...) |
Python
Catkin leverages Python distutils. If you have python packages or scripts in your catkin package you will need to add a setup.py:
For a standard layout with the python module in the src subdirectory of your catkin package:
1 #!/usr/bin/env python
2
3 from distutils.core import setup
4 from catkin_pkg.python_setup import generate_distutils_setup
5
6 d = generate_distutils_setup(
7 ## don't do this unless you want a globally visible script
8 # scripts=['bin/myscript'],
9 packages=['PYTHON_PACKAGE_NAME'],
10 package_dir={'': 'src'}
11 )
12
13 setup(**d)
and in your CMakeLists.txt call:
catkin_python_setup()
and
install(PROGRAMS scripts/foo_script
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)For more details see: http://ros.org/doc/groovy/api/catkin/html/user_guide/setup_dot_py.html
Migration Help - "Catkinize" Scripts
There is a Python project available that can help you:
- Convert your manifest.xml files to package.xml files
- Convert your rosbuild-based CMakeLists.txt files to use the updated catkin macros
Here is an example of how to use them.
First, install the scripts:
$ git clone https://github.com/ros-infrastructure/catkinize $ cd catkinize $ sudo python setup.py install
Next, set up a catkin workspace in which to do the migration:
$ mkdir filter_ws $ mkdir filter_ws/src $ cd filter_ws $ catkin_make $ source devel/setup.bash
Check out a ROS stack that hasn't yet been converted to catkin into workspace src folder:
$ cd filter_ws/src $ hg clone https://kforge.ros.org/common/filters $ cd filters $ catkinize_stack filters 1.0.0
to catkinize single packages only, call:
$ catkinize filters 1.0.0
As an alternative to the catkinize scripts, use catkin_create_pkg to create a new package, and copy & paste or adapt the contents manually.
Migration checks
Now check and adapt the CMakeLists.txt and package.xml with any text editor.
- Make sure there is a valid maintainer in package.xml
- Uncomment dependencies as needed
- deal with all TODO comments
- Validate marked changes
- remove all commented blocks that should now be obsolete
list message, service and action files in the add_message_files, add_service_files and add_action_files macro calls
remove obsolete include calls
- In the catkin_package macro, export those dependencies required to build against your package, i.e. all that your API header files use, so that client packages do not have to speciy those redundantly
- adapt target and variable names in CMakeLists.txt to make them likely unique
- for targets depending on ROS message, addd add_dependencies() call to the respective message generation targets.
- install any scripts (python) using cmake install() macro
- create a setup.py for your own python modules
The last point is of particular importance. With catkin, projects are commonly build as one project, meaning cmake target names and global (cached) variables can conflict with each other between projects. See http://ros.org/doc/groovy/api/catkin/html/user_guide/standards.html for details on recommended standards for CMakeLists.txt. So pay particular attention to any items like:
catkin_add_gtest(targetname ...) add_executable(targetname ...) set(varname CACHED ...) option(varname...)
and be sure that targetname and varname are likely to be unique among plenty of projects in the ROS ecosystem.
Check the results
$ cd ~/groovy_overlay/build $ cmake ../src $ make
Overlaying Dry and Wet Workspaces
A common problem you will likely run into is having to mix wet packages and dry packages. This is possible with the following constraints:
- catkin and rosbuild workspaces need to be in different, isolated directories
- Dry packages can depend on wet packages, but wet packages cannot depend on dry
That being said, things work in the same way through the use of environment setup files (i.e. setup.* scripts). Both catkin and rosbuild workspaces have this concept; in rosbuild these files are located in the workspace root, in catkin they are located in the devel and install spaces. Here is an example showing the difference between the layouts.
rosbuild_ws/
.rosinstall
setup.bash
setup.sh
setup.py
catkin_ws/
devel/
setup.bash
setup.sh
setup.py
install/
setup.bash
setup.sh
setup.pyTo overlay a rosbuild workspace on top of a catkin workspace, the rosbuild workspace has to reference the setup.sh file as setup-file of either the devel or the install space in the .rosinstall file (not both). Which one is up to you, the catkin way would be to use the devel space setup.sh.
When not using rosws/rosinstall, just make sure your ROS_PACKAGE_PATH includes the src folder of your catkin workspace.
A tutorial exists for this here
Updating References
rosbuild packages which are released are indexed in the release repo on code.ros.org while catkin packages are indexed in the git rosdistro repo. When you convert a released package from rosbuild to catkin you need to remove the old indexing entries and add them to the new location.
Remove Old Reference
To remove the old entry you will need to remove your repository from the appropriate rosdistro file in the release repo. All maintainers have access to this repo to be able to update their packages on release. [release/Setup/Repository|Reverse These Setup Instructions]
Add new entry in new rosdistro repo
After converting your package to catkin. If you would like it to be released you will need to follow the new releasing instructions. [http://ros-infrastructure.github.com/bloom/doc|Instructions for releasing] you will need to add it to the [https://github.com/ros/rosdistro| releases folder in the rosdistro repo]






