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).
Action Item List
- Update post on cause of gnss-sdr delay in tracking after losing acquisition
- Post on SoftGNSS with links to my github repo