Onboard/Offboard Distributed Computing¶
AirStack uses stacks (docs/development/stacks.md)
to control which autonomy modules launch inside each container. Each compose
service carries a default stack — no environment variables need to be set by
hand. (Stacks are the only dispatch mechanism; a set AUTONOMY_ROLE
environment variable is a preflight error.)
| Stack | What runs |
|---|---|
full_default |
Every autonomy module: interface, sensors, perception, local planning, global planning, behavior, logging — the default when no stack is selected |
lite_default |
Lite modules only: interface, sensors, perception, local planning, behavior — no global planner |
lite_offload_global:onboard |
The lite set on the vehicle, bridged to an offboard global half per the stack's bridge.yaml |
lite_offload_global:offboard |
Global planner + world model only — runs on the GCS paired with onboard robots |
full_droan_cpu |
full_default with the CPU DROAN local planner (droan_local_planner + disparity_expansion) instead of the GPU droan_gl node |
full_macvo |
full_default with MAC-VO as the disparity source — requires airstack module add asm_macvo first |
full_mighty |
full_default with the MIGHTY map-based local planner (asm_mighty module: planner + acl-mapping voxel world model + NavigateTask bridge) in place of droan_gl |
Instead of picking a stack per container, airstack up --fleet <name> launches
a whole fleet: config/fleets/<name>.yaml declares who exists, which
vehicle each robot flies, which stack it runs, and which ground hosts run each
split stack's offboard half — see Fleets.
Compose profiles¶
Profiles are split into deployment and simulator categories.
Deployment profiles:
| Profile | Machine | Services started | Default stack(s) |
|---|---|---|---|
desktop |
Dev desktop | robot-desktop + gcs |
full_default |
desktop_split |
Dev desktop | robot-desktop-onboard + robot-offboard + gcs |
lite_default + lite_offload_global:offboard |
l4t |
Jetson | robot-l4t + zed-l4t |
full_default |
l4t_lite |
Jetson | robot-l4t-onboard |
lite_default |
voxl (alias voxl_onboard) |
VOXL2 | robot-voxl-onboard |
lite_default (compute-constrained) |
offboard |
Ground station | robot-offboard ×N + gcs-real |
lite_offload_global:offboard |
The hardware-profile defaults are redefinable per deployment (env /
--env-file / --stack).
Simulator profiles (mutually exclusive, desktop/desktop_split only):
| Profile | Simulator |
|---|---|
isaac-sim |
NVIDIA Isaac Sim (Pegasus) |
ms-airsim |
Microsoft AirSim (legacy) (UE4) |
simple |
Simple Sim |
Only one simulator profile can be active at a time. airstack up will error if multiple are set.
Profile: desktop (default)¶
Standard simulation and development. All autonomy runs in one container per simulated robot. Combine with a simulator profile.
Dev desktop
├── simulator (isaac-sim / ms-airsim / simple)
├── robot-desktop × N [stack: full_default]
└── gcs
# Isaac Sim:
airstack up --sim isaac
# Microsoft AirSim (legacy):
airstack up --sim airsim
# Multiple simulated robots:
airstack up --sim isaac --robots 3
Each replica gets a unique ROBOT_NAME (robot_1, robot_2, robot_3) and ROS_DOMAIN_ID (1, 2, 3)
automatically from the robot_name_map.
Profile: desktop_split¶
Simulates the onboard/offboard split on a single developer machine.
robot-desktop-onboard acts as the simulated onboard computer (lite modules only).
robot-offboard acts as the GCS containers (global planning only).
Use this to debug the split configuration and domain bridge without needing physical hardware.
Dev desktop
├── simulator (isaac-sim / ms-airsim / simple)
├── robot-desktop-onboard × N [stack: lite_default, ROS_DOMAIN_ID = 1..N]
├── robot-offboard × N [stack: lite_offload_global:offboard, ROS_DOMAIN_ID = 0]
└── gcs [domain 0]
COMPOSE_PROFILES="desktop_split,isaac-sim" airstack up
# Or:
airstack --profile desktop_split --profile isaac-sim up
Domain isolation
Onboard containers run on ROS_DOMAIN_ID 1, 2, 3… (one per robot).
All offboard containers and the GCS share ROS_DOMAIN_ID=0.
The DDS router bridges only the topics listed in the split stack's
bridge.yaml across the domain boundary to avoid flooding the radio
link — generate its config first:
python3 tools/gen_dds_router.py stacks/lite_offload_global/bridge.yaml
(or airstack fleet generate <fleet>).
Profile: l4t (Jetson, fully autonomous)¶
All autonomy runs on the Jetson. Use when the Jetson has sufficient compute to run global planning onboard, or when no GCS is available.
Profile: l4t_lite + offboard (Jetson with GCS offboard)¶
Lite modules run on the Jetson; global planning runs on the ground station.
# On the Jetson:
airstack --profile l4t_lite up
# On the ground station (--robots must match the fleet size):
airstack --profile offboard up --robots 3
Profile: voxl + offboard¶
VOXL2 always runs in onboard-only (lite) mode — it does not have sufficient compute for global planning. Global planning must always run on the GCS.
# On the VOXL2:
airstack --profile voxl up
# On the ground station:
airstack --profile offboard up --robots 3
Launching manually (without AUTOLAUNCH)¶
If AUTOLAUNCH=false, containers start idle. Launch manually inside the container:
# Full stack (desktop or l4t) — also the default with no stack args:
ros2 launch autonomy_bringup robot.launch.xml sim:=false \
stack_dir:=/root/AirStack/stacks/full_default
# Lite stack (VOXL, l4t_lite, desktop_split onboard):
ros2 launch autonomy_bringup robot.launch.xml sim:=false \
stack_dir:=/root/AirStack/stacks/lite_default
# Offboard half of the split stack (GCS):
ros2 launch autonomy_bringup robot.launch.xml sim:=false \
stack_dir:=/root/AirStack/stacks/lite_offload_global stack_entry:=offboard
desktop_bringup wraps the above and adds RViz (only when sim:=true);
the stack selection flows through the AIRSTACK_STACK_DIR /
AIRSTACK_STACK_ENTRY env vars: