Целимся и общаемся со спутниками: Часть первая — целимся программно

rfrqyb8g75teydwige-xkqncwe8.jpeg

Дизклеймер — я практически не знаком с астрономией, только вот в Kerbal на орбиту выходил и как-то мне удалось сделать парочку орбитальных маневров. Но тема интересная, так, что даже если я где-то не верно выражаюсь — сорян.

Все ссылочки в конце статьи.

На всякий случай, под видимостью подразумевается не только видимость глазом.

Для того, что бы начать взаимодействовать со спутником, он должен быть виден в небе. Видимость спутника зависит от того, где он находится на текущий момент относительно вашего расположения. Существуют спутники которые никогда не видны из некоторых локаций. К таким относятся спутники находящиеся на геосинхронной орбите — они видны только с половины Земли, так как их движение синхронизировано с вращением Земли.

ekcxc5k_trlnq3fg_jywi2_zhmk.gif

Так же на видимость спутника влияет наклон орбиты.

ef6e91fb4632455184dcff340dc9694d.jpg

Орбиты с низким наклоном находятся ближе к экватору. Находясь на экваторе, вы наверняка увидите спутники в какой-то момент времени. Если вы находитесь выше по широте, то видимость спутника зависит от высоты его орбиты. Чем дальше спутник от Земли, тем больше локаций с которых его можно увидеть. Например спутник LEMUR-2 JOEL, находится на высоте 640 км и может быть виден в Найроби и Дар-эс-Салам, но его никогда не видно в Ереване.
O3B FM8 который находится на высоте 8,000 км, можно увидеть из Стокгольма или южней из Tierra del Fuego. Оба спутника с очень низким наклоном и возле экватора. Высота спутника с высоким наклоном (полярная орбита) так же влияет на то откуда он может быть виден, но в основном они видны отовсюду (если хорошенько подождать, пока он пролетит в поле вашего зрения).

nldkfrl9eljd6-f2vx6il3dovpw.png


Что такое орбита?

dzvhv9lwcyvalfjautrngdortxk.jpeg
(Откройте изображение в новой вкладке, что бы получше разглядеть)

Все орбиты разные. Большинство спутников находятся в 3-х основных зонах Низкая околоземная орбита (LEO), Средняя околоземная (MEO), или Геосинхронной орбите (GSO).

Спутники на низкой орбите, находятся ближе всех к поверхности Земли (до 2,000 км), требуют меньше всего энергии для выхода на такую орбиту (так как если вы играли в Kerbal, то знаете, чем больше скорость тем выше орбита, а скорость это кол-во сожженного топлива и время работы двигателя), а так же с ними проще общаться. На такой орбите находится Международная космическая станция и спутники телефонной связи. Такие спутники движутся по небу довольно быстро и находятся в поле зрения около 20–30 минут. Но до нового пролета ждать примерно столько же. Вращение вокруг земли занимает около 90 минут.

Медиана, средняя орбита или Medium Earth Orbit  — орбита, которая находится между геосинхронной орбитой (GSO) и низкой орбитой (LEO). Большинство спутников находятся на высоте между 10,000 км и 30,000 км. Орбиты между 2000 км и 8000 км не желательны из-за высокой радиации от Van Allen Belt (пояса радиации).
На таких орбитах много GPS спутников. Они так же двигаются вокруг поверхности Земли, но медленней (так как орбита выше). Оборот вокруг Земли занимает примерно 12 часов.

mmbxxhilnkgh_sjgyptqy3dnheq.gif

На геосинхронной орбите спутники делают 1 оборот за день. Находятся они на высоте 36,000 км. Если геосинхронный спутник вращается вокруг экватора, то такая орбита называется геостационарная. Спутники всегда находятся в одном и том же положении относительно наблюдателя на земле. Словно они находятся на высокой вышке. Задержка сигнала достигает пол секунды.


Зачем целиться в спутник?


Так как я знаком с FPV хобби, я что-то уже знаю про антенны. Минимально, но понимаю, что есть антенны направленные которые словно фонарик, а есть всенаправленные антенны.

kjv_8k8clrp_twygb_cviziprju.gif

Направленные антенны лучше принимают и отправляют сигналы, но они ограничены «полем зрения».

В хобби обычно комбинируют антенны:

infumvda7mjkhlskwqkxirtwso8.jpeg
(плоские это направленные патч антенны, а ниже всенаправленные)

Но вернемся к нашей теме, для общения со спутниками используют такие вот параболические антенны:

_fytggd4_4qfxk4wtpbissvq0hg.jpeg

