Documenting a ROS 2 package
This guide introduces the standard way to create documentation for ROS 2 packages.
For packages with binary releases this also results in the docs being hosted at docs.ros.org/en/<distro>/p/<package>/
.
For information on how to contribute to this documentation on docs.ros.org, see Contributing to ROS 2 Documentation.
Prerequisites
Package Documentation Overview
The type of documentation discussed in this guide is referred to as “package docs” or “API docs”.
For ROS packages that have been released on ROS Index, their documentation will be built on the ROS buildfarm, included on docs.ros.org, and visible via the API Docs
button on index.ros.org.
The tool responsible for generating ROS 2 package docs is rosdoc2.
rosdoc2
is a convenient wrapper around the commonly used Sphinx documentation framework.
Sphinx allows freeform written documentation as well as API documentation for python code generated from comments in the code.
The breathe + exhale packages allow integration with Doxygen, to include autogenerated C++ API documentation as well.
rosdoc2
creates a default configuration for packages with no documentation or configuration at all, and applies options for a uniform theme and integration with other packages.
Building Package Docs
To generate the documentation for a package in HTML format with rosdoc2
, run:
rosdoc2 build --package-path <package-path>
The documentation is written to docs_output/<package-name>/index.html
and can be viewed in a browser.
Configuration
There are three configuration locations for ROS package docs: rosdoc2.yaml
for general settings,
conf.py
for sphinx settings and the Doxyfile
for doxygen settings.
For all of those, a default is assumed or generated if not present, so none of them is strictly required.
However, it might be necessary to create and modify those once you want to use features such as custom textual documentation pages.
rosdoc2.yaml
This is the main entrypoint for rosdoc2. It specifies generic settings, and can be used to control the execution of specific builders (Doxygen and Sphinx) and decides which builders to run.
rosdoc2
provides a multitude of configuration options, which can be adjusted in a config file rosdoc2.yaml
.
To generate a default rosdoc2.yaml
which you can then further customize, run:
rosdoc2 default_config --package-path <package-path>
And add <rosdoc2>rosdoc2.yaml</rosdoc2>
to the export section in your package.xml
:
<package>
<!-- [...] -->
<export>
<!-- [...] -->
<rosdoc2>rosdoc2.yaml</rosdoc2>
</export>
</package>
However, for most packages, the default settings in rosdoc2
will suffice, and no custom config is necessary.
More information about rosdoc2.yaml
can be found in the rosdoc2 readme.
conf.py, rosdoc2_settings
The final output of the package docs is (almost) always built by Sphinx.
Each Sphinx project is configured by a conf.py
file in the doc
directory.
If no configuration is present, a default Sphinx project is created and used when building the documentation.
If however a conf.py
Sphinx config is found in the doc
subdirectory of the package, this is used instead.
A custom Sphinx project is required if you want to include a standalone reStructuredText documentation page.
A standalone documentation page can be used to list multiple tutorials and guides; if that’s something you want for your package you’ll need to create a custom Sphinx project.
rosdoc2
provides additional settings to conf.py
and overrides some.
Information about changes done to the Sphinx settings are logged to the console with a [rosdoc2]
prefix.
Doxyfile
Doxygen is a tool for automatically generating C++ API docs from code comments.
While Doxygen can also generate HTML output directly, in the usual workflow for ROS packages, Doxygen produces machine readable output in XML format which is then consumed by Sphinx and integrated with the rest of the documentation.
Doxygen-only docs are possible by only enabling the Doxygen builder in rosdoc2.yaml
, but this is uncommon.
Customizing Sphinx Documentation
Creating a Sphinx Project
In order to add standalone documentation pages in addition to the automatically generated API docs, a custom Sphinx project is necessary.
This should be created in a subdirectory called doc
in the package directory.
A new Sphinx project can be created by running sphinx-quickstart
in the doc
directory, answering no
to “Separate source and build directories”.
The wizard requires entering the project name, author and version, but this can later be removed and will be provided to Sphinx by rosdoc2
from your packages package.xml
.
More information about creating a sphinx project can be found on the Sphinx quickstart page,
Customizing index.rst
The sphinx-quickstart
wizard creates an index.rst
file, which is the custom landing page for your package, similar to a Github README
file.
Adding Python API-Docs
By default rosdoc2
uses the sphinx-apidoc tool and the autodoc Sphinx extension to automatically generate documentation for python code.
In order for autodoc to find the Python modules in your package, it must be added to the python search path in conf.py
:
sys.path.insert(0, os.path.abspath('.'))
This is because rosdoc2
wraps the custom conf.py
with more configuration from a script which will be placed in the package.
In this case the .
path in os.path.abspath
refers to the package’s directory root, not the package’s doc
directory due to the interaction between rosdoc2 and conf.py
.
By default, package API docs are already reachable through the “Module Index” link that is present on the landing page.
For the API docs to also appear in the table of contents, simply add a link to the modules
page to your index.rst
:
.. toctree::
:maxdepth: 2
:caption: Contents:
Python Modules <modules>
Adding C++ API-Docs
If you would like to add your automatically generated API docs back to your custom landing page, add the line generated/index
to your documentation page where you would like the API docs to appear:
.. toctree::
:maxdepth: 2
C++ API Docs <generated/index>
This adds the elements “Class Hierarchy”, “File Hierarchy” and “Reference” to the table of contents in the sidebar.
To make those appear under one “C++ API Docs” heading for a less cluttered sidebar, a separate file such as cpp_api_docs.rst
can be added, which links to the generated docs:
C++ API Docs
============
These are the autogenerated docs for the internal implementation.
.. toctree::
:maxdepth: 3
:caption: Contents:
generated/index
Which then also needs to be added in index.rst
to appear in the sidebar:
.. toctree::
:maxdepth: 2
:caption: Contents:
cpp_api_docs
Including an existing README.md
If your git repository already has an existing README.md
, it is possible to reuse this as the landing page for the documentation, without duplicating the contents.
To correctly include a Markdown file in Sphinx while preserving relative links and images, some additional effort is required.
First, create a proxy-file readme_include.md
next to index.rst
.
This is a markdown file which just includes the original README.md, but preserves the relative image paths, which would otherwise break in the next step:
```{include} ../README.md
:relative-images:
```
Then, include the contents of this file from index.rst
using myst
to include markdown from rst:
.. include:: readme_include.md
:parser: myst_parser.sphinx_
This also requires adding myst_parser
to the extensions in conf.py
:
extensions = ["myst_parser"]
CI, docs.ros.org
The ROS build farm uses rosdoc2
to build the package documentation hosted at docs.ros.org/en/<distro>/p/<package>/
.
To enable this, the repository containing the documentation must be configured in rosdistro/jazzy/distribution.yaml.
This would usually be the package source repository:
<package_name>:
doc:
type: git
url: https://github.com/<github_username>/<package_name>.git
version: main
release:
[...]
The buildfarm hosts the documentation for every distribution separately, and periodically rebuilds it from the latest commit on the specified branch.
It is not required to tag a new release to update the hosted documentation.
To view the status of your package’s documentation build, search for doc__<package_name>
on https://build.ros2.org.
One job is created for every distribution for which the package is released.
On each job page, you can see when a build was last triggered, as well as the status and logs of each build.
Further Reading
rosdoc2
readme: https://github.com/ros-infrastructure/rosdoc2/blob/main/README.mdROS 2 design document on package documentation: https://design.ros2.org/articles/per_package_documentation.html
The ROS 2 cookbook: https://github.com/mikeferguson/ros2_cookbook/blob/main/pages/rosdoc2.md