Setting up the right environment is crucial for effective development. In this blog post, I will guide you through setting up a ROS 2 development environment using Docker and Emacs on MacOS. This guide assumes that Emacs is already installed on your system.
Install Docker
You need to install Homebrew first. After that, you can install Docker with:
brew install --cask docker
Start the docker app to bring up the docker daemon.
Now you can check if the installation was successful by running the following command:
docker run hello-world
Add your ROS 2 workspace
Add a workspace in order to build and open them in a container, e.g.:
cd ~/
mkdir -p ws_[project]/src
Now create a .devcontainer
folder in the root of your workspace and add a devcontainer.json
and Dockerfile
to this .devcontainer
folder.
Additionally, you need to create a cache
folder in which you can cache the build
, install
and log
folders for different ROS 2 distros.
The workspace structure should look like this:
ws_[project]
├── cache
| ├── [ROS2_DISTRO]
| | ├── build
| | ├── install
| | └── log
| └── ...
|
├── src
├── .devcontainer
│ ├── devcontainer.json
│ └── Dockerfile
├── package1
└── package2
Edit devcontainer.json
For the Dev Container to function properly, we have to build it with the correct user.
Therefore add the following to .devcontainer/devcontainer.json
:
{
"name": "ROS 2 Development Container",
"privileged": true,
"remoteUser": "YOUR_USERNAME",
"build": {
"dockerfile": "Dockerfile",
"args": {
"USERNAME": "YOUR_USERNAME"
}
},
"workspaceFolder": "/home/ws",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/ws/src,type=bind",
"customizations": {
"vscode": {
"extensions":[
"ms-vscode.cpptools",
"ms-vscode.cpptools-themes",
"twxs.cmake",
"donjayamanne.python-extension-pack",
"eamodio.gitlens",
"ms-iot.vscode-ros"
]
}
},
"containerEnv": {
"DISPLAY": "unix:0",
"ROS_AUTOMATIC_DISCOVERY_RANGE": "LOCALHOST",
"ROS_DOMAIN_ID": "42"
},
"runArgs": [
"--net=host",
"-e", "DISPLAY=host.docker.internal:0"
],
"mounts": [
"source=/tmp/.X11-unix,target=/tmp/.X11-unix,type=bind,consistency=cached",
"source=${localWorkspaceFolder}/../cache/ROS_DISTRO/build,target=/home/ws/build,type=bind",
"source=${localWorkspaceFolder}/../cache/ROS_DISTRO/install,target=/home/ws/install,type=bind",
"source=${localWorkspaceFolder}/../cache/ROS_DISTRO/log,target=/home/ws/log,type=bind"
],
"postCreateCommand": "sudo rosdep update && sudo rosdep install --from-paths src --ignore-src -y && sudo chown -R YOUR_USERNAME /home/ws/"
}
Open the file in your editor, search for YOUR_USERNAME
and replace it with your username.
If you do not know your username, you can find it by running echo $USER
in the terminal.
Also replace ROS_DISTRO
, with the ROS 2 distribution that you want to use and added to the cache previously, for example, humble
or rolling
.
Edit Dockerfile
Open the Dockerfile
and add the following contents:
FROM ros:ROS_DISTRO
ARG USERNAME=YOUR_USERNAME
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Create the user
RUN groupadd --gid $USER_GID $USERNAME
RUN useradd --uid $USER_UID --gid $USER_GID -m $USERNAME
#
# [Optional] Add sudo support. Omit if you don't need to install software after connecting.
RUN apt-get -y update
RUN apt-get install -y sudo
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
RUN chmod 0440 /etc/sudoers.d/$USERNAME
RUN apt-get update && apt-get upgrade -y
# Install a few important dev dependencies
RUN apt-get install -y \
ament-cmake \
ccls \
python3-colcon-common-extensions \
python3-pip \
vim \
clang \
clang-format \
clang-tidy
RUN echo "source /opt/ros/ROS_DISTRO/setup.bash" >> /home/$USERNAME/.bashrc
ENV SHELL /bin/bash
# ********************************************************
# * Anything else you want to do like clean up goes here *
# ********************************************************
# [Optional] Set the default user. Omit if you want to keep the default as root.
USER $USERNAME
CMD ["/bin/bash"]
Search here also for the YOUR_USERNAME
and replace it with your username and the
ROS_DISTRO
with the ROS 2 distribution you wish to use and added to the cache
previously.
Open and Build Devcontainer
To build and start the devcontainer, we need GitHub - devcontainers/cli. Install it with:
brew install devcontainer
Afterwards, execute the following commands to build and start the devcontainer:
devcontainer up --workspace-folder ~/ws_[project]/src
Build the ROS 2 workspace
To build the ROS 2 workspace, run
devcontainer exec --workspace-folder ~/ws_[project]/src colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
Edit files with emacs
Open the file you want to edit with helm-find-files
, type /docker:
and press TAB
to auto-complete the docker container name.
Then you can find the file you want to edit in the container with path like:
/docker:container_name:/home/ws/src/package1/src/file.cpp
Once the file is opened, you can edit it as usual. ccls
or clangd
will automatically index the file if
- it is configured in your emacs configuration,
- the
compile_commands.json
is present in the build folder of the ROS 2 workspace, - and the executable
ccls
orclangd
is installed in the container.
Test ROS 2 CLI
Here we will follow the turtlesim, ros2, and rqt — ROS 2 Tutorial.
Install turtlesim
First, we need to install the turtlesim package. Open a new terminal and run:
devcontainer exec --workspace-folder ~/ws_[project]/src bash
which gives you a bash shell in the container. Then in the bash shell, run:
sudo apt install ros-ROS_DISTRO-turtlesim
Now check if the installation was successful by running:
ros2 pkg executables turtlesim
Start turtlesim
To start turtlesim, you can either run:
ros2 run turtlesim turtlesim_node
in the bash shell of the container, ordevcontainer exec --workspace-folder ~/ws_[project]/src ros2 run turtlesim turtlesim_node
in a new terminal.
Now you may encounter an error saying
Error: Can't open display: host.docker.internal:0
To solve it you need to follow the steps here:
- Install XQuartz with
brew install --cask xquartz
. - Open XQuartz and go to
Preferences
->Security
and checkAllow connections from network clients
. - Reboot the computer.
- Run
xhost +localhost
in a terminal to allow connections to the MacOS host.
Now you would be able to start turtlesim and see a “TurtleSim” window pop up.
Use TurtleSim
To control the turtle, you can either run:
ros2 run turtlesim turtle_teleop_key
in the bash shell of the container, ordevcontainer exec --workspace-folder ~/ws_[project]/src ros2 run turtlesim turtle_teleop_key
in a new terminal.
Now you can use the arrow keys to control the turtle in the “TurtleSim” window. And you should be able to continue the tutorial to learn more about ROS 2 CLI.