# GNSS-SDR: a software-defined GNSS receiver that shows you every stage between samples and a fix

> A C++ receiver built around GNU Radio that decodes GPS, Galileo, GLONASS, BeiDou and QZSS signals, and whose real value is the inspectable processing chain rather than the position fix it produces.

**gnss-sdr/gnss-sdr** — GNSS-SDR, an open-source software-defined GNSS receiver

- Repository: https://github.com/gnss-sdr/gnss-sdr
- Website: https://gnss-sdr.org
- Stars: 2,284 · Forks: 736
- Language: C++
- License: GPL-3.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/gnss-sdr-gnss-sdr

## What the receiver actually processes, signal by signal

The README defines the scope by listing signals rather than features. A software-defined receiver here means the program performs detection, synchronization, demodulation and decoding of the navigation message, computation of observables, and finally computation of position fixes. That chain is spelled out because each stage is separately configurable, which is the whole point.

The supported signals are listed by band with their center frequencies. In the L1 band: GLONASS L1 C/A at 1602.000 MHz, GPS L1 C/A at 1575.420 MHz, Galileo E1b/c at 1575.420 MHz, BeiDou B1I at 1561.098 MHz, and QZSS L1 C/A where available at 1575.420 MHz. In the E6 band, Galileo E6B at 1278.750 MHz. In the L2 band: BeiDou B3I at 1268.520 MHz, GLONASS L2 C/A at 1246.000 MHz, and GPS L2C at 1227.600 MHz. In the L5 band: Galileo E5b at 1207.140 MHz, Galileo E5a and GPS L5 both at 1176.450 MHz, and QZSS L5 where available at the same 1176.450 MHz.

That table is more informative than it first appears. Galileo and GPS share center frequencies, which is why a wideband front end can see both constellations in one pass, and BeiDou B1I sitting 14 MHz away from the GPS L1 carrier is exactly the kind of detail a receiver designer has to know. Every entry carries a check mark in the README, so the full list is currently supported rather than aspirational.

The topics on the repository name the surrounding ecosystem rather than just the receiver: gnuradio, rtl-sdr, sdr, signal-processing, gps, galileo, glonass and gnss. A companion project for signal generation appears in the topic list as well, which tells you the ecosystem assumes you will want to feed the receiver something other than a live sky.

## The block chain from signal source to PVT, as the README names it

The table of contents in the README is effectively the architecture, and it is worth reading as a data flow rather than as documentation navigation.

The signal processing plane starts with a Signal Source, which is where a file or a radio enters. That feeds a Signal Conditioner, which is itself three blocks: a data type adapter, an input filter, and a resampler. The conditioner normalises whatever the front end produced into the format the rest of the chain expects, which is the stage that makes a file replay and a live radio interchangeable.

From there each satellite becomes a Channel. A channel contains an Acquisition block, a Tracking block, and decoding of the navigation message, in that order. Acquisition is the search problem: find the code and Doppler for a satellite you do not yet know about. Tracking is the follow problem: keep a lock on it as it moves. Decoding turns the tracked bits into the navigation message, which is what actually contains ephemeris data and time.

Two blocks close the chain. Observables turns decoded data into the measurements a receiver actually navigates with, pseudorange and carrier phase. Computation of Position, Velocity, and Time then solves for a fix.

Above that sits a separate control plane with Configuration and a GNSS block factory. The factory idea matters: rather than hardwiring the chain, the configuration names blocks and the factory builds them, which is what lets the same binary run a one channel demonstration or a multi-constellation setup without recompiling. Full inspection of the whole signal processing chain is listed as a project feature, and that is the feature to keep in mind when comparing this project to a closed receiver.

## Building on Linux, and what the dependency list costs you

There is no installer in this repository and no container image in the tree. You compile it. The README names the tested distributions as Ubuntu 14.04 LTS and above, Debian 9.0 and above, Arch Linux, Fedora 26 and above, and openSUSE 42.3 and above, and lists six ways to get dependencies: packaged install on Debian or Ubuntu, AlmaLinux, Arch, Fedora, openSUSE or Rocky Linux, or a manual route.

The manual route is the informative one, because the README enumerates the libraries instead of hiding them. Armadillo, described as a C++ linear algebra library. Gflags for command line flag processing. Glog for application level logging. The OpenSSL libraries. Matio for MATLAB MAT file I/O. Protocol Buffers for serialization of structured data. Pugixml as a light-weight C++ XML processing library. And GoogleTest, which tells you the test suite is a real part of the build rather than an afterthought.

