diff --git a/.circleci/config.yml b/.circleci/config.yml index 084b735e8..c3b33c341 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,34 +3,34 @@ version: 2.1 references: on_checkout: &on_checkout checkout: - path: nav2_docs + path: . setup_doc_dependencies: &setup_doc_dependencies run: name: Install Doc Dependencies command: | export DEBIAN_FRONTEND=noninteractive apt update - apt install make -y - apt install doxygen -y - apt install graphviz -y - apt install ttf-dejavu -y - apt install openjdk-8-jre -y - apt install bash git openssh-server -y - apt install python3-pip python3 -y - pip3 install sphinx==3.5.0 docutils==0.14 sphinx_rtd_theme breathe==4.28.0 sphinxcontrib-plantuml jinja2==3.0.3 + apt install -y \ + doxygen \ + git \ + graphviz \ + make \ + openjdk-8-jre \ + openssh-server \ + python3-pip \ + ttf-dejavu + pip3 install -r requirements.txt make_docs: &make_docs run: command: | - cd nav2_docs make html store_docs: &store_docs store_artifacts: - path: nav2_docs/_build/html + path: _build/html destination: html publish_docs: &publish_docs run: command: | - cd nav2_docs make publish install_deployment_key: &install_deployment_key add_ssh_keys: @@ -56,27 +56,27 @@ executors: docs_exec: docker: - image: ubuntu:focal - working_directory: / + working_directory: /nav2_docs jobs: docs_build: executor: docs_exec steps: - - install_doc_dependencies - *on_checkout + - install_doc_dependencies - build_docs - persist_to_workspace: - root: nav2_docs + root: . paths: - _build docs_publish: executor: docs_exec steps: - - install_doc_dependencies - *on_checkout + - install_doc_dependencies - *install_deployment_key - attach_workspace: - at: nav2_docs + at: . - publish_docs_to_gh_pages_branch workflows: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..4ef032abb --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +{ + "name": "Nav2 Docs", + "build": { + "dockerfile": "../Dockerfile", + "context": ".." + }, + "workspaceMount": "source=${localWorkspaceFolder},target=/docs,type=bind", + "workspaceFolder": "/docs", + "onCreateCommand": ".devcontainer/on-create-command.sh", + "updateContentCommand": ".devcontainer/update-content-command.sh", + "customizations": { + "vscode": { + "settings": {}, + "extensions": [ + "eamodio.gitlens", + "esbenp.prettier-vscode", + "GitHub.copilot", + "streetsidesoftware.code-spell-checker" + ] + } + } +} diff --git a/.devcontainer/on-create-command.sh b/.devcontainer/on-create-command.sh new file mode 100755 index 000000000..f86d22bc8 --- /dev/null +++ b/.devcontainer/on-create-command.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Immediately catch all errors +set -eo pipefail + +# Uncomment for debugging +# set -x +# env + +git config --global --add safe.directory "*" + +.devcontainer/update-content-command.sh diff --git a/.devcontainer/update-content-command.sh b/.devcontainer/update-content-command.sh new file mode 100755 index 000000000..b7f6536ee --- /dev/null +++ b/.devcontainer/update-content-command.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Immediately catch all errors +set -eo pipefail + +# Uncomment for debugging +# set -x +# env + +# make clean +# make html diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..111b0017b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +################################################################################ +# Repo + +.circleci/ +.devcontainer/ +.dockerignore +.git/ +.github/ +.gitignore +.vscode/ +**.Dockerfile +**Dockerfile +_build/ diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..d654a782f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,35 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "icon": { + "id": "gear" + }, + "type": "shell", + "command": "make html", + "isBackground": false, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Autobuild", + "icon": { + "id": "debug-start" + }, + "type": "shell", + "command": "make autobuild", + "isBackground": true, + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": false + } + } + ] +} diff --git a/2021summerOfCode/Summer_2021_Student_Program.rst b/2021summerOfCode/Summer_2021_Student_Program.rst index 492fc4255..7e90bad69 100644 --- a/2021summerOfCode/Summer_2021_Student_Program.rst +++ b/2021summerOfCode/Summer_2021_Student_Program.rst @@ -1,3 +1,5 @@ +:orphan: + .. _summer_2021_student_program: diff --git a/2021summerOfCode/projects/create_configuration_assistant.rst b/2021summerOfCode/projects/create_configuration_assistant.rst index cb7597006..02340a782 100644 --- a/2021summerOfCode/projects/create_configuration_assistant.rst +++ b/2021summerOfCode/projects/create_configuration_assistant.rst @@ -1,3 +1,5 @@ +:orphan: + .. _create_moveit_analog: 1. Create a Configuration Assistant (Analog to MoveIt) diff --git a/2021summerOfCode/projects/create_plugins.rst b/2021summerOfCode/projects/create_plugins.rst index d5afb9fea..ae40be3a6 100644 --- a/2021summerOfCode/projects/create_plugins.rst +++ b/2021summerOfCode/projects/create_plugins.rst @@ -1,3 +1,5 @@ +:orphan: + .. _create_plugins: diff --git a/2021summerOfCode/projects/grid_maps.rst b/2021summerOfCode/projects/grid_maps.rst index cf7baa293..1cd1f3011 100644 --- a/2021summerOfCode/projects/grid_maps.rst +++ b/2021summerOfCode/projects/grid_maps.rst @@ -1,3 +1,5 @@ +:orphan: + .. _grid_maps: diff --git a/2021summerOfCode/projects/localization.rst b/2021summerOfCode/projects/localization.rst index 058a55b9e..db29af9d7 100644 --- a/2021summerOfCode/projects/localization.rst +++ b/2021summerOfCode/projects/localization.rst @@ -1,3 +1,5 @@ +:orphan: + .. _localization: diff --git a/2021summerOfCode/projects/navigation_rebranding.rst b/2021summerOfCode/projects/navigation_rebranding.rst index 5660898ab..adf0a59de 100644 --- a/2021summerOfCode/projects/navigation_rebranding.rst +++ b/2021summerOfCode/projects/navigation_rebranding.rst @@ -1,3 +1,5 @@ +:orphan: + .. _rebranding: diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..789258bf3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM ubuntu:focal + +ARG DEBIAN_FRONTEND=noninteractive +RUN apt update && \ + apt install -y \ + doxygen \ + git \ + graphviz \ + make \ + openjdk-8-jre \ + openssh-server \ + python3-pip \ + ttf-dejavu + +COPY requirements.txt ./ +RUN pip3 install -r requirements.txt diff --git a/Makefile b/Makefile index c2de14db2..7a87b96a3 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ else endif # You can set these variables from the command line. -SPHINXOPTS ?= -q +SPHINXOPTS ?= SPHINXBUILD = sphinx-build SPHINXPROJ = "Nav2 Documentation" SOURCEDIR = . @@ -35,6 +35,11 @@ help: html: $(Q)$(SPHINXBUILD) -t $(DOC_TAG) -b html -d $(BUILDDIR)/doctrees $(SOURCEDIR) $(BUILDDIR)/html $(SPHINXOPTS) $(O) +# Autobuild the docs on changes + +autobuild: + sphinx-autobuild -t $(DOC_TAG) -b html -d $(BUILDDIR)/doctrees $(SOURCEDIR) $(BUILDDIR)/html $(SPHINXOPTS) + # Remove generated content (Sphinx and doxygen) clean: diff --git a/README.md b/README.md index 72dda5ae5..0a8ee244c 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,13 @@ https://navigation.ros.org/ This folder holds the source and configuration files used to generate the [Navigation2 documentation](https://navigation.ros.org) web site. -Dependencies for Build: -* `sudo apt install python3-pip` -* `pip3 install sphinx==3.5.0 breathe==4.28.0 sphinx_rtd_theme sphinxcontrib-plantuml jinja2==3.0.3` +Dependencies for Build: + +``` bash +sudo apt install python3-pip +pip3 install -r requirements.txt +``` Build the docs locally with `make html` and you'll find the built docs entry point in `_build/html/index.html`. -Any images, diagrams, or videos are subject to their own copyrights, trademarks, and licenses. +Any images, diagrams, or videos are subject to their own copyrights, trademarks, and licenses. diff --git a/build_instructions/index.rst b/build_instructions/index.rst deleted file mode 100644 index 46e9f657a..000000000 --- a/build_instructions/index.rst +++ /dev/null @@ -1,153 +0,0 @@ -.. _build-instructions: - -Build and Install -################# - -Install -******* - -Nav2 and its dependencies are released as binaries. -You may install it via the following to get the latest stable released version: - - ``sudo apt install ros--navigation2 ros--nav2-bringup ros--turtlebot3*`` - -(For Ubuntu 20.04 use this command as the parsing of wildcards have been changed: - - ``sudo apt install ros--navigation2 ros--nav2-bringup '~ros--turtlebot3-.*'`` - - -Build -***** - -There are 3 ways to build Nav2. -Building for a specific released distribution (e.g. ``foxy``, ``galactic``), build Nav2 on main branch using a quickstart setup script, or building main branch manually. - -.. rst-class:: content-collapse - -For Released Distributions -========================== - -Install ROS ------------ - -Please install ROS 2 via the usual `install instructions `_ for your desired distribution. -Note: ``-devel`` was the branch naming schema pre-``galactic``. -For Galactic and newer, it is simply ````. - -Build Nav2 ----------- - -We're going to create a new workspace, ``nav2_ws``, clone our Nav2 branch into it, and build. -``rosdep`` will be used to get the dependency binaries for Nav2 in your specific distribution. - -.. code:: bash - - mkdir -p ~/nav2_ws/src - cd ~/nav2_ws/src - git clone https://github.com/ros-planning/navigation2.git --branch -devel - cd ~/nav2_ws - rosdep install -y -r -q --from-paths src --ignore-src --rosdistro - colcon build --symlink-install - -Note: You need to change ``--rosdistro`` to the selected ROS 2 distribution name (e.g ``foxy``, ``galactic``). - - - -.. rst-class:: content-collapse - - -For Main Branch Development -=========================== - -Build ROS 2 Main ----------------- -Build or install ROS 2 ``rolling`` using the `build instructions `_ provided in the ROS 2 documentation. -All development is done using the ``rolling`` distribution on Nav2's ``main`` branch and cherry-picked over to released distributions during syncs (if ABI compatible). - -Build Nav2 Main ---------------- - -Now that ROS 2 ``rolling`` is installed, we have to install our dependencies and build Nav2 itself. -We'll create a new workspace, ``nav2_ws`` and clone the Nav2 project into it. -Afterwards, we'll use ``rosdep`` to automatically find and install our dependencies that were not included in the core ROS 2 install itself (``behaviortree.CPP``, ``ompl``, etc). -If you would like to use a custom version of any of these dependencies, simply overlay them in your ``nav2_ws`` and it will use those rather than the binary installed versions. - -.. code:: bash - - mkdir -p ~/nav2_ws/src - cd ~/nav2_ws/src - git clone https://github.com/ros-planning/navigation2.git --branch main - cd ~/nav2_ws - rosdep install -y -r -q --from-paths src --ignore-src --rosdistro rolling - colcon build --symlink-install - source install/setup.bash - -You are now ready for the demonstrations! - -Docker -****** - -The official Dockerhub entries are primarily for use in the Nav2 CI, but they may also be used for development. It is useful to have a docker image that tracks Nav2 ``main`` branch. The ``Dockerfile`` in the root of the repository is recommended for production use, set to your distribution of choice. - -It is though generally recomended to install Nav2 releases from the apt repository inside a container if you'd like to use our released binaries. - -.. rst-class:: content-collapse - -Building Docker Container -========================= - -To build an image from the Dockerfile in the Nav2 folder: -First, clone the repo to your local system (or see Building the source above) - - -.. code:: bash - - sudo docker build -t nav2/latest . - -If proxies are needed: - -.. code:: bash - - sudo docker build -t nav2/latest --build-arg http_proxy=http://proxy.my.com:### --build-arg https_proxy=http://proxy.my.com:### . - -Note: You may also need to configure your docker for DNS to work. See article here for details: https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/ - -If you would like to build from dockerhub cache to speed up the build - -.. code:: bash - - sudo docker pull rosplanning/navigation2:main - sudo docker build -t nav2/latest --cache-from rosplanning/navigation2:main . - -.. rst-class:: content-collapse - -Using DockerHub Container -========================= -We allow for you to pull the latest docker image from the main branch at any time. As new releases and tags are made, docker containers on docker hub will be versioned as well to chose from. -This docker image will not contain a built overlay, and you must build the overlay Nav2 workspace yourself (see Build Nav2 Main up above). - -.. code:: bash - - sudo docker pull rosplanning/navigation2:main - -!!!! - -Generate Doxygen -**************** - -Run ``doxygen`` in the root of the Nav2 repository. -It will generate a ``/doc/*`` directory containing the documentation. -The documentation entrypoint in a browser is index.html. - -!!!! - -Help -**** - -:ref:`build-troubleshooting-guide` - - -.. toctree:: - :hidden: - - build_docs/build_troubleshooting_guide.rst diff --git a/conf.py b/conf.py index 856ef8218..14bd0061b 100644 --- a/conf.py +++ b/conf.py @@ -30,7 +30,16 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['breathe', 'sphinx.ext.graphviz', 'sphinxcontrib.plantuml', 'sphinx.ext.extlinks'] +extensions = [ + 'breathe', + 'myst_parser', + 'sphinx_copybutton', + 'sphinx.ext.extlinks', + 'sphinx.ext.graphviz', + 'sphinxcontrib.plantuml', +] + +myst_enable_extensions = ['colon_fence'] graphviz_output_format='png' graphviz_dot_args=[ @@ -48,7 +57,7 @@ # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ['.rst', '.md'] # The master toctree document. master_doc = 'index' @@ -75,12 +84,12 @@ # # 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 +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build','_themes','scripts' ] +exclude_patterns = ['_build','_themes','scripts', 'README.md' ] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' diff --git a/build_instructions/build_docs/build_troubleshooting_guide.rst b/development_guides/build_docs/build_troubleshooting_guide.rst similarity index 100% rename from build_instructions/build_docs/build_troubleshooting_guide.rst rename to development_guides/build_docs/build_troubleshooting_guide.rst diff --git a/development_guides/build_docs/index.rst b/development_guides/build_docs/index.rst new file mode 100644 index 000000000..017756f2c --- /dev/null +++ b/development_guides/build_docs/index.rst @@ -0,0 +1,158 @@ +.. _build-instructions: + +Build and Install +################# + +Install +******* + +Nav2 and its dependencies are released as binaries. +You may install it via the following to get the latest stable released version: + +.. code:: bash + + source /opt/ros//setup.bash + sudo apt install \ + ros-$ROS_DISTRO-navigation2 \ + ros-$ROS_DISTRO-nav2-bringup \ + ros-$ROS_DISTRO-turtlebot3* + +Build +***** + +There are a few ways to build Nav2 using: + +* Released Distribution Binaries + + * Build Nav2 using readily installable binary dependencies + +* Rolling Development Source + + * Build Nav2 using custom or latest source dependencies + +* Docker Container Images + + * Build Nav2 using cached images and templated Dockerfiles + +.. tip:: + For a *repeatable*, *reproducible* and *streamlined* development experience, check the Nav2 documentation on using :ref:`devcontainers`! + +.. rst-class:: content-collapse + +Released Distribution Binaries +============================== + +To build Nav2, you'll first need to build or install ROS 2 and related development tools, including: ``colcon``, ``rosdep`` and ``vcstool``. + +.. seealso:: + For more information on building or installing ROS 2 distros, see the official documentation: + + * `ROS 2 Installation `_ + * `Install development tools and ROS tools `_ + +Once your environment is setup, clone the repo, install all dependencies, and build the workspace: + +.. attention:: + The branch naming schema for Nav2 is organized by ROS distro, while the default branch for Rolling is ``main``. + +.. code:: bash + + source /opt/ros//setup.bash + mkdir -p ~/nav2_ws/src && cd ~/nav2_ws + git clone https://github.com/ros-planning/navigation2.git --branch $ROS_DISTRO ./src/navigation2 + rosdep install -y \ + --from-paths ./src \ + --ignore-src + colcon build \ + --symlink-install + +You can then ``source ~/nav2_ws/install/setup.bash`` to get ready for demonstrations! + +.. hint:: + For more examples on building Nav2 from released distribution binaries, checkout `distro.Dockerfile `_. + +.. rst-class:: content-collapse + +Rolling Development Source +========================== + +Building Nav2 using rolling development source is similar to building Nav2 from released distribution binaries, where instead you build dependencies from source using the main development branches for all ROS based packages. + +.. seealso:: + For more information on building ROS 2 from source, see the official documentation: + + * `ROS 2 Building from source `_ + +Once your environment is setup, clone the repo, import all dependencies, and build the workspace: + +.. attention:: + Be sure to check that all dependencies you need are included and uncommented in the ``.repos`` file. + +.. code:: bash + + source /install/setup.bash + mkdir -p ~/nav2_ws/src && cd ~/nav2_ws + git clone https://github.com/ros-planning/navigation2.git --branch $ROS_DISTRO ./src/navigation2 + vcs import ./src < ./src/navigation2/tools/underlay.repos + rosdep install -y \ + --from-paths ./src \ + --ignore-src + colcon build \ + --symlink-install + +You can then ``source ~/nav2_ws/install/setup.bash`` to get ready for demonstrations! + +.. hint:: + For more examples on building Nav2 from rolling development source, checkout `source.Dockerfile `_. + +.. rst-class:: content-collapse + +Docker Container Images +======================= + +Building Nav2 using Docker container images provides a repeatable and reproducible environment to automate and self document the entire setup process. Instead of manually invoking the development tools as documented above, you can leverage the project's Dockerfiles to build and install Nav2 for various distributions. + +.. seealso:: + For more information on installing Docker or leaning about Dockerfiles, see the official documentation: + + * `Docker Engine `_ + * `Dockerfile reference `_ + +Once your system is setup, you can build the Nav2 Dockerfile from the root of the repo: + +.. code:: bash + + export ROS_DISTRO=rolling + git clone https://github.com/ros-planning/navigation2.git --branch main + docker build --tag navigation2:$ROS_DISTRO \ + --build-arg FROM_IMAGE=ros:$ROS_DISTRO \ + --build-arg OVERLAY_MIXINS="release ccache lld" \ + --cache-from ghcr.io/ros-planning/navigation2:main \ + ./navigation2 + +The `docker build `_ command above creates a tagged image using the `Dockerfile` from the context specified using the path to the repo, where build-time variables are set using additional arguments, e.g. passing a set of `colcon mixins `_ to configure the workspace build. Check the ``ARG`` directives in the `Dockerfile` to discover all build-time variables available. The command also specifies an `external cache source `_ to pull the latest cached image from Nav2's `Container Registry `_ to speed up the build process. + +.. tip:: + The images cached from above are used for Nav2 CI, but can also be used with Nav2 :ref:`devcontainers`! + +!!!! + +Generate Doxygen +**************** + +Run ``doxygen`` in the root of the Nav2 repository. +It will generate a ``/doc/*`` directory containing the documentation. +The documentation entrypoint in a browser is index.html. + +!!!! + +Help +**** + +:ref:`build-troubleshooting-guide` + + +.. toctree:: + :hidden: + + build_troubleshooting_guide.rst diff --git a/development_guides/devcontainer_docs/devcontainer_guide.md b/development_guides/devcontainer_docs/devcontainer_guide.md new file mode 100644 index 000000000..dd2403185 --- /dev/null +++ b/development_guides/devcontainer_docs/devcontainer_guide.md @@ -0,0 +1,192 @@ +(devcontainer-guide)= +# Dev Container Guide + +In this guide, we'll walk through the process of creating and using dev containers for the project. While included subsections will provide greater detail on the various aspects of the process, complete comprehension of the entire guide is not required to get started, but is recommended for those interested in how dev containers work, or how to customize and optimize them for their own personal workflows. + +## Creating Dev Containers + +Before creating a dev container, you'll want to choose the exact configuration to use. By default the `.devcontainer/devcontainer.json` configuration is selected, however you can also choose any other `devcontainer.json` file in the `.devcontainer/` directory, where such configurations can be nested to provide greater customization: either by targeting different stages within different Dockerfiles, overriding any merged metadata or default properties, or inclusion of additional extensions and alternate commands. + +:::{seealso} +The specification, reference, and schema for the `devcontainer.json` config file format can be found here: +- [Specification](https://containers.dev/implementors/spec) + - Development Container Specification +- [Reference](https://containers.dev/implementors/json_reference) + - Metadata and properties reference +- [Schema](https://containers.dev/implementors/json_schema) + - JSON schema for `devcontainer.json` +::: + +### Building the image + +When first creating Dev Containers, any supporting tool or service used will download and build the docker images needed to run the container. This includes pulling any parent images the project's Dockerfile builds `FROM`, as well as any tags or layers declared via `cacheFrom`, as specified in the chosen `devcontainer.json` config file. This can take a while, but only needs to be done once, or at least not again until such layers are updated and pushed to the image registry. + +Specifically, for this project, the default `devcontainer.json` file targets the `dever` stage within the project's root Dockerfile, the stage that also includes handy tools for developing the project, such as bash auto completion. This stage is in turn built `FROM` the `builder` stage, the stage that only includes the dependencies needed for building the project, as reused by the project's CI. For example, the `dever` stage modifies `/etc/bash.bashrc` to automatically source `install/setup.bash` from the underlay workspace, ensuring all VS Code extensions are loaded with the correct environment, while avoiding any race conditions during installation and startup. + +To speed up the initial build, images layers from this `builder` stage are cached by pulling the same image tag used by the project's CI, hosted from the image registry. This ensures your local dev container replicates our CI environment as close as possible, while benefiting from any cached work preemptively performed by the CI. Yet, this still allows you to customize the project's Dockerfile and rebuild the container, without needing to update CI images to reflect your local modifications. + +:::{seealso} +More details on the project's CI and related docker image registry can be found here: + +- [Chronicles of Caching and Containerising CI for Nav2](https://vimeo.com/649647161/5b0c278e6c) + - Video presentation from ROS World 2021 - Ruffin White +::: + +Once the base image from the target stage is built, the supporting tool or service may then add additional layers to the image, such as installing additional [features](https://containers.dev/features) or customizations. For VS Code, this also includes some fancy file caching for any extensions to install later. Once this custom image is built, it is then used to start the dev container. + +### Starting the container + +When first creating Dev Containers, any supporting tool or service will invoke a sequence of commands specified in the chosen `devcontainer.json` config file. This can take a while, but only needs to be done once, or at least not again until the container is rebuilt, triggered by either updating the Dockerfile, base image, or `.devcontainer/` config. + +Specifically, for this project, the default `devcontainer.json` config executes the `onCreateCommand` to initially colcon cache, clean, and build the overlay workspace for the project. This ensures the workspace is precompiled and ready to use, while also ensuring any changes to the project's source code are reflected in the container. This is useful for: + +- IntelliSense + - Enables VS Code extensions to parse auto generated code + - Applicable for ROS package defining messages and services files + - Necessary for code modeling, navigation, and syntax highlighting +- Caching + - Enables Codespace Prebuilds to cache the workspace artifacts + - Applicable for reducing startup time when spawning new Codespaces + - Necessary for limiting costs from CPU and storage usage + +While the colcon workspace is being built, VS Code will simultaneously install any specified extensions and settings. Next the `updateContentCommand` is executed, which reruns whenever the container is started or restarted. Specifically, for this project, this command re-cleans and re-builds the same colcon workspace as before, but only for invalidated packages detected by colcon cache using the lockfiles initialized during the `onCreateCommand`. This caching behavior also replicates the project's CI workflow. This is useful for: + +- Branching + - Enables caching of workspace artifacts when switching between branches + - Applicable for reviewing pull requests without rebuilding entire container + - Necessary for reducing startup time when spawning new Codespaces + +:::{hint} +More documentation about these additional colcon verb extensions can be found here: + +- [colcon-cache](https://github.com/ruffsl/colcon-cache) + - A colcon extension to cache the processing of packages +- [colcon-clean](https://github.com/colcon/colcon-clean) + - A colcon extension to clean package workspaces +::: + +Finally, the `postCreateCommand` is executed, which also reruns whenever the container is started or restarted. Specifically, for this project, this command makes a last few tweaks to the user's environment to improve the development experience. + +To speed up subsequent startups, volumes that are mounted to the container store a persistent ccache and colcon workspace, while the environment is set to enable [ccache](https://ccache.dev/) via [colcon mixins](https://github.com/colcon/colcon-mixin-repository). These volumes are labeled using the [`devcontainerId`](https://containers.dev/implementors/json_reference/#variables-in-devcontainerjson) variable, which uniquely identify the dev container on a Docker host, allowing us to refer to a common identifier that is unique to the dev container, while remaining stable across rebuilds. This is useful for: + +- Caching + - Enables colcon workspaces and ccache to persist between container rebuilds + - Applicable for avoiding re-compilation when modifying dev container config files + - Necessary for quickly customizing image or features without rebuilding from scratch + +:::{tip} +While these volumes are uniquely named, you could rename them locally to further organize or segment works-in-progress. E.g. appending branch names to the volume name to quickly switch between pull requests and cached colcon workspaces. +::: + +Additionally, the container can be granted [privileged](https://docs.docker.com/engine/reference/commandline/run/#privileged) and non-default [Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities), connected using the [host](https://docs.docker.com/network/host/) network mode and [IPC](https://docs.docker.com/engine/reference/run/#ipc-settings---ipc) and [PID](https://docs.docker.com/engine/reference/run/#pid-settings---pid) spaces, with a relaxed [security configuration](https://docs.docker.com/engine/reference/run/#security-configuration) and seccomp confinement for native debugging and external connectivity. This is useful for: + +- Hybrid development + - Enables connecting ROS nodes external to the container + - Applicable for debugging or visualizing distributed systems + - Necessary for DDS discovery and shared memory transport +- Device connectivity + - Enables hardware forwarding from host machine to container + - Applicable for ROS package using sensors and actuators + - Necessary for some GPU drivers and USB devices + +:::{attention} +Such `runArgs` in the `devcontainer.json` config can be enabled or customized, either expanded or or narrowed in scope, to better suit your desired development environment. The default configuration merely comments out these parameters, to limit unintended side effects or cross talk between containers, but can be uncommented to accommodate the widest range of development use cases. +::: + +:::{seealso} +More details on using DDS, debuggers, or devices with Docker containers can be found here: + +- [How to Communicate Across Docker Containers Using the Host Driver](https://community.rti.com/kb/how-use-rti-connext-dds-communicate-across-docker-containers-using-host-driver) + - Using the `host` network driver to access all network interfaces of the host machine from the Docker container +- [Communicate between two Docker containers using DDS and shared memory](https://community.rti.com/kb/communicate-between-two-docker-containers-using-rti-connext-dds-and-shared-memory) + - Enabling containers to communicate with one another and with the host machine using interprocess communication (IPC) +- [Debugging programs running inside Docker containers, in production](https://nvartolomei.com/debugging-programs-running-inside-docker-containers--in-production/) + - Using tools like strace, perf, gdb when debugging programs running inside containers +::: + +## Using Dev Containers + +Once the dev container has been created and setup completed, VS Code will open a new workspace directly from the project's root directory, which itself is mounted within the source directory in the overlay colcon workspace. From here you can build, test, and debug the project as you normally would, with the added benefit of having the project's dependencies, intellisense, linters, and other extensions pre-configured and ready to use. Simply open a new terminal (Crtl+Shift+`), cd to the root of the colcon workspace, and run the usual colcon commands. + +:::{tip} +You can incorporate the same scripts used by the `devcontainer.json` config file to further automate your local development workflow. +::: + +### Terminals + +If you prefer using an alternate terminal emulator, rather than the built-in VS Code terminal, you can open a separate shell session by simply using the Dev Container CLI or directly using the Docker CLI via the `exec` subcommands. + +- [Dev Container CLI](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli) + - `devcontainer exec --workspace-folder $NAV2_WS/src/navigation2 bash` +- [docker exec +](https://docs.docker.com/engine/reference/commandline/exec/) + - `docker exec -it bash` + +:::{attention} +Shell sessions spawned directly via `docker exec` do not set the same environment that `devcontainer exec` does using `userEnvProbe`. Additional environment variables include `REMOTE_CONTAINERS_IPC`, `REMOTE_CONTAINERS_SOCKETS` and are used by vscode, ssh and X11. +::: + +:::{hint} +:class: dropdown +The environment provided by `userEnvProbe` can be sourced manually. E.g. for the default `loginInteractiveShell` probe: + +``` bash +find /tmp -type f -path "*/devcontainers-*/env-loginInteractiveShell.json" -exec \ + jq -r 'to_entries | .[] | "\(.key)=\(.value | @sh)"' {} \; > .env +source .env +``` +::: + +### Lifecycle + +While using the dev container, try and keep in mind the lifecycle of the container itself. Specifically, containers are ephemeral, meaning they are normally destroyed and recreated whenever the dev environment is rebuilt or updated. Subsequently, a best practice is to avoid storing any persistent data within the container, and instead utilize the project's source directory, or a separate mounted volume. When altering the development environment inside the container, try to remember to codify your changes into the Dockerfile, or the `devcontainer.json` config file, so that they can be easily reproduced and shared with others. + +:::{important} +This is particularly important when the host machine is inherently ephemeral as well, as the case may be when using cloud based environments such as Codespaces, so be sure to commit and push local changes to a remote repository: + +- [The codespace lifecycle](https://docs.github.com/en/codespaces/getting-started/the-codespace-lifecycle) + - Maintain your data throughout the entire codespace lifecycle +::: + +### Rebuilding + +From time to time, you may need to rebuild the dev container, either because the base image, or `.devcontainer/` config was updated, or simply out of wanting a new fresh development environment. To do so, simply open the Command Palette (Ctrl+Shift+P) and select the `Remote-Containers: Rebuild Container` command. + +:::{caution} +Rebuilding the container will destroy any changes made to the container itself, such as installing additional packages, or modifying the environment. However, the project's source directory, and any mounted volumes, will remain unaffected. +::: + +For example, you may need to rebuild the dev container when: + +- Pulling newer images from a container registry + - specifically, image tags built `FROM` in the Dockerfile + - or tags listed under `cacheFrom` in `devcontainer.json` + - periodically done manually to ensure local environment reflects CI +- Updating the dev container configuration + - specifically when modifying dependent stages in the `Dockerfile` + - or when modifying `./devcontainer` files and commands + - where build cache reuse correlates with severity of changes made + +When necessary, you can also rebuild the container from scratch, e.i. without caching from docker, by selecting the `Remote-Containers: Rebuild Container Without Cache` command. This instead omits the `--cache-from` flag from the `docker buildx` command, while also adding the `--no-cache` and `--pull` flags to prevent caching from any existing image layers, using only the latest images from a container registry. + +:::{caution} +Rebuilding the container without cache may likely pull newer images from a container registry or install newer packages, as is common when developing for ROS 2 Rolling. You may then want to clean your overlay volume to avoid ABI incompatibilities or stale artifacts. +::: + +Rebuilding without caching may be necessary when: + +- Needing to update the base image + - specifically if dev container configurations remain unmodified + - to forcefully rerun a `RUN` directive in the Dockerfile + - such as unchanged `apt upgrade` or `rosdep update` commands + +Specifically, for this project, volumes remain unaffected by this rebuilding process: i.e. those used to mount the ccache directory or colcon workspace. While volume management is left to the user's discretion, other projects may of course handle this differently, so be sure to check the `./devcontainer` configuration to inspect how various container resources may be managed. + +:::{tip} +Docker volume management can be done via the Docker CLI, or the VS Code Docker extension: + +* [Docker Volume CLI](https://docs.docker.com/engine/reference/commandline/volume) + * Manage volumes using subcommands to create, inspect, list, remove, or prune volumes +* [VS Code Docker extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) + * Makes it easy to create, manage, and debug containerized applications +::: diff --git a/development_guides/devcontainer_docs/index.md b/development_guides/devcontainer_docs/index.md new file mode 100644 index 000000000..a6d3bdd6a --- /dev/null +++ b/development_guides/devcontainer_docs/index.md @@ -0,0 +1,103 @@ +(devcontainers)= +# Dev Containers + +You can use dev containers to build the project if you prefer a streamlined setup experience. This means you can use the same tools and dependencies as the rest of the team, including our Continuous Integration (CI) workflows, without worrying about installing dependencies on your host machine. Additionally, using Dev Containers makes it simple to switch between local or remote development environments, such as GitHub Codespaces. + +:::{seealso} +More info on Dev Containers can be found here: + +- [Development Containers](https://containers.dev/) + - An open specification for enriching containers with development specific content and settings +- [Developing inside a Container](https://code.visualstudio.com/docs/remote/containers) + - Learn how to use Visual Studio Code to develop inside a Docker container +- [GitHub Codespaces overview](https://docs.github.com/en/codespaces/overview) + - A development environment hosted in the cloud +::: + +```{toctree} +:hidden: +:glob: + +* +``` + +## What, Why, How? + +Lets briefly explain what dev containers are, why you should use them, and how they work. + +:::{hint} +Here we'll assume the use of VS Code, but still applies to alternative tools and services, including other CLIs, IDEs, etc. such as: + +- [Dev Container CLI](https://github.com/devcontainers/cli) + - A reference implementation for the open specification +- [JetBrains Space | Develop in Dev Environment](https://www.jetbrains.com/help/space/develop-in-a-dev-environment.html) + - Using Dev Containers with JetBrain based products +- [Supporting tools](https://containers.dev/supporting) + - List of tools and services supporting the development container specification +::: + +### What is a Dev Container? + +A dev container is a Docker container that has all the tools and dependencies you need to develop the project. It runs in a self-contained environment and is isolated from other containers and your host machine. This lets you reliably develop for the project anywhere, notably for linux distributions targeted by ROS, regardless of your host machine's operating system. + +### Why use a Dev Container? + +A dev container provides a common and consistent development environment. It ensures that everyone on the team is using the same tools and dependencies. It also makes it easy to switch between projects because each project can use a different container. This is especially useful if you work on multiple projects that use different versions of the same tools and dependencies, such as different versions of ROS. + +### How do Dev Containers work? + +When you open the project in VS Code, VS Code checks for the dev container configuration nested within the `.devcontainer` folder under the project's root directory. If it finds one, it can prompt you to reopen the project in a container. If you choose to do so, it launches the container, connects to it, and mounts your project folder inside the container. You can then use VS Code in the container just as you would locally. While setting up the container, VS Code can also attempt to passthrough useful aspects of your local environment, such as git user configurations, X11 sockets, and more. + +This is quite similar to earlier tools used to customize and run docker containers for development: + +- [rocker | ROS + Docker](https://github.com/osrf/rocker) + - A tool to run docker containers with overlays and convenient options for things like GUIs etc. + - Developed by [Open Robotics](https://www.openrobotics.org/) +- [ADE Development Environment](https://ade-cli.readthedocs.io/en/latest/) + - A modular Docker-based tool to ensure developers have a common, consistent development environment + - Developed by [Apex.AI](https://www.apex.ai/) + +## Prerequisites + +To use dev containers, you'll need the following: + +- [Docker Engine](https://docs.docker.com/engine/install/) installed and running on the host machine +- [Visual Studio Code](https://code.visualstudio.com/) installed on any remote machine +- [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension installed in VS Code + +:::{note} +Alternatively, you could use GitHub Codespaces directly from the project repo, or any other remote host machine: + +- [Creating a codespace for a repository](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace-for-a-repository?tool=webui) + - How to create a codespace for repository via GitHub CLI, VS Code, or Web browser +- [Develop on a remote Docker host](https://code.visualstudio.com/remote/advancedcontainers/develop-remote-host) + - How to connect VS Code to a remote Docker host using SSH tunnels or TCP sockets +::: + +## Getting started + +Getting started using dev containers is as simple as opening the project in VS Code by either: following the notification prompt to reopen the project in a container, or explicitly opening the command palette (Crtl+Shift+P) and selecting `Remote-Containers: Reopen in Container`. This will create a new container, install any extensions specified in the project's default `.devcontainer/devcontainer.json` config file, and mount the project's root directory as the workspace folder. Once the container is created, VS Code will connect to it and you can start developing. + +:::{tip} +Clicking the `Starting Dev Container (show log)` notification in VS Code allows you to observe in live time how the sausage is made, while typing `Dev Containers: Show Log` into the command palette will list all the available commands to review and revisit these log files later. +::: + +While waiting for the initial setup, feel free to stretch your legs, grab a coffee, or continue to read the following guides to learn more about creating and using dev containers, or how to visualize and leverage graphical user interfaces from a headless development environment. + +- **[](devcontainer_guide.md)** + - How to develop Nav2 using dev containers and supporting tools + +## Security + +:::{caution} +Ensure you trust the authors and contents of workspaces before launching derived dev containers. +::: + +A word of caution when using dev containers: they are powerful tools, but can be a security concern, as the capability of arbitrary code execution facilitated by IDE extensions to enable such automation and convenience remains inherently dual use. Before launching a dev container, ensure you trust the workspaces and authors. For example, when reviewing a pull request, verify patches remain benign and do not introduce any malicious code. Although such vigilance is merited whenever compiling and running patched code, using containers with either elevated privileges or filesystem access renders this diligence even more prudent. + +:::{seealso} +More info on trusting workspaces and extensions in general can be found here: + +- [Workspace Trust](https://code.visualstudio.com/docs/editor/workspace-trust) + - VS Code user guid on trusting and configure workspaces +::: diff --git a/development_guides/index.rst b/development_guides/index.rst new file mode 100644 index 000000000..862a7e8ee --- /dev/null +++ b/development_guides/index.rst @@ -0,0 +1,12 @@ +.. _development-guides: + +Development Guides +################## + +This section includes guides for developing Nav2, e.g. how to build from source, how to use dev containers, and how to get involved. + +.. toctree:: + :maxdepth: 2 + :glob: + + */index diff --git a/contribute/index.rst b/development_guides/involvement_docs/index.rst similarity index 100% rename from contribute/index.rst rename to development_guides/involvement_docs/index.rst diff --git a/index.rst b/index.rst index 2e4d8b21d..18c3469b0 100644 --- a/index.rst +++ b/index.rst @@ -136,7 +136,7 @@ Below is an example of the TB3 navigating in a small lounge. :hidden: getting_started/index.rst - build_instructions/index.rst + development_guides/index.rst concepts/index.rst setup_guides/index.rst tutorials/index.rst @@ -148,6 +148,5 @@ Below is an example of the TB3 navigating in a small lounge. migration/index.rst commander_api/index.rst roadmap/roadmap.rst - contribute/index.rst about/index.rst about/robots.rst diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..a09f86ad9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +breathe==4.28.0 +docutils==0.14 +jinja2==3.0.3 +myst-parser==1.0.0 +sphinx_copybutton==0.5.2 +sphinx_rtd_theme +sphinx-autobuild +sphinx==3.5.0 +sphinxcontrib-plantuml diff --git a/scripts/docker/Dockerfile b/scripts/docker/Dockerfile deleted file mode 100644 index 9b6747f68..000000000 --- a/scripts/docker/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM alpine:latest - -#ENV http_proxy -#ENV https_proxy - -RUN apk --no-cache add python3 -RUN python3 -m ensurepip -RUN pip3 install sphinx==1.7.5 docutils==0.14 sphinx_rtd_theme breathe==4.9.1 sphinxcontrib-plantuml -RUN apk --no-cache add make -RUN apk --no-cache add doxygen -RUN apk --no-cache add graphviz -RUN apk --no-cache add ttf-dejavu -RUN apk --no-cache add openjdk8-jre diff --git a/scripts/requirements.txt b/scripts/requirements.txt deleted file mode 100644 index 939919ae8..000000000 --- a/scripts/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -breathe==4.9.1 -sphinx==1.7.5 -docutils==0.14 -sphinx_rtd_theme -sphinxcontrib-plantuml