Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .devcontainer/postCreateCommand.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ set -e

export PIP_BREAK_SYSTEM_PACKAGES=1
pip install -r ../docs/source/requirements.txt
pip install sphinx-autobuild
pip install sphinx-autobuild
chmod +x serve_sphinx.sh
4 changes: 4 additions & 0 deletions .devcontainer/serve_sphinx.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash
set -e

sphinx-autobuild ../docs/source ../build/html
5 changes: 4 additions & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ build:
tools:
python: "3.11"
# You can also specify other tool versions:
# nodejs: "19"
nodejs: "19"
# rust: "1.64"
# golang: "1.19"
jobs:
post_install:
- npm install -g @mermaid-js/mermaid-cli

# Build documentation in the docs/ directory with Sphinx
sphinx:
Expand Down
14 changes: 12 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# -- Project information

project = 'ROS2 Tutorial'
project = "(Murilo's) ROS2 Tutorial"
author = 'Murilo M. Marinho'

if this_year_str == '2023':
Expand All @@ -31,7 +31,8 @@
'hoverxref.extension', # https://sphinx-hoverxref.readthedocs.io/en/latest/index.html
'sphinx_copybutton', # https://sphinx-copybutton.readthedocs.io/en/latest/
'sphinx_design', # https://sphinx-design.readthedocs.io/en/latest/get_started.html
"sphinxext.remoteliteralinclude" # https://github.com/wpilibsuite/sphinxext-remoteliteralinclude
'sphinxext.remoteliteralinclude', # https://github.com/wpilibsuite/sphinxext-remoteliteralinclude
'sphinxcontrib.mermaid' #https://sphinxcontrib-mermaid-demo.readthedocs.io/en/latest/
]

