A constellation is a moving set of possible connections. Orbital propagation supplies positions, but a network simulation must also decide which positions can connect, what route to select, and what its reported latency represents.

The orbital tools in tsim divide that work among satviz, the entity backend, and grayscale. They share globe rendering through WGFX, while propagation, ingestion, and graph construction run independently of the display.

Three Tools, Three Responsibilities

Tool Primary responsibility
satviz Propagate and inspect a TLE catalog or generated constellation
backend Ingest and advance satellite, aircraft, and ship sources; serve HTTP/WebSocket data and DIS truth
grayscale Display combined entities, assign aircraft connections, and explore constellation routes

tview is the separate tactical viewer for DIS truth, sensor reports, and scenario editing. Its sensor-fusion displays answer a different question from Grayscale’s constellation route view.

From TLEs to Earth-Fixed Positions

The propagator accepts a TLE catalog or generated constellation parameters. SGP4 advances each orbit to the requested time. The result is converted to geodetic latitude, longitude, and altitude, then to Earth-fixed Cartesian arrays used by rendering and network geometry.

graph LR
    catalog["TLE catalog or constellation parameters"] --> sgp4["SGP4 at simulation time"]
    sgp4 --> llh["Geodetic position"]
    llh --> ecef["ECEF arrays in kilometres"]
    ecef --> globe["Globe rendering"]
    ecef --> neighbors["Nearest-neighbor graph"]
    neighbors --> route["Aircraft-to-aircraft route"]

The orbital arrays use kilometres, while DIS entity positions and the flight model use metres. Conversion at those boundaries is essential. The propagator’s optional velocity output uses a finite difference over a 100 ms interval in Earth-fixed coordinates.

Taskflow distributes independent orbit propagation across workers. Invalid or decayed entries receive a zero-position sentinel; neighbor searches exclude those entries instead of allowing a satellite at Earth’s center to enter the graph.

A generated constellation is useful for changing plane count, satellites per plane, altitude, inclination, and staggering in a controlled experiment. A TLE catalog instead represents particular orbital elements at their recorded epochs. Neither input makes a preset a reconstruction of an operator’s current fleet or network configuration.

The implementation is in the propagator.

A Graph Built from Moving Geometry

The dynamic nearest-neighbor network searches the position arrays for each satellite’s closest candidates. It constructs an undirected graph with distance-weighted edges and removes duplicate edge pairs. Neighbor selection and vertex creation can run independently; edge construction waits for both.

Because the graph is undirected, another satellite selecting a node can add to that node’s connections. The configured neighbor order is therefore a selection count, not a guarantee that every node has exactly that final graph degree.

Graph work runs asynchronously. The renderer can keep displaying the completed state while a new one is being computed, then take ownership of the finished network buffer. Passing ownership avoids copying an entire graph merely to exchange the working and displayed states.

Changing orbital geometry can change both edge lengths and selected neighbors. A path that was short on one update can become longer or disappear on another. Simulation time, graph refresh, and display frame rate consequently describe different rates of change.

The nearest-neighbor graph is a geometry model. It does not by itself enforce a complete inter-satellite RF link budget, terminal pointing model, or physical visibility policy. Those constraints would need to participate in edge eligibility to make stronger connectivity claims.

Connecting Aircraft to Satellites

Grayscale assigns aircraft to nearby eligible satellites using a maximum zenith angle and a per-satellite connection limit. A candidate outside the allowed angle is rejected; a satellite already at capacity cannot accept another connection. Capacity reservation uses atomic counters because aircraft assignment runs in parallel.

These controls expose two different coverage problems. Tightening the zenith angle limits which satellites can serve an aircraft. Lowering the connection cap can leave an aircraft unconnected even when geometrically eligible satellites are visible.

The viewer reports connected and unconnected aircraft, draws uplinks, and lets selected aircraft define route endpoints. Their assigned satellites become the start and end of the inter-satellite route.

Grayscale showing constellation edges, aircraft connections, and a selected route
Grayscale showing constellation edges, aircraft connections, and a selected route

