GNSS-SDR is an open-source <a href="https://en.wikipedia.org/wiki/Software_GNSS_receiver" target="_blank">GNSS software receiver</a> freely available to the research community. This project provides a common framework for GNSS signal processing which can operate in a variety of computer platforms. This tool is intended to foster collaboration, increase awareness, and reduce development costs in the field of GNSS receiver design and customized use of GNSS signals.
buses to a variety of either commercially available or custom-made RF front-ends, adapting the processing algorithms to different sampling frequencies, intermediate
frequencies and sample resolutions. This makes possible rapid prototyping of specific receivers intended, for instance, to geodetic applications,
observation of the ionospheric impact on navigation signals, GNSS reflectometry, signal quality monitoring, or carrier-phase based navigation techniques.
\li Any suitable RF configuration that can be driven by the Universal Software Radio Peripheral Hardware Driver (<a href="https://files.ettus.com/uhd_docs/manual/html/" target="_blank">UHD</a>).
This includes all current and future <a href="https://www.ettus.com/">Ettus Research</a> products. The USRP1 + DBSRX 2.2 daughterboard is an example of working configuration for GPS L1 C/A and Galileo E1B and E1C signals.
\li Experimentally, with some <a href="https://gnss-sdr.org/docs/tutorials/gnss-sdr-operation-realtek-rtl2832u-usb-dongle-dvb-t-receiver/" target="_blank">USB DVB-T dongles based on the Realtek RTL2832U chipset</a>.
In principle, GNSS-SDR can be built in any Unix-like system. In practice, it depends on being able to install all the required dependencies. See the <a href="https://gnss-sdr.org/build-and-install/" target="_blank">building guide</a> page for details about the project's
dependencies and build process. Mainly, it consists on installing <a href="https://www.gnuradio.org/" target="_blank">GNU Radio</a> plus some few more libraries:
\li <a href="https://github.com/google/googletest" target="_blank">Googletest</a>, Google's framework for writing C++ tests,
\li <a href="https://www.makotemplates.org/" target="_blank">Mako</a>, a template library written in Python,
\li <a href="https://github.com/tbeu/matio" target="_blank">Matio</a>, a MATLAB MAT File I/O Library,
\li <a href="https://developers.google.com/protocol-buffers" target="_blank">Protocol Buffers</a>, a language-neutral, platform-neutral extensible mechanism for serializing structured data,
\li <a href="https://pugixml.org/" target="_blank">PugiXML</a>, a light-weight, simple and fast XML parser for C++ with XPath support,
\li <a href="https://www.libvolk.org" target="_blank">Volk</a>, a Vector-Optimized Library of Kernels which provides an abstraction of optimized math routines targeting several SIMD processors,
If everything goes well, three new executables will be created at <tt>gnss-sdr/install</tt>, namely <tt>gnss-sdr</tt>, <tt>volk_gnsssdr_profile</tt> and <tt>run_tests</tt>.
You can run them from that folder, but if you prefer to install gnss-sdr on your system and have it available anywhere else, do:
from the <tt>gnss-sdr/build</tt> folder. In both cases, <a href="https://www.doxygen.nl/" target="_blank">Doxygen</a> will generate HTML documentation that can be
will create a PDF manual at <tt>gnss-sdr/docs/GNSS-SDR_manual.pdf</tt>. Please note that the PDF generation requires some fonts to be installed on the host system.
\subsection debug_and_release Debug and Release builds
By default, CMake will build the Release version, meaning that the compiler will generate a faster, optimized executable. This is the recommended build type when using
a RF front-end and you need to attain real time. If working with a file (and thus without real-time constraints), you may want to obtain more information about
the internals of the receiver, as well as more fine-grained logging. This can be done by building the Debug version, by doing:
If you checked out GNSS-SDR some days ago, it is possible that some developer had updated files at the Git repository. You can update your local copy by doing:
With GNSS-SDR, you can define you own receiver, work with captured raw data or from a RF front-end, dump into files intermediate signals, or tune every single algorithm used in the \ref signal_processing. All the configuration
is done in a single file. Those configuration files reside at the <tt>gnss-sdr/conf</tt> folder. By default, the executable <tt>gnss-sdr</tt> will read the configuration
available at <tt>gnss-sdr/conf/gnss-sdr.conf</tt>. You can edit that file to fit your needs, or even better, define a new <tt>my_receiver.conf</tt> file with your own configuration.
You can see a guide of available implementations at <a href="https://gnss-sdr.org/docs/" target="_blank">the online documentation</a>. That folder contains other working examples as well. If you have a working
configuration and want to share it will others, please email it to the <a href="https://lists.sourceforge.net/lists/listinfo/gnss-sdr-developers" target="_blank"><b>GNSS-SDR developers mailing list</b></a>
GNSS-SDR's main method initializes the logging library, processes the command line flags, if any, provided by the user and instantiates a ControlThread object.
Its constructor reads the configuration file, creates a control queue and creates a flowgraph according to the configuration. Then, the program's main method
calls the run() method of the instantiated object, an action that connects the flowgraph and starts running it. After that, and until a stop message is received,
it reads control messages sent by the receiver's modules through a safe-thread queue and processes them. Finally, when a stop message is received, the main
The GNSSFlowgraph class is responsible for preparing the graph of blocks according to the configuration, running it, modifying it during run-time and stopping it.
Blocks are identified by its role. This class knows which roles it has to instantiate and how to connect them.
It relies on the configuration to get the correct instances of the roles it needs and then it applies the connections between GNU Radio blocks to make the
graph ready to be started. The complexity related to managing the blocks and the data stream is handled by GNU Radio's <tt>gr::top_block</tt> class. GNSSFlowgraph wraps
the <tt>gr::top_block</tt> instance so we can take advantage of the \ref gnss_block_factory, the configuration system and the processing blocks. This class is also responsible
for applying changes to the configuration of the flowgraph during run-time, dynamically reconfiguring channels: it selects the strategy for selecting satellites.
This can range from a sequential search over all the satellites' ID to smarter approaches that determine what are the satellites most likely in-view based on rough
estimations of the receiver position in order to avoid searching satellites in the other side of the Earth.
The Control Plane is in charge of creating a flowgraph according to the configuration and then managing the modules. Configuration allows users to define in an easy way their own
custom receiver by specifying the flowgraph (type of signal source, number of channels, algorithms to be used for each channel and each module, strategies for
satellite selection, type of output format, etc.). Since it is difficult to foresee what future module implementations will be needed in terms of configuration,
we used a very simple approach that can be extended without a major impact in the code. This can be achieved by simply mapping the names of the variables in the
Properties are passed around within the program using the ConfigurationInterface class. There are two implementations of this interface: FileConfiguration and
InMemoryConfiguration. FileConfiguration reads the properties (pairs of property name and value) from a file and stores them internally. InMemoryConfiguration does
not read from a file; it remains empty after instantiation and property values and names are set using the set property method. FileConfiguration is intended to be
used in the actual GNSS-SDR application whereas InMemoryConfiguration is intended to be used in tests to avoid file-dependency in the file system. Classes that
need to read configuration parameters will receive instances of ConfigurationInterface from where they will fetch the values. For instance, parameters related
The name of these parameters can be anything but one reserved word: implementation. This parameter indicates in its value the name of the class that has to be instantiated
by the factory for that role. For instance, if our signal source is providing data already at baseband and thus we want to use the implementation Pass_Through for module SignalConditioner, the corresponding line in the
Since the configuration is just a set of property names and values without any meaning or syntax, the system is very versatile and easily extendable. Adding new
properties to the system only implies modifications in the classes that will make use of these properties. In addition, the configuration files are not checked
against any strict syntax so it is always in a correct status (as long as it contains pairs of property names and values in <a href="https://en.wikipedia.org/wiki/INI_file" target="_blank">INI format</a>).
Hence, the application defines a simple accessor class to fetch the configuration pairs of values and passes them to a factory class called GNSSBlockFactory.
This factory decides, according to the configuration, which class needs to be instantiated and which parameters should be passed to the constructor. Hence, the factory
encapsulates the complexity of blocks' instantiation. With that approach, adding a new block that requires new parameters will be as simple as adding the block
class and modifying the factory to be able to instantiate it. This loose coupling between the blocks' implementations and the syntax of the configuration
enables extending the application capacities in a high degree. It also allows to produce fully customized receivers, for instance a testbed for acquisition
GNU Radio's class <tt>gr::basic_block</tt> is the abstract base class for all signal processing blocks, a bare abstraction of an entity that has a name and a set of
inputs and outputs. It is never instantiated directly; rather, this is the abstract parent class of both <tt>gr::hier_block2</tt>, which is a recursive container that
adds or removes processing or hierarchical blocks to the internal graph, and <tt>gr::block</tt>, which is the abstract base class for all the processing blocks.
A signal processing flow is constructed by creating a tree of hierarchical blocks, which at any level may also contain terminal nodes that actually implement signal
Class <tt>gr::top_block</tt> is the top-level hierarchical block representing a flowgraph. It defines GNU Radio runtime functions used during the execution of the
program: run(), start(), stop(), wait(), etc. A a subclass called GNSSBlockInterface is the common interface for all the GNSS-SDR modules. It defines pure virtual
Subclassing GNSSBlockInterface, we defined interfaces for the GNSS receiver blocks depicted in the figure above. This hierarchy provides the definition of different
algorithms and different implementations, which will be instantiated according to the configuration. This strategy allows
multiple implementations sharing a common interface, achieving the objective of decoupling interfaces from implementations: it defines a family of algorithms, encapsulates each one,
The Signal Source module is in charge of implementing the hardware driver, that is, the portion of the code that communicates with the RF front-end and receives
the samples coming from the ADC. This communication is usually performed through USB or Ethernet buses. Since real-time processing requires a highly optimized
implementation of the whole receiver, this module also allows to read samples from a file stored in a hard disk, and thus processing without time constraints.
Relevant parameters of those samples are the intermediate frequency (or baseband I&Q components), the sampling rate and number of bits per sample, that must be
This module also performs bit-depth adaptation, since most of the existing RF front-ends provide samples quantized with 2 or 3 bits, while operations inside
the processor are performed on 32- or 64-bit words, depending on its architecture. Although there are implementations of the most intensive computational
processes (mainly correlation) that take advantage of specific data types and architectures for the sake of
efficiency, the approach is processor-specific and hardly portable. We suggest to keep signal samples in standard data types and letting the compiler
select the best library version (implemented using SIMD or any other processor-specific technology) of the required routines for a given processor.
A channel encapsulates all signal processing devoted to a single satellite. Thus, it is a large composite object which encapsulates the \ref acquisition,
\ref tracking and \ref decoding modules. As a composite object, it can be treated as a single entity, meaning that it can be easily replicated. Since the number of
channels is selectable by the user in the configuration file, this approach helps improving the scalability and maintainability of the receiver.
the prior information available (called cold start when the receiver has no information about its position nor the satellites almanac; warm start when
a rough location and the approximate time of day are available, and the receiver has a recently recorded almanac broadcast; or hot start when the receiver
was tracking a satellite and the signal line of sight broke for a short period of time, but the ephemeris and almanac data is still valid, or this information
is provided by other means), and an acquisition process can finish deciding that the satellite is not present, that longer integration is needed in order to
confirm the presence of the satellite, or declaring the satellite present. In the latter case, acquisition process should stop and trigger the tracking module
The first task of a GNSS receiver is to detect the presence or absence of in-view satellites. This is done by the acquisition system process, which also provides a coarse estimation of two signal parameters: the frequency shift
AcquisitionInterface is the common interface for all the acquisition algorithms and their corresponding implementations. Algorithms' interface, that may vary
depending on the use of information external to the receiver, such as in Assisted GNSS, is defined in classes referred to as <i>adapters</i>.
These adapters wrap the GNU Radio blocks interface into a compatible interface expected by AcquisitionInterface. This allows the use of existing GNU Radio blocks
derived from <tt>gr::block</tt>, and ensures that newly developed implementations will also be reusable in other GNU Radio-based applications.
different numerical libraries). In such a way, implementations can be continuously improved without having any impact neither on the algorithm interface nor the general acquisition interface.
Check GpsL1CaPcpsAcquisition and GalileoE1PcpsAmbiguousAcquisition for examples of adapters from a Parallel Code Phase Search (PCPS) acquisition block, and
The user can select a given implementation for the algorithm to be used in each receiver channel, as well as their parameters, in the configuration file:
When a satellite is declared present, the parameters estimated by the acquisition module are then fed to the receiver tracking module, which represents the
second stage of the signal processing unit, aiming to perform a local search for accurate estimates of code delay and carrier phase, and following their eventual
Again, a class hierarchy consisting of a TrackingInterface class and subclasses implementing algorithms provides a way of testing different approaches,
with full access to their parameters. Check GpsL1CaDllPllTracking or GalileoE1DllPllVemlTracking for examples of adapters, and Gps_L1_Ca_Dll_Pll_Tracking_cc for an example
of a signal processing block implementation. There are also available some useful classes and functions for signal tracking; take a look at Correlator, lock_detectors.h, tracking_discriminators.h or
The user can select a given implementation for the algorithm to be used in all the tracking blocks, as well as its parameters, in the configuration file:
Most of GNSS signal links are modulated by a navigation message containing the time the message was transmitted, orbital parameters of satellites
(also known as ephemeris) and an almanac (information about the general system health, rough orbits of all satellites in the network as well as data related to
error correction). Navigation data bits are structured in words, pages, subframes, frames and superframes. Sometimes, bits corresponding to a single parameter are
spread over different words, and values extracted from different frames are required for proper decoding. Some words are for synchronization purposes, others for
error control an others contain actual information. There are also error control mechanisms, from parity checks to forward error correction (FEC) encoding and
The common interface is TelemetryDecoderInterface. Check GpsL1CaTelemetryDecoder for an example of the GPS L1 NAV message decoding adapter, and gps_l1_ca_telemetry_decoder_cc
GNSS systems provide different kinds of observations. The most commonly used are the code observations, also called pseudoranges. The <i>pseudo</i> comes from
the fact that on the receiver side the clock error is unknown and thus the measurement is not a pure range observation. High accuracy applications also use the
carrier phase observations, which are based on measuring the difference between the carrier phase transmitted by the GNSS satellites and the phase of the carrier
generated in the receiver. Both observables are computed from the outputs of the tracking module and the decoding of the navigation message.
\subsection pvt Computation of Position, Velocity and Time
Although data processing for obtaining high-accuracy PVT solutions is out of the scope of GNSS-SDR, we provide a module that can compute a simple least square
solution and leaves room for more sophisticated positioning methods. The integration with libraries and software tools that are able to deal with multi-constellation
data such as <a href="https://github.com/SGL-UT/GPSTk" target="_blank">GPSTk</a> or <a href="https://gage.upc.edu/gLAB/" target="_blank">gLAB</a> appears as a viable solution for high performance, completely customizable GNSS receivers.
GNSS-SDR is released under the <a href="https://www.gnu.org/licenses/gpl.html" target="_blank">General Public License (GPL) v3</a>, thus securing practical usability, inspection,
and continuous improvement by the research community, allowing the discussion based on tangible code and the analysis of results obtained with real signals.
\li Copies may be distributed free of charge or for money, but the source code has to be shipped or provided free of charge (or at cost price) on demand. The receiver of the source code has the same rights meaning he can share copies free of charge or resell.
\li The licensed material may be analyzed or modified.
\li Modified material may be distributed under the same licensing terms but <b>do not</b> have to be distributed.
\li \anchor Navitec2012 C. Fernández-Prades, J. Arribas, L. Esteve, D. Pubill, P. Closas, <a href="https://www.researchgate.net/publication/233859838_An_Open_Source_Galileo_E1_Software_Receiver/" target="_blank"><i>An Open Source Galileo E1 Software Receiver</i></a>, in Proc. of the 6th ESA Workshop on Satellite Navigation Technologies (NAVITEC 2012), ESTEC, Noordwijk, The Netherlands, Dec. 2012.
\li J. Arribas, <a href="https://theses.eurasip.org/theses/449/gnss-array-based-acquisition-theory-and/" target="_blank"><i>GNSS Array-based Acquisition: Theory and Implementation</i></a>, PhD Thesis, Universitat Politècnica de Catalunya, Barcelona, Spain, June 2012.
\li C. Fernández-Prades, J. Arribas, P. Closas, C. Avilés, and L. Esteve, <a href="https://www.researchgate.net/publication/233380791_GNSS-SDR_An_open_source_tool_for_researchers_and_developers" target="_blank"><i>GNSS-SDR: an open source tool for researchers and developers</i></a>, in Proc. of the ION GNSS 2011 Conference, Portland, Oregon, Sept. 19-23, 2011.
\li C. Fernández-Prades, C. Avilés, L. Esteve, J. Arribas, and P. Closas, <a href="https://www.researchgate.net/publication/228624103_Design_Patterns_for_GNSS_Software_Receivers" target="_blank"><i>Design patterns for GNSS software receivers</i></a>, in Proc. of the 5th ESA Workshop on Satellite Navigation Technologies (NAVITEC'2010), ESTEC, Noordwijk, The Netherlands, Dec. 2010. DOI:10.1109/NAVITEC.2010.5707981
In order to start using GNSS-SDR, you may want to populate <tt>gnss-sdr/data</tt> folder (or anywhere else on your system) with raw data files. By "raw data" we mean the output
of a Radio Frequency front-end's Analog-to_Digital converter. GNSS-SDR needs signal samples already in baseband or in passband, at a suitable intemediate frequency (on the order of MHz).
Prepare your configuration file, and then you are ready for going to the <tt> gnss-sdr/install</tt> folder, running <tt>./gnss-sdr</tt>, and see how the file is processed.
Please ask the Developer Team for a signal sample if you need one, and they will do their best ;-)
Another interesting option is working in real-time with a RF front-end. We provide drivers for UHD-compatible hardware (see \ref signal_source) and for some DVB-T USB dongles.
Start with a low number of channels and then increase it in order to test how many channels your processor can handle in real-time.
You can find more information at the <a href="https://gnss-sdr.org/docs/" target="_blank"><b>GNSS-SDR Documentation page</b></a> or directly asking to the
You are also very welcome to contribute to the project, there are many ways to <a href="https://gnss-sdr.org/contribute/" target="_blank"><b>participate in GNSS-SDR</b></a>.
If you need some special feature not yet implemented, the Developer Team would love to be hired for developing it.
Please do not hesitate to <a href="https://gnss-sdr.org/team/" target="_blank"><b>contact them</b></a>.