intersphinx_mapping = {
Expand All @@ -46,13 +47,22 @@

html_theme = 'sphinx_book_theme'
# Tried with `furo` on May 23, 2025, but somehow it didn't look right. In particular the download button wasn't as clear.
html_theme_options = {
"announcement": "The documentation is being updated to Jazzy in this branch. "
"See <a href='https://ros2-tutorial.readthedocs.io/en/humble/'>Humble Docs</a> for the stable ones. "
"Create an <a href='https://github.com/mmmarinho/ROS2_Tutorial/issues'>issue</a> for inconsistencies.",
}
html_title = project

# -- Options for EPUB output
epub_show_urls = 'footnote'

# -- Options for hoverxref.extension https://sphinx-hoverxref.readthedocs.io/en/latest/configuration.html
hoverxref_auto_ref = True

# https://sphinxcontrib-mermaid-demo.readthedocs.io/en/latest/
mermaid_params = ['-p' 'puppeteer-config.json']

# -- Options for latex https://docs.readthedocs.io/en/stable/guides/pdf-non-ascii-languages.html
# latex_engine = "xelatex"
# By using this, the UTF emojis became question marks in the PDF.
Expand Down
87 changes: 56 additions & 31 deletions docs/source/create_interface_package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Creating a dedicated package for custom interfaces

Despite this push in ROS2 towards having the users define even the simplest of message types, to define new interfaces in ROS2 we must use an :program:`ament_cmake` package. It **cannot** be done with an :program:`ament_python` package.

.. seealso::

The contents of this session were simplified in this version. A more complex example is shown in https://ros2-tutorial.readthedocs.io/en/humble/service_servers_and_clients.html.

All interfaces in ROS2 must be made in an :program:`ament_cmake` package. We have so far not needed it, but for this scenario we cannot escape. Thankfully, for this we don't need to dig too deep into :program:`CMake`, so fear not.

Creating the package
Expand All @@ -28,14 +32,14 @@ which again shows our beloved wall of text, with a few highlighted differences b

going to create a new package
package name: package_with_interfaces
destination directory: /home/murilo/git/ROS2_Tutorial/ros2_tutorial_workspace/src
destination directory: /root/ros2_tutorial_workspace/src
package format: 3
version: 0.0.0
description: TODO: Package description
maintainer: ['murilo <[email protected]>']
maintainer: ['root <[email protected]>']
licenses: ['TODO: License declaration']
build type: ament_cmake
dependencies: [geometry_msgs]
dependencies: ['geometry_msgs']
creating folder ./package_with_interfaces
creating ./package_with_interfaces/package.xml
creating source and include folder
Expand All @@ -44,7 +48,7 @@ which again shows our beloved wall of text, with a few highlighted differences b
creating ./package_with_interfaces/CMakeLists.txt

[WARNING]: Unknown license 'TODO: License declaration'. This has been set in the package.xml, but no LICENSE file has been created.
It is recommended to use one of the ament license identitifers:
It is recommended to use one of the ament license identifiers:
Apache-2.0
BSL-1.0
BSD-2.0
Expand All @@ -63,7 +67,7 @@ The :file:`package.xml` dependencies
Whenever the package has any type of interface, the :file:`package.xml` **must** include three specific dependencies. Namely, the ones highlighted below.
Edit the :file:`package_with_interfaces/package.xml` like so

:download:`package.xml <../../ros2_tutorial_workspace/src/package_with_interfaces/package.xml>`
:download:`~/ros2_tutorial_workspace/src/package_with_interfaces/package.xml <../../ros2_tutorial_workspace/src/package_with_interfaces/package.xml>`

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/package.xml
:language: xml
Expand Down Expand Up @@ -98,12 +102,28 @@ Let us create a message file to transfer inspirational quotes between Nodes. For
There are many ways to represent this, but for the sake of the example let us give each message an :code:`id` and two rather obvious fields.
Create a file called :file:`AmazingQuote.msg` in the folder :file:`msg` that we just created with the following contents.

:download:`AmazingQuote.msg <../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuote.msg>`
:download:`~/ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuote.msg <../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuote.msg>`

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuote.msg
:language: yaml
:linenos:

Re-using a message from the same package
++++++++++++++++++++++++++++++++++++++++

With the :file:`AmazingQuote.msg`, we have seen how to use built-in types. Let's use another message, :file:`AmazingQuoteStamped.msg`, to learn two more possibilities, namely using messages from the same package and messages defined elsewhere.

:download:`~/ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuoteStamped.msg <../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuoteStamped.msg>`

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuoteStamped.msg
:language: yaml
:linenos:

Note that if the message is defined in the same package, the package name does not appear in the message (or service) definition. If the message is defined elsewhere, we have to fully specify the package.

In many :program:`ROS2` packages, messages with the suffix ``Stamped`` exist. As a rule, those are the same messages but with a additional
``std_msgs/Header`` so that they can be timestamped.

The service folder
------------------

Expand All @@ -119,17 +139,18 @@ The convention is to add all services to a folder called :file:`srv`. Let's foll
The service file
----------------

With the :file:`AmazingQuote.msg`, we have seen how to use built-in types. Let's use the service to learn two more possibilities. Let us use a message from the same package and a message from another package. Services cannot be used to define other services.
.. note::

Services cannot be used to define other services.

Add the file :file:`WhatIsThePoint.srv` in the :file:`srv` folder with the following contents
Add the file :file:`AddPoints.srv` in the :file:`srv` folder with the following contents

:download:`WhatIsThePoint.srv <../../ros2_tutorial_workspace/src/package_with_interfaces/srv/WhatIsThePoint.srv>`
:download:`~/ros2_tutorial_workspace/src/package_with_interfaces/srv/AddPoints.srv <../../ros2_tutorial_workspace/src/package_with_interfaces/srv/AddPoints.srv>`

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/srv/WhatIsThePoint.srv
.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/srv/AddPoints.srv
:language: yaml
:linenos:

Note that if the message is defined in the same package, the package name does not appear in the service or message definition. If the message is defined elsewhere, we have to specify it.

The :file:`CMakeLists.txt` directives
-------------------------------------
Expand All @@ -141,12 +162,12 @@ The :file:`CMakeLists.txt` directives
If a package is dedicated to interfaces, there is no need to worry too much about the :program:`CMake` details. We can follow the boilerplate as shown below.
Edit the :file:`package_with_interfaces/CMakeLists.txt` like so

:download:`CMakeLists.txt <../../ros2_tutorial_workspace/src/package_with_interfaces/CMakeLists.txt>`
:download:`~/ros2_tutorial_workspace/src/package_with_interfaces/CMakeLists.txt <../../ros2_tutorial_workspace/src/package_with_interfaces/CMakeLists.txt>`

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/CMakeLists.txt
:language: cmake
:linenos:
:emphasize-lines: 14-36
:emphasize-lines: 14-37

What to do when adding new interfaces?
--------------------------------------
Expand All @@ -167,8 +188,8 @@ If additional interfaces are required

.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/CMakeLists.txt
:language: cmake
:lines: 17-24
:emphasize-lines: 4, 7
:lines: 17-25
:emphasize-lines: 5, 8

.. note::

Expand Down Expand Up @@ -196,8 +217,9 @@ returns

.. code:: console

package_with_interfaces/srv/WhatIsThePoint
package_with_interfaces/msg/AmazingQuote
package_with_interfaces/msg/AmazingQuote
package_with_interfaces/msg/AmazingQuoteStamped
package_with_interfaces/srv/AddPoints

and we can further get more specific info on :file:`AmazingQuote.msg`

Expand All @@ -210,26 +232,29 @@ which returns
.. literalinclude:: ../../ros2_tutorial_workspace/src/package_with_interfaces/msg/AmazingQuote.msg
:language: yaml

alternatively, we can do the same for :file:`WhatIsThePoint.srv`
alternatively, we can do the same for :file:`AddPoints.srv`

.. code:: console

ros2 interface show package_with_interfaces/srv/WhatIsThePoint
ros2 interface show package_with_interfaces/srv/AddPoints

which returns expanded information on each field of the service


.. code:: yaml

# WhatIsThePoint.srv from https://ros2-tutorial.readthedocs.io
# Receives an AmazingQuote and returns what is the point
AmazingQuote quote
int32 id
string quote
string philosopher_name
---
geometry_msgs/Point point
float64 x
float64 y
float64 z
# AddPoints.srv from https://ros2-tutorial.readthedocs.io
# Adds the values of points `a` and `b` to give the output `result`
geometry_msgs/Point a
float64 x
float64 y
float64 z
geometry_msgs/Point b
float64 x
float64 y
float64 z
---
geometry_msgs/Point result
float64 x
float64 y
float64 z

74 changes: 33 additions & 41 deletions docs/source/create_packages.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Create packages (:program:`ros2 pkg create`)
---------------
--------------------------------------------

ROS2 has a tool to help create package templates. We can get all available options by running

Expand All @@ -10,43 +10,35 @@ ROS2 has a tool to help create package templates. We can get all available optio
which outputs a list of handy options to populate the package template with useful files. Namely, the four emphasized ones.

.. code-block:: console
:emphasize-lines: 27, 29, 35, 37

usage: ros2 pkg create [-h] [--package-format {2,3}] [--description DESCRIPTION]
[--license LICENSE]
[--destination-directory DESTINATION_DIRECTORY]
[--build-type {cmake,ament_cmake,ament_python}]
[--dependencies DEPENDENCIES [DEPENDENCIES ...]]
[--maintainer-email MAINTAINER_EMAIL]
[--maintainer-name MAINTAINER_NAME] [--node-name NODE_NAME]
[--library-name LIBRARY_NAME]
package_name

Create a new ROS 2 package

positional arguments:
package_name The package name

options:
-h, --help show this help message and exit
--package-format {2,3}, --package_format {2,3}
The package.xml format.
--description DESCRIPTION
The description given in the package.xml
--license LICENSE The license attached to this package; this can be an arbitrary
string, but a LICENSE file will only be generated if it is one
of the supported licenses (pass '?' to get a list)
--destination-directory DESTINATION_DIRECTORY
Directory where to create the package directory
--build-type {cmake,ament_cmake,ament_python}
The build type to process the package with
--dependencies DEPENDENCIES [DEPENDENCIES ...]
list of dependencies
--maintainer-email MAINTAINER_EMAIL
email address of the maintainer of this package
--maintainer-name MAINTAINER_NAME
name of the maintainer of this package
--node-name NODE_NAME
name of the empty executable
--library-name LIBRARY_NAME
name of the empty library
:emphasize-lines: 19,21,27, 29

usage: ros2 pkg create [-h] [--package-format {2,3}] [--description DESCRIPTION] [--license LICENSE] [--destination-directory DESTINATION_DIRECTORY] [--build-type {cmake,ament_cmake,ament_python}]
[--dependencies DEPENDENCIES [DEPENDENCIES ...]] [--maintainer-email MAINTAINER_EMAIL] [--maintainer-name MAINTAINER_NAME] [--node-name NODE_NAME] [--library-name LIBRARY_NAME]
package_name

Create a new ROS 2 package

positional arguments:
package_name The package name

options:
-h, --help show this help message and exit
--package-format {2,3}, --package_format {2,3}
The package.xml format.
--description DESCRIPTION
The description given in the package.xml
--license LICENSE The license attached to this package; this can be an arbitrary string, but a LICENSE file will only be generated if it is one of the supported licenses (pass '?' to get a list)
--destination-directory DESTINATION_DIRECTORY
Directory where to create the package directory
--build-type {cmake,ament_cmake,ament_python}
The build type to process the package with
--dependencies DEPENDENCIES [DEPENDENCIES ...]
list of dependencies
--maintainer-email MAINTAINER_EMAIL
email address of the maintainer of this package
--maintainer-name MAINTAINER_NAME
name of the maintainer of this package
--node-name NODE_NAME
name of the empty executable
--library-name LIBRARY_NAME
name of the empty library
Loading