Por qué el PRN obtenido de Android es diferente al calculado por TLE

Quiero usar datos TLE para calcular el acimut y la elevación de todos los satélites GPS en la ubicación del usuario.
Para verificar la exactitud del cálculo de TLE, escribí una aplicación de Android que se puede posicionar usando GPS y obtener los datos de cada satélite cuando se posiciona usando la API de Android.
Al mismo tiempo, el acimut y la elevación del satélite se calculan utilizando el piefem y la posición del usuario, el tiempo de posicionamiento y los datos TLE cuando la aplicación está en ejecución.
Extrañamente, los resultados de mi cálculo de datos TLE son diferentes de los obtenidos por la aplicación en los teléfonos.
El siguiente es el proceso específico:

Primero , escribo un programa simple de Android, uso getPrn() , getAzimuth() , getElevation() para obtener prn, acimut y elevación de cada satélite. Y obtener la ubicación gps. El código central es el siguiente:

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;
    }
}

Ejecuté la aplicación en mi teléfono y obtuve los siguientes resultados:

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

A partir de los datos, podemos ver que el acimut del satélite con PRN igual a 10 es 185° y la elevación es 49°.

En segundo lugar , cuando ejecuto la aplicación, el resultado del posicionamiento GPS es 116.295953,40.050029,42.00(longitude,latitude,altitude)
que uso pyephem y TLE para calcular el acimut y la elevación de cada satélite cuando mi posición es 116.295953,40.050029,42.00y la hora es 2018-11-9 18:30:30(esta es la hora en que solía ejecutar la aplicación de Android).
El código es el siguiente:

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

La salida de este código es:

24.5045833546
-19.6957760088

Debido a que configuré la misma ubicación y hora, los resultados calculados a partir de TLE deberían ser similares a los resultados que obtuve al ejecutar la aplicación de Android. Pero en el resultado de la aplicación, el acimut y la elevación de prn10 son: 185° y 49°. En el resultado de TLE, el acimut y la elevación de prn10 son: 24,5045833546°, -19,6957760088°. Son muy diferentes. Es extraño.

Por favor, dime dónde está el problema. Muchas gracias.

