def setUp(self): # Source self.db = MemoryTLESource() self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, dt.datetime.utcnow()) # Predictor self.predictor = TLEPredictor(BUGSAT_SATE_ID, self.db)
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, dt.datetime.utcnow()) # Predictor self.predictor = TLEPredictor(BUGSAT_SATE_ID, self.db) self.is_ascending_mock = self._patch( 'orbit_predictor.predictors.base.LocationPredictor._is_ascending') self.start = dt.datetime(2017, 3, 6, 7, 51) logassert.setup(self, 'orbit_predictor.predictors.pass_iterators') 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( ARG, self.start, location_predictor_class=LocationPredictor) self.assertLoggedError(str(ARG), 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( ARG, self.start, location_predictor_class=LocationPredictor) self.assertLoggedError(str(ARG), str(self.start), *BUGSAT1_TLE_LINES)
def setUp(self): tle_lines = ( "1 42760U 17034C 19070.46618549 .00000282 00000-0 30543-4 0 9995", "2 42760 43.0166 56.1509 0009676 356.3576 146.0151 15.09909885 95848", ) self.db = MemoryTLESource() self.db.add_tle("42760U", tle_lines, dt.datetime.now()) self.predictor = TLEPredictor("42760U", self.db)
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 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(tortu1, when_utc=date)
class SkippedPassesRegressionTests(TestCase): """Check that we do not skip passes""" # See https://github.com/satellogic/orbit-predictor/issues/99 def setUp(self): self.db = MemoryTLESource() self.db.add_tle(TRICKY_SAT_ID, TRICKY_SAT_TLE_LINES, dt.datetime.now()) self.predictor = TLEPredictor(TRICKY_SAT_ID, self.db) @pytest.mark.xfail(reason="Legacy LocationPredictor skips some passes") def test_pass_is_not_skipped_old(self): loc = Location( name="loc", latitude_deg=-15.137152171507697, longitude_deg=-0.4276612055384211, elevation_m=1.665102900005877e-05, ) PASS_DATE = dt.datetime(2020, 9, 25, 9, 2, 6) LIMIT_DATE = dt.datetime(2020, 9, 25, 10, 36, 0) predicted_passes = list( self.predictor.passes_over( loc, when_utc=PASS_DATE, limit_date=LIMIT_DATE, aos_at_dg=0, max_elevation_gt=0, location_predictor_class=LocationPredictor, )) assert predicted_passes @pytest.mark.skipif(sys.version_info < (3, 5), reason="Not installing SciPy in Python 3.4") def test_pass_is_not_skipped_smart(self): loc = Location( name="loc", latitude_deg=-15.137152171507697, longitude_deg=-0.4276612055384211, elevation_m=1.665102900005877e-05, ) PASS_DATE = dt.datetime(2020, 9, 25, 9, 2, 6) LIMIT_DATE = dt.datetime(2020, 9, 25, 10, 36, 0) predicted_passes = list( self.predictor.passes_over( loc, when_utc=PASS_DATE, limit_date=LIMIT_DATE, aos_at_dg=0, max_elevation_gt=0, location_predictor_class=SmartLocationPredictor, )) assert predicted_passes
def setUp(self): # Source self.db = MemoryTLESource() self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, dt.datetime.utcnow()) # Predictor self.predictor = TLEPredictor(BUGSAT_SATE_ID, self.db) self.is_ascending_mock = self._patch( 'orbit_predictor.predictors.base.LocationPredictor._is_ascending') self.start = dt.datetime(2017, 3, 6, 7, 51) logassert.setup(self, 'orbit_predictor.predictors.pass_iterators')
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)
def from_tle(cls, sate_id, source, date=None): """Returns approximate keplerian elements from TLE. The conversion between mean elements in the TEME reference frame to osculating elements in any standard reference frame is not well defined in literature (see Vallado 3rd edition, pp 236 to 240) """ # Get latest TLE, or the one corresponding to a specified date if date is None: date = datetime.datetime.utcnow() tle = source.get_tle(sate_id, date) # Retrieve TLE epoch and corresponding position epoch = twoline2rv(tle.lines[0], tle.lines[1], wgs84).epoch pos = TLEPredictor(sate_id, source).get_position(epoch) # Convert position from ECEF to ECI gmst = gstime_from_datetime(epoch) position_eci = coordinate_systems.ecef_to_eci(pos.position_ecef, gmst) velocity_eci = coordinate_systems.ecef_to_eci(pos.velocity_ecef, gmst) # Convert position to Keplerian osculating elements p, ecc, inc, raan, argp, ta = rv2coe(wgs84.mu, np.array(position_eci), np.array(velocity_eci)) sma = p / (1 - ecc**2) return cls(sma, ecc, degrees(inc), degrees(raan), degrees(argp), degrees(ta), epoch)
def get_predictor_from_tle_lines(tle_lines): db = MemoryTLESource() sgp4_sat = Satrec.twoline2rv(tle_lines[0], tle_lines[1]) db.add_tle( sgp4_sat.satnum, tuple(tle_lines), datetime_from_jday(sgp4_sat.jdsatepoch, sgp4_sat.jdsatepochF), ) predictor = TLEPredictor(sgp4_sat.satnum, db) return predictor
class AccurateVsGpredictTests(TestCase): def setUp(self): # Source self.db = MemoryTLESource() self.db.add_tle(BUGSAT_SATE_ID, BUGSAT1_TLE_LINES, dt.datetime.utcnow()) # Predictor self.predictor = TLEPredictor(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 = dt.datetime.strptime(" ".join(line_parts[:2]), '%Y/%m/%d %H:%M:%S.%f') max_elevation_date = dt.datetime.strptime( " ".join(line_parts[2:4]), '%Y/%m/%d %H:%M:%S.%f') los = dt.datetime.strptime(" ".join(line_parts[4:6]), '%Y/%m/%d %H:%M:%S.%f') duration = dt.datetime.strptime(line_parts[6], '%H:%M:%S.%f') duration_s = dt.timedelta(minutes=duration.minute, seconds=duration.second).total_seconds() max_elev_deg = float(line_parts[7]) try: date = pass_.los # NOQA except UnboundLocalError: date = dt.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)
def from_tle(cls, sate_id, source, date=None): """Returns approximate keplerian elements from TLE. The conversion between mean elements in the TEME reference frame to osculating elements in any standard reference frame is not well defined in literature (see Vallado 3rd edition, pp 236 to 240) """ # Get latest TLE, or the one corresponding to a specified date if date is None: date = dt.datetime.utcnow() # Retrieve TLE position at given date as starting point pos = TLEPredictor(sate_id, source).get_position(date) return cls(*pos.osculating_elements, epoch=date)
class LOSComputationRegressionTests(TestCase): """Check that the LOS is computed correctly""" # See https://github.com/satellogic/orbit-predictor/issues/104 def setUp(self): tle_lines = ( "1 42760U 17034C 19070.46618549 .00000282 00000-0 30543-4 0 9995", "2 42760 43.0166 56.1509 0009676 356.3576 146.0151 15.09909885 95848", ) self.db = MemoryTLESource() self.db.add_tle("42760U", tle_lines, dt.datetime.now()) self.predictor = TLEPredictor("42760U", self.db) @pytest.mark.skipif(sys.version_info < (3, 5), reason="Not installing SciPy in Python 3.4") def test_los_is_correctly_computed(self): loc = Location( name='loc', latitude_deg=-34.61315, longitude_deg=-58.37723, elevation_m=30, ) PASS_DATE = dt.datetime(2019, 1, 1, 0, 0) LIMIT_DATE = dt.datetime(2019, 1, 15, 0, 0) predicted_passes = list( self.predictor.passes_over( loc, when_utc=PASS_DATE, limit_date=LIMIT_DATE, aos_at_dg=0, max_elevation_gt=0, location_predictor_class=SmartLocationPredictor, )) assert predicted_passes
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)
def setUpClass(cls): # Source cls.db = MemoryTLESource() cls.db.add_tle(SATE_ID, BUGSAT1_TLE_LINES, datetime.datetime.now()) # Predictor cls.predictor = TLEPredictor(SATE_ID, cls.db)
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)
def get_predictor_from_tle_lines(tle_lines): db = MemoryTLESource() sgp4_sat = twoline2rv(tle_lines[0], tle_lines[1], wgs84) db.add_tle(sgp4_sat.satnum, tuple(tle_lines), sgp4_sat.epoch) predictor = TLEPredictor(sgp4_sat.satnum, db) return predictor
def setUp(self): self.db = MemoryTLESource() self.db.add_tle(TRICKY_SAT_ID, TRICKY_SAT_TLE_LINES, dt.datetime.now()) self.predictor = TLEPredictor(TRICKY_SAT_ID, self.db)
def get_predictor(self, sate_id): """Return a Predictor instance using the current storage.""" return TLEPredictor(sate_id, self)
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)
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)
import matplotlib.pyplot as plt import cartopy.crs as ccrs 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"],