Эффективный способ распространения спутникового каталога во времени
Постановка задачи
Мне нужно распространять весь каталог последних TLE (нужна бесплатная учетная запись для просмотра) с space-track.org, используя skyfield
или похожие. Обычно в списке 15–16 тыс. TLE. У меня это работает, но это очень медленно. На порядок часов используется 46 ядер на сервере.
Не замужем за skyfield
, Если astropy
или же pyephem
или что-то еще быстрее, я бы с радостью принял ответ, который показывает, что я пытаюсь сделать, используя это.
Минимальный пример
Для моего приложения я загружаю TLE в фрейм данных Pandas и выполняю там анализ, поэтому я буду держать свой пример в мире Pandas. Ниже приведен минимальный пример.
Предполагая, что каталог спутников был сохранен как catalog.txt
, настройте среду, затем прочитайте TLE, сгенерируйте sf.sgp4lib.EarthSatellite
объекты, и загрузите все в фрейм данных Pandas. Мы также смещаем позиции к некоторому месту наблюдения. Я оставляю выбор места наблюдения за читателем (0, 0, 0 было бы хорошо):
import skyfield as sf
import pandas as pd
from skyfield.api import load, Topos
from datetime import datetime, timezone, timedelta
with open('catalog.txt', 'r') as f:
tle_list = [line.strip() for line in f.read().split('\n')
if line is not '']
data = []
for i in range(0, len(tle), 2): # every two lines
temp = {}
temp['tle1'] = tle_list[i]
temp['tle2'] = tle_list[i+1]
temp['earthsat'] = sf.sgp4lib.EarthSatellite(tle_list[i],
tle_list[i+1])
data.append(temp)
df = pd.DataFrame(data=data)
site = Topos(latitude_degrees=site_lat,
longitude_degrees=site_lon,
elevation_m=site_alt)
df['earthsat'] = df.earthsat - site # offset to site location
2,1 с ± 20 мс на цикл (среднее ± стандартное отклонение из 7 циклов, по 1 циклу каждый)
Создайте массив объектов datetime с учетом часового пояса, по которым будут распространяться все спутники. Здесь я выбрал каждые 10 минут с 4 часов до полуночи в день, когда я пишу это, до 4 часов после.
ts = load.timescale()
tz = timezone(timedelta(hours=-4)) # Eastern or whatever timezone
midnight = datetime(2018, 4, 4, 0, 0, 0, tzinfo=tz) # midnight today
start = midnight - timedelta(hours=4)
end = midnight + timedelta(hours=4)
delta_time = timedelta(minutes=10)
# This is ugly, but I had issues using linspace or arange...
times = [start]
now = start
while now <= end:
now += delta_time
times.append(now)
189 мс ± 36,9 мс на цикл (среднее ± стандартное отклонение из 7 циклов, по 10 циклов в каждом)
Наконец, рассчитайте астрометрические положения для каждого временного шага для каждого спутника. Это то, что нужно навсегда. Слишком долго, чтобы я мог запустить снова, чтобы получить время, но это порядка нескольких часов при использовании 46 ядер на сервере.
df['astrometric'] = df.earthsat.apply(lambda x: [x.at(ts.utc(time)) for time in times])
Дополнительные детали
Я нашел это обсуждение массивов дат в документации, которая предлагает передать весь массив сразу: x.at(ts.utc(times))
, Пока это занимает меньше ядер и работает немного быстрее, но все равно занимает слишком много времени.
Я немного обошел это замедление, создав генераторы для астрометрии (изначально, поэтому я отказался от прохождения целого times
сразу в массив), но в конце концов мне действительно нужно оценивать вещи, поэтому я не могу избежать тяжелой работы навсегда.
В случае, если окончательный вариант использования поддается определенному ускорению, мне, в конечном счете, необходимо получить углы наблюдения от объекта из этих объектов, поэтому [x.altaz() for x in row.astrometrics]
Тип вещи.
Мысли о решении
Сейчас я думаю, что я вычисляю положение места наблюдения на каждом временном шаге в течение ночи для каждого спутника в каталоге. Я могу ошибаться, но если я прав, то думаю, что я бы увидел довольно приличное ускорение (может быть, недостаточно), рассчитав это один раз, а затем просмотрев его для каждого нового спутника. Кто-нибудь знает, как это сделать?
Кроме того, если есть более быстрая реализация пропагатора орбиты или способ ускорить реализацию скайфилда, я бы с радостью принял ответ, который показывает, как сделать то, что я пытаюсь сделать, используя это (включая astropy
а также pyephem
теги).
Спасибо.
0 ответов
Мой лучший совет - использовать НАСА SPICE Toolkit для этого вида работ. Это позволяет вам загружать двухстрочные элементы, а затем использовать ядра NAIF/SPICE НАСА для выполнения остальной части работы (вы можете также найти некоторые спутники в других форматах, но TLE в порядке).
Если бы вы работали в C, вы бы использовали метод getelm_c, чтобы прочитать их, и spkpos_c, чтобы получить позицию. К счастью, есть оболочка для Python, которая называется spiceypy!
getelm_c
метод обернут в spiceypy.spiceypy.getelm(frstyr, lineln, lines)
загрузить в свой TLE. Вы бы их хотели использовать spiceypy.spiceypy.spkpos(targ, et, ref, abcorr, obs)
чтобы получить вашу позицию относительно контрольного тела.
Я предлагаю использовать документы из spiceypy, в частности, положение примера Cassini, чтобы убедиться, что у вас есть все правильные файлы на месте, если вы решите использовать ядра SPICE НАСА: https://spiceypy.readthedocs.io/en/master/exampleone.html