# Software Architecture for Multi-Orbit Satellite Constellations
The satellite constellation software challenge isn't building one ground system — it's orchestrating hundreds or thousands of spacecraft across multiple orbital regimes, each with different physics, different communication windows, and different mission profiles. A LEO imaging satellite at 500 km altitude sees a ground station for 8 minutes per pass. A GEO relay at 36,000 km sees the same station continuously. The software that manages both must understand these fundamental differences and optimize across them.
We've built software for space operations where the physics can't be faked and downtime means missed observation windows that don't come back. The architecture patterns for multi-orbit constellations emerge from production experience with ground systems for satellite operations and the unique constraints of orbital mechanics.
The Multi-Orbit Challenge
Modern constellations aren't single-orbit anymore. Operators combine orbital regimes to optimize for different objectives:
- LEO (200-2,000 km): High-resolution imaging, low-latency communications, frequent revisit for persistent coverage through large constellations
- MEO (2,000-35,786 km): Navigation (GPS, Galileo), regional communications, balance of coverage area and latency
- GEO (35,786 km): Persistent coverage of one-third of Earth's surface, weather monitoring, communications relay
A defense constellation might use LEO for tactical imaging, MEO for resilient navigation backup, and GEO for continuous communications relay. The software must manage all three as a unified system while respecting the physics of each regime.
Constellation-Level Orchestration
The orchestration layer sits above individual spacecraft management and makes constellation-level decisions: which satellite captures which target, how data routes from sensor to analyst, and how the constellation reconfigures when assets are lost.
Task Scheduling Across Orbits
Task scheduling for a multi-orbit constellation is a constrained optimization problem. Each satellite has:
- Orbital position and velocity (changing constantly)
- Sensor capabilities and current mode
- Power and thermal constraints
- Communication windows with ground stations and relay satellites
- Queued tasks and priorities
from dataclasses import dataclass
from datetime import datetime
from typing import List, Optional
@dataclass
class SatelliteState:
norad_id: str
orbit_regime: str # LEO, MEO, GEO
position_eci: tuple # x, y, z in km
velocity_eci: tuple # vx, vy, vz in km/s
available_power_w: float
storage_available_gb: float
next_ground_contact: datetime
contact_duration_s: float
@dataclass
class CollectionTask:
target_lat: float
target_lon: float
priority: int
required_resolution_m: float
time_window: tuple # start, end
data_size_estimate_gb: float
class ConstellationScheduler:
def __init__(self, propagator, ground_network):
self.propagator = propagator
self.ground_network = ground_network
def schedule(self, tasks: List[CollectionTask],
constellation: List[SatelliteState]) -> dict:
assignments = {}
for task in sorted(tasks, key=lambda t: t.priority, reverse=True):
candidates = self._find_capable_satellites(
task, constellation
)
if candidates:
best = self._select_optimal(task, candidates)
assignments[task] = best
self._update_satellite_resources(best, task)
return assignments
def _find_capable_satellites(self, task, constellation):
capable = []
for sat in constellation:
access_windows = self.propagator.compute_access(
sat, task.target_lat, task.target_lon,
task.time_window[0], task.time_window[1]
)
if access_windows and sat.storage_available_gb >= task.data_size_estimate_gb:
capable.append((sat, access_windows))
return capable
def _select_optimal(self, task, candidates):
return min(candidates, key=lambda c: self._cost_function(task, c))
def _cost_function(self, task, candidate):
sat, windows = candidate
earliest_access = windows[0].start
time_to_downlink = (earliest_access - sat.next_ground_contact).total_seconds()
power_margin = sat.available_power_w / 100.0
return time_to_downlink / power_margin The scheduler considers physical constraints — a LEO satellite can only image a target during a brief access window, while a GEO satellite might have persistent visibility but lower resolution. The optimization balances timeliness, resolution, and resource consumption across the entire constellation.
Orbital Mechanics APIs
Every constellation management decision depends on orbital mechanics. Where will each satellite be in 30 minutes? When is the next communication window? Can this satellite see this ground target at this time?
Propagation Services
Orbit propagation predicts future satellite positions. For operational timelines (hours to days), SGP4/SDP4 propagation using TLE data provides sufficient accuracy. For precision operations, numerical propagation using high-fidelity force models is required.
from sgp4.api import Satrec, jday
from datetime import datetime, timedelta
class OrbitPropagator:
def __init__(self, tle_line1, tle_line2):
self.satellite = Satrec.twoline2rv(tle_line1, tle_line2)
def propagate(self, dt: datetime):
jd, fr = jday(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second + dt.microsecond / 1e6)
e, r, v = self.satellite.sgp4(jd, fr)
if e != 0:
raise PropagationError(f"SGP4 error code: {e}")
return Position(r[0], r[1], r[2]), Velocity(v[0], v[1], v[2])
def compute_access_windows(self, ground_lat, ground_lon, ground_alt,
start: datetime, end: datetime,
min_elevation_deg: float = 5.0):
windows = []
current = start
step = timedelta(seconds=30)
in_access = False
window_start = None
while current <= end:
pos, _ = self.propagate(current)
el = self._compute_elevation(
pos, ground_lat, ground_lon, ground_alt
)
if el >= min_elevation_deg and not in_access:
window_start = current
in_access = True
elif el < min_elevation_deg and in_access:
windows.append(AccessWindow(window_start, current))
in_access = False
current += step
return windows Ephemeris Management
TLE data degrades in accuracy over time. For LEO satellites, a TLE is useful for roughly 3-7 days. For constellation management, continuous ephemeris updates are essential.
Build an ephemeris service that:
- Ingests TLEs from Space-Track.org or owner/operator ephemeris
- Maintains historical and predicted state vectors
- Provides RESTful APIs for position queries
- Caches propagation results for frequently queried time windows
- Supports both SGP4 and numerical propagation modes
Ground Station Handoff
When a LEO satellite passes over a ground station, the communication window is measured in minutes. Maximizing data throughput during each pass — and seamlessly handing off to the next station in the network — is critical.
Contact Prediction and Scheduling
Ground contact scheduling is another constrained optimization problem. Each ground station has:
- Geographic location (determines which satellites it can see)
- Antenna count and capabilities (frequency bands, gain, tracking rate)
- Current schedule (no double-booking antennas)
- Weather forecast (rain fade degrades link budget)
class GroundNetworkScheduler:
def __init__(self, stations, propagator):
self.stations = stations
self.propagator = propagator
def schedule_downlinks(self, constellation, time_horizon_hours=24):
schedule = {}
pending_data = self._get_pending_downloads(constellation)
for sat_id, data_queue in sorted(
pending_data.items(),
key=lambda x: x[1].priority,
reverse=True
):
contacts = self._find_all_contacts(
sat_id, time_horizon_hours
)
for contact in contacts:
station = contact.station
if self._station_available(station, contact.window):
data_volume = self._estimate_throughput(contact)
schedule[contact] = DownlinkPlan(
satellite=sat_id,
station=station,
window=contact.window,
estimated_volume_gb=data_volume,
data_priority=data_queue.priority
)
break
return schedule Inter-Satellite Links
Modern constellations increasingly use inter-satellite links (ISLs) to route data between spacecraft. A LEO satellite that just captured imagery over a denied area might not see a friendly ground station for 45 minutes — but it can relay data through neighboring satellites in the constellation to one that has a ground contact now.
ISL routing is fundamentally a dynamic network problem. The topology changes continuously as satellites move. Routing algorithms must account for:
- Link availability (satellites must be within line-of-sight)
- Link capacity (laser or RF bandwidth)
- Latency requirements (how quickly must data reach the ground?)
- Orbital mechanics (which links will exist in 5 minutes vs. now?)
Data Routing and Processing
The data pipeline from satellite sensor to analyst workstation spans multiple orbital regimes, ground stations, and processing stages.
Edge Processing on Spacecraft
Downloading every raw image from a LEO constellation would overwhelm ground bandwidth. Onboard processing — cloud detection, change detection, target classification — filters data before downlink. Only relevant data consumes precious communication bandwidth.
This is the space-domain application of edge computing principles, where processing happens closest to the data source and only results traverse constrained communication links.
Ground Processing Architecture
Once data reaches the ground, it flows through a processing pipeline that we architect using the same space and aerospace software patterns proven in production:
- Ingest: Raw data received from ground station, cataloged with metadata
- Calibration: Radiometric and geometric correction
- Processing: Derived products (orthorectified images, signal analysis)
- Dissemination: Processed products delivered to end users via APIs or data stores
- Archive: Long-term storage with search and retrieval
The patterns for processing satellite data at scale align with satellite data processing and AI workflows where throughput and latency both matter.
Constellation Health Management
Managing hundreds of spacecraft requires automated health monitoring. Individual anomalies must be detected, categorized, and addressed without requiring human attention for every telemetry deviation.
Telemetry Analysis
Each satellite streams housekeeping telemetry — temperatures, voltages, reaction wheel speeds, solar array currents. Automated analysis compares current values against expected ranges and trend baselines:
- Red limits: Immediate safety concern — automated safing response
- Yellow limits: Approaching operational boundary — alert for review
- Trend deviation: Parameter drifting outside historical baseline — schedule investigation
For a constellation of 200+ satellites, this means processing thousands of telemetry parameters per satellite, per pass. The analysis must be automated, and anomaly detection must distinguish between real problems and normal orbital variation.
Frequently Asked Questions
How do you handle clock synchronization across a multi-orbit constellation?
GPS provides nanosecond-accurate timing for satellites equipped with GPS receivers (most LEO and MEO spacecraft). GEO satellites may use ground-based time correlation. All telemetry and command timestamps use UTC. The ground system correlates events across the constellation using synchronized clocks and propagation delay models for each communication link.
What programming languages are used for constellation management software?
Ground systems typically use Python for mission planning and analysis, C++ or Rust for high-performance propagation and real-time systems, and TypeScript/React for operator interfaces. Flight software is predominantly C or C++ for heritage reasons, though Rust is gaining adoption for new missions. The key constraint is determinism and reliability, not language features.
How does a constellation recover from losing multiple satellites?
Constellation design includes graceful degradation. The coverage pattern is designed with enough overlap that losing 5-10% of spacecraft degrades performance but doesn't create coverage gaps. The constellation management software automatically re-optimizes task scheduling and data routing around the reduced constellation. Orbit-raising of spare spacecraft from parking orbits can restore full capability over weeks.
What's the difference between managing LEO vs GEO constellations?
LEO management is dominated by short contact windows, high revisit rates, and large constellation sizes. GEO management focuses on station-keeping, long-duration operations, and spectrum coordination. LEO constellations require automated operations due to scale — you can't have a human operator per satellite when you have 500 spacecraft. GEO operations allow more manual intervention because the pace is slower and each asset is individually high-value.
How do you test constellation management software without actual satellites?
High-fidelity simulation environments model every aspect: orbital mechanics, sensor performance, communication link budgets, ground station schedules, and environmental effects. Test scenarios include nominal operations, contingency responses, and degraded constellation configurations. The simulation uses the same APIs as the operational system, so the software doesn't know the difference between simulated and real spacecraft.
---
Multi-orbit constellation software demands architecture that respects orbital mechanics and scales to hundreds of spacecraft. Contact Rutagon to discuss constellation management and ground system architecture.