GPS is the modern answer to the ancient question about one’s place in the world yet it has its limitations. It depends on the time of flight of radio signals emitted by satellites twenty thousand kilometers above you. Like any system involving large distances and high velocities, this is bound to offer some challenges to precise measurements which result in a limit to achievable accuracy. In other words: The fact that GPS locations tend to be off by a few meters is rooted in the underlying principle of operation.
Today’s level of precision was virtually unattainable just decades ago, and we’re getting that precision with a handheld device in mere seconds. Incredible! Yet the goal posts continue to move and people are working to get rid of the remaining error. The solution is called Differential GPS or ‘DGPS’ and its concept looks surprisingly simple.
What’s fascinating is that you can use one GPS to precisely measure the error of another GPS. This is because the inherent error of a GPS fix is known to be locally constant. Two receivers next to each other pick up signals that have been affected in the same way and thus can be expected to calculate identical wrong positions. This holds true for distances up to several kilometers between individual receivers. So in order to remove the error, all you need is a GPS receiver in a known location to measure the current deviation and a way to transmit correction information to other units. DGPS does just that, using either terrestrial radio in some regions and satellites in others. Mobile solutions exist as well.
So a raspi with a USB GPS dongle in a known location should be able to act as a DGPS over IP base station, right? In theory, yes. In practice… fail.
Setting Up The Base Station
The hardware for a complete DGPS system is pretty minimal and quite affordable. Many of the necessary items you probably already on hand.
A base station is no more than a computer connected to the Internet and a GPS module. In this case I use a Raspberry Pi from the parts bin. I connected a USB GPS receiver dongle using a five meter USB extension. The important thing is to install it in a known location, a task you can hire out but it’s more fun to roll your own and I’ll get to that in a minute.
For the receiving hardware I had intended to provide accurate initial positioning for smart phones as part of an augmented reality project. I did not quite get there, so I replaced the Android app with a netbook and a handheld GPS.
The first steps were to find a suitable location for the receiver station and to weatherproof everything. The barbecue hut in my backyard provided shelter for the raspi and even power. The GPS dongle was ziptied to a length of bamboo and covered in a plastic bag. The overly long cable had a nice amount of slack, so rain running along it would drip off before it got to the computer.
The Software Side
Installing and reading the output of the dongle is charmingly effortless under Linux. The interface is serial over USB and the protocol is standard NMEA 0183 text. Getting this to work, only required me to turn off echoing for the relevant port and then read whatever poured out of the dongle. NMEA 0183 is a well documented standard and sufficiently human readable. To make things even easier, Python libraries to handle NMEA and geospatial data exist and work great.
As mentioned, knowing the exact location of your base station is crucial to this project. There are several ways to obtain it. You could hire a surveyor to precisely measure the location of your antenna or acquire a sufficiently accurate map of your site. You can also resort to brute force: Assuming that the GPS error is evenly distributed over time, just logging enough positions and averaging them should result in the correct location. So I started to write the GPS fixes into a file and let the installation sit for four days. This provided me with over 70,000 fixes that were fed to a Python script for clean up and averaging. Cross checking with OpenStreetMap put the result right in my backyard and above sea level, so I was confident.
All that remained was to whip up a script that continuously listened to the GPS and subtracted the known position to acquire the current error and a second one to deliver the info to the web. Again, Python makes this easy and now I have what you might call an error beacon.
Client Hardware and Software
The originally intended target platform for the client was Android. This is not an environment I’m familiar with and after reading the documentation on Android location services I postponed the app and instead decided to first build a test rig. I used a netbook and a handheld GPS for which I had made a USB cable ages ago.
The software did nothing more than fetching the correction calculated by the base station via HTTP and then subtracting it from the fixes provided by the GPS. To assess the performance of this solution, the client machine was placed in my back yard and set up to log the corrected fixes for some time. If my implementation worked, the recorded positions should be stationary and precisely indicate the location of my garden chair.
Why Did This Fail?
This is a ‘Fail of the Week’ so I’m sure you already guessed that my location data from this test was completely unreliable. The positions showed the same amount of spread as the raw data that I had used earlier to locate the base station!
Something clearly was not working as expected. I checked my code for errors, then tried some random modifications, hoping to infuse correctness by accident and finally took a break to do what should have been the first step of this project: testing my assumptions about the working principle of DGPS.
To achieve this, an hour of position were measured by both the GPS dongle and the hand-held while both receivers were placed right next to each other. NMEA provides a timestamp for each fix and so it was easy to correlate the measurements of the two devices. And it turned out, even if the GPS error is locally constant, the way it affects individual receivers may be different.
What is the Path to Success?
One could say that you should always test your basic assumptions. “Never assume anything” is an often repeated mantra in all flavours of development. But sometimes this is not feasible and often assumptions are not discernible from common sense.
For example, when building an autonomous underwater robot, do you really want to test the wetness of water, the buoyancy of lead, and the effects of moisture on electronics before you begin? The German language provides the term ‘gefühltes Wissen’ — perceived knowledge — for such situations. Perceived knowledge is sometimes dangerous but often hard to avoid and always hard to identify.
So far this project let me familiarize myself with the intricacies of GPS, seriously brush up my bash-fu, and let me finally build my first internet connected thing. It doesn’t work as intended and that is where I want to tap into the power of the Hackaday comments section. Do you think the basics of this DGPS system are in place? How can a simple and inexpensive system like this be put back on track and ultimately achieve accuracy greater than a single, commercially available GPS receiver?
I hope that together we can turn this article about learning from failure into one entitled: ‘How To Build Your Own DGPS Base Station’.
- DGPS over IP has been done successfully by a team of Italian researchers to position autonomous robots with decimeter precision in mountainous terrain. I didn’t copy their approach because I somehow can’t find their paper again.
- Local DGPS is used in agriculture and I have the strong suspicion that these devices employ WiFi or Bluetooth as a communication layer, because it’s easy to use and saves you a lot of headache regarding the legal aspects of radio.
- Sanitizing your exact location out of software that is designed to provide just that is a major piece of work. Also my scripts have not been written to hold up to public scrutiny so I’ll keep them to myself for now.