mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-09-09 22:36:02 +00:00
feat: add extra data source
This commit is contained in:

committed by
Carles Fernandez

parent
ba2ca73959
commit
53006b4ea6
@@ -1993,7 +1993,7 @@ int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_item
|
|||||||
{
|
{
|
||||||
std::vector<gr::tag_t> tags_vec;
|
std::vector<gr::tag_t> tags_vec;
|
||||||
// time tag from obs to pvt is always propagated in channel 0
|
// time tag from obs to pvt is always propagated in channel 0
|
||||||
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + noutput_items);
|
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + noutput_items, pmt::mp("timetag"));
|
||||||
for (const auto& it : tags_vec)
|
for (const auto& it : tags_vec)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -70,6 +70,7 @@ hybrid_observables_gs::hybrid_observables_gs(const Obs_Conf &conf_)
|
|||||||
d_smooth_filter_M(static_cast<double>(conf_.smoothing_factor)),
|
d_smooth_filter_M(static_cast<double>(conf_.smoothing_factor)),
|
||||||
d_T_rx_step_s(static_cast<double>(conf_.observable_interval_ms) / 1000.0),
|
d_T_rx_step_s(static_cast<double>(conf_.observable_interval_ms) / 1000.0),
|
||||||
d_last_rx_clock_round20ms_error(0.0),
|
d_last_rx_clock_round20ms_error(0.0),
|
||||||
|
d_ref_channel(0U),
|
||||||
d_T_rx_TOW_ms(0U),
|
d_T_rx_TOW_ms(0U),
|
||||||
d_T_rx_step_ms(conf_.observable_interval_ms),
|
d_T_rx_step_ms(conf_.observable_interval_ms),
|
||||||
d_T_status_report_timer_ms(0),
|
d_T_status_report_timer_ms(0),
|
||||||
@@ -225,6 +226,7 @@ void hybrid_observables_gs::msg_handler_pvt_to_observables(const pmt::pmt_t &msg
|
|||||||
{
|
{
|
||||||
case 1: // reset TOW
|
case 1: // reset TOW
|
||||||
d_T_rx_TOW_ms = 0;
|
d_T_rx_TOW_ms = 0;
|
||||||
|
d_ref_channel = 0;
|
||||||
d_last_rx_clock_round20ms_error = 0;
|
d_last_rx_clock_round20ms_error = 0;
|
||||||
d_T_rx_TOW_set = false;
|
d_T_rx_TOW_set = false;
|
||||||
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
||||||
@@ -508,17 +510,20 @@ void hybrid_observables_gs::update_TOW(const std::vector<Gnss_Synchro> &data)
|
|||||||
{
|
{
|
||||||
// int32_t TOW_ref = std::numeric_limits<uint32_t>::max();
|
// int32_t TOW_ref = std::numeric_limits<uint32_t>::max();
|
||||||
uint32_t TOW_ref = 0U;
|
uint32_t TOW_ref = 0U;
|
||||||
|
uint32_t ref_ch = 0U;
|
||||||
for (it = data.cbegin(); it != data.cend(); it++)
|
for (it = data.cbegin(); it != data.cend(); it++)
|
||||||
{
|
{
|
||||||
if (it->Flag_valid_word)
|
if (it->Flag_valid_word)
|
||||||
{
|
{
|
||||||
if (it->TOW_at_current_symbol_ms > TOW_ref)
|
if (it->TOW_at_current_symbol_ms > TOW_ref)
|
||||||
{
|
{
|
||||||
|
ref_ch = it->Channel_ID;
|
||||||
TOW_ref = it->TOW_at_current_symbol_ms;
|
TOW_ref = it->TOW_at_current_symbol_ms;
|
||||||
d_T_rx_TOW_set = true;
|
d_T_rx_TOW_set = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
d_ref_channel = ref_ch;
|
||||||
d_T_rx_TOW_ms = TOW_ref;
|
d_T_rx_TOW_ms = TOW_ref;
|
||||||
// align the receiver clock to integer multiple of d_T_rx_step_ms
|
// align the receiver clock to integer multiple of d_T_rx_step_ms
|
||||||
if (d_T_rx_TOW_ms % d_T_rx_step_ms)
|
if (d_T_rx_TOW_ms % d_T_rx_step_ms)
|
||||||
@@ -657,6 +662,22 @@ void hybrid_observables_gs::set_tag_timestamp_in_sdr_timeframe(const std::vector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hybrid_observables_gs::propagate_extra_data(const std::vector<Gnss_Synchro> &data)
|
||||||
|
{
|
||||||
|
if (d_extra_data_tags.empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
auto &tag = d_extra_data_tags.front();
|
||||||
|
add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
|
||||||
|
d_extra_data_tags.pop();
|
||||||
|
}
|
||||||
|
while (!d_extra_data_tags.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)),
|
int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)),
|
||||||
gr_vector_int &ninput_items, gr_vector_const_void_star &input_items,
|
gr_vector_int &ninput_items, gr_vector_const_void_star &input_items,
|
||||||
@@ -671,9 +692,21 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
|||||||
{
|
{
|
||||||
d_Rx_clock_buffer.push_back(in[d_nchannels_in - 1][0].Tracking_sample_counter);
|
d_Rx_clock_buffer.push_back(in[d_nchannels_in - 1][0].Tracking_sample_counter);
|
||||||
|
|
||||||
// time tags
|
|
||||||
std::vector<gr::tag_t> tags_vec;
|
std::vector<gr::tag_t> tags_vec;
|
||||||
this->get_tags_in_range(tags_vec, d_nchannels_in - 1, this->nitems_read(d_nchannels_in - 1), this->nitems_read(d_nchannels_in - 1) + 1);
|
// extra data tags
|
||||||
|
get_tags_in_range(tags_vec, d_nchannels_in - 1, this->nitems_read(d_nchannels_in - 1), this->nitems_read(d_nchannels_in - 1) + 1, pmt::mp("extra_data"));
|
||||||
|
// std::cout << "OBS (" << std::to_string(tags_vec.size()) << ")" << std::endl;
|
||||||
|
while (!d_extra_data_tags.empty())
|
||||||
|
{
|
||||||
|
d_extra_data_tags.pop();
|
||||||
|
}
|
||||||
|
for (const auto &tag : tags_vec)
|
||||||
|
{
|
||||||
|
d_extra_data_tags.emplace(tag);
|
||||||
|
}
|
||||||
|
// time tags
|
||||||
|
tags_vec.clear();
|
||||||
|
this->get_tags_in_range(tags_vec, d_nchannels_in - 1, this->nitems_read(d_nchannels_in - 1), this->nitems_read(d_nchannels_in - 1) + 1, pmt::mp("timetag"));
|
||||||
for (const auto &it : tags_vec)
|
for (const auto &it : tags_vec)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -759,6 +792,8 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
|||||||
{
|
{
|
||||||
std::vector<Gnss_Synchro> epoch_data(d_nchannels_out);
|
std::vector<Gnss_Synchro> epoch_data(d_nchannels_out);
|
||||||
int32_t n_valid = 0;
|
int32_t n_valid = 0;
|
||||||
|
std::vector<gr::tag_t> tags{};
|
||||||
|
|
||||||
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
||||||
{
|
{
|
||||||
Gnss_Synchro interpolated_gnss_synchro{};
|
Gnss_Synchro interpolated_gnss_synchro{};
|
||||||
@@ -794,6 +829,7 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
|
|||||||
{
|
{
|
||||||
compute_pranges(epoch_data);
|
compute_pranges(epoch_data);
|
||||||
set_tag_timestamp_in_sdr_timeframe(epoch_data, d_Rx_clock_buffer.front());
|
set_tag_timestamp_in_sdr_timeframe(epoch_data, d_Rx_clock_buffer.front());
|
||||||
|
propagate_extra_data(epoch_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carrier smoothing (optional)
|
// Carrier smoothing (optional)
|
||||||
|
@@ -79,6 +79,9 @@ private:
|
|||||||
void smooth_pseudoranges(std::vector<Gnss_Synchro>& data);
|
void smooth_pseudoranges(std::vector<Gnss_Synchro>& data);
|
||||||
|
|
||||||
void set_tag_timestamp_in_sdr_timeframe(const std::vector<Gnss_Synchro>& data, uint64_t rx_clock);
|
void set_tag_timestamp_in_sdr_timeframe(const std::vector<Gnss_Synchro>& data, uint64_t rx_clock);
|
||||||
|
|
||||||
|
void propagate_extra_data(const std::vector<Gnss_Synchro> &data);
|
||||||
|
|
||||||
int32_t save_matfile() const;
|
int32_t save_matfile() const;
|
||||||
|
|
||||||
Obs_Conf d_conf;
|
Obs_Conf d_conf;
|
||||||
@@ -90,6 +93,8 @@ private:
|
|||||||
std::vector<std::queue<GnssTime>> d_SourceTagTimestamps;
|
std::vector<std::queue<GnssTime>> d_SourceTagTimestamps;
|
||||||
std::queue<GnssTime> d_TimeChannelTagTimestamps;
|
std::queue<GnssTime> d_TimeChannelTagTimestamps;
|
||||||
|
|
||||||
|
std::queue<gr::tag_t> d_extra_data_tags;
|
||||||
|
|
||||||
std::vector<bool> d_channel_last_pll_lock;
|
std::vector<bool> d_channel_last_pll_lock;
|
||||||
std::vector<double> d_channel_last_pseudorange_smooth;
|
std::vector<double> d_channel_last_pseudorange_smooth;
|
||||||
std::vector<double> d_channel_last_carrier_phase_rads;
|
std::vector<double> d_channel_last_carrier_phase_rads;
|
||||||
@@ -102,6 +107,7 @@ private:
|
|||||||
double d_T_rx_step_s;
|
double d_T_rx_step_s;
|
||||||
double d_last_rx_clock_round20ms_error;
|
double d_last_rx_clock_round20ms_error;
|
||||||
|
|
||||||
|
uint32_t d_ref_channel;
|
||||||
uint32_t d_T_rx_TOW_ms;
|
uint32_t d_T_rx_TOW_ms;
|
||||||
uint32_t d_T_rx_step_ms;
|
uint32_t d_T_rx_step_ms;
|
||||||
uint32_t d_T_status_report_timer_ms;
|
uint32_t d_T_status_report_timer_ms;
|
||||||
|
@@ -60,7 +60,15 @@ FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std:
|
|||||||
is_complex_(false),
|
is_complex_(false),
|
||||||
repeat_(configuration->property(role_ + ".repeat"s, false)),
|
repeat_(configuration->property(role_ + ".repeat"s, false)),
|
||||||
enable_throttle_control_(configuration->property(role_ + ".enable_throttle_control"s, false)),
|
enable_throttle_control_(configuration->property(role_ + ".enable_throttle_control"s, false)),
|
||||||
dump_(configuration->property(role_ + ".dump"s, false))
|
dump_(configuration->property(role_ + ".dump"s, false)),
|
||||||
|
// Configuration for attaching extra data to the sample stream
|
||||||
|
attach_extra_data_(configuration->property(role_ + ".extra_data.enabled"s, false)),
|
||||||
|
ed_path_(configuration->property(role_ + ".extra_data.filename"s, "../data/extra_data.dat"s)),
|
||||||
|
ed_offset_in_file_(configuration->property(role_ + ".extra_data.file_offset"s, 0UL)),
|
||||||
|
ed_item_size_(configuration->property(role_ + ".extra_data.item_size"s, 1UL)),
|
||||||
|
ed_repeat_(configuration->property(role_ + ".extra_data.repeat"s, false)),
|
||||||
|
ed_offset_in_samples_(configuration->property(role_ + ".extra_data.sample_offset"s, 0UL)),
|
||||||
|
ed_sample_period_(configuration->property(role_ + ".extra_data.sample_period"s, 1UL))
|
||||||
{
|
{
|
||||||
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_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_2S.coherent_integration_time_ms", 0.0) * 0.001 * 2.0, minimum_tail_s_);
|
||||||
@@ -157,6 +165,7 @@ void FileSourceBase::init()
|
|||||||
create_throttle();
|
create_throttle();
|
||||||
create_valve();
|
create_valve();
|
||||||
create_sink();
|
create_sink();
|
||||||
|
create_extra_data_source();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -205,6 +214,14 @@ void FileSourceBase::connect(gr::top_block_sptr top_block)
|
|||||||
DLOG(INFO) << "connected output to file sink";
|
DLOG(INFO) << "connected output to file sink";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXTRA DATA
|
||||||
|
if (extra_data_source())
|
||||||
|
{
|
||||||
|
top_block->connect(std::move(output), 0, extra_data_source(), 0);
|
||||||
|
DLOG(INFO) << "connected output to extra data source, which now becomes the new output";
|
||||||
|
output = extra_data_source();
|
||||||
|
}
|
||||||
|
|
||||||
post_connect_hook(std::move(top_block));
|
post_connect_hook(std::move(top_block));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,13 +270,21 @@ void FileSourceBase::disconnect(gr::top_block_sptr top_block)
|
|||||||
DLOG(INFO) << "disconnected output to file sink";
|
DLOG(INFO) << "disconnected output to file sink";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXTRA DATA
|
||||||
|
if (extra_data_source())
|
||||||
|
{
|
||||||
|
// TODO - FIXME: This is NOT okay, `output` is the extra data source, not the valve/source/throttle/whatever is left of this
|
||||||
|
top_block->disconnect(std::move(output), 0, extra_data_source(), 0);
|
||||||
|
DLOG(INFO) << "disconnected output to extra data source";
|
||||||
|
output = extra_data_source();
|
||||||
|
}
|
||||||
|
|
||||||
post_disconnect_hook(std::move(top_block));
|
post_disconnect_hook(std::move(top_block));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gr::basic_block_sptr FileSourceBase::get_left_block()
|
gr::basic_block_sptr FileSourceBase::get_left_block()
|
||||||
{
|
{
|
||||||
// TODO: is this right? Shouldn't the left block be a nullptr?
|
|
||||||
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
LOG(WARNING) << "Left block of a signal source should not be retrieved";
|
||||||
return gr::blocks::file_source::sptr();
|
return gr::blocks::file_source::sptr();
|
||||||
}
|
}
|
||||||
@@ -270,6 +295,7 @@ gr::basic_block_sptr FileSourceBase::get_right_block()
|
|||||||
// clang-tidy wants braces around the if-conditions. clang-format wants to break the braces into
|
// clang-tidy wants braces around the if-conditions. clang-format wants to break the braces into
|
||||||
// multiple line blocks. It's much more readable this way
|
// multiple line blocks. It's much more readable this way
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
if (extra_data_source_) { return extra_data_source_; }
|
||||||
if (valve_) { return valve_; }
|
if (valve_) { return valve_; }
|
||||||
if (throttle_) { return throttle_; }
|
if (throttle_) { return throttle_; }
|
||||||
return source();
|
return source();
|
||||||
@@ -478,6 +504,7 @@ gnss_shared_ptr<gr::block> FileSourceBase::file_source() const { return file_sou
|
|||||||
gnss_shared_ptr<gr::block> FileSourceBase::valve() const { return valve_; }
|
gnss_shared_ptr<gr::block> FileSourceBase::valve() const { return valve_; }
|
||||||
gnss_shared_ptr<gr::block> FileSourceBase::throttle() const { return throttle_; }
|
gnss_shared_ptr<gr::block> FileSourceBase::throttle() const { return throttle_; }
|
||||||
gnss_shared_ptr<gr::block> FileSourceBase::sink() const { return sink_; }
|
gnss_shared_ptr<gr::block> FileSourceBase::sink() const { return sink_; }
|
||||||
|
ExtraDataSource::sptr FileSourceBase::extra_data_source() const { return extra_data_source_; }
|
||||||
|
|
||||||
|
|
||||||
gr::blocks::file_source::sptr FileSourceBase::create_file_source()
|
gr::blocks::file_source::sptr FileSourceBase::create_file_source()
|
||||||
@@ -574,6 +601,24 @@ gr::blocks::file_sink::sptr FileSourceBase::create_sink()
|
|||||||
return sink_;
|
return sink_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraDataSource::sptr FileSourceBase::create_extra_data_source()
|
||||||
|
{
|
||||||
|
if (attach_extra_data_)
|
||||||
|
{
|
||||||
|
extra_data_source_ = std::make_shared<ExtraDataSource>(
|
||||||
|
ed_path_,
|
||||||
|
ed_offset_in_file_,
|
||||||
|
ed_item_size_,
|
||||||
|
ed_repeat_,
|
||||||
|
ed_offset_in_samples_,
|
||||||
|
ed_sample_period_,
|
||||||
|
gr::io_signature::make(1, 1, item_size_));
|
||||||
|
DLOG(INFO) << "extra_data_source(" << extra_data_source_->unique_id() << ")";
|
||||||
|
}
|
||||||
|
return extra_data_source_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Subclass hooks to augment created objects, as required
|
// Subclass hooks to augment created objects, as required
|
||||||
void FileSourceBase::create_file_source_hook() {}
|
void FileSourceBase::create_file_source_hook() {}
|
||||||
|
@@ -28,6 +28,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "extra_data_source.h"
|
||||||
|
|
||||||
/** \addtogroup Signal_Source
|
/** \addtogroup Signal_Source
|
||||||
* \{ */
|
* \{ */
|
||||||
/** \addtogroup Signal_Source_adapters
|
/** \addtogroup Signal_Source_adapters
|
||||||
@@ -131,6 +133,7 @@ protected:
|
|||||||
gnss_shared_ptr<gr::block> valve() const;
|
gnss_shared_ptr<gr::block> valve() const;
|
||||||
gnss_shared_ptr<gr::block> throttle() const;
|
gnss_shared_ptr<gr::block> throttle() const;
|
||||||
gnss_shared_ptr<gr::block> sink() const;
|
gnss_shared_ptr<gr::block> sink() const;
|
||||||
|
ExtraDataSource::sptr extra_data_source() const;
|
||||||
|
|
||||||
// The methods create the various blocks, if enabled, and return access to them. The created
|
// The methods create the various blocks, if enabled, and return access to them. The created
|
||||||
// object is also held in this class
|
// object is also held in this class
|
||||||
@@ -138,6 +141,7 @@ protected:
|
|||||||
gr::blocks::throttle::sptr create_throttle();
|
gr::blocks::throttle::sptr create_throttle();
|
||||||
gnss_shared_ptr<gr::block> create_valve();
|
gnss_shared_ptr<gr::block> create_valve();
|
||||||
gr::blocks::file_sink::sptr create_sink();
|
gr::blocks::file_sink::sptr create_sink();
|
||||||
|
ExtraDataSource::sptr create_extra_data_source();
|
||||||
|
|
||||||
// Subclass hooks to augment created objects, as required
|
// Subclass hooks to augment created objects, as required
|
||||||
virtual void create_file_source_hook();
|
virtual void create_file_source_hook();
|
||||||
@@ -155,6 +159,7 @@ private:
|
|||||||
gr::blocks::file_source::sptr file_source_;
|
gr::blocks::file_source::sptr file_source_;
|
||||||
gr::blocks::throttle::sptr throttle_;
|
gr::blocks::throttle::sptr throttle_;
|
||||||
gr::blocks::file_sink::sptr sink_;
|
gr::blocks::file_sink::sptr sink_;
|
||||||
|
ExtraDataSource::sptr extra_data_source_;
|
||||||
|
|
||||||
// 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.
|
||||||
|
|
||||||
@@ -179,6 +184,15 @@ private:
|
|||||||
bool repeat_;
|
bool repeat_;
|
||||||
bool enable_throttle_control_;
|
bool enable_throttle_control_;
|
||||||
bool dump_;
|
bool dump_;
|
||||||
|
|
||||||
|
// Configuration for Extra Data source
|
||||||
|
bool attach_extra_data_;
|
||||||
|
std::string ed_path_;
|
||||||
|
std::size_t ed_offset_in_file_;
|
||||||
|
std::size_t ed_item_size_;
|
||||||
|
bool ed_repeat_;
|
||||||
|
std::size_t ed_offset_in_samples_;
|
||||||
|
std::size_t ed_sample_period_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
@@ -31,6 +31,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
|
|||||||
unpack_2bit_samples.cc
|
unpack_2bit_samples.cc
|
||||||
unpack_spir_gss6450_samples.cc
|
unpack_spir_gss6450_samples.cc
|
||||||
labsat23_source.cc
|
labsat23_source.cc
|
||||||
|
extra_data_source.cc
|
||||||
${OPT_DRIVER_SOURCES}
|
${OPT_DRIVER_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
|
|||||||
unpack_2bit_samples.h
|
unpack_2bit_samples.h
|
||||||
unpack_spir_gss6450_samples.h
|
unpack_spir_gss6450_samples.h
|
||||||
labsat23_source.h
|
labsat23_source.h
|
||||||
|
extra_data_source.h
|
||||||
${OPT_DRIVER_HEADERS}
|
${OPT_DRIVER_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*!
|
||||||
|
* \file extra_data_source.cc
|
||||||
|
* \brief GNURadio block that adds extra data to the sample stream.
|
||||||
|
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "extra_data_source.h"
|
||||||
|
#include <pmt/pmt.h>
|
||||||
|
|
||||||
|
|
||||||
|
ExtraDataSource::ExtraDataSource(
|
||||||
|
const std::string& path,
|
||||||
|
const std::size_t& offset_in_file,
|
||||||
|
const std::size_t& item_size,
|
||||||
|
const bool& repeat,
|
||||||
|
const std::size_t& offset_in_samples,
|
||||||
|
const std::size_t& sample_period,
|
||||||
|
const gr::io_signature::sptr& io_signature
|
||||||
|
)
|
||||||
|
: gr::sync_block("Extra Data Source",
|
||||||
|
io_signature, io_signature),
|
||||||
|
extra_data_file_(
|
||||||
|
path,
|
||||||
|
offset_in_file,
|
||||||
|
item_size,
|
||||||
|
repeat),
|
||||||
|
offset_in_samples_(offset_in_samples),
|
||||||
|
sample_period_(sample_period),
|
||||||
|
next_tagged_sample_(offset_in_samples_)
|
||||||
|
{
|
||||||
|
if (io_signature->min_streams() != 1 and io_signature->max_streams() != 1)
|
||||||
|
{
|
||||||
|
std::cout << "ERROR: This block only supports adding data to a single stream." << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> ExtraDataSource::get_next_item()
|
||||||
|
{
|
||||||
|
return extra_data_file_.read_item();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ExtraDataSource::get_offset_in_samples() const
|
||||||
|
{
|
||||||
|
return offset_in_samples_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ExtraDataSource::get_sample_period() const
|
||||||
|
{
|
||||||
|
return sample_period_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ExtraDataSource::work(int noutput_items,
|
||||||
|
gr_vector_const_void_star& input_items,
|
||||||
|
gr_vector_void_star& output_items)
|
||||||
|
{
|
||||||
|
const std::size_t ch = 0;
|
||||||
|
const int item_size = input_signature()->sizeof_stream_item(ch);
|
||||||
|
std::memcpy(output_items[ch], input_items[ch], noutput_items * item_size);
|
||||||
|
|
||||||
|
const uint64_t total_items_written = nitems_written(ch) + noutput_items;
|
||||||
|
if (total_items_written >= next_tagged_sample_)
|
||||||
|
{
|
||||||
|
for (uint64_t sample = next_tagged_sample_; sample < total_items_written; sample += sample_period_)
|
||||||
|
{
|
||||||
|
auto extra_data_item = get_next_item();
|
||||||
|
add_item_tag(ch, sample, pmt::mp("extra_data"), pmt::init_u8vector(extra_data_item.size(), extra_data_item));
|
||||||
|
next_tagged_sample_ += sample_period_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return noutput_items;
|
||||||
|
}
|
@@ -0,0 +1,72 @@
|
|||||||
|
/*!
|
||||||
|
* \file extra_data_source.h
|
||||||
|
* \brief GNURadio block that adds extra data to the sample stream.
|
||||||
|
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_EXTRA_DATA_SOURCE_H
|
||||||
|
#define GNSS_SDR_EXTRA_DATA_SOURCE_H
|
||||||
|
|
||||||
|
#include "gnss_block_interface.h"
|
||||||
|
#include "extra_data_file.h"
|
||||||
|
#include <gnuradio/sync_block.h> // for sync_block
|
||||||
|
#include <gnuradio/types.h> // for gr_vector_const_void_star
|
||||||
|
#include <cstddef> // for size_t
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_gnuradio_blocks
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
|
||||||
|
class ExtraDataSource: public gr::sync_block
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using sptr = gnss_shared_ptr<ExtraDataSource>;
|
||||||
|
|
||||||
|
ExtraDataSource(
|
||||||
|
const std::string& path,
|
||||||
|
const std::size_t& offset_in_file,
|
||||||
|
const std::size_t& item_size,
|
||||||
|
const bool& repeat,
|
||||||
|
const std::size_t& offset_in_samples,
|
||||||
|
const std::size_t& sample_period,
|
||||||
|
const gr::io_signature::sptr& io_signature);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint8_t> get_next_item();
|
||||||
|
|
||||||
|
std::size_t get_offset_in_samples() const;
|
||||||
|
|
||||||
|
std::size_t get_sample_period() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
int work(int noutput_items,
|
||||||
|
gr_vector_const_void_star& input_items,
|
||||||
|
gr_vector_void_star& output_items) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ExtraDataFile extra_data_file_;
|
||||||
|
std::size_t offset_in_samples_;
|
||||||
|
std::size_t sample_period_;
|
||||||
|
|
||||||
|
std::size_t next_tagged_sample_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif // GNSS_SDR_EXTRA_DATA_SOURCE_H
|
@@ -56,6 +56,7 @@ set(SIGNAL_SOURCE_LIB_SOURCES
|
|||||||
rtl_tcp_dongle_info.cc
|
rtl_tcp_dongle_info.cc
|
||||||
gnss_sdr_valve.cc
|
gnss_sdr_valve.cc
|
||||||
gnss_sdr_timestamp.cc
|
gnss_sdr_timestamp.cc
|
||||||
|
extra_data_file.cc
|
||||||
${OPT_SIGNAL_SOURCE_LIB_SOURCES}
|
${OPT_SIGNAL_SOURCE_LIB_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ set(SIGNAL_SOURCE_LIB_HEADERS
|
|||||||
rtl_tcp_commands.h
|
rtl_tcp_commands.h
|
||||||
rtl_tcp_dongle_info.h
|
rtl_tcp_dongle_info.h
|
||||||
gnss_sdr_valve.h
|
gnss_sdr_valve.h
|
||||||
|
extra_data_file.h
|
||||||
${OPT_SIGNAL_SOURCE_LIB_HEADERS}
|
${OPT_SIGNAL_SOURCE_LIB_HEADERS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
93
src/algorithms/signal_source/libs/extra_data_file.cc
Normal file
93
src/algorithms/signal_source/libs/extra_data_file.cc
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*!
|
||||||
|
* \file extra_data_file.cc
|
||||||
|
* \brief Provides a simple abstraction for reading contiguous binary data from a file
|
||||||
|
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "extra_data_file.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
ExtraDataFile::ExtraDataFile(
|
||||||
|
const std::string& path,
|
||||||
|
const std::size_t& offset_in_file,
|
||||||
|
const std::size_t& item_size,
|
||||||
|
const bool& repeat)
|
||||||
|
: path_(path),
|
||||||
|
file_(path_),
|
||||||
|
offset_in_file_(offset_in_file),
|
||||||
|
item_size_(item_size),
|
||||||
|
repeat_(repeat),
|
||||||
|
done_(false),
|
||||||
|
io_buffer_size_(item_size * IO_BUFFER_CAPACITY),
|
||||||
|
offset_in_io_buffer_(io_buffer_size_) // Set to end of buffer so that first look up will trigger a read.
|
||||||
|
{
|
||||||
|
file_.seekg(offset_in_file_, std::ios_base::beg);
|
||||||
|
|
||||||
|
io_buffer_.resize(io_buffer_size_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraDataFile::reset()
|
||||||
|
{
|
||||||
|
file_.seekg(offset_in_file_, std::ios_base::beg);
|
||||||
|
offset_in_io_buffer_ = io_buffer_size_;
|
||||||
|
done_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> ExtraDataFile::read_item()
|
||||||
|
{
|
||||||
|
if (offset_in_io_buffer_ >= io_buffer_size_)
|
||||||
|
{
|
||||||
|
if (done_)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
read_into_io_buffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> item_buf{};
|
||||||
|
read_into_item_buffer(item_buf);
|
||||||
|
|
||||||
|
return item_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraDataFile::read_into_io_buffer()
|
||||||
|
{
|
||||||
|
file_.read(reinterpret_cast<char*>(&io_buffer_[0]), io_buffer_size_);
|
||||||
|
const std::size_t bytes_read = file_.gcount();
|
||||||
|
|
||||||
|
if (bytes_read < io_buffer_size_)
|
||||||
|
{
|
||||||
|
if (repeat_)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
file_.read(reinterpret_cast<char*>(&io_buffer_[bytes_read]), io_buffer_size_ - bytes_read);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
io_buffer_size_ = bytes_read;
|
||||||
|
done_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset_in_io_buffer_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtraDataFile::read_into_item_buffer(std::vector<uint8_t>& item_buf)
|
||||||
|
{
|
||||||
|
item_buf.resize(item_size_);
|
||||||
|
std::memcpy(item_buf.data(), &io_buffer_[offset_in_io_buffer_], item_size_);
|
||||||
|
offset_in_io_buffer_ += item_size_;
|
||||||
|
}
|
69
src/algorithms/signal_source/libs/extra_data_file.h
Normal file
69
src/algorithms/signal_source/libs/extra_data_file.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/*!
|
||||||
|
* \file extra_data_file.h
|
||||||
|
* \brief Provides a simple abstraction for reading contiguous binary data from a file
|
||||||
|
* \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||||
|
* This file is part of GNSS-SDR.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* -----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef GNSS_SDR_EXTRA_DATA_FILE_H
|
||||||
|
#define GNSS_SDR_EXTRA_DATA_FILE_H
|
||||||
|
|
||||||
|
#include <cstddef> // for size_t
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/** \addtogroup Signal_Source
|
||||||
|
* \{ */
|
||||||
|
/** \addtogroup Signal_Source_libs
|
||||||
|
* \{ */
|
||||||
|
|
||||||
|
|
||||||
|
class ExtraDataFile
|
||||||
|
{
|
||||||
|
static constexpr std::size_t IO_BUFFER_CAPACITY = 1024;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ExtraDataFile(
|
||||||
|
const std::string& path,
|
||||||
|
const std::size_t& offset_in_file,
|
||||||
|
const std::size_t& item_size,
|
||||||
|
const bool& repeat);
|
||||||
|
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
std::vector<uint8_t> read_item();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void read_into_io_buffer();
|
||||||
|
|
||||||
|
void read_into_item_buffer(std::vector<uint8_t>& item_buf);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string path_;
|
||||||
|
std::ifstream file_;
|
||||||
|
std::size_t offset_in_file_;
|
||||||
|
std::size_t item_size_;
|
||||||
|
bool repeat_;
|
||||||
|
bool done_;
|
||||||
|
|
||||||
|
std::vector<uint8_t> io_buffer_;
|
||||||
|
std::size_t io_buffer_size_;
|
||||||
|
std::size_t offset_in_io_buffer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \} */
|
||||||
|
/** \} */
|
||||||
|
#endif // GNSS_SDR_EXTRA_DATA_FILE_H
|
@@ -645,9 +645,17 @@ int gps_l1_ca_telemetry_decoder_gs::general_work(int noutput_items __attribute__
|
|||||||
current_symbol.Flag_PLL_180_deg_phase_locked = false;
|
current_symbol.Flag_PLL_180_deg_phase_locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// time tags
|
// TODO - Merge these two loops
|
||||||
std::vector<gr::tag_t> tags_vec;
|
std::vector<gr::tag_t> tags_vec;
|
||||||
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + 1);
|
// get_tags_in_range(tags_vec, 0, this->nitems_read(0)-1, this->nitems_read(0), pmt::mp("extra_data"));
|
||||||
|
// for (const auto & tag : tags_vec)
|
||||||
|
// {
|
||||||
|
// add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
|
||||||
|
// }
|
||||||
|
// tags_vec.clear();
|
||||||
|
|
||||||
|
// time tags
|
||||||
|
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + 1, pmt::mp("timetag"));
|
||||||
for (const auto &it : tags_vec)
|
for (const auto &it : tags_vec)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -2095,6 +2095,16 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
|
|||||||
d_timetag_waiting = false;
|
d_timetag_waiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<gr::tag_t> tags{};
|
||||||
|
// get_tags_in_window(tags, 0, 0, ninput_items[0], pmt::mp("extra_data"));
|
||||||
|
get_tags_in_range(tags, 0, nitems_read(0) - d_current_prn_length_samples, nitems_read(0), pmt::mp("extra_data"));
|
||||||
|
|
||||||
|
for (const auto &tag : tags)
|
||||||
|
{
|
||||||
|
add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
|
||||||
|
// std::cout << "[ED TAG (TRK)] [" << std::to_string(tag.offset) << "] ";
|
||||||
|
// std::cout << std::endl;
|
||||||
|
}
|
||||||
*out[0] = std::move(current_synchro_data);
|
*out[0] = std::move(current_synchro_data);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -154,7 +154,15 @@ int gnss_sdr_sample_counter::work(int noutput_items __attribute__((unused)),
|
|||||||
// *************** time tags ****************
|
// *************** time tags ****************
|
||||||
std::vector<gr::tag_t> tags_vec;
|
std::vector<gr::tag_t> tags_vec;
|
||||||
// notice that nitems_read is updated in decimation blocks after leaving work() with return 1, equivalent to call consume_each
|
// notice that nitems_read is updated in decimation blocks after leaving work() with return 1, equivalent to call consume_each
|
||||||
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + samples_per_output);
|
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + samples_per_output, pmt::mp("extra_data"));
|
||||||
|
// std::cout << "SAMPLE COUNTER (" << std::to_string(tags_vec.size()) << ")" << std::endl;
|
||||||
|
for (const auto &tag : tags_vec)
|
||||||
|
{
|
||||||
|
add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
tags_vec.clear();
|
||||||
|
this->get_tags_in_range(tags_vec, 0, this->nitems_read(0), this->nitems_read(0) + samples_per_output, pmt::mp("timetag"));
|
||||||
for (const auto &it : tags_vec)
|
for (const auto &it : tags_vec)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
Reference in New Issue
Block a user