Contact Plan Designer

Compute · Visualize · Design · Export

Scenario (YAML)

Selection

Add contact

Contact Plan Designer — help

License & credits

MIT — © 2026 Juan A. Fraire, Pablo G. Madoery, and contributors.

Juan A. Fraire — Inria — juanfraire@inria.fr
Pablo G. Madoery — Universidad Nacional de Córdoba — pablo.madoery@unc.edu.ar

What this tool does

A contact plan is the time-ordered list of communication opportunities between spacecraft, landers and ground stations. CPD computes those opportunities from orbital geometry and link constraints (range, antenna cone, elevation), then designs an applicable plan by resolving resource conflicts, and exports it to the DTN ecosystem (ION / HDTN) and the IPN-V 3D visualizer.

How it works (methods & assumptions)

Propagation. Orbits are advanced with analytic two-body (Keplerian) propagation. Every body and node is placed onto one fixed time grid by recursive frame composition into a single Sun-centered inertial frame, so a moon's orbiter inherits the moon's and planet's motion automatically.

Contact computation. At each time sample a contact is feasible when a composite condition holds: range within [min, max], elevation within limits at each endpoint, the target inside the antenna boresight cone, and a line of sight clear of every occluding body sphere. Landers use a horizon / elevation test instead of self-occlusion (their own body is excluded as an occluder). Windows are found on the fixed step, then each boundary is bisection-refined to sub-step (≈1 ms) precision.

Design. The raw topology may oversubscribe a node's interfaces; the FCP solver resolves this on a time-expanded graph by per-state max-weight matching, weighting starved links for fairness, to yield a conflict-free plan.

Design options. A terminal pointed at a peer is busy in both directions, and it keeps receiving for one OWLT after the transmit window closes. The second status badge counts the episodes where that tail overlaps the next booking of the same terminal: a plan can be conflict-free and still not be light-time clean. Book reception reserves the receiving terminal for that tail, which removes those episodes at the price of roughly one OWLT of idle time per hand-over (very short windows are lost entirely). Slice makes the solver re-decide at least that often, so competing links alternate within a long pass instead of one link holding all of it, and Min run commits a scheduled link to its terminals for at least that long (plus one OWLT with reception booked), so the solver never leaves hand-over slivers shorter than a terminal could realistically acquire and lock.

Assumptions to know. Geometric (T1) works from instantaneous (true) positions and takes OWLT = range / c. Apparent (T2) solves the light path for each direction and reports the resulting receive window. Aberration shifts pointing rather than feasibility and stays out of scope; relativistic (Shapiro) delays are recorded as a diagnostic and never applied to a window. Node inclinations and lander latitudes are expressed in the body's equatorial frame; body obliquity is carried for visualization but not applied to contact geometry. Contacts are unidirectional (ION-style): a full-duplex link emits one contact per direction, each carrying that transmitter's rate.

Quick start

  1. Describe the scenario. Click ✎ Build scenario… to design one with a guided form (no YAML needed), edit or paste YAML in the left pane, or use Import file…. The example scenario is pre-loaded.
  2. Load & Compute (or Ctrl+S / ⌘S from the editor). Propagates the orbits and determines the raw contact topology — drawn as the schematic and the timeline.
  3. Apply design. Pick a method (FCP) and run it to resolve oversubscription conflicts; the badge flips to conflict-free.
  4. Edit the timeline. Drag a contact to move it, drag its edges to crop, or use Razor, Split @▷, + Add contact and Delete selected. Conflicts re-evaluate live. Hide selected (or H) dims a contact and removes it from the 2D/3D views without changing the plan.
  5. Export the result with Export ION / HDTN / TVR / IPN-V, as STK-style access / AER CSVs (STK Access / STK AER), or as an Osmium emulator bundle (topology.yaml + contacts.yaml).

Scenario time is relative: everything is counted in seconds from t = 0. Add epoch: 2025-01-01T00:00:00Z (or epoch-s, POSIX seconds) to the scenario to tag that instant, and the playbars, the timeline playhead tooltip and every export show real dates. Without it the exports anchor t = 0 at 1970-01-01.

Bundled examples

The Examples menu lists ready-made scenarios: the earth_moon starter, a solar_system tour, the ESA CCSDS / DSNS validation reconstructions, the paper2 light-time study set, and the stint_demo pair from the STINT 2026 talk: a Leuven station with one LEO satellite, and DSN Madrid with two Mars relays and a rover, 20 minutes of light time apart.

The code02_* examples implement the IETF/IRTF constellation-code I-D (-02): code02_cislunar embeds a Walker shell with the draft's link-patterns (in-plane ring + staggered cross-plane ISLs) and its Charleroi ground station into a cislunar scenario, showing how the constellation code composes into an interplanetary one. code02_one_shell is the intermediate, Earth-only demo: one patterned shell of 120 satellites whose ground-station antenna conflicts the design stage resolves. code02_two_shell is the faithful replication of the draft's own two-shell example (452 satellites, 652 patterned ISLs); at that scale the browser views get heavy, so prefer the 2D and Statistics views. See examples/README.md in the repo for the full catalog.

Views

2D Static — a logical schematic (Sun → planets → moons → nodes) above the editable contact timeline.

Contact timeline — every bar is the transmit window on the sender's clock. The dashed reception rail under it, capped by a dot at each end, is the receive window: the first bit arrives one OWLT after transmission starts, the last one OWLT after it stops. The rail therefore overhangs the bar by one OWLT in either tier, and the coloured part of it is reception happening after the window has closed.

2D Dynamic — the same scenario with nodes at their real orbital phase; press ▶ to animate and watch links light up.

3D View — a CesiumJS globe-free scene of the same scenario, to scale: bodies and nodes at their real positions from CPD's own ephemeris, with contact links drawn live from the current plan. Scheduled links propagate at the speed of light: each contact lights up at the transmitter, sweeps across to the receiver one OWLT later, holds while transmitting, then drains transmitter-to-receiver, so you can see when reception begins and ends.

Each direction of a link rides its own lane, with chevrons pointing to the receiver (toggle Flow to turn this off).

Statistics — a read-only dashboard summarizing the scenario and the current contact plan: node/body counts, scheduled vs. dropped contacts, total contact-time and data volume, duration/rate/range/OWLT distributions, and per-category and per-node rollups. It tracks every design and timeline edit.

Tips

In the schematic and dynamic views: wheel = zoom, drag = pan, click = select (details show under Selection). In the 3D view: drag = orbit, wheel = zoom, double-click a body to follow it, and use the focus buttons (top-left of the scene) to center on a planet, the Moon, the nodes, or fit the whole system. The ▶ playhead and its speed are shared across all views, so the schematic, timeline, dynamic and 3D views all move together.

Transport keys: Space plays forward, Shift+Space backward (or use ▶ and ◀), → / ← jog by one second of playback at the current speed, and Shift+→ / Shift+← by ten; hold an arrow to scrub. H hides or shows the selected contacts, Delete removes them.

Code & contributing

CPD is open source. Browse the code, file issues, or contribute at gitlab.inria.fr/jfraire/contact-plan-designer.

Have you created a cool scenario? Send it to us so we can add it to the pre-loaded examples! Reach out at juanfraire@inria.fr.

Privacy

One essential session cookie; privacy-friendly first-party analytics (no third-party trackers, no raw IPs stored), with opt-out anytime. See the privacy policy to review or change your choice.