Doppler correction with GNURadio

When receiving signals from a satellite, it can be important to correct for the Doppler shift in the signal. Normally, I use Gpredict to track satellites and compute the Doppler shift. Gpredict can control the frequency of a receiver using Hamlib to track the Doppler shift. When using an SDR receiver, there are several possible ways of using Gpredict's frequency control.

Normally, the SDR software doesn't support Hamlib control in a way that it's useful and easy to use for this purpose. This is the case with Linrad, which is the software I use, and probably with many other popular SDR softwares. An easy solution is to let Gpredict completely control the frequency of the SDR receiver through Hamlib and prevent the SDR software from controlling the frequency. With the FUNCube Dongle Pro+, which is the receiver I normally use, this is easy to do. It can be controlled without problem with recent versions of Hamlib, and if you set the dongle in Linrad as an "Undefined" card instead of a FUNCube Dongle, then Linrad will not try to control its frequency.

The problem with this solution is that each time that the frequency gets updated, it does so in a non phase continuous manner, because the PLL of the receiver has to lock on to the new frequency, effectively losing reception for just a tiny amount of time. This supposes no problem for SSB, CW or FM reception, because your ears just don't notice. However, if you want to receive any digital signal or SSTV, the frequency change usually messes with the decoder software, which loses sync and suffers decoding problems. An alternative solution is to leave the receiver frequency fixed and correct for Doppler shift in software.

It turns out that it's quite easy to do this in GNURadio. By using gr-grpedict-doppler, one can interface Gpredict's frequency control with a GNURadio flowgraph. I have made a really simple flowgraph that it's supposed to sit between the FUNCube Dongle Pro+ and Linrad and do it's Doppler correction job. Other SDR receiver hardware and software can be used with this flowgraph with the appropriate setup.

To give you an idea of how this is used, I'll quickly describe my setup. I have set a radio device in Gpredict using port 4534 to control gr-gpredict-doppler. I have the Linux module snd-aloop loaded, and this gets device hw:1. Windows users can probably use some virtual audio cable software. I have my FUNCube Dongle Pro+, which gets device hw:2. The GNURadio flowgraph is set to read from the dongle at hw:2,0 and write to the audio loop at hw:1,0,0. Linrad is set to use an ALSA input at hw:1,1 of type "undefined" (this will read from the other end of the audio loop).

When I want to receive a satellite, I first decide on the centre frequency to use. I have to take into account that I must be able to fit the desired signals into the passband of the dongle, which is 192kHz around the centre frequency. The centre frequency has a DC spike, so the desired signals should not fall on top of it. Also, keep in mind that for a typical LEO satellite the signals will move throughout the pass about +/-3.3kHz if on the 2m band and +/-10kHz if on the 70cm band. I have to take this into account and prevent the signals from going out of the passband or crossing over the centre frequency DC spike as the Doppler shifts them in frequency.

Once I have decided on an centre frequency, I set that frequency into Gpredict, into the GNURadio flowgraph and into the dongle using Qthid. Then I run the flowgraph, engage Gpredict radio control using a 100ms update interval and run Linrad. I also set the correct centre frequency in Linrad (this is only to make the frequency readings in Linrad accurate). This is all that is needed for the setup. Signals of any type, including digital signals can be received without problem.

This kind of techniques can also be used on the transmit side. An application that comes to mind is the PSK31 transponder on PSAT. This transponder can receive several PSK31 signals in a 3kHz passband in the 10m band and downlink that band through FM on the 70cm band. The 10m band is used on the uplink because the Doppler shift is much less than on the VHF and UHF bands. Even so, a usual PSK31 decoder will fail to track signals that drift more than about 1Hz/s, and the 10m Doppler will be more than than in may occasions. Therefore, it is quite useful to use Doppler control on the uplink. This has to be done in a phase continuous manner for the reasons already mentioned.

Fortunately, the total Doppler shift on 10m is only about 1.4kHz. This is smaller than 2.7kHz, which is the passband that an SSB transceiver usually has. Therefore, the Doppler control can be done in software, keeping the SSB transmitter's frequency fixed and doing all the Doppler correction in the audio frequency. There is a program called DopplerPSK which does precisely that: it is a transmit-only PSK31 software that corrects for the transmit audio frequency in a phase continuous manner. To date, it is the only software I know that is capable of doing this. Using a simple GNURadio flowgraph similar to the one that has been describe here, one could also use his favorite PSK31 software (fldigi perhaps) for Doppler corrected transmission. The flowgraph would just sit between the PSK31 software and the audio output connected to the transceiver, and shift the audio frequency to correct for Doppler. I will probably be testing this in the future, when I have access to my HF station.

