Skip to content

AirStack 0.20.0

Latest

Choose a tag to compare

@andrewjong andrewjong released this 29 Aug 22:04
1d40fe9
  • Pre-release versioning terminology: -alpha.N-dev.N. The
    development line on develop now uses X.Y.Z-dev.N pre-release versions
    (first: 0.21.0-dev.0) instead of X.Y.Z-alpha.N. The
    check-version-increment PR gate accepts exactly dev, beta, rc
    (ordering dev < beta < rc < release); the main→develop sync workflow
    rolls develop forward to the next minor's -dev.0 after a release. Docs,
    skills, and the PR template were updated to match. Existing -alpha.N
    versions in git history and in declared module-compat ranges remain valid
    historical references.

  • Single, revamped repo README. The repo now has one README.md (at the
    root — docs/README.md was removed), rewritten around the redesigned docs
    home page: quickstart, one-command bring-up, sim-to-real parity, CI flight
    campaigns, and agent-driven workflows.

  • Module-catalog sync automation + drift alarm. Registering a module is
    two merges (registry PR to
    airstack-modules-index

    • trunk fixture/catalog sync), and the docs deploy regenerates the
      published catalog from the live registry — so a missed half used to
      drop the module from the site silently. Now the develop docs deploy
      raises a docs-catalog-drift issue whenever the committed catalog and
      the live registry disagree, and the new sync-modules-index workflow
      (daily + manual dispatch) opens the trunk sync PR automatically
      (.github/workflows/scripts/registry_sync.py).
  • Trustworthy system-test outcomes. A red system-tests run now always
    means the code under test got worse, never that CI infrastructure hiccuped:
    run_meta.json (schema v2) classifies every failure as
    assertion / infrastructure / collection / ci_integrity, and CI fails
    only on those — comparable numeric metric deltas (Hz, CPU, error metrics)
    are advisory in the report and no longer fail the PR. Metric
    comparisons only happen between fingerprint-identical campaigns (same
    tests and same behavior-changing CLI config: sim, robot count,
    trajectories, velocities, tolerances), with the baseline selected from
    recent base-branch artifacts by fingerprint instead of "newest artifact of
    any shape". Bring-up/readiness failures fail fast when the simulator
    process dies (instead of burning the full /clock timeout on an ephemeral
    GPU pod) and capture a bounded, secret-free diagnostics/ bundle before
    the pod is destroyed. Maintainers can dispatch focused flight campaigns
    (trajectory_types, takeoff_velocities) from workflow_dispatch. New
    airstack up --config-only: dry-run restricted to logical launch-config
    contracts (no Docker/credentials/image/submodule prerequisites).

  • CI un-redded: Metrics Report and Unit Tests fixed. Every PR had been
    failing since ~2026-08-20 for reasons unrelated to the code under test.
    The system-tests Metrics Report job installed only tabulate, so
    tests/parse_metrics.py (which imports the tests/harness package)
    crashed with ModuleNotFoundError: No module named 'yaml' — and the crash
    was misreported as "Metric regression detected"; the job now installs
    tests/requirements.txt, and the regression verdict additionally requires
    a written report.md so a parser crash can never masquerade as a metric
    regression. The Unit Tests workflow ran the tests/meta/ contract
    suite on a checkout with no submodules and no omni_pass.env, so every
    airstack up --dry-run --sim isaac contract hard-failed preflight and the
    docs-catalog contract missed the submodule-resident vdb_mapping_ros2
    README; the workflow now checks out submodules recursively and provisions
    the same guest omni_pass.env stub that module-system-tests.yml uses
    (preflight itself stays strict).

  • New reference stack full_mighty + registered mighty module. The
    MIGHTY Hermite-spline local planner (MIT ACL, RA-L 2026) with its
    acl-mapping voxel world model and a NavigateTask/trajectory_controller
    bridge, packaged as the external
    asm_mighty module (pinned at
    v0.1.1 in the stack's modules.repos; repo private until the AirStack
    agent study concludes). full_mighty
    is full_default with only the local-planner include swapped — the
    module-swap demonstration for the modular architecture. Registered in the
    module catalog; validated on Isaac Sim (44/44
    vendored gtests, empty-world route flight, 7/7 pillar-field traversals,
    5/5 judged obstacle-route flights at 1.59–1.65 m min clearance vs a 1.0 m
    gate).

  • Fixed: the docs search dropdown rendered behind the nav-tabs bar and the
    version-selector text (custom z-indexes inside the header's stacking
    context); the search subtree is now lifted above both.

Documentation overhaul (Diátaxis restructuring). The docs site was
audited against the Diátaxis framework and
reorganized; page URLs are preserved (moves are covered by redirects):

  • The nav is now organized by document kind — Tutorials / How-to Guides /
    Reference / Concepts
    tabs — replacing the difficulty-tier
    ("Beginner/Intermediate/Advanced Tutorials") buckets, which contained no
    tutorials. The doc-authoring standards (Documentation Guide, mkdocs
    skills) now prescribe the quadrant taxonomy and include a decision tree.
  • 18 verified doc/code mismatches fixed, including: a phantom
    --recreate flag and missing --scene in the CLI reference; phantom
    ROBOT_LAUNCH_PACKAGE/ROBOT_LAUNCH_FILE env vars (real: LAUNCH_PACKAGE);
    nonexistent airstack_msgs/TrajectorySegment/TrajectoryOverride types in
    doc templates (real: TrajectoryXYZVYaw); the MS-AirSim tmux window
    ordering (bridges launch before PX4) and MAVLink port math; the Getting
    Started Foxglove step (layout now auto-seeds; manual import retired).
  • Removed superseded pages with redirects: the Ascent-era scene-setup pair,
    the pre-harness testing-frameworks page, the orphaned tutorials index and
    two stale duplicate pages (development_environment, airstack-cli index).
    The git-hooks docker-versioning READMEs are now deprecation notices — the
    hook they described conflicts with the semver check-version-increment
    gate (note: airstack config git-hooks still installs it; CLI removal is
    a follow-up).
  • Pages that documented never-built or fabricated behavior were rewritten
    from the code: global planning (the unimplemented Global-Manager/
    PlanRequest protocol is gone), the robot interface page (state flows via
    odometry_conversion), robot configuration, HITL (now uses the
    gcs-real hitl profile and Foxglove verification), rosbags, and the
    robot-side data-offloading page (now points at the storage-tools
    workflow).
  • Hybrid pages split by audience: system_architecture.md (explanation
    core; drifted topic tables replaced with links into the interface
    conventions spec), CI/CD (new Using CI how-to), GCS Foxglove (new
    Extending the Visualizer), Isaac Sim docker (new Container
    Workflows
    ). Duplicated hot tables (topics, CLI flags, pytest marks,
    requirements) now live in one canonical home each.
  • Previously off-site references added to the nav: the vehicle.yaml and
    module.yaml schemas, local calibration contract, the RViz tasks/waypoint
    panel manuals, the LiDAR point-cloud filter README, and the OSMO lab-admin
    guide. New reference pages: the complete .env schema, the
    airstack_msgs interface reference, the trajectory-library YAML format,
    and a supported-platform matrix. New/rewritten onboarding: Deploying to
    Hardware and Operating the GCS.
  • The Interface Conventions Specification was bumped to v1.0.1: §8 now
    lists all eight task_msgs actions (added tasks/coverage and
    tasks/chat, both defined with no shipped executor).
  • Six new how-to guides: Adding a State Estimator, Adding a Planner,
    Creating a Multi-Agent Coordination Algorithm (grouped under a new
    How-to → Autonomy section), Creating a Custom Stack Topology, Adding a
    Vehicle Type/Unit/Platform, and Getting the Most out of Your Coding
    Agent (the feature-notebook workflow). Each presents the in-tree
    package vs airstack module create --in-tree module-scaffolding
    choice. The Concepts tab now sits directly after Tutorials, and the
    UE→Isaac export tutorial was refreshed (new walkthrough video, export
    as Z-up in meters, note that UE Decals — paint markings, dirt,
    puddles — do not export).
  • Five new beginner tutorials completing the learning path: Fly a Mission
    from the GCS, Change a Parameter (the edit→relaunch loop; config YAML is
    symlink-installed from the bind-mounted source, so no rebuild), Write
    Your First Module (airstack module create --in-tree scaffold, with a
    fix-it note for the scaffold's double-namespace stub), Your First Fleet
    (two-robot fleet file, per-robot Foxglove tabs), and Build and Fly Your
    Own Scene (GUI stage → scene catalog → --scene flight → baked
    *.scene.usd). New how-to: Adding a Controller (verified
    trajectory_controller → pid_controller → interface command chain);
    Adding a Planner expanded into Adding a World Model and Planner
    (local world-model/planner matched pairs vs the spec'd global map
    interchange).

This release restructures AirStack from a monolith into modules,
stacks, and fleets, implementing
RFC #379 (Modular AirStack)
scales 1–2 of
RFC #380 (Heterogeneous AirStack),
and the stack-folder anatomy of
RFC #385 (Directory Atlas).
Feature docs deliberately cite none of these — the design sources live here:

  • Modules are thin external repos with a small module.yaml, pulled on
    demand: airstack module add <url> --version <pin>. Three capabilities
    were extracted from trunk into new repos:
    asm_macvo (with its torch/TensorRT
    stack moved out of the base robot image — 17.1 GB → ~6 GB, −65%),
    asm_optitrack (including the
    Isaac Sim NatNet emulator), and
    asm_dfm2_disturbances.
    The registry lives at
    castacks/airstack-modules-index.
  • Stacks (stacks/) are self-contained topology folders — pinned
    modules.repos, plain XML entry launch files, and a CI-observed
    wiring.md graph baseline. Wiring that used to be spread across per-layer
    *_bringup packages (local_bringup, onboard_all, and the
    local*.launch.xml variant files) now lives in one place: the selected
    stack's entry launch file.
  • Module provenance: asm_dfm2_disturbances originates from the DFM2
    ("don't fool me twice") AirStack fork, hand-built as the pilot module
    before the tooling existed (its FRICTION_LOG.md records every manual
    step; the port drops omni.isaac.dynamic_control in favor of the PhysX
    simulation interface). asm_optitrack was extracted from the trunk
    OptiTrack PR series (#359/#374/#375/#376) with git history preserved; its
    unit/integration/e2e tests run in the module's own CI.
  • Fleets (config/fleets/) declare who exists, which vehicle, which
    stack, and which ground hosts run split-stack halves:
    airstack up --fleet <name>.

Launch-path changes (breaking)

  • AUTONOMY_ROLE is removed. The env-var role dispatch
    (full/onboard/offboard) is gone; a set AUTONOMY_ROLE is a preflight
    hard error (as is setting it alongside --stack, which previously let the
    stack silently win). Stacks are the only dispatch: airstack up --stack <name>[:<entry>], defaulting to full_default. The per-role launch trees
    (onboard_all/, onboard_local_offboard_global/) are deleted, the
    wrap-then-flatten migration is complete (every reference stack composes
    flat module-launch includes; the launch-lint allowlist is down to the two
    deliberately wrapped blocks: interface.launch.py and the DDS-router/
    gossip helpers). Migration map:

    Before Now
    no role set / AUTONOMY_ROLE=full full_default (default; machine-proven graph-identical)
    full + local_droan_cpu.launch.xml variant --stack full_droan_cpu (variant file deleted; wiring captured from it before deletion)
    local_macvo_obstacle_avoidance.launch.xml variant --stack full_macvo — the variant was broken three ways (unprefixed args silently ignored, stale disparity topic, launch_macvo never enabled); the stack fixes all three
    AUTONOMY_ROLE=onboard (no split) --stack lite_default (on the desktop profile the onboard role was unreachable anyway — robot-desktop hardcoded full)
    onboard/offboard split pair --stack lite_offload_global:onboard / :offboard
  • The split onboard/offboard deployment is now the lite_offload_global
    stack (:onboard / :offboard entries) bridged per its bridge.yaml;
    the DDS-router config is generated by tools/gen_dds_router.py rather
    than hand-maintained. The generated bridge deliberately drops the legacy
    split's set_trajectory_mode crossing (control-mode topics may not cross
    a bridge — airstack doctor hard gate).

  • Module launch files are remap-free and declare prefixed, described
    arguments with canonical defaults; generically named arguments (like
    config_file) were renamed with per-module prefixes because ROS 2 launch
    configurations are global across includes.

  • Shared DDS-router configs moved out of the per-role onboard_all/ tree up
    to autonomy_bringup/config/.

  • OptiTrack activation changed: trunk's
    overrides/isaac-optitrack-simulation.env and the LAUNCH_NATNET toggle
    are gone (a set LAUNCH_NATNET draws a preflight warning). Mocap is
    brought up by a stack that includes natnet_ros2 unconditionally — the
    asm_optitrack module's test_stack/ is the reference.

  • SKIP_MACVO / SKIP_TENSORRT build args removed from Dockerfile.robot
    along with the payload they gated; MAC-VO deps enter an image only via
    airstack module lock --build. stacks/full_macvo includes the module's
    own macvo.launch.xml (the in-tree perception/macvo_ros2 copy is
    deleted; the module preserves its git history, and fixes the previously
    hardcoded camera_info subscription to honor its topic parameter).

Added

  • airstack up --stack <name>[:<entry>] stack dispatch with 5 reference
    stacks under stacks/ (full_default, full_droan_cpu, full_macvo,
    lite_default, lite_offload_global), each carrying pinned
    modules.repos and a CI-observed wiring.md graph baseline
  • Module CLI — airstack module add <url> --version <tag|sha> (branches
    refused; local paths allowed), list|sync|remove|create --in-tree|doctor,
    workspace overlay of module packages, and auto-generated module compose
    overrides included by airstack up; Docker module layers composed via
    modules.lock (airstack module lock --build)
  • Fleet system: airstack up --fleet <name> driven by
    config/fleets/*.yaml (identity, vehicle from config/vehicles/, stack
    selection, spawns) with hosts: split-stack placement onto ground hosts;
    airstack fleet list|generate per-robot compose for heterogeneous fleets;
    airstack sync reconciles airstack.yaml (modules, external stack repos,
    fleet validation)
  • airstack doctor [--live|--snapshot] [--stack NAME] — observe-and-report
    checks with exactly two hard gates (module dependency-conflict gate;
    bridge gate: no control-setpoint / trajectory-group topics may cross a
    split-stack bridge); --live diffs the RUNNING ROS graph against the
    stack's committed wiring.md
  • airstack stack list|new <src> <dst>|diff <a> <b> (diff compares
    generated wiring, not launch XML)
  • tests/meta/ contract-test tier (unit mark) pinning the CLI/docs/stack
    contracts, plus the wiring system-test mark: an observed wiring snapshot
    of the running graph drift-checked against the stack's committed
    stacks/<name>/wiring.md
  • Split-stack bridging: stacks/lite_offload_global/bridge.yaml explicitly
    lists every boundary crossing and tools/gen_dds_router.py generates the
    DDS-router config from it deterministically (--check enforces the bridge
    hard gate)
  • New docs: Modules, Stacks, Fleets, Module CI guides, the generated
    Module & Stack Catalog marketplace, and the Modular AirStack Walkthrough
  • Intent flags on airstack up--sim isaac|airsim|simple, --robots N,
    --headless, --play/--no-play, --no-autolaunch, --wait,
    --dry-run — deriving the coordinated env-var sets as exported leaf
    values, with a resolved-config banner and a per-run
    .airstack/runs/<ts>/effective_config.env dump; contract-tested
  • airstack up --scene <shortname>: simulator-agnostic scene selection via
    a new catalog (simulation/scenes.yaml, resolved host-side by
    simulation/resolve_scene.py). Isaac maps shortnames to Pegasus catalog
    keys or Nucleus USD URLs (exported as ISAAC_SIM_SCENE +
    ISAAC_SIM_STAGE_SCALE; the example launch scripts and fleet_spawn.py
    now resolve their scene from these instead of hardcoding env_url);
    MS AirSim maps to fetch_scene.sh keys (MS_AIRSIM_SCENE — the
    entrypoint's auto-fetch, previously Blocks-only, now fetches any catalog
    scene, and an interactive airstack up asks before a multi-GB download).
    The fetch_scene.sh catalog was corrected to the UE4 binaries that
    actually exist in the AirSim v1.8.1 release: forest, soccerfield, and
    building99 were removed (their zips were never published, or are empty),
    airsimnh now downloads AirSimNH.zip (was the nonexistent
    Neighborhood.zip), and africasavannah / msbuild2018 were added; the
    entrypoint resolves the UE launcher by glob after extraction, so zips whose
    inner .sh doesn't match the folder name still boot.
    Unknown scene = error + per-simulator availability table. Five stages were
    published to the guest-readable
    omniverse://airlab-nucleus.andrew.cmu.edu:443/Public/AirStack/Stages/
    (AbandonedFactory, AbandonedWarehouse day/night, ChemicalPlant,
    ConstructionSite, RetroNeighborhood) and cataloged with per-stage scale.
    See Simulation Scenes
  • airstack ready (and airstack up --wait): staged flight-readiness gates
    mirroring the system-test budgets — containers → sim /clock → per-robot
    sentinel nodes → PX4 MAVROS-connected + local_position/odom streaming —
    with per-gate diagnostics and --json for scripts
  • Preflight validation in airstack up on resolved configuration (env >
    --env-file > .env): one-simulator guard, NUM_ROBOTS>1 vs
    single-drone Isaac script as a named hard error, missing images listed
    with an image-pull hint, missing omni_pass.env / empty Pegasus
    submodule / Docker < 29 surfaced on the host
    (AIRSTACK_SKIP_PREFLIGHT=1 downgrades errors to warnings)
  • tmux pane output mirrored to container stdout via shared .tmux.conf
    hooks, so docker logs / airstack logs show colcon builds,
    ros2 launch output, sim loading, and crashes
  • simple-sim as a first-class simulator: airstack up --sim simple and a
    simple_sim smoke-test mark (it had been broken since the ROS Jazzy
    migration — its container sourced a Humble path — and is fixed)
  • Automatic unit-tests.yml PR gate on ubuntu-latest, plus
    run_meta.json outcome metadata so reports distinguish completed
    simulation campaigns from collection errors, empty selections, timeouts,
    and cancellations
  • Feature notebook workflow (use-feature-notebook skill): gitignored
    notebook/NNN-feature-slug/ entries whose design_spec.md and
    results_summary.md populate feature PR descriptions
  • Battery and telemetry display in the GCS control panel (voltage and
    percentage per robot when the MAVROS battery topic is bridged)
  • TARGET_ARCH build arg (default x86_64) in Dockerfile.robot;
    docker-compose.yaml passes TARGET_ARCH: aarch64 to the voxl and
    l4t real-robot image builds
  • ros-${ROS_DISTRO}-mavros-extras in the robot image (provides the
    vision_pose plugin used for external-pose deployments)
  • overrides/l4t-px4-realrobot.env — site-agnostic deployment override for
    a single real PX4 robot on a Jetson (aarch64/l4t)
  • integration test tier (tests/integration/, integration mark) with a
    shared robot_autonomy_stack fixture (robot container, no sim/GPU)
  • waypoint_flight system test: takeoff → ordered waypoint route via
    NavigateTask → land, judged on the odometry track by the standalone
    tests/waypoint_checker.py; the standard acceptance check after
    integrating or swapping a planner module
  • Foxglove auto-loaded layout: render_layout.py seeds the rendered
    NUM_ROBOTS-matched layout directly into the Foxglove desktop app's
    local layout store and gcs.launch.xml selects it via the layoutId
    deep link, so Foxglove opens on the right layout with no manual
    Import from file... step; user-saved edits are hash-detected and
    never overwritten (delete the layout in the UI to reset). Requires the
    pinned Foxglove version — see Changed

Changed

  • The simulator now starts playing by default: PLAY_SIM_ON_START
    defaults to true in .env (was false). Pass airstack up --no-play
    to come up paused and press Play yourself; --play remains available as
    an explicit override
  • Container autolaunch (robot desktop/voxl/l4t and GCS) now runs through an
    autolaunch shell helper instead of a bare bws && sws && ros2 launch
    chain: a build failure or launch crash prints an unmissable red
    "AUTOLAUNCH FAILED" banner in the tmux pane (mirrored to docker logs /
    airstack logs) instead of silently returning to a prompt with the stack
    down
  • Dockerfile.gcs pins the Foxglove desktop version (FOXGLOVE_VERSION
    build arg, currently 3.0.0) instead of installing latest, since the
    layout auto-load writes the app's on-disk local-layout record format
    directly (verified against 3.0.0; re-verify before bumping the pin)
  • robot-desktop image slimmed 17.1 GB → ~6 GB (−65%) by moving MACVO's
    torch/TensorRT/weights into the asm_macvo module Docker layer; a further
    dependency purge removed unused apt/pip packages (−152 MB) and droan_gl's
    GL dependencies are declared explicitly
  • Isaac launch scripts deduplicated onto a shared pegasus_app.PegasusApp
    base: the scripts become scenario declarations (~40–170 lines each, net
    −438 lines) with hooks for NatNet/scene-import extras; behavior verified
    by full system-test parity. ISAAC_SIM_HEADLESS and
    ISAAC_SIM_LIVESTREAM work uniformly in every launch script (each was
    honored by only half of them before)
  • Launch-workflow docs corrected against actual behavior: ISAAC_SIM_SCENE
    (nonexistent) replaced by ISAAC_SIM_SCRIPT_NAME/ISAAC_SIM_GUI,
    getting-started reflects the paused-by-default sim and Foxglove UI, isaac
    docker.md defaults match .env, ms-airsim MAVROS ports/FOV/vehicle naming
    fixed
  • Unit-test documentation matches the co-located layout: C++ gtests run via
    colcon test under the build_packages mark; Python via the root harness
    (conftest.py applies the unit mark by file location)
  • The CI orchestrator polls a repos: list (one instance covers trunk and
    every asm_* module repo; the singular repo: key still works) — module CI
    jobs on airstack-ephemeral no longer need per-repo orchestrator instances
  • Ephemeral CI GPU runners spawn via NVIDIA OSMO as a drop-in replacement
    for the earlier OpenStack-Nova backend: the GitHub side (labels, JIT
    tokens, fork guard) is unchanged; only the spawn target moved. The OSMO
    service-account token plays the old application-credential role,
    osmo workflow exec replaces SSH-via-floating-IP debugging, and the
    runner image prebakes what cloud-init used to install at boot
  • Pegasus launch scripts drive lidar through the RTX OmniLidar API
    (add_rtx_lidar_subgraph) in place of the Ouster graph path, with ROS
    topics reconciled (raw cloud on …/sensors/ouster/point_cloud_raw,
    filtered on …/sensors/ouster/point_cloud)
  • The airstack-osmo SSH config block for OSMO IDE sessions is
    StrictHostKeyChecking no + UserKnownHostsFile /dev/null (replacing
    accept-new); users with the earlier block should replace it and run
    ssh-keygen -R "[localhost]:2200" once
  • Default system-test --sim is isaacsim; pass --sim msairsim to opt in
  • -m build_packages CI runs pull cache_* images instead of baking sim
    images; docker-build.yml retags unchanged images on VERSION bumps
    (content fingerprint) instead of always rebuilding
  • Automatic OSMO validation runs the pull-only build_packages gate on
    every PR update; GPU simulation campaigns are selected through /pytest
    or workflow_dispatch
  • robot-l4t compose service knobs are env-overridable (FCU_URL, rosbag
    path via BAG_STORAGE_PATH); FCU_URL unquoted so the literal serial
    path reaches MAVROS
  • zed-l4t image: ZED SDK 4.2 → 5.2 with coupled ROS deps (zed_msgs
    5.2.1, point_cloud_transport(_plugins) 4.x, backward_ros)
  • Unit tests are defined by tests/colcon_unit_test_packages.yaml
  • Repo-wide relicense to BSD 3-Clause Clear (vendored packages keep
    their upstream licenses); airstack_msgs stabilized at 1.0.0; every
    package.xml carries a real maintainer and description (contract-tested)
  • DOCKER_IMAGE_BUILD_MODE=prebuilt is a tag discriminator only; a real
    prebuilt-workspace image stage is future work
  • The repository CHANGELOG.md is removed in favor of this page — all
    change records live here, per version
  • Docs policy: standalone snapshots. Feature docs describe only the
    current system; all change-relative language (including RFC citations)
    coalesces here. A full docs audit applied the policy and corrected pages
    that had drifted from the code, notably: bag recording is NOT
    auto-triggered at takeoff (the recorder starts idle; toggle via
    /{robot_name}/bag_record/set_recording_status); tracking_point /
    look_ahead carry airstack_msgs/msg/Odometry (older docs said
    geometry_msgs/PointStamped) and trajectory topics are
    airstack_msgs/TrajectoryXYZVYaw; MAVROSInterface targets any
    MAVLink-compatible FC (the documented Ascent/Ardupilot specificity does
    not exist in code); the RobotInterface command topic is cmd_pose; the
    DDS-router allowlist table is regenerated from the real config; the
    Jetson install flow is ./airstack.sh setup + the robot-l4t service.
    Two orphaned pages documenting the behavior-tree framework
    (behavior_tree, behavior_executive — packages removed in an earlier
    release, PR #332; only behavior_tree_msgs remains) were deleted; the
    behavior layer is drone_safety_monitor with mission sequencing via
    GCS-sent task goals

Removed

An audit removed dead or superseded code wholesale. Anything here is
recoverable from git history, and hardware-specific capabilities return as
out-of-trunk modules:

  • The AUTONOMY_ROLE launch dispatch and its per-role launch trees —
    stacks are the only launch path
  • MACVO extracted to castacks/asm_macvo;
    OptiTrack/NatNet extracted to
    castacks/asm_optitrack
    (client, PX4 external-vision fusion, NatNet emulator + Isaac wrapper,
    e2e/integration tests, env overrides)
  • px4_interface + vendored px4_msgs — a native PX4 uXRCE-DDS interface
    is tracked as a fresh design in
    #387; MAVROS remains
    the flight interface
  • waypoint_interface, attitude_controller(+_msgs) — dead code
  • The RQT/RViz GUI set: rviz_behavior_tree_panel (with the xdot_cpp
    submodule), rqt_behavior_tree_command, rqt_behavior_tree, rqt_gcs,
    rqt_airstack_control_panel — Foxglove is the GCS surface
  • Sensors-layer hardware packages camera_param_server,
    gimbal_stabilizer, sensor_interfaces
    (lidar_point_cloud_filter remains)
  • WinTAK / TAK integration (ros2tak_tools, CLI plumbing, GCS image
    dependencies) — can return as a module
  • Isaac Sim standalone_examples copies, stale robot-docker helpers, the
    ensemble_planner skeleton, the Gazebo parallel-bringup tree, and
    pre-co-location test scaffolding
  • trajectory_library's vestigial rqt selector (catkin-era GUI source,
    plugin.xml, setup.py, launcher script — never installed by its
    CMakeLists), the orphaned behavior-tree docs images, and an empty
    integration-testing stub page
  • tests/goldens/wiring/ — wiring baselines live per-stack as
    stacks/<name>/wiring.md

Fixed

  • airstack up guards (one-simulator, URDF pairing) validated .env only
    and were bypassed by --env-file; they now check the resolved
    configuration
  • pytest tests/ collects the co-located unit tests before mark filtering
    (CI previously collected 97 of 252 items, so the Python unit tests ran
    nowhere); empty CI pytest arguments no longer recurse the repository;
    non-comparable artifacts are reported instead of false 0% results
  • barebones_pegasus_launch.py crashed with NameError: os;
    isaac-sim-livestream produced a black stream with multi-drone scripts;
    NATNET_BODY_NAME/NATNET_TARGET_NAME overrides now work
  • Isaac Sim image: PX4 ubuntu.sh no longer fails dpkg configure on the
    NVIDIA base; robot image pins pytest<8.1 and disables launch_testing
    for colcon unit tests
  • Robot identity: a pre-set ROBOT_NAME is honored; the name-map catch-all
    maps to unknown_robot (valid ROS namespace token) and logs a warning
    naming both fixes; inert ROBOT_NAME/ROS_DOMAIN_ID lines dropped from
    overrides/l4t-px4-realrobot.env
  • l4t robot image: dustynv's /ros_entrypoint.sh replaced with a
    passthrough so stale prebuilt fastcdr libs no longer crash apt-built
    nodes like MAVROS; the GeographicLib egm96-5 geoid is asserted at build
    time (MAVROS dies at startup without it)
  • Bag recording: RECORD_BAGS=true now actually starts the recorder on a
    robot; recorder status is bridged in the correct direction so GCS
    indicators work; ros2 bag record --exclude updated for Jazzy's
    --exclude-regex (multiple excludes alternated into one regex)
  • OptiTrack/NatNet: NATNET_SERVER_IP is forwarded to the robot container;
    the default tracked body matches the emulator; EKF2 external-vision
    parameters are passed as PX4_PARAM_* so PX4 actually fuses mocap;
    external-vision tuning corrected from real-flight bags (EKF2_EV_DELAY
    7.0, EKF2_EVP_NOISE 0.05); an unrecognized connection_type fails at
    startup instead of silently falling back; MODELDEF drone-body count is
    cross-checked against NUM_ROBOTS after the handshake; the emulator is
    installed as a Kit extension so launch scripts can import it

Landing page & simulation camera/lighting (alpha.13)

  • Docs landing page redesigned around four demonstrated pillars
    (one-command bring-up, sim-to-vehicle code parity, full-stack CI, agent
    readiness): real quickstart commands with copy buttons, the actual
    airstack ready checklist, a live test-mark matrix, and a fresh
    autoplay hero video (Isaac full-warehouse and office, Foxglove's live
    3-robot trajectory traces, MS AirSim neighborhood and ZhangJiajie) —
    40 s / 5.4 MB, replacing the 37 MB splash GIF. Per-simulator and Foxglove
    clips are embedded in their docs sections, and the architecture image is
    now an unedited full-system desktop capture (sim + GCS + CLI, live).
  • Isaac launch scripts grew camera/spawn/lighting env knobs
    (pegasus_app.py, plumbed through the isaac-sim compose service):
    ISAAC_SIM_FOLLOW_CAM / _OFFSET — a smoothed viewport chase camera
    tracking a drone via live Pegasus vehicle state (also fixes the black
    viewport at spawn on cm-authored stages; on by default, off disables);
    ISAAC_SIM_SPAWN_XY — recenter the spawn row away from a cluttered scene
    origin; ISAAC_SIM_LIGHT_BOOST — multiply the scene's own lights
    (de-instances light-bearing subtrees first, so e.g. the NVIDIA office's
    121 instanceable ceiling lights become editable);
    ISAAC_SIM_FOLLOW_CAM_LIGHT — headlight riding the follow camera;
    ISAAC_SIM_DOME_LIGHT — dome-light intensity/exposure override.