Scope: A precise statement of the hidden-node problem for LoRa mesh, the LoRa-specific
physics that make it hard, quantification of its severity, and an evaluation of candidate
solutions. This document is the problem statement that mac-layer-options.md then turns into
an airtime budget for each MAC approach. It is the central technical challenge named in the
project brief.
Three nodes: A, B, R. A and B can both reach R, but A and B cannot hear each other. A and B are hidden from one another behind R.
Any carrier-sense scheme works by listening before transmitting. But A listening finds the channel clear with respect to what A can hear — and A cannot hear B. So A and B can both sense "clear" and transmit at overlapping times. Their signals collide at R, and (absent a large power difference — see §2.3 capture) both packets are lost. Neither A nor B can detect this: they hear only their own transmission, and a missing acknowledgement is the only (delayed, ambiguous) symptom.
This is not a corner case for Loomwave — it is the expected operating regime, because of the architecture the brief mandates:
"INFRA nodes at elevation can hear many clients that cannot hear each other."
An elevated INFRA/REPEATER node is, by design, a node that maximises the hidden-node population: it is placed precisely so that many clients who cannot hear each other can all hear it. The very thing that makes an elevated relay useful is the thing that makes the hidden-node problem dominate. Adding a high-site relay to a naïve CSMA mesh can increase collisions, because it gathers together transmitters that would otherwise never have contended. This is consistent with the documented community failure reports of "Meshtastic at scale" once a high relay is introduced.
LoRa radios (SX127x/SX126x/LR11xx) are half-duplex: while transmitting, the radio cannot receive. So a node has zero awareness of the channel during its own (long) transmission. Collision detection (CSMA/CD, as in wired Ethernet) is physically impossible; only collision avoidance (CSMA/CA) is available, and avoidance fails for hidden nodes by definition.
The probability of a hidden-node collision scales with how long a packet occupies the channel. In unslotted ALOHA, a packet is vulnerable for 2× its airtime (a colliding transmission can start any time from one airtime before to one airtime after). LoRa airtimes (Meshtastic LongFast, SF11/BW250, 16-symbol preamble, CR4/5):
| Payload | Airtime | 2× vulnerability window |
|---|---|---|
| 16 B | 354 ms | 708 ms |
| 32 B | 477 ms | 954 ms |
| 64 B | 723 ms | 1446 ms |
| 237 B | 2034 ms | 4068 ms |
Compare Wi-Fi, where a frame is tens of microseconds. A LoRa node sits exposed ~10⁴× longer per packet. The hidden-node collision probability is correspondingly enormous.
LoRa can sometimes capture the stronger of two overlapping signals if it arrives first and is ≥ ~6 dB stronger (co-SF) — the weaker is treated as noise and the strong one survives. This helps an elevated node that hears one client much louder than another, but it is asymmetric and unreliable: it cannot be designed around, it silently starves the weaker (often more distant, more important) node, and it disappears when powers are comparable. We treat capture as occasional luck, not a mechanism.
Different spreading factors are quasi-orthogonal, so same-SF collisions are the dominant concern. But a Loomwave network must interoperate on a common SF for the mesh to connect; SF diversity is a frequency/diversity planning tool for INFRA (the brief asks us to evaluate multi-radio INFRA), not a per-packet collision solution for a single logical channel.
EU 868 limits a node to ≤1% (or 10% on some sub-bands; Meshtastic uses 10% for routers). When a hidden-node collision forces a retransmission, the retransmit competes with the duty-cycle budget — so collisions don't just cost airtime, they consume the node's regulatory allowance, throttling legitimate traffic. In the US (no hard duty limit) the constraint is softer, but FHSS / dwell-time rules still bound long packets.
Model the canonical case: an elevated INFRA node hears K clients that are mutually hidden,
each transmitting 1 packet per period. Treat arrivals at the INFRA receiver as
independent (the worst case — no coordination). Unslotted-ALOHA survival probability of a
given packet is P = e^(−2·λ·T), where λ = K/period is the aggregate arrival rate at the
receiver and T is the packet airtime (0.477 s for a 32 B LongFast packet).
| K (hidden clients) | period | aggregate pkts/s | P(delivered) | collision loss |
|---|---|---|---|---|
| 5 | 60 s | 0.083 | 0.924 | 7.6% |
| 10 | 60 s | 0.167 | 0.853 | 14.7% |
| 20 | 60 s | 0.333 | 0.728 | 27.2% |
| 50 | 60 s | 0.833 | 0.452 | 54.8% |
| 100 | 60 s | 1.667 | 0.204 | 79.6% |
| 50 | 300 s | 0.167 | 0.853 | 14.7% |
| 100 | 300 s | 0.333 | 0.728 | 27.2% |
Reading: with 20 mutually-hidden clients each sending once a minute, >27% of packets are lost to collision at the shared INFRA node before any routing, flooding amplification, or retransmission storms are considered. At the dense-event scale (100 clients), a naïve CSMA mesh loses ~80% of packets to hidden-node collisions at 1 msg/min. Slowing to one message every 5 minutes only buys back roughly one severity tier. This is the failure mode that caps every flood-based system well below the brief's 500-node target, and it is the quantitative justification for moving away from pure CSMA.
(These are loss rates at a single receiver from hidden peers. They compound with the N²
flooding load from meshtastic-routing-analysis.md §8.1 — flooding both adds more
transmitters and makes each retransmission another exposure.)
The textbook hidden-node solution is RTS/CTS: A sends a short Request-To-Send; R replies with Clear-To-Send, which B can hear (B hears R); B now defers. This converts the hidden node into an exposed one.
On LoRa it is unaffordable. RTS and CTS are themselves packets with full preamble + headers (~12–16 B minimum), so each costs roughly a minimum-size airtime:
| Preset | RTS+CTS airtime | data airtime | control overhead of the exchange |
|---|---|---|---|
| LongFast | 708 ms | 477 ms | 60% |
| MediumFast | 198 ms | 140 ms | 59% |
| ShortFast | 60 ms | 40 ms | 60% |
A two-way handshake before every data packet spends ~60% of the exchange's airtime on control and triples the number of transmissions on the channel — which, with long LoRa airtimes, increases total contention. RTS/CTS is rejected for Loomwave data traffic (confirming the brief's prompt to "evaluate alternatives"). It might survive only as a rare, reservation-style mechanism for unusually large transfers, not the common path.
For each, the question is: does it actually break the hidden-node mechanism (transmitters
coordinating despite not hearing each other), and at what airtime cost? Detailed airtime
budgets are in mac-layer-options.md; this section is the qualitative verdict.
meshtastic-routing-analysis.md §4, MeshCore
calcRxDelay §6).mac-layer-options.md.reticulum-routing-analysis.md).mac-layer-options.md and routing-options.md.mac-layer-options.md)Severity and cost figures use the LoRa airtime model verified against Meshtastic's
implementation (RadioInterface.cpp:getPacketTime:615 → RadioLib getTimeOnAir; slot model
computeSlotTimeMsec:1172) and the modem-preset table (MeshRadio.h:modemPresetToParams,
LongFast = SF11/BW250/CR4-5, 16-symbol preamble). The "elevated relay increases hidden-node
contention" claim follows directly from Meshtastic's CSMA-only design
(meshtastic-routing-analysis.md §9) and MeshCore's CAD-only Dispatcher
(meshcore-routing-analysis.md §8). The ALOHA e^(−2λT) model is the standard unslotted
result; the TDMA "collisions→0 by construction" claim is definitional given non-overlapping
slots and adequate guard time.