예제 #1
0
def sv(request):
    tle = Tle(
        """ISS (ZARYA)
1 25544U 98067A   18124.55610684  .00001524  00000-0  30197-4 0  9997
2 25544  51.6421 236.2139 0003381  47.8509  47.6767 15.54198229111731"""
    )
    return tle.orbit().as_statevector().copy(form=request.param)
예제 #2
0
def test_tle_to_and_from():

    txt = """1 25544U 98067A   08264.51782528 -.00002182  00000-0 -11606-4 0  2927
2 25544  51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537"""
    orb = Tle(txt).orbit()
    new_txt = Tle.from_orbit(orb, norad_id=25544, cospar_id='1998-067A')

    assert str(new_txt) == txt
예제 #3
0
def test_orbit2frame():

    iss = Tle("""0 ISS (ZARYA)
1 25544U 98067A   16333.80487076  .00003660  00000-0  63336-4 0  9996
2 25544  51.6440 317.1570 0006082 266.5744 156.9779 15.53752683 30592"""
              ).orbit()
    soyouz = Tle("""0 SOYUZ MS-03
1 41864U 16070A   16332.46460811 +.00003583 +00000-0 +62193-4 0  9996
2 41864 051.6436 323.8351 0006073 261.8114 220.0268 15.53741335030385"""
                 ).orbit()

    # This is done to convert the TLE format to cartesian coordinates
    # as done during propagation
    soyouz = soyouz.propagate(soyouz.date)

    inert = iss.as_frame('iss_inert')
    qsw = iss.as_frame('iss_qsw', orientation='QSW')
    tnw = iss.as_frame('iss_tnw', orientation='TNW')

    assert inert.orientation == "TEME"
    assert qsw.orientation == "QSW"
    assert tnw.orientation == "TNW"

    s1 = soyouz.copy(frame='iss_inert')
    assert_vector(
        s1,
        np.array([
            70.5889585, 73.6584008, -62.5406308, 0.0521557, 0.0998631,
            -0.0423856
        ]))

    s2 = soyouz.copy(frame="iss_qsw")
    assert_vector(
        s2,
        np.array([
            4.5450528, -18.6989377, -118.107503, 0.0393978, -0.0046244,
            -0.1136478
        ]))

    s3 = soyouz.copy(frame="iss_tnw")
    assert_vector(
        s3,
        np.array([
            -18.6974528, -4.5511611, -118.107503, -0.0046116, -0.0393993,
            -0.1136478
        ]))

    # Whatever the local reference frame, the W vector is the same
    assert s2[2] == s3[2]

    # The norm of the position vectors should the same, because it's always the
    # same relative positions, but expressed in differents frames
    assert_almost_equal(norm(s1[:3]), norm(s2[:3]), decimal=5)
    assert_almost_equal(norm(s2[:3]), norm(s3[:3]))
예제 #4
0
def test_convert_to_orbit(tle_txt):

    tle = Tle(tle_txt)
    orb = tle.orbit()

    assert orb.frame.name == "TEME"
    assert repr(orb.form).startswith("<Form 'tle'")
    assert repr(orb.date) == "<Date '2008-09-20T12:25:40.104192 UTC'>"
    assert orb['i'] == np.deg2rad(51.6416)
    assert orb['Ω'] == np.deg2rad(247.4627)
    assert orb['e'] == 6.703e-4
    assert orb['ω'] == np.deg2rad(130.5360)
    assert orb['M'] == np.deg2rad(325.0288)
    assert orb['n'] == 15.72125391 * 2 * np.pi / 86400.
