Example #1
0
class AccuratePredictorCalculationErrorTests(TestCase):
    """Check that we can learn from calculation errors and provide patches for corner cases"""
    def setUp(self):
        # Source
        self.db = MemoryTLESource()
        self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, datetime.now())
        # Predictor
        self.predictor = HighAccuracyTLEPredictor(BUGSAT_SATE_ID, self.db)
        self.is_ascending_mock = self._patch(
            'orbit_predictor.accuratepredictor.LocationPredictor.is_ascending')
        self.start = datetime(2017, 3, 6, 7, 51)
        logassert.setup(self, 'orbit_predictor.accuratepredictor')

    def _patch(self, *args, **kwargs):
        patcher = mock.patch(*args, **kwargs)
        self.addCleanup(patcher.stop)
        return patcher.start()

    def test_ascending_failure(self):
        self.is_ascending_mock.return_value = False
        with self.assertRaises(PropagationError):
            self.predictor.get_next_pass(svalbard, self.start)

        self.assertLoggedError(str(svalbard), str(self.start),
                               *BUGSAT1_TLE_LINES)

    def test_descending_failure(self):
        self.is_ascending_mock.return_value = True
        with self.assertRaises(PropagationError):
            self.predictor.get_next_pass(svalbard, self.start)

        self.assertLoggedError(str(svalbard), str(self.start),
                               *BUGSAT1_TLE_LINES)
 def setUp(self):
     # Source
     self.db = MemoryTLESource()
     self.start = datetime(2017, 3, 6, 7, 51)
     self.db.add_tle(SATE_ID, LINES, self.start)
     # Predictor
     self.predictor = HighAccuracyTLEPredictor(SATE_ID, self.db)
     self.end = self.start + timedelta(days=5)
Example #3
0
 def setUp(self):
     # Source
     self.db = MemoryTLESource()
     self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, datetime.now())
     # Predictor
     self.predictor = HighAccuracyTLEPredictor(BUGSAT_SATE_ID, self.db)
     self.is_ascending_mock = self._patch(
         'orbit_predictor.accuratepredictor.LocationPredictor.is_ascending')
     self.start = datetime(2017, 3, 6, 7, 51)
     logassert.setup(self, 'orbit_predictor.accuratepredictor')
Example #4
0
class AccurateVsGpredictTests(TestCase):
    def setUp(self):
        # Source
        self.db = MemoryTLESource()
        self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, datetime.now())
        # Predictor
        self.predictor = HighAccuracyTLEPredictor(BUGSAT_SATE_ID, self.db)

    def test_get_next_pass_with_gpredict_data(self):
        GPREDICT_DATA = """
        -------------------------------------------------------------------------------------------------
         AOS                  TCA                  LOS                  Duration  Max El  AOS Az  LOS Az
        -------------------------------------------------------------------------------------------------
         2014/10/23 01:27:09  2014/10/23 01:33:03  2014/10/23 01:38:57  00:11:47   25.85   40.28  177.59
         2014/10/23 03:02:44  2014/10/23 03:08:31  2014/10/23 03:14:17  00:11:32   20.55  341.35  209.65
         2014/10/23 14:48:23  2014/10/23 14:54:39  2014/10/23 15:00:55  00:12:31   75.31  166.30  350.27
         2014/10/23 16:25:19  2014/10/23 16:29:32  2014/10/23 16:33:46  00:08:27    7.14  200.60  287.00
         2014/10/24 01:35:34  2014/10/24 01:41:37  2014/10/24 01:47:39  00:12:05   32.20   34.97  180.38
         2014/10/24 03:11:40  2014/10/24 03:17:11  2014/10/24 03:22:42  00:11:02   16.30  335.44  213.21
         2014/10/24 14:57:00  2014/10/24 15:03:16  2014/10/24 15:09:32  00:12:32   84.30  169.06  345.11
         2014/10/24 16:34:18  2014/10/24 16:38:02  2014/10/24 16:41:45  00:07:27    5.09  205.18  279.57
         2014/10/25 01:44:01  2014/10/25 01:50:11  2014/10/25 01:56:20  00:12:19   40.61   29.75  183.12
         2014/10/25 03:20:39  2014/10/25 03:25:51  2014/10/25 03:31:04  00:10:25   12.78  329.21  217.10"""  # NOQA

        for line in GPREDICT_DATA.splitlines()[4:]:
            line_parts = line.split()
            aos = datetime.strptime(" ".join(line_parts[:2]),
                                    '%Y/%m/%d %H:%M:%S')
            max_elevation_date = datetime.strptime(" ".join(line_parts[2:4]),
                                                   '%Y/%m/%d %H:%M:%S')
            los = datetime.strptime(" ".join(line_parts[4:6]),
                                    '%Y/%m/%d %H:%M:%S')
            duration = datetime.strptime(line_parts[6], '%H:%M:%S')
            duration_s = timedelta(minutes=duration.minute,
                                   seconds=duration.second).total_seconds()
            max_elev_deg = float(line_parts[7])

            try:
                date = pass_.los  # NOQA
            except UnboundLocalError:
                date = datetime.strptime("2014-10-22 20:18:11.921921",
                                         '%Y-%m-%d %H:%M:%S.%f')

            pass_ = self.predictor.get_next_pass(tortu1, date)
            self.assertAlmostEqual(pass_.aos, aos, delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.los, los, delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.max_elevation_date,
                                   max_elevation_date,
                                   delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.duration_s, duration_s, delta=1)
            self.assertAlmostEqual(pass_.max_elevation_deg,
                                   max_elev_deg,
                                   delta=0.05)