Armadillo, Matio and GoogleTest together are the dependency profile of a scientific computing project rather than a radio application, which is what you would expect from code that does matrix work on correlation results and writes MATLAB output for offline analysis.

The supported architecture list is unusually long, including amd64, armel, armhf, arm64, i386, loong64 for LoongArch, several MIPS variants, and the PowerPC family in 32-bit and both 64-bit endiannesses. That breadth is a signal about the deployments this receiver has been built for, including single-board computers and embedded systems.

Optional build features are marked as such in the table of contents: OSMOSDR support, FMCOMMS2 based SDR hardware support, OpenCL support and CUDA support. macOS has its own section covering Macports, Homebrew and other package managers, followed by a build step. Two build arguments mentioned in the release notes suggest where the frontier is: enabling FPGA support adds board-specific signal sources for SoC FPGA platforms such as the ADRV9361-Z7035, the FMCOMMS5 front end and the MAX2771 evaluation kit.

## What v0.0.21 tells you about where the project is

The version numbers are the first thing to note. The current release is v0.0.21, published on 2026-04-14, preceded by v0.0.20 on 2025-04-02 and v0.0.19.1 on 2024-01-26. That is roughly one release a year, and a version number that has never left 0.0.x in the project's history on display here. Both facts matter for planning, though neither is a criticism: a receiver is research infrastructure, and the releases carry a Zenodo DOI badge because the project archives each one for citation.

The v0.0.21 notes are a good sample of what a release in this project actually contains, and they are refreshingly specific. The main item is a histogram-based navigation data bit synchronizer for tracking loops, used to detect navigation-bit transitions in signals without a secondary code. Lock is declared when the histogram shows a clearly dominant phase bin, verified with a configurable dominance ratio and a stability criterion, and once synchronized the tracking loop can switch to extended coherent integration, which improves tracking sensitivity and time to first fix.

Three new configuration parameters come with it, and their defaults tell you the tuning philosophy: `Tracking_1C.bs_dominance_ratio` at 0.6 as the ratio between the dominant bin count and the total number of detected transition events, `Tracking_1C.bs_stable_best_required` at 3 as the number of consecutive evaluations agreeing on the same dominant bin, and `Tracking_1C.bs_min_events_for_lock` at 10 as the minimum number of transition events before lock is evaluated. Sensible defaults with every threshold exposed, which is what you want from a receiver whose behaviour you are trying to understand rather than just consume.

Earlier notes show the same pattern. v0.0.20 improved error handling on UDP connections and made it possible to receive multiple constellations using a single channel wideband device, naming HackRF, LimeSDR and USRP explicitly. v0.0.19 added a `flag_geohash_log_out` flag to the PVT configuration and new fields to `monitor_pvt.proto` including a `utc_time` RFC 3339 string and velocity in the local ENU frame.

## Hardware abstraction and why the file replay path matters most

The README claims interfaces for a wide range of radio frequency front-ends and raw sample file formats, and that second half is the part that changes how you can work on the project.

A live radio makes experimentation expensive. Every acquisition experiment depends on where the satellites are, what the interference looks like, and whether the sky is clear. A raw sample file freezes all of that. You can replay the same capture while you change a tracking loop, and the only variable is your change. For a project whose release notes are full of threshold parameters like the bit synchronizer above, that is the difference between tuning and guessing.

This is also why the multi-constellation single-channel support in v0.0.20 matters more than its changelog line suggests. GPS, Galileo and QZSS share the L1 center frequency, so one wideband capture of the L1 band contains all three, and a receiver that can pull more than one constellation out of one channel changes the economics of an experiment.

The output side is similarly deliberate. The project generates processing outputs in standard formats, and the monitor protocol file `monitor_pvt.proto` shows what the observability output looks like: position, velocity, time, and with v0.0.19 the ability to emit a geohash tag in INFO logs through `flag_geohash_log_out`, disabled by default. Protocol Buffers for the telemetry channel and Matio for MATLAB files together mean a capture can leave the receiver in whatever form the next tool wants.

The `conf/` directory in the tree is where those configurations live, and `utils/` is where the command line tools sit. Combined with the `tests/` directory, the picture is a project that treats a run as something you can save, diff and replay rather than something that happened once.

## Licensing, institutional home, and honest limits

