Contributing#
Bug fixes, plugins, new robot platforms (Integrating a Robot), documentation, tests and performance improvements are welcome. By participating, you agree to abide by the Code of Conduct, and by contributing, that your contributions are licensed under the BSD 3-Clause License.
Development Setup#
Open Apero builds natively on Ubuntu 20.04 with ROS Noetic; on any other host, develop in the Docker image
(In Docker). Fork OpenApero/openapero, follow
Installation but clone your fork with upstream as a second remote, and install the commit hooks
of .pre-commit-config.yaml:
cd ~/catkin_ws/src
git clone --recursive https://github.com/<your-username>/openapero.git open_apero
git -C open_apero remote add upstream https://github.com/OpenApero/openapero.git
curl -LsSf https://astral.sh/uv/install.sh | sh && source ~/.local/bin/env # uv, unless installed
uv tool install --python 3.11 'pre-commit<4.6.1' # 4.6.1 and later need git 2.31; Ubuntu 20.04 has 2.25
cd open_apero && pre-commit install
Build (cd ~/catkin_ws && catkin build && source devel/setup.bash), run the tests, then create a branch.
Running Tests#
After a full catkin build, build and run the tests of Open Apero’s own packages, as CI’s
build_test.yml does:
cd ~/catkin_ws
OWNED="open_apero_analysis open_apero_controllers open_apero_core open_apero_ros \
open_apero_graph_benchmark open_apero_habitat open_apero_voxblox"
catkin build $OWNED --no-deps --catkin-make-args run_tests --
for pkg in $OWNED; do catkin_test_results "build/$pkg"; done
catkin_test_results exits non-zero when one of a package’s tests failed. A workspace-wide run_tests would also
build third-party tests, and those of eigen_checks fail to build. To iterate on one package, set OWNED to it alone.
In Docker#
The image copies the source tree when it is built: rebuild it after every change, then run the
test command of docker/README.md.
Coding Standards#
The commit hooks format C++ with clang-format 10.0.1, which they install themselves (for an editor,
pip install clang-format==10.0.1; other versions differ), and
.clang-format, and Python with black and ruff,
configured in pyproject.toml.
C++: C++17, built with
-Wall -Wextra -Werror=return-type, and new code adds no warnings. Headers use#pragma once. The vendored headers inopen_apero_core/include/open_apero_core/third_party/stay as upstream’s.Naming: classes and structs
PascalCase; functionscamelCase; variables and struct memberssnake_case; class memberssnake_case_(p_<key>_when bound to a parameter key,c_*_when derived from parameters); constantskPascalCase; namespacessnake_case; files thesnake_caseof their class. Acronyms are cased as words (NodeId,TsdfMap), except algorithm names that are plugin IDs (RRT,RRAG). Spelling is American (center,color).Includes: own header (
.cpponly), C system, C++ standard library, third-party and other packages, same package, one blank line apart and alphabetical within;""for the same package,<>for all others. Include what you use; no forward declarations unless one breaks a circular include.Python: PEP 8, Python 3.8 (the ROS Noetic system Python). Code lives in
<pkg>/python/<pkg>/; anodes/<module>_nodeorscripts/<tool>.pyonly calls its module’smain()and is listed intest/test_<pkg>_imports.py(<pkg>without itsopen_apero_prefix). Runs write below~/open_apero_data, never into the source tree.Folders: a package holds only
include/,src/(plugins inplugin/<kind>/),python/,nodes/,scripts/,launch/,config/,rviz/,meshes/,msg/,cmake/,data/(tracked input, never run output) andtest/.ROS and tools: the executable, the node name and the launch file’s
name=are the same<module>_node. Parameter keys aresnake_casewith words spelled out (visualization, notviz); a frame parameter ends in_frame. Command-line options are kebab-case (--data-root DIR,--out-dir DIR,--dry-run).
Adding a Plugin#
Extending Open Apero holds the plugin extension contract. A type that ships in this repository also needs, in the same pull request:
Its header and source in
plugin/<role>/ofopen_apero_core(a ROS-dependent type:open_apero_ros), listed in the library’s sources (SRC_FILESofopen_apero_core/CMakeLists.txt); the class in the namespace of its role (open_apero::generator::RRAG), registered under its class name.For a core type, a recipe in
open_apero_core/test/test_plugin_conformance.cpp.Its keys, defaults and shipped values in the Parameter Reference.
A Doxygen
@briefon the class and its public methods, and a{doxygenclass}entry indocs/api/builtin-plugins.md(a layer:layers.md; a map backend:maps.md; anopen_apero_rostype:ros.md; a new role’s base class:plugin-interfaces.md).For a new planner,
open_apero_ros/config/planners/<planner>.yamlholding only itslayers.planningblock.
Documentation#
One fact has one home, and every other place links to it: explanation and guides in docs/*.md; plugin and agent YAML
keys in docs/parameters.md; a node’s parameters, topics and services in its package README.md (a tool’s flags in
scripts/README.md); a launch argument in a comment next to its <arg>; the C++ API in Doxygen comments. Diagrams are
Mermaid blocks. Keep pages short: a sentence and a link instead of a repeated default.
Links use relative paths. The site includes CONTRIBUTING.md and CHANGELOG.md whole, and README passages between
<!-- <name>-start… --> and <!-- <name>-end --> comments: there, link a docs/ page by its relative path and any
other file by its https://github.com/OpenApero/openapero/blob/main/... URL.
Build the docs for a change to them or to a public header, in a separate environment (Sphinx 8.2 needs Python 3.11 or
newer). Sphinx runs with -W, so any warning fails the build, as in CI’s
docs.yml. From the repository root:
sudo apt-get install doxygen
uv venv -p 3.11 ~/venvs/open_apero_docs && . ~/venvs/open_apero_docs/bin/activate
uv pip install -r docs/requirements.txt
docs/generate_docs.sh # output: docs/_build/html/index.html
Submitting Changes#
Run the tests (Running Tests) and
pre-commit run --all-filesfrom the repository root, as CI’sportability.ymldoes.If you changed documentation or public headers, build the docs (Documentation).
For a user-visible change, add one line to
CHANGELOG.mdunder## [Unreleased](add the heading above the latest release if missing), in its group (### Added,### Changed,### Fixed,### Removed).Rebase on
main(git fetch upstream && git rebase upstream/main), then open one pull request per change with the pull request template.
A commit subject is one imperative sentence of at most 72 characters, without a trailing period. A change confined to
one package may prefix it with [<package>], one confined to one class with <Class>:
(Agent: Count dispatched commands and integrated frames per cycle). A body, after a blank line, gives the motivation.
Reporting Bugs and Requesting Features#
Open an issue with the bug report or feature request template; for a bug, the commit, native or Docker, the launch command and the planner configuration usually decide whether it reproduces. Report security problems privately (SECURITY.md).