예제 #5
0
def test_one(helper):

    test_cases = {
        """1 25544U 98067A   08264.51782528 -.00002182  00000-0 -11606-4 0  2927
2 25544  51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537""": ([
            -3199119.3019953547, -5925838.8951945184, -104283.88301037039,
            4160.9001260610321, -2340.8666910921365, 6034.2397874890266
        ]),
        """1 27421U 02021A   15290.39156189  .00000174  00000-0  10000-3 0  9996
2 27421  98.4973 341.4832 0001168 101.4896  26.7296 14.20902451697482""": ([
            -6313390.5470795343, 2392162.4266701187, -2518309.642217699,
            2810.1811696038776, 188.82949370476567, -6882.790571054541
        ]),
        """1 38012U 11076F   15290.43560975 -.00001375  00000-0 -28626-3 0  9990
2 38012  98.1856   3.4028 0001255  65.6426 294.5016 14.58534477204126""": ([
            -6278750.6667313213, -8651.4824499131028, -3277187.0595075251,
            3419.2465632815151, 1208.7786614934848, -6564.4998427326509
        ]),
        """1 25544U 98067A   15290.14517523  .00013306  00000-0  20592-3 0  9999
2 25544  51.6447 195.3542 0006630  48.0978  95.2885 15.54379613967013""": ([
            -6596477.2658053627, 63108.245806605715, -1577202.6429111576,
            -1410.6459948627141, -4877.7460063862927, 5746.8315844151275
        ]),
    }

    for lines, expected in test_cases.items():
        tle = Tle(lines).orbit()

        sgp4 = Sgp4Beta()
        sgp4.orbit = tle
        pv = sgp4.propagate(tle.date + timedelta(days=1))

        helper.assert_vector(pv, expected)
예제 #6
0
def test_dump_omm_bluebook(ccsds_format, datafile, str_tle_bluebook):
    """Example from the CCSDS Blue Book (4-1 and 4-2)
    """

    tle = Tle(str_tle_bluebook)
    omm = tle.orbit()
    # omm.name = tle.name
    # omm.norad_id = tle.norad_id
    # omm.cospar_id = tle.cospar_id

    # assert tle.epoch == Date(2007, 5, 4, 10, 34, 41, 426400)

    omm = dumps(omm, fmt=ccsds_format).splitlines()
    ref_bluebook = datafile("omm_bluebook").splitlines()

    assert ref_bluebook[0] == omm[0]
    for i in range(4, len(ref_bluebook)):
        assert ref_bluebook[i] == omm[i]
예제 #7
0
파일: utils.py 프로젝트: rumbis/sattools
def tle_from_file(filename):
    '''
    Returns: TLE:Tle, Object name:str
    '''

    with open(filename, 'r') as f:
        lines = f.readlines()

    return Tle(''.join(lines)), lines[0].strip()
예제 #8
0
def test_to_and_from(both):

    tle = Tle(both)
    orb = tle.orbit()
    orb2 = orb.copy()
    del orb2._data["cospar_id"]

    tle2 = Tle.from_orbit(orb, name=tle.name, norad_id=tle.norad_id, cospar_id=tle.cospar_id)
    tle3 = Tle.from_orbit(orb2, name=tle.name, norad_id=tle.norad_id)

    assert tle2.cospar_id == tle.cospar_id
    assert tle3.cospar_id == ""

    tle, tle2 = tle.text.splitlines(), tle2.text.splitlines()
    for i in range(2):
        # We don't test the last two fields of the TLE because when we reconstruct one from scracth
        # we can't have any information about the element set number. And because of that, the
        # checksum is also different
        assert tle[i][:63] == tle2[i][:63]
예제 #9
0
    def dump(self, all=False):

        bd_request = self.model.select().order_by(self.model.norad_id,
                                                  self.model.epoch)

        if not all:
            bd_request = bd_request.group_by(self.model.norad_id)

        for tle in bd_request:
            yield Tle("%s\n%s" % (tle.name, tle.data), src=tle.src)
예제 #10
0
def test_tle(tle, ccsds_format):
    # Check that a TLE and its OMM representation are the same

    txt = dumps(tle, fmt=ccsds_format)
    orb = loads(txt)
    new_tle = Tle.from_orbit(orb)
    assert str(tle.tle) == str(new_tle)

    assert all(tle == orb)
    date = Date(2020, 9, 30)
    assert all(tle.propagate(date) == orb.propagate(date))
