[OLD] Ramblings about Earth orbit - poliastro/poliastro GitHub Wiki
This was implemented in the poliastro.earth
module
New ideas for the object hierarchy
Current ideas
Remember Orbit = BaseState + epoch
Many Orbit
properties like this:
@property
def raan(self):
return self.state.raan
EarthOrbit(Orbit)
is a bad idea, for example:
synchronous
stop receiving anattractor
- if
.propagate()
hardcodes method "SGP4" - (there are other examples)
_BaseOrbit
with some shared functionality, and thenOrbit(_BaseOrbit)
andEartOrbit(_BaseOrbit)
...- Try to minimize inheritance and leverage composition, for example adding more functionality a
BaseState
Current API is like this:
orb = Orbit.from_vectors(Mars, r, v, Time.now())
print(orb.a)
print(orb.ecc)
new_orb = orb.propagate(10 * u.min, method=farnocchia)
new_orb = orb.propagate(
10 * u.min,
method=lambda ...: cowell(..., a_d=...)
)
orb.plot()
# Before: BaseCoordinateFrame = data (BaseRepresentation) + transformations
# Now: BaseRepresentation
# orb.sample()
User story: Load an orbit from a TLE/OMM.
from poliastro.earth.atmosphere import JR77
# from poliastro.earth.gravity import EGM96
# EarthSatellite contains an Orbit + ... (can grow)
# orb = EarthSatellite.from_tle(tle)
orb = EarthSatellite.from_vectors(r, v)
orb = EarthSatellite.from_classical(a, ecc, inc, raan, argp, nu)
orb.propagate(10 * u.min, atmosphere=JR77)
class EarthSatellite:
def propagate(self, tof, *, atmosphere=None, gravity=None):
if atmosphere is None and gravity is None:
return self.orbit.propagate()
# a_d = _a_d_from_perturbations(atmosphere=atmosphere) # Magic
a_d = functools.partial(atmospheric_drag_model, model=atmosphere)
return self.orbit.propagate(tof, method=cowell, a_d=a_d)
Propagators:
- Two body propagators: farnocchia, vallado, mikkola, ...
func(k, r, v, tofs, **kwargs)
- Semianalytic(??) propagators:
J2
, ...func(k, r, v, tofs, J2)
- Generic(??) propagators:
cowell
, "Encke"?func(k, r, v, tofs, rtol=1e-11, *, events=None, ad=None, **ad_kwargs)
Class-based propagators:
class Vallado(Propagator):
def __init__(self, numiter):
super()
self.numiter = numiter
# def propagate
def __call__(self, r, v, tofs):
# internally uses self.numiter
class Cowell(Propagator):
def __init__(self, rtol, events, ad, **ad_kwargs):
super()
self.rtol = rtol
...
def __call__(self, r, v, tofs):
# internally use self.events, self.ad, ...
...
# NO!
class SGP4(Propagator):
def __init__(self, ndot, nddot, bc, bstar, ...):
...
# def __call__(self, r, v, tofs): # NOPE!
def __call__(self, n_brouwer, e_brouwer, i_brouwer, raan_brouwer, ...):
orb.propagate(10 * u.min, method=Vallado(numiter=35))
Upper layer:
ClassicalState = attractor + ClassicalElementSet + plane
TLE =
attractor = Earth
(hardcoded SGP4 propagator) +
frame=TEME +
ClassicalElementSet(n, e, i, raan, argp, M) +
epoch +
extra_parameters +
metadata
tle = TLE.from_string(...)
tle.propagate(10 * u.min) # TEME(x, y, z, d_x, d_y, d_z)
tle.plot()
tle.sample()
plotter = OrbitPlotter()
plotter.plot(tle) # NotImplementedError: Cannot plot BaseCoordinateFrame
tle = """
...
...
"""
orb = TLE.from_string(tle)
print(orb.attractor) # Earth
print(orb.ballistic_coefficient) # 0.01 [...]
print(orb.a) # Mean or osculating?
new_orb = orb.propagate(10 * u.min) # SGP4 is mandatory
Problems with frames:
orb = Orbit.from_coords(
Mars,
HCRS(..., obstime=Time.now()),
plane=Planes.EARTH_EQUATOR
) # Why do you need planes?
orb = Orbit.from_coords(
Earth,
ITRS(..., obstime=Time.now()),
) # How do you guarantee this is inertial?