# Conventions
## ROS packages
ROS packages are defined in the *ros2_ws/src* directory.
### Folder Structure
We try to follow this folder structure for the ROS packages:
```text
ros_package/
| CMakeLists.txt
| package.xml
|
└───src/
| | cpp_node.cpp
|
└───include/
| └───ros_package/
| | cpp_header.hpp
|
└───src_py/
| | py_node.py
|
└───ros_package/
| | __init__.py
| | py_module.py
│ └── test/
│ ├── conftest.py
│ ├── unit/
│ │ └── test_py_module.py
│ ├── integration/
│ │ └── test_service_client.py
│ └── end_to_end/
│ └── test_full_launch.py
└───launch/
| launch_file.launch.py
```
- Every ROS package contains the `CMakeLists.txt` and `package.xml` in the root directory.
- In case of development using C++, the executables are located in the `src/` directory. The corresponding headers are located in the `include/` directory, inside a sub-directory that equals the package name.
- In case of development using Python, the executables are located in the `src_py/` directory.
- A sub-directory `ros_package/` with the same name as the ROS package can be used to create a Python package. This directory contains an `__init__.py` file and the Python modules of the Python package.
- Possible launch files are located in the `launch/` directory.
- More directories are possible, like `urdf/` for urdf files or `config/` for config files.
- The testing layout is placed alongside the Python package, with these subfolders:
- `unit/` for fast, logic-only tests
- `integration/` for multi-component or ROS client/server tests
- `end_to_end/` for full launch/simulation tests
Use a top-level `test/conftest.py` to define shared fixtures, and name your files/functions `test_*` so pytest auto-discovers them. The most general fixtures are defined in the `conftest.py` in the root of the repository.
### CMakeLists.txt
This CMakeLists.txt file shows the different parts required to build a ROS package:
:::{literalinclude} example_files/ros_package/CMakeLists.txt
:language: CMake
:linenos:
:::
**5-10**:\
The file always starts with a version definition, the package name and the CMake dependencies when building C++ and/or python files.
**12-14**:\
If the package depends on other packages, these are defined. In this case, the packaged depends on the *vision_msgs* and *geometry_msgs* packages.
**16-22**:\
Building a C++ executable requires 3 steps: defining the executable, linking dependencies (if any) and installing the targets to the lib directory.
**24-28**:\
For Python executables, we can simply install them all at the same time, by providing the directory.
**30-31**:\
If the package contains a Python package, it needs to be installed.
**33-37**:\
All shared folders are installed into the share directory. This includes the directory of launch files, but also other possible directories, like `urdf/` or `config/`, if these exist.
**39-45**:\
The file always ends with a default test and the *ament_package()* command.
### package.xml
The package.xml file is related to the CMakeLists.txt file:
:::{literalinclude} example_files/ros_package/package.xml
:language: xml
:linenos:
:::
**1-2**:\
The files starts with default xml definitions.
**10-15**:\
Inside the *package* tag, we start with some general information about the package.
**17-18**:\
Next, we define the build tool dependencies for building C++ and/or Python files.
**20-21**:\
Next, we define other packages where our package depends on.
**23-28**:\
The file ends with the default test dependency and an export definition.
### Custom messages, services and actions
We define custom messages, services and actions in our *rcdt_messages* package. This package has the following folder structure:
```text
ros_package/
| CMakeLists.txt
| package.xml
|
└───msg/
| | custom_message_definition.msg
|
└───srv/
| | custom_service_definition.srv
|
└───action/
| custom_action_definition.action
```
In the CMake file, we automatically look for all msg, srv and action files and generate interfaces for them:
:::{literalinclude} example_files/ros_msgs_package/CMakeLists.txt
:language: CMake
:linenos:
:::
To generate custom messages successfully, we also need to specify the following dependencies in the package.xml file:
```xml
rosidl_default_generators
rosidl_interface_packages
```