Почему PRN, полученный от Android, отличается от рассчитанного TLE

Я хочу использовать данные TLE для расчета азимута и высоты каждого спутника GPS в местоположении пользователя.
Чтобы проверить правильность расчета TLE, я написал приложение для Android, которое может позиционироваться с помощью GPS и получать данные каждого спутника при позиционировании с помощью Android API.
В то же время азимут и высота спутника рассчитываются с использованием pyephem и положения пользователя, времени позиционирования и данных TLE, когда приложение запущено.
Как ни странно, результаты моего расчета данных TLE отличаются от результатов, полученных приложением на телефонах.
Ниже приведен конкретный процесс:

Во- первых , я пишу простую программу для Android, используя getPrn() , getAzimuth() , getElevation() для получения prn, азимута и высоты каждого спутника. И получить местоположение GPS. Основной код выглядит следующим образом:

private final GpsStatus.Listener gpsStatusListener = new GpsStatus.Listener() {
    public void onGpsStatusChanged(int event) {
        GpsStatus status = mLocationManager.getGpsStatus(null);
        getGPSStatus(event, status);
    }
};

private void getGPSStatus(int event, GpsStatus status) {
    if (status == null) {
    } else if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
        String detail = "";
        int maxSatellites = status.getMaxSatellites();
        Iterator<GpsSatellite> it = status.getSatellites().iterator();
        // numSatelliteList.clear();
        int count = 0;
        int goodcount = 0;
        mPrnStr = "";
        while (it.hasNext() && count <= maxSatellites) {
            GpsSatellite gpsSatellite = it.next();
            float elevation = gpsSatellite.getElevation();
            float azimuth = gpsSatellite.getAzimuth();
            int prn = gpsSatellite.getPrn();
            float snr = gpsSatellite.getSnr();
            int hasAlmanac = gpsSatellite.hasAlmanac() ? 1 : 0;
            int hasEphemeris = gpsSatellite.hasEphemeris() ? 1 : 0;
            int usedInFix = gpsSatellite.usedInFix() ? 1 : 0;
            if (usedInFix == 1) {
                goodcount++;
                mPrnStr += (prn + "|");
            }
            count++;
            detail = detail + String.format("%.5f:%.5f:%d:%.5f:%d:%d:%d|", elevation, azimuth, prn, snr, hasAlmanac,
                    hasEphemeris, usedInFix);
        }
        mGpsStar = String.format("%d-%d", goodcount, count);
        mGpsStarDetail = detail;
    }
}

Я запустил приложение на своем телефоне и получил следующие результаты:

49.00000:185.00000:10:29.20000:1:1:1|33.00000:52.00000:12:42.30000:1:1:1|54.00000:312.00000:14:38.80000:1:0:1

Из данных видно, что азимут спутника с PRN, равным 10, составляет 185°, а угол места равен 49°.

Во- вторых , когда я запускаю приложение, результатом позиционирования GPS является то, 116.295953,40.050029,42.00(longitude,latitude,altitude)
что я использую pyephem, а TLE вычисляет азимут и высоту каждого спутника, когда моя позиция 116.295953,40.050029,42.00и время 2018-11-9 18:30:30(это время, которое я использовал для запуска приложения для Android).
Код выглядит следующим образом:

import ephem
me = ephem.Observer()
me.lon, me.lat, me.elevation = 116.295953,40.050029,42.00
line1 = 'GPS BIIF-11  (PRN 10)'
line2 = '1 41019U 15062A   18315.18162228  .00000031  00000-0  00000-0 0  9991'
line3 = '2 41019  55.1130 139.9366 0040562 201.4871 158.3788  2.00564661 22171'
sat = ephem.readtle(line1, line2, line3)
me.date = ephem.date((2018, 11, 9, 18, 30, 30))
sat.compute(me)
print sat.az * 180.0 / 3.1416
print sat.alt * 180.0 / 3.1416

Вывод этого кода:

24.5045833546
-19.6957760088

Поскольку я установил то же место и время, результаты, рассчитанные с помощью TLE, должны быть аналогичны результатам, полученным при запуске приложения для Android. Но в результате приложения азимут и высота prn10 составляют: 185° и 49°. В результате TLE азимут и высота prn10 составляют: 24,5045833546°, -19,6957760088°. Они очень разные. Странно.

