def test_from_tle_returns_same_initial_conditions_on_epoch(self): start = datetime(2017, 3, 6, 7, 51) db = MemoryTLESource() db.add_tle(self.SATE_ID, self.LINES, start) keplerian_predictor = KeplerianPredictor.from_tle(self.SATE_ID, db, start) tle_predictor = TLEPredictor(self.SATE_ID, db) epoch = keplerian_predictor._epoch pos_keplerian = keplerian_predictor.get_position(epoch) pos_tle = tle_predictor.get_position(epoch) assert_allclose(pos_keplerian.position_ecef, pos_tle.position_ecef, rtol=1e-11) assert_allclose(pos_keplerian.velocity_ecef, pos_tle.velocity_ecef, rtol=1e-13)
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)
class LocationTestCase(unittest.TestCase): def setUp(self): # Source self.db = MemoryTLESource() self.db.add_tle(SATE_ID, BUGSAT1_TLE_LINES, datetime.datetime.now()) # Predictor self.predictor = TLEPredictor(SATE_ID, self.db) date = datetime.datetime.strptime("2014-10-22 20:18:11.921921", '%Y-%m-%d %H:%M:%S.%f') self.next_pass = self.predictor.get_next_pass(ARG, when_utc=date) def test_compare_eq(self): l1 = Location(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location1") l2 = Location(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location1") self.assertEqual(l1, l2) self.assertEqual(l2, l1) def test_compare_no_eq(self): l1 = Location(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location_other") l2 = Location(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location1") self.assertNotEqual(l1, l2) self.assertNotEqual(l2, l1) def test_compare_eq_subclass(self): class SubLocation(Location): pass l1 = Location(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location1") l2 = SubLocation(latitude_deg=1, longitude_deg=2, elevation_m=3, name="location1") self.assertEqual(l1, l2) self.assertEqual(l2, l1) def test_get_azimuth_elev(self): date = datetime.datetime.strptime("2014-10-21 22:47:29.147740", '%Y-%m-%d %H:%M:%S.%f') azimuth, elevation = ARG.get_azimuth_elev( self.predictor.get_position(date)) self.assertAlmostEqual(degrees(azimuth), 249.7, delta=0.1) self.assertAlmostEqual(degrees(elevation), -52.1, delta=0.1) def test_get_azimuth_elev_deg(self): date = datetime.datetime.strptime("2014-10-21 22:47:29.147740", '%Y-%m-%d %H:%M:%S.%f') azimuth, elevation = ARG.get_azimuth_elev_deg( self.predictor.get_position(date)) self.assertAlmostEqual(azimuth, 249.7, delta=0.1) self.assertAlmostEqual(elevation, -52.1, delta=0.1) def test_is_visible(self): position = self.predictor.get_position(self.next_pass.aos) self.assertTrue(ARG.is_visible(position)) def test_no_visible(self): position = self.predictor.get_position(self.next_pass.los + datetime.timedelta(minutes=10)) self.assertFalse(ARG.is_visible(position)) def test_is_visible_with_deg(self): position = self.predictor.get_position(self.next_pass.aos + datetime.timedelta(minutes=4)) # 21 deg self.assertTrue(ARG.is_visible(position, elevation=4)) def test_no_visible_with_deg(self): position = self.predictor.get_position(self.next_pass.aos + datetime.timedelta(minutes=4)) # 21 deg self.assertFalse(ARG.is_visible(position, elevation=30)) def test_doppler_factor(self): date = datetime.datetime.strptime("2014-10-21 23:06:11.132438", '%Y-%m-%d %H:%M:%S.%f') position = self.predictor.get_position(date) doppler_factor = ARG.doppler_factor(position) self.assertAlmostEqual((2 - doppler_factor) * 437.445e6, 437.445632e6, delta=100)
class AccuratePredictorTests(TestCase): def setUp(self): # Source self.db = MemoryTLESource() self.start = dt.datetime(2017, 3, 6, 7, 51) self.db.add_tle(SATE_ID, LINES, self.start) # Predictor self.predictor = TLEPredictor(SATE_ID, self.db) self.end = self.start + dt.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 + dt.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 + dt.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 = dt.datetime(2017, 3, 6, 13, 30) end = start + dt.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=dt.datetime(2017, 1, 1), max_value=dt.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=dt.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 = dt.datetime(2017, 3, 6, 13, 30) end = start + dt.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=dt.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 + dt.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)
import pandas as pd from orbit_predictor.sources import EtcTLESource from orbit_predictor.predictors import TLEPredictor source = EtcTLESource(filename=r'e:/resource.txt') #source = EtcTLESource(filename=r'd:/visual.txt') predictor = TLEPredictor("WORLDVIEW-2 (WV-2) ", source) #predictor = TLEPredictor('ATLAS CENTAUR 2 ', source) dates = pd.date_range(start="2018-04-01 00:00", periods=1000, freq="30S") latlon = pd.DataFrame(index=dates, columns=["lat", "lon"]) for date in dates: lat, lon, _ = predictor.get_position(date).position_llh latlon.loc[date] = (lat, lon) latlon.plot() plt.figure(figsize=(15, 25)) ax = plt.axes(projection=ccrs.PlateCarree()) ax.stock_img() plt.plot( latlon["lon"], latlon["lat"], 'red', transform=ccrs.Geodetic(), linestyle=":", )