예제 #11
0
    def get(cls, **kwargs):
        """Retrieve one TLE from the table from one of the available fields

        Keyword Arguments:
            norad_id (int)
            cospar_id (str)
            name (str)
        Return:
            Tle:
        """
        entity = cls()._get_last_raw(**kwargs)
        return Tle("%s\n%s" % (entity.name, entity.data), src=entity.src)
예제 #12
0
def test_generator(caplog):

    text = "\n".join(ref) + "\n1   \n2   "

    with raises(TleParseError):
        for tle in Tle.from_string(text, error="raise"):
            continue

    for tle in Tle.from_string(text):
        continue

    assert len(caplog.records) == 1
    assert caplog.record_tuples == [
        ('beyond.io.tle', logging.WARNING, "Invalid TLE size on line 1. Expected 69, got 1.")
    ]

    caplog.clear()

    for tle in Tle.from_string(text, error="ignore"):
        continue

    assert len(caplog.records) == 0
예제 #13
0
def test_generator(caplog):

    text = "\n".join(ref) + "\n1   \n2   "

    with raises(TleParseError):
        for tle in Tle.from_string(text, error="raise"):
            continue

    for tle in Tle.from_string(text):
        continue

    assert len(caplog.records) == 1
    assert caplog.record_tuples == [
        ('beyond.io.tle', logging.WARNING,
         "invalid literal for int() with base 10: '  '")
    ]

    caplog.clear()

    for tle in Tle.from_string(text, error="ignore"):
        continue

    assert len(caplog.records) == 0
예제 #14
0
    def get_dated(cls, limit=None, date=None, **kwargs):

        self = cls()

        if limit == "after":
            r = (self.model.select().where(self.model.epoch >= date).order_by(
                self.model.epoch.asc()))
        else:
            r = self.model.select().where(self.model.epoch <= date)

        try:
            entity = r.filter(**kwargs).get()
        except self.model.DoesNotExist:
            mode, selector = kwargs.popitem()
            raise TleNotFound(selector, mode=mode) from e
        else:
            return Tle("%s\n%s" % (entity.name, entity.data), src=entity.src)
예제 #15
0
    def from_text(cls, text):
        """This method is used to parse an orbit from stdin
        """
        sats = [cls.from_orb(tle) for tle in Tle.from_string(text)]

        if not sats:
            try:
                orb = ccsds.loads(text)
            except ValueError:
                raise ValueError("No valid TLE nor CCSDS")
            else:
                if isinstance(orb, (Ephem, Orbit)):
                    sats = [cls.from_orb(orb)]
                else:
                    sats = [cls.from_orb(ephem) for ephem in orb]

        return sats
예제 #16
0
    def history(self, number=None, **kwargs):
        """Retrieve all the TLE of a given object

        Keyword Arguments:
            norad_id (int)
            cospar_id (str)
            name (str)
        Yield:
            TleModel:
        """

        query = self.model.select().filter(**kwargs).order_by(self.model.epoch)

        if not query:
            mode, selector = kwargs.popitem()
            raise TleNotFound(selector, mode=mode)

        number = 0 if number is None else number

        for el in query[-number:]:
            yield Tle("%s\n%s" % (el.name, el.data), src=el.src)
예제 #17
0
    def insert(self, text, src):
        """
        Args:
            text (str): text containing the TLEs
            src (str): Where those TLEs come from
        Return:
            2-tuple: Number of tle inserted, total tle found in the text
        """

        with self.db.atomic():
            entities = []
            i = None
            for i, tle in enumerate(Tle.from_string(text)):
                try:
                    # An entry in the table correponding to this TLE has been
                    # found, there is no need to update it
                    entity = self.model.get(
                        self.model.norad_id == tle.norad_id,
                        self.model.epoch == tle.epoch.datetime,
                    )
                    continue
                except TleModel.DoesNotExist:
                    # This TLE is not registered yet, lets go !
                    entity = {
                        "norad_id": int(tle.norad_id),
                        "cospar_id": tle.cospar_id,
                        "name": tle.name,
                        "data": tle.text,
                        "epoch": tle.epoch.datetime,
                        "src": src,
                        "insert_date": datetime.now(),
                    }
                    entities.append(entity)

            if entities:
                TleModel.insert_many(entities).execute()
            elif i is None:
                raise ValueError("{} contains no TLE".format(src))

        log.info("{:<20}   {:>3}/{}".format(src, len(entities), i + 1))
