Aerostack2

DocsDevelop

Creating a package

How an Aerostack2 package is laid out, the style its code follows, and where to register it.

Authored by
  • @alvgaona

Aerostack2 packages share a layout and a set of conventions, so anyone on the team can find their way around a new one. The easiest start is to copy a small package that's close to yours, like as2_geozones for a C++ node or as2_keyboard_teleoperation for Python, and rename it.

Naming

Every Aerostack2 package is named as2_ followed by what it does, in snake case, like as2_core, as2_state_estimator or as2_platform_gazebo. Packages of the same kind share a second prefix, such as as2_platform_ for aerial platforms and as2_behaviors_ for behaviors. The aerostack2 metapackage, which installs all the others, is the one exception.

The examples on this page use as2_example.

Layout

  • as2_example/
    • CMakeLists.txtHow the package is built and tested
    • package.xmlName, version, license and dependencies
    • pixi.tomlThe package's Pixi build
    • README.md
    • config/Default parameters
    • include/
      • as2_example/
        • as2_example.hppPublic headers
    • launch/Launch files
    • src/
      • as2_example.cppThe node's code, built into a library
      • as2_example_node.cppOnly main, which runs the node
    • tests/
      • CMakeLists.txtPicks up the tests by suffix
      • as2_example_gtest.cppA GoogleTest test, run by colcon test
      • as2_example_test.cppAn executable you run by hand

The node's main lives in its own _node.cpp file. Everything else is built into a library, so the tests can link against it.

A package with a single node names the node after itself. Tests go in tests, not the ROS 2 default of test.

Build files

package.xml uses format 3 and the BSD-3-Clause license, and its version matches the other packages, since every package is released together. C++ packages need these test dependencies:

package.xml
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<test_depend>ament_cmake_gtest</test_depend>

CMakeLists.txt builds with C++17 and defaults to a release build. Its testing block runs the linters and adds the tests folder:

CMakeLists.txt
if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  ament_lint_auto_find_test_dependencies()
  add_subdirectory(tests)
endif()

tests/CMakeLists.txt picks up test files by their suffix. A file ending in _gtest.cpp becomes a GoogleTest test that colcon test runs. A file ending in _test.cpp becomes a plain executable, for checks you run by hand. Copy it from an existing package, such as as2_geozones.

Code style

C++ follows the Google C++ style guide and Python follows PEP 8 and PEP 257, as in the ROS 2 code style. The git hooks and linters check most of it.

Every file starts with the BSD 3-Clause license text, which the copyright test checks. Copy it from any file in the repository and set the year. After it, C++ files have a Doxygen header:

src/as2_example.cpp
/**
 * @file as2_example.cpp
 *
 * What this file implements.
 *
 * @author Your Name
 */

Python modules open with a docstring, then the license, then these fields:

as2_example/as2_example.py
"""What this module does."""

# Copyright 2026 Universidad Politécnica de Madrid
# ...

__authors__ = 'Your Name'
__copyright__ = 'Copyright (c) 2026 Universidad Politécnica de Madrid'
__license__ = 'BSD-3-Clause'

Document every public class and function in the headers, in Doxygen style. Log with the ROS 2 logging macros, like RCLCPP_INFO, not std::cout or print.

Register the package

A new package isn't built, released or tested until the repository knows about it. Add it to these files.

FileWhat to add
as2_example/pixi.tomlThe package's Pixi build, with its Aerostack2 dependencies as paths. Copy it from a similar package
aerostack2/package.xmlAn exec_depend on the package, so the aerostack2 metapackage installs it
aerostack2/pixi.tomlThe package under extra-package-mappings and under run-dependencies, with its path
.github/workflows/build-humble.yaml, build-jazzy.yaml and codecov_test.yamlThe package name in the package-name list, so CI builds and tests it
.github/labeler.ymlA label for its folder, if it doesn't fall under an existing one
.github/CODEOWNERSIts reviewers, if they differ from those of the folder it sits in

Build and test it

as2 build as2_example
as2 test -v as2_example

-v prints the full output, so you can see which test or linter failed and why. When everything passes, open a pull request.

Last updated on November 3, 2026

On this page

Last updated on November 3, 2026