Tutorial

Create a Plan

A plan is one YAML file in plans/ that describes everything a launch should bring up: which commands run, in which packages’ containers, arranged in tmux windows and panes. airfield project up <plan> turns it into a running session; airfield project down <plan> tears it down.

Plans need tmux and tmuxinator on the host; airfield doctor checks for both.

1. Write the plan

Create plans/navstack.yaml:

name: navstack
pre_window: export MAP=speedway

windows:
  - name: main
    layout: main-vertical
    panes:
      - package: camera_driver
        cmd: ros2 run image_processor image_node

      - package: base_driver
        cmd: ros2 run motor_driver motor_node

      - package: base_driver
        cmd: ros2 run joystick joystick_node

      - package: nav_stack
        cmd: ros2 launch nav_stack navigation.launch.py

2. Choose pane forms

Panes come in three forms:

panes:
  # 1. A package pane: cmd runs inside that package's container
  - package: base_driver
    cmd: ros2 run motor_driver motor_node

  # 2. A plain host command
  - htop

  # 3. A bare shell pane (null), handy for debugging alongside the nodes
  -

A package pane is rendered as airfield package cmd <package> -- bash -lc "<cmd>", so the command executes inside the container with ROS and the workspace already sourced. Shell syntax like &&, pipes, and loops runs inside the container too. Because the command is raw shell, it addresses the wrapped ROS packages directly (ros2 run <ros_package> <executable>), not the Airfield package name.

The same package may appear in any number of panes: each pane gets its own container from the package’s single image.

3. Launch it

airfield project up navstack

This renders the plan to .airfield/navstack.tmuxinator.yml and starts the tmux session. Useful variants:

airfield project up                        # list available plans
airfield project up navstack --inspect     # print the generated config only
airfield project up navstack --no-launch   # write the config without starting
airfield project up navstack --output custom.yml

The first pane that needs an unbuilt package triggers the in-container colcon build (see the Overview for how first-run builds and the shared workspace interact); later panes reuse the result.

4. Tear it down

airfield project down navstack

Killing the session signals each pane’s Airfield process, which stops its own container, so a plain down leaves no orphans (the Runtime & Environment page explains the teardown mechanics). Running airfield project down with no name tears down every running session that matches a plan. After a hard crash (power loss, SIGKILL) where containers had no chance to stop:

airfield project down --prune

This force-removes all airfield-run-* containers on the host.

5. Sequential launches with liftoff

A plan may also carry a simple package list:

name: smoke-test
packages:
  - base_driver
  - nav_stack

airfield project liftoff smoke-test runs each package’s default run command one after another, blocking until each exits. That suits smoke tests and scripted checks rather than interactive development. (project up also accepts this form and gives each package its own window.) For anything interactive, prefer windows: panes with project up.