ROS Packages

A ROS package regroups node definitions and other resources into a same location. It relies on colcon tool to build, install and manage the package dependancies.

Documention on colcon.readthedocs.io.

The colcon command

colcon is a meta command with several sub-command like ros2 or git. Its main sub-command is build. The colcon build command searches for all compliant packages included in a directory tree, at any depth. It should be processes at the root directory, so in your ros_space.

cd ~/ros_space
colcon build
ls

The build process generates three directories:

  • build with temporaly generated files by the build process ;
  • install with generated ressources of the packages ;
  • log for logs.

At this time, there is no packages on your workspace, the build, install and log directories are almost empty. The results of colcon list (listing packages in the directory tree) or colcon graph (list with dependancies) are also empty.

colcon list
colcon graph

Create a new package

A ROS package interpreted by colcon build is simplely a directory with configurations files. There is \(2\) files by using cmake build tool.

  • package.xml: describing the package and its dependancies
  • CMakeLists.txt: describing the build process (based on famous cmake tool)
mkdir a-package
touch a-package/package.xml
touch a-package/CMakeLists.txt

Naturally the package.xml and the CMakeLists.txt should include minimal informations in a correct way.

rm -fr a-package
colcon build

ROS2, with the pkg sub-command, provide a tool to generate the directory structure of a new package. Let create a tutorial_pkg package for instance.

ros2 pkg create --build-type ament_cmake tutorial_pkg
colcon list
colcon build

Configuration files

The package.xml provides metadata on the package (title, description, author licence). It should be manually completed.

Its also give the build tool to use (a variation of cmake named ament-cmake in our exemple) and permit to specify dependancies with the mark <depend>. Typically, our new tutorial_pkg should depend from rclpy andstd_msgs package and lines <depend>rclpy</depend> and <depend>std_msgs</depend> need to be added after the license information.

Open the CMakeLists.txt file. At this step, it is almost empty. It only include information about the project to build, the C/C++ compiler to use, and some element relative to ament tool trigering action relative to ROS working environement. This file need to be update every time a new ressource (node or other) is added to the package project.

Python Based Nodes

For convenient reason, our python scripts, coding new ros nodes, will be saved on a scripts directory. Typically, we can install there your talker and listerner from previous tutorial.

mkdir tutorial_pkg/scripts
cp playground/talker.py tutorial_pkg/scripts/talker
cp playground/listener.py tutorial_pkg/scripts/listener

Also, we need to inform which interpreter can process our script (ie python3). Add a #!/usr/bin/python3 at the first line in talker and listerner scripts. #! is a shebang meaning that the rest of the line is used to determine the program to interpret the content of the current file. /usr/bin/python3 is simplely the result of the command whereis python3.

Next, we have to modify CMakeLists.txt to state that talker and listerner should be installed as program (ie. in the appropriate destination to make them reachable by ros2 command).

So add a python scripts section to your CMakeLists.txt file:

# Python scripts
install( PROGRAMS scripts/talker DESTINATION lib/${PROJECT_NAME} )
install( PROGRAMS scripts/listener DESTINATION lib/${PROJECT_NAME} )

You can now build again your ros workspace. The install directory contain a tutorial_pkg with every think=gs inside.

colcon build
ls install/
ls install/tutorial_pkg/lib/tutorial_pkg/

To use your package with ros2 commands, you have to update your bash environment. Then it would be possible to start your node with ros2 run command.

source ./install/local_setup.bash
ros2 run tutorial_pkg talker #or listener

Notice that, if your python node script relies on a local python package (myLocalPkg for instance). This one should be install aside of your script with the following cmake instruction:

install( DIRECTORY scripts/myLocalPkg DESTINATION lib/${PROJECT_NAME} )

Launch file

ROS proposes a launch mechanism to start in one command a configuration of several nodes. Launch file can be defined with markup language (XML or YAML) or python3 for more complex launch scenarios.

Yaml provides the simplest syntax to write launch files. The yaml.org gives an example of a yaml resources. Similarly to Python, it relies on indentation to mark the ownership of elements.

Another example:

aMark:
    aMarkedAttribute: "a string value"
    aSecondAttribut: ["a", "list", "of", "string", "element"]
    'a third attribute':
        - 1
        - 2
        - 12
    again:
        anotherMark:
            aMarkedAttribute: 36.8
...

ROS yaml relies on predefinite marks, key works: 'launch' as the first element and composed by a list of nodes. Minimal configuration for a node include pkg and exec attributes to identify the node to start.

A simple launch file for talker/listener will be:

launch:
    - node:
        pkg: "tutorial_pkg"
        exec: "talker"
    - node:
        pkg: "tutorial_pkg"
        exec: "listener"

The file has to be set on a launch directory into your package and with a name ending by _launch.yaml, converse_launch.yaml for instance.

At this point the launch file can be run using ros2 launch commands.

ros2 launch ./tutorial_pkg/launch/converse_launch.yaml

By adding launch resources to your package with CMakeList.txt configuration file, you make launch files easier to find.

In CMakeList.txt file:

# Install resource files.
install(DIRECTORY
  launch
  DESTINATION share/${PROJECT_NAME}/
)

Then in the terminal:

colcon build
ros2 launch tutorial_pkg converse_launch.yaml

Notice that other resources can be added to your package. Typically rviz for visualization configuration, world for simulation configuration, etc.

# Install resource files.
install(DIRECTORY
  launch rviz world
  DESTINATION share/${PROJECT_NAME}/
)