@AndyShan (Tratando de salvar su pregunta): pregunta por qué el azimut y la elevación de los satélites son diferentes, sin embargo, el fragmento de código que publicó calcula z / alt solo una vez, aparentemente usando PyEphem (como dijiste) y dos líneas que yo Supongo que vienen de TLE. Entonces, ¿quién es diferente a qué? es decir, cuando imprimes sat.az, supongo que el resultado no te satisface, pero ¿con qué estás comparando este resultado?
@AndyShan, también sería bueno si el código se pudiera ejecutar simplemente copiándolo/pegándolo sin tener que agregar nada. Por lo tanto, agregue "importar efem" al principio y también el código de donde provienen lon, lat, ele y time.
@BlueCoder Lo siento, la descripción anterior es demasiado aproximada. Renové los detalles y expliqué mi propósito. El código de Python se puede ejecutar, pero el código de Android es solo un fragmento central. Depuré repetidamente el código y sentí que no había ningún problema con el programa. Entonces, me pregunto si el acimut del GPS calculado por TLE es diferente del acimut real del satélite escaneado por el usuario.
@uhoh Lo siento, no dije claramente mis intenciones. No quiero hacer preguntas específicas de programación. Debido a que he depurado mi programa repetidamente, creo que no hay ningún problema con el programa. Me pregunto si el acimut GPS calculado por TLE es diferente del acimut real del satélite. escaneado por el usuario.
@AndyShan Cambié mi voto a "arriba" y voté para reabrir su pregunta bien editada. ¡Gracias y bienvenidos a Space!
@AndyShan aquí hay una ejecución usando el paquete Skyfield de python , que está escrito por la misma persona que implementó PyEphem. pastebin.com/yHFaZuBw Agregué mis resultados en los comentarios en la parte inferior. Parece diferente a cualquiera de sus respuestas, pero creo que PyEphem usa la misma implementación de Python de SGP4 (el propagador TLE) que Skyfield. No sé dónde está el problema, pero vigile de cerca cosas como el cambio de latitud y longitud. Es por eso que usé argumentos con nombre Topos()en mi script. Agregué subsat por diversión. ¡Buena suerte!
Fui a in-the-sky.org/satmap_worldmap.php y puse el 9 de noviembre a las 21:30 (estoy en hora del este), y encontré gps 10 acercándose a Ciudad del Cabo. No estoy seguro, pero tal vez ese sitio pueda ayudar.
@AndyShan buena edición! Voté para reabrir la pregunta :) Un par de preguntas para verificar algunos datos: 1) entonces, la ubicación de su observador está muy cerca de Beijing, ¿verdad? 2) ¿Pusiste la hora correcta? Veo aquí que PyEphem probablemente necesita el tiempo universal (y no el tiempo en la zona horaria local) [ rhodesmill.org/pyephem/quick.html#dates]
Mi respuesta: parece que la latitud y la longitud pueden (¿o deben?) proporcionarse a PyEphem como una cadena, usando el formato de grados, es decir, Longitud en grados: 116: 17.75718 Latitud en grados: 40: 3.00174, consulte rhodesmill.org/pyephem/ quick.html#observers Estaba haciendo algunas pruebas y mis resultados con PyEphem solo coincidieron con los resultados en in-the-sky.org/… cuando usé ese formato. Además, utilicé la hora universal actual, no mi zona horaria local. Usando ese formato y 10:30 como tiempo (en lugar de 18:30) obtengo Az: 183.2 El: 38.5 cerca de lo esperado.
10:30 tiene sentido ya que Beijing es GMT+8, por lo que se esperaría que para obtener UTC tenga que restar 8 horas :) De hecho, actualmente son las 10:32 UTC y las 18:32 en Beijing en este mismo momento: ) El resultado sigue siendo diferente de los 185° / 49° esperados, pero ¿quizás el tiempo fue unos minutos más tarde o más temprano? (podría dar cuenta de +11 elevación tal vez)
De hecho, puedo obtener 185 Az, 49 Elev proporcionando 10:08 como hora de observación. Sigue el código modificado (tengo que dividirlo en dos comentarios y se verá feo hasta que pueda volver a publicarlo como respuesta) ,42.00 longitud = '116:'+str(int(0.295953*60))+str((0.295953*60)%1)[1:] latitud = '40:'+str(int(0.050029*60))+ str((0.050029*60)%1)[1:] print "Longitud en grados:", longitud, " Latitud en grados:", latitud me.lon = longitud me.lat = latitud
línea1 = 'gps biif-11 (prn 10)' line2 = '1 41019u 15062a 18315.181622228 .0000000031 00000-0 00000-0 0 9991' line3 = '2 41019 55.1130 139.9366 0040562 201.4871 158.3788 2.0056666111111111111111111111111711711711711711711711711711711711711TROS , línea2, línea3) 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

Respuestas (1)

Parece que la latitud y la longitud pueden (¿o deben?) proporcionarse a PyEphem como una cadena, usando el formato de grados: minutos, es decir, Longitud: 116: 17.75718, Latitud: 40: 3.00174
Ver rhodesmill.org/pyephem/quick.html#observers

PyEphem también necesita la hora universal (y no la hora en la zona horaria local)
Consulte rhodesmill.org/pyephem/quick.html#dates

Dado que 40 N, 116 E está cerca de Beijing (GMT-8), supuse que la hora UTC correcta sería las 10:30.

Al usar el formato largo/lat correcto y la hora UTC de las 10:30, obtengo Az: 183,2 El: 38,5 cerca de lo esperado.

El resultado sigue siendo diferente de los 185°/49° esperados, pero ¿quizás el tiempo fue unos minutos tarde o temprano?

De hecho, puedo obtener 185 Az, 49 Elev proporcionando 10:08 como hora de observación.

Mi código sigue:

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 

EDITAR: al proporcionar Lat/Lon como números, en lugar de cadenas, se interpretan como radianes. Entonces, su código existente funcionaría si me.lon y me.lat se convirtieran en grados (divididos por 180, multiplicados por 3.1416). La hora aún debe convertirse a UTC.

¡Excelente trabajo detectivesco!
@BlueCoder Este es un proyecto muy importante para mí. Ayer vi tu respuesta. Inmediatamente descubrí que su respuesta es la respuesta correcta a esta pregunta. No tuve tiempo de agradecerte porque resolví el problema y terminé mi proyecto. Ahora, me gustaría expresarles mi más sincero agradecimiento por su paciencia y su increíble trabajo.
@AndyShan ¡De nada! Gracias a ti, ahora sé cómo usar TLE y PyEphem :)