Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BLE Sensor Coverage Simulator

A browser-based tool for planning Bluetooth Low Energy (BLE) sensor deployments in real buildings. Load a 3D floor plan (GLB/GLTF), automatically detect rooms, and simulate RF coverage with physically-grounded propagation math. A greedy optimizer places the minimum number of sensors needed to hit a target coverage percentage.


Features

Feature Description
GLB/GLTF floor plan import Load any 3D building model; the tool rasterizes a top-down slice and detects rooms automatically
Manual floor plan Rectangle fallback when no 3D model is available
Room detection Binary morphology + run-length scan + BFS flood fill extracts individual rooms from the rendered floor plan
RF heatmap Log-distance path loss with per-wall attenuation; rendered at canvas resolution
Confidence overlay Probability that the actual received signal exceeds the target threshold, given shadow fading
Sensor placement modes Place, select, drag, and delete sensors interactively on the canvas
Wall drawing Draw axis-aligned walls with material-specific attenuation; erase walls by clicking them
Greedy optimizer Automatically places the fewest sensors needed to reach a user-defined coverage target
Multi-floor stub Data model supports multiple floors (UI expansion in progress)
Export Download sensor layout as JSON, CSV, or a rendered PNG

Getting Started

No build step. Open index.html directly in a modern browser (Chrome/Edge recommended for WebGL support).

open index.html

Or serve locally to avoid CORS issues with the Three.js CDN imports:

python3 -m http.server 8080
# → http://localhost:8080

RF Propagation Model

Log-Distance Path Loss

RSSI at a point p from a single sensor s is:

RSSI(p, s) = A  −  10·n·log₁₀(d)  −  WAF
Symbol Parameter Typical values
A Reference power at 1 m (dBm) −40 to −80 dBm
n Path-loss exponent 2 (free space), 2.5–3.5 (office), 4–6 (cluttered)
d 3D Euclidean distance in metres (clamped ≥ 0.3 m)
WAF Accumulated wall-attenuation factor along the ray see table below

When multiple sensors are deployed, each point takes the best (highest) RSSI across all sensors:

RSSI_best(p) = max over all sensors s { A − 10·n·log₁₀(d_s) − WAF_s }

Wall Attenuation Factors (WAF)

Each wall segment has a material. Every wall segment whose 2D line crosses the straight ray between a sensor and an evaluation point contributes its full attenuation:

Material Attenuation
Glass 2 dB
Drywall 3 dB
Brick 8 dB
Concrete 15 dB
Metal 25 dB

