Видимая область Skyfield под Землей Спутник

Как мне рассчитать площадь под спутником Земли, чтобы я мог отобразить полосу земли, покрытую при прохождении спутника?

Есть ли что-нибудь в Skyfield, что могло бы этому облегчить?

Изменить: просто подумал, что я поясню, что я имею в виду под областью под спутником. Мне нужно нанести на график максимальную площадь под спутником, которую можно наблюдать, учитывая, что Земля является сфероидом. Я знаю, как построить путь спутника, но теперь мне нужно построить несколько линий, чтобы представить область, видимую этим спутником, когда он летит над землей.


person Gordon13    schedule 03.03.2019    source источник
comment
Можно рассчитать геоцентрическое положение спутника по центру Земли и сопоставить его с геоцентрическим положением на Земле. Для области вы должны составить справочную таблицу с размерами спутника и построить область вокруг геоцентрической позиции.   -  person rfkortekaas    schedule 03.03.2019
comment
@rfkortekaas Под площадью, я имею в виду максимальную видимую зону с позиции спутника (без учета оптической системы визуализации полезной нагрузки). то, что я пытаюсь сделать прямо сейчас, - это использовать тригонометрию для построения треугольников и вычислить длину края, пересекающего земную поверхность, и вектора от центра Земли до спутника. Я предполагаю, что Земля сферическая, что мне не нравится. Но это должно дать мне достаточно информации, чтобы вычислить приблизительную круглую область, видимую спутником.   -  person Gordon13    schedule 03.03.2019


Ответы (1)


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

Если вы хотите рассчитать видимую область, когда Земля рассматривается как сфера, нам нужно внести некоторые изменения в Skyfield. Со спутником, загруженным с помощью TLE api, вы можете легко получить дополнительную точку с положением на Земле. Библиотека называет это положением Geocentric, но на самом деле это положение Geodetic (где Земля выглядит как сплюснутый сфероид). Чтобы исправить это, нам нужно настроить subpoint класса Geocentric, чтобы использовать вычисление для позиции Geocentric, а не для позиции Geodetic. Из-за ошибки и отсутствия информации в функции reverse_terra нам также необходимо заменить эту функцию. И нам нужно иметь возможность получить радиус Земли. Это приводит к следующему:

from skyfield import api
from skyfield.positionlib import ICRF, Geocentric
from skyfield.constants import (AU_M, ERAD, DEG2RAD,
                                IERS_2010_INVERSE_EARTH_FLATTENING, tau)
from skyfield.units import Angle

from numpy import einsum, sqrt, arctan2, pi, cos, sin

def reverse_terra(xyz_au, gast, iterations=3):
    """Convert a geocentric (x,y,z) at time `t` to latitude and longitude.
    Returns a tuple of latitude, longitude, and elevation whose units
    are radians and meters.  Based on Dr. T.S. Kelso's quite helpful
    article "Orbital Coordinate Systems, Part III":
    https://www.celestrak.com/columns/v02n03/
    """
    x, y, z = xyz_au
    R = sqrt(x*x + y*y)

    lon = (arctan2(y, x) - 15 * DEG2RAD * gast - pi) % tau - pi
    lat = arctan2(z, R)

    a = ERAD / AU_M
    f = 1.0 / IERS_2010_INVERSE_EARTH_FLATTENING
    e2 = 2.0*f - f*f
    i = 0
    C = 1.0
    while i < iterations:
        i += 1
        C = 1.0 / sqrt(1.0 - e2 * (sin(lat) ** 2.0))
        lat = arctan2(z + a * C * e2 * sin(lat), R)
    elevation_m = ((R / cos(lat)) - a * C) * AU_M
    earth_R = (a*C)*AU_M
    return lat, lon, elevation_m, earth_R

def subpoint(self, iterations):
    """Return the latitude an longitude directly beneath this position.

    Returns a :class:`~skyfield.toposlib.Topos` whose ``longitude``
    and ``latitude`` are those of the point on the Earth's surface
    directly beneath this position (according to the center of the
    earth), and whose ``elevation`` is the height of this position
    above the Earth's center.
    """
    if self.center != 399:  # TODO: should an __init__() check this?
        raise ValueError("you can only ask for the geographic subpoint"
                            " of a position measured from Earth's center")
    t = self.t
    xyz_au = einsum('ij...,j...->i...', t.M, self.position.au)
    lat, lon, elevation_m, self.earth_R = reverse_terra(xyz_au, t.gast, iterations)

    from skyfield.toposlib import Topos
    return Topos(latitude=Angle(radians=lat),
                    longitude=Angle(radians=lon),
                    elevation_m=elevation_m)