class AccurateVsGpredictTests(TestCase):
    def setUp(self):
        # Source
        self.db = MemoryTLESource()
        self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, datetime.now())
        # Predictor
        self.predictor = HighAccuracyTLEPredictor(BUGSAT_SATE_ID, self.db)

    def test_get_next_pass_with_stk_data(self):
        STK_DATA = """
        ------------------------------------------------------------------------------------------------
         AOS                      TCA                      LOS                      Duration      Max El
        ------------------------------------------------------------------------------------------------
         2014/10/23 01:27:33.224  2014/10/23 01:32:41.074  2014/10/23 01:37:47.944  00:10:14.720   12.76
         2014/10/23 03:01:37.007  2014/10/23 03:07:48.890  2014/10/23 03:14:01.451  00:12:24.000   39.32
         2014/10/23 14:49:34.783  2014/10/23 14:55:44.394  2014/10/23 15:01:51.154  00:12:16.000   41.75
         2014/10/23 16:25:54.939  2014/10/23 16:30:50.152  2014/10/23 16:35:44.984  00:09:50.000   11.45
         2014/10/24 01:35:47.889  2014/10/24 01:41:13.181  2014/10/24 01:46:37.548  00:10:50.000   16.07
         2014/10/24 03:10:23.486  2014/10/24 03:16:27.230  2014/10/24 03:22:31.865  00:12:08.000   30.62
         2014/10/24 14:58:07.378  2014/10/24 15:04:21.721  2014/10/24 15:10:33.546  00:12:26.000   54.83
         2014/10/24 16:34:48.635  2014/10/24 16:39:20.960  2014/10/24 16:43:53.204  00:09:04.000    8.78
         2014/10/25 01:44:05.771  2014/10/25 01:49:45.487  2014/10/25 01:55:24.414  00:11:18.000   20.07
         2014/10/25 03:19:12.611  2014/10/25 03:25:05.674  2014/10/25 03:30:59.815  00:11:47.000   24.09"""  # NOQA

        for line in STK_DATA.splitlines()[4:]:
            line_parts = line.split()
            aos = datetime.strptime(" ".join(line_parts[:2]),
                                    '%Y/%m/%d %H:%M:%S.%f')
            max_elevation_date = datetime.strptime(" ".join(line_parts[2:4]),
                                                   '%Y/%m/%d %H:%M:%S.%f')
            los = datetime.strptime(" ".join(line_parts[4:6]),
                                    '%Y/%m/%d %H:%M:%S.%f')
            duration = datetime.strptime(line_parts[6], '%H:%M:%S.%f')
            duration_s = timedelta(minutes=duration.minute,
                                   seconds=duration.second).total_seconds()
            max_elev_deg = float(line_parts[7])

            try:
                date = pass_.los  # NOQA
            except UnboundLocalError:
                date = datetime.strptime("2014-10-22 20:18:11.921921",
                                         '%Y-%m-%d %H:%M:%S.%f')

            pass_ = self.predictor.get_next_pass(ARG, date)
            self.assertAlmostEqual(pass_.aos, aos, delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.los, los, delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.max_elevation_date,
                                   max_elevation_date,
                                   delta=ONE_SECOND)
            self.assertAlmostEqual(pass_.duration_s, duration_s, delta=2 * 1)
            self.assertAlmostEqual(pass_.max_elevation_deg,
                                   max_elev_deg,
                                   delta=0.05)