Ray–wall intersection uses the parametric cross-product test (Cramér's rule). An axis-aligned bounding-box pre-filter skips walls that cannot possibly intersect, keeping per-pixel cost sub-linear in wall count.

Shadow Fading and Coverage Confidence

Real-world BLE signals fluctuate around the path-loss mean due to multipath, body blocking, and environmental changes. The instantaneous RSSI is modelled as:

RSSI_actual ~ N(RSSI_mean, σ²)

The probability that the actual signal exceeds a threshold T is:

P(coverage | p) = Φ( (RSSI_mean − T) / σ )

where Φ is the standard normal CDF, approximated with the Abramowitz & Stegun polynomial (error < 7.5 × 10⁻⁸):

Φ(z) = 1 − φ(z)·t·(a₁ + t(a₂ + t(a₃ + t(a₄ + t·a₅))))
t = 1 / (1 + 0.2316419·|z|)
φ(z) = (1/√2π)·e^(−z²/2)
a = [0.3193815, −0.3565638, 1.7814779, −1.8212560, 1.3302744]
Parameter Description Default
T Target RSSI threshold −85 dBm
σ Shadow-fading standard deviation 7 dB

The mean coverage metric is the area-weighted mean of P(coverage) across all evaluation pixels.

Human Traffic Attenuation

A "Human Traffic" slider (0–100 %) scales additional body-blocking attenuation on top of the base path-loss model, simulating the effect of people moving through the space.


Room Detection Pipeline

When a GLB file is loaded, the following pipeline runs entirely in the browser:

1. Orthographic Rasterization

Three.js renders the 3D scene top-down using an OrthographicCamera at resolution 1024 × H (H derived from the model's XZ aspect ratio). Clipping planes restrict rendering to the 15%–85% height band of the model, isolating the structural floor slice and excluding furniture or ceiling geometry.

2. Binary Thresholding

The alpha channel of the rendered canvas is thresholded at α > 30, producing a binary occupancy map where 1 = wall/structure pixel.

3. Morphological Dilation (×2)

Two passes of 4-connectivity dilation close sub-pixel gaps in walls:

out[x,y] = src[x,y] OR src[x±1,y] OR src[x,y±1]

Applied twice to bridge wall segments that were slightly separated in the render.

4. Run-Length Wall Extraction

Horizontal and vertical runs of consecutive 1 pixels are collected. Runs shorter than max(6, 1.5% of canvas min-dimension) are discarded (short noise artefacts).

5. Collinear Segment Merging

Parallel runs within 6 px of each other (same row/column) are grouped. Within each group, segments separated by ≤ 10 px are joined into a single segment.

6. Virtual Wall Completion

Wall endpoints that do not meet a junction shoot a perpendicular ray (up to 35% of canvas). If the ray hits another wall, a virtual closing segment is inserted. These appear as dashed magenta lines in the UI.

7. BFS Flood Fill

A BFS flood fill labels every non-wall connected region. Each region accumulates bounding box, area (px²), and an touchesEdge flag.

8. Room Filtering

  • The largest edge-touching region is identified as exterior space and discarded.
  • All other edge-touching regions are retained (they are rooms against outer walls).
  • Regions with area < max(50, 0.05% × canvas area) are discarded as noise.

The output is a Uint16Array room mask (room ID per pixel) and an array of room descriptors { id, minX, maxX, minY, maxY, area }.


Greedy Coverage Optimizer

The optimizer finds the minimum-sensor placement that achieves a target mean coverage probability.

Algorithm

  1. Candidate grid — every 2 px walkable pixel (inside the room mask) is a candidate sensor location.
  2. Evaluation grid — every 4 px walkable pixel is an evaluation point.
  3. Locked-sensor seed — pre-compute bestRSSI[i] for each evaluation point from any manually-placed sensors.
  4. Greedy loop — repeat until coverage ≥ target or sensor budget exhausted:
    • For each candidate, count how many currently-uncovered evaluation points it would bring above the coverage threshold (P(coverage) ≥ 0.5).
    • Place the candidate with the highest marginal gain.
    • Update bestRSSI[i] with the newly placed sensor's contribution.
    • Remove the chosen candidate from the pool.

The coverage threshold inside the optimizer uses P(coverage | rssi) ≥ 0.5, i.e., the median signal-quality criterion. The outer meanCoverage panel metric uses the full continuous probability integral.

Complexity

Each greedy iteration is O(C × E) where C = candidate count and E = evaluation-point count. For a 1024 × 1024 canvas with a dense floor plan, C ≈ 250k and E ≈ 65k. In practice the loop terminates quickly (< 20 sensors for typical rooms) so wall-time is under a second for most buildings.


Wall Store

Walls are stored in metre coordinates. Three source types coexist:

Source Color in UI Description
detected Cyan, solid Extracted automatically from the GLB rasterization
virtual Magenta, dashed Inferred closing segments from the virtual-wall pass
manual Yellow, solid Drawn interactively by the user

Ray–segment intersection uses the parametric form with a 1 × 10⁻⁶ endpoint exclusion tolerance so sensor-at-wall-endpoint cases do not double-count the wall.


Module Architecture

index.html          Entry point, importmap, UI layout
js/
  rf-engine.js      Log-distance RSSI, shadow-fading CDF, field rasterizer
  wall-store.js     Wall segment store, WAF lookup, ray–segment intersection
  room-detector.js  GLB loader, morphology, flood fill, room extraction
  optimizer.js      Greedy coverage-maximization sensor placement
  renderer.js       Canvas compositing (GLB layer + heatmap + walls)
  ui.js             Event wiring, canvas interaction, mode state machine
tests/
  test-rf-engine.mjs
  test-wall-store.mjs
  test-room-detector.mjs
  test-optimizer.mjs

All pure functions in rf-engine.js, wall-store.js, room-detector.js, and optimizer.js are importable in Node.js for unit testing. Browser-only code (WebGL renderer, Three.js GLTFLoader) is isolated behind async factory functions.

Running Tests

node tests/test-rf-engine.mjs
node tests/test-wall-store.mjs
node tests/test-room-detector.mjs
node tests/test-optimizer.mjs

Export Formats

Format Contents
JSON { sensors, walls, state } — full simulation state
CSV One row per sensor: id, x_m, y_m, floor, manual
PNG Current canvas frame (heatmap + floor plan + sensors) at screen resolution

Dependencies

  • Three.js r160 — GLB loading and WebGL rasterization (CDN, no install)
  • Vanilla JS ES modules — no bundler required

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages