Pi Plane Project – Video Tracking


The Pi Plane Project


The Pi Plane Project tracks planes the fly over my house; records a short video – and uploads the clips onto the web.

You can see the latest overhead fly-overs here; and the closest aerial visits here

This is a result of a lot of tinkering; and a curious need of mine to combine my love of electronics, programming and aviation.

A Quick Video?

The Basic Theory

Pi Plane Picture Overview


Commercial aircraft in Australia (and a lot of the world) periodically transmit their location and the altitude.  Aircraft with ADS-B  determine their position using GPS; and broadcast that position along with identity string, altitude (plus other useful information such as speed).

Using some inexpensive components, we can build a receiver to listen to these ADS-B signals to track these aircraft as they fly overhead.   Using a bit of spunky maths, a bit of electro-mechanical tinkering and a few elastic bands I built a system to determine where in the sky these planes are; point a camera to them and track their movement whilst recording a short video of the flyby.

The videos are pushed onto a website; along with basic information such as aircraft type and destination.  This flight information is textually overlaid onto the video.

The videos and metdata are stored in a database; and a dynamic public web site allows the curious to see a short video of planes and magic carpets flying over my home

The bits


To create your own (or if you plan to rob me; you can score) …

  • Raspberry Pi – a very inexpensive  credit-card sized computer
  • Powered USB hub – allows the peripheral parts to connect and be fed
  • DVB-T & RTL-SDR Receiver, RTL2832U – helps receive and decode aircraft transmissions
  • GPIO Kit for Raspberry Pi, T-Cobbler – connects the Raspberry Pi to outputs such as the servo motors
  • PT Pan/Tilt Camera Platform Camera Mount w/ 2 Servo – a pre-assembled platform to allow 2-axis of movement for the camera
  • Raspberry Pi Camera Board – a CMOS camera suitable for the Raspberry Pi
  • LCD Display: lcd1602 – an LCD display panel

The Operating System


The Raspberry Pi has some fantastic tutorials.  In short, you put the image of the free operating system (a Linux varient) on an SD card; and add power


I used a RTL2832U  as a software defined radio (SDR).  This is a USB stick (a TV “dongle”), designed for digital TV on a computer.  This is re-purposed as a powerful, configurable receiver.  Using specialized software a device originally intended to receive television broadcasts can be configured to listen for aircraft transmissions.


On the Pi I installed Dump1090 – a program which accesses ADS-B data via the RTL2832U and a small antennae

Firing up dump1090 dumps all transmissions as they come in.  There are multiple aircraft puking this information out; so it looks like a random jumble of text initially (it’s like everyone’s talking at the same time at a party)


I’m no expert, and I relied tremendously on the hard work (and great tutorials) scattered across the web.  A terrific introduction to RTL-SDR cheap ads-b aircraft radar is at http://www.rtl-sdr.com/adsb-aircraft-radar-with-rtl-sdr/

And an equally useful explanation for understanding ADS-B using dump1090 for the Raspberry Pi is at http://www.satsignal.eu/raspberry-pi/dump1090.html

Pi Plane Picture Overview 1


So remember the RTL2832U  is acting as software defined radio (SDR). On the Pi I installed Dump1090 – which does a fine job of understanding the data packets transmitter by a planes transponders.  The Dump1090 suite of programs can also display the locations and track of aircraft on a map, but all of this visual trickery was unnecessary for my project


For simplicity, lets look at a single transponder message.  Mode S ADS-B transponders transmit information about the aircraft such as this location message below.  Information is always sent with an identifier called the ICAO Address.   In Dump1090 this 24-bit address takes the form of a hex code such as 7c6c99.  It is a permanent and constant part of the aircraft’s transponder; so we can use this to correlate messages back to an air-frame.

capture 1

And here is another message.  Same air-frame 7c6c99 now reporting the flight code

capture 3

Parsing these addresses and messages you can rapidly assemble a representation of aircraft and movements within a close range

Pi Plane Picture Overview 2

The maths

So after receiving the latitude/longitude and height as transmitted from the plane, and knowing where we are  we can do some nifty maths to point a camera at where the plane should be.

