# Conventions
## Folder Structure
We try to follow this folder structure for the ROS packages:
```text
ros_package/
| docker-compose.yml
| ros_package.Dockerfile
|
└───src/
|
└───ros_package/
| CMakeLists.txt
| package.xml
|
└───src/
| | cpp_node.cpp
|
└───include/
| └───ros_package/
| | cpp_header.hpp
|
└───src_py/
| | py_node.py
|
└── test/
| __init__.py
| test_feature.py
|
└───ros_package/
| | __init__.py
| | py_module.py
|
└───launch/
| launch_file.launch.py
```
- Every overall ROS package contains the `docker-compose.yml` and `ros_package.Dockerfile` in the root directory.
- Every "sub"-ROS package contains the `CMakeLists.txt` and `package.xml` in the 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 optionally 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
A top-level `test/conftest.py` can be used 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 *alliander_interfaces* 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
```
### The Service Structure
Unless more data is required, the `Response` of our services contains the following data by default:
```text
---
bool success
string message
```
When our service only requires a single request datatype, and the default response as described above, the name of the service will simply be the datatype of the request + `Srv`. So for example, when the only datatype in the request is a `string`, the service will be called `StringSrv.srv`.
In case the service is more complex, the name of the service will represent its purpose. E.g., if the intention of the service is to add an object to a scene, the name of the service will be `AddObject.srv`.
### The Action Structure
Unless more data is required, the `Response` and `Feedback` of our actions contains the following data by default:
```text
---
bool success
string message
---
string status
```
When our action only requires a single request datatype, and the default response & feedback as described above, the name of the action will simply be the datatype of the request + `Action`. So for example, when the only datatype in the request is a `string`, the action will be called `StringAction.action`.
In case the action is more complex, the name of the action will represent its purpose. E.g., if the intention of the action is to move an object to a location in the scene, the name of the action will be `MoveObjectToLocation.action`.