OpenWorld Radio Twin

Authors: TBD
Affiliations: TBD
Under review · Code released under Apache 2.0
OpenWorld Radio Twin explorer over central Boston with a Sionna RT received-power map draped onto the 3D scene
Central Boston in the interactive explorer: three transmitters, 2,973 Overture buildings, and a 750 m Sionna RT received-power map blended into its 3D context. Downloads keep the exact solver cells and raw linear arrays.

Only the import changes

A geographic scene loads like a Sionna file scene. The returned object is a native sionna.rt.Scene; arrays, radio devices, solvers, radio maps, rendering and preview stay the upstream API.

# Sionna file scene
from sionna.rt import load_scene
scene = load_scene(filename)

# Geographic scene: same call, WGS84 coordinates
from openworld_radio_twin.rt import load_scene
scene = load_scene(latitude=52.3762, longitude=4.8993, radius_m=250)

From a point on the globe to a Sionna scene

Four environmental layers from open geodata, compiled into one metric frame with the receiver surface and the radio outputs.

Building parts, terrain and semantic surfaces compiled into one native Sionna scene
1

Compile

Buildings from Overture and OpenStreetMap worldwide, or from 3DBAG, Berlin LoD2 and Boston BPDA models by region; bare-earth terrain from USGS 3DEP or Mapzen; water levelled per component; ground, vegetation, paved and water classes with ITU material proxies.

2

Simulate

The scene is plain Mitsuba XML and PLY. Sionna RT solves radio maps on a terrain-following measurement surface and channel responses with PathSolver. The explorer places transmitters inside the compiled scene and drapes the result on its terrain; a CPU preview shares the same output contract.

3

Generate

One scene expands into seeded cases with per-case transmitter layouts and solver settings. Datasets resume after interruption, extend deterministically, and record the source, release and resolution behind every array.

What each layer changes

Controlled comparisons on the same scene, transmitter and seed. Only one layer changes at a time.

Exported products from one Boston run

Path gain export
Path gain (dB)
Received signal strength export
Received power (dBm)
SINR export
SINR (dB)
Transmitter association export
Transmitter association
Receiver-height voxel occupancy slice
Receiver-height voxel slice
Maximum occupied voxel elevation preview
Voxel z-depth preview

One 1,500 m × 1,500 m scene, one 3.5 GHz sector transmitter, 1 m cells, 1.5 m receiver plane. PNGs keep one pixel per solver cell with transparent no-data; raw arrays ship alongside.

Features

Continuous globe

A CesiumJS world with display terrain everywhere. Drag a diagonal to define a scene; the compiled scene replaces the globe inside its square, with its own terrain, surfaces and buildings, and transmitters are placed inside it.

Buildings at source detail

Overture and OSM extrusions worldwide; native LoD2 roofs from 3DBAG, Berlin and Boston selected automatically by location, or by explicit ID.

Auditable terrain

Bare-earth DEMs from USGS 3DEP and Mapzen Skadi with source, model and local elevation arrays kept apart; water levelled and recorded.

Semantic surfaces

Non-overlapping ground, vegetation, paved and water meshes with documented ITU material proxies, each switchable at solve time.

Sionna-native

Terrain-following measurement surfaces, native propagation controls, path solvers and rendering on the same scene. The CPU preview shares the same output contract.

Reproducible datasets

Seeded expansion with PCG64, per-case provenance, resume after interruption, deterministic extension, and selective artifacts.

Get started

# install
git clone https://github.com/zhiheng-yang/openworld-radio-twin.git
cd openworld-radio-twin
./scripts/setup.sh
conda activate owrt

# interactive explorer
./scripts/run.sh          # http://127.0.0.1:8765

# compile a reusable scene
owrt scene compile --lat 52.3762 --lon 4.8993 --radius 250 --output scenes/amsterdam
from openworld_radio_twin import rt as owrt
from sionna.rt import PlanarArray, RadioMapSolver, Transmitter

scene = owrt.load_scene(latitude=52.3762, longitude=4.8993, radius_m=250)
scene.tx_array = PlanarArray(num_rows=1, num_cols=1, pattern="iso", polarization="V")
scene.rx_array = PlanarArray(num_rows=1, num_cols=1, pattern="iso", polarization="V")
scene.add(Transmitter(name="tx", position=owrt.position(
    scene, latitude=52.3770, longitude=4.9003, height_agl=25.0)))

radio_map = RadioMapSolver()(
    scene, measurement_surface=owrt.measurement_surface(scene, cell_size=(5.0, 5.0)))

Read the quickstart

BibTeX

@software{yang2026openworldradiotwin,
  author  = {Zhiheng Yang},
  title   = {OpenWorld Radio Twin: Interactive World-Scale Wireless Digital Twins},
  year    = {2026},
  version = {0.2.1},
  url     = {https://github.com/zhiheng-yang/openworld-radio-twin},
  license = {Apache-2.0}
}