Adding UDP GNSS signal source block

This commit is contained in:
Javier Arribas 2018-05-01 21:25:15 +02:00
parent 43103068fd
commit 7865387df9
8 changed files with 710 additions and 0 deletions

View File

@ -0,0 +1,86 @@
; You can define your own receiver and invoke it by doing
; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf
;
[GNSS-SDR]
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [Sps].
GNSS-SDR.internal_fs_sps=2600000
;######### SIGNAL_SOURCE CONFIG ############
SignalSource.implementation=UDP_Signal_Source
;SignalSource.implementation=File_Signal_Source
SignalSource.filename=/home/javier/gnss/gnss-simulator/build/signal_out.bin ; <- PUT YOUR FILE HERE
SignalSource.item_type=gr_complex
SignalSource.address=0.0.0.0
SignalSource.port=1234
SignalSource.payload_bytes=1024
SignalSource.sample_type=cbyte
SignalSource.RF_channels=2
SignalSource.dump=true
SignalSource.dump_filename=./signal_source.dat
;######### SIGNAL_CONDITIONER CONFIG ############
SignalConditioner0.implementation=Pass_Through
SignalConditioner1.implementation=Pass_Through
;######### CHANNELS GLOBAL CONFIG ############
Channels_1C.count=2
Channels.in_acquisition=1
;# CHANNEL CONNECTION
Channel0.RF_channel_ID=0
Channel0.signal=1C
Channel1.RF_channel_ID=1
Channel1.signal=1C
;######### ACQUISITION GLOBAL CONFIG ############
Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition
Acquisition_1C.item_type=gr_complex
Acquisition_1C.threshold=20
Acquisition_1C.use_CFAR_algorithm=false
Acquisition_1C.blocking=true
Acquisition_1C.doppler_max=10000
Acquisition_1C.doppler_step=250
Acquisition_1C.dump=false
Acquisition_1C.dump_filename=./acq_dump.dat
;######### TRACKING GLOBAL CONFIG ############
Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_Tracking
Tracking_1C.item_type=gr_complex
Tracking_1C.dump=false
Tracking_1C.dump_filename=./tracking_ch_
Tracking_1C.pll_bw_hz=35.0;
Tracking_1C.dll_bw_hz=2.0;
Tracking_1C.early_late_space_chips=0.5;
;######### TELEMETRY DECODER GPS CONFIG ############
TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder
TelemetryDecoder_1C.dump=false
;######### OBSERVABLES CONFIG ############
Observables.implementation=Hybrid_Observables
Observables.dump=false
Observables.dump_filename=./observables.dat
;######### PVT CONFIG ############
PVT.implementation=RTKLIB_PVT
PVT.positioning_mode=Single ; options: Single, Static, Kinematic, PPP_Static, PPP_Kinematic
PVT.iono_model=Broadcast ; options: OFF, Broadcast, SBAS, Iono-Free-LC, Estimate_STEC, IONEX
PVT.trop_model=Saastamoinen ; options: OFF, Saastamoinen, SBAS, Estimate_ZTD, Estimate_ZTD_Grad
PVT.output_rate_ms=100
PVT.display_rate_ms=500
PVT.dump_filename=./PVT
PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea;
PVT.flag_nmea_tty_port=false;
PVT.nmea_dump_devname=/dev/pts/4
PVT.flag_rtcm_server=false
PVT.flag_rtcm_tty_port=false
PVT.rtcm_dump_devname=/dev/pts/1
PVT.dump=false

View File

@ -166,6 +166,7 @@ set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc
spir_gss6450_file_signal_source.cc
rtl_tcp_signal_source.cc
labsat_signal_source.cc
udp_signal_source.cc
${OPT_DRIVER_SOURCES}
)

View File

