Tutorial
Create a New Package
Use an Airfield package for one buildable and runnable robotics component. Packages can live inside an Airfield project or stand alone.
1. Create a package inside a project
From an Airfield project root:
airfield package init nav_stack
This creates:
packages/nav_stack/
airfield.yaml
src/
README.md
.dockerignore
.gitignore
The package inherits the project’s ROS distribution unless you pass
--ros-distro.
2. Create a standalone package
For a package outside a project:
mkdir nav_stack
cd nav_stack
airfield package init .
Standalone packages resolve dependency manifests from their own
dependencies/<target-device>/ and dependencies/xplatform/ folders first,
then fall back to the shared packages repository.
When a local manifest should be shared with other packages, check and upstream
it with airfield package dependencies check . and
airfield package dependencies upstream .; see
Manage Dependencies.
3. Edit package metadata
Open airfield.yaml:
kind: package
name: nav_stack
dependencies:
- tqdm
source_path: src
ros_distro: jazzy
run:
list-packages: ros2 pkg list
Core fields:
namecontrols the package identifier and the Docker image name (airfield-pkg-<name>).dependenciesnames dependency manifests such astqdm.yaml. Entries may carry version constraints (tqdm>=1.0). An entry with no manifest can also name a peer package underpackages/; its source is then mounted and built from source alongside this one, which is how shared message packages are usually handled.source_pathis the source folder mounted into the runtime container. Usesrc(the default) when the folder holds one or more ROS packages, or.when the package root itself is the ROS package.ros_distroselects the ROS base image.rundefines named commands forairfield package run. Two names have extra meaning:defaultis whatairfield project runandliftoffexecute, andtestis whatproject run --testexecutes.
Optional fields:
base_imageoverrides the container base image (e.g.osrf/ros:jazzy-desktop); otherwise the project default or the ROS distro default applies.devicespasses host devices into the container (e.g./dev/ttyACM0); missing devices are skipped with a warning rather than failing the run.group_addadds supplementary groups (e.g."20"for dialout) so nodes can open serial ports and similar hardware.colcon_argsappends extra arguments to the automaticcolcon buildrun on first start (e.g.--cmake-args -DCMAKE_BUILD_TYPE=Release).default_workdirchanges the working directory forrun/shell/cmd. Relative paths resolve against the mounted source; absolute paths are used as-is.
4. Wrap one ROS package, or several
On the first container start, Airfield runs
colcon build --packages-up-to <name>, so the Airfield package’s name must
match a colcon package in its source tree. If no colcon package matches the
name, the automatic build silently does nothing, and the run command fails
later with missing executables. When the names cannot match (a config-only
tool package, for instance), that is fine: there is simply nothing to build.
- One ROS package (the common case): wrap it with
source_path: .and the names match automatically. - Several ROS packages in one container: put them side by side under
src/and add a small ROS metapackage named after the Airfield package that depends on the others. Building the metapackage then builds the whole bundle. The Overview shows this layout in detail.
5. Build the package
airfield package build nav_stack --target-device x86_64
Inside a standalone package root, use . for the current package:
airfield package build . --target-device x86_64
6. Run package workflows
List configured run commands:
airfield package run nav_stack
Run a configured command:
airfield package run nav_stack list-packages
Open an interactive package container:
airfield package shell nav_stack
Run an ad hoc command in the package container:
airfield package cmd nav_stack -- ros2 pkg list
Inside the package’s folder, the package name can be omitted; Airfield detects it from the working directory.
7. Wrap an existing ROS package
For a ROS package that already has package.xml:
airfield package init --path /path/to/existing_ros_package --ros-distro jazzy
Airfield reads the ROS package name and dependencies from package.xml,
writes airfield.yaml with source_path: ., and leaves the ROS source files
untouched. Dependencies fall into three buckets:
- deps the ROS base image already provides are omitted,
- deps with an existing manifest (or a peer package in the project) are kept,
- for the rest, Airfield generates local manifests under
dependencies/xplatform/that installros-<distro>-<name>via apt. These are marked for review, since not every ROS name has a released apt package, and can be shared later withairfield package dependencies upstream ..