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.jsonDesign '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.jsonThe 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 24Link 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: 1means the worst-served point saw exactly one satellite. No redundancy, so a single failure creates an outage.latency margin: inf msmeans 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 25Coverage 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 s27.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
- Is the verification window long enough to be representative, at least a full Earth rotation for a continuous-service design?
- Is the step fine enough to resolve gaps you care about?
- Did you state a minimum fold, if the mission needs redundancy?
- Did you state a latency bound, if latency matters?
- Did you re-verify the recommendation yourself, at finer settings than the solver used?
- Are you measuring against the requirement you stated, rather than a different one?
Next steps
- Coverage and revisit to converge a coverage number properly.
designreference for the full requirement schema.
main (pre-release)