Customizing rosdoc2 with Sphinx
Table of Contents
With renewed activity around rosdoc2 (my PR got merged after 498 days!), and ongoing discussion about the state of documentation in ROS 2, I decided to look at ROS 2 package docs once again. This is also a followup to my older post on releasing a ROS package.
rosdoc2⌗
The tool responsible for generating ROS 2 package docs is rosdoc2
.
It is what runs on the ROS build farm whenever you update your package and have enabled the appropriate options in rosdistro/<ROS DISTRO>/distribution.yaml
:
rviz_2d_overlay_plugins:
doc:
type: git
url: https://github.com/teamspatzenhirn/rviz_2d_overlay_plugins.git
version: main
release:
[...]
While somewhat intimidating at first, rosdoc2
really is just a very convenient wrapper around the commonly used Sphinx
documentation framework including its C++ integration with doxygen via breathe
+ exhale
.
It creates a somewhat sensible default configuration for packages with no documentation or configuration at all, applies some options for a uniform theme and integration with other packages.
Custom Sphinx project⌗
But where do we go once the default is not sufficient anymore (which is immediately once you start writing docs which go beyond API-docs)?
Luckily, it is possible to setup a completely standard sphinx project, which rosdoc2
will pick up on.
Using the sphinx-quickstart
tool in the <package-root>/doc
directory creates an empty sphinx project that rosdoc2
will find.
This does not require any custom rosdoc2.yaml
!
Now, you can write any free-form documentation, tutorials and more just as you would with sphinx, and build and preview them using:
rosdoc2 build --package-path ./<package-path>
Including the generated (default) pages in the custom project⌗
I wanted to still include the generated API docs in a subdirectory, and link to it from my new, custom index page.
Looking at the default index page, all it does is link to generated/index
.
I added a page cpp_api_docs.rst
besides index.rst
, with the following content:
C++ API Docs
============
These are the autogenerated docs for the internal implementation.
.. toctree::
:maxdepth: 3
:caption: Contents:
rviz_2d_overlay_plugins <generated/index>
Which is included from index.rst
:
.. toctree::
:maxdepth: 2
:caption: Contents:
self
cpp_api_docs
This results in the generated docs to appear in a sub-category “C++ API Docs” without cluttering the index page or table of contents!
Including an existing README.md⌗
I already had a README.md with a few screenshots, which I wanted to use as the index page for the documentation, without copying it. After some fiddling around with sphinx, I found a satisfying solution which doesn’t require changing the readme to rst and doesn’t break relative paths to images included in the markdown:
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"]
What now?⌗
I will now try to include this in the README of rosdoc2
, i guess…
Up next: finding out how to automate more of the process, such as eliminating options in config.py
that could be generated from package.xml
and generating docs from ROS message definitions!