Seastead Convoy Mode – Design & Network Overview
This document expands the “convoy mode” concept for a fleet of tri‑float seasteads. It includes the logical grid layout, a recommended low‑cost Wi‑Fi mesh network, the software stack, protocol definitions, joining logic, safety considerations, and a sample implementation.
2. Grid & Spatial Layout
- Each seastead is assigned a grid coordinate (x, y) in a planar coordinate system (e.g., UTM). The grid spacing is configurable; typical spacing is 20 m–30 m.
- Neighbour relationship: a node typically talks to 4 (N, S, E, W) or up to 8 (including diagonals) neighbours. The protocol uses directional antennas so each link is point‑to‑point.
- Position accuracy: using RTK‑GPS, relative positions are known to ≤ 2 cm.
- The convoy can be a rectangular or arbitrary‑shaped patch. When a new node wants to join, the “convoy manager” (any node that currently holds the master role) assigns the nearest empty slot.
3. Communications Hardware
3.1 Recommended Hardware
| Component | Typical Model | Key Specs | Approx. Cost (USD) |
|---|---|---|---|
| Wi‑Fi Radio (5 GHz) | Ubiquiti NanoStation 5AC Loco (or MikroTik SXT 5) | 802.11ac, 2×2 MIMO, 23 dBi gain, 10‑20 km range (LOS), 450 Mbps max throughput | $130 – $150 |
| Dual‑Band AP (optional redundancy) | TP‑Link EAP225 (ceiling AP) | 2.4/5 GHz, 802.11ac, 5 dBi, 300 Mbps per band | $80 |
| Antenna (directional, 5 GHz) | MikroTik mANT 5‑19 (19 dBi) | Beamwidth ~30°, 30 km LOS with clear line‑of‑sight | $40 |
| POE Injector + cabling | Ubiquiti 48 V 0.5 A PoE injector | Power over Ethernet for radio | $15 – $20 |
| Mounting hardware | Stainless steel pole & clamps (2 m above deck) | Marine‑grade, anti‑corrosion | $30 – $50 |
| Network switch (optional, for multi‑radio) | TP‑Link TL‑SG108E (8‑port, managed) | 1 Gbps, VLAN support | $45 |
3.2 Range & Data Rate
- Range: With 23 dBi gain, a clear line‑of‑sight link can reach 10‑15 km. At sea the horizon is ~4 km for a 4 m antenna height, but a 2 m mast on each float gives ~5 km horizon. Practical inter‑float range = 4‑6 km.
- Data Rate: 802.11ac can push ~200‑300 Mbps (real‑world) under 5 km, more than enough for position updates (a few KB), camera frames (JPEG ~200 KB per frame) and object‑tracking telemetry (< 50 KB/s). Latency is < 5 ms in the mesh.
- Channel planning: Choose a clean 20 MHz channel in the UNII‑2 (5.25‑5.35 GHz) or UNII‑3 (5.47‑5.725 GHz) band. Avoid overlapping with nearby convoys or shore Wi‑Fi.
3.3 Cost Estimates (per seastead)
| Item | Qty | Unit Price | Total (USD) |
|---|---|---|---|
| 5 GHz Wi‑Fi radio (NanoStation AC) | 1 | $140 | $140 |
| Directional antenna (mANT 5‑19) | 1 | $40 | $40 |
| POE injector + cables | 1 | $20 | $20 |
| Mount pole & hardware | 1 | $40 | $40 |
| Network switch (8‑port, optional) | 1 | $45 | $45 |
| Total | ~$285 |
4. Mesh Network Software
4.1 OS & Firmware
Run a lightweight Linux distribution (e.g., OpenWrt 21.02 or Debian minimal) on a small industrial PC (e.g., BeagleBone Black, Raspberry Pi 4, or a fanless x86 board). This gives you full control over the Wi‑Fi driver, hostapd, and routing daemons.
4.2 Routing Protocol
- Mesh Layer‑2: Use
batman‑adv(Batman‑Advanced) to create a transparent Ethernet mesh across the 5 GHz radios. It auto‑discovers routes and works at Layer 2, making the mesh behave like a giant switch. - Routing daemon: For larger convoys (>10 nodes) consider
olsrd2(OLSRv2) to compute shortest‑path routes at Layer 3. Batman‑adv is simpler for up to ~30 nodes and works well with point‑to‑point directional links. - Position broadcast: Each node periodically (e.g., every 500 ms) broadcasts its RTK‑derived position via UDP (port 9876). This is consumed by neighbours to compute relative positions.
4.3 Security
- Encryption: Use
WPA3‑Personalwith a strong pre‑shared key (PSK) that is rotated automatically using a secure secret‑sharing scheme (e.g., a TOTP based on a shared seed). - 802.1X (optional): For higher security, deploy a RADIUS server (e.g., FreeRADIUS) on one of the seasteads and use certificates for each node.
- MAC ACL: Limit which MACs can associate with each AP (the directional radios should only accept a specific set of neighbour MACs).
- Firewall: iptables/nftables to block unwanted inbound traffic, but allow the mesh protocol, UDP broadcast of position, and necessary services (e.g., MQTT broker).
5. Data Structures & Protocols
5.1 Heartbeat / Watch Status
Every node publishes a Heartbeat message at 2 Hz. The payload is JSON:
{
"type": "heartbeat",
"nodeId": "SEASTEAD‑42",
"timestamp": "2026-01-25T14:32:01.123Z",
"position": { "x": 567.23, "y": 1024.89, "z": 0.0 }, // meters (RTK)
"heading": 45.6, // degrees true
"speed": 0.2, // m/s
"watchStatus": { "onWatch": true, "confirmBy": "operator1", "confirmTs": "..." },
"health": { "cpuTemp": 58.3, "batteryVoltage": 48.2 }
}
5.2 Grid‑Assignment Messages
{
"type": "gridAssign",
"assignedNode": "SEASTEAD‑42",
"targetPos": { "x": 580.0, "y": 1020.0 }, // assigned grid coordinate
"assignedBy": "SEASTEAD‑01",
"timestamp": "2026-01-25T14:32:05.000Z",
"ttl": 300 // seconds until the assignment expires
}
5.3 Object‑Tracking Database
Tracked objects are stored in a distributed CRDT‑based hash table (e.g., using libp2p’s Kademlia + a Grow‑only Set). Each entry:
{
"id": "OBJ‑00123",
"firstSeen": "2026-01-25T14:30:00Z",
"lastSeen": "2026-01-25T14:32:20Z",
"class": "ship",
"position": { "lat": 21.2345, "lon": -158.9876 },
"velocity": { "vEast": 2.5, "vNorth": 0.8 }, // m/s
"confidence": 0.93,
"observedBy": ["SEASTEAD‑01","SEASTEAD‑05"],
"observations": [ /* raw camera parallax data */ ]
}
All nodes append observations; the CRDT automatically merges concurrent updates.
6. Convoy‑Join Procedure (State Machine)
- Idle → Approach: The new seastead receives a “grid‑assignment” request (from a master node or from a pre‑configured static IP if no master exists). It sets its autopilot destination to the assigned coordinate and approaches from outside the convoy.
- Approach → Half‑Grid Inside: When the node’s RTK‑GPS shows that it is within
spacing/2of the target coordinate, it enters a “pre‑join” state. It continues to broadcast heartbeat, but also begins to listen for “convoy‑mode‑allowed” messages from neighbours. - Half‑Grid → Convoy‑Mode Activated: At least two neighbouring nodes must send a
convoyModeAckmessage confirming the node is within half‑grid and its heading matches the convoy’s average heading (within ±5°). The autopilot then locks onto the target coordinate and maintains it using the same control loop as other nodes. - Active → Leaving: A node can voluntarily leave by issuing a
convoyLeavebroadcast. The master (or any node) will update the grid occupancy map and, if needed, re‑assign the vacated spot.
7. Safety & Failsafes
- Communication loss: If a node does not receive a heartbeat from any neighbour for > 3 s, it reverts to “stand‑alone” mode, keeps last known position, and slowly drifts to a safe “parking” waypoint (e.g., 50 m away from the convoy).
- Collision avoidance: The autopilot continuously runs a simple “keep‑out‑zone” algorithm: each neighbour’s position is projected forward for 2 s; if the node would enter a 5 m radius around any neighbour, it applies a repulsive heading adjustment.
- Manual override: The on‑watch operator can trigger an “Emergency Stop” button that instantly disables thrusters and sets the node to “hold position” via the autopilot.
- Redundant radios: Install a second 5 GHz radio on a different channel; if the primary link fails, the secondary takes over within 1 s. Use the same SSID for seamless failover.
- Watch‑status integrity: A cryptographic signature (HMAC‑SHA256) is added to each heartbeat using a shared secret known to all nodes. A “watch‑confirm” field includes the operator’s digital certificate (or TOTP) to prove human presence.
8. Example Code – Node‑Join Handshake (JavaScript / Node.js)
/**
* Convoy node join state machine – simplified example
* Assumes: node has access to `network` (WebSocket or UDP), `autopilot`, `rtk`
*/
const MSG_TYPES = {
GRID_ASSIGN: 'gridAssign',
CONVOY_ACK: 'convoyAck',
HEARTBEAT: 'heartbeat',
CONVOY_LEAVE:'convoyLeave'
};
class ConvoyNode {
constructor(config) {
this.id = config.nodeId;
this.network = config.network; // abstraction of mesh socket
this.autopilot = config.autopilot;
this.rtk = config.rtk;
this.state = 'idle'; // idle | approach | preJoin | convoy | leave
this.targetPos = null; // {x, y}
this.gridSpacing = 30; // meters
this.heartbeatTimer = null;
this.listeners = [];
}
/** Start listening for convoy messages */
start() {
this.network.on('message', this.handleMsg.bind(this));
this.startHeartbeat();
this.state = 'idle';
}
/** Send a heartbeat every 500ms */
startHeartbeat() {
const tick = () => {
const msg = {
type: MSG_TYPES.HEARTBEAT,
nodeId: this.id,
timestamp: new Date().toISOString(),
position: this.rtk.position(), // {x, y, z}
heading: this.autopilot.heading(),
watchStatus: { onWatch: this.isOnWatch() }
};
this.network.broadcast(JSON.stringify(msg));
};
this.heartbeatTimer = setInterval(tick, 500);
}
/** Process inbound messages */
handleMsg(raw) {
let msg;
try { msg = JSON.parse(raw); } catch(e) { return; }
switch (msg.type) {
case MSG_TYPES.GRID_ASSIGN:
if (this.state === 'idle') {
this.targetPos = msg.targetPos;
this.state = 'approach';
this.autopilot.goTo(this.targetPos);
}
break;
case MSG_TYPES.CONVOY_ACK:
// Two ACKs required → transition to convoy
this.onAckReceived(msg);
break;
case MSG_TYPES.CONVOY_LEAVE:
this.handleLeave(msg);
break;
}
}
onAckReceived(ack) {
// Keep track of ACKs (at least 2 from different neighbours)
const ackKey = ack.fromNode;
if (!this.acks) this.acks = new Map();
this.acks.set(ackKey, ack);
if (this.acks.size >= 2 && this.state === 'approach') {
// Check distance to target
const dist = this.rtk.distanceTo(this.targetPos);
if (dist < this.gridSpacing / 2) {
this.state = 'convoy';
this.autopilot.lockPosition(this.targetPos);
// Notify neighbours we are in convoy mode
const notify = {
type: MSG_TYPES.CONVOY_ACK,
fromNode: this.id,
targetPos: this.targetPos,
timestamp: new Date().toISOString()
};
this.network.broadcast(JSON.stringify(notify));
}
}
}
/** Example of a human watch confirmation (simplified) */
isOnWatch() {
// In real code, query a UI button or biometric sensor
return this._watchOn;
}
confirmWatch(operatorId) {
this._watchOn = true;
this._operator = operatorId;
}
handleLeave(msg) {
this.state = 'leave';
this.autopilot.releasePosition();
this.network.broadcast(JSON.stringify({
type: MSG_TYPES.CONVOY_LEAVE,
nodeId: this.id,
timestamp: new Date().toISOString()
}));
}
}
This script can run on a lightweight SBC (e.g., Raspberry Pi) using Node.js. It communicates over a UDP socket that the underlying Linux bridge (batman‑adv) forwards to all mesh nodes.
9. Future Enhancements
- Directional laser links (free‑space optics) for inter‑convoy distances > 10 km, offering > 1 Gbps with no licensing.
- 5G NR / LTE‑Advanced as a fallback link, especially when within cellular coverage.
- AI‑based collision prediction using the shared object‑tracking database; a warning could be broadcast 30 s before a potential crossing.
- Dynamic grid spacing: the convoy could adjust spacing based on sea state, wind, or traffic density.
- Distributed ledger for logging all watch‑status confirmations and safety events, providing immutable auditability.
10. References & Resources
- OpenWrt – lightweight Linux for embedded devices.
- Batman‑adv – Layer‑2 mesh protocol.
- OLSRv2 – Optimized Link State Routing.
- libp2p – library for peer‑to‑peer networking (CRDT, Kademlia).
- Ubiquiti NanoStation 5AC – example Wi‑Fi radio.
- MikroTik mANT 5‑19 – directional antenna.
- RTK GPS for autonomous vessels – background on precision positioning.
- Convoy formation concepts – general reference.