diff --git a/tf2/Doxyfile b/tf2/Doxyfile
index de1043057..0b6201322 100644
--- a/tf2/Doxyfile
+++ b/tf2/Doxyfile
@@ -6,7 +6,7 @@ PROJECT_BRIEF = "tf2 maintains the relationship between coordinate fram
structure buffered in time, and lets the user transform points, vectors, etc between any two \
coordinate frames at any desired point in time."
-INPUT = ./include mainpage.dox
+INPUT = ./include
RECURSIVE = YES
OUTPUT_DIRECTORY = doc_output
@@ -21,3 +21,4 @@ EXPAND_ONLY_PREDEF = YES
PREDEFINED += TF2_PUBLIC=
PREDEFINED += TF2SIMD_FORCE_INLINE=
PREDEFINED += ATTRIBUTE_ALIGNED16(class)=
+EXCLUDE_PATTERNS = */test/*
diff --git a/tf2/doc/conf.py b/tf2/doc/conf.py
new file mode 100644
index 000000000..8e4fce7bd
--- /dev/null
+++ b/tf2/doc/conf.py
@@ -0,0 +1,199 @@
+# Copyright 2024 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+import os
+import sys
+sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+
+from datetime import datetime
+now = datetime.now() # current date and time
+year = now.strftime("%Y")
+
+project = 'tf2'
+copyright = '2008-' + year + ', Open Source Robotics Foundation, Inc.' # noqa
+author = 'Open Source Robotics Foundation, Inc.'
+
+# The short X.Y version
+version = ''
+# The full version, including alpha/beta/rc tags
+release = '0.36.2'
+
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.autosummary',
+ 'sphinx.ext.doctest',
+ 'sphinx.ext.coverage',
+ 'sphinx_rtd_theme',
+ 'myst_parser'
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = None
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = []
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = None
+
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_rtd_theme'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself. Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
+
+
+# -- Options for HTMLHelp output ---------------------------------------------
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'tf2_doc'
+
+
+# -- Options for LaTeX output ------------------------------------------------
+
+latex_elements = {
+ # The paper size ('letterpaper' or 'a4paper').
+ #
+ # 'papersize': 'letterpaper',
+
+ # The font size ('10pt', '11pt' or '12pt').
+ #
+ # 'pointsize': '10pt',
+
+ # Additional stuff for the LaTeX preamble.
+ #
+ # 'preamble': '',
+
+ # Latex figure (float) alignment
+ #
+ # 'figure_align': 'htbp',
+}
+
+
+# -- Options for manual page output ------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ (master_doc, 'tf2', 'tf2 Documentation',
+ [author], 1)
+]
+
+
+# -- Options for Texinfo output ----------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ (master_doc, 'tf2', 'tf2 Documentation',
+ author, 'tf2', 'ROS 2 components for point cloud transport.',
+ 'Miscellaneous'),
+]
+
+
+# -- Options for Epub output -------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = project
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#
+# epub_identifier = ''
+
+# A unique identification for the text.
+#
+# epub_uid = ''
+
+# A list of files that should not be packed into the epub file.
+epub_exclude_files = ['search.html']
+
+
+# -- Extension configuration -------------------------------------------------
+
+autoclass_content = 'both'
+
+autodoc_default_options = {
+ 'members': True, # document members
+ 'undoc-members': True, # also document members without documentation
+}
diff --git a/tf2/doc/cpp_api_docs.rst b/tf2/doc/cpp_api_docs.rst
new file mode 100644
index 000000000..2fe7df7e6
--- /dev/null
+++ b/tf2/doc/cpp_api_docs.rst
@@ -0,0 +1,10 @@
+C++ API Docs
+============
+
+These are the autogenerated docs for the internal implementation.
+
+.. toctree::
+ :maxdepth: 3
+ :caption: Contents:
+
+ generated/index
diff --git a/tf2/doc/index.rst b/tf2/doc/index.rst
new file mode 100644
index 000000000..781e5abf9
--- /dev/null
+++ b/tf2/doc/index.rst
@@ -0,0 +1,14 @@
+.. include:: ./mainpage.md
+ :parser: myst_parser.sphinx_
+
+.. toctree::
+ :maxdepth: 2
+
+ cpp_api_docs
+ self
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/tf2/mainpage.dox b/tf2/doc/mainpage.md
similarity index 93%
rename from tf2/mainpage.dox
rename to tf2/doc/mainpage.md
index 05f174bb9..99733956e 100644
--- a/tf2/mainpage.dox
+++ b/tf2/doc/mainpage.md
@@ -1,6 +1,3 @@
-/**
-\mainpage
-
``tf2`` is the second generation of the tf library.
This library implements the interface defined by `tf2::BufferCore`.
@@ -9,26 +6,26 @@ There is also a Python wrapper with the same API that class this library using C
Some tutorials are available at https://docs.ros.org/.
-\section architecture Architecture
+# Architecture
``tf2`` is a transform library designed to provide implementation of interface that keeps track of multiple coordinate frames over time.
``tf2`` maintains the relationship between coordinate frames in a tree structure buffered in time, and lets the user transform data between any two coordinate frames at any desired point in time.
The high level goal is to allow developers and users not to have to worry about which coordinate frame any specific data is stored in.
-\subsection main-interface Main Interface
+# Main Interface
The main interface is through the `tf2::BufferCore` interface.
It uses the exceptions in tf2/exceptions.h and the `tf2::Stamped` datatype in tf2/transform_datatypes.h.
-\subsection conversion-interface Conversion Interface
+# Conversion Interface
tf2 offers a templated conversion interface for external libraries to specify conversions between ``tf2``-specific data types and user-defined data types.
Various templated functions in ``tf2_ros`` use the conversion interface to apply transformations from the tf server to these custom datatypes.
The conversion interface is defined in tf2/convert.h.
-\subsection buffer-core-relations Buffer Core: Record and lookup relations between frames
+# Buffer Core: Record and lookup relations between frames
The ``tf2`` library implements the interface defined by `tf2::BufferCore`.
This class and all classes derived from it are responsible for providing coordinate transforms between any two frames in a system.
@@ -45,7 +42,7 @@ Therefore, for any given query it can be expected that data is interpolated.
It should be noted that buffer implicitly limits the maximum cache size of 10s by default as defined by the `tf2::TIMECACHE_DEFAULT_MAX_STORAGE_TIME` and it cannot interpolate outside of the cache history.
Thus there is a risk of incurring extrapolation limits based on specific system.
-\subsubsection buffer-core-methods Buffer Core Methods
+# Buffer Core Methods
The `tf2::BufferCore` class contains useful methods to update the existing tf buffer.
@@ -78,7 +75,7 @@ The `tf2::BufferCore` class contains useful methods to update the existing tf bu
- This method allows to see what frames have been cached and is useful for debugging.
-\subsection supported-datatypes Supported Datatypes
+# Supported Datatypes
``tf2`` implements templated datatype support.
This allows the core packages to have minimal dependencies and there be packages which add support for converting to and from different datatypes as well as transforming those data types.
@@ -88,7 +85,7 @@ However it's recommended to use a fully supported math datatype which best suppo
At it's core ``tf2`` relies on the `tf2::Stamped` data types which can be conveniently correlated to ROS 2 messages which have a `std_msgs::msg::Header`.
-\subsubsection data-type-support-packages Data Type Support Packages
+# Data Type Support Packages
These packages provide methods to allow ``tf2`` to work natively with data types of any external library.
Most are either C++ or Python specific.
@@ -113,7 +110,7 @@ Most are either C++ or Python specific.
- ``tf2`` methods to work with sensor_msgs datatypes natively in C++ or Python.
-\subsection coordinate-frame-conventions Coordinate Frame Conventions
+# Coordinate Frame Conventions
An important part of using ``tf2`` is to use standard conventions for coordinate frames.
There are several sources of conventions for using coordinate frames.
@@ -124,7 +121,7 @@ There are several sources of conventions for using coordinate frames.
- Standard coordinate frames for Humanoid Robots are in REP 120.
-\subsection geometry Geometry
+# Geometry
``tf2`` provides basic geometry data types, such as
@@ -138,7 +135,7 @@ There are several sources of conventions for using coordinate frames.
These data types support linear algebra operations between each other.
-\subsection high-level-design High level Design
+# High level Design
- A distributed system:
@@ -191,5 +188,3 @@ These data types support linear algebra operations between each other.
And as long as any datatype provides the methods ``msgType toMsg(datatype)`` and ``fromMsg(msgType, datatype)`` it can be automatically converted to any other datatype with the same methods defined and a matching ``msgType``.
All ``tf2_ros`` interfaces can then be called with native type in and native type out.
Note, the native type in and out do not need to match.
-
-*/
diff --git a/tf2/package.xml b/tf2/package.xml
index 4c688e8c2..029f1e39a 100644
--- a/tf2/package.xml
+++ b/tf2/package.xml
@@ -41,5 +41,6 @@
ament_cmake
+ rosdoc2.yaml
diff --git a/tf2/rosdoc2.yaml b/tf2/rosdoc2.yaml
new file mode 100644
index 000000000..a80c829b8
--- /dev/null
+++ b/tf2/rosdoc2.yaml
@@ -0,0 +1,68 @@
+## Default configuration, generated by rosdoc2.
+
+## This 'attic section' self-documents this file's type and version.
+type: 'rosdoc2 config'
+version: 1
+
+---
+
+settings:
+ ## If this is true, a standard index page is generated in the output directory.
+ ## It uses the package information from the 'package.xml' to show details
+ ## about the package, creates a table of contents for the various builders
+ ## that were run, and may contain links to things like build farm jobs for
+ ## this package or links to other versions of this package.
+
+ ## If false, you can still include content that would have been in the index
+ ## into one of your '.rst' files from your Sphinx project, using the
+ ## '.. include::' directive in Sphinx.
+ ## For example, you could include it in a custom 'index.rst' so you can have
+ ## the standard information followed by custom content.
+
+ ## TODO(wjwwood): provide a concrete example of this (relative path?)
+
+ ## If this is not specified explicitly, it defaults to 'true'.
+ generate_package_index: true
+
+ ## This setting is relevant mostly if the standard Python package layout cannot
+ ## be assumed for 'sphinx-apidoc' invocation. The user can provide the path
+ ## (relative to the 'package.xml' file) where the Python modules defined by this
+ ## package are located.
+ python_source: 'tf2'
+
+ ## This setting, if true, attempts to run `doxygen` and the `breathe`/`exhale`
+ ## extensions to `sphinx` regardless of build type. This is most useful if the
+ ## user would like to generate C/C++ API documentation for a package that is not
+ ## of the `ament_cmake/cmake` build type.
+ always_run_doxygen: false
+
+ ## This setting, if true, attempts to run `sphinx-apidoc` regardless of build
+ ## type. This is most useful if the user would like to generate Python API
+ ## documentation for a package that is not of the `ament_python` build type.
+ always_run_sphinx_apidoc: false
+
+ # This setting, if provided, will override the build_type of this package
+ # for documentation purposes only. If not provided, documentation will be
+ # generated assuming the build_type in package.xml.
+ # override_build_type: 'ament_python'
+builders:
+ ## Each stanza represents a separate build step, performed by a specific 'builder'.
+ ## The key of each stanza is the builder to use; this must be one of the
+ ## available builders.
+ ## The value of each stanza is a dictionary of settings for the builder that
+ ## outputs to that directory.
+ ## Required keys in the settings dictionary are:
+ ## * 'output_dir' - determines output subdirectory for builder instance
+ ## relative to --output-directory
+ ## * 'name' - used when referencing the built docs from the index.
+
+ - doxygen: {
+ name: 'tf2 Public C/C++ API',
+ output_dir: 'generated/doxygen'
+ }
+ - sphinx: {
+ name: 'tf2',
+ ## This path is relative to output staging.
+ doxygen_xml_directory: 'generated/doxygen/xml',
+ output_dir: ''
+ }