Tuesday, December 27, 2016

RTL-SDR to Orbit with LimeSDR!

As promised, I'd like to show you how the LimeSDR can be used as a GPS simulator to fake out a RTL-SDR device using a rocket trajectory and gps-sdr-sim.

First, I need to thank Dr. Takuji Ebinuma - the author of gps-sdr-sim, who provided me with the rocket trajectory. Takuji designed and built the GPS/GLONASS receiver for the satellite TRICOM 1, scheduled to be launched early next year on the Japanese SS-520-4 rocket. The satellite weighs 3kg and will be spin-stabilizied and contains an earth imaging camera. Here's a picture of the satellite, the GPS/GLONASS receiver is the yellow box:

The rocket is pretty cool too - a 3 stage to orbit vehicle just under 32' long and 2' in diameter which can put a few kilograms into orbit. The launch vehicle is tiny compared to conventional launch vehicles like Altas, Delta or Falcon. Its relative size and scale are encouraging to ambitious amateurs who would like to tackle the project of putting something small into orbit.

More information on the satellite and rocket can be found in this article. Takuji also blogged about it on his blog.

On to the simulation. Takuji provided the trajectory file which is included with his bladeGPS real-time simulator. The trajectory is generated using OpenTsiolkovsky, an open-source rocket trajectory simulator. The trajectory goes from T-60 seconds through the first orbital period but I will only be investigating the first 6 minutes of the trajectory. SoftGNSS only acquires satellites once, at the beginning of processing, so by 6 minutes in several satellites are starting to fall out of view and the GPS fix starts to wander and ultimately fail. However the first 6 minutes are sufficiently interesting as the vehicle accelerates from standing still in the ECEF (Earth Centered Earth Fixed) frame to orbital velocity.

Using gps-sdr-sim (with one tweak - in gpssim.h, change USER_MOTION_SIZE to 3600 or higher to allow for 360+ seconds of simulation, then recompile) the baseband RF can be generated by executing the following:

./gps-sdr-sim -e brdc3540.14n -u ss520-4.csv -d 900 -o trajectory_10M.s8 -s 10000000 -b 8

Then I took the flowgraph I used last time, disabled the receive chain and updated the source file on the transmit chain. I connected the output from my LimeSDR directly to the 1PPM RTL-SDR with bias tee I've been using for testing over the past year. I started the transmission in GNU Radio and then captured the RF using rtl_sdr on the command line like so:

Here is the setup. The USB cable sends samples from GNU Radio to the lime colored LimeSDR. The output from transmitter 1 is sent via SMA cable to the RTL-SDR stick plugged directly in the computer. The samples from the RTL-SDR stick are then captured by rtl_sdr on the command line:

Feeding the output from the RTL-SDR into SoftGNSS, we can see the RTL-SDR captures the trajectory of the rocket from launchpad to low earth orbit. Green satellites are sufficiently strong to track, I use the seven strongest satellites in my navigation solution below.

We can clearly see all three motor burns in the velocity profile. These align well with the values given in the input deck.

Finally, a map showing the ascending trajectory of the rocket as it flies from Uchinoura Space Center in Japan. The three red segments are the three stage burns. Yellow denotes coast phases. 

Now, while this is very exciting, there are a few important caveats
  1. The signal generated is perfect: there is no thermal noise or other RF interference
  2. The trajectory is idealized: acceleration is smooth and there is no jerk
  3. There is no occlusion of satellites due to the location and orientation of the antenna on the vehicle
  4. There is no structural vibration or other environmental factors
As such there is no guarantee a RTL-SDR would perform as admirably on an actual rocket.

Next: will be focusing my attention on working with the FPGA.

Tuesday, December 20, 2016

GPS Fake-out with the LimeSDR

I've been privileged to receive an early LimeSDR unit to perform some testing and demonstration! Today I'd like to show you the LimeSDR, the 3d printed case I designed for it, and a demonstration of using the LimeSDR to simulate GPS signals.

First, here's the LimeSDR. It was funded via Crowd Supply and features dual TX/RX with operating frequencies of 100kHz to 3.8GHz at 12 bits, full duplex! You can find more information at the Crowd Supply link and at the MyriadRF discourse.