Пожалуйста, скажите мне, в чем проблема. Большое спасибо.

@AndyShan (пытаясь спасти ваш вопрос) - вы спрашиваете, почему азимут и высота спутников различаются, однако фрагмент кода, который вы разместили, вычисляет az/alt только один раз, по-видимому, используя PyEphem (как вы сказали) и две строки, которые я Думаю, они исходят от TLE. Так кто чем отличается? т.е. когда вы печатаете sat.az, я предполагаю, что результат вас не удовлетворяет, но с чем вы сравниваете этот результат?
@AndyShan также было бы хорошо, если бы код можно было запустить, просто скопировав / вставив его без необходимости что-либо добавлять. Поэтому, пожалуйста, добавьте «import ephem» в начале, а также код, откуда берутся lon, lat, ele и time.
@BlueCoder Извините, предыдущее описание слишком грубое. Я обновил детали и объяснил свою цель. Код Python работоспособен, но код Android — это только основной фрагмент. Я неоднократно отлаживал код и чувствовал, что с программой проблем нет. Поэтому мне интересно, отличается ли азимут GPS, рассчитанный TLE, от фактического азимута спутника, отсканированного пользователем.
@uhoh Извините, я не ясно выразил свои намерения. Я не хочу задавать конкретные вопросы по программированию. Поскольку я неоднократно отлаживал свою программу, поэтому я думаю, что с программой нет проблем. Мне интересно, отличается ли азимут GPS, рассчитанный TLE, от фактического азимута спутника сканируется пользователем.
@AndyShan Я изменил свой голос на «за» и проголосовал за повторное открытие вашего хорошо отредактированного вопроса. Спасибо и добро пожаловать в космос!
@AndyShan, вот запуск с использованием пакета Python Skyfield , написанного тем же человеком, который реализовал PyEphem. pastebin.com/yHFaZuBw Я добавил свои результаты в комментариях внизу. Это кажется другим, чем любой из ваших ответов, но я думаю, что PyEphem использует ту же реализацию Python SGP4 (распространитель TLE), что и Skyfield. Я не знаю, в чем проблема, но внимательно следите за такими вещами, как переключение широты и долготы. Вот почему я использовал именованные аргументы в Topos()своем сценарии. Я добавил подспутник для удовольствия. Удачи!
Я зашел на сайт in-the-sky.org/satmap_worldmap.php и указал 9 ноября в 21:30 (у меня восточное время), и обнаружил, что GPS 10 приближается к Кейптауну. Не уверен, но, возможно, этот сайт может помочь.
@AndyShan хорошее редактирование! Я проголосовал за то, чтобы снова открыть вопрос :) Пара вопросов, чтобы проверить некоторые данные: 1) значит, ваше местоположение наблюдателя находится очень близко к Пекину, верно? 2) Вы правильно указали время? Я вижу здесь, что PyEphem, вероятно, нуждается в универсальном времени (а не в местном часовом поясе) [ rhodesmill.org/pyephem/quick.html#dates]
Мой ответ: кажется, что широта и долгота могут (или должны?) быть предоставлены PyEphem в виде строки, используя формат градусов, т.е. долгота в градусах: 116:17,75718 широта в градусах: 40:3,00174, см. rhodesmill.org/pyephem/ quick.html#observers Я проводил некоторые тесты, и мои результаты с PyEphem совпадали только с результатами на in-the-sky.org/…, когда я использовал этот формат. Кроме того, я использовал текущее универсальное время, а не местный часовой пояс. Используя этот формат и 10:30 в качестве времени (вместо 18:30), я получаю Az: 183,2 El: 38,5, что близко к ожидаемому.
10:30 имеет смысл, поскольку в Пекине GMT+8, поэтому можно было бы ожидать, что для получения UTC нужно вычесть 8 часов :) Действительно, сейчас 10:32 UTC, а в Пекине в этот самый момент 18:32: ) Результат все же отличается от ожидаемых 185°/49°, но может время было на несколько минут раньше или позже? (возможно, это может составлять +11 высоты)
Действительно, я могу получить 185 Az, 49 Elev, указав 10:08 в качестве времени наблюдения. Далее следует измененный код (мне нужно разделить его на два комментария, и он будет выглядеть уродливо, пока я не смогу опубликовать его как ответ) ,42.00 долгота = '116:'+str(int(0.295953*60))+str((0.295953*60)%1)[1:] широта = '40:'+str(int(0.050029*60))+ str((0.050029*60)%1)[1:] print "Долгота в градусах:", долгота, "Широта в градусах:", широта me.lon = долгота me.lat = широта
LINE1 = 'GPS BIIF-11 (PRN 10)' LINE2 = '1 41019U 15062A 18315.18162228 .00000031 00000-0 00000-0 0 9991' LINE3 = '2 41019 55.1130 139.9366 0040562 201.4871 158888,00666666666666666666666666666666666666666666666666666666666666666666666666666666666666666ERER. , строка2, строка3) me.date = ephem.date((2018, 11, 9, 10, 30, 30)) sat.compute(me) print sat.az * 180.0 / 3.1416 print sat.alt * 180.0 / 3.1416 me .date = ephem.date((2018, 11, 9, 10, 8, 30)) sat.compute(me) print sat.az * 180,0 / 3,1416 print sat.alt * 180,0 / 3,1416

