Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ classifiers = [
"Development Status :: 4 - Beta"
]
dependencies = [
"astropy",
"geopandas >= 0.13.2",
"joblib",
"numba",
Expand Down
84 changes: 84 additions & 0 deletions src/tatc/schemas/orbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from typing import List, Optional, Tuple, Union

import numpy as np
from astropy.time import Time
from pydantic import AfterValidator, BaseModel, Field
from sgp4.api import Satrec, WGS72
from sgp4 import exporter
Expand Down Expand Up @@ -1181,3 +1182,86 @@ def get_derived_orbit(
eccentricity=self.eccentricity,
perigee_argument=self.perigee_argument,
)


class GeosynchronousOrbit(CircularOrbit):
"""
Geosynchronous orbit defined by longitude to be observed.
Geostationary orbit can be specified with inclination equal to 0.
"""

type: Literal["geosynchronous"] = Field(
"geosynchronous", description="Orbit type discriminator."
)
altitude: float = Field(35786000, description="Mean altitude (meters).")
longitude: float = Field(0, description="Longitude (degrees).", ge=0, lt=360)

def get_true_anomaly(self) -> float:
"""
Gets the true anomaly for the satellite over a given longitude at a given epoch.

Returns:
float: True anomaly in degrees.
"""
# convert to astropy time
t = Time(self.epoch, scale="utc")
# get greenwich sidereal time in degrees
gst = t.sidereal_time("mean", "greenwich").deg
# return earth-centered inertial angle
return (self.longitude + gst) % 360

def get_derived_orbit(
self, delta_mean_anomaly: float, delta_raan: float
) -> GeosynchronousOrbit:
"""
Gets a derived geosynchronous orbit with pertubations to the
mean anomaly (interpreted as a shift in observed longitude) and
right ascension of ascending node.

Args:
delta_mean_anomaly (float): Delta mean anomaly (degrees).
delta_raan (float): Delta right ascension of ascending node (degrees).

Returns:
GeosynchronousOrbit: the derived orbit
"""
true_anomaly = utils.mean_anomaly_to_true_anomaly(
np.mod(self.get_mean_anomaly() + delta_mean_anomaly, 360)
)
longitude = np.mod(self.longitude + delta_mean_anomaly, 360)
raan = np.mod(self.right_ascension_ascending_node + delta_raan, 360)
return GeosynchronousOrbit(
altitude=self.altitude,
true_anomaly=true_anomaly,
epoch=self.epoch,
inclination=self.inclination,
right_ascension_ascending_node=raan,
longitude=longitude,
)

def to_tle(self, lazy_load: bool = None) -> TwoLineElements:
"""
Converts this orbit to a two line elements representation.

Args:
lazy_load (bool): True, if this tle should be lazy-loaded.

Returns:
TwoLineElements: the two line elements orbit
"""
if lazy_load is None:
lazy_load = config.rc.orbit_tle_lazy_load
if lazy_load:
tle = self.__dict__.get("tle")
else:
tle = None
if tle is None:
tle = CircularOrbit(
altitude=self.altitude,
inclination=self.inclination,
right_ascension_ascending_node=self.right_ascension_ascending_node,
true_anomaly=self.compute_true_anomaly(),
epoch=self.epoch,
).to_tle()
self.__dict__["tle"] = tle
return tle
2 changes: 1 addition & 1 deletion src/tatc/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def mean_anomaly_to_true_anomaly(mean_anomaly: float, eccentricity: float = 0) -

Args:
mean_anomaly (float): The mean anomaly (degrees).
true_anomaly (float): The orbit eccentricity.
eccentricity (float): The orbit eccentricity.

Returns:
float: The true anomaly (degrees).
Expand Down