First thing I did was to design a case to be 3D printed to protect the board. I am always paranoid about using bare circuit board. (Part of the reason I've been negligent in posting the past few months is because I caught the 3D printed bug. My kids and I have been busy building and fighting plastic antweight robots at Robot Roundabout) You can download the STL models of the case from Thingiverse. Here's the case in action:

I used a sharpie to mark the channels and TX/RX. I have a CAD model which has those engraved, but my printer is not quite that precise. I'm pretty happy with the case it has served me well. The only thing I might add is a clip to hang it from my laptop monitor like I did with my HackRF. If you decide to use it and have any feedback I'd be happy to take it! 

So once you get your LimeSDR, it is pretty straightforward to set up. Under Linux, follow the instructions on the wiki, with one minor alteration: during step 2.1 do not apt-get limesuite or limesuite-udev. Instead, continue with the instructions as you will be installing LimeSuite from source in Step 4.1. On my machine, anyways, the presence of the lms7 driver from the ppa and the lms driver installed from source confused SoapySDR. If you are using Windows, download the drivers from here, plug it in to your USB port and tell Windows where the drivers reside. You can then download Pothos to run GNURadio and other supported applications in Windows.

So once I was set up under Linux, I did the canonical SDR test of tuning in the FM band in gqrx. And behold, there was spectrum! Next, to probe the features of the device, use the command "SoapySDR --probe". Study the output closely and you will see there are multiple transmit and receive antennas for each channel. Cross-check the names with the LimeSDR Schematic (page 5/6) and you can see the appropriate frequency ranges for each antenna. You will need to know which antenna port your antenna is connected to so you can tell GNURadio which antenna to tune.

On to GNU Radio. If you have your own installation, make sure that gr-osmosdr is installed with SoapySDR enabled. If you use pybombs, you can uninstall gr-osmosdr and then reinstall gr-osmosdr and it should work since you installed SoapySDR two paragraphs ago. Alternately if you don't have GNU Radio installed you can get them from the MyraidRF GNU Radio PPA.

In order to fake out GPS, I needed to either record and replay acquired GPS signals, or generate the GPS signals from software. I opted for the latter, as eventually I want to simulate high speed and high altitude trajectories to test software receivers on the bench. I used gps-sdr-sim by Takuji Ebinuma. An open-source code, it uses a GPS broadcast ephemeris file (one is provided) to orient the satellite constellation, and then based on a user specified location or path you can generate a baseband signal of the GPS constellation. For this first example, I picked a fixed location, 5 degrees latitude, 10 degrees longitude, 15 feet altitude - nice, round numbers that happen to lie outside Nkongsamba in Cameroon. I used 10Msps and 8 bits of I/Q resolution. The command line is thus:

./gps-sdr-sim -e brdc3540.14n -l 5,10,15 -d 60 -s 10000000 -b 8
Now to build the GNURadio flowgraph. On the transmit chain, we need to read in the file generated by gps-sdr sim, convert it from 8 bit interleaved samples (I,Q,I,Q,I,Q...) into 32 bit Complex values for the osmocom sink. For the file source, grab the full file path and set repeat to false. This is what I consider to be best practice because if you repeat, you won't see a change in the statistics of the transmission, but the satellites jump places in the sky and this will cause errant results on the decoding. If you don't repeat, the void will be filled in with null values and this, statistically, is visible to the naked eye in a waterfall. For the osmocom sink, specify the device string and the antenna. 

On the receive chain, our source is the LimeSDR using the same device arguments but specifying the LNAW output antenna. We use the Complex to IChar block to reduce from 32 bit integer to 8 and interleave the samples, and write to file.

The complete flowgraph looks like this:

If you are having trouble setting up your flowgraph, you can download my grc file

On the hardware side you need to connect the transmit antenna (BAND1) to the receive antennal (LNAW). To do this I used a direct connection via SMA cables and an attenuator. Once connected I ran the flowgraph. I then took the recorded file and ran it through my fork of SoftGNSS.

What's next? I want to fake out the flight RTLSDR stack with a rocket-type trajectory with velocity/altitude which violates the so-called COCOM limits. After that, I am going to play with the FPGA on board the LimeSDR. 

Thursday, October 6, 2016

Blue Origin In-Flight Escape Test

Super proud "dad mode" on.

I work for Blue Origin. I had the honor and privilege of representing the company as one of the co-hosts for the live webcast. The full webcast is here, if the director's cut (below) gets your blood pumping you should definitely watch the entire flight.

I've spent the last four and a half years working on the propulsion modules' aerodynamics and integrated simulation. It's my baby. I'm glad to have her back from space after five successful missions, including a triggered in-flight escape. 

More cool footage: here's a frame-by-frame of the escape event:

While I enjoy playing with SDR in my free time - this is my passion. Gradatim Ferociter! 

Tuesday, September 27, 2016

Navigation bit plot

Inspired by http://kom.aau.dk/project/softgps/galileoSdr.php the following plot shows the bits sent by PRN-31 over the course of one hour, recorded about a month ago. Each row is a single subframe (6 seconds) and a total of 300 columns represents the bits from each subframe.

Thursday, August 25, 2016

SoftGNSS w/5 Satellites

I fixed a few small bugs and added a few features. In addition, I played around with skipping the initial few milliseconds of sample time and I'm now able to get a fix with five satellites. This gets a better fix and removes the noise we saw in the last post. We now get a pretty clean trajectory without the 'jitter' until after apogee where the nose cone deploys and the radio is dangling under drogue.

The speed of sound is 343 m/sec at sea level; the flight briefly but clearly passed the speed of sound. 

I posted my fork of the SoftGNSS code on GitHub so you can attempt to reconstruct the flight for yourself and play with the data. You can also look at other data sources. I'm sure there are still improvements to be made, but the code is usable. The code requires Matlab. To use,
  1. cd to \SoftGNSS\GNSS_SDR
  2. edit initSettings.m, line 60 to point to the data file (you can download it here, 1.3GB)
  3. run 'init'
This code is flexible enough to work with a variety of file formats; a close inspection of initSettings will show you the options you can play with. The Matlab documentation for fread will provide insight into which format type to use for different data types. Experiment boldly!

One thing I haven't teased out yet: The number of satellites acquired varies depending on the number of bytes skipped. A small jump in a file will change the number of satellites seen, which shouldn't happen, barring a satellite moving out of the visible horizon, but in this case I can step through the file every couple of milliseconds and see satellites come and go. My first instinct is to suspect this is due to automatic gain control (AGC) and changes in the AGC may influence whether or not you pick up the weaker satellites. I don't know for sure; it may also be the way the satellite search is performed, but it's something I'd like to tease out in the near future. 

Tuesday, July 5, 2016

Paul Breed Rocket Test Flight Data #4: SoftGNSS

So where we last left off, I had successfully tracked the last 15 seconds of coast before apogee using GNSS-SDR. We discovered thanks to a little help from jddes on reddit that there was a loud burst of RF noise (confirmed by Paul to be due to a 900 MHz wireless igniter) which caused GNSS-SDR to lose lock on the GPS signal. It had to reacquire and could not do so for ~ 15 seconds

To quote myself:
There are 30 seconds from ignition to apogee, gnss-sdr loses lock during motor firing (~6 seconds) assuming that is insurmountable there is a maximum of 18 seconds of valid GPS data. Assuming perfection, you could start tracking on the next subframe and have a maximum of 20 seconds of flight data, (if you miss that subframe, 15 seconds) so we're over halfway there.

The assumption, in bold, is incorrect! There is no need to wait for a valid subframe of data to resume calculating pseudoranges, rather, the only thing required is that we are locked onto the signal, ie, that our DLL and PLL are actively and correctly tracking the signals. I am still investigating, but this appears to be due to the way gnss-sdr performs the acquisition and tracking: re-acquisition occurs shortly after the noise source goes away, but tracking doesn't occur until after the next subframe is acquired. I believe this is an implicit assumption in the code which doesn't perform a tracking check until that subframe comes in but I am still investigating and will update this post when I determine the exact culprit.

Earlier this year I read the book A Software-Defined GPS and Galileo Receiver: A Single-Frequency Approach. With the book came an accompanying CD with a Matlab-based GPS receiver (GPLv2 licensed) and there are several updates available online. I was unable to run the example data provided with the book and felt gnss-sdr was a far more mature solution. I cached the code for later. After a few months it was gnawing at me that the code wasn't working and I wanted to try and get Paul's data working in another code. It took a week of evenings to get the code up and running, primarily due to Matlab language changes to legacy functions and several bugs in the code. I will document this in an upcoming post along with a link to my repository of the updated code.

It took another evening or two to get Paul's data fed in, as the data type was different (8 bit I/Q instead of 8 bit real) and there were a number of hardcoded assumptions in the code (including file seek operations and FFT bin sizes) that had to be exposed as parameters to get the data working...

...But work it did! The code tracks through the entire ascent until the nose cone jettisons to deploy drogues at apogee, and a few seconds beyond that although it becomes very noisy as the receiver suffers from multipath and the GPS constellation coming in and out of view as the cone tumbles. You will notice the signal is pretty noisy in the east and up components with up to 200 meters of error - this is due to the GPS constellation orientation (bottom right). All of the satellites are in the east quadrant and thus we get excellent resolution in the north direction but poor (ambiguous, one-sided) resolution in the east and up directions. There is a satellite to the west (PRN13) which gnss-sdr picks up. SoftGNSS will acquire it but not successfully track it - if I can get that tracking, the noise in the E/U channels will go away.

Coplotted with the GNSS-SDR data and the Big Red Bee GPS tracker, things fit nicely.

The BRB, gnss-sdr and SoftGNSS all agree on the location of the launch site. gnss-sdr (yellow) loses it at ignition but reacquires near apogee. SoftGNSS tracks all the way past apogee into reentry when the nose cone is swinging under drogue and the BRB reacquires satellites all the way to the ground. Between SoftGNSS and the BRB tracker we have end-to-end GPS coverage for the flight, with gnss-sdr confirmation at liftoff and apogee. The max speed according to SoftGNSS (with generous filtering) is 350 m/s... right about Mach 1. Still below the CoCOM limit for velocity, but as we see the COTS GPS solution loses lock where we are able to tease out a PVT solution.

So why did this work where gnss-sdr failed? Basically, the naivete of the SoftGNSS program design alowed it happen. SoftGNSS only acquires satellites at the start of file (plus specified offset). It then processes the data, tracking the signals with DLL/PLL for the duration of the file. Once all the file is processed it looks for the first subframe and decodes the next 30 seconds of transmission (five subframes at 6 seconds/subframe) to propagate the ephemeris for each satellite. It then takes the timing information from signal that was tracked to calculate pseudoranges. So long as the DLL/PLL retains a lock we get valid pseudoranges and there's no signal saying "We lost lock, stop calculating pseudoranges." More or less. The figure below shows tracking for PRN22. On the bottom left you see the filtered PLL discriminator which stays tight until liftoff where there's notable jump due to doppler (and likely RTLSDR cystal drift due to acceleration).

    1. Big Red Bee GPS tracker KML file
    2. GNSS-SDR KML file
    3. SoftGNSS KML file

    Action Item List
    1. Update post on cause of gnss-sdr delay in tracking after losing acquisition
    2. Post on SoftGNSS with links to my github repo

    Tuesday, April 12, 2016

    GNURadio XMLRPC hints

    If you are like me with a Windows computer using GNURadio in a VMware virtual machine, here's what you need to know to XMLRPC from a remote computer into your VMware instance on your local machine.

    First, you need to make sure your VMWare instance is using a bridged connection. A bridged connection will present your VMware instance as a separate computer to your router giving it a unique IP address on the LAN (note: it is possible to use NAT, where the VMware instance appears on a private LAN to your PC, but the configuration gets messy for port forwarding)

    Now, you should be able to use XMLRPC on your LAN. Download the example scripts from the GNURadio repository. In your virtual machine open up 'xmlrpc_server.grc' in grc. Open up the XMLRPC server block and change the IP address from 'localhost' to '' and the port to whatever port you want to use.

    If you use 'localhost' you will default to the local loopback device and will not be able to reach it from outside the VM instance. Execute the diagram and start the server - you should see a window pop up with a scope and FFT. 

    You will need to get your VMware instances' IP address using ifconfig or some other tool. In my case it is

    On your client machine, download the example scripts and open up 'xmlrpc_client.grc' and edit the XMLRPC client blocks to use the IP address of your VMware instance and the same port

    Execute the diagram and move the slider - you should see it update on the server.

    Now, if you want remote access from outside your LAN we need to configure the router. First off for convenience' sake give the VMware instance a static or reserved IP address so that the MAC address of the VMware instance will always get the same IP address on the local network. Now, we can configure port forwarding, in which your router will take incoming traffic on a certain port and forward it to your virtual machine. My configuration looks like this:

    Now you need to determine your routers' IP address or - better yet - set up a dynamic DNS address so that you can use a URL to always hit your router. I'm not telling you mine :) but I use a free one from freedns.afraid.org. Now go to your off-the-lan computer and update the XMLRPC client as above, but with your router IP address or dynamic DNS. If you did everything right it will work!

    Friday, April 8, 2016

    Paul Breed Rocket Test Flight Data #3: MOAR RESULTS!

    I got a little help on Reddit. Thanks to PE1NUT for identify a way to visualize the crystal drift in the data and jddes for doing some sleuthing: he identified some On Off Keying (OOK) right at ignition. Sure enough; I loadded the data up in Inspectrum (which I should have done in the first place!):

    Turns out Paul is using a 900 MHz wireless transmitter to ignite the rocket which sends OOK for about 1.5 seconds, which leave its mark at 1.5 GHz! There are peaks at ~ -300kHz and ~ +650kHz.

    So I played around with filtering the data with mixed success initially. When you look at the data, the intermediate frequency (IF) is 110 Hz, or damn near zero, so half the spectrum is negative in frequency and the other half is positive. In order to filter just one half of the spectrum you need to have complex taps on your FIR filter. Now, the problem is most of the GNURadio filter blocks don't expose complex taps! The generic FIR filter and the band pass filter do but you have to provide the taps. Fair enough... but the gui to firdes (Finite Impulse Response Design tool) doesn't expose complex taps either! Ideally we'd want two band reject or notch filter. But since the band pass filter does work with complex taps we can add (n+1) band pass filters together to do the same thing - we just band pass two chunks instead of band rejecting one. Ultimately the flowgraph looks like this:

    I also put in an automatic gain control block to try and deal with the jumps in the spectrum (horizontal lines). You can download the flowgraph if you like.

    The easiest way to just filter a chunk of time is to split up the data file into three - the first part, the noisy part, and the last part. A combination of "split -b" and "head -c" are used on the command line, then the files are re-merged with CAT.

    Here's the cleaned-up spectrum. There's still some jumps in the spectrum but the peaks are nulled out. We lose data, but the hope is that the data lost is outweighed by the interference removed.

    I still don't get a valid fix during engine firing but I do reacquire satellites a bit quicker... meaning more data in flight!  Updated trendline in black. Tracking from ~ 3500m to 5000m, covering 12 seconds of flight. There are 30 seconds from ignition to apogee, gnss-sdr loses lock during motor firing (~6 seconds) assuming that is insurmountable there is a maximum of 18 seconds of valid GPS data. Assuming perfection, you could start tracking on the next subframe and have a maximum of 20 seconds of flight data, (if you miss that subframe, 15 seconds) so we're over halfway there. Of course, not losing it during the motor firing would be ideal!

    Money shot

    Tuesday, April 5, 2016

    Paul Breed Rocket Flight Test Data #2: PROGRESS!


    Success kid is successful.

    So I managed to get a valid navigation solution for ~ 7 seconds in flight close to what I presume is apogee, absent additional information. Paul flew an IMU but lost the SD card and a Big Red Bee GPS tracker which is, of course, subject to CoCom limits. Below I plotted both the RTLSDR (in red) and the Big Red Bee (in yellow... in retrospect this should have been red!)

    I removed spurious readings from the GPS tracker: these are easy to identify because the GPS time is out of sync. The long red and yellow lines connect the dots from the last good reading on the pad to the first good reading in flight, and are not representative paths per see. If we assume data to be correct it appears the RTLSDR acquires a navigation solution at a higher altitude than the BRB, which based on the speed and drift is operating under chutes. Next up I extracted the the lat/lon/alt from the PVT solution generated by GNSS-SDR (again, the blue line is just connecting the last good fix on the pad with  the first good fix in flight). The data is aligned with the last good fixes for both the RTLSDR and BRB. 

    Now we get confirmation that the RTLSDR does indeed acquire before the BRB, and a little mental extrapolation can connect the dots between the last RTLSDR sample and the first BRB sample post-launch if we presume the rocket is drifting steadily under a drogue parachute. (The inflection in the BRB is likely going from drogues to main chute - awaiting confirmation.)

    The rocket pops the nosecone at apogee to deploy a drogue chute, at which time the nosecone is swinging in the breeze and we don't anticipate getting any data from the RTLSDR because the directional antenna is no longer pointed up. However the BRB is expected to get a fix under chutes, when within the CoCom limits. My thesis is that we get a valid GPS solution about 7 seconds before popping the nosecone and deploying the drogue, which then causes us to lose track on most of the satellites and thus lose our navigation solution. Indeed, the rest of the flight is filled with messages of acquiring and subsequently losing acquisition of satellites.

    Here's an excerpt of the output from just before liftoff to just after apogee:
    Current input signal time = 145 [s]
    NAV Message: received subframe 3 from satellite GPS PRN 22 (Block IIR)
    NAV Message: received subframe 3 from satellite GPS PRN 31 (Block IIR-M)
    NAV Message: received subframe 3 from satellite GPS PRN 1 (Block IIF)
    NAV Message: received subframe 3 from satellite GPS PRN 14 (Block IIR)
    NAV Message: received subframe 3 from satellite GPS PRN 3 (Block IIF)
    NAV Message: received subframe 3 from satellite GPS PRN 10 (Block IIA)
    NAV Message: received subframe 3 from satellite GPS PRN 25 (Block IIF)
    Position at 2016-Feb-06 18:45:47 UTC is Lat = 35.34828164793844 [deg], Long = -117.8089714500355 [deg], Height= 646.4366382388398 [m]
    Current input signal time = 146 [s]
    Position at 2016-Feb-06 18:45:48 UTC is Lat = 35.34792485975112 [deg], Long = -117.8090110485498 [deg], Height= 653.1580742103979 [m]
    Current input signal time = 147 [s]
    Position at 2016-Feb-06 18:45:49 UTC is Lat = 35.34836233536886 [deg], Long = -117.8087743892498 [deg], Height= 622.0710280425847 [m]
    Current input signal time = 148 [s]
    Position at 2016-Feb-06 18:45:50 UTC is Lat = 35.34776621261069 [deg], Long = -117.8090573844694 [deg], Height= 649.063727453351 [m]
    Current input signal time = 149 [s]
    Position at 2016-Feb-06 18:45:51 UTC is Lat = 35.34842555835016 [deg], Long = -117.8087875236563 [deg], Height= 634.0006730658934 [m]
    Current input signal time = 150 [s]
    Position at 2016-Feb-06 18:45:52 UTC is Lat = 35.34802741910629 [deg], Long = -117.808877076439 [deg], Height= 641.1753705441952 [m]
    Current input signal time = 151 [s]
    NAV Message: received subframe 4 from satellite GPS PRN 22 (Block IIR)
    NAV Message: received subframe 4 from satellite GPS PRN 10 (Block IIA)
    Loss of lock in channel 5!
    Tracking start on channel 5 for satellite GPS PRN 11 (Block IIR)
    Current input signal time = 152 [s]
    Loss of lock in channel 6!
    Loss of lock in channel 3!
    Tracking start on channel 6 for satellite GPS PRN 31 (Block IIR-M)
    Tracking start on channel 3 for satellite GPS PRN 14 (Block IIR)
    Loss of lock in channel 0!
    Tracking start on channel 0 for satellite GPS PRN 1 (Block IIF)
    Loss of lock in channel 4!
    Tracking start on channel 4 for satellite GPS PRN 22 (Block IIR)
    Current input signal time = 153 [s]
    Loss of lock in channel 5!
    Tracking start on channel 5 for satellite GPS PRN 11 (Block IIR)
    Loss of lock in channel 6!
    Tracking start on channel 6 for satellite GPS PRN 31 (Block IIR-M)
    Loss of lock in channel 3!
    Tracking start on channel 3 for satellite GPS PRN 14 (Block IIR)
    Loss of lock in channel 0!
    Tracking start on channel 0 for satellite GPS PRN 1 (Block IIF)
    Loss of lock in channel 4!
    Tracking start on channel 4 for satellite GPS PRN 22 (Block IIR)
    Current input signal time = 154 [s]
    Current input signal time = 155 [s]
    Loss of lock in channel 4!
    Tracking start on channel 4 for satellite GPS PRN 22 (Block IIR)
    Current input signal time = 156 [s]
    Current input signal time = 157 [s]
    Loss of lock in channel 4!
    Tracking start on channel 4 for satellite GPS PRN 22 (Block IIR)
    Current input signal time = 158 [s]
    Current input signal time = 159 [s]
    Current input signal time = 160 [s]
    Current input signal time = 161 [s]
    Current input signal time = 162 [s]
    Current input signal time = 163 [s]
    NAV Message: received subframe 1 from satellite GPS PRN 11 (Block IIR)
    NAV Message: received subframe 1 from satellite GPS PRN 14 (Block IIR)
    Current input signal time = 164 [s]
    Current input signal time = 165 [s]
    Current input signal time = 166 [s]
    Current input signal time = 167 [s]
    Current input signal time = 168 [s]
    Current input signal time = 169 [s]
    NAV Message: received subframe 2 from satellite GPS PRN 11 (Block IIR)
    Current input signal time = 170 [s]
    Current input signal time = 171 [s]
    Current input signal time = 172 [s]
    Current input signal time = 173 [s]
    Current input signal time = 174 [s]
    Current input signal time = 175 [s]
    NAV Message: received subframe 3 from satellite GPS PRN 1 (Block IIF)
    NAV Message: received subframe 3 from satellite GPS PRN 11 (Block IIR)
    NAV Message: received subframe 3 from satellite GPS PRN 14 (Block IIR)
    NAV Message: received subframe 3 from satellite GPS PRN 3 (Block IIF)
    Current input signal time = 176 [s]
    Position at 2016-Feb-06 18:46:18 UTC is Lat = 35.3536423978743 [deg], Long = -117.8154004936006 [deg], Height= 4891.649443297647 [m]
    Current input signal time = 177 [s]
    Position at 2016-Feb-06 18:46:19 UTC is Lat = 35.35313826705141 [deg], Long = -117.8151172574466 [deg], Height= 4786.770911485888 [m]
    Current input signal time = 178 [s]
    Position at 2016-Feb-06 18:46:20 UTC is Lat = 35.35361800624526 [deg], Long = -117.8156283909009 [deg], Height= 4907.156536793336 [m]
    Current input signal time = 179 [s]
    Position at 2016-Feb-06 18:46:21 UTC is Lat = 35.35351364315449 [deg], Long = -117.815566988265 [deg], Height= 4801.439769400284 [m]
    Current input signal time = 180 [s]
    Position at 2016-Feb-06 18:46:22 UTC is Lat = 35.35325156470748 [deg], Long = -117.8156706709576 [deg], Height= 4741.917847431265 [m]
    Current input signal time = 181 [s]
    NAV Message: received subframe 4 from satellite GPS PRN 22 (Block IIR)
    NAV Message: received subframe 4 from satellite GPS PRN 1 (Block IIF)
    NAV Message: received subframe 4 from satellite GPS PRN 31 (Block IIR-M)
    NAV Message: received subframe 4 from satellite GPS PRN 11 (Block IIR)
    NAV Message: received subframe 4 from satellite GPS PRN 3 (Block IIF)
    Loss of lock in channel 7!
    Current input signal time = 182 [s]
    Tracking start on channel 7 for satellite GPS PRN 23 (Block IIR)
    Loss of lock in channel 3!
    Tracking start on channel 3 for satellite GPS PRN 26 (Block IIF)
    Current input signal time = 183 [s]

    Therefore, based on the output and plots, I believe liftoff takes place at 151 seconds, engine burns for ~ 5-6 seconds (highlighted in yellow), with apogee occurring at 182 seconds, or roughly 30 seconds on ascent. Apogee of ~ 4850 meters ASL.

    The numerous subframes from 163-182 seconds show we are still getting some meaningful data which could be interpreted by a fft-based approach like fastpgs.

    So what did you change?

    I lowered the bandwidth of all 3 tracking loops by roughly half. Previously I had increased the bandwidth on the loops figuring more bandwidth = ability to deal with rapid shifts in phase/frequency but my intuition was incorrect. I'm still a DSP newbie but I am learning.

    To Do
    1. Continue playing with tracking loops 
    2. Investigate fastgps fft-based solutions

    1. BRB.kml - Big Red Bee GPS Logger
    2. RTLSDR.kml - RTLSDR tracking

    Saturday, April 2, 2016

    Paul Breed Rocket Flight Test Data!

    This post is long overdue as I've been quite busy with my day job that I've been remiss in updating the blog with the progress happening with the rocket GPS.

    On February 6th, 2016 Paul Breed flew an RTL-SDR on a high power rocket to capture GPS RF data for post-processing. This was the second test flight and the first one to get good data.

    Hardware Configuration

    Paul shows off the payload. The blue box outlines a 6DOF IMU, the orange box is a LNA4ALL low noise amplifier. On the reverse the orange box outlines a 2S LiPo battery, the green box a Nooelec 0.5PPM TXCO in aluminum case and the blue box an Intel Compute Stick running Ubuntu, and the yellow trapezoid a quadrifilar antenna GPS antenna from antennas.us.

    Backside of RF capture unit.

    Frontside of RF capture unit.

    Hardware Configuration

    They payload is packaged inside the nosecone fairing of the rocket. Here, the rocket is mounted on the launch rail in a horizontal configuration. Before launch the rail is elevated to near vertical, but this orientation allows for easy handling of the rocket.

    Rocket mounted on the launch rail

    At T-2 minutes (2 minutes prior to launch) the rocket begins aquiring data - Paul SSH's over wifi into the Intel Compute Stick to trigger a script which calls rtl_sdr centered on the L1 frequency with a bandwidth of 2048000 Hz. Two minutes is sufficient time to get multiple GPS fixes of the launch site.

    And at T-0, smoke and flames!


    Post-flight analysis

    I took the output from rtl_sdr and converted it to complex for gnss-sdr. I was able to get a fix on the pad but not much after that. The last fix was at about 145 seconds - liftoff was likely between 145 and 150 seconds. I attempted to make a few tweaks to the tracking loop configuration gnss-sdr file with little success - it changed the results but not the actual character, that is not a whole lot after liftoff. I did find I was able to get a few subframes well after launch - 3 with the final configuration file - but not enough to get a fix. But there are other codes to be investigated which can get an approximate fix without a full 4 satellite solution.

    One of the productive changes was decreasing the step size of the doppler search - this performs a more refined search and reveal more post-launch subframes. Initially I had one subframe and through tweaking the search step size (to 100 hz) I was able to get three. It is tempting to increase the doppler window but the max doppler shift of a GPS satellite to a stationary receiver is ~ 5kHz and the default search window is +/- 10 kHz - unless you are going orbital velocity at the satellite while it is coming at you, you are well within 10 kHz.

    Here's the KML file in Google Earth. Don't get too excited about the altitude jumps! There are two of them in the file one occurs during the first few fixes and the last ones are of similar magnitude. I've seen the same thing happen with fixes at home. We know for the early jumps the rocket is sitting soundly on the pad and the latter jump is of the same magnitude.

    I took the GPS time from gnss-sdr and used an online tool to back out the orientation of the satellite constellation during the rocket flight. The arrows point to the satellites which were used to get position fixes as output in the RINEX files. It is interesting to see some satellites which appear farther away on the map are useful to getting a fix where closer ones are not - however that's only half the story.

    If we look at altitude (the earth is crudely pointed so the launch site is oriented up towards the top of your monitor) we see the satellites it uses are largely overhead and the "closer" satellites are on the horizon.

    I also looked at the two satellites which gave valid subframes after T-0, they are PRN 3 and PRN 11, shown here.

    So why didn't we get a good fix in flight? There are two likely culprits - the vibration / acclereation environment and the loop dynamics. Both vibration and acceleration affect the crystal which effects the frequency being captured. If the tracking loops are off then we'd anticipate losing satellite  directly overhead (in the direction of acceleration) and not laterally where the acceleration of the rocket doesn't effect things much. I tweaked the tracking loops as far as I could without making results worse and they didn't seem to get any better. Based on the fact that one of the satellites is fairly high in the sky my gut suspects the acceleration/vibe environment.

    UPDATE: Got a brief in-flight nav solution; see this post!

    But there's still work to be done to try fft-based approaches like fastgps, dig into the intermediate outputs and see if some smart people out there have ideas!

    Thanks to Paul for providing the data, test hardware and ideas on how to look at and understand the data. Follow his blog or twitter!
    1. Feb6.bin - raw RTLSDR binary file (interleaved shorts) you will need to convert to complex.
    2. flight.conf - gnss-sdr configuration file
    3. output.log - Console output from "gnss-sdr --config_file=flight.conf"
    4. PVT.kml - Position fixes in Google Earth format
    5. GSDR086x11.16N - Navigation data in RINEX format 
    6. GSDR086x11.16O - Observation data in RINEX format

    Next Actions
    1. Investigate gnss-sdr telemetry and tracking outputs
    2. Try running through fastgps code 
    3. Get help from smart gps/sdr folk!