mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-06-07 09:04:08 +00:00
Fix program termination when usign extended intergration times
Reorder private data members, initialize them in constructor list
This commit is contained in:
parent
561c422309
commit
26964a365a
@ -98,12 +98,14 @@ All notable changes to GNSS-SDR will be documented in this file.
|
|||||||
- Added a new output parameter `Flag_PLL_180_deg_phase_locked` in the monitor
|
- Added a new output parameter `Flag_PLL_180_deg_phase_locked` in the monitor
|
||||||
output that indicates if the PLL got locked at 180 degrees, so the symbol sign
|
output that indicates if the PLL got locked at 180 degrees, so the symbol sign
|
||||||
is reversed.
|
is reversed.
|
||||||
- Fix bug in the satellite selection algorithm for configurations with a large
|
- Fixed a bug in the satellite selection algorithm for configurations with a
|
||||||
number of channels. The maximum number of channels per signal is now limited
|
large number of channels. The maximum number of channels per signal is now
|
||||||
to the number of available satellites per system minus one. The number of
|
limited to the number of available satellites per system minus one. The number
|
||||||
channels performing concurrent acquisition, `Channels.in_acquisition`, cannot
|
of channels performing concurrent acquisition, `Channels.in_acquisition`,
|
||||||
be larger than the total number of channels. The program will stop if those
|
cannot be larger than the total number of channels. The program will stop if
|
||||||
requirements are not met in the configuration file.
|
those requirements are not met in the configuration file.
|
||||||
|
- Fixed program termination when using `File_Signal_Source` and extended
|
||||||
|
integration times.
|
||||||
|
|
||||||
See the definitions of concepts and metrics at
|
See the definitions of concepts and metrics at
|
||||||
https://gnss-sdr.org/design-forces/
|
https://gnss-sdr.org/design-forces/
|
||||||
|
@ -15,15 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "file_source_base.h"
|
#include "file_source_base.h"
|
||||||
|
#include "Beidou_B1I.h"
|
||||||
|
#include "Beidou_B3I.h"
|
||||||
|
#include "GPS_L1_CA.h"
|
||||||
|
#include "GPS_L2C.h"
|
||||||
|
#include "GPS_L5.h"
|
||||||
|
#include "Galileo_E1.h"
|
||||||
|
#include "Galileo_E5a.h"
|
||||||
|
#include "Galileo_E5b.h"
|
||||||
|
#include "Galileo_E6.h"
|
||||||
#include "configuration_interface.h"
|
#include "configuration_interface.h"
|
||||||
#include "gnss_sdr_filesystem.h"
|
#include "gnss_sdr_filesystem.h"
|
||||||
#include "gnss_sdr_flags.h"
|
#include "gnss_sdr_flags.h"
|
||||||
#include "gnss_sdr_string_literals.h"
|
#include "gnss_sdr_string_literals.h"
|
||||||
#include "gnss_sdr_valve.h"
|
#include "gnss_sdr_valve.h"
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <cmath> // ceil, floor
|
#include <algorithm> // for std::max
|
||||||
#include <fstream>
|
#include <cmath> // for ceil, floor
|
||||||
#include <utility> // move
|
#include <iostream> // for std::cout, std:cerr
|
||||||
|
#include <utility> // for std::move
|
||||||
|
|
||||||
|
|
||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
@ -31,31 +41,58 @@ using namespace std::string_literals;
|
|||||||
FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl,
|
FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std::string const& role, std::string impl,
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue,
|
Concurrent_Queue<pmt::pmt_t>* queue,
|
||||||
std::string default_item_type)
|
std::string default_item_type)
|
||||||
: SignalSourceBase(configuration, role, std::move(impl)), filename_(configuration->property(role + ".filename"s, "../data/example_capture.dat"s)),
|
: SignalSourceBase(configuration, role, std::move(impl)),
|
||||||
|
|
||||||
file_source_(), // NOLINT
|
|
||||||
|
|
||||||
item_type_(configuration->property(role + ".item_type"s, default_item_type)), // NOLINT
|
|
||||||
item_size_(0),
|
|
||||||
is_complex_(false),
|
|
||||||
|
|
||||||
// apparently, MacOS (LLVM) finds 0UL ambiguous with bool, int64_t, uint64_t, int32_t, int16_t, uint16_t,... float, double
|
|
||||||
header_size_(configuration->property(role + ".header_size"s, uint64_t(0))),
|
|
||||||
seconds_to_skip_(configuration->property(role + ".seconds_to_skip"s, 0.0)),
|
|
||||||
repeat_(configuration->property(role + ".repeat"s, false)),
|
|
||||||
|
|
||||||
samples_(configuration->property(role + ".samples"s, uint64_t(0))),
|
|
||||||
sampling_frequency_(configuration->property(role + ".sampling_frequency"s, int64_t(0))),
|
|
||||||
valve_(), // NOLINT
|
|
||||||
queue_(queue),
|
queue_(queue),
|
||||||
|
role_(role),
|
||||||
enable_throttle_control_(configuration->property(role + ".enable_throttle_control"s, false)),
|
filename_(configuration->property(role_ + ".filename"s, "../data/example_capture.dat"s)),
|
||||||
throttle_(), // NOLINT
|
dump_filename_(configuration->property(role_ + ".dump_filename"s, "../data/my_capture.dat"s)),
|
||||||
|
item_type_(configuration->property(role_ + ".item_type"s, std::move(default_item_type))),
|
||||||
dump_(configuration->property(role + ".dump"s, false)),
|
item_size_(0),
|
||||||
dump_filename_(configuration->property(role + ".dump_filename"s, "../data/my_capture.dat"s)),
|
header_size_(configuration->property(role_ + ".header_size"s, uint64_t(0))),
|
||||||
sink_() // NOLINT
|
samples_(configuration->property(role_ + ".samples"s, uint64_t(0))),
|
||||||
|
sampling_frequency_(configuration->property(role_ + ".sampling_frequency"s, int64_t(0))),
|
||||||
|
minimum_tail_s_(0.1),
|
||||||
|
seconds_to_skip_(configuration->property(role_ + ".seconds_to_skip"s, 0.0)),
|
||||||
|
is_complex_(false),
|
||||||
|
repeat_(configuration->property(role_ + ".repeat"s, false)),
|
||||||
|
enable_throttle_control_(configuration->property(role_ + ".enable_throttle_control"s, false)),
|
||||||
|
dump_(configuration->property(role_ + ".dump"s, false))
|
||||||
{
|
{
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_1C.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_2S.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_L5.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_1B.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_5X.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_7X.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_E6.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_B1.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_B3.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_1G.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Acquisition_2G.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_1C.extend_correlation_symbols", 0.0) * GPS_L1_CA_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_2S.extend_correlation_symbols", 0.0) * GPS_L2_M_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_L5.extend_correlation_symbols", 0.0) * GPS_L5I_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_1B.extend_correlation_symbols", 0.0) * GALILEO_E1_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_5X.extend_correlation_symbols", 0.0) * GALILEO_E5A_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_7X.extend_correlation_symbols", 0.0) * GALILEO_E5B_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_E6.extend_correlation_symbols", 0.0) * GALILEO_E6_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_B1.extend_correlation_symbols", 0.0) * BEIDOU_B1I_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_B3.extend_correlation_symbols", 0.0) * BEIDOU_B3I_CODE_PERIOD_S * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_1G.extend_correlation_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
minimum_tail_s_ = std::max(configuration->property("Tracking_2G.extend_correlation_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
|
|
||||||
|
if (repeat())
|
||||||
|
{
|
||||||
|
minimum_tail_s_ = 0.0;
|
||||||
|
if (seconds_to_skip_ != 0.0)
|
||||||
|
{
|
||||||
|
seconds_to_skip_ = 0.0;
|
||||||
|
std::cout << "Warning: since " << role_ << ".repeat is set to true, "
|
||||||
|
<< role_ << ".seconds_to_skip parameter will be ignored.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// override value with commandline flag, if present
|
// override value with commandline flag, if present
|
||||||
if (FLAGS_signal_source != "-")
|
if (FLAGS_signal_source != "-")
|
||||||
{
|
{
|
||||||
@ -67,9 +104,9 @@ FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std:
|
|||||||
}
|
}
|
||||||
if (sampling_frequency_ == 0)
|
if (sampling_frequency_ == 0)
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: parameter " << role << ".sampling_frequency is not set, this could lead to wrong results.\n"
|
std::cerr << "Warning: parameter " << role_ << ".sampling_frequency is not set, this could lead to wrong results.\n"
|
||||||
<< " Please set the " << role << ".sampling_frequency parameter in your configuration file.\n"
|
<< " Please set the " << role_ << ".sampling_frequency parameter in your configuration file.\n"
|
||||||
<< " If not set, " << role << ".sampling_frequency=" << configuration->property("GNSS-SDR.internal_fs_sps"s, int64_t(0))
|
<< " If not set, " << role_ << ".sampling_frequency=" << configuration->property("GNSS-SDR.internal_fs_sps"s, int64_t(0))
|
||||||
<< " will be assumed.\n";
|
<< " will be assumed.\n";
|
||||||
sampling_frequency_ = configuration->property("GNSS-SDR.internal_fs_sps"s, int64_t(0));
|
sampling_frequency_ = configuration->property("GNSS-SDR.internal_fs_sps"s, int64_t(0));
|
||||||
}
|
}
|
||||||
@ -348,39 +385,62 @@ size_t FileSourceBase::computeSamplesInFile() const
|
|||||||
{
|
{
|
||||||
auto n_samples = static_cast<size_t>(samples());
|
auto n_samples = static_cast<size_t>(samples());
|
||||||
|
|
||||||
|
// this could throw, but the existence of the file has been proven before we get here.
|
||||||
|
const auto size = fs::file_size(filename());
|
||||||
|
|
||||||
|
const auto to_skip = samplesToSkip();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* BUG workaround: The GNU Radio 3.7 file source does not stop the receiver after reaching the End of File.
|
||||||
|
* A possible solution is to compute the file length in samples using file size, excluding at least
|
||||||
|
* the last 2 milliseconds, and enable always the valve block
|
||||||
|
*/
|
||||||
|
const auto tail = static_cast<size_t>(std::ceil(minimum_tail_s_ * sampling_frequency()));
|
||||||
|
|
||||||
|
if (tail > size)
|
||||||
|
{
|
||||||
|
std::cout << "Warning: file " << filename() << " has " << size << " samples (it is too short).\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (to_skip + tail > size)
|
||||||
|
{
|
||||||
|
std::cout << "Warning: " << role_ << ".seconds_to_skip is larger than file duration.\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// if configured with 0 samples (read the whole file), figure out how many samples are in the file, and go from there
|
// if configured with 0 samples (read the whole file), figure out how many samples are in the file, and go from there
|
||||||
if (n_samples == 0)
|
if (n_samples == 0)
|
||||||
{
|
{
|
||||||
// this could throw, but the existence of the file has been proven before we get here.
|
|
||||||
auto size = fs::file_size(filename());
|
|
||||||
|
|
||||||
// if there is some kind of compression/encoding, figure out the uncompressed number of samples
|
// if there is some kind of compression/encoding, figure out the uncompressed number of samples
|
||||||
n_samples = std::floor(packetsPerSample() * size / item_size());
|
n_samples = std::floor(packetsPerSample() * size / item_size());
|
||||||
|
|
||||||
auto to_skip = samplesToSkip();
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* BUG workaround: The GNU Radio file source does not stop the receiver after reaching the End of File.
|
|
||||||
* A possible solution is to compute the file length in samples using file size, excluding at least
|
|
||||||
* the last 2 milliseconds, and enable always the valve block
|
|
||||||
*/
|
|
||||||
auto tail = static_cast<size_t>(std::ceil(0.002 * sampling_frequency()));
|
|
||||||
|
|
||||||
DLOG(INFO) << "Total samples in the file= " << n_samples;
|
DLOG(INFO) << "Total samples in the file= " << n_samples;
|
||||||
std::cout << "Processing file " << filename() << ", which contains " << n_samples << " samples (" << size << " bytes)\n";
|
std::cout << "Processing file " << filename() << ", which contains " << n_samples << " samples (" << size << " bytes)\n";
|
||||||
|
|
||||||
if (n_samples > (to_skip + tail))
|
if (n_samples > (to_skip + tail))
|
||||||
{
|
{
|
||||||
// process all the samples available in the file excluding up to the last 2 ms
|
// process all the samples available in the file excluding the hearder and the tail
|
||||||
n_samples -= to_skip + tail;
|
n_samples -= to_skip + tail;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// this will terminate the program
|
std::cout << "Warning: Skipping " << to_skip << " samples from the front and truncating " << tail << " samples\n"
|
||||||
LOG(FATAL) << "Skipping " << to_skip << " samples from the front and truncating 2ms (" << tail << " samples)\n"
|
<< "is greater than the number of samples in the file (" << size << ")\n";
|
||||||
<< "is greater than the number of samples in the file (" << n_samples << ")";
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (n_samples > size - to_skip - tail)
|
||||||
|
{
|
||||||
|
std::cout << "Warning: file " << filename() << " has " << size - to_skip
|
||||||
|
<< " samples, but " << role_ << ".samples has been set to " << n_samples << ".\n"
|
||||||
|
<< " Setting " << role_ << ".samples to " << size - to_skip - tail
|
||||||
|
<< " (" << to_skip << " samples skipped at header and " << tail << " samples skipped at the tail).\n";
|
||||||
|
n_samples = size - to_skip - tail;
|
||||||
|
}
|
||||||
|
std::cout << "Processing " << n_samples << " samples from file " << filename() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
return n_samples;
|
return n_samples;
|
||||||
}
|
}
|
||||||
@ -421,7 +481,7 @@ gr::blocks::file_source::sptr FileSourceBase::create_file_source()
|
|||||||
if (samples_to_skip > 0)
|
if (samples_to_skip > 0)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file";
|
LOG(INFO) << "Skipping " << samples_to_skip << " samples of the input file";
|
||||||
if (not file_source_->seek(samples_to_skip, SEEK_SET))
|
if (!file_source_->seek(samples_to_skip, SEEK_SET))
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "Error skipping bytes!";
|
LOG(ERROR) << "Error skipping bytes!";
|
||||||
}
|
}
|
||||||
@ -435,7 +495,7 @@ gr::blocks::file_source::sptr FileSourceBase::create_file_source()
|
|||||||
<< "[" << filename() << "]\n"
|
<< "[" << filename() << "]\n"
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< "Please modify your configuration file\n"
|
<< "Please modify your configuration file\n"
|
||||||
<< "and point SignalSource.filename to a valid raw data file. Then:\n"
|
<< "and point " << role_ << ".filename to a valid raw data file. Then:\n"
|
||||||
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
<< "$ gnss-sdr --config_file=/path/to/my_GNSS_SDR_configuration.conf\n"
|
||||||
<< "Examples of configuration files available at:\n"
|
<< "Examples of configuration files available at:\n"
|
||||||
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n"
|
<< GNSSSDR_INSTALL_DIR "/share/gnss-sdr/conf/\n"
|
||||||
|
@ -152,16 +152,9 @@ protected:
|
|||||||
virtual void post_disconnect_hook(gr::top_block_sptr top_block);
|
virtual void post_disconnect_hook(gr::top_block_sptr top_block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string filename_;
|
|
||||||
gr::blocks::file_source::sptr file_source_;
|
gr::blocks::file_source::sptr file_source_;
|
||||||
|
gr::blocks::throttle::sptr throttle_;
|
||||||
std::string item_type_;
|
gr::blocks::file_sink::sptr sink_;
|
||||||
size_t item_size_;
|
|
||||||
bool is_complex_; // a misnomer; if I/Q are interleaved as integer values
|
|
||||||
|
|
||||||
size_t header_size_; // length (in samples) of the header (if any)
|
|
||||||
double seconds_to_skip_;
|
|
||||||
bool repeat_;
|
|
||||||
|
|
||||||
// The valve allows only the configured number of samples through, then it closes.
|
// The valve allows only the configured number of samples through, then it closes.
|
||||||
|
|
||||||
@ -169,17 +162,23 @@ private:
|
|||||||
// class has two choices: construct the valve in the ctor, or hold onto the pointer, possibly
|
// class has two choices: construct the valve in the ctor, or hold onto the pointer, possibly
|
||||||
// beyond its lifetime. Fortunately, the queue is only used to create the valve, so the
|
// beyond its lifetime. Fortunately, the queue is only used to create the valve, so the
|
||||||
// likelihood of holding a stale pointer is mitigated
|
// likelihood of holding a stale pointer is mitigated
|
||||||
uint64_t samples_;
|
|
||||||
int64_t sampling_frequency_; // why is this signed
|
|
||||||
gnss_shared_ptr<gr::block> valve_;
|
gnss_shared_ptr<gr::block> valve_;
|
||||||
Concurrent_Queue<pmt::pmt_t>* queue_;
|
Concurrent_Queue<pmt::pmt_t>* queue_;
|
||||||
|
|
||||||
bool enable_throttle_control_;
|
std::string role_;
|
||||||
gr::blocks::throttle::sptr throttle_;
|
std::string filename_;
|
||||||
|
|
||||||
bool dump_;
|
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
gr::blocks::file_sink::sptr sink_;
|
std::string item_type_;
|
||||||
|
size_t item_size_;
|
||||||
|
size_t header_size_; // length (in samples) of the header (if any)
|
||||||
|
uint64_t samples_;
|
||||||
|
int64_t sampling_frequency_; // why is this signed
|
||||||
|
double minimum_tail_s_;
|
||||||
|
double seconds_to_skip_;
|
||||||
|
bool is_complex_; // a misnomer; if I/Q are interleaved as integer values
|
||||||
|
bool repeat_;
|
||||||
|
bool enable_throttle_control_;
|
||||||
|
bool dump_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user