The routing implementation calls A* with a zero heuristic. With nonnegative distance weights, this acts as Dijkstra’s shortest-path search: it finds the minimum-distance route through the available graph without a heuristic guiding exploration.

That route minimizes geometric distance. It does not optimize measured queue delay, congestion, RF quality, or file-delivery success. See the graph implementation and aircraft network controller for the current selection and routing policies.

What the Latency Number Includes

The path latency model adds two terms:

latency_ms = sum(inter_satellite_edge_length_km) / 299.792458
           + sum(sampled_node_delay_us) * 0.001

Here, 299.792458 is the speed of light in kilometres per millisecond. A 3,000 km inter-satellite path contributes approximately 10.01 ms of propagation delay before node processing.

Each route node receives a stochastic delay based on a gamma distribution, with a 250 µs floor. If a sampled node delay exceeds 1,850 µs, the model returns a drop sentinel rather than a normal latency. This is a synthetic processing/drop model, not a queue simulation driven by packet arrivals.

The displayed path can include the aircraft-to-satellite legs, but the current latency calculation receives the inter-satellite path. Aircraft uplink and downlink propagation are not included in that reported value. Interpreting it as complete aircraft-to-aircraft application latency would therefore overstate what is measured.

Latency history and hop-count plots help compare routes under this model. Actual decoded packet and file delivery is explored separately in the iqradio article.

Entity Sources and Reproducible Time

The backend ingests satellite catalogs and aircraft/ship data, advances the sources, and supplies viewers over HTTP/WebSockets and DIS. Source preparation can include downloads and cache loading, so startup readiness is separate from steady-state frame health.

Cached data and explicit simulation dates help make a run repeatable. A view can use a recorded source date rather than silently assuming it represents present-day traffic. Staged downloads and completion checks also matter: partially written source files should not replace a usable cache.

This distinction carries over to weather. Availability is tied to source date and UTC slice, rather than to the rate at which a viewer redraws Earth.

Weather as Data and as a Display

The globe weather controller loads GRIB2 rasters through GDAL and displays one selected field at a time. Presets include total and layered cloud cover, temperature, pressure, humidity, precipitation rate, composite reflectivity, and wind. Isobaric fields expose available pressure levels.

Raster values carry units and a valid-data mask. Color scale, opacity, field selection, and pressure level control the display. Changing the palette does not change the underlying weather data.

Global cloud-cover field displayed on the tactical globe
Global cloud-cover field displayed on the tactical globe

The source uses four six-hour UTC slices per date. The default date is the prior local day; a date override selects a specific replay dataset. The backend can prefetch the slices, while viewer field loading is asynchronous and requested through the weather controls.

The weather HTTP source is configurable, and its default is a local deployment address. A fresh checkout therefore needs a reachable data service or the appropriate cache to load these fields. For example, with a compatible local service:

./build/dist/bin/satviz --like starlink \
  --weather-date 2026-10-09 \
  --weather-base-url "http://localhost:9769/ncep"

The weather controller defines the fields and configuration. The flight weather sampler consumes physical atmospheric fields independently of rendering. A visible overlay is not, by itself, an enabled coupling to every RF or sensor model.

Run an Orbital Experiment

After the shared build steps, start with a preset:

./build/dist/bin/satviz --like starlink -t 4 -r 60

Or define a smaller constellation explicitly:

./build/dist/bin/satviz \
  --planes 12 --sats-per-plane 24 \
  --altitude 550 --inclination 53 --phase-shift 7.5 \
  -t 4 -r 60

Altitude is in kilometres; inclination and phase shift are in degrees. Use --input for a TLE file and --log for Parquet output. Grayscale uses the backend for combined entity sources; the main Process Compose group includes that backend alongside the tactical tools.

A useful experiment changes one policy at a time: constellation geometry, nearest-neighbor selection, zenith limit, or connection capacity. Inspect connectivity and route length before attributing a latency change to processing delay. The application guide covers the executable options, while the linked implementations specify the current model boundaries.

Return to the tsim overview, or continue with sensor fusion and waveform-based radio communication.