Ответы (1)

Кажется, что широта и долгота могут (или должны?) быть предоставлены PyEphem в виде строки, используя формат градусы:минуты, т.е. долгота: 116:17.75718, широта: 40:3.00174
См. rhodesmill.org/pyephem/quick.html#observers

PyEphem также требуется универсальное время (а не время в местном часовом поясе)
. См. rhodesmill.org/pyephem/quick.html#dates .

Учитывая, что 40° северной широты и 116° восточной долготы находятся рядом с Пекином (GMT-8), я предположил, что правильное время UTC будет 10:30.

Используя правильный формат долготы/широты и время 10:30 UTC, я получаю Az: 183,2 El: 38,5, что близко к ожидаемому.

Результат все же отличается от ожидаемых 185°/49°, но, может быть, время было на несколько минут раньше или позже?

Действительно, я могу получить 185 Az, 49 Elev, указав 10:08 в качестве времени наблюдения.

Мой код следует:

import ephem
me = ephem.Observer()
me.lon, me.lat, me.elevation = 116.295953,40.050029,42.00 
longitude = '116:'+str(int(0.295953*60))+str((0.295953*60)%1)[1:] 
latitude = '40:'+str(int(0.050029*60))+str((0.050029*60)%1)[1:]
print "Longitude in degrees:minutes format:", longitude
print "Latitude in degrees:minutes format:", latitude 
me.lon = longitude 
me.lat = latitude
line1 = 'GPS BIIF-11  (PRN 10)'
line2 = '1 41019U 15062A   18315.18162228  .00000031  00000-0  00000-0 0  9991'
line3 = '2 41019  55.1130 139.9366 0040562 201.4871 158.3788  2.00564661 22171'
sat = ephem.readtle(line1, line2, line3)


me.date = ephem.date((2018, 11, 9, 10, 30, 30)) 
sat.compute(me) 
print sat.az * 180.0 / 3.1416 
print sat.alt * 180.0 / 3.1416 

me.date = ephem.date((2018, 11, 9, 10, 8, 30)) 
sat.compute(me) 
print sat.az * 180.0 / 3.1416 
print sat.alt * 180.0 / 3.1416 

РЕДАКТИРОВАТЬ: при предоставлении широты/долготы в виде чисел вместо строк они интерпретируются как радианы. Таким образом, ваш существующий код будет работать, если me.lon и me.lat будут преобразованы в градусы (деленные на 180, умноженные на 3,1416). Время все еще необходимо преобразовать в UTC.

Отличная детективная работа!
@BlueCoder Для меня это очень важный проект. Вчера увидел твой ответ. Я сразу обнаружил, что ваш ответ является правильным ответом на этот вопрос. У меня не было времени поблагодарить вас, потому что я решил проблему и закончил свой проект. Теперь я хотел бы выразить вам свою сердечную благодарность за ваше терпение и прекрасную работу.
@AndyShan Добро пожаловать! Благодаря вам теперь я знаю, как использовать TLE и PyEphem :)