Skip to Content
GuidesDesigningSynthesize from requirements

Synthesize from requirements

What you will accomplish

You will turn a mission requirement into a candidate constellation, and then discover that the solver’s own verification was not enough to trust it.

The verification step is the point of this guide. It is also the step people skip.

Prerequisites

  • Installation complete.
  • A sense of which ground sites the mission must serve.

Steps

Write the requirement

State the sites and the verification window. Everything else has a default.

{ "name": "europe-broadband", "start": "2026-01-01T00:00:00Z", "verification_hours": 6.0, "step_seconds": 120.0, "stations": [ { "id": "madrid", "name": "Madrid", "latitude_deg": 40.43, "longitude_deg": -3.7, "altitude_km": 0.6 }, { "id": "stockholm", "name": "Stockholm", "latitude_deg": 59.33, "longitude_deg": 18.07, "altitude_km": 0.02 } ] }

Solve

orbitforge design \ --requirements req.json \ --output d.json \ --constellation designed.json
Design 'europe-broadband': Feasible. Recommended: 16 satellites (Star, 4 planes x 4 per plane, 1238 km, 59.0 deg). worst-case round-trip latency: 22.3 ms; global min fold: 1; latency margin: inf ms. verified 518 candidates across 50 geometries. Wrote design report -> d.json Wrote recommended constellation -> designed.json

The solver chose 1238 km, 59.0 degrees, and a Star pattern. Nothing in the request named any of those. 59.0 degrees is just enough to reach Stockholm at 59.33; the altitude is high because fewer satellites is what the default objective rewards.

Verify against the requirement you actually stated

Do not stop at “Feasible”. Re-run the check yourself, over a longer window and a finer step than the solver used:

orbitforge link \ --constellation designed.json \ --station "Madrid,40.43,-3.7,0.6" \ --station "Stockholm,59.33,18.07,0.02" \ --frequency-ghz 12 --availability 99.9 --climate-zone K \ --duration-hours 24
Link analysis: 16 satellites, 2 stations, 24.0 h at 60 s (12.0 GHz). madrid: coverage 74.3%, 110 contacts, best margin 7.2 dB stockholm: coverage 69.3%, 99 contacts, best margin 7.5 dB Madrid link availability: 95.210% Stockholm link availability: 95.550%

What just happened

The solver reported the design feasible. Independent verification of the same two stations it was given shows 74.3 percent and 69.3 percent coverage, and availability around 95 percent against a 99.9 percent target.

These two results do not contradict each other. They answer the same question over different windows.

The solver verified over 6 hours at 120-second steps, because that is what the requirement document asked for. The check above ran 24 hours at 60 seconds.

Six hours is under four orbits at 1238 km, and the Earth turns only 90 degrees in that time. A design can look continuous over a quarter turn and open large gaps once the planet rotates fully beneath it.

The lesson is not that the solver is wrong. It is that the verification window is part of the requirement, and a short one silently produces an optimistic verdict.

Fix the requirement, not the answer

The correct response is to state a window that can actually falsify the design, then re-solve:

{ "verification_hours": 24.0, "step_seconds": 60.0 }

Re-running with those values searches the same space against a harder test. The recommendation will be larger, and it will be one you can defend.

Two other defaults in that first run were doing no work at all:

  • global min fold: 1 means the worst-served point saw exactly one satellite. No redundancy, so a single failure creates an outage.
  • latency margin: inf ms means no latency limit was stated, so every candidate satisfied it trivially.

Both are symptoms of an under-constrained request. The solver optimizes what you ask for and adds nothing you did not.

A global check answers a different question

It is tempting to also run coverage globally:

orbitforge coverage --constellation designed.json \ --duration-hours 24 --step-seconds 60 --grid-deg 5 --min-elevation-deg 25
Coverage over 2664 grid points (5 deg), 16 sats, 24.0 h at 60 s: mean coverage 27.8% (area-weighted), min 0.0%, fully covered 0.0%, any 78.4% max fold 2, max coverage gap 35280 s

27.8 percent global coverage and a 9.8-hour maximum gap look alarming, and they are not evidence that the design failed. Global coverage was never requested: the requirement named two stations in Europe, and 16 satellites cannot cover the Earth.

Quoting that global figure against this design would be measuring it on a requirement it never had. Verify against the requirement you stated.

Checklist before trusting a synthesis

  1. Is the verification window long enough to be representative, at least a full Earth rotation for a continuous-service design?
  2. Is the step fine enough to resolve gaps you care about?
  3. Did you state a minimum fold, if the mission needs redundancy?
  4. Did you state a latency bound, if latency matters?
  5. Did you re-verify the recommendation yourself, at finer settings than the solver used?
  6. Are you measuring against the requirement you stated, rather than a different one?

Next steps

Question? Give us feedbackDocuments Varaha Constellation Designer main (pre-release)
Last updated on