You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

7.5 KiB

Adaptive Routing Simulation — Design & Results

Overview

This document describes the ADAPTIVE routing strategy added to the MeshCore simulation harness, including the density estimator, hash-based relay selection, relay suppression, and adaptive TX power saving. Empirical validation results across all scenario types are summarised below.


1. Density Estimator (DensityEstimator.h)

Passive, protocol-free neighbour density measurement. Each node counts how many unique direct senders it hears within a 60-second rolling window. Only hop_count==1 packets are counted (direct neighbours only — relays don't inflate the estimate).

Threshold Tier Default value
≤ DENSITY_SPARSE_MAX SPARSE ≤ 4 neighbours
≥ DENSITY_DENSE_MIN DENSE ≥ 15 neighbours
Between MEDIUM

All thresholds are compile-time overridable (-DDENSITY_WINDOW_MS=30000, etc.).

Implementation note: Uses std::unordered_set<uint32_t> for unique-sender counting, eliminating the former fixed-array cap at 64 neighbours.


2. Hash-Based Relay Gate

In ADAPTIVE mode, only a deterministic subset of nodes relay each flood. Selection is based on a hash of the packet content XOR a per-node seed:

selected = hash(packet_seed XOR node_seed) % 100 < relay_pct
  • packet_seed: first 4 bytes of packet payload (stable across all recipients of the same flood)
  • node_seed: per-node constant — node_idx × 0x9e3779b9 (in sim); firmware uses pub-key prefix

This is zero-coordination: every node independently makes the same relay/suppress decision for a given packet without any signalling. Different packets select different relay subsets, providing stochastic load balancing.

Relay percentages by density tier

Tier Relay % Rationale
SPARSE 100% Every relay counts; no redundancy to spare
MEDIUM 25% Enough redundancy to survive single relay failure
DENSE 15% Flood reaches all neighbours with 7–8 relayers in FM50; collisions reduced ≈ 60–70% vs DEFAULT

These were derived empirically from scenario_relay_pct_sweep across FM50, FM100, Chain20, Grid5×5 topologies.


3. Relay Suppression

After transmitting or scheduling a relay, if a node overhears another node already successfully relaying the same flood (matched by packet hash), it cancels its own queued outbound. This catches the edge case where two ADAPTIVE-selected relays race.

Implemented in SimNode::logRx() via _mgr_ref.removeOutboundByIdx().


4. Routing Strategies

Four strategies are available via RoutingStrategy enum in RoutingStrategies.h:

Strategy Description
DEFAULT Stock MeshCore: random backoff 0–5× base airtime. All nodes relay.
SNR_WEIGHTED Nodes with better SNR relay sooner (lower backoff).
PATH_SNR_HYBRID SNR-weighted backoff scaled by hop count — far nodes deprioritised.
ADAPTIVE Hash-gate + density-aware relay pct + relay suppression.

The ADAPTIVE strategy is the primary contribution. It matches or exceeds DEFAULT delivery rate while reducing total airtime by 60–70% in dense topologies.


5. Adaptive TX Power Saving

When power_save_enabled = true, ADAPTIVE-mode nodes reduce their transmit power based on current density tier:

Tier Default TX power Example setting TX current (SX1262)
SPARSE 20 dBm (full) 20 dBm 120 mA
MEDIUM configurable 14 dBm 45 mA
DENSE configurable 10 dBm 25 mA

TX power affects received SNR at all neighbours via a linear offset: received_snr += (tx_power_dbm - 20.0).

Capture effect: reducing TX power in dense areas shrinks the interference radius — nearby nodes still receive well above LoRa sensitivity, while the node no longer stomps on distant clusters. The LoRa capture effect (6 dB threshold in SimRadio) means the stronger local signal always wins over a distant weaker interferer.

Battery model (SX1262 typical)

tx_energy_mah = txCurrentMa(dbm) × airtime_s / 3600
rx_energy_mah = 5.5 mA × airtime_s / 3600

TX current lookup (txCurrentMa()):

  • ≥ 20 dBm → 120 mA
  • ≥ 17 dBm → 90 mA
  • ≥ 14 dBm → 45 mA
  • ≥ 10 dBm → 25 mA
  • < 10 dBm → 15 mA

6. Empirical Results

6a. ADAPTIVE vs DEFAULT (FM50, SNR=8dB)

Metric DEFAULT ADAPTIVE
Delivery rate 100% 100%
Total TX packets ~2500 ~450
Collisions ~800 ~120
Airtime reduction ≈ 65%

6b. TX Power Saving (FM50, ADAPTIVE, 20 floods)

Mode Dense dBm Med dBm Delivery Energy saving vs FULL
FULL_PWR 20 20 100%
CONSERV 14 17 100% ≈ 20%
MODERATE 10 14 100% ≈ 35%
AGGRESSIVE 7 10 100% ≈ 45%

TX power reduction does not hurt delivery in full-mesh or dense positional cluster topologies. Chain topologies (sparse by nature) stay at full power (SPARSE tier = 100% relay, full power always).

6c. Long chain (20 hops, SNR=6dB)

PATH_SNR_HYBRID outperforms DEFAULT on marginal multi-hop links (+5–8% DR). ADAPTIVE matches DEFAULT on chains because density stays SPARSE throughout — no relay suppression, all nodes relay at full power.

6d. Duty cycle enforcement

At 1% EU duty cycle (duty_cycle_factor=99), ADAPTIVE requires ≈ 40% fewer TX slots than DEFAULT, providing significantly more headroom before the duty cycle budget is exhausted.

6e. Legacy compatibility (mixed firmware)

Legacy nodes (DEFAULT strategy) interoperate fully. ADAPTIVE nodes relay legacy floods with the same hash gate. Legacy nodes relay ADAPTIVE-originated floods without suppression (they simply forward everything), which provides additional redundancy — no delivery regression observed.


7. Festival Weekend Battery Estimate

Assumptions: 50-node full-mesh, 1 flood/30s, SF8 BW62.5, SX1262, 2000 mAh battery.

Mode TX mAh/hr RX mAh/hr Radio total Est. hours (radio only)
FULL_PWR 0.373 0.114 0.487 ~4100 hrs
MODERATE 0.078 0.114 0.192 ~10400 hrs
AGGRESSIVE 0.046 0.114 0.160 ~12500 hrs

Note: MCU idle current (~10–30 mA continuous) dominates in practice, adding ≈ 9.6 mAh/hr at 20 mA. On a 2000 mAh battery this limits runtime to ≈ 100–130 hours regardless of radio power level. TX power reduction remains valuable for: peak current management, heat reduction, and lowering the area RF noise floor during high-density events.


8. Configuration Reference

// SimNode fields (set after addNode(), before run())
node->routing_strategy      = RoutingStrategy::ADAPTIVE;
node->power_save_enabled    = true;
node->power_save_dense_dbm  = 10.0f;   // TX power in DENSE tier
node->power_save_medium_dbm = 14.0f;   // TX power in MEDIUM tier
node->full_power_dbm        = 20.0f;   // TX power in SPARSE tier (and non-ADAPTIVE)
node->duty_cycle_factor     = 99.0f;   // EU 1% duty cycle
node->p_forward             = 1.0f;    // manual relay probability (non-ADAPTIVE only)

Compile-time density thresholds (set in CMakeLists.txt or via -D flags):

DENSITY_WINDOW_MS    (default: 60000)
DENSITY_SPARSE_MAX   (default: 4)
DENSITY_DENSE_MIN    (default: 15)