Showing posts with label howto. Show all posts
Showing posts with label howto. Show all posts

Sunday, March 6, 2016

An RTL-SDR dataset for gnss-sdr

I've had several requests for a dataset for users to play with. I've been recalcitrant simply because every dataset I've taken has been from my house! So this week I went to a park and took a two-minute acquisition using GNSS-SDR. My setup is a RTL-SDR stick with a 0.5PPM TXCO and aluminum case with the bias tee mod, a LNA4ALL, and a cheap active GPS antenna. (By no means are 0.5PPM TXCO, aluminum care or LNA4ALL requirements, I've gotten a good fix with a cheap dongle in a plastic case with no LNA.)

The dataset lives on my Google Drive. The .conf file is the file I used for acquisition. If you want to use it for playback with gnss-sdr, you need to make the following changes

Line 29: Change the SignalSource.implementation from Osmosdr_Signal_Source to File_Signal_Source
Line 30: Uncomment the SignalSource.filename and provide the correct path to the data file
Line 42: Change SignalSource.dump to false

gnss_sdr_pvt.nmea contains position/velocity/time (PVT) in NMEA format. The GSDR063p40.16N contains the raw navigational information and the GSDR063p40.16O contains the observables. PVT.kml is a Google Earth file with coordinates.

You might be interested in recovering the chip rate.

Saturday, February 27, 2016

Find the signal in the noise




 GPS signals are very weak, coming in at about 120 dBm ... which is below the thermal noise floor of ~ 100 dBm! If you try plotting an FFT 2 MHz wide about the L1 frequency you won't be able to distinguish the signal from the noise.



But it is there, and we can find it! 

First, we need data. I used data collected with an RTL-SDR stick converted to complex output. The output from the RTL-SDR is interleaved unsigned short, whereas the input block expects signed complex numbers. I talked about this in a prior post; I use the gcc code myself. 

So when we have data we can build a very simple flow diagram in GNURadio to play back the file and visualize it using the Fast Autocorrelation Sink. As noted in a previous post, there is a bug in GNURadio which breaks the Fast Autocorrelation Sink, but it is an easy fix!


The Fast Autcorrelation Sink is documented on Balint Seeber's blog and provides links to why the fast autcorrelation sink is indeed so fast! If you aren't familiar with autocorrelation, it is the correlation of a signal with itself. At any given time the correlation of a signal with itself is perfect, but if you insert a time delay and look at a later signal compared to a previous signal we can see just how similar the later signal. 

For example let's visualize a triangle wave with a frequency of 1000 Hz - that is, 1000 peaks per second, or 1 peak per millisecond. Since each repetition of the triangle is exactly 1 millisecond apart and since there is no noise in the system we would expect that every millisecond we'd have a perfect correlation of the shifted signal to the current signal. In between those milliseconds the correlation would get worse until we were half a millisecond apart where the peaks from the original signal would line up with the troughs of the shifted signal, resulting in a negative correlation.

Here's a simple flowgraph in GNURadio to visualize the autocorrelation using the Fast Autocorrelation Block from gr-baz. First, we create a signal source of a triangle wave with a frequency of 1000 Hz. Then we insert a throttle - this throttles the rate at which the diagram runs so we can visualize the signal. Left to its own devices GNURadio would simply pump triangle waves as quickly as it could with the given CPU resources. Then we can visualize the waveform using a WX GUI signal sink and the autocorrelation using the Fast Autocorrelation Sink:



Note the color of the block interfaces: Orange. This means floating point. Most of the blocks will default to complex, which is what you'd want for a lot of radio work but in this case it just makes things confusing as you will be plotting the triangle waves in both the Re and Im space. You can double click on each block and change the types to floating point or POWERUSER TIP: Click on the block and use up/down arrows to change the type. Once the flowgraph is complete (or download it here) hit play and you should see something like this:


We see our triangle waves with a period of 1 Hz and the Fast Autocorrelation Sink showing peaks at 1 Hz, and negative peak at a rate of 1 Hz shifted by half a Hz. 

So now let's do it with a real signal. You can use the same flowgraph, we just need to substitute the signal source block for a file source and specify our complex file. And since the file is complex, we need to change the data types. Finally, the throttle should be set to the sample rate of your input source - in my case, 2048000 Hz for the RTL-SDR. For the fast autocorrelation sink you will likely want to tweak the size to make the number of milliseconds a reasonable number. For my use I did (2**18)/2. Here's the updated diagram, running with the Fast Autocorrelation Sink, which you can download from github.


We see nice peaks every millisecond. Why every millisecond?

The coarse/acquisition code for GPS (C/A) has a period of 1023 chips which are transmitted at a rate of 1.023 MBit/s. This results in period of 1 millisecond. BAM! You can read more about the encoding on wikipedia. The L1 carrier at 1575.42 MHz has two codes, the C/A code and the navigation message. The navigation message varies with time as the satellites move through space but the C/A code does not change.  The C/A code is used for locking onto the satellites: Each satellite has a different unique C/A code. Earthside a receiver generates a particular C/A code and then shifts it in time and frequency to correlate the known C/A code with the C/A code of the satellite. Since we don't have a perfect clock we have to shift in time to line up our signal with the GPS signal timing and since the satellites are moving rapidly they frequency we receive is subject to a doppler shift of up to 5kHz (10kHz if we are moving very quickly, say, on a rocket or missile)

But that's a story for another day.

Wednesday, December 16, 2015

Acquiring GPS signals with an RTLSDR dongle using gnss-sdr

Once you've installed gnss-sdr and tested your installation with prerecorded data, the next step is to try and get a live GPS solution. The following is based off this node at gnss-sdr.org and this paper. The paper is a really good mix of theory and implementation and I strongly recommend reading it.