Работают следующим образом — собирая сигнал на своей параболической «тарелке» они концентрируют его на «feed antenna». Не могу найти как это называется по-русски. Скорей всего принимающая антенна.

Можно провести аналогию с солнечными электростанциями:

0b3w93nshxeozu32feedmffgpok.png

Слежение за спутником (прицеливание вашей направленной антенны), технически не обязательно для отправки и получения сигнала. Но вместо того, что бы тратить энергию и отправлять сигналы во все стороны, это можно делать концентрировано. Такой подход более эффективен и позволяет использовать антенны поменьше.


Находим положение спутника относительно вашей локации

Для получениях данных о движении спутников относительно конкретной локации, можно воспользоваться библиотекой Skyfield или публичной базой данных. С помощью этих данных можно предсказать, когда конкретный спутник будет над вами и в поле зрения. Следовательно, и прицеливать антенну.

Например мы можем предсказать когда МКС пролетит над вами, и если на улице не слишком светло, то вы сможете увидеть МКС не вооруженным глазом. Станция делает один оборот в 90 минут, двигается она по ночному небу очень быстро. Относительно вас она будет в поле зрения не более 8 минут. Если станция будет пролетать низко — коло 10 — 2- градусов над горизонтом, то возможно из-за зданий и деревьев ее будет сложно разглядеть. Но как я сказал выше, мы можем подождать, пока пролет станции будет повыше и использовать данные для предсказания положения в будущем.

Угол спутника к горизонту от вашей локации, называют высотой (altitude) или elevation.
Горизонтальная система координат.

ibonamsx_diewrvwnmp6ukkjcwg.png

Для того, что бы хорошо наблюдать спутник, надо примерно 45 градусов. Другой параметр который нам интересен — азимут. Это направление, куда надо смотреть. Азимут равный 0 градусов находится на севере, 180 на юге.

Skyfield написан на Python, по этому придется использовать Python (3). Конечно, можно сделать и на другом языке, но не будем усложнять себе задачу.

Нам необходимо поставить одну зависимость:

pip3 install skyfield

И подключить все необходимые пакеты следующим образом:

index.py

import datetime
import time
from skyfield.api import load, Topos, EarthSatellite

Далее несколько необходимых нам констант:

TLE_FILE = "https://celestrak.com/NORAD/elements/active.txt" # DB file to download
ISS_NAME = "ISS (ZARYA)"

# Coordinats
# 57°00'13.7"N 37°02'53.7"E
# Kimrsky District, Tver Oblast, Russia
LONGITUDE = 57.003810
LATITUDE = 37.048262

Основной класс:

class SatelliteObserver:

    def __init__(self, where: Topos, what: EarthSatellite):
        self.where = where
        self.sat = what
        self.sat_name = what.name
        self.ts = load.timescale(builtin=True)
# ...

В этом «конструкторе» мы принимаем координаты, название спутника (такое, как в данных), и EarthSatellite своего рода обертка которая нам позволяет работать с данными.

kbmzx46s_wu_mr0bwiuguncr7ke.png

# ...
@classmethod
    def from_strings(cls, longitude: str or float, latitude: str or float, sat_name: str, tle_file: str) -> 'SatelliteObserver':
        place = Topos(latitude, longitude)
        satellites = load.tle(tle_file)
        print("loaded {} sats from {}".format(len(satellites), tle_file))
        _sats_by_name = {sat.name: sat for sat in satellites.values()}
        satellite = _sats_by_name[sat_name]
        return cls(place, satellite)
# ...

В данной функции используем векторную функцию Topos которая знает о месте на Земле (определение из этой функции).

Затем загружаем все спутники из файла, и находим интересующий нас _sats_by_name[sat_name].

def altAzDist_at(self, at: float) -> (float, float, float):
        """
        :param at: Unix time GMT (timestamp)
        :return: (altitude, azimuth, distance)
        """
        current_gmt = datetime.datetime.utcfromtimestamp(at)
        current_ts = self.ts.utc(current_gmt.year, current_gmt.month, current_gmt.day, current_gmt.hour,
                            current_gmt.minute, current_gmt.second + current_gmt.microsecond / 1000000.0)
        difference = self.sat - self.where
        observer_to_sat = difference.at(current_ts)
        altitude, azimuth, distance = observer_to_sat.altaz()
        return (altitude.degrees, azimuth.degrees, distance.km)