Example #6
0
class AccuratePredictorTests(TestCase):
    def setUp(self):
        # Source
        self.db = MemoryTLESource()
        self.start = datetime(2017, 3, 6, 7, 51)
        self.db.add_tle(SATE_ID, LINES, self.start)
        # Predictor
        self.predictor = HighAccuracyTLEPredictor(SATE_ID, self.db)
        self.old_predictor = TLEPredictor(SATE_ID, self.db)
        self.end = self.start + timedelta(days=5)

    def all_passes_old_predictor(self, location, start, end):
        while True:
            try:
                pass_ = self.old_predictor.get_next_pass(location,
                                                         when_utc=start,
                                                         limit_date=end)
                start = pass_.los
                yield pass_
            except Exception:
                break

    def assertEqualOrGreaterPassesAmount(self, location):
        """Compare propagators and check no passes lost and no performance degradation"""
        t0 = time.time()
        old_passes = list(
            self.all_passes_old_predictor(location, self.start, self.end))
        t1 = time.time()
        predicted_passes = list(
            self.predictor.passes_over(location, self.start, self.end))
        t2 = time.time()
        self.assertGreaterEqual(len(predicted_passes), len(old_passes),
                                'We are loosing passes')
        self.assertLessEqual(t2 - t1, t1 - t0, 'Performance is degraded')

    def test_accurate_predictor_find_more_or_equal_passes_amount(self):
        self.assertEqualOrGreaterPassesAmount(
            Location('bad-case-1', 11.937501570612568, -55.35189435098657,
                     1780.674044538666))
        self.assertEqualOrGreaterPassesAmount(tortu1)
        self.assertEqualOrGreaterPassesAmount(svalbard)
        self.assertEqualOrGreaterPassesAmount(
            Location('bad-case-2', -11.011509137116818, 123.29554733688798,
                     1451.5695915302097))
        self.assertEqualOrGreaterPassesAmount(
            Location('bad-case-3', 10.20803236163988, 138.01236517021056,
                     4967.661890730469))
        self.assertEqualOrGreaterPassesAmount(
            Location('less passes', -82.41515032683046, -33.712555446065664,
                     4417.427841452149))

    def test_predicted_passes_are_equal_between_executions(self):
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)
        first_set = list(
            self.predictor.passes_over(location, self.start, self.end))
        second_set = list(
            self.predictor.passes_over(location,
                                       self.start + timedelta(seconds=3),
                                       self.end))

        self.assertEqual(first_set, second_set)

    def test_predicted_passes_have_elevation_positive_and_visible_on_date(
            self):
        end = self.start + timedelta(days=60)
        for pass_ in self.predictor.passes_over(svalbard, self.start, end):
            self.assertGreater(pass_.max_elevation_deg, 0)
            position = self.old_predictor.get_position(
                pass_.max_elevation_date)
            svalbard.is_visible(position)
            self.assertGreaterEqual(pass_.off_nadir_deg, -90)
            self.assertLessEqual(pass_.off_nadir_deg, 90)

    def test_predicted_passes_off_nadir_angle_works(self):
        start = datetime(2017, 3, 6, 13, 30)
        end = start + timedelta(hours=1)
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)

        pass_ = self.predictor.get_next_pass(location,
                                             when_utc=start,
                                             limit_date=end)
        self.assertGreaterEqual(0, pass_.off_nadir_deg)

    @given(start=datetimes(
        min_value=datetime(2017, 1, 1),
        max_value=datetime(2020, 12, 31),
    ),
           location=tuples(floats(min_value=-90, max_value=90),
                           floats(min_value=0, max_value=180),
                           floats(min_value=-200, max_value=9000)))
    @settings(max_examples=10000, deadline=None)
    @example(start=datetime(2017, 1, 26, 11, 51, 51),
             location=(-37.69358328273305, 153.96875, 0.0))
    def test_pass_is_always_returned(self, start, location):
        location = Location('bad-case-1', *location)
        pass_ = self.predictor.get_next_pass(location, start)
        self.assertGreater(pass_.max_elevation_deg, 0)

    def test_aos_deg_can_be_used_in_get_next_pass(self):
        start = datetime(2017, 3, 6, 13, 30)
        end = start + timedelta(hours=1)
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)
        complete_pass = self.predictor.get_next_pass(location,
                                                     when_utc=start,
                                                     limit_date=end)

        pass_with_aos = self.predictor.get_next_pass(location,
                                                     when_utc=start,
                                                     limit_date=end,
                                                     aos_at_dg=5)

        self.assertGreater(pass_with_aos.aos, complete_pass.aos)
        self.assertLess(pass_with_aos.aos, complete_pass.max_elevation_date)
        self.assertAlmostEqual(pass_with_aos.max_elevation_date,
                               complete_pass.max_elevation_date,
                               delta=timedelta(seconds=1))

        self.assertGreater(pass_with_aos.los, complete_pass.max_elevation_date)
        self.assertLess(pass_with_aos.los, complete_pass.los)

        position = self.old_predictor.get_position(pass_with_aos.aos)
        _, elev = location.get_azimuth_elev_deg(position)

        self.assertAlmostEqual(elev, 5, delta=0.1)

        position = self.old_predictor.get_position(pass_with_aos.los)
        _, elev = location.get_azimuth_elev_deg(position)

        self.assertAlmostEqual(elev, 5, delta=0.1)

    def test_predicted_passes_whit_aos(self):
        end = self.start + timedelta(days=60)
        for pass_ in self.predictor.passes_over(svalbard,
                                                self.start,
                                                end,
                                                aos_at_dg=5):
            self.assertGreater(pass_.max_elevation_deg, 5)
            position = self.old_predictor.get_position(pass_.aos)
            _, elev = svalbard.get_azimuth_elev_deg(position)
            self.assertAlmostEqual(elev, 5, delta=0.1)