예제 #18
0
    def find(self, txt):
        """Retrieve every TLE containing a string. For each object, only get the
        last TLE in database

        Args:
            txt (str)
        Return:
            Tle:
        """

        entities = (self.model.select().where(
            self.model.data.contains(txt)
            | self.model.name.contains(txt)).order_by(
                self.model.norad_id,
                self.model.epoch.desc()).group_by(self.model.norad_id))

        sats = []
        for entity in entities:
            sats.append(
                Tle("%s\n%s" % (entity.name, entity.data), src=entity.src))
        if not sats:
            raise TleNotFound(txt)

        return sats
예제 #19
0
def iss_tle(common_env):
    return Tle("""ISS (ZARYA)
1 25544U 98067A   18124.55610684  .00001524  00000-0  30197-4 0  9997
2 25544  51.6421 236.2139 0003381  47.8509  47.6767 15.54198229111731""")
예제 #20
0
#!/usr/bin/env python

import sys
import numpy as np
import matplotlib.pyplot as plt

from beyond.dates import Date, timedelta
from beyond.io.tle import Tle
from beyond.frames import create_station
from beyond.config import config

tle = Tle("""ISS (ZARYA)
1 25544U 98067A   16086.49419020  .00003976  00000-0  66962-4 0  9998
2 25544  51.6423 110.4590 0001967   0.7896 153.8407 15.54256299992114"""
          ).orbit()

# Station definition
station = create_station('TLS', (43.428889, 1.497778, 178.0))
azims, elevs = [], []

print("    Time      Azim    Elev    Distance   Radial Velocity")
print("=========================================================")

for orb in station.visibility(tle,
                              start=Date.now(),
                              stop=timedelta(hours=24),
                              step=timedelta(seconds=30),
                              events=True):
    elev = np.degrees(orb.phi)
    # Radians are counterclockwise and azimuth is clockwise
    azim = np.degrees(-orb.theta) % 360
예제 #21
0
#!/usr/bin/env python

from beyond.dates import Date, timedelta
from beyond.io.tle import Tle
from beyond.frames import create_station
from beyond.orbits.listeners import stations_listeners, NodeListener, ApsideListener, LightListener

tle = Tle("""ISS (ZARYA)
1 25544U 98067A   17153.89608442  .00001425  00000-0  28940-4 0  9997
2 25544  51.6419 109.5559 0004850 223.1783 180.8272 15.53969766 59532"""
          ).orbit()

# Station definition
station = create_station('TLS', (43.428889, 1.497778, 178.0))

# Listeners declaration
listeners = stations_listeners(station)  # AOS, LOS and MAX elevation
listeners.append(NodeListener())  # Ascending and Descending Node
listeners.append(ApsideListener())  # Apogee and Perigee
listeners.append(LightListener())  # Illumination events

start = Date.now()
stop = timedelta(minutes=100)
step = timedelta(seconds=180)

for orb in tle.iter(start=start, stop=stop, step=step, listeners=listeners):
    event = orb.event if orb.event is not None else ""
    print("{orb.date:%Y-%m-%d %H:%M:%S} {event}".format(orb=orb, event=event))
