# Why the PRN obtained from Android is different from calculated by TLE

I want to use TLE data to calculate the azimuth and elevation of every GPS satellites at user's location.
In order to verify the correctness of TLE calculation, I wrote an Android app that can be positioned using GPS and get the data of each satellite when positioning using Android API.
At the same time, the azimuth and elevation of the satellite are calculated using pyephem and user position, positioning time and TLE data when the app is in run.
Strangely, the results of my TLE data calculation are different from those obtained by app on phones.
The following is the specific process：

First,I write a simple Android program, use getPrn() , getAzimuth() , getElevation() to get prn, azimuth and elevation of each satellite. And get gps location. The core code is as follows：

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


I ran the APP on my phone and got the following results:

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


From the data, we can see that the azimuth of the satellite with PRN equal to 10 is 185° and elevation is 49°.

Second, when I run the app, the result of GPS positioning is 116.295953,40.050029,42.00(longitude,latitude,altitude)
I use pyephem and TLE compute azimuth and elevation of each satellite When my position is 116.295953,40.050029,42.00 and time is 2018-11-9 18:30:30 (This is the time I used to run Android app).
The code is as follows：

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'
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


The output of this code is：

24.5045833546
-19.6957760088


Because I set the same location and time, the results calculated from TLE should be similar to the results I got from running android app. But in the app result, the azimuth and elevation of prn10 is：185° and 49°.In the TLE result, the azimuth and elevation of prn10 is：24.5045833546°,-19.6957760088°. They're very different. It's strange.

Please tell me where the problem is. Thanks a lot.

• @AndyShan (Trying to salvage your question) - You ask why the azimuth and elevation of satellites are different, however, the snippet of code you posted calculates az/alt only once, apparently using PyEphem (as you said) and two lines that I guess they come from TLE. So who is different to what? i.e. when you do print sat.az I guess that the result does not satisfy you, but what are you comparing this result against? – BlueCoder Nov 12 '18 at 16:26
• @AndyShan it would also be good if the code was runnable by simply copy/pasting it without having to add anything. So please add "import ephem" at the start and also the code where lon, lat, ele and time come from. – BlueCoder Nov 12 '18 at 16:28
• @uhoh Sorry, I didn't say my intentions clearly. I don't want to ask specific programming questions.Because I have debugged my program repeatedly, so I think there is no problem with the program.I'm wondering if the GPS azimuth calculated by TLE is different from the actual azimuth of the satellite scanned by the user. – AndyShan Nov 13 '18 at 2:48
• I went to in-the-sky.org/satmap_worldmap.php and put in Nov 9 at 21:30 (I'm on Eastern time), and found gps 10 approaching Cape Town. Not sure, but maybe that site can help. – bitchaser Nov 13 '18 at 4:23
• 10:30 makes sense since Bejing is GMT+8, so it would be expected that to get UTC you have to subtract 8 hours :) Indeed, it is currently 10:32 UTC, and 18:32 in Bejing in this very moment :) The result is still different from the 185° / 49° expected, but maybe the time was a few minutes sooner or later? (it could account for +11 elevation maybe) – BlueCoder Nov 13 '18 at 10:33

It seems that latitude and longitude can (or must?) be provided to PyEphem as a string, using the degrees:minutes format i.e. Longitude: 116:17.75718, Latitude: 40:3.00174
See rhodesmill.org/pyephem/quick.html#observers

PyEphem also needs Universal Time (and not the time in the local Timezone)
See rhodesmill.org/pyephem/quick.html#dates

Given that 40 N, 116 E is near Bejing (GMT-8) I guessed that the correct UTC time would be 10:30.

By using the correct long/lat format and 10:30 UTC time, I get Az: 183.2 El: 38.5 close to what was expected.

The result is still different from the 185° / 49° expected, but maybe the time was a few minutes sooner or later?

Indeed I can get 185 Az, 49 Elev by providing 10:08 as the time of observation.

My code follows:

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'

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


EDIT: when providing Lat/Lon as numbers, instead of strings, they are interpreted as radians. So your existing code would work if me.lon and me.lat would be converted to degrees (divided by 180, multiplied by 3.1416). The time still needs to be converted to UTC.

• Excellent detective work! – uhoh Nov 13 '18 at 14:07
• @BlueCoder This is a very important project for me. Yesterday I saw your reply. I immediately found that your answer is the correct answer to this question. I didn't have time to thank you because I solved the problem and finished my project. Now, I would like to express my heartfelt thanks to you for your patience and amazing work. – AndyShan Nov 14 '18 at 3:24
• @AndyShan You're welcome! Thanks to you now I know how to use TLE and PyEphem :) – BlueCoder Nov 14 '18 at 12:09