Данный кусок кода отвечает за нахождение высоты, азимута и расстояние на время переданное в at и относительно заданной позиции.

    def current_altAzDist(self) -> (float, float, float):
        return self.altAzDist_at(time.mktime(time.gmtime()))

    def above_horizon(self, at: float) -> bool:
        """
        :param at: Unix time GMT
        :return:
        """
        (alt, az, dist) = self.altAzDist_at(at)
        return alt > 0

current_altAzDist (self) — небольшая обертка для передачи времени на данный момент и функция определения, находится ли спутник выше горизонта.

И наконец main функция:

def main():
    iss = SatelliteObserver.from_strings(LONGITUDE, LATITUDE, ISS_NAME, TLE_FILE)
    elevation, azimuth, distance = iss.current_altAzDist()
    visible = "visible!" if elevation > 0 else "not visible =/"
    print("ISS from latitude {}, longitude {}: azimuth {}, elevation {} ({})".format(LATITUDE, LONGITUDE, azimuth, elevation, visible))

if __name__ == "__main__":
    main()


Полный код
import datetime
import time
from skyfield.api import load, Topos, EarthSatellite

TLE_FILE = "https://celestrak.com/NORAD/elements/active.txt" # DB file to download
ISS_NAME = "ISS (ZARYA)"

# Coordinats
# 57°00'13.7"N 37°02'53.7"E
# Kimrsky District, Tver Oblast, Russia
LONGITUDE = 57.003810
LATITUDE = 37.048262

class SatelliteObserver:

    def __init__(self, where: Topos, what: EarthSatellite):
        self.where = where
        self.sat = what
        self.sat_name = what.name
        self.ts = load.timescale(builtin=True)

    @classmethod
    def from_strings(cls, longitude: str or float, latitude: str or float, sat_name: str, tle_file: str) -> 'SatelliteObserver':
        place = Topos(latitude, longitude)
        satellites = load.tle(tle_file)
        print("loaded {} sats from {}".format(len(satellites), tle_file))
        _sats_by_name = {sat.name: sat for sat in satellites.values()}
        satellite = _sats_by_name[sat_name]
        return cls(place, satellite)

    def altAzDist_at(self, at: float) -> (float, float, float):
        """
        :param at: Unix time GMT (timestamp)
        :return: (altitude, azimuth, distance)
        """
        current_gmt = datetime.datetime.utcfromtimestamp(at)
        current_ts = self.ts.utc(current_gmt.year, current_gmt.month, current_gmt.day, current_gmt.hour,
                            current_gmt.minute, current_gmt.second + current_gmt.microsecond / 1000000.0)
        difference = self.sat - self.where
        observer_to_sat = difference.at(current_ts)
        altitude, azimuth, distance = observer_to_sat.altaz()
        return (altitude.degrees, azimuth.degrees, distance.km)

    def current_altAzDist(self) -> (float, float, float):
        return self.altAzDist_at(time.mktime(time.gmtime()))

    def above_horizon(self, at: float) -> bool:
        """
        :param at: Unix time GMT
        :return:
        """
        (alt, az, dist) = self.altAzDist_at(at)
        return alt > 0

def main():
    iss = SatelliteObserver.from_strings(LONGITUDE, LATITUDE, ISS_NAME, TLE_FILE)
    elevation, azimuth, distance = iss.current_altAzDist()
    visible = "visible!" if elevation > 0 else "not visible =/"
    print("ISS from latitude {}, longitude {}: azimuth {}, elevation {} ({})".format(LATITUDE, LONGITUDE, azimuth, elevation, visible))

if __name__ == "__main__":
    main()

Для запуска программы используем python3:

python3 index.py

Результат выполнения —

[#################################] 100% active.txt
loaded 6351 sats from https://celestrak.com/NORAD/elements/active.txt
ISS from latitude 37.048262, longitude 57.00381: azimuth 55.695482310974974, elevation 6.232187065056109 (visible!)

В данном выводе мы получаем градус (как в компасе) в какую сторону смотреть и угол (elevation), как высоко над горизонтом.

(visible!) в данном случае — видно!… Но 6 градусов в городе маловато. Как я писал выше, надо хотя бы 45.

Такие данные можно передавать на сервопривод и управлять направление антенны в реальном времени. Но об этом в следующих статьях.

Данные которые мы скачиваем (https://celestrak.com/NORAD/elements/active.txt) могут устаревать, так как спутники постоянно корректируют свою орбиту по разным причинам, по этому следует скачивать свежее как можно чаще.

Спасибо за внимание.


Литература

https://nyan-sat.com/chapter0.html
геосинхронная орбита
наклон орбиты
полярная орбита

© Habrahabr.ru