13 Replies to “Doppler correction with GNURadio”

  1. Hi Daniel,

    Great Job.
    I want to analyse satellite CW signals on gnuradio. With this I need a tracking system with Doppler shift. WHAT is the best way you suggest.

    Now, I have Gpredict installed and added to GNUradio library blocks and I have added the block( doppler) to my flow graph but when I try to run the graph it says

    [traceback (most recent call last):
    File "/home/ernest/Desktop/", line 22, in
    import gpredict
    ImportError: No module named gpredict]

    From your script above, I learn I can control the receiver hardware( HackRf) directly from Gpredict through Hamlib. If I do that, does GNURadio still receives the signals for analysis?

    Secondly, I tried to install Hamlib but it says have to first delete some files of GNURadio before it is installed. I dont want to temper with my healthy running GNURadio companion.

    What do you advice please.
    I am using Ubuntu 14
    I am new the these things.

    Thank You

    1. Dear Ernest,

      You need to install gr-gpredict-doppler as well. The import error you get means that you don't have it correctly installed.

      With my GNURadio script, Gpredict doesn't talk directly to the HackRF. GNURadio sets the HackRF to a fixed frequency and starts reading IQ samples. Gpredict tells the GNURadio script periodically which frequency you should listen for the satellite signal, taking Doppler into account. The GNURadio script uses this information to compute the Doppler shift and then shifts the IQ samples in the frequency domain.

      Of course, you will need to modify the GNURadio script to use an Osmocom block (or whatever you use to read from the HackRF) instead of the Audio Source block, and replace the Audio Sink block by whatever signal processing you want to do in GNURadio.

      The thing is that once you manage to install gr-gpredict-doppler, you don't need much else to make this work. Just run your modified script together with Gpredict. The GNURadio script writes on the console every time it gets a frequency update from Gpredict, so you can know if GNURadio and Gpredict are interfacing well.

  2. Hi, Daniel,

    I am trying to implement the gr-predict-doppler you link to in this post, and I am running into trouble. I'd be grateful if you could point me toward my error.

    My understanding is that I should:

    1. Set up a dummy radio using Hamlib: rigctld -m 1 -t 4532
    2. Configure a GPredict radio as described in the gr-predict-doppler documentation.
    3. In GPredict radio control, "track" a satellite and then "engage" my radio.
    4. Execute my GNURadio flowgraph.

    If I follow this procedure, I encounter a GNURadio error:

    Exception in thread Thread-5:
    Traceback (most recent call last):
    File "/usr/lib/python2.7/", line 801, in __bootstrap_inner
    File "/usr/local/lib/python2.7/dist-packages/gpredict/", line 36, in run
    File "/usr/lib/python2.7/", line 228, in meth
    return getattr(self._sock,name)(*args)
    error: [Errno 98] Address already in use

    I have also tried starting the flowgraph first, then running rigctld. In that case, the connection in port 4532 isn't established via Hamlib, and GNURadio just reports:

    Waiting for connection on: localhost:4532

    Do you have any ideas what I'm doing incorrectly?


    1. Hi Noble,

      You don't need to run step 1 (rigctld) and if your run it, it will actually mess up with everything else, so I think that your problem is just this.

      1. Daniel,

        Thank you very much for your reply. I tried running without executing the rigctld command. Now, when I execute the GNURadio flow graph, I receive the message "Waiting for connection on: localhost:4532"

        In GPredict radio control, I then click to "Track" a satellite, and then click to "Engage" the radio. However, when I click engage, GPredict becomes unresponsive, and I have to either (1) exit the GNURadio flow graph or (2) force-quit GPredict in order to unfreeze GPredict.

        Have you observed any of these problems before?

        Thanks again,

        1. I haven't ever seen GPredict freeze when trying to do Doppler control. It's a bit weird. Perhaps you can use wireshark or a similar tool to try to debug the TCP connection between GPredict and GNU Radio.

          1. Thanks for your suggestion, Daniel. I used wireshark to take a look a port 4532. I'm not an expert on this, but what appears to be happening is that data is sent from a port (for example, 49912) to 4532. If the gnuradio flowgraph is off, then an ack is sent from 4532 back to the sending port. However, if the flowgraph is running, then no ack is sent, and the original message is repeatedly resent: "[TCP Restransmission]" in wireshark.

  3. That is rather weird. If the GNU Radio flowgraph is off then the TCP connection should not succeed, since no one should be listening on 4532. With the flowgraph off, check if there is something listening on that port using "netstat -lpn" or something similar.

  4. Daniel,

    If the flowgraph is not running, then I do not see any reference to port 4532 with netstat. For what it is worth, I have tried this procedure on two Ubuntu 16.04 computers and received the same result with both.


  5. Daniel,

    I have figured out a way to make things work (or at least a workaround): In, I changed the line




    Now, everything seems to be operating as I expect. Thanks for your help!


  6. Dear Daniel
    I worked on gpredict for hours but could not find a way to feed an old TLE to it. How do you import old TLEs to gpredict in order to correct Doppler of a recorded file?
    Would you mind letting me know the exact procedures required for correcting Doppler of an already recorded file? I mean those steps that should be handled in gpredict.

    1. To feed an old TLE to Gpredict you can do it manually by editing the corresponding file in ~/.config/Gpredict/satdata/

      To correct the Doppler of a recorded file you must use the "time controller" function in Gpredict, pause time and set it to the time when the recording was started. Then you start up the GNU Radio flowgraph and adjust the Radio control function in Gpredict. Finally, you have to simultaneously start playing back the recording while you hit play in the time controller.

Leave a Reply

Your email address will not be published. Required fields are marked *