Fork me on GitHub

Use Beebotte to track the ISS position in real-time

This tutorial demonstrates how to use Beebotte to track the position of the International Space Station (ISS) in real-time.

We will use the two-line element set (TLE)to compute the position of the ISS in real-time using PyEphem astrophysics library.

Tutorial contents:

At the end of this tutorial, we will be able to display the position of the ISS in real-time in Google Maps:

Get ISS position

We will retrieve the TLE data of the ISS from CelesTrak.

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 [Wikipedia].

The TLE data from CelesTrak looks as follows:

ISS (ZARYA)
1 25544U 98067A   14361.11356206  .00017231  00000-0  28015-3 0  6359
2 25544  51.6460 222.7302 0007398 178.4506 330.5659 15.52766391921266
TIANGONG 1
1 37820U 11053A   14361.07836743  .00050955  00000-0  49300-3 0  6993
2 37820  42.7683 229.1478 0014000  23.8878 134.9459 15.65491102186336
CHASQUI-1
...
...

As you can see, the first three lines are related to the ISS. So we will extract these 3 lines as follows:

import urllib2

req = urllib2.Request(url)
response = urllib2.urlopen(req)
data = response.read()

tle = data.split("\n")[0:3]
line1 = tle[0]
line2 = tle[1]
line3 = tle[2]

We will now use the PyEphem library to compute the position of the ISS:

PyEphem can be installed using pip like this:

pip install pyephem
import datetime
import ephem

iss = ephem.readtle(line1, line2, line3)
now = datetime.datetime.utcnow()
iss.compute(now)
### transform longitude and latitude to degrees
print("longitude: %f - latitude: %f" % (degrees(iss.sublong), degrees(iss.sublat)))

Now we have the latitude & longitude of the ISS and we can start having fun.

Send ISS position to Beebotte

We will use Beebotte Python SDK to publish ISS position. We need to specify the API and secret keys of our account,and to indicate the names of a channel and resource to publish to. We will use "ISS" as channel name and "position" as resource name.

Beebotte Python SDK can be installed using pip like this:

pip install beebotte

We will publish ISS position to Beebotte. Published data is transient and will not be persisted (see documentation for details):

from beebotte import *
from math import degrees

### Replace API_KEY and SECRET_KEY with those of your account
bbt = BBT('API_KEY', 'SECRET_KEY')

### Change channel name and resource names as suits you
iss_position = Resource(bbt, "ISS", "position")
iss_position.publish({
    "timestamp": round(time.time()),
    "position": {
        ### transform longitude and latitude to degrees
        "long": degrees(iss.sublong),
        "lat": degrees(iss.sublat)
    }
})

ISS speed is about 28000 km/h! It moves very fast, we need to update its position frequently to have a reasonable accuracy (once per second gives an accuracy of about ~8km):

while True:
  ### update the TLE data once per hour
  if count > 3600:
    update_tle()
    count = 0
  count += 1
  try:
    ### compute the ISS position
    now = datetime.datetime.utcnow()
    iss.compute(now)
    print('longitude: %f - latitude: %f' % (degrees(iss.sublong), degrees(iss.sublat)))
    #Send temperature to Beebotte
    iss_position_resource.publish({
      "timestamp": round(time.time()),
      "position": {
        ### transform longitude and latitude to degrees
        "long": degrees(iss.sublong),
        "lat": degrees(iss.sublat)
      }
    })
  ### catch the exceptions darling :)
  except Exception as inst:
    print type(inst)     # the exception instance
    print inst.args      # arguments stored in .args
    print inst           #

  #Sleep one second
  time.sleep( 1 )

Display in Google Maps

We used the API documentation of Google maps and in particular:

To initialize the map we will use:

var map, marker, isInitialized = false;

function InitializeMap(pos) {
    var options = {
        zoom: 4,
        center: pos,
        mapTypeId: google.maps.MapTypeId.TERRAIN
    };

    // Assuming we have a div with id 'map' in our HTML code
    map = new google.maps.Map(document.getElementById('map'), options);

    // Add a marker at the center of the map
    marker = new google.maps.Marker({
        position: map.center,
        icon: {
            path: google.maps.SymbolPath.CIRCLE,
            scale: 5
        },
        draggable: false,
    });
    marker.setMap( map );
}

To draw the ISS trajectory and update its position marker we will use:

var flightPath = []; // array of positions to draw the trajectory

function drawPath (pos) {
    flightPath.push( pos );
    map.setCenter( pos )

    var traject = new google.maps.Polyline({
        path: flightPath,
        geodesic: true,
        strokeColor: '#FF0000',
        strokeOpacity: 1.0,
        strokeWeight: 2
    });

    traject.setMap(map);
    marker.setPosition( map.center ); // update the position of the marker
}

In order to display the position of the ISS in google maps, we need to subscribe to published position data:

var bbt;
// Replace API_KEY with that of your account
function init() {
    bbt = new BBT('API_KEY');

    bbt.subscribe( {channel: 'ISS', resource: 'position', read: true, write: false}, function(msg){
        var newposition = new google.maps.LatLng( msg.data.position.lat, msg.data.position.long );

        if( !isInitialized ) {
            // Initialize the map
            InitializeMap( newposition );
        } else {
            // update map with newposition
            drawPath( newposition );
        }
    });
}

google.maps.event.addDomListener(window, 'load', init);

Now every time a position is published (see above), the position of the marker and the trajectory will be updated.