ROS2 workspace directory structure
In ROS2, the directory structure has a standard convention that helps in organization, package discovery, and build tooling.
Here's a typical filesystem layout for a ROS2 workspace as currently in-use:
workspace_directory/
│
├── src/
│ ├── package_1/
│ │ ├── package.xml
│ │ ├── setup.py
│ │ ├── setup.cfg
│ │ ├── CMakeLists.txt
│ │ ├── package_1/
│ │ │ ├── __init__.py
│ │ │ ├── node_1.py
│ │ │ └── node_2.py
│ │ └── ...
│ │
│ ├── voice_assistant/
│ │ ├── package.xml
│ │ ├── setup.py
│ │ ├── setup.cfg
│ │ └── voice_assistant/
│ │ ├── __init__.py
│ │ └── assistant.py
│ │
│ ├── motors/
│ │ ├── package.xml
│ │ ├── setup.py
│ │ ├── setup.cfg
│ │ └── motors/
│ │ ├── __init__.py
│ │ ├── motor_control.py
│ │ └── motor_feedback.py
│ │
│ ├── datatypes/
│ │ ├── package.xml
│ │ ├── CMakeLists.txt
│ │ ├── srv/
│ │ └── service.srv
│ │ └── msg/
│ │ └── messages.msg
│ │
│ └── …
│
├── build/
├── install/
└── log/
Â
Here's a breakdown:
workspace_directory: The root directory of your ROS 2 workspace. This is basically just a folder that contains all the necessary directories to run a ros2 application: build, install, log and src. The first three can be generated with the
colcon build
command and do not have to be downloaded.src: This directory contains all your ROS 2 packages (interfaces and nodes).
package_1, ...: Directories for individual ROS 2 packages. Each package can contain one or more nodes. Inside a package the files package.xml, setup.cfg and setup.py enable the configuration of nodes and communications. The folder in a package, with the package name contains the __init__.py and the node-files. It is possible to have multiple node-files in one package.
package.xml: Provides metadata about the package, including its name, version, dependencies, etc.
setup.py: Provides setup-metadata of setup, including its name, and wat channels of communication are used, for what file (Topic-name used for reading & writing messages).
CMakeLists.txt: Describes how the package should be built using CMake. ROS 2 uses ament as its build system, which extends CMake. Used in order to run interfaces.
Packages
Packages is a collective for interfaces and nodes. It is good practice to group nodes with similar function or interactions with the same topic into one packages, depending on how related they are and your organizational preferences.
Nodes can be Client- or Service-Nodes. This means that they can subscribe or publish to topics.
Interfaces are definitions of data-types. These can be Services, Messages or Actions.
Create and Run
After navigating to the workspace-directory, any changes in packages needs to be updated. This includes a building command: colcon build
(or a similar command, that only builds the recently changed packages) and a source command: source install/setup.bash
. The build command automatically generates / edits the existing build/
, install/
, and log/
files.
To execute a node the designated package and node-name should be used:
ros2 run <package_name> <node_alias_name>
The interfaces only need to be build and sourced. Thereafter the provided Datatypes can be used by all the nodes.
Naming conventions
ROS 2 maintains a set of naming conventions and guidelines to ensure consistency, clarity, and discoverability across the vast ecosystem of ROS packages. These conventions help users and developers navigate, understand, and use ROS packages effectively. Here are the naming conventions for ROS 2 packages:
Use Only Alphanumeric and Underscores: Package names should consist only of lowercase alphabetic characters and underscores. Avoid using numbers unless necessary.
No Capital Letters: Use of capital letters in package names is discouraged. Instead, separate words with underscores. For instance,
my_awesome_package
is preferred overMyAwesomePackage
.No Hyphens: Hyphens (
-
) are not allowed in package names. Use underscores (_
) instead.Short and Descriptive: Names should be as short as possible but also descriptive. For instance,
laser_drivers
is more descriptive than justdrivers
.Avoid Redundancies: Do not use redundant prefixes or suffixes like
ros2
ornode
. For example, if creating a package for a ROS 2 driver for a LIDAR, preferlidar_driver
overros2_lidar_driver
.Specific Over General: If you're creating a package for a specific brand or model, it's okay to use that in the name for clarity, e.g.,
kuka_arm_driver
orvelodyne_lidar_driver
.Dependencies and Extensions: If your package is a plugin, driver, or some extension for another package or framework, you can use the main package or framework's name as a prefix. For instance, if you're writing a plugin for
rviz
(the ROS visualization tool), you might name your packagerviz_my_plugin
.Avoid Using Reserved or Overloaded Names: Names that are general programming terms like
test
,system
,interface
, etc., might be misleading or ambiguous. Always opt for a name that gives more context.Migration or Versions: If you're migrating a ROS 1 package to ROS 2, it's recommended not to append a
_ros2
suffix. Instead, ROS 2 packages should have the same name as their ROS 1 counterpart if they provide the same functionality.
These conventions, combined with other best practices, ensure the ROS 2 community has a coherent and easy-to-navigate ecosystem of packages.