Support wrapping raw sgp4 satellite object
This commit is contained in:
parent
3c24f5ce11
commit
e3f0cdca94
|
@ -656,3 +656,59 @@ and otherwise recording the propagator error:
|
|||
None,
|
||||
None,
|
||||
'mrt is less than 1.0 which indicates the satellite has decayed']
|
||||
|
||||
Building a satellite from orbital elements
|
||||
------------------------------------------
|
||||
|
||||
If you are starting with raw satellite orbital parameters
|
||||
instead of TLE text,
|
||||
you will want to interact directly
|
||||
with the `sgp4 <https://github.com/brandon-rhodes/python-sgp4>`_ library
|
||||
that Skyfield uses for its low-level satellite calculations.
|
||||
|
||||
The underlying library provides access to a low-level constructor
|
||||
that builds a satellite model directly from numeric orbital parameters:
|
||||
|
||||
.. testcode::
|
||||
|
||||
from sgp4.api import Satrec, WGS72
|
||||
|
||||
satrec = Satrec()
|
||||
satrec.sgp4init(
|
||||
WGS72, # gravity model
|
||||
'i', # 'a' = old AFSPC mode, 'i' = improved mode
|
||||
5, # satnum: Satellite number
|
||||
18441.785, # epoch: days since 1949 December 31 00:00 UT
|
||||
2.8098e-05, # bstar: drag coefficient (/earth radii)
|
||||
6.969196665e-13, # ndot: ballistic coefficient (revs/day)
|
||||
0.0, # nddot: second derivative of mean motion (revs/day^3)
|
||||
0.1859667, # ecco: eccentricity
|
||||
5.7904160274885, # argpo: argument of perigee (radians)
|
||||
0.5980929187319, # inclo: inclination (radians)
|
||||
0.3373093125574, # mo: mean anomaly (radians)
|
||||
0.0472294454407, # no_kozai: mean motion (radians/minute)
|
||||
6.0863854713832, # nodeo: right ascension of ascending node (radians)
|
||||
)
|
||||
|
||||
If you need any more details,
|
||||
this ``sgp4init`` constructor
|
||||
is documented in the
|
||||
`Providing your own elements <https://pypi.org/project/sgp4/#providing-your-own-elements>`_
|
||||
section of the sgp4 library’s documentation on the Python Packaging Index.
|
||||
|
||||
To wrap this low-level satellite model in a Skyfield object,
|
||||
call this special constructor:
|
||||
|
||||
.. testcode::
|
||||
|
||||
sat = EarthSatellite.from_satrec(satrec, ts)
|
||||
print('Satellite number:', sat.model.satnum)
|
||||
print('Epoch:', sat.epoch.utc_jpl())
|
||||
|
||||
.. testoutput::
|
||||
|
||||
Satellite number: 5
|
||||
Epoch: A.D. 2000-Jun-27 06:50:24.0000 UT
|
||||
|
||||
The result should be a satellite object that behaves
|
||||
exactly as though it had been loaded from TLE lines.
|
||||
|
|
|
@ -10,7 +10,7 @@ from .constants import AU_KM, DAY_S, T0, tau
|
|||
from .functions import rot_x, rot_y, rot_z
|
||||
from .positionlib import ITRF_to_GCRS2
|
||||
from .searchlib import _find_discrete, find_maxima
|
||||
from .timelib import Timescale
|
||||
from .timelib import Timescale, calendar_date
|
||||
from .vectorlib import VectorFunction
|
||||
|
||||
_minutes_per_day = 1440.
|
||||
|
@ -90,24 +90,46 @@ class EarthSatellite(VectorFunction):
|
|||
ts = ts or _ts
|
||||
|
||||
self.name = None if name is None else name.strip()
|
||||
sat = Satrec.twoline2rv(line1, line2)
|
||||
self.model = sat
|
||||
satrec = Satrec.twoline2rv(line1, line2)
|
||||
self.model = satrec
|
||||
|
||||
# TODO: just use the Julian dates instead
|
||||
two_digit_year = sat.epochyr
|
||||
two_digit_year = satrec.epochyr
|
||||
if two_digit_year < 57:
|
||||
year = two_digit_year + 2000;
|
||||
year = two_digit_year + 2000
|
||||
else:
|
||||
year = two_digit_year + 1900;
|
||||
year = two_digit_year + 1900
|
||||
|
||||
self.epoch = ts.utc(year, 1, sat.epochdays)
|
||||
self.epoch = ts.utc(year, 1, satrec.epochdays)
|
||||
|
||||
self.target = -100000 - self.model.satnum
|
||||
self._setup(satrec, ts)
|
||||
|
||||
def _setup(self, satrec, ts):
|
||||
# If only I had not made __init__() specific to TLE lines, but
|
||||
# had put them in an alternate construtor instead, this would
|
||||
# simply have lived in __init__(). Alas! I was so young then.
|
||||
|
||||
self.target = -100000 - satrec.satnum
|
||||
self.target_name = 'Satellite{0} {1}'.format(
|
||||
self.model.satnum,
|
||||
satrec.satnum,
|
||||
' ' + repr(self.name) if self.name else '',
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_satrec(cls, satrec, ts):
|
||||
"""Build an EarthSatellite from a raw sgp4 Satrec object."""
|
||||
self = cls.__new__(cls)
|
||||
self.model = satrec
|
||||
self.name = None
|
||||
|
||||
# TODO: once sgp4 starts filling in epochyr and epochdays in
|
||||
# sgp4init(), the separate epoch code here and in __init__() can
|
||||
# be unified to always use epochyr and epochdays.
|
||||
year, month, day = calendar_date(satrec.jdsatepoch)
|
||||
self.epoch = ts.utc(year, month, day + satrec.jdsatepochF)
|
||||
|
||||
self._setup(satrec, ts)
|
||||
return self
|
||||
|
||||
def __str__(self):
|
||||
sat = self.model
|
||||
return 'EarthSatellite{0} number={1!r} epoch={2}'.format(
|
||||
|
|
Loading…
Reference in New Issue