Pure module. No processes. No I/O.
Input
%{
drones: [:a, :b, :c, :d],
positions: %{a: %{x: -50, y: 0, z: 30, yaw: 0}, ...},
heading_deg: 0,
spacing_cm: 100,
min_separation_cm: 80,
origin: :centroid
# origin: {:xy, 0, 0}
# leader: :a # optional; plan-time pose only
}
Output
{:ok, %{a: Mission.t(), b: Mission.t(), ...}}
# or
{:error, :separation_violation | :unsupported_formation | :too_few_drones | :leader_unavailable}
Built-in formations
| Atom |
Min drones |
Layout |
:front |
2 |
Side-by-side, perpendicular to heading_deg |
:column |
2 |
Nose-to-tail along heading_deg |
:vee |
3 |
V opening opposite travel (geometry only) |
:diamond |
4 |
Four-sided closed layout |
:echelon |
2 |
Diagonal stepped rank; opt side: :left | :right |
:circle |
3 |
Even spacing on ring; opt radius_cm |
:shoulder_pair |
2 |
Alias for :front with two members |
:grid |
2 |
Optional classroom row/column lattice |
Default reference: :centroid or configured {:xy, x, y} — not a living
leader. Optional leader: uses that member’s pose as the plan-time origin
only. See docs/design/v0_2_0_deferred.md for leader-failure recovery that is
explicitly out of scope.
Each mission should:
- Move horizontally toward slot (decompose into forward/back/left/right
relative to current yaw, or rotate then forward — pick one deterministic
strategy and document it)
- Optionally hover briefly
Movement strategy for v0.2.0: rotate to face target bearing, move forward
by horizontal distance, restore yaw if needed. Keep altitudes unchanged unless
formation specifies height.
Use existing Drone.Geometry for deltas. Add pure helpers in Drone.Formation
for bearing/distance if needed.
Separation check (Separate, plan-time only)
Before returning missions, verify pairwise horizontal distance between planned
slots >= min_separation_cm. Live Separate / Align / Cohere are deferred.
Pure module. No processes. No I/O.
Input
Output
Built-in formations
:frontheading_deg:columnheading_deg:vee:diamond:echelonside: :left | :right:circleradius_cm:shoulder_pair:frontwith two members:gridDefault reference:
:centroidor configured{:xy, x, y}— not a livingleader. Optional
leader:uses that member’s pose as the plan-time originonly. See
docs/design/v0_2_0_deferred.mdfor leader-failure recovery that isexplicitly out of scope.
Each mission should:
relative to current yaw, or rotate then forward — pick one deterministic
strategy and document it)
Movement strategy for v0.2.0: rotate to face target bearing, move forward
by horizontal distance, restore yaw if needed. Keep altitudes unchanged unless
formation specifies height.
Use existing
Drone.Geometryfor deltas. Add pure helpers inDrone.Formationfor bearing/distance if needed.
Separation check (Separate, plan-time only)
Before returning missions, verify pairwise horizontal distance between planned
slots >=
min_separation_cm. Live Separate / Align / Cohere are deferred.