예제 #22
0
"""

import sys
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from beyond.io.tle import Tle
from beyond.dates import timedelta
from beyond.propagators.keplernum import KeplerNum
from beyond.env.solarsystem import get_body
from beyond.orbits.man import ImpulsiveMan
from beyond.orbits.listeners import ApsideListener, find_event

orb = Tle("""ISS (ZARYA)
1 25544U 98067A   18124.55610684  .00001524  00000-0  30197-4 0  9997
2 25544  51.6421 236.2139 0003381  47.8509  47.6767 15.54198229111731"""
          ).orbit()

start = orb.date
stop = timedelta(minutes=300)
step = timedelta(seconds=60)

# Changing the propagator to Keplerian, as SGP4 is not able to perform maneuvers
orb.propagator = KeplerNum(step, bodies=get_body("Earth"))

# Research for the next perigee
perigee = find_event(orb.iter(stop=stop, listeners=ApsideListener()),
                     'Periapsis')

man1 = ImpulsiveMan(perigee.date, (280, 0, 0), frame="TNW")
orb.maneuvers = [man1]
예제 #23
0
def test_read(tle_txt):

    tle = Tle(tle_txt)

    assert tle.name == "ISS (ZARYA)"
    assert tle.norad_id == 25544
    assert tle.cospar_id == "1998-067A"
    assert tle.epoch == Date(2008, 9, 20, 12, 25, 40, 104192)
    assert tle.ndot == -2.182e-5 * 2
    assert tle.ndotdot == 0.
    assert tle.bstar == -0.11606e-4
    assert tle.i == np.deg2rad(51.6416)
    assert tle.Ω == np.deg2rad(247.4627)
    assert tle.e == 6.703e-4
    assert tle.ω == np.deg2rad(130.5360)
    assert tle.M == np.deg2rad(325.0288)
    assert tle.n == 15.72125391 * 2 * np.pi / 86400.

    tle = Tle(tle_txt.splitlines()[1:])

    assert tle.name == ""

    with raises(TleParseError):
        ref2 = tle_txt[:-1] + "8"
        Tle(ref2)

    orbs = list(Tle.from_string("# comment\n" + tle_txt))
    assert len(orbs) == 1
    assert (orbs[0].orbit() == tle.orbit()).all()

    tle3 = Tle("Name\n" + "\n".join(tle_txt.splitlines()[1:]))
    assert (tle3.orbit() == tle.orbit()).all()

    with raises(TleParseError) as eee:
        l = tle_txt.splitlines()
        l[1] = "3" + l[1][1:]
        Tle("\n".join(l))

    assert str(eee.value) == "Line number check failed"
예제 #24
0
def ref_orb():
    tle = """1 25544U 98067A   08264.51782528 -.00002182  00000-0 -11606-4 0  2927
2 25544  51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537"""

    return Tle(tle).orbit()
예제 #25
0
def tle():
    tle = Tle("""ISS (ZARYA)
1 25544U 98067A   08264.51782528 -.00002182  00000-0 -11606-4 0  2927
2 25544  51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537""")

    return tle.orbit()
예제 #26
0
#!/usr/bin/env python
"""Script showing the position of the ISS at the time of the TLE
and the ground track for the previous and the next orbit
"""

import sys
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path

from beyond.io.tle import Tle
from beyond.dates import Date, timedelta

# Parsing of TLE
tle = Tle("""ISS (ZARYA)
1 25544U 98067A   19004.59354167  .00000715  00000-0  18267-4 0  9995
2 25544  51.6416  95.0104 0002419 236.2184 323.8248 15.53730729149833""")

# Conversion into `Orbit` object
orb = tle.orbit()

# Tables containing the positions of the ground track
latitudes, longitudes = [], []
prev_lon, prev_lat = None, None

period = orb.infos.period
start = orb.date - period
stop = 2 * period
step = period / 100

for point in orb.ephemeris(start=start, stop=stop, step=step):
예제 #27
0
def molniya_tle(common_env):
    return Tle("""MOLNIYA 1-90
1 24960U 97054A   18123.22759647  .00000163  00000-0  24467-3 0  9999
2 24960  62.6812 182.7824 6470982 294.8616  12.8538  3.18684355160009""")