Track and Photograph Ships with Software Defined Radio
This project uses a Raspberry Pi, a Raspberry Pi Camera, and an RTL-SDR receiver to capture timelapses of ships transiting the Sydney harbour.
You can view the videos on the capture website for the project, Sydney Ships Viewer.
A Software Defined Radio allows you to pick up all kinds of interesting signals using cheap commercial hardware. A RTL dongle is easily obtained online and combined with a Raspberry Pi, creates a perfect platform for experiments. I used an RTL2832 dongle for this project, and there are several alternatives available as listed on the RTL-SDR website.
Ships at sea broadcast AIS (Automatic Identification System) messages every few minutes when underway. They also broadcast messages when at port at a slower frequency. The AIS system aids navigation - other vessels can use this information to plot their courses, avoiding collisions.
This project uses the RTL dongle to listen to these signals and track ships as they move into and out of the Sydney harbour.
The area under the harbour bridge and to Circular Quay (the geofenced area below) is the designated geofence - ships entering or leaving the area, as advertised by AIS, are logged. In addition, having access to a location with line of sight to the area in question, I photograph the ships exactly as they pass under the harbour bridge and in front of the opera house.
Using the GPS coordinates from the AIS messages, it is possible to compute if the ship is inside the geofence or not, and a ship entering the geofenced area can be used as a trigger to start a capture.
The Raspberry Pi camera, though cheap, isn't the best for taking pretty pictures - particularly when you're only interested in a small portion of the image being captured. The sensor quality leaves a lot to be desired and I found that using a cheap smartphone zoom lens (2x) massively improved the captures.
The capture software is written in Python and uses AWS for backend processing work. A link to this repository is at the bottom of this post.
The project uses the excellent RTL-AIS project to process incoming AIS messages and libais to access them in Python.
The data reported by the ships themselves is not always accurate, with some jumps in position that needed to be filtered out. As you might imagine, Sydney harbour is a busy area with lots of traffic - and most of the vessels are too small to photograph with the Raspberry Pi camera, so ships too small to photograph well need to be filtered out.
In theory the AIS messages themselves carry information such as the ship's dimensions, draught, name, and even destination port. In practice, this information is self-reported with no real standards, and the information (other than the MMSI identifier and the GPS co-ordinates) is often wildly inaccurate. I attempt to filter out ships smaller than 80 metres in length to reduce the number of false captures although this often fails because not all ships report accurate sizes.
The Pi sends the captured images to an S3 bucket, and an AWS Lambda uses ffmpeg to convert these to a video. This could be done on the Pi, but the Raspberry Pi Zero I use lacks power.
- The source for the Python ship capture running on the Raspberry Pi: varunnaik/shippix
- The React webapp to view captures: varunnaik/sydney-ships