Creating an Earth-Orbiting Satellite Tracker using Linux Bash, Python, PHP and HTML

I'm currently teaching myself Bash and Python scripting. After seeing the International Space Station fly over my house, I got the idea to create a tracker and learn at the same time. The end result is this. I'm going to keep working and improve it, but for now its functional. I'm sure someone with a little more skill than me could cut my Python code right down.

The tracker works by reading earth-orbiting satellite data, computing it, and throwing out a location. This location is then fed into a Google Maps API and plotted onto a map. The map marker is updated every second.

1. Building a web-server
This is out of scope for this post, but you will need a web-server with the following:
Linux based
PHP support
Python 2.7.3
Pyephem-3.7.5.2

2. Obtaining Tracking Data
Satellites can be tracked using two line element sets. Wikipedia reads, "A two-line element set (TLE) is a data format used to convey sets of orbital elements that describe the orbits of Earth-orbiting satellites. A computer program called a model can use the TLE to compute the position of a satellite at a particular time. The TLE is a format specified by NORAD and used by NORAD and NASA. The TLE can be used directly by the SGP4 model (or one of the SGP8, SDP4, SDP8 models). Orbital elements are determined for many thousands of space objects byNORAD and are freely distributed on the Internet in the form of TLEs.[1] A TLE consists of a title line followed by two lines of formatted text".

I noted down a few satellites to track and went about downloading orbital data.

I found the best place to obtain TLE data was Space-Track. They provide an API we can tap into to automate the process of TLE downloads. TLE data will depreciate and become inaccurate after a period of time, so I carry out weekly updates.

The easiest way to update the TLE's is via a Linux cron  job. My web-server automatically kicks off this script every Monday morning. The script looks like this:

#!/bin/bash
#Grab the current TLE data.
wget  --post-data='identity=**EmailAddress**&password=**Password**&query=https://www.space-track.org/basicspacedata/query/class/tle_latest/NORAD_CAT_ID/25544/orderby/ORDINAL asc/limit/1/format/3le/metadata/false' --cookies=on --keep-session-cookies --save-cookies=cookies.txt 'https://www.space-track.org/ajaxauth/login' -O ISS.txt

The above command uses wget to log into the Space-Track API. It creates a session and then uses that session cookie to pull back data. In this case its downloading the latest TLE for the International Space Station and saving it to ISS.txt

I pull 6 TLE files every time the script runs . All you need to do is copy the line and change the elements highlighted in red. The Email and Password are the same as your Space-Track login details. 25544 is the North American Aerospace Defence Command (NORAD) identifier for the International Space Station. The .txt file is where the script saves the TLE data.

This script will log in and download a new session cookie for each TLE file. I will review the Space-Track API documentation and make my script smoother when I get time.

3. Creating a Sub-Latitude(+N) and Sub-Longitude(+E) out of TLE data.
A TLE file looks like this:
0 ISS (ZARYA)
1 25544U 98067A   14124.53379023  .00007028  00000-0  13175-3 0  2130
2 25544 051.6491 315.9409 0001820 318.2358 139.3975 15.49835475884558

It is possible to work out a satellites current location using the above data and a time stamp. You can also work out where it was at any given time in the past, and where it will be at any given time in the future. This is how pass predictions are calculated. I found an awesome astronomical computation Python module called PyEphem. After a couple of hours of playing around, I managed to get PyEphem to analyse TLE data and spit out a location. Lets work through some of the code:

#Open the ISS TLE file
    tlefile=open('ISS.txt', 'r').read()
#Split the TLE data into a ephem readable format.
    tlesplit=tlefile.split('\n')
#Analyse the split data.
    tle_rec = ephem.readtle(tlesplit[0], tlesplit[1], tlesplit[2])
    tle_rec.compute()
#Convert the sub satellite value (lat) to a string, then into DDMMSS format. 
    DMSsublatS="%s" %tle_rec.sublat
    DMSsublat=DMSsublatS.split(':')
    Dlat=int(DMSsublat[0])
    Mlat=int(DMSsublat[1])
    Slat=int(float(DMSsublat[2]))
    DMSsublatsum=Dlat+Mlat/60+Slat/3600
#Convert the sub satellite value (lon) to a string, then into DDMMSS format. 
    DMSsublonS="%s" %tle_rec.sublong
    DMSsublon=DMSsublonS.split(':')
    Dlon=int(DMSsublon[0])
    Mlon=int(DMSsublon[1])
    Slon=int(float(DMSsublon[2]))
    DMSsublonsum=Dlon+Mlon/60+Slon/3600

PyEphem likes the TLE data to come in line by line. To do this I had to split the file in Python at new line (\n). Once split, the module could compute and throw out a DDMMSS formatted Latitude and Longitude. Unfortunately this wasn't quite what I required.
The Google Maps APIv3 uses decimal co-ordinates to plot the marker location. A quick Google taught me the maths to convert DDMMSS to deciaml co-ordinates. I'm not that happy with the way I have implemented this, and will improve it. For now, it's Dlon+Mlon/60+Slon/3600 replacing lon with lat when required.

This gives us a decimal output that we can feed into the Google Maps API.

I'll finish this write up (including the PHP/HTML/JS code) soon. I'm going to focus on the code a little and try and make improvements where I can. 

3 comments:

  1. I'm really interested in your app. I would like to get more information about it. When will you write your new post?

    ReplyDelete
  2. I really liked your article, especially the idea that came to mind. I would like to read about its future implementation, with examples of your code concept.
    Richard Brown data room

    ReplyDelete
  3. You have a great idea, I will follow your blog. I recently was on a trip and tried a new software for GPS location find out more about uboro . I advise you to try this and transfer this technology to your work, I think you'll like the result.

    ReplyDelete