@ -0,0 +1,186 @@
/*!
* \file rtl_tcp_signal_source.cc
* \brief Signal source for the Realtek RTL2832U USB dongle DVB-T receiver
* over TCP.
* (see http://sdr.osmocom.org/trac/wiki/rtl-sdr for more information)
* \author Anthony Arnold, 2015. anthony.arnold(at)uqconnect.edu.au
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "udp_signal_source.h"
#include "configuration_interface.h"
#include "GPS_L1_CA.h"
#include <boost/format.hpp>
#include <glog/logging.h>
#include <iostream>
using google::LogMessage;
UDPSignalSource::UDPSignalSource(ConfigurationInterface* configuration,
std::string role, unsigned int in_stream, unsigned int out_stream,
boost::shared_ptr<gr::msg_queue> queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(queue)
{
// DUMP PARAMETERS
std::string empty = "";
std::string default_dump_file = "./data/signal_source.dat";
std::string default_item_type = "gr_complex";
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename",
default_dump_file);
// rtl_tcp PARAMETERS
std::string default_address = "127.0.0.1";
int default_port = 1234;
RF_channels_ = configuration->property(role + ".RF_channels", 2);
std::string default_sample_type = "cbyte";
std::string sample_type = configuration->property(role + ".sample_type", default_sample_type);
item_type_ = configuration->property(role + ".item_type", default_item_type);
address_ = configuration->property(role + ".address", default_address);
port_ = configuration->property(role + ".port", default_port);
int payload_bytes = configuration->property(role + ".payload_bytes", 1024);
if (sample_type.compare("cbyte")==0)
{
std::cout<<"address_ "<<address_<<" port_ "<<port_<<" payload_bytes"<<payload_bytes<<std::endl;
udp_gnss_rx_source_ = make_udp_gnss_rx_source(sizeof(char), address_, port_, payload_bytes, true);
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
}else{
std::cout<<"WARNING: Requested UDP sample type unsuported, setting sample type to cbyte\n";
udp_gnss_rx_source_ = make_udp_gnss_rx_source(sizeof(char), address_, port_, payload_bytes, true);
demux_=gr::blocks::deinterleave::make(sizeof(char),1);
}
//create I, Q -> gr_complex type conversion blocks
for (int n = 0; n < (RF_channels_ * 2); n++)
{
char_to_float.push_back(gr::blocks::char_to_float::make());
}
for (int n = 0; n < RF_channels_; n++)
{
float_to_complex_.push_back(gr::blocks::float_to_complex::make());
}
item_size_ = sizeof(gr_complex);
if (dump_)
{
file_sink_dbg_=gr::blocks::file_sink::make(sizeof(char), "debug.dat");
for (int n = 0; n < RF_channels_; n++)
{
DLOG(INFO) << "Dumping output into file " << (dump_filename_+"ch"+std::to_string(n));
file_sink_.push_back(gr::blocks::file_sink::make(item_size_, (dump_filename_+"ch"+std::to_string(n)).c_str()));
}
}
}
UDPSignalSource::~UDPSignalSource()
{
}
void UDPSignalSource::connect(gr::top_block_sptr top_block)
{
top_block->connect(udp_gnss_rx_source_,0, demux_,0);
DLOG(INFO)<<"connected udp_source to demux"<<std::endl;
for (int n = 0; n < (RF_channels_ * 2); n++)
{
top_block->connect(demux_, n, char_to_float.at(n), 0);
DLOG(INFO) << "connected demux to char_to_float CH" << n;
}
for (int n = 0; n < RF_channels_; n++)
{
top_block->connect(char_to_float.at(n * 2), 0, float_to_complex_.at(n), 0);
top_block->connect(char_to_float.at(n * 2 + 1), 0, float_to_complex_.at(n), 1);
DLOG(INFO) << "connected char_to_float to float_to_complex_ CH" << n;
}
if (dump_)
{
top_block->connect(udp_gnss_rx_source_,0, file_sink_dbg_,0);
for (int n = 0; n < RF_channels_; n++)
{
top_block->connect(float_to_complex_.at(n), 0, file_sink_.at(n), 0);
DLOG(INFO) << "connected source to file sink";
}
}
}
void UDPSignalSource::disconnect(gr::top_block_sptr top_block)
{
for (int n = 0; n < (RF_channels_ * 2); n++)
{
top_block->disconnect(demux_, n, char_to_float.at(n), 0);
DLOG(INFO) << "disconnect demux to char_to_float CH" << n;
}
for (int n = 0; n < RF_channels_; n++)
{
top_block->disconnect(char_to_float.at(n * 2), 0, float_to_complex_.at(n), 0);
top_block->disconnect(char_to_float.at(n * 2 + 1), 0, float_to_complex_.at(n), 1);
DLOG(INFO) << "disconnect char_to_float to float_to_complex_ CH" << n;
}
if (dump_)
{
top_block->disconnect(udp_gnss_rx_source_,0, file_sink_dbg_,0);
for (int n = 0; n < RF_channels_; n++)
{
top_block->disconnect(float_to_complex_.at(n), 0, file_sink_.at(n), 0);
DLOG(INFO) << "disconnected source to file sink";
}
}
top_block->disconnect(udp_gnss_rx_source_,0, demux_,0);
DLOG(INFO)<<"disconnected udp_source to demux"<<std::endl;
}
gr::basic_block_sptr UDPSignalSource::get_left_block()
{
LOG(WARNING) << "Left block of a signal source should not be retrieved";
return gr::block_sptr();
}
gr::basic_block_sptr UDPSignalSource::get_right_block()
{
return get_right_block(0);
}
gr::basic_block_sptr UDPSignalSource::get_right_block(int RF_channel)
{
return float_to_complex_.at(RF_channel);
}

View File

@ -0,0 +1,114 @@
/*!
* \file rtl_tcp_signal_source.h
* \brief Signal source which reads from rtl_tcp.
* (see http://sdr.osmocom.org/trac/wiki/rtl-sdr for more information)
* \author Anthony Arnold, 2015. anthony.arnold(at)uqconnect.edu.au
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_UDP_SIGNAL_SOURCE_H
#define GNSS_SDR_UDP_SIGNAL_SOURCE_H
#include "gnss_block_interface.h"
#include "udp_gnss_rx_source.h"
#include <boost/shared_ptr.hpp>
#include <gnuradio/msg_queue.h>
#include <gnuradio/blocks/char_to_float.h>
//#include <gnuradio/blocks/udp_source.h>
#include <gnuradio/blocks/file_sink.h>
#include <gnuradio/blocks/deinterleave.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <stdexcept>
#include <string>
#include <vector>
class ConfigurationInterface;
/*!
* \brief This class reads from UDP packets, which streams interleaved
* I/Q samples over a network.
*/
class UDPSignalSource : public GNSSBlockInterface
{
public:
UDPSignalSource(ConfigurationInterface* configuration,
std::string role, unsigned int in_stream,
unsigned int out_stream, boost::shared_ptr<gr::msg_queue> queue);
virtual ~UDPSignalSource();
inline std::string role() override
{
return role_;
}
/*!
* \brief Returns "UDP_Signal_Source"
*/
inline std::string implementation() override
{
return "UDP_Signal_Source";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
gr::basic_block_sptr get_right_block(int RF_channel) override;
private:
std::string role_;
// UDP settings
std::string address_;
int port_;
int RF_channels_;
unsigned int in_stream_;
unsigned int out_stream_;
std::string item_type_;
size_t item_size_;
bool dump_;
std::string dump_filename_;
std::vector<boost::shared_ptr<gr::block>> char_to_float;
std::vector<boost::shared_ptr<gr::block>> float_to_complex_;
udp_gnss_rx_source_sptr udp_gnss_rx_source_;
gr::blocks::deinterleave::sptr demux_;
gr::blocks::file_sink::sptr file_sink_dbg_;
std::vector<boost::shared_ptr<gr::block>> file_sink_;
boost::shared_ptr<gr::msg_queue> queue_;
};
#endif /*GNSS_SDR_UDP_SIGNAL_SOURCE_H */

View File

@ -25,6 +25,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
unpack_2bit_samples.cc
unpack_spir_gss6450_samples.cc
labsat23_source.cc
udp_gnss_rx_source.cc
)
include_directories(

View File

@ -0,0 +1,215 @@
/* -*- c++ -*- */
/*
* Copyright 2007-2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "udp_gnss_rx_source.h"
#include <gnuradio/io_signature.h>
#include <gnuradio/math.h>
#include <gnuradio/prefs.h>
#include <stdexcept>
#include <errno.h>
#include <stdio.h>
#include <string.h>
const int udp_gnss_rx_source::BUF_SIZE_PAYLOADS =
gr::prefs::singleton()->get_long("udp_blocks", "buf_size_payloads", 50);
udp_gnss_rx_source_sptr
make_udp_gnss_rx_source(size_t itemsize,
const std::string &ipaddr, int port,
int payload_size, bool eof)
{
return gnuradio::get_initial_sptr
(new udp_gnss_rx_source(itemsize, ipaddr, port,
payload_size, eof));
}
udp_gnss_rx_source::udp_gnss_rx_source(size_t itemsize,
const std::string &host, int port,
int payload_size, bool eof)
: sync_block("udp_gnss_rx_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, itemsize)),
d_itemsize(itemsize), d_payload_size(payload_size),
d_eof(eof), d_connected(false), d_residual(0), d_sent(0), d_offset(0)
{
// Give us some more room to play.
d_rxbuf = new char[4*d_payload_size];
d_residbuf = new char[BUF_SIZE_PAYLOADS*d_payload_size];
connect(host, port);
}
udp_gnss_rx_source::~udp_gnss_rx_source()
{
if(d_connected)
disconnect();
delete [] d_rxbuf;
delete [] d_residbuf;
}
void
udp_gnss_rx_source::connect(const std::string &host, int port)
{
if(d_connected)
disconnect();
d_host = host;
d_port = static_cast<unsigned short>(port);
std::string s_port;
s_port = (boost::format("%d")%d_port).str();
if(host.size() > 0) {
boost::asio::ip::udp::resolver resolver(d_io_service);
boost::asio::ip::udp::resolver::query query(d_host, s_port,
boost::asio::ip::resolver_query_base::passive);
d_endpoint = *resolver.resolve(query);
d_socket = new boost::asio::ip::udp::socket(d_io_service);
d_socket->open(d_endpoint.protocol());
boost::asio::socket_base::reuse_address roption(true);
d_socket->set_option(roption);
d_socket->bind(d_endpoint);
start_receive();
d_udp_thread = gr::thread::thread(boost::bind(&udp_gnss_rx_source::run_io_service, this));
d_connected = true;
}
}
void
udp_gnss_rx_source::disconnect()
{
gr::thread::scoped_lock lock(d_setlock);
if(!d_connected)
return;
d_io_service.reset();
d_io_service.stop();
d_udp_thread.join();
d_socket->close();
delete d_socket;
d_connected = false;
}
// Return port number of d_socket
int
udp_gnss_rx_source::get_port(void)
{
//return d_endpoint.port();
return d_socket->local_endpoint().port();
}
void
udp_gnss_rx_source::start_receive()
{
d_socket->async_receive_from(boost::asio::buffer((void*)d_rxbuf, d_payload_size), d_endpoint_rcvd,
boost::bind(&udp_gnss_rx_source::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void
udp_gnss_rx_source::handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if(!error) {
{
boost::lock_guard<gr::thread::mutex> lock(d_udp_mutex);
if(d_eof && (bytes_transferred == 0)) {
// If we are using EOF notification, test for it and don't
// add anything to the output.
d_residual = WORK_DONE;
d_cond_wait.notify_one();
return;
}
else {
// Make sure we never go beyond the boundary of the
// residual buffer. This will just drop the last bit of
// data in the buffer if we've run out of room.
if((int)(d_residual + bytes_transferred) >= (BUF_SIZE_PAYLOADS*d_payload_size)) {
GR_LOG_WARN(d_logger, "Too much data; dropping packet.");
}
else {
// otherwise, copy received data into local buffer for
// copying later.
memcpy(d_residbuf+d_residual, d_rxbuf, bytes_transferred);
d_residual += bytes_transferred;
}
}
d_cond_wait.notify_one();
}
}
start_receive();
}
int
udp_gnss_rx_source::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
gr::thread::scoped_lock l(d_setlock);
char *out = (char*)output_items[0];
// Use async receive_from to get data from UDP buffer and wait
// on a conditional signal before proceeding. We use this
// because the conditional wait is interruptable while a
// synchronous receive_from is not.
boost::unique_lock<boost::mutex> lock(d_udp_mutex);
//use timed_wait to avoid permanent blocking in the work function
d_cond_wait.timed_wait(lock, boost::posix_time::milliseconds(10));
if (d_residual < 0) {
return d_residual;
}
int bytes_left_in_buffer = (int)(d_residual - d_sent);
int bytes_to_send = std::min<int>(d_itemsize * noutput_items, bytes_left_in_buffer);
// Copy the received data in the residual buffer to the output stream
memcpy(out, d_residbuf+d_sent, bytes_to_send);
int nitems = bytes_to_send/d_itemsize;
// Keep track of where we are if we don't have enough output
// space to send all the data in the residbuf.
if (bytes_to_send == bytes_left_in_buffer) {
d_residual = 0;
d_sent = 0;
}
else {
d_sent += bytes_to_send;
}
return nitems;
}

View File

@ -0,0 +1,91 @@
/* -*- c++ -*- */
/*
* Copyright 2007-2010,2013 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_GR_UDP_GNSS_RX_SOURCE_IMPL_H
#define INCLUDED_GR_UDP_GNSS_RX_SOURCE_IMPL_H
#include <gnuradio/blocks/udp_source.h>
#include <boost/asio.hpp>
#include <boost/format.hpp>
#include <gnuradio/thread/thread.h>
class udp_gnss_rx_source;
typedef boost::shared_ptr<udp_gnss_rx_source> udp_gnss_rx_source_sptr;
udp_gnss_rx_source_sptr make_udp_gnss_rx_source(size_t itemsize,
const std::string &ipaddr, int port,
int payload_size, bool eof);
class udp_gnss_rx_source : public gr::blocks::udp_source
{
private:
size_t d_itemsize;
int d_payload_size; // maximum transmission unit (packet length)
bool d_eof; // look for an EOF signal
bool d_connected; // are we connected?
char *d_rxbuf; // get UDP buffer items
char *d_residbuf; // hold buffer between calls
ssize_t d_residual; // hold information about number of bytes stored in residbuf
ssize_t d_sent; // track how much of d_residbuf we've outputted
size_t d_offset; // point to residbuf location offset
static const int BUF_SIZE_PAYLOADS; //!< The d_residbuf size in multiples of d_payload_size
std::string d_host;
unsigned short d_port;
boost::asio::ip::udp::socket *d_socket;
boost::asio::ip::udp::endpoint d_endpoint;
boost::asio::ip::udp::endpoint d_endpoint_rcvd;
boost::asio::io_service d_io_service;
gr::thread::condition_variable d_cond_wait;
gr::thread::mutex d_udp_mutex;
gr::thread::thread d_udp_thread;
void start_receive();
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred);
void run_io_service() { d_io_service.run(); }
public:
udp_gnss_rx_source(size_t itemsize,
const std::string &host, int port,
int payload_size, bool eof);
~udp_gnss_rx_source();
void connect(const std::string &host, int port);
void disconnect();
int payload_size() { return d_payload_size; }
int get_port();
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /* INCLUDED_GR_UDP_GNSS_RX_SOURCE_H */

View File

@ -45,6 +45,7 @@
#include "spir_file_signal_source.h"
#include "spir_gss6450_file_signal_source.h"
#include "rtl_tcp_signal_source.h"
#include "udp_signal_source.h"
#include "two_bit_packed_file_signal_source.h"
#include "labsat_signal_source.h"
#include "channel.h"
@ -1029,6 +1030,21 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
block = std::move(block_);
}
catch (const std::exception &e)
{
std::cout << "GNSS-SDR program ended." << std::endl;
exit(1);
}
}
else if (implementation.compare("UDP_Signal_Source") == 0)
{
try
{
std::unique_ptr<GNSSBlockInterface> block_(new UDPSignalSource(configuration.get(), role, in_streams,
out_streams, queue));
block = std::move(block_);
}
catch (const std::exception &e)
{
std::cout << "GNSS-SDR program ended." << std::endl;