Example #7
0
 def setUp(self):
     # Source
     self.db = MemoryTLESource()
     self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, datetime.now())
     # Predictor
     self.predictor = HighAccuracyTLEPredictor(BUGSAT_SATE_ID, self.db)
Example #8
0
    def get_predictor(self, sate_id, precise=False):
        """Return a Predictor instance using the current storage."""
        if precise:
            return HighAccuracyTLEPredictor(sate_id, self)

        return TLEPredictor(sate_id, self)
class AccuratePredictorTests(TestCase):
    def setUp(self):
        # Source
        self.db = MemoryTLESource()
        self.start = datetime(2017, 3, 6, 7, 51)
        self.db.add_tle(SATE_ID, LINES, self.start)
        # Predictor
        self.predictor = HighAccuracyTLEPredictor(SATE_ID, self.db)
        self.end = self.start + timedelta(days=5)

    def test_predicted_passes_are_equal_between_executions(self):
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)
        first_set = list(
            self.predictor.passes_over(location, self.start, self.end))
        second_set = list(
            self.predictor.passes_over(location,
                                       self.start + timedelta(seconds=3),
                                       self.end))

        # We use delta=ONE_SECOND because
        # that's the hardcoded value for the precision
        self.assertAlmostEqual(first_set[0].aos,
                               second_set[0].aos,
                               delta=ONE_SECOND)
        self.assertAlmostEqual(first_set[0].los,
                               second_set[0].los,
                               delta=ONE_SECOND)

    def test_predicted_passes_have_elevation_positive_and_visible_on_date(
            self):
        end = self.start + timedelta(days=60)
        for pass_ in self.predictor.passes_over(ARG, self.start, end):
            self.assertGreater(pass_.max_elevation_deg, 0)
            position = self.predictor.get_position(pass_.max_elevation_date)
            ARG.is_visible(position)
            self.assertGreaterEqual(pass_.off_nadir_deg, -90)
            self.assertLessEqual(pass_.off_nadir_deg, 90)

    def test_predicted_passes_off_nadir_angle_works(self):
        start = datetime(2017, 3, 6, 13, 30)
        end = start + timedelta(hours=1)
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)

        pass_ = self.predictor.get_next_pass(location,
                                             when_utc=start,
                                             limit_date=end)
        self.assertGreaterEqual(0, pass_.off_nadir_deg)

    @given(start=datetimes(
        min_value=datetime(2017, 1, 1),
        max_value=datetime(2020, 12, 31),
    ),
           location=tuples(floats(min_value=-90, max_value=90),
                           floats(min_value=0, max_value=180),
                           floats(min_value=-200, max_value=9000)))
    @settings(max_examples=10000, deadline=None)
    @example(start=datetime(2017, 1, 26, 11, 51, 51),
             location=(-37.69358328273305, 153.96875, 0.0))
    def test_pass_is_always_returned(self, start, location):
        location = Location('bad-case-1', *location)
        pass_ = self.predictor.get_next_pass(location, start)
        self.assertGreater(pass_.max_elevation_deg, 0)

    def test_aos_deg_can_be_used_in_get_next_pass(self):
        start = datetime(2017, 3, 6, 13, 30)
        end = start + timedelta(hours=1)
        location = Location('bad-case-1', 11.937501570612568,
                            -55.35189435098657, 1780.674044538666)
        complete_pass = self.predictor.get_next_pass(location,
                                                     when_utc=start,
                                                     limit_date=end)

        pass_with_aos = self.predictor.get_next_pass(location,
                                                     when_utc=start,
                                                     limit_date=end,
                                                     aos_at_dg=5)

        self.assertGreater(pass_with_aos.aos, complete_pass.aos)
        self.assertLess(pass_with_aos.aos, complete_pass.max_elevation_date)
        self.assertAlmostEqual(pass_with_aos.max_elevation_date,
                               complete_pass.max_elevation_date,
                               delta=timedelta(seconds=1))

        self.assertGreater(pass_with_aos.los, complete_pass.max_elevation_date)
        self.assertLess(pass_with_aos.los, complete_pass.los)

        position = self.predictor.get_position(pass_with_aos.aos)
        _, elev = location.get_azimuth_elev_deg(position)

        self.assertAlmostEqual(elev, 5, delta=0.1)

        position = self.predictor.get_position(pass_with_aos.los)
        _, elev = location.get_azimuth_elev_deg(position)

        self.assertAlmostEqual(elev, 5, delta=0.1)

    def test_predicted_passes_whit_aos(self):
        end = self.start + timedelta(days=60)
        for pass_ in self.predictor.passes_over(ARG,
                                                self.start,
                                                end,
                                                aos_at_dg=5):
            self.assertGreater(pass_.max_elevation_deg, 5)
            position = self.predictor.get_position(pass_.aos)
            _, elev = ARG.get_azimuth_elev_deg(position)
            self.assertAlmostEqual(elev, 5, delta=0.1)