Skip to content

constellation

cosmica.dynamics.constellation

__all__ module-attribute

__all__ = [
    "MOPCSatelliteKey",
    "MultiOrbitalPlaneConstellation",
    "SatelliteConstellation",
]

logger module-attribute

logger = getLogger(__name__)

MOPCSatelliteKey

Bases: NamedTuple

plane_id instance-attribute

plane_id: int

satellite_id instance-attribute

satellite_id: int

__str__

__str__() -> str
Source code in src/cosmica/dynamics/constellation.py
50
51
def __str__(self) -> str:
    return f"({self.plane_id},{self.satellite_id})"

MultiOrbitalPlaneConstellation

MultiOrbitalPlaneConstellation(
    satellite_orbits: Mapping[
        ConstellationSatellite[MOPCSatelliteKey], TOrbit
    ],
)

Bases: SatelliteConstellation[MOPCSatelliteKey, TOrbit]

A constellation of satellites in multiple orbital planes.

The satellite key is a tuple of the plane ID and the satellite ID.

Source code in src/cosmica/dynamics/constellation.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
def __init__(
    self,
    satellite_orbits: Mapping[ConstellationSatellite[MOPCSatelliteKey], TOrbit],
) -> None:
    self.satellite_orbits = satellite_orbits

    self.satellites = tuple(self.satellite_orbits.keys())
    self.plane_ids = sorted({sat.id.plane_id for sat in self.satellites})
    self.satellite_ids = sorted({sat.id.satellite_id for sat in self.satellites})

    self.plane_id_to_satellites: dict[int, list[ConstellationSatellite[MOPCSatelliteKey]]] = {
        plane_id: [sat for sat in self.satellites if sat.id.plane_id == plane_id] for plane_id in self.plane_ids
    }

    # Check if all planes have the same number of satellites
    self._all_planes_have_same_n_satellites = (
        len({len(self.plane_id_to_satellites[plane_id]) for plane_id in self.plane_ids}) == 1
    )
    if not self._all_planes_have_same_n_satellites:
        logger.warning("Not all planes have the same number of satellites.")

n_satellites_per_plane property

n_satellites_per_plane: int

Number of satellites per orbital plane.

It is assumed that all planes have the same number of satellites. Otherwise, it will raise an exception.

plane_id_to_satellites instance-attribute

plane_id_to_satellites: dict[
    int, list[ConstellationSatellite[MOPCSatelliteKey]]
] = {
    plane_id: [
        sat for sat in (satellites) if plane_id == plane_id
    ]
    for plane_id in (plane_ids)
}

plane_ids instance-attribute

plane_ids = sorted({(plane_id) for sat in (satellites)})

satellite_ids instance-attribute

satellite_ids = sorted(
    {(satellite_id) for sat in (satellites)}
)

satellite_orbits instance-attribute

satellite_orbits = satellite_orbits

satellites instance-attribute

satellites = tuple(keys())

from_toml_file classmethod

from_toml_file(
    toml_file_path: Path | str,
) -> MultiOrbitalPlaneConstellation
Source code in src/cosmica/dynamics/constellation.py
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
@classmethod
@deprecated("Construction of objects from TOML files is deprecated and will be removed in future versions.")
def from_toml_file(cls, toml_file_path: Path | str) -> MultiOrbitalPlaneConstellation:
    toml_file_path = Path(toml_file_path)
    with toml_file_path.open("rb") as f:
        toml_data = tomllib.load(f)

    epoch = np.datetime64(toml_data["epoch"].astimezone(tz=UTC).replace(tzinfo=None))

    @deprecated("Construction of objects from TOML files is deprecated and will be removed in future versions.")
    def parse_satellite_item(
        item: dict[str, Any],
    ) -> tuple[ConstellationSatellite[MOPCSatelliteKey], TOrbit]:
        plane_id = item.pop("plane_id")
        satellite_id = item.pop("id")

        # Convert degrees to radians
        item["semi_major_axis"] = item.pop("sma_m")
        item["inclination"] = np.radians(item.pop("inc_deg"))
        item["raan"] = np.radians(item.pop("raan_deg"))
        item["phase_at_epoch"] = np.radians(item.pop("phase_at_epoch_deg"))
        item["epoch"] = epoch

        orbit_type = item.pop("orbit_type")
        return ConstellationSatellite(  # type: ignore[return-value]
            id=MOPCSatelliteKey(plane_id, satellite_id),
        ), make_satellite_orbit(
            orbit_type=orbit_type,
            **item,
        )

    satellite_orbits = dict(map(parse_satellite_item, toml_data["satellites"]))

    return cls(satellite_orbits)

propagate

propagate(
    time: NDArray[datetime64],
) -> dict[ConstellationSatellite[T], SatelliteOrbitState]
Source code in src/cosmica/dynamics/constellation.py
42
43
def propagate(self, time: npt.NDArray[np.datetime64]) -> dict[ConstellationSatellite[T], SatelliteOrbitState]:
    return {sat: orbit.propagate(time) for sat, orbit in self.satellite_orbits.items()}

SatelliteConstellation

Bases: ABC

A constellation of satellites.

satellite_orbits is a dictionary mapping satellite keys to satellite orbits.

satellite_orbits instance-attribute

satellite_orbits: Mapping[
    ConstellationSatellite[T], TOrbit
]

satellites instance-attribute

satellites: Sequence[ConstellationSatellite[T]]

propagate

propagate(
    time: NDArray[datetime64],
) -> dict[ConstellationSatellite[T], SatelliteOrbitState]
Source code in src/cosmica/dynamics/constellation.py
42
43
def propagate(self, time: npt.NDArray[np.datetime64]) -> dict[ConstellationSatellite[T], SatelliteOrbitState]:
    return {sat: orbit.propagate(time) for sat, orbit in self.satellite_orbits.items()}