Skip to main content

ROS2 Development Base

ros2_metapackage_template is a ready-made base for ROS2 projects (CORE) — a workspace, a Docker environment with the MRS UAV System inside, and a tmux launch layer — which you copy with Use this template on GitHub and then fill with your own packages.

It is not a library and you never depend on it. It is a starting point: after the first commit the repository is yours, and every line in it is meant to be edited.

The idea​

  • One environment. We already run Docker on the real drones for other reasons, so why not make the same image base for development and simulation too? It carries the MRS UAV System, ROS2 and the usual development tools, so what runs on one machine runs the same way on every other. That traceability pays off when debugging, both inside the team and with a client.
  • The same project runs in simulation and on the drone. One script, one set of configs; the difference is a single flag.
  • Less duplication, less work to extend. The sessions are ERB templates, so one tmuxinator session covers both the simulator and the real robot. The templating has been there all along, we simply started using it — no wrapper shell scripts and no second copy of every session to keep in sync. Adding a node, an airframe or a new combination of flags is a single entry in a yaml or one small file, and it takes effect in simulation and in flight at once.
  • Docker stays out of your way. You never attach to a container by hand. A few scripts in the repository root build it, start it and tear it down, and the workspace is bind-mounted, so you keep editing on your own machine with your own editor. Most of the time you do not notice there is a container at all.
  • It is meant to stay only as a base. Projects differ a lot and have their own needs, so nothing here is meant to constrain them. But the more of us start from the same structure and keep it roughly intact, the easier it gets to move between each other's projects.

What's inside​

The repository carries the configuration, the environment and the launch layer, and nothing else. The ROS code lives in its own repositories and is cloned in, and whatever a build produces stays on your machine.

PathPurpose
.reposThe manifest of git repositories that make up the project, imported by vcstool. Nothing forces this choice — git submodules do the same job if you prefer them.
ros2_ws/The colcon workspace. Only colcon_defaults.yaml and an empty src/ are tracked; build/, install/, log/ and the imported packages are local.
docker/The image definition and its compose files, plus env.sh, which detects your user, GPU and display.
start.sh, build.sh, kill.shThe three commands you will actually type day to day.
tmux/The launch layer: sessions, per-airframe configs, presets and ERB templates.
logs/Bind-mounted runtime logs from real flights.

A few details worth knowing:

  • The image is built on ctumrs/mrs_uav_system and recreates your host user inside the container, so files created in the workspace belong to you, not to root.
  • ros2_ws/ and tmux/ are bind-mounted into the container. You edit them on the host with your own editor and the container sees the change immediately.
  • colcon_defaults.yaml turns on --symlink-install and a release-with-debug-info build with compile_commands.json, which is what your editor's C++ tooling wants.
  • GPU access is automatic: an AMD card needs nothing, an NVIDIA card is picked up when the Docker nvidia runtime is registered on the host.

Getting it running​

On the host you need Docker with your user in the docker group, an SSH key registered in your GitHub account, and vcstool. ROS itself lives in the image, so you do not install it.

  1. Create your repository from the metapackage template on GitHub, then clone it.
  2. Import the packages listed in the manifest: vcs import < .repos from the repository root. Do this before the first build, because the image collects every package.xml and resolves the dependencies while it is being built. Later, vcs pull -n updates all of them at once.
  3. Build the image and the workspace with ./build.sh.
  4. Start it: ./start.sh --sim=gz (./start.sh sim) for simulation, plain ./start.sh on a real drone.

You know it worked when the tmux session opens and the status window fills with the MRS status overlay. In simulation you can take off straight away from the arm_and_offboard window, where the arming and offboard calls are waiting in the shell history.

./start.sh dev drops you into an interactive shell instead of the sessions, and ./kill.sh tears everything down.

Prefer a local ROS install?

It works too — rosdep install --from-paths src --ignore-src -r -y and colcon build --symlink-install from the workspace root. The template's own README.md has the step-by-step version of both paths.

How launching works​

Everything you start is described by two tmuxinator sessions: one for the simulator and one per UAV. ./start.sh renders them and attaches you to the result.

./start.sh [--uavs=uav1,uav2,...] [--sim=gz|mrs] [--gui] [preset] [tmuxinator args]
  • Asking for a simulator is what decides the mode. With --sim you get the simulator session plus one session per UAV, without it you get the UAV sessions alone, which is what you want on a real drone.
  • sessions/simulator.yaml and sessions/robot.yaml are the two templates; a ROS node you want launched is one entry in their windows: list.
  • config/common/world.yaml carries the shared world origin and safety area, while config/<platform>/custom.yaml carries the per-airframe MRS UAV System settings, chosen by $UAV_TYPE on a real robot and by sim in simulation.
  • A preset is a text file of flags under presets/ that you invoke by name, so ./start.sh two_drones_gz_gui replaces a line of arguments you would otherwise retype.
  • Inside the session, Ctrl+a then Shift+S switches between UAVs and Ctrl+a then k closes it.
warning

Always start from the repository root. tmux/start.sh is the inside-the-container half of the machinery and is not meant to be run by hand.

For how the sessions themselves are put together, see Tmux Session Preparation in the robot setup section.

Making it yours​

Right after you create the repository, replace the example content:

  • README.md — the project name, description, logo and docs link, and delete the template notice at the top.
  • .repos — swap the example mrs_robot_diagnostics entry for your project's own repositories.
  • tmux/sessions/, config/, presets/ — your nodes, your airframes, your shortcuts.
  • docker/Dockerfile — the MRS system version and ROS distribution build args, plus any extra apt or pip dependencies.

Everything else — the compose, the GPU detection, the vcs or colcon wiring — is meant to stay untouched. If you find yourself rewriting it, that is a good sign the fix belongs back in the template.

Tips​

Release a package as a .deb

The template carries no release tooling of its own. Use the MRS CI scripts, which wrap bloom-generate in the same environment the build farm uses, see Local Docker Package Build.

Troubleshooting​

Warning: you are already inside a tmux session

./start.sh refuses to nest sessions. Run it from a plain terminal. If you only lost the view of a running session, reattach with tmux -L f4f attach.

The NVIDIA GPU is not used

Starting the project prints a warning when nvidia-smi works but Docker has no nvidia runtime registered. Install the NVIDIA Container Toolkit and run nvidia-ctk runtime configure --runtime=docker.