Here is a typical location message, note we know the air-frame and the altitude, latitude and longitude as reported by the plane

capture 2

So we now know where the plane is and we want to point a camera towards it.    Most specifically, we need to work out a relative bearing (from ground station to latest location of plane)  to work out which direction to twist left/right (relative to North).  We also need to determine the azimuth to work out how to angle up/down (relative to the horizon) to aim the camera


The maths involved turned out to be harder than I had anticipated (and in no way do I understand it).  I’m heavily indebted to this website to help me with the ‘haversine’ formula to calculate distance, bearing and more between Latitude/Longitude point

haversine function

The website very helpfully has some JavaScript demonstrations; so it was not too taxing to form some Python equivalents

So after receiving the latitude/longitude and height as transmitted from the plane, and knowing where we are (gosh; hope that’s a constant) we can do some nifty maths. We need to work out a relative bearing (from ground station to latest location of plane) to work out which direction to twist left/right (relative to North). We also need to determine the azimuth to work out how to angle up/down (relative to the horizon)

cRadiusOfEarth = 6371;
cFeetToKm = 0.0003048

f1 = math.radians(cHomeLat1);
f2 = math.radians(lat2);
delta_f = math.radians(lat2-cHomeLat1);
delta_g = math.radians(lon2-cHomeLon1);
a = math.sin(delta_f/2) * math.sin(delta_f/2) + math.cos(f1) * math.cos(f2) * math.sin(delta_g/2) * math.sin(delta_g/2);
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a));
dist_km = cRadiusOfEarth * c;
math.sin(lon2-cHomeLon1) * math.cos(lat2)
, math.cos(cHomeLat1)*math.sin(lat2)-math.sin(cHomeLat1)*math.cos(lat2)*math.cos(lon2-cHomeLon1)

brng_d=(360.0 - math.degrees(brng_r))%360.0
azmth=math.degrees(math.atan(pFeet*cFeetToKm / dist_km))

Pi Plane Picture Overview 3

Using a Raspberry Pi to control servos

Servos are small, cheap, actuators used for radio control and small-scale robotics (thanks Wikipedia).

The servo is commanded to hold at a particular angle using a PWM (pulse width modulated) signal.  That is, the rate of the pulses is changed to command a new position, or the pulses are held at a constant rate to remain in the same position.  Generally servos are connected to dedicated hardware to maintain these pulses (it’s very tedious using software).  Unfortunately the raspberry pi does not have hardware PWM; but you can fake a reasonable signal on the GPIO pins

IMG_1461 IMG_1580

I found the ServoBlaster  package a great interface to drive my two servos via the GPIO pins.  This module nicely hides the grunt work of maintaining these pulses, and sends the signals over the GPIO pins on the Raspberry Pi.  As I only needed to control 2 servos (and I wanted to keep the other GPIO pins for driving the LCD screen).   I could free up all but 2 of the GPIO pins using these settings

vi /etc/init.d/servoblaster
OPTS="--idle-timeout=2000 --p1pins=7,12"


I wanted to display some basic flight information on the PiPlane itself.  So I attached an LCD Display (lcd1602) to show some flight data.  The wiring diagram is below; it’s pretty basic and requires only 8 connections between the LCD and the Pi.

I used the Python code for Adafruit’s Character LCDs on the Pi is available on Github at https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code


Ugly breadboards to ugly perf-boards

I love breadboards.  I spent many hours (some of them enjoyable) trying out my circuit before committing to a pseudo-permanent perf-board solution.

The breadboard (1st picture) shows the LCD and initial servo setup.  The perf-board (2nd picture) shows a slightly more “robust” solution



My project actually has 3 (!) databases (hey: my day job is a DBA after all).   Two are on the Raspberry Pi and act as lookup tables; and one is one the main server in the cloud to capture metadata and respond to web requests


Say we get a message like this, wouldn’t it be nice to know what 7c6c99 actually is

capture 5


Allow you to find the aircraft type (Airbus A320) and the tail-code