def earth_radius(self):
    return self.earth_R

def satellite_visiable_area(earth_radius, satellite_elevation):
    """Returns the visible area from a satellite in square meters.

    Formula is in the form is 2piR^2h/R+h where:
        R = earth radius
        h = satellite elevation from center of earth
    """
    return ((2 * pi * ( earth_radius ** 2 ) * 
            ( earth_radius + satellite_elevation)) /
            (earth_radius + earth_radius + satellite_elevation))


stations_url = 'http://celestrak.com/NORAD/elements/stations.txt'
satellites = api.load.tle(stations_url)
satellite = satellites['ISS (ZARYA)']
print(satellite)

ts = api.load.timescale()
t = ts.now()

geocentric = satellite.at(t)
geocentric.subpoint = subpoint.__get__(geocentric, Geocentric)
geocentric.earth_radius = earth_radius.__get__(geocentric, Geocentric)

geodetic_sub = geocentric.subpoint(3)

print('Geodetic latitude:', geodetic_sub.latitude)
print('Geodetic longitude:', geodetic_sub.longitude)
print('Geodetic elevation (m)', int(geodetic_sub.elevation.m))
print('Geodetic earth radius (m)', int(geocentric.earth_radius()))

geocentric_sub = geocentric.subpoint(0)
print('Geocentric latitude:', geocentric_sub.latitude)
print('Geocentric longitude:', geocentric_sub.longitude)
print('Geocentric elevation (m)', int(geocentric_sub.elevation.m))
print('Geocentric earth radius (m)', int(geocentric.earth_radius()))
print('Visible area (m^2)', satellite_visiable_area(geocentric.earth_radius(), 
                                                    geocentric_sub.elevation.m))
person rfkortekaas    schedule 04.03.2019
comment
Это действительно здорово, большое спасибо. А пока подойдет сферическая земля. Я думаю, что способ сделать это со сжатой сферой - это как-то подогнать этот сфероид к вычисленным координатам Земли в Skyfield, а затем получить конус для представления обзора спутника (при условии, что оптическая система увеличена), из координаты спутника, а затем пересечь их со сфероидом. Но это вопрос другого дня! - person Gordon13; 06.03.2019
comment
Какую ошибку вы исправили в функции reverse_terra()? Мне интересно исправить это, если функция в Skyfield неверна - похоже, вы добавили новый возвращаемый параметр, но не обязательно изменили способ вычисления других параметров? - person Brandon Rhodes; 25.03.2019
comment
@BrandonRhodes Ошибка в функции reverse_terra() заключается в том, что C не инициализируется. Когда iterations равны нулю для геоцентрической позиции, это не удается из-за этого. Добавление возвращаемого параметра earth_R было отсутствующей функцией для расчета спутника над центром Земли. - person rfkortekaas; 25.03.2019
comment
Никогда не считал нулевые итерации, интересно! Параметр был там на тот случай, если люди захотят больше итераций, а не меньше. Я подумаю о добавлении теста для случая нулевых итераций, хотя было бы проще выделить его как отдельную процедуру, поскольку в этом случае он возвращает другую систему координат. Может быть, подпрограмма должна возвращать ошибку для итераций ≤ 0. В любом случае спасибо за пояснение! - person Brandon Rhodes; 26.03.2019
comment
@BrandonRhodes, пожалуйста. Вы правы насчет другой системы координат, но я думаю, что вы их перепутали. То, что reverse_terra возвращает с 3 итерациями, - это координата geodetic, а с 0 итерациями - координата geocentric. - person rfkortekaas; 26.03.2019
comment
Skyfield использует термин Geocentric для вектора x, y, z, источником которого является геоцентр, что соответствует использованию USNO термина в исходном коде, результаты которого Skyfield предназначены для сопоставления. Я старался избегать применения этого термина к широте и долготе, которые Skyfield всегда считает геодезическими = истинные широта и долгота. Если вы найдете место, которое я случайно назвал геоцентрическим по широте и долготе, дайте мне знать, и я уберу эти ссылки. - person Brandon Rhodes; 27.03.2019