GNSS-SDR is GPL-3.0-or-later, stated through an SPDX identifier at the top of the README and a licence badge, with the file list in the tree showing both a `COPYING` file and a `LICENSES/` directory. That is the REUSE specification layout, and the README carries a REUSE status badge alongside it. There is a dedicated About the software license section in the table of contents, which is a good sign: the project has thought about how the licence interacts with the fact that it links against libraries with their own terms.

For most research, teaching and internal tooling use, GPL-3.0 is not an obstacle. It becomes one when you consider linking this into a proprietary receiver product, and that question deserves an answer from your own legal advice before you write code, not after.

The institutional origin is visible in the file header, which carries a copyright line from 2011 to 2026 for Carles Fernandez-Prades at CTTC, the Spanish telecommunications research centre. That is a twenty-year-old line, and the copyright range is itself a statement about continuity. The last push recorded for the repository is 2026-09-28, and there is a Publications and Credits section in the README, which for a project like this is where you find the papers describing the algorithms you are about to read in `src/`.

The honest limits are these. It is C++ with a heavy dependency set, so contributing means matching an existing style in a codebase with conventions set over many years. It is research software, so interfaces can change between minor releases and the 0.0.x numbering reflects that. And the decision to build on GNU Radio, visible in the topics, means you inherit that framework's threading and configuration model rather than choosing your own.

None of that makes it unsuitable. It makes it a project to read before you adopt, which is what the signal processing chain documentation and the changelog are for.

## Conclusion

GNSS-SDR is worth the dependency list if you are doing GNSS research, teaching a receiver's stages, testing a front end, or generating and decoding your own signals. It is the wrong tool for a navigation application: the version line is still 0.0.x, releases arrive roughly annually, and the build wants Armadillo, Gflags, Glog, OpenSSL, Matio, Protocol Buffers, Pugixml and GoogleTest before CMake will run. Two decisions shape everything else. It is GPL-3.0-or-later, so linking it into a proprietary product has consequences you should settle before you start. And the C++ core predates the current open source radio tooling, which is why the companion projects in the topic list exist at all. Start on Linux with packaged dependencies, fix a single GPS L1 C/A channel, and read `docs/CHANGELOG.md` to see whether the release notes mention whatever you are trying to debug.

## FAQ

### Can software defined radio receive GPS signals?

Yes, and GNSS-SDR is built for exactly that. It processes GPS L1 C/A at 1575.420 MHz, GPS L2C at 1227.600 MHz and GPS L5 at 1176.450 MHz, and the v0.0.20 notes describe receiving multiple constellations from a single channel wideband device such as a HackRF, LimeSDR or USRP.

### Which GNSS signals does GNSS-SDR support?

The README lists GLONASS L1 C/A and L2 C/A, GPS L1 C/A, L2C and L5, Galileo E1b/c, E5a, E5b and E6B, BeiDou B1I and B3I, and QZSS L1 C/A and L5 where available. Each entry is given with its band and center frequency, and every one carries a check mark in the current README.

### What is the GNSS block factory in GNSS-SDR?

It is part of the control plane, alongside configuration. The chain from signal source through signal conditioner, channels with acquisition, tracking and navigation message decoding, observables and finally position, velocity and time is described as a sequence of named blocks, which is what lets one binary run different receiver configurations without recompiling.

### What does it take to build GNSS-SDR from source?

The README lists Armadillo, Gflags, Glog, OpenSSL, Matio, Protocol Buffers, Pugixml and GoogleTest as the manual dependency set, with packaged installs offered for Debian or Ubuntu, AlmaLinux, Arch, Fedora, openSUSE and Rocky Linux. Optional build features cover OSMOSDR, FMCOMMS2 hardware, OpenCL and CUDA support.

### What license is GNSS-SDR released under?

GPL-3.0-or-later, declared through an SPDX identifier at the top of the README, with the repository carrying a COPYING file and a LICENSES directory in the REUSE layout. The README also has a dedicated section on the software license and a Publications and Credits section.

## Sources

- [gnss-sdr/gnss-sdr on GitHub](https://github.com/gnss-sdr/gnss-sdr)
- [License: GPL-3.0](https://github.com/gnss-sdr/gnss-sdr/blob/main/LICENSE)
- [Project website](https://gnss-sdr.org)
- [README](https://github.com/gnss-sdr/gnss-sdr/blob/main/README.md)
- [Releases](https://github.com/gnss-sdr/gnss-sdr/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gnss-sdr-gnss-sdr