And air-frame what 7c6c99 is operating as JST672, so lets find out where we’re travelling to

capture 4


Hey, we’re off to Darwin!


 The Software – distributed processing

The software stack is split across processing performed on the RaspberryPi and processing running on a hosted Windows machine (AWS – Amazon Web Services)

The RaspberryPi is responsible for local time critical processing (decoding the data stream and positioning the camera) whereas the Windows machine does the heavy processing for recoding video files and running a Web Server facing the public internet

Raspberry Pi Software


  • The Raspberry Pi is running Linux raspberrypi 3.10.25 as its operating system.
  • The ServoBlaster kernel module mimics a hardware PWM system.
  • The AdaFruit LCD character display has been installed from github
  • SQLite databases StandingData.sqb and BaseStation.sqb act as read-only reference sources
  • The majority of my processing code is in my Python program piplanepicture.py

PiPlanePicture.py program runs in a permant loop

  • Spawn, and read the output of dump1090. That is, receiving the ADS-B signals and parse the ouput
  • Determine if there is a valid transmission (ICAO Address, Altitude, Latitude) etc., Store useful transmissions in an associative array (looking up details against SQLite databases)
  • If a transmission indicates a plane is inbound, is close and within sweep of servo then start recording a video and write details into a JSON formed file

Whenever a plane video recording is complete (typically after 45 seconds) a mp4 and description data file are created.

  • 20141104_083335.h264
  • 20141104_083335.json
{"AZMT": "12.0", "CODE": "TGW758", "FROM": "Perth", "DEST": "Sydney",
"ALTD": "3925.0", "ICAO": "7c6c27", "REGO": "VH-VND", "BRNG": "169.0",
"ARLN": "TGW", "DATE": "04/11/2014 0833", "DIST": "5.42", "TYPE": "A320"}


Pi Plane Picture Overview 4

MoveToNAS simply runs in a busy loop, looking for files that have been static for 2 minutes and ships them to an AWS share

while [ true ]; do
  for myfile in `find . -mmin +2 -name \*.[hj][2s][6o][4n]`; do
     . . .
     CMD="put ${BASE_FILE_NAME} ${BASE_FILE_NAME}.pending; rename ${BASE_FILE_NAME}.pending ${BASE_FILE_NAME}"
     smbclient // -A /home/pi/secret.txt -c "${CMD}"

Windows AWS Software


  • The AWS instance is a t2.small running Windows Server 2008 R2
  • Installed is IIS and ffmpeg
  • SQLite databases PiPlaneData acts as a local store for all

ProcessVideoFiles.py runs in a loop.  When a pair of files is found (both the movie file and the json file)

The json stream is loaded like this

lv_jsondata = json.load(f_json_data)
lv_string1 = 'Flight ' + lv_jsondata["CODE"] + " From " + lv_jsondata["FROM"] + " To " + lv_jsondata["DEST"]
lv_string2 = "Type " + lv_jsondata["TYPE"]
lv_string3 = "Seen at " + lv_jsondata["DATE"] + " at distance " + str(lv_jsondata["DIST"]) + " km at " + str(lv_jsondata["ALTD"]) + " ft"

The ffmpeg is then called with parameters like this

drawtext=fontsize=20:box=1:boxcolor=black@0.3:fontcolor=White:fontfile=\'c\:/Windows/Fonts/arial.ttf\':text=\'' + lv_string1 + '\':x=(w)/10:y=400
, drawtext=fontsize=20:box=1:boxcolor=black@0.3:fontcolor=White:fontfile=\'c\:/Windows/Fonts/arial.ttf\':text=\'' + lv_string2 + '\':x=(w)/10:y=425
, drawtext=fontsize=20:box=1:boxcolor=black@0.3:fontcolor=White:fontfile=\'c\:/Windows/Fonts/arial.ttf\':text=\'' + lv_string3 + '\':x=(w)/10:y=450

And behold – a video with text overlay


I’m using IIS as the web server.  It simply exposes the files and video files

For the very enthusiastic you can download my files here


A Longer Video of Pi Plane Operating?