diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 061cbde..a0e965c 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -1,28 +1,21 @@
-// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
-// https://github.com/microsoft/vscode-dev-containers/tree/v0.238.0/containers/docker-existing-docker-compose
+// Dev Container configuration.
+// For format details, see https://aka.ms/devcontainer.json.
+// For config options, see the README at:
+// https://github.com/microsoft/vscode-dev-containers/tree/main/containers/docker-existing-docker-compose
{
+ // (OPTION) Change the name to help identify which workspace you are in.
"name": "ROS2 Dev",
- // Update the 'dockerComposeFile' list if you have more compose files or use different names.
- // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make.
"dockerComposeFile": ["../docker-compose.yml", "../docker-compose.dev.yml"],
- // The 'service' property is the name of the service for the container that VS Code should
- // use. Update this value and .devcontainer/docker-compose.yml to the real service name.
"service": "dev",
- // The optional 'workspaceFolder' property is the path VS Code should open by default when
- // connected. This is typically a file mount in .devcontainer/docker-compose.yml
"workspaceFolder": "/code",
- // Use 'forwardPorts' to make a list of ports inside the container available locally.
- // "forwardPorts": [],
- // Uncomment the next line if you want start specific services in your Docker Compose config.
- // "runServices": [],
- // Uncomment the next line if you want to keep your containers running after VS Code shuts down.
- // "shutdownAction": "none",
+ // See: https://containers.dev/implementors/json_reference/#lifecycle-scripts
+ // Please follow the same method of creating shell scripts in the `hooks` folder.
"postCreateCommand": ". /tmp/.devcontainer/hooks/postCreate.sh",
"postStartCommand": ". /tmp/.devcontainer/hooks/postStart.sh",
- // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "user",
"customizations": {
"vscode": {
+ // Extensions suggested.
"extensions": [
"njpwerner.autodocstring",
"bungcip.better-toml",
diff --git a/.devcontainer/hooks/postCreate.sh b/.devcontainer/hooks/postCreate.sh
index 64c624c..0cc33fa 100644
--- a/.devcontainer/hooks/postCreate.sh
+++ b/.devcontainer/hooks/postCreate.sh
@@ -1,12 +1,12 @@
#!/bin/sh
+# `postCreate.sh` is called when the Dev Container is first created.
+# It can be used for setup steps outside the Dockerfile.
-# postCreate.sh is called after the container is created by devcontainer.json.
-# It can be used to install & setup tools not wanted in the Dockerfile.
+. /opt/ros/$ROS_DISTRO/setup.sh
-# This mitigates the Dockerfile somehow breaking the folder permissions.
+# Mitigates the Dockerfile somehow breaking folder permissions.
sudo chown user:user /code
-. /opt/ros/$ROS_DISTRO/setup.sh
-# Something removed the package indexes so we download them again for convenience.
+# Something deleted the package indexes so we re-download them for convenience.
sudo apt-get update
sudo rosdep update
diff --git a/.devcontainer/hooks/postStart.sh b/.devcontainer/hooks/postStart.sh
index cbee4a2..a54bf8b 100644
--- a/.devcontainer/hooks/postStart.sh
+++ b/.devcontainer/hooks/postStart.sh
@@ -1,24 +1,23 @@
#!/bin/sh
+# `postStart.sh` is called whenever the Dev Container starts.
+# It can be used for misc tasks (e.g., ensuring dependencies are installed).
-# postStart.sh is called every time the container starts by devcontainer.json.
-# It can be for misc tasks like ensuring all dependencies are installed.
+. /opt/ros/$ROS_DISTRO/setup.sh
-# Due to https://github.com/microsoft/vscode-remote-release/issues/6683
-# we have to explicitly trust workspace folder for git.
-# Due to https://github.com/microsoft/vscode-remote-release/issues/6810#issuecomment-1159354677
-# this cannot be done in Dockerfile (else VSCode fails to configure git in the container).
+# Due to https://github.com/microsoft/vscode-remote-release/issues/6683,
+# we have to disable git's repository trust feature.
+# Due to https://github.com/microsoft/vscode-remote-release/issues/6810#issuecomment-1159354677,
+# this cannot be done in the Dockerfile (else VS Code doesn't configure `.gitconfig`).
git config --global safe.directory "*"
-. /opt/ros/$ROS_DISTRO/setup.sh
-
-# (Optional) Clone repo on first setup if using named volume to store repo.
+# If using named volume to store repository, clone and setup the repository.
test -d "/code/.git" \
|| ( \
- git clone "(Optional) Insert repo url" /code --recurse-submodules \
+ git clone "(OPTION) Insert repository url" /code --recurse-submodules \
&& cd /code \
&& git submodule foreach --recursive git checkout main \
)
-# Ensure all dependencies are installed.
+# Ensure dependencies are installed.
sudo rosdep install -i --from-path /code -y
sudo pip install -r /code/requirements.txt
diff --git a/.dockerignore b/.dockerignore
index ff1df7e..0c04d6f 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,7 +1,6 @@
-# You can partially generate this from .gitignore.
-# A online converter: https://codesandbox.io/s/7e9ox7
+# `.gitignore` to `.dockerignore` converter: https://codesandbox.io/s/7e9ox7
-# Don't ignore .devcontainer if using volume to store repository.
+# If using named volume to store repository, don't ignore `.devcontainer`.
# Config & Others
**/.vscode
@@ -19,5 +18,5 @@ log
**/*.py[cod]
**/*.lprof
-# Mount Points
+# (OPTION) Ignore mount points.
# data
diff --git a/.gitignore b/.gitignore
index 03055bc..67148a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,12 +8,12 @@ log/*
__pycache__/
*.py[cod]
-# VSCode
+# VS Code
.vscode
!.vscode/*.json
# Profiling
*.lprof
-# Mount Points
+# (OPTION) Ignore mount points.
# data/*
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 8b57744..150f35a 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -1,3 +1,4 @@
+// VS Code configuration for ROS C/C++.
{
"configurations": [
{
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index a5e1f8b..72e3745 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,3 +1,4 @@
+// Extensions suggested.
{
"recommendations": [
"ms-vscode-remote.remote-containers",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 110c171..5210512 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,4 @@
+// VS Code configuration.
{
"python.autoComplete.extraPaths": [
"/opt/ros/humble/lib/python3.10/site-packages",
@@ -10,5 +11,19 @@
"python.languageServer": "Pylance",
"ros.distro": "humble",
"editor.formatOnSave": true,
- "python.formatting.provider": "black"
+ // Use black by default for formatting Python code.
+ "python.formatting.provider": "black",
+ "editor.codeActionsOnSave": {
+ // Automatically sort imports by default.
+ "source.organizeImports": true
+ },
+ // Format Python imports in a way compatible with black.
+ // See: https://github.com/microsoft/vscode-python/issues/6933#issuecomment-543059396
+ "python.sortImports.args": [
+ "--multi-line=3",
+ "--trailing-comma",
+ "--force-grid-wrap=0",
+ "--use-parentheses",
+ "--line-width=88"
+ ]
}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 68c2fb6..ba1bad8 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -3,7 +3,7 @@
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
- // ROS extension is glitchy; separate tasks created for convenience.
+ // ROS extension is broken; Below tasks created for developer convenience.
{
"label": "rosdep install dependencies",
"type": "shell",
diff --git a/Dockerfile b/Dockerfile
index c938099..acb961a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Dockerfile for production
-# Referring to Dockerfile.dev might be useful for understanding the below.
+# Referring to Dockerfile.dev might be useful for understanding the contents.
FROM nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu22.04
@@ -10,7 +10,7 @@ ENV LANG="C.UTF-8" LC_ALL="C.UTF-8"
RUN echo 'Etc/UTC' > /etc/timezone \
&& ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime
-# (Optional) Add VNC for debugging and control.
+# (OPTION) Add VNC server & noVNC web app for debugging and control.
# COPY ./.devcontainer/scripts/desktop-lite-debian.sh /tmp/scripts/desktop-lite-debian.sh
# ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" \
# VNC_RESOLUTION="1440x768x16" \
@@ -42,7 +42,7 @@ ENV ROS_DISTRO=$ROS_DISTRO
RUN apt-get update && apt-get install -y \
ros-${ROS_DISTRO}-ros-core \
- # (Optional) Add rqt for debugging and control.
+ # (OPTION) Add RQT for debugging and control.
# ~nros-${ROS_DISTRO}-rqt* \
python3-rosdep \
python3-colcon-common-extensions \
@@ -62,17 +62,20 @@ RUN echo "ENV=$HOME/.shrc; export ENV" >> ~/.profile
RUN echo "exec bash" >> ~/.shrc
RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash\nsource /code/install/local_setup.bash" >> ~/.bashrc
-# (Optional) Uncomment below if using rqt for icons to show up.
+# (OPTION) Uncomment below if using RQT for icons to show up.
# RUN mkdir ~/.icons && ln -s /usr/share/icons/Tango ~/.icons/hicolor
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
-# (Optional) Expose rosbridge port & noVNC port respectively.
+# (OPTION) Expose rosbridge port & noVNC port respectively.
# EXPOSE 9090 6080
ENTRYPOINT [ \
- # (Optional) VNC entrypoint
+ # (OPTION) VNC entrypoint
# "/usr/local/share/desktop-init.sh", \
# ROS entrypoint
"/entrypoint.sh" \
]
-CMD [ "bash" ]
+
+# (OPTION) Choose between calling roslaunch directly or opening a bash shell.
+# CMD [ "ros2", "launch", "main", "launch.py" ]
+# CMD [ "bash" ]
diff --git a/Dockerfile.dev b/Dockerfile.dev
index 3b512e7..5c3c829 100644
--- a/Dockerfile.dev
+++ b/Dockerfile.dev
@@ -1,9 +1,9 @@
# syntax=docker/dockerfile:1
# Dockerfile for development
-# Please create a separate Dockerfile with more precise dependencies for production.
+# Below RUN statements are broken up to take advantage of Docker layer cache.
-# If developing without a Nvidia GPU, using base Ubuntu 22.04 is possible.
+# (OPTION) Use base Ubuntu 22.04 if a Nvidia GPU is unavailable.
# FROM ubuntu:22.04
FROM nvidia/cuda:11.7.1-cudnn8-runtime-ubuntu22.04
@@ -12,7 +12,6 @@ ENV LANG="C.UTF-8" LC_ALL="C.UTF-8"
RUN echo 'Etc/UTC' > /etc/timezone \
&& ln -s /usr/share/zoneinfo/Etc/UTC /etc/localtime
-# Below RUN statements are broken up to take advantage of Docker layer cache.
RUN apt-get update \
# Needed to curl and authorize ROS repository key.
&& apt-get install -y curl gnupg lsb-release software-properties-common \
@@ -20,7 +19,7 @@ RUN apt-get update \
# Enable universe repositories.
&& add-apt-repository universe
-# Create user & add to sudoers.
+# Create user and add to sudoers.
ARG USERNAME=user
ARG USER_UID=1000
ARG USER_GID=$USER_UID
@@ -30,7 +29,7 @@ RUN groupadd -g $USER_GID $USERNAME \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 0440 /etc/sudoers.d/$USERNAME
-# Add VNC for debugging and control.
+# Add VNC server & noVNC web app for debugging and control.
COPY ./.devcontainer/scripts/desktop-lite-debian.sh /tmp/scripts/desktop-lite-debian.sh
ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" \
VNC_RESOLUTION="1440x768x16" \
@@ -40,11 +39,11 @@ ENV DBUS_SESSION_BUS_ADDRESS="autolaunch:" \
DISPLAY=":1"
RUN bash /tmp/scripts/desktop-lite-debian.sh $USERNAME password
-# Enable openCL support (OpenCV autodetects this & will use it to accelerate).
+# Enable openCL support (OpenCV uses it for hardware acceleration).
RUN mkdir -p /etc/OpenCL/vendors && \
echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
-# Curl key & authorize ROS repository.
+# Curl key and authorize ROS repository.
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" > /etc/apt/sources.list.d/ros2.list
@@ -52,8 +51,6 @@ RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/r
ARG ROS_DISTRO=humble
ENV ROS_DISTRO=$ROS_DISTRO
-# Upgrading all system packages to latest is optional.
-# RUN apt-get update && apt-get upgrade -y
RUN apt-get update
RUN apt-get install -y \
ros-${ROS_DISTRO}-ros-base \
@@ -64,26 +61,17 @@ RUN apt-get install -y \
# Set default version of Python to be the one ROS Humble uses.
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.10 10
-# Initialize rosdep.
+# Initialize rosdep package manager.
RUN rosdep init && rosdep update
-# rqt comes with useful debugging and control tools.
-# rqt's plugin support allows for custom visualizations, tools or control panels.
+# RQT comes with useful debugging and control tools.
+# RQT's plugin support allows for custom visualizations, tools or control panels.
RUN apt-get install -y ~nros-${ROS_DISTRO}-rqt*
-# One of the dependencies breaks Xsession. So we won't use the entire ROS desktop suite.
-# It is better for dependency management anyways to explicitly choose what is installed.
-# See https://github.com/ros2/variants/blob/master/desktop/package.xml
-# and browse https://index.ros.org/ to find out what is in the ROS desktop suite.
-# RUN apt-get install -y ros-${ROS_DISTRO}-desktop
-
-# Install some common dependencies.
-# RUN apt-get install -y python3-opencv ros-${ROS_DISTRO}-rosbridge-suite
-
-# Use Python Black formatter.
+# Use black by default for formatting Python code.
RUN apt-get install -y black
-# Needed for devcontainer hooks to run.
+# Needed for Dev Container lifecycle hooks to run.
COPY ./.devcontainer /tmp/.devcontainer
COPY ./entrypoint.sh /entrypoint.sh
@@ -100,8 +88,8 @@ USER $USERNAME
# Make /bin/sh launch bash instead.
RUN echo "ENV=$HOME/.shrc; export ENV" >> ~/.profile
RUN echo "exec bash" >> ~/.shrc
-# Auto-activate ROS whenever shell is opened.
+# Auto-activate ROS whenever bash shell is opened.
RUN echo "source /opt/ros/$ROS_DISTRO/setup.bash\nsource /code/install/local_setup.bash" >> ~/.bashrc
-# Ensure rqt icons show up.
+# Ensure RQT icons show up.
RUN mkdir ~/.icons && ln -s /usr/share/icons/Tango ~/.icons/hicolor
diff --git a/README.md b/README.md
index 9cc3ce4..2abc5fc 100644
--- a/README.md
+++ b/README.md
@@ -1,92 +1,115 @@
# ros2-workspace-template
-Template for ROS2 workspace using [VSCode Remote Container](https://code.visualstudio.com/docs/remote/containers) with [Docker Compose](https://docs.docker.com/compose/). Go to in order to view the development container's desktop (for GUI apps).
+Template for ROS2 workspace using [VS Code Dev Containers](https://code.visualstudio.com/docs/remote/containers) & [Docker Compose](https://docs.docker.com/compose/).
-## Customizing
+- **Before creating the Dev Container**, do a global search for `(OPTION)` and read what they say!
+- GUI apps are viewable via [noVNC](https://novnc.com/info.html) (VNC client web app) hosted on .
+ - **The password is `password`!**
-All parts of the template to pay attention to have been marked with `(Optional)`. Doing a global search for it should guide you in customizing the various builtin features.
+## Table of Contents
-### Additional Disk Performance on Windows
+- [Options](#options)
+ - [Store Repository in Named Volume](#store-repository-in-named-volume)
+ - [Mount Point `/data`](#mount-point-data)
+ - [VNC & RQT in Production Image](#vnc--rqt-in-production-image)
+ - [Native GUI Apps via X11](#native-gui-apps-via-x11)
+- [Other Features](#other-features)
+ - [`requirements.txt` Escape Hatch](#requirementstxt-escape-hatch)
+ - [VS Code Tasks](#vs-code-tasks)
+ - [Docker Image Distribution](#docker-image-distribution)
+ - [VS Code Extension Suggestions](#vs-code-extension-suggestions)
+ - [Code Formatting](#code-formatting)
+ - [Dev Container Lifecycle Hooks](#dev-container-lifecycle-hooks)
+- [Tips](#tips)
+ - [`git` Submodules](#git-submodules)
+ - [Update Package Indexes](#update-package-indexes)
+ - [Minimize Changes to the Dockerfile](#minimize-changes-to-the-dockerfile)
+ - [Change ROS Distro](#change-ros-distro)
+- [Troubleshooting](#troubleshooting)
-Following , it is possible to use a named volume to store the entire repository to improve disk performance on Windows. This resolves the longer ROS build times due to the inefficiencies of bind mounting. To use a named volume, there are instructions in [`postStart.sh`](.devcontainer/hooks/postStart.sh) and [`docker-compose.dev.yml`](docker-compose.dev.yml).
+## Options
-### Adding Volume Mounts
+`(OPTION)` marks key options to consider before creating the Dev Container. `(LINUX)` and `(X11)` indicate options that are valid only if your host OS is Linux, or you use X11 on Linux. Some of the `(OPTION)`s work together to activate the features listed below:
-See the example for mounting a folder to `/data` in `docker-compose.dev.yml` (under `volumes`), `.gitignore` and `.dockerignore`.
+### Store Repository in Named Volume
-## Testing
+On Windows or MacOS, using a named volume to store the repository fixes slow build times and avoids certain issues. The steps for this feature are:
-Run `ros2 run pyratetest pub` and `ros2 run pyratetest sub` in two separate terminals. Use `rqt` (see GUI section [below](#using-gui-apps)) to reconfigure both nodes live (located under Plugins > Configuration > Dynamic Reconfigure). Alternatively, use the launch file via `ros2 launch pyratetest test.launch.py`. Use `--show-args` to see the launch options.
+1. ([`docker-compose.dev.yml`](./docker-compose.dev.yml)) Create a named volume to store the repository.
+2. ([`docker-compose.dev.yml`](./docker-compose.dev.yml)) Mount the named volume to `/code` where the repository should be.
+3. ([`postStart.sh`](./.devcontainer/hooks/postStart.sh)) Clone the repository into the named volume.
-## Docker Image Distribution
+See for more info.
-### Building
+### Mount Point `/data`
-```sh
-docker build . -t example/example:vx.x.x -t example/example:latest
-```
+Mount points are used to mount a folder from the host into the container. By following `(OPTION)`s, `./data` on the host is mounted to `/data` in the container. `/data` can be used to share anything from the host with the container (e.g., config files, models, databases).
-Each Docker image can have multiple names associated to it. In the above, tagging the image by both the version number and as latest helps for distributing images.
+While one mount point is sufficient, more can be added by following `/data`'s example. See for more info.
-### Exporting
+### VNC & RQT in Production Image
-```sh
-docker save example/example:vx.x.x example/example:latest -o example.tar
-```
+By default, noVNC & RQT are not installed in the production image to save space. It is recommended to use ROS CLI or create a proper API instead to manage ROS systems. However, they can be enabled by following `(OPTION)`s in [`Dockerfile`](./Dockerfile). This can be convenient for early stages of deployment.
-Compressing the image afterwards using `xzip` is recommended to save space. Docker is able to load compressed images (i.e. `example.tar.xz`) without manually decompressing first.
+### Native GUI Apps via X11
-### Importing
-
-```sh
-docker load -i example.tar.xz
-```
+For Linux users, it is possible for GUI apps in the container to show natively on the host if using X11 instead of Wayland. For Windows users, it is also possible via software like [VcXsrv](https://sourceforge.net/projects/vcxsrv/).
-Imports the Docker image and its names. It will still be tagged as `example/example:vx.x.x` and `example/example:latest`, conveniently replacing the old image that was tagged as `latest`.
+## Other Features
-## Using GUI Apps
+### `requirements.txt` Escape Hatch
-For ease of usage, the VNC approach is default over the X Server approach. ~~However, the X Server approach is more performant.~~ The X Server approach is only more performant on Linux, whereas on Windows, the VNC approach performs better. However, the X Server approach has a more native feel.
+Some dependencies may be unavailable from the `rosdep` package manager (check [ROS Index](https://index.ros.org)). For Python dependencies, they should be added to a `requirements.txt` created within the ROS package. The ROS package's `requirements.txt` should then be composed into the workspace's [`requirements.txt`](./requirements.txt) (example in [`requirements.txt`](./requirements.txt)). For other dependencies, they should be added to both Dockerfiles. See with regards to adding new packages to `rosdep`.
-### Connecting to VNC
+### VS Code Tasks
-Go to to view the container's desktop via the noVNC web client, or use a VNC client of your choice.
+For developer convenience, some common tasks such as building packages and installing dependencies are present in [`tasks.json`](./.vscode/tasks.json). Use them by opening the command bar and typing `task`.
-### Using Host's X Server
+### Docker Image Distribution
-#### Linux
+See for more info.
-Within [`docker-compose.dev.yml`](docker-compose.dev.yml), there are comments such as the below:
+#### Building
-```yml
-# (Optional)(Linux only)(X Server) Use X Server address from host.
-# environment:
-# DISPLAY: ${DISPLAY}
+```sh
+docker build . -t organization/repo:vx.x.x -t organization/repo:latest
```
-Uncomment these in order for GUI apps in the container to use the host Linux's X Server.
-
-#### Windows
+Images can have multiple names tagged to them. Tagging images with the version number and as latest helps when distributing images.
-On Windows, installing an X Server such as [VcXsrv](https://sourceforge.net/projects/vcxsrv/) is required. You will also need to set the `DISPLAY` environment. For example, insert the below into [`.devcontainer/hooks/postStart.sh`](.devcontainer/hooks/postStart.sh):
+#### Exporting
```sh
-# postStart.sh
-echo "export DISPLAY=host.docker.internal:0.0" >> ~/.bashrc
+docker save organization/repo:vx.x.x organization/repo:latest -o repo-vx.x.x.tar
```
-If using a high-resolution display, `rqt` might appear small, in which case adjusting `QT_SCALE_FACTOR` might help:
+Compressing the image afterwards using `xzip` is recommended to save space. Docker is able to load compressed images (i.e., `repo-vx.x.x.tar.xz`) without decompressing manually.
+
+#### Importing
```sh
-# postStart.sh
-echo "export QT_SCALE_FACTOR=2" >> ~/.bashrc
+docker load -i repo-vx.x.x.tar.xz
```
-## Additional Tips
+Imports the image and its names. It will still be tagged as `organization/repo:vx.x.x` and `organization/repo:latest`, conveniently replacing the previous `latest`.
+
+### VS Code Extension Suggestions
+
+Both [`devcontainer.json`](./.devcontainer/devcontainer.json) and [`extensions.json`](./.vscode/extensions.json) are configured such that VS Code will automatically install some extensions. These are highly recommended for developer experience.
+
+### Code Formatting
+
+[`black`](https://github.com/psf/black) is used to format Python code due to its uncompromising design. Imports are also automatically sorted using compatible rules. See [`settings.json`](./.vscode/settings.json) for the configuration.
-### Git Submodules
+### Dev Container Lifecycle Hooks
-When cloning a repository using `git`, it will not clone submodules by default. In order to clone submodules, use:
+[`devcontainer.json`](./.devcontainer/devcontainer.json) allows adding lifecycle hooks which can be useful for special cases. See the [`hooks`](./.devcontainer/hooks/) folder for some examples.
+
+## Tips
+
+### `git` Submodules
+
+It is recommended to add custom ROS packages to the workspace via [`git` Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules). However, when cloning a repository using `git`, it will not clone submodules by default. In order to clone submodules, use:
```sh
git clone --recurse-submodules
@@ -104,9 +127,9 @@ If you want `git` to clone submodules by default, try:
git config --global submodule.recurse true
```
-Otherwise, use Github Desktop, which uses `--recurse-submodules` by default.
+Otherwise, use [Github Desktop](https://desktop.github.com/), which uses `--recurse-submodules` by default.
-Nonetheless, when submodules are cloned, they will be in a detached state by default, which hinders commits. Switching submodules to the main branch can either be done through VSCode's Source Control tab, or:
+Nonetheless, when submodules are cloned, they will be in a detached state, which prevents committing. Switching submodules to the main branch can either be done through VS Code's Source Control tab, or:
```sh
git submodule foreach --recursive git checkout main
@@ -114,32 +137,29 @@ git submodule foreach --recursive git checkout main
This is done for you automatically if using a named volume to store the repository.
-### Update `rosdistro` Ocassionally
+### Update Package Indexes
-Run `sudo rosdep update` to update the package index.
+The `rosdep` and Ubuntu package managers rely on a local cache of their package index. If the package index is outdated, it may not contain any active package distribution server, leading to package downloads failing. Hence, it is recommended to periodically re-download the package index:
+
+```sh
+sudo apt-get update
+sudo rosdep update
+```
### Minimize changes to the Dockerfile
-If there is time for the Docker Image to rebuild, it is a good idea to reorganize the Dockerfile ocassionally. However, if in a rush, add new steps to the end instead of modifying earlier steps to take advantage of the Docker layer cache.
+When a step in the Dockerfile is changed, subsequent steps are invalidated and need to be rebuilt. Furthermore, ROS workspaces with the same Dockerfile share cache, resulting in less disk usage and shorter rebuilds.
+
+The current Dockerfiles should work in most cases without needing edits. Nonetheless, if the Dockerfile becomes too complex, re-organizing it is fine.
-That said, the current Dockerfiles work in most cases without needing edits. Additionally, all ROS Workspaces based on the same Dockerfile will share cache, leading to less disk usage and lower rebuild times.
+### Change ROS Distro
+
+To change ROS Distro, do a global search for the current distro (`humble`) and replace as necessary with the new distro. Afterwards, rebuild the Dev Container.
## Troubleshooting
- `rosdep` has no version lock, see: .
- One solution would be to use your own install script instead of `rosdep`.
- Delete both the `build` and `install` folder and rebuild everything.
-- While Python code is symlinked, the `launch` files aren't, meaning rebuilding the _specific_ package is needed when `launch` files are changed.
-- In the worst case scenario, rebuild the container without cache.
-
-## Conventions
-
-### `Dockerfile` Naming
-
-`Dockerfile` may be suffixed when multiple images (with different dependencies) are built within a project. For example, `Dockerfile.ui` for the production UI image, `Dockerfile.talker` for the ROS2 talker node, and `Dockerfile.listener` for the ROS2 listener node. If there is only one image or a "main image", `Dockerfile` should be unsuffixed.
-
-For development, ideally a single `Dockerfile.dev` that is comprehensive (i.e. having all dependencies) should be used (to minimize rebuilding & wasted space for multiple images).
-
-### `docker-compose.yml` Naming
-
-`docker-compose.yml` may be suffixed for special configurations. For example, `docker-compose.dev.yml` for development, `docker-compose.ci.yml` for testing, or `docker-compose.prod.yml` for production. `docker-compose.yml` unsuffixed should be the base/common configuration.
+- While Python code is symlinked, the ROS `launch` files aren't, meaning rebuilding the _specific_ package is needed when `launch` files are changed.
+- Rebuild the container without cache.
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 955fe55..1eb4a28 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -1,44 +1,39 @@
version: '3.9'
-# (Optional) Uncomment below to use named volume to store project repo.
+# (OPTION) Create named volume to store repository.
# volumes:
# code:
services:
- # Service used for development.
dev:
- # NOTE: all paths below are relative to the primary docker-compose.yml file,
- # e.g. the first in the devcontainer.json "dockerComposeFile" array.
+ # NOTE: All paths are relative to the first file in the `dockerComposeFile`
+ # array found in `devcontainer.json`.
build:
context: .
dockerfile: Dockerfile.dev
- # (Optional)(Linux only) Configure below to match host UID & GID to fix permission issues.
+ # (OPTION)(LINUX) Configure to match host's UID & GID to fix permission issues.
# args:
# USER_UID: 1000 # default 1000
# USER_GID: 1000 # default 1000
volumes:
- # Mount project repo into container.
- - .:/code:cached
- # (Optional) Comment the above & uncomment below to use named volume to store project repo.
- # - code:/code
- # Example mount for data.
+ # (OPTION) Choose whether to use named volume to store repository.
+ # - .:/code:cached # Repository located on host is mounted into container.
+ # - code:/code # named volume used to store repository.
+ # (OPTION) Mount point for `data` folder.
# - ./data:/data:cached
- # (Optional) Uncomment the next line to use Docker from inside the container.
- # See https://aka.ms/vscode-remote/samples/docker-from-docker-compose for details.
- - /var/run/docker.sock:/var/run/docker.sock
- # (Optional)(Linux only)(X Server) Mount host's .Xauthority to allow container to self-authenticate with X Server.
+ # (OPTION)(LINUX)(X11) Mount host's `.Xauthority` to allow container to self-authenticate with X Server.
# - $HOME/.Xauthority:/home/user/.Xauthority:rw
- # (Optional)(Linux only)(X Server) Use X Server address from host.
+ # (OPTION)(LINUX)(X11) Use X Server address from host.
# environment:
# DISPLAY: ${DISPLAY}
- # Better process handling by actually have an process management system (tini).
+ # Better process handling by using a process management system (tini).
init: true
- # Larger shared memory for VNC & ROS2's DDS.
+ # Larger shared memory for VNC & ROS2.
shm_size: 1gb
# Uncomment the next four lines if you will use a ptrace-based debugger like C++, Go, and Rust.
@@ -54,22 +49,22 @@ services:
# Isolate ROS2 nodes into their own network.
network_mode: service:donor
- # Overrides default command so things don't shut down after the process ends.
+ # Override default command so things don't shut down after the process ends.
command: /bin/sh -c "while sleep 1000; do :; done"
- # Request GPU.
+ # Request for GPU access.
deploy:
resources:
reservations:
devices:
- capabilities: [gpu]
- # Extension of donor service defined in docker-compose.yml.
+ # Extension of donor service defined in `docker-compose.yml`.
donor:
- # (Optional)(Linux only)(X Server) Needed to use host's X Server for GUI apps.
+ # (OPTION)(LINUX)(X11) Needed to use host's X Server for GUI apps.
# network_mode: host
ports:
- # Expose noVNC installed by devcontainer.json features.
+ # Expose noVNC web app.
- 6080:6080
# Expose rosbridge.
- 9090:9090
diff --git a/docker-compose.yml b/docker-compose.yml
index ed50588..8c560e9 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.9'
services:
# Used to allow ROS2's underlying DDS to communicate across containers.
donor:
- image: alpine # tiniest linux image
+ image: alpine # smallest linux image
ipc: shareable
pid: shareable
stop_signal: SIGKILL
diff --git a/pyratetest/pyratetest/__init__.py b/pyratetest/pyratetest/__init__.py
index 3614ef0..098db82 100644
--- a/pyratetest/pyratetest/__init__.py
+++ b/pyratetest/pyratetest/__init__.py
@@ -1,5 +1,5 @@
"""
-Simple example PubSub to measure communication rate. Surprisingly, the rqt
+Simple example PubSub to measure communication rate. Surprisingly, the RQT
topic monitor plugin chokes if the messages are:
- big (like images)
- very rapid
diff --git a/requirements.txt b/requirements.txt
index 8d1688d..125a5e2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,4 @@
-# Insert additional requirements not covered by rosdistro here.
+# Insert Python requirements that aren't available on https://index.ros.org/.
# e.g. opencv-contrib-python-headless, numpy > 1.21, norfair
# or -r ./some-module/some-package/requirements.txt