Trade
/trade/sweepPurpose
Evaluates a grid of candidate constellations and reports coverage, gaps, and cost for each, marking those on the Pareto front.
Where /design searches for one recommendation against
stated requirements, this enumerates a space you define and hands back every
point. It is the endpoint for exploring a trade rather than closing one.
Request
The request is a cross product: every combination of planes, satellites per plane, and altitude is evaluated.
| Parameter | Type | Unit | Default | Required | Description |
|---|---|---|---|---|---|
planes | array of integers | count | — | Yes | Candidate plane counts. |
sats_per_plane | array of integers | count | — | Yes | Candidate satellites-per-plane counts. |
altitudes_km | array of numbers | km | — | Yes | Candidate altitudes. |
inclination_deg | number | deg | — | Yes | Inclination, shared by every candidate. |
cost | object | n/a | — | Yes | A complete econ request, nested. See below. |
pattern | string | n/a | delta | No | `delta` or `star`. |
duration_hours | number | h | — | No | Simulated span per candidate. |
step_seconds | number | s | — | No | Sampling step per candidate. |
grid_deg | number | deg | — | No | Coverage grid resolution. |
min_elevation_deg | number | deg | — | No | Coverage elevation mask. |
cost is required and takes the whole flat econ request as a nested
object, minus total_satellites and planes, which the sweep supplies per
candidate. Omitting it fails:
Failed to deserialize the JSON body into the target type: missing field `cost`So this endpoint nests an object that /econ/estimate
takes flat. Both shapes are correct in their own place.
Example
Two plane counts, two satellite counts, two altitudes: eight candidates.
curl -s -X POST http://127.0.0.1:8080/trade/sweep \
-H 'content-type: application/json' \
-d '{
"planes": [4, 6],
"sats_per_plane": [8, 10],
"altitudes_km": [550.0, 700.0],
"inclination_deg": 53.0,
"duration_hours": 2.0,
"step_seconds": 300.0,
"grid_deg": 20.0,
"cost": {
"satellite_recurring_usd": 1500000.0,
"satellite_mass_kg": 260.0,
"non_recurring_usd": 50000000.0,
"launch_price_usd": 60000000.0,
"launch_capacity_kg": 5500.0,
"spares_per_plane": 1,
"annual_operations_usd": 5000000.0,
"mission_years": 5.0
}
}'{
"evaluations": [
{
"point": {
"pattern": "Delta",
"planes": 4,
"sats_per_plane": 8,
"altitude_km": 550.0,
"inclination_deg": 53.0
},
"metrics": {
"satellite_count": 32,
"mean_coverage_percent": 45.89277392995268,
"max_gap_seconds": 3900.0,
"total_cost_usd": 249000000.0,
"cost_per_satellite_usd": 7781250.0,
"sk_delta_v_mps_per_year": 5.213741824754842
},
"pareto": false
}
]
}Response elided; evaluations holds one entry per candidate, eight in this run.
Reading the result
| Parameter | Type | Unit | Default | Required | Description |
|---|---|---|---|---|---|
mean_coverage_percent | number | percent | — | No | Area-weighted mean coverage. Look at gaps too; a mean can hide a structural hole. |
max_gap_seconds | number | s | — | No | Longest coverage gap. Usually the binding requirement. |
total_cost_usd | number | USD | — | No | Lifetime cost from the nested econ model. |
cost_per_satellite_usd | number | USD | — | No | Total divided by satellites built. |
sk_delta_v_mps_per_year | number | m/s per year | — | No | Station-keeping cost, which rises sharply at lower altitude. |
pareto | boolean | n/a | — | No | True when no other candidate is better on every objective at once. |
The pareto flag is the point
A candidate is Pareto-optimal when no other candidate beats it on every
objective simultaneously. Those are the only designs worth arguing about: any
candidate with pareto: false is dominated, meaning some other point in the
same sweep is at least as good everywhere and strictly better somewhere.
Filter on pareto: true first. It typically removes most of the grid and turns
a list of eight into a genuine choice between two or three.
The example candidate is pareto: false: 45.9 percent mean coverage with a
65-minute gap, at 249 million. Something else in the sweep beats it outright.
The sweep is a cross product, so it grows fast
Three arrays of length 2 give 8 candidates. Arrays of length 5 give 125, and each is a full propagation plus coverage analysis.
Keep exploratory sweeps coarse: short duration_hours, large step_seconds, and
a wide grid_deg, as in the example above. Those settings under-report gaps, so
they rank candidates rather than qualify them. Re-run the Pareto survivors at
proper resolution before quoting any number.
See also
/designto solve for a recommendation instead of enumerating./econ/estimatefor the cost model, which this nests.
main (pre-release)