diff --git a/.env b/.env index bd877d365..64a1b3f6b 100644 --- a/.env +++ b/.env @@ -12,7 +12,7 @@ PROJECT_NAME="airstack" # If you've run ./airstack.sh setup, then this will auto-generate from the git commit hash every time a change is made # to a Dockerfile or docker-compose.yaml file. Otherwise this can also be set explicitly to make a release version. # auto-generated from git commit hash -VERSION="0.20.0-alpha.16" +VERSION="0.20.0-alpha.17" # Image-tag discriminator ONLY (appears in the image tag suffix, e.g. ..._robot-x86-64_dev). # No Dockerfile consumes it: "prebuilt" does NOT bake the built ros_ws into the image today — # a real prebuilt (workspace-baked) stage is future work. Keep "dev" (mounted code, built live). diff --git a/docs/development/stacks.md b/docs/development/stacks.md index 76d6063ed..cfbc9d29b 100644 --- a/docs/development/stacks.md +++ b/docs/development/stacks.md @@ -30,6 +30,7 @@ Anatomy is enforced by a unit test: `tests/meta/test_stack_layout_contract.py` | [`full_default`](https://github.com/castacks/AirStack/tree/develop/stacks/full_default) | The full-autonomy topology (GPU `droan_gl` planner) — the baseline, and what launches when no stack is selected. | | [`full_droan_cpu`](https://github.com/castacks/AirStack/tree/develop/stacks/full_droan_cpu) | CPU DROAN planner + live `disparity_expansion` (for machines without the GPU planner). | | [`full_macvo`](https://github.com/castacks/AirStack/tree/develop/stacks/full_macvo) | MAC-VO as the planner's disparity source. Requires the `asm_macvo` module (`airstack module add asm_macvo`). | +| [`full_mighty`](https://github.com/castacks/AirStack/tree/develop/stacks/full_mighty) | The MIGHTY map-based local planner (+ acl-mapping voxel world model) in place of `droan_gl`. Requires the `asm_mighty` module (pinned in the stack's `modules.repos`). | | [`lite_default`](https://github.com/castacks/AirStack/tree/develop/stacks/lite_default) | Onboard-lite topology, unsplit: interface, sensors, perception, flat Local layer, behavior; **no global, no logging**. | | [`lite_offload_global`](https://github.com/castacks/AirStack/tree/develop/stacks/lite_offload_global) | A **split stack**: `onboard.launch.xml` (= lite topology) + `offboard.launch.xml` (global layer only) + `bridge.yaml`. | @@ -283,5 +284,6 @@ ignored. Select the topology with `--stack`: | The full-autonomy baseline | Nothing — `full_default` launches by default (or be explicit: `--stack full_default`) | | CPU DROAN topology | `--stack full_droan_cpu` | | MAC-VO disparity topology | `--stack full_macvo` (requires the `asm_macvo` module) | +| MIGHTY map-based local planner | `--stack full_mighty` (requires the `asm_mighty` module) | | Onboard-lite, unsplit | `--stack lite_default` | | Split onboard/offboard | `--stack lite_offload_global:onboard` / `:offboard` (+ generate the router config from `bridge.yaml`) | diff --git a/docs/modules/index.md b/docs/modules/index.md index 7a28abc3b..db55baf9b 100644 --- a/docs/modules/index.md +++ b/docs/modules/index.md @@ -20,6 +20,7 @@ directory and is never hand-edited. |--------|-------------|------|------------|-----------------|-------| | [dfm2_disturbances](dfm2_disturbances.md) | Isaac Sim disturbance library (fan/vent force fields, strobe lights, lens flare) | `isaac_extension` | ajong@andrew.cmu.edu | `>=0.19.0-alpha.18 <0.20.0` | [repo](https://github.com/castacks/asm_dfm2_disturbances) | | [macvo](macvo.md) | MAC-VO learned stereo visual odometry (ICRA 2025 best paper) — macvo_ros2 wrapper around the MAC-VO network, publishing odometry, a covariance-aware point cloud, and the disparity image the local planner can consume | `ros_package` | ajong@andrew.cmu.edu | `>=0.19.0-alpha.18 <0.20.0` | [repo](https://github.com/castacks/asm_macvo) · [full_macvo](../../stacks/full_macvo/README.md) | +| [mighty](mighty.md) | MIGHTY Hermite-spline local planner (MIT ACL, RA-L 2026) with its acl-mapping voxel world model and a bridge to AirStack's NavigateTask / trajectory_controller seam — a map-based replacement for the DROAN local planner | `ros_package` | ajong@andrew.cmu.edu | `>=0.20.0-alpha.16 <0.21.0` | [repo](https://github.com/castacks/asm_mighty) · [full_mighty](../../stacks/full_mighty/README.md) | | [optitrack](optitrack.md) | OptiTrack NatNet mocap integration — natnet_ros2 client + PX4 external-vision fusion bridges on the robot, and the Motive-compatible NatNet server emulator for Isaac Sim | `ros_package` | ajong@andrew.cmu.edu | `>=0.19.0-alpha.18 <0.20.0` | [repo](https://github.com/castacks/asm_optitrack) | ## Registered stacks @@ -35,6 +36,7 @@ The stacks below are the ones REGISTERED in the index; the site nav's | [full_default](../../stacks/full_default/README.md) | The current full-autonomy topology as a self-contained stack folder — the baseline most users start from and the stack other stacks are copied from | `>=0.19.0-alpha.18 <0.21.0` | [wiring.md](../../stacks/full_default/wiring.md) | [full_default.yaml](https://github.com/castacks/airstack-modules-index/blob/main/stacks/full_default.yaml) | | [full_droan_cpu](../../stacks/full_droan_cpu/README.md) | Full autonomy with the CPU DROAN local planner (droan_local_planner + live disparity_expansion world model) instead of the GPU droan_gl node | `>=0.19.0-alpha.18 <0.21.0` | [wiring.md](../../stacks/full_droan_cpu/wiring.md) | [full_droan_cpu.yaml](https://github.com/castacks/airstack-modules-index/blob/main/stacks/full_droan_cpu.yaml) | | [full_macvo](../../stacks/full_macvo/README.md) | Full autonomy with MAC-VO learned stereo visual odometry as the disparity source for the local planner (droan_gl consumes /$ROBOT_NAME/perception/macvo/disparity) | `>=0.19.0-alpha.18 <0.21.0` | [wiring.md](../../stacks/full_macvo/wiring.md) | [full_macvo.yaml](https://github.com/castacks/airstack-modules-index/blob/main/stacks/full_macvo.yaml) | +| [full_mighty](../../stacks/full_mighty/README.md) | Full autonomy with the local planning layer swapped to the MIGHTY module (mighty planner + acl-mapping voxel world model fed by the filtered Ouster cloud + NavigateTask bridge) in place of droan_gl; everything else is identical to full_default | `>=0.20.0-alpha.16 <0.21.0` | *not committed yet* | [full_mighty.yaml](https://github.com/castacks/airstack-modules-index/blob/main/stacks/full_mighty.yaml) | ## See also diff --git a/docs/modules/mighty.md b/docs/modules/mighty.md new file mode 100644 index 000000000..935467e9e --- /dev/null +++ b/docs/modules/mighty.md @@ -0,0 +1,56 @@ +# mighty + + + +> MIGHTY Hermite-spline local planner (MIT ACL, RA-L 2026) with its acl-mapping voxel world model and a bridge to AirStack's NavigateTask / trajectory_controller seam — a map-based replacement for the DROAN local planner + +| | | +|---|---| +| Repository | [castacks/asm_mighty](https://github.com/castacks/asm_mighty) | +| Type | `ros_package` | +| Maintainer | ajong@andrew.cmu.edu | +| License | BSD-3-Clause-Clear | +| Registered ref | [`v0.1.1`](https://github.com/castacks/asm_mighty/tree/v0.1.1) | +| Declared compat | `>=0.20.0-alpha.16 <0.21.0` | +| Registry entry | [modules/mighty.yaml](https://github.com/castacks/airstack-modules-index/blob/main/modules/mighty.yaml) | + +## Install + +From an AirStack checkout ([AirStack Modules guide](../development/modules.md)): + +```bash +airstack module add https://github.com/castacks/asm_mighty --version v0.1.1 +airstack up +``` + +`module add` pins the module in `modules.repos` and syncs it into the +gitignored `modules/` overlay; `airstack up` automatically includes the +generated compose override that mounts it into the containers. + +## Compatibility: declared vs verified + +The range `>=0.20.0-alpha.16 <0.21.0` is **DECLARED** by the module author +(copied from the module's `module.yaml`). The **VERIFIED** record — rows +stamped exclusively by CI runs of the reusable +[module-system-tests workflow](../development/module_ci.md) — lives in the +registry's [compat/ matrix](https://github.com/castacks/airstack-modules-index/tree/main/compat) +([compat/mighty.yaml](https://github.com/castacks/airstack-modules-index/blob/main/compat/mighty.yaml) once stamped). +A compatibility claim that isn't CI-verified rots: trust the +matrix, read the declaration as intent. + +## Documentation + +- [Module README on GitHub @ `v0.1.1`](https://github.com/castacks/asm_mighty/blob/v0.1.1/README.md) +- *The module repo was not fetched when this page was generated — the* + *links above go to GitHub at the registered ref (failure isolation:* + *an unreachable module repo never fails the docs deploy).* + +## Registered stacks using this module + +- [full_mighty](../../stacks/full_mighty/README.md) + +## Registry notes + +> Repo is PRIVATE until the AirStack agent study (ICRA 2027 paper, Sec. VI-C) concludes, then flips public — until then the repo/README links 404 for non-members. v0.1.1 is code-identical to v0.1.0 (README-only delta); v0.1.0 was validated end-to-end on Isaac Sim: 44/44 vendored gtests, synthetic smoke harness, empty-world NavigateTask flight, 7/7 practice pillar-field traversals, and 5/5 judged obstacle-route flights (min clearances 1.59–1.65 m vs a 1.0 m gate). Wrapper packages are BSD-3-Clause-Clear; vendored upstream packages (mighty, DecompROS2, acl-mapping) keep their own permissive licenses — see the module's VENDORED.md. Consumed by trunk reference stack full_mighty. diff --git a/docs/release_notes/index.md b/docs/release_notes/index.md index 490159def..b8d93e369 100644 --- a/docs/release_notes/index.md +++ b/docs/release_notes/index.md @@ -19,6 +19,20 @@ its own notes. --> ## 0.20.0 (Unreleased) +- **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](https://github.com/castacks/asm_mighty) module (pinned at + v0.1.1 in the stack's `modules.repos`; repo private until the AirStack + agent study concludes). [`full_mighty`](../../stacks/full_mighty/README.md) + is `full_default` with only the local-planner include swapped — the + module-swap demonstration for the modular architecture. Registered in the + [module catalog](../modules/index.md); 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. diff --git a/docs/robot/autonomy/adding_a_controller.md b/docs/robot/autonomy/adding_a_controller.md index b23625ff8..3cb97db93 100644 --- a/docs/robot/autonomy/adding_a_controller.md +++ b/docs/robot/autonomy/adding_a_controller.md @@ -5,7 +5,7 @@ AirStack splits control into two roles ([Controls overview](local/controls/index - **Trajectory controller** — a pure-pursuit trajectory *manager*, not itself a feedback controller. It **owns the [trajectory group (spec §5)](interface_conventions.md#5-trajectory-group-the-trajectory-controllers-contract-onboard-only)**: it consumes `trajectory_controller/trajectory_segment_to_add` and `trajectory_override` (`airstack_msgs/msg/TrajectoryXYZVYaw`), serves the `set_trajectory_mode` service, and emits `tracking_point` and `look_ahead` (`airstack_msgs/msg/Odometry` — not `nav_msgs`). Reference: [Trajectory Controller](../../../robot/ros_ws/src/local/controls/trajectory_controller/README.md). - **Feedback controller** — closes the loop between the tracking point and the vehicle's actual state and emits the [`control_setpoint` (spec §6)](interface_conventions.md#6-control_setpoint-controller-interface-command-onboard-only) command into the interface. Reference: `pid_controller` (`robot/ros_ws/src/local/controls/pid_controller` — no README; the cascaded position→velocity PID is described in the [Trajectory Controller README's Control Architecture section](../../../robot/ros_ws/src/local/controls/trajectory_controller/README.md#control-architecture)). -The verified chain in every reference stack (`full_default`, `full_droan_cpu`, `full_macvo`, `lite_default`, `lite_offload_global` onboard) is: +The verified chain in every reference stack (`full_default`, `full_droan_cpu`, `full_macvo`, `full_mighty`, `lite_default`, `lite_offload_global` onboard) is: ```text trajectory_controller/tracking_point (airstack_msgs/Odometry, §5) diff --git a/docs/robot/autonomy/adding_a_world_model_and_planner.md b/docs/robot/autonomy/adding_a_world_model_and_planner.md index 4ad0325c5..6c403ebf4 100644 --- a/docs/robot/autonomy/adding_a_world_model_and_planner.md +++ b/docs/robot/autonomy/adding_a_world_model_and_planner.md @@ -49,7 +49,7 @@ Planner variants are named stacks, not launch arguments — the [single-locus ru ``` -Do the same for yours: `airstack stack new full_default full_my_planner`, then in `stacks/full_my_planner/launch/stack.launch.xml` replace the DROAN include with your planner's include (plus any world-model include it needs). Only deviations from canonical names appear as include args — see how `full_macvo` passes exactly one (`droan_gl_disparity_topic`). +Do the same for yours: `airstack stack new full_default full_my_planner`, then in `stacks/full_my_planner/launch/stack.launch.xml` replace the DROAN include with your planner's include (plus any world-model include it needs). Only deviations from canonical names appear as include args — see how `full_macvo` passes exactly one (`droan_gl_disparity_topic`). For a planner that ships as an **external module**, the worked example is [full_mighty](../../../stacks/full_mighty/README.md): its `modules.repos` pins the [mighty module](../../modules/mighty.md) (planner + voxel world model + bridge), and the local-planner block is one `mighty_module.launch.xml` include. **Verify:** `airstack up --stack full_my_planner --sim isaac --robots 1 && airstack ready` succeeds and `ros2 node list` shows your planner in place of DROAN. diff --git a/docs/robot/autonomy_modes.md b/docs/robot/autonomy_modes.md index 31d0ea382..b1536658f 100644 --- a/docs/robot/autonomy_modes.md +++ b/docs/robot/autonomy_modes.md @@ -14,6 +14,7 @@ environment variable is a preflight error.) | **`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 ` launches a whole **fleet**: `config/fleets/.yaml` declares who exists, which diff --git a/mkdocs.yml b/mkdocs.yml index fe771b31f..662a2780c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -173,6 +173,7 @@ nav: - full_default: stacks/full_default/README.md - full_droan_cpu: stacks/full_droan_cpu/README.md - full_macvo: stacks/full_macvo/README.md + - full_mighty: stacks/full_mighty/README.md - lite_default: stacks/lite_default/README.md - lite_offload_global: stacks/lite_offload_global/README.md - Modules Catalog: @@ -180,6 +181,7 @@ nav: - module.yaml Schema: common/module_schema/README.md - dfm2_disturbances: docs/modules/dfm2_disturbances.md - macvo: docs/modules/macvo.md + - mighty: docs/modules/mighty.md - optitrack: docs/modules/optitrack.md - Autonomy Packages: - Robot Overview: docs/robot/index.md diff --git a/stacks/full_mighty/README.md b/stacks/full_mighty/README.md new file mode 100644 index 000000000..0893f5643 --- /dev/null +++ b/stacks/full_mighty/README.md @@ -0,0 +1,39 @@ +# full_mighty + +`full_default` with the local planner swapped: the DROAN GPU planner +(`droan_gl`) is replaced by the **MIGHTY** Hermite-spline planner from the +external **asm_mighty** module (MIT ACL, RA-L 2026), together with its +acl-mapping voxel world model (fed by the filtered Ouster cloud) and a +`mighty_bridge` adapter that serves the same `tasks/navigate` NavigateTask +action and publishes `trajectory_controller/trajectory_segment_to_add` +segments — so the rest of the stack (trajectory controller, PID, safety +monitor, takeoff/landing, GCS) is unchanged from `full_default`. + +This stack is the module-swap demonstration for the modular architecture: +the only difference vs `full_default` is one include in +`launch/stack.launch.xml` plus the `asm_mighty` pin in `modules.repos`. + +Bring-up: + +```bash +airstack module sync # pulls asm_mighty per this stack's modules.repos +airstack up --stack full_mighty --sim isaac +``` + +Notes: + +- MIGHTY is CPU-only (no GPU contention with Isaac). +- The planner needs the module's `nlohmann-json3-dev` dep layer: + `airstack module lock --build` before `airstack up`. +- Planner/world-model tuning lives in the module + (`mighty_bridge/config/*_airstack.yaml`). +- The [asm_mighty repo](https://github.com/castacks/asm_mighty) is **private + until the AirStack agent study concludes** (then public) — until the flip, + `airstack module sync` needs castacks-member credentials. Registry entry: + [modules/mighty.yaml](https://github.com/castacks/airstack-modules-index/blob/main/modules/mighty.yaml); + catalog page: [mighty](../../docs/modules/mighty.md). +- Validation at the pinned version (Isaac Sim, judged on ground truth): + 44/44 vendored gtests, empty-world NavigateTask route (goal error 0.14 m), + 7/7 pillar-field traversals, and 5/5 judged obstacle-route flights with + min clearances 1.59–1.65 m against a 1.0 m gate — the motivating DROAN + comparison (figures + numbers) is in the module README. diff --git a/stacks/full_mighty/docker-compose.yaml b/stacks/full_mighty/docker-compose.yaml new file mode 100644 index 000000000..ce3ebf780 --- /dev/null +++ b/stacks/full_mighty/docker-compose.yaml @@ -0,0 +1,11 @@ +# Per-stack image composition: the P4 machinery +# (tools/compose_module_layers.py) composes per-module dependency layers on +# top of the trunk base image and emits a compose override for `airstack up`. +# +# full_mighty pins the asm_mighty module (see modules.repos); its apt dep +# (nlohmann-json3-dev) enters the robot image via the module's +# content-addressed dependency layer — `airstack module lock --build` +# GENERATES that override at lock time, so nothing is committed here. The +# empty services map keeps this file valid YAML for the stack-anatomy +# contract (tests/meta/test_stack_layout_contract.py). +services: {} diff --git a/stacks/full_mighty/launch/stack.launch.xml b/stacks/full_mighty/launch/stack.launch.xml new file mode 100644 index 000000000..b032f9562 --- /dev/null +++ b/stacks/full_mighty/launch/stack.launch.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/stacks/full_mighty/modules.repos b/stacks/full_mighty/modules.repos new file mode 100644 index 000000000..4bd6cdfe9 --- /dev/null +++ b/stacks/full_mighty/modules.repos @@ -0,0 +1,23 @@ +# modules.repos : module pins for the full_mighty stack. +# +# vcstool format, PINNED to tags/commits (never branches). `airstack module sync` +# reads this file into the gitignored modules/ dir; a stack with a pinned .repos +# IS a localized release set. +# +# airstack_compat is a top-level sibling of repositories: (vcstool ignores it, +# AirStack tooling reads it) declaring the trunk semver range this stack was +# tested against. sync warns on mismatch; it never gates. +# +# full_mighty pulls the asm_mighty module (MIGHTY local planner + acl-mapping +# world model + NavigateTask bridge); everything else is trunk-resident. +# asm_mighty lives at castacks/asm_mighty (PRIVATE until the AirStack agent +# study concludes, then public — until the flip, syncing this stack needs +# castacks-member credentials). v0.1.1 is code-identical to the validated +# v0.1.0 (README-only delta). +airstack_compat: ">=0.20.0-alpha.16 <0.21.0" +repositories: + asm_mighty: + type: git + url: git@github.com:castacks/asm_mighty.git + version: v0.1.1 +x-local-modules: [] diff --git a/tests/meta/fixtures/modules_index/modules/mighty.yaml b/tests/meta/fixtures/modules_index/modules/mighty.yaml new file mode 100644 index 000000000..5044b5aba --- /dev/null +++ b/tests/meta/fixtures/modules_index/modules/mighty.yaml @@ -0,0 +1,26 @@ +# Registry entry for the mighty module (schema/module-entry.schema.json). +# airstack_compat is the DECLARED range copied from the module's module.yaml; +# the VERIFIED matrix lives in compat/mighty.yaml (CI-stamped only). +name: mighty +repo: https://github.com/castacks/asm_mighty +description: >- + MIGHTY Hermite-spline local planner (MIT ACL, RA-L 2026) with its + acl-mapping voxel world model and a bridge to AirStack's NavigateTask / + trajectory_controller seam — a map-based replacement for the DROAN local + planner +maintainer: ajong@andrew.cmu.edu # Andrew Jong +license: BSD-3-Clause-Clear +type: ros_package +registered_ref: v0.1.1 +airstack_compat: ">=0.20.0-alpha.16 <0.21.0" # DECLARED (from module.yaml) +notes: >- + Repo is PRIVATE until the AirStack agent study (ICRA 2027 paper, Sec. VI-C) + concludes, then flips public — until then the repo/README links 404 for + non-members. v0.1.1 is code-identical to v0.1.0 (README-only delta); v0.1.0 + was validated end-to-end on Isaac Sim: 44/44 vendored gtests, synthetic + smoke harness, empty-world NavigateTask flight, 7/7 practice pillar-field + traversals, and 5/5 judged obstacle-route flights (min clearances + 1.59–1.65 m vs a 1.0 m gate). Wrapper packages are BSD-3-Clause-Clear; + vendored upstream packages (mighty, DecompROS2, acl-mapping) keep their own + permissive licenses — see the module's VENDORED.md. Consumed by trunk + reference stack full_mighty. diff --git a/tests/meta/fixtures/modules_index/stacks/full_mighty.yaml b/tests/meta/fixtures/modules_index/stacks/full_mighty.yaml new file mode 100644 index 000000000..5dea3ffe3 --- /dev/null +++ b/tests/meta/fixtures/modules_index/stacks/full_mighty.yaml @@ -0,0 +1,17 @@ +# Registry entry for the full_mighty trunk reference stack (schema/stack-entry.schema.json). +name: full_mighty +repo: https://github.com/castacks/AirStack +path: stacks/full_mighty +description: >- + Full autonomy with the local planning layer swapped to the MIGHTY module + (mighty planner + acl-mapping voxel world model fed by the filtered Ouster + cloud + NavigateTask bridge) in place of droan_gl; everything else is + identical to full_default +airstack_compat: ">=0.20.0-alpha.16 <0.21.0" # from the stack's modules.repos airstack_compat key +wiring: stacks/full_mighty/wiring.md # docs site embeds the CI-generated wiring.md from trunk +notes: >- + The module-swap demonstration for the modular architecture: the only + difference vs full_default is one include in launch/stack.launch.xml plus + the asm_mighty pin in modules.repos (registry: modules/mighty.yaml — repo + private until the agent study concludes). wiring.md is pending the stack's + first validated wiring-snapshot run.