The first thing you need to do is calibrate the front end of your RTL-SDR device. The calibration procedure will do the following
  1. Download an ephemeris via SUPL. This provides your computer with advance knowledge of the GPS satellite locations, allowing you to get a quick fix.
  2. Search for GPS satellites
  3. Calculate the doppler shift assuming your RTL-SDR stick is perfect (trust me, it's not!)
  4. Using the predicted doppler shift and some fancy math (see the paper, section 5), calculate
    1. The actual sampling frequency
    2. The actual IF bias

Before running the calibration you need to update the front-end-cal.conf. Make a copy of the version installed (typically to /usr/local/share/gnss-sdr/conf/front-end-cal.conf). On the first couple of lines you will see a number of GPS lat/lon/alt locations commented out using a semicolon. You need to provide your best estimate at lat/lon/alt, bearing in mind altitude is in meters. The easiest way to do this is use a tool like the aptly named mapcoordinates.net. The other change I had to make was to change both SUPL servers to supl.google.com in place of supl.nokia.com - for some reason the nokia servers were not working. Once complete, you can run the front end calibration like so 

sudo front-end-cal --config_file=/path/to/my/front-end-cal.conf

Your output should look something like this
linux; GNU C++ version 4.9.1; Boost_105500; UHD_003.007.003-0-unknown
Initializing... Please wait.
Logging will be done at /tmp
Use front-end-cal --log_dir=/path/to/log to change that.
Trying to read ephemeris from SUPL server...
SUPL: Trying to read GPS ephemeris from SUPL server...
SUPL: Received Ephemeris for GPS SV 1
SUPL: Received Ephemeris for GPS SV 2
SUPL: Received Ephemeris for GPS SV 3
SUPL: Received Ephemeris for GPS SV 5
SUPL: Received Ephemeris for GPS SV 6
SUPL: Received Ephemeris for GPS SV 7
SUPL: Received Ephemeris for GPS SV 8
SUPL: Received Ephemeris for GPS SV 9
SUPL: Received Ephemeris for GPS SV 10
SUPL: Received Ephemeris for GPS SV 11
SUPL: Received Ephemeris for GPS SV 12
SUPL: Received Ephemeris for GPS SV 13
SUPL: Received Ephemeris for GPS SV 14
SUPL: Received Ephemeris for GPS SV 15
SUPL: Received Ephemeris for GPS SV 16
SUPL: Received Ephemeris for GPS SV 17
SUPL: Received Ephemeris for GPS SV 18
SUPL: Received Ephemeris for GPS SV 19
SUPL: Received Ephemeris for GPS SV 20
SUPL: Received Ephemeris for GPS SV 21
SUPL: Received Ephemeris for GPS SV 23
SUPL: Received Ephemeris for GPS SV 24
SUPL: Received Ephemeris for GPS SV 25
SUPL: Received Ephemeris for GPS SV 26
SUPL: Received Ephemeris for GPS SV 27
SUPL: Received Ephemeris for GPS SV 28
SUPL: Received Ephemeris for GPS SV 29
SUPL: Received Ephemeris for GPS SV 30
SUPL: Received Ephemeris for GPS SV 31
SUPL: Received Ephemeris for GPS SV 32
SUPL: Trying to read Acquisition assistance from SUPL server...
Actual RX Rate: 2000000.000000 [SPS]...
Actual RX Freq: 1575420000.000000 [Hz]...
PLL Frequency tune error 0.000000 [Hz]...Actual RX Gain: 40.200000 dB...
Front-end RAW samples captured
Using Volk machine: sse4_2_64_orc
Searching for GPS Satellites in L1 band...
[ . . . . 5 . 7 8 9 . . . . . . . . . 19 . . . 23 . . . 27 28 . 30 . . ]
Total signal acquisition run time 2.73478 [seconds]
Reference Time:
GPS Week: 851
GPS TOW: 276680 22134.400000
~ UTC: Tue Dec 15 20:51:21 2015
Current TOW obtained from SUPL assistance = 276680
Doppler analysis results:
SV ID Measured [Hz] Predicted [Hz]
5 3000.00 871.77
7 2875.00 524.39
8 2500.00 170.24
9 1125.00 -1220.17
19 6000.00 3734.82
23 -750.00 -3032.99
27 687.50 -1703.53
28 4375.00 2306.86
30 3750.00 1621.38
Parameters estimation for Elonics E4000 Front-End:
Sampling frequency =1999997.27 [Hz]
IF bias present in baseband=2151.87 [Hz]
Reference oscillator error =-1.37 [ppm]
Corrected Doppler vs. Predicted
SV ID Corrected [Hz] Predicted [Hz]
5 848.13 871.77
7 723.13 524.39
8 348.13 170.24
9 -1026.87 -1220.17
19 3848.13 3734.82
23 -2901.87 -3032.99
27 -1464.37 -1703.53
28 2223.13 2306.86
30 1598.13 1621.38GNSS-SDR Front-end calibration program ended.

The important outputs are highlighted above, the sampling frequency and the IF bias. The sampling frequency is nominally 2 MHz but deviation of a few Hz are normal. Baseband is defined as 0 Hz, so when the signal is shifted to baseband if the signal is not exactly centered at 0 Hz this bias is calculated as an IF bias. 

To receive GPS, then, we can copy the gnss-sdr_GPS_L1_rtlsdr_realtime.conf file (typically located in /usr/local/share/gnss-sdr/conf) to another directory and make a few edits. Handily enough there are comments in the file like this

NSS-SDR WITH RTLSDR DONGLES USER MUST SET THE CALIBRATED SAMPLE RATE HERE
; i.e. using front-end-cal as reported here:http://www.cttc.es/publication/turning-a-television-into-a-gnss-receiver/


at each place we need to make an edit. The four edits you need to make are

GNSS-SDR.internal_fs_hz=(your sampling frequency)
SignalSource.sampling_frequency=(your sampling frequency)
InputFilter.sampling_frequency=(your sampling frequency)
InputFilter.IF=(your IF bias)

Once complete, you can run the receiver 

gnss-sdr ---config_file=/path/to/your/gnss-sdr_GPS_L1_rtlsdr_realtime.conf

It will likely take a minute or two to get a fix as a certain amount of ephemeris and almanac data must be downloaded from the satellites. You also must have at least four satellites in view. Here is example output once a fix was found:


Using the KML file generated by gnss-sdr I was able to plot the locations generated in Google Earth


The red dots are individual position fixes. The blue arrow points to the skylight where my GPS antenna is mounted. The road is a two-lane road with no shoulder and the boat in the backyard is 20' long. There is a bias which may be due to the fact that the roof occludes satellites to the east (the four satellites I picked up were, at the time, overhead and eastward). I want to move the antenna up to a (plastic) roof vent in the attic to get a better view of the sky.


Testing gnss-sdr with prerecorded data

Under the documentation section of gnss-sdr.org there is a post entitled "First positioning fix using Galileo" where they document getting a position fix using (at the time) all four Galileo satellites (there are now ten in orbit). They provide not only the position fix but the raw I/Q data which can be fed into gnss-sdr to replicate the fix. This makes a good first test of a gnss-sdr installation.

The page is not incredibly verbose so I will add some verbosity here. First off download and decompress the data from the link provided on the page. Inside the folder you will find the raw data file (.dat) along with a configuration file (.conf) USRP recording output log (.log) and output from their gnss-sdr run (.txt), Google Earth output (.kml) and NMEA messages (.nmea) 

Unfortunately the provided configuration file doesn't work with the current gnss-sdr. However the default configuration file provided with gnss-sdr works just fine. So do the following

  1. Copy gnss-sdr.conf from the installation location (typically /usr/local/share/gnss-sdr/conf/gnss-sdr.conf) to the directory containing the raw data file you downloaded
  2. Update the line SignalSource.filename to the full path filename of the data file
  3. Set GNSS-SDR.SUPL_read_gps_assistance_xml=false

Once you made those two tweaks you can execute the example by running
gnss-sdr --config_file=/path/to/my/gnss-sdr.conf

You should see similar but not identical output to the output provided with the data file. Once the run completes you should have a number of new files. The KML and NMEA files were already described, but you will also see some files named GSDR350w40.15N and GSDR350w40.15O. The file ending in "N" is the navigation solution and the file ending in "O" is the observables. Basically, the navigation solution is your 'fix' and the observables are what information you received from the satellite to generate that fix. Lastly, the gps_ephemeris.xml is an ephemeris which is a description of the satellites' orbit in space.

Setting up gnss-sdr in Kali Linux


Here's instructions on how to set up gnss-sdr in Kali Linux virtual machine. Kali Linux is

... an open source project that is maintained and funded by Offensive Security, a provider of world-class information security training and penetration testing services. In addition to Kali Linux, Offensive Security also maintains the Exploit Database and the free online course, Metasploit Unleashed.

Most importantly, it comes with a modern version of GNURadio and up to date versions of nearly all the dependencies, making getting gnss-sdr installed quite easy.

Installation Instructions

1. Download the Kali Linux VM, or install Kali Linux from ISO.

2. Create a user account and home directory

3. Update apt-get
sudo apt-get update
4. Install cmake
sudo apt-get install cmake
5. Install gnss-sdr dependancies
sudo apt-get install libboost-all-dev gnuradio-dev liblapack-dev libgnutls-openssl-dev libgoogle-glog-dev liblog4cpp5 liblog4cpp5-dev liblog4cpp-doc
6. Install Doxygen
sudo apt-get install doxygen doxygen-gui graphviz
7. Install gnss-sdr (instructions derived from http://gnss-sdr.org/node/45)
git clone https://github.com/gnss-sdr/gnss-sdr
cd gnss-sdr/build $ cmake -DENABLE_OSMOSDR=ON ../
make
sudo make install
make doc
make pdfmanual
make doc-clean
The -DENABLE_OSMOSDR=ON is required to build the rtlsdr drivers!

You should now have a working copy of gnss-sdr; to test it out type gnss-sdr into your console and you should see something like this:


There is an error message because no configuration file was specified, and the default configuration file doesn't point to a valid signal source on my file system (and likely yours, either). No worries we'll fix that later. The message generated here indicates a good installation.