mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 01:03:04 +00:00 
			
		
		
		
	feat: refactored configuration & renamed to sensor data
This commit is contained in:
		
				
					committed by
					
						
						Carles Fernandez
					
				
			
			
				
	
			
			
			
						parent
						
							53006b4ea6
						
					
				
				
					commit
					4db7f775b5
				
			@@ -1988,34 +1988,9 @@ void rtklib_pvt_gs::update_HAS_corrections()
 | 
			
		||||
int rtklib_pvt_gs::work(int noutput_items, gr_vector_const_void_star& input_items,
 | 
			
		||||
    gr_vector_void_star& output_items __attribute__((unused)))
 | 
			
		||||
{
 | 
			
		||||
    // *************** time tags ****************
 | 
			
		||||
    if (d_enable_rx_clock_correction == false)  // todo: currently only works if clock correction is disabled
 | 
			
		||||
        {
 | 
			
		||||
            std::vector<gr::tag_t> tags_vec;
 | 
			
		||||
            // 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, pmt::mp("timetag"));
 | 
			
		||||
            for (const auto& it : tags_vec)
 | 
			
		||||
                {
 | 
			
		||||
                    try
 | 
			
		||||
                        {
 | 
			
		||||
                            if (pmt::any_ref(it.value).type().hash_code() == typeid(const std::shared_ptr<GnssTime>).hash_code())
 | 
			
		||||
                                {
 | 
			
		||||
                                    const auto timetag = wht::any_cast<const std::shared_ptr<GnssTime>>(pmt::any_ref(it.value));
 | 
			
		||||
                                    // std::cout << "PVT timetag: " << timetag->rx_time << '\n';
 | 
			
		||||
                                    d_TimeChannelTagTimestamps.push(*timetag);
 | 
			
		||||
                                }
 | 
			
		||||
                            else
 | 
			
		||||
                                {
 | 
			
		||||
                                    std::cout << "hash code not match\n";
 | 
			
		||||
                                }
 | 
			
		||||
                        }
 | 
			
		||||
                    catch (const wht::bad_any_cast& e)
 | 
			
		||||
                        {
 | 
			
		||||
                            std::cout << "msg Bad any_cast: " << e.what();
 | 
			
		||||
                        }
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    // ************ end time tags **************
 | 
			
		||||
    std::vector<gr::tag_t> sensor_tags;
 | 
			
		||||
    this->get_tags_in_range(sensor_tags, 0, this->nitems_read(0), this->nitems_read(0) + noutput_items, pmt::mp("sensor_data"));
 | 
			
		||||
    SensorDataAggregator sensor_data{sensor_tags};
 | 
			
		||||
 | 
			
		||||
    for (int32_t epoch = 0; epoch < noutput_items; epoch++)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -662,20 +662,20 @@ 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)
 | 
			
		||||
void hybrid_observables_gs::propagate_sensor_data(const std::vector<Gnss_Synchro> &data)
 | 
			
		||||
{
 | 
			
		||||
    if (d_extra_data_tags.empty())
 | 
			
		||||
    if (d_sensor_data_tags.empty())
 | 
			
		||||
        {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    do
 | 
			
		||||
        {
 | 
			
		||||
            auto &tag = d_extra_data_tags.front();
 | 
			
		||||
            auto &tag = d_sensor_data_tags.front();
 | 
			
		||||
            add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
 | 
			
		||||
            d_extra_data_tags.pop();
 | 
			
		||||
            d_sensor_data_tags.pop();
 | 
			
		||||
        }
 | 
			
		||||
    while (!d_extra_data_tags.empty());
 | 
			
		||||
    while (!d_sensor_data_tags.empty());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -693,16 +693,16 @@ 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);
 | 
			
		||||
 | 
			
		||||
            std::vector<gr::tag_t> tags_vec;
 | 
			
		||||
            // 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"));
 | 
			
		||||
            // sensor 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("sensor_data"));
 | 
			
		||||
            // std::cout << "OBS (" << std::to_string(tags_vec.size()) << ")" << std::endl;
 | 
			
		||||
            while (!d_extra_data_tags.empty())
 | 
			
		||||
            while (!d_sensor_data_tags.empty())
 | 
			
		||||
                {
 | 
			
		||||
                    d_extra_data_tags.pop();
 | 
			
		||||
                    d_sensor_data_tags.pop();
 | 
			
		||||
                }
 | 
			
		||||
            for (const auto &tag : tags_vec)
 | 
			
		||||
                {
 | 
			
		||||
                    d_extra_data_tags.emplace(tag);
 | 
			
		||||
                    d_sensor_data_tags.emplace(tag);
 | 
			
		||||
                }
 | 
			
		||||
            // time tags
 | 
			
		||||
            tags_vec.clear();
 | 
			
		||||
@@ -829,7 +829,7 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
 | 
			
		||||
                {
 | 
			
		||||
                    compute_pranges(epoch_data);
 | 
			
		||||
                    set_tag_timestamp_in_sdr_timeframe(epoch_data, d_Rx_clock_buffer.front());
 | 
			
		||||
                    propagate_extra_data(epoch_data);
 | 
			
		||||
                    propagate_sensor_data(epoch_data);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Carrier smoothing (optional)
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,7 @@ private:
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    void propagate_sensor_data(const std::vector<Gnss_Synchro> &data);
 | 
			
		||||
 | 
			
		||||
    int32_t save_matfile() const;
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +93,7 @@ private:
 | 
			
		||||
    std::vector<std::queue<GnssTime>> d_SourceTagTimestamps;
 | 
			
		||||
    std::queue<GnssTime> d_TimeChannelTagTimestamps;
 | 
			
		||||
 | 
			
		||||
    std::queue<gr::tag_t> d_extra_data_tags;
 | 
			
		||||
    std::queue<gr::tag_t> d_sensor_data_tags;
 | 
			
		||||
 | 
			
		||||
    std::vector<bool> d_channel_last_pll_lock;
 | 
			
		||||
    std::vector<double> d_channel_last_pseudorange_smooth;
 | 
			
		||||
 
 | 
			
		||||
@@ -61,14 +61,7 @@ FileSourceBase::FileSourceBase(ConfigurationInterface const* configuration, std:
 | 
			
		||||
      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)),
 | 
			
		||||
      // 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))
 | 
			
		||||
      sensor_data_source_configuration_(configuration, configuration->property(role_ + ".sensor_data.enabled"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_);
 | 
			
		||||
@@ -165,7 +158,7 @@ void FileSourceBase::init()
 | 
			
		||||
    create_throttle();
 | 
			
		||||
    create_valve();
 | 
			
		||||
    create_sink();
 | 
			
		||||
    create_extra_data_source();
 | 
			
		||||
    create_sensor_data_source();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -215,11 +208,11 @@ void FileSourceBase::connect(gr::top_block_sptr top_block)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // EXTRA DATA
 | 
			
		||||
    if (extra_data_source())
 | 
			
		||||
    if (sensor_data_source())
 | 
			
		||||
        {
 | 
			
		||||
            top_block->connect(std::move(output), 0, extra_data_source(), 0);
 | 
			
		||||
            top_block->connect(std::move(output), 0, sensor_data_source(), 0);
 | 
			
		||||
            DLOG(INFO) << "connected output to extra data source, which now becomes the new output";
 | 
			
		||||
            output = extra_data_source();
 | 
			
		||||
            output = sensor_data_source();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    post_connect_hook(std::move(top_block));
 | 
			
		||||
@@ -271,12 +264,12 @@ void FileSourceBase::disconnect(gr::top_block_sptr top_block)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // EXTRA DATA
 | 
			
		||||
    if (extra_data_source())
 | 
			
		||||
    if (sensor_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);
 | 
			
		||||
            top_block->disconnect(std::move(output), 0, sensor_data_source(), 0);
 | 
			
		||||
            DLOG(INFO) << "disconnected output to extra data source";
 | 
			
		||||
            output = extra_data_source();
 | 
			
		||||
            output = sensor_data_source();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    post_disconnect_hook(std::move(top_block));
 | 
			
		||||
@@ -295,7 +288,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
 | 
			
		||||
    // multiple line blocks. It's much more readable this way
 | 
			
		||||
    // clang-format off
 | 
			
		||||
    if (extra_data_source_) { return extra_data_source_; }
 | 
			
		||||
    if (sensor_data_source_) { return sensor_data_source_; }
 | 
			
		||||
    if (valve_) { return valve_; }
 | 
			
		||||
    if (throttle_) { return throttle_; }
 | 
			
		||||
    return source();
 | 
			
		||||
@@ -504,7 +497,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::throttle() const { return throttle_; }
 | 
			
		||||
gnss_shared_ptr<gr::block> FileSourceBase::sink() const { return sink_; }
 | 
			
		||||
ExtraDataSource::sptr FileSourceBase::extra_data_source() const { return extra_data_source_; }
 | 
			
		||||
SensorDataSource::sptr FileSourceBase::sensor_data_source() const { return sensor_data_source_; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
gr::blocks::file_source::sptr FileSourceBase::create_file_source()
 | 
			
		||||
@@ -601,25 +594,23 @@ gr::blocks::file_sink::sptr FileSourceBase::create_sink()
 | 
			
		||||
    return sink_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ExtraDataSource::sptr FileSourceBase::create_extra_data_source()
 | 
			
		||||
SensorDataSource::sptr FileSourceBase::create_sensor_data_source()
 | 
			
		||||
{
 | 
			
		||||
    if (attach_extra_data_)
 | 
			
		||||
    if (sensor_data_source_configuration_.is_enabled())
 | 
			
		||||
        {
 | 
			
		||||
            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_,
 | 
			
		||||
            if (is_complex_)
 | 
			
		||||
                {
 | 
			
		||||
                    sensor_data_source_configuration_.set_items_per_sample(2);
 | 
			
		||||
                }
 | 
			
		||||
            sensor_data_source_ = std::make_shared<SensorDataSource>(
 | 
			
		||||
                sensor_data_source_configuration_,
 | 
			
		||||
                gr::io_signature::make(1, 1, item_size_));
 | 
			
		||||
            DLOG(INFO) << "extra_data_source(" << extra_data_source_->unique_id() << ")";
 | 
			
		||||
            DLOG(INFO) << "sensor_data_source(" << sensor_data_source_->unique_id() << ")";
 | 
			
		||||
        }
 | 
			
		||||
    return extra_data_source_;
 | 
			
		||||
    return sensor_data_source_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Subclass hooks to augment created objects, as required
 | 
			
		||||
void FileSourceBase::create_file_source_hook() {}
 | 
			
		||||
void FileSourceBase::create_throttle_hook() {}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
#define GNSS_SDR_FILE_SOURCE_BASE_H
 | 
			
		||||
 | 
			
		||||
#include "concurrent_queue.h"
 | 
			
		||||
#include "sensor_data_source.h"
 | 
			
		||||
#include "signal_source_base.h"
 | 
			
		||||
#include <gnuradio/blocks/file_sink.h>  // for dump
 | 
			
		||||
#include <gnuradio/blocks/file_source.h>
 | 
			
		||||
@@ -28,7 +29,6 @@
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
 | 
			
		||||
#include "extra_data_source.h"
 | 
			
		||||
 | 
			
		||||
/** \addtogroup Signal_Source
 | 
			
		||||
 * \{ */
 | 
			
		||||
@@ -133,7 +133,7 @@ protected:
 | 
			
		||||
    gnss_shared_ptr<gr::block> valve() const;
 | 
			
		||||
    gnss_shared_ptr<gr::block> throttle() const;
 | 
			
		||||
    gnss_shared_ptr<gr::block> sink() const;
 | 
			
		||||
    ExtraDataSource::sptr extra_data_source() const;
 | 
			
		||||
    SensorDataSource::sptr sensor_data_source() const;
 | 
			
		||||
 | 
			
		||||
    // The methods create the various blocks, if enabled, and return access to them. The created
 | 
			
		||||
    // object is also held in this class
 | 
			
		||||
@@ -141,7 +141,7 @@ protected:
 | 
			
		||||
    gr::blocks::throttle::sptr create_throttle();
 | 
			
		||||
    gnss_shared_ptr<gr::block> create_valve();
 | 
			
		||||
    gr::blocks::file_sink::sptr create_sink();
 | 
			
		||||
    ExtraDataSource::sptr create_extra_data_source();
 | 
			
		||||
    SensorDataSource::sptr create_sensor_data_source();
 | 
			
		||||
 | 
			
		||||
    // Subclass hooks to augment created objects, as required
 | 
			
		||||
    virtual void create_file_source_hook();
 | 
			
		||||
@@ -159,7 +159,7 @@ private:
 | 
			
		||||
    gr::blocks::file_source::sptr file_source_;
 | 
			
		||||
    gr::blocks::throttle::sptr throttle_;
 | 
			
		||||
    gr::blocks::file_sink::sptr sink_;
 | 
			
		||||
    ExtraDataSource::sptr extra_data_source_;
 | 
			
		||||
    SensorDataSource::sptr sensor_data_source_;
 | 
			
		||||
 | 
			
		||||
    // The valve allows only the configured number of samples through, then it closes.
 | 
			
		||||
 | 
			
		||||
@@ -186,13 +186,7 @@ private:
 | 
			
		||||
    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_;
 | 
			
		||||
    SensorDataSourceConfiguration sensor_data_source_configuration_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_SOURCES
 | 
			
		||||
    unpack_2bit_samples.cc
 | 
			
		||||
    unpack_spir_gss6450_samples.cc
 | 
			
		||||
    labsat23_source.cc
 | 
			
		||||
    extra_data_source.cc
 | 
			
		||||
    sensor_data_source.cc
 | 
			
		||||
    ${OPT_DRIVER_SOURCES}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -46,7 +46,7 @@ set(SIGNAL_SOURCE_GR_BLOCKS_HEADERS
 | 
			
		||||
    unpack_2bit_samples.h
 | 
			
		||||
    unpack_spir_gss6450_samples.h
 | 
			
		||||
    labsat23_source.h
 | 
			
		||||
    extra_data_source.h
 | 
			
		||||
    sensor_data_source.h
 | 
			
		||||
    ${OPT_DRIVER_HEADERS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,82 +0,0 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,72 +0,0 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \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
 | 
			
		||||
@@ -0,0 +1,113 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_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 "sensor_data_source.h"
 | 
			
		||||
#include "sensor_data_file.h"
 | 
			
		||||
#include <pmt/pmt.h>
 | 
			
		||||
 | 
			
		||||
#if USE_GLOG_AND_GFLAGS
 | 
			
		||||
#include <glog/logging.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <absl/log/log.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace std::string_literals;
 | 
			
		||||
 | 
			
		||||
SensorDataSource::SensorDataSource(
 | 
			
		||||
    const SensorDataSourceConfiguration& configuration,
 | 
			
		||||
    const gr::io_signature::sptr& io_signature)
 | 
			
		||||
    : gr::sync_block("Sensor Data Source",
 | 
			
		||||
          io_signature, io_signature),
 | 
			
		||||
      sensor_data_files_({}),
 | 
			
		||||
      item_size_(io_signature->sizeof_stream_item(0)),
 | 
			
		||||
      items_per_sample_(configuration.get_items_per_sample())
 | 
			
		||||
{
 | 
			
		||||
    // Open needed data files
 | 
			
		||||
    for (const auto& file_pair : configuration.files())
 | 
			
		||||
        {
 | 
			
		||||
            const auto& id = file_pair.first;
 | 
			
		||||
            const auto& file = file_pair.second;
 | 
			
		||||
 | 
			
		||||
            std::size_t s_offset = file.sample_offset;
 | 
			
		||||
            std::size_t s_period = file.sample_period;
 | 
			
		||||
            if (items_per_sample_ != 1)
 | 
			
		||||
                {
 | 
			
		||||
                    s_offset *= items_per_sample_;
 | 
			
		||||
                    s_period *= items_per_sample_;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            sensor_data_files_.emplace(id, std::make_shared<SensorDataFile>(file.filename, s_offset, s_period, file.file_offset, file.chunk_size, file.repeat));
 | 
			
		||||
 | 
			
		||||
            if (not sensor_config_map_.contains(id))
 | 
			
		||||
                {
 | 
			
		||||
                    sensor_config_map_[id] = {};
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // Populate sensor map (groups sensors by file ID)
 | 
			
		||||
    for (const auto& sensor : configuration.sensors())
 | 
			
		||||
        {
 | 
			
		||||
            sensor_config_map_.at(sensor.file_id).emplace_back(sensor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // Sort lists in sensor map by byte offset within chunk
 | 
			
		||||
    for (auto& it : sensor_config_map_)
 | 
			
		||||
        {
 | 
			
		||||
            auto& sensors_in_file = it.second;
 | 
			
		||||
            std::sort(sensors_in_file.begin(), sensors_in_file.end(), [](const SensorDataConfiguration& lhs, const SensorDataConfiguration& rhs) -> bool {
 | 
			
		||||
                return lhs.offset < rhs.offset;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // Validate IO signature
 | 
			
		||||
    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";
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int SensorDataSource::work(int noutput_items,
 | 
			
		||||
    gr_vector_const_void_star& input_items,
 | 
			
		||||
    gr_vector_void_star& output_items)
 | 
			
		||||
{
 | 
			
		||||
    std::memcpy(output_items[0], input_items[0], noutput_items * item_size_);
 | 
			
		||||
 | 
			
		||||
    const uint64_t total_items_written = nitems_written(0) + noutput_items;
 | 
			
		||||
 | 
			
		||||
    std::size_t sample_stamp;
 | 
			
		||||
    std::vector<uint8_t> chunk{};
 | 
			
		||||
    pmt::pmt_t tag_key = pmt::mp("sensor_data");
 | 
			
		||||
    pmt::pmt_t chunk_count_key = pmt::mp("CHUNK_COUNT");
 | 
			
		||||
    pmt::pmt_t sample_stamp_key = pmt::mp("SAMPLE_STAMP");
 | 
			
		||||
    for (auto& file_pair : sensor_data_files_)
 | 
			
		||||
        {
 | 
			
		||||
            const auto& file_id = file_pair.first;
 | 
			
		||||
            auto& data_file = file_pair.second;
 | 
			
		||||
            while (data_file->read_until_sample(total_items_written, sample_stamp, chunk))
 | 
			
		||||
                {
 | 
			
		||||
                    pmt::pmt_t data_tag = pmt::make_dict();
 | 
			
		||||
                    data_tag = pmt::dict_add(data_tag, sample_stamp_key, pmt::from_long(sample_stamp / items_per_sample_));
 | 
			
		||||
                    data_tag = pmt::dict_add(data_tag, chunk_count_key, pmt::from_long(data_file->get_chunks_read()));
 | 
			
		||||
                    for (const auto& sensor : sensor_config_map_.at(file_id))
 | 
			
		||||
                        {
 | 
			
		||||
                            data_tag = pmt::dict_add(data_tag, sensor.tag_key, SensorDataType::make_value(sensor.type, &chunk[sensor.offset]));
 | 
			
		||||
                        }
 | 
			
		||||
                    add_item_tag(0, sample_stamp, tag_key, data_tag);
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    return noutput_items;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,108 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_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_SENSOR_DATA_SOURCE_H
 | 
			
		||||
#define GNSS_SDR_SENSOR_DATA_SOURCE_H
 | 
			
		||||
 | 
			
		||||
#include "gnss_block_interface.h"
 | 
			
		||||
#include "sensor_data_file.h"
 | 
			
		||||
#include "sensor_data_source_configuration.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 SensorDataSource : public gr::sync_block
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    using sptr = gnss_shared_ptr<SensorDataSource>;
 | 
			
		||||
 | 
			
		||||
    SensorDataSource(
 | 
			
		||||
        const SensorDataSourceConfiguration& configuration,
 | 
			
		||||
        const gr::io_signature::sptr& io_signature);
 | 
			
		||||
 | 
			
		||||
    int work(int noutput_items,
 | 
			
		||||
        gr_vector_const_void_star& input_items,
 | 
			
		||||
        gr_vector_void_star& output_items) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unordered_map<SensorDataFile::id_type, SensorDataFile::sptr> sensor_data_files_;
 | 
			
		||||
    std::unordered_map<SensorDataFile::id_type, std::vector<SensorDataConfiguration>> sensor_config_map_;
 | 
			
		||||
    std::size_t item_size_;
 | 
			
		||||
    std::size_t items_per_sample_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SensorDataAggregator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit SensorDataAggregator(std::vector<gr::tag_t> tags)
 | 
			
		||||
    {
 | 
			
		||||
        for (const auto& sensor_tag : tags)
 | 
			
		||||
            {
 | 
			
		||||
                if (sensor_tag.value->is_dict())
 | 
			
		||||
                    {
 | 
			
		||||
                        append_data(sensor_tag.value);
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto get(SensorIdentifier::value_type sensor_id) const
 | 
			
		||||
    {
 | 
			
		||||
        if (data_.contains(sensor_id))
 | 
			
		||||
            {
 | 
			
		||||
                return data_.at(sensor_id);
 | 
			
		||||
            }
 | 
			
		||||
        else
 | 
			
		||||
            {
 | 
			
		||||
                return {};
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void append_data(const pmt::pmt_t& data)
 | 
			
		||||
    {
 | 
			
		||||
        pmt::pmt_t data_list = pmt::dict_items(data);
 | 
			
		||||
        while (not pmt::is_null(data_list))
 | 
			
		||||
            {
 | 
			
		||||
                pmt::pmt_t pair = pmt::car(data_list);
 | 
			
		||||
                pmt::pmt_t key = pmt::car(pair);
 | 
			
		||||
                pmt::pmt_t val = pmt::cdr(pair);
 | 
			
		||||
 | 
			
		||||
                std::string key_str = pmt::write_string(key);
 | 
			
		||||
                SensorIdentifier::value_type sensor_id = SensorIdentifier::from_string(key_str);
 | 
			
		||||
 | 
			
		||||
                if (not data_.contains(sensor_id))
 | 
			
		||||
                    {
 | 
			
		||||
                        data_[sensor_id] = {};
 | 
			
		||||
                    }
 | 
			
		||||
                data_[sensor_id].emplace_back(val);
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::unordered_map<SensorIdentifier::value_type, std::vector<pmt::pmt_t>> data_{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
/** \} */
 | 
			
		||||
#endif  // GNSS_SDR_SENSOR_DATA_SOURCE_H
 | 
			
		||||
@@ -56,7 +56,10 @@ set(SIGNAL_SOURCE_LIB_SOURCES
 | 
			
		||||
    rtl_tcp_dongle_info.cc
 | 
			
		||||
    gnss_sdr_valve.cc
 | 
			
		||||
    gnss_sdr_timestamp.cc
 | 
			
		||||
    extra_data_file.cc
 | 
			
		||||
    sensor_data_file.cc
 | 
			
		||||
    sensor_data_source_configuration.cc
 | 
			
		||||
    sensor_data_type.cc
 | 
			
		||||
    sensor_identifier.cc
 | 
			
		||||
    ${OPT_SIGNAL_SOURCE_LIB_SOURCES}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -64,7 +67,10 @@ set(SIGNAL_SOURCE_LIB_HEADERS
 | 
			
		||||
    rtl_tcp_commands.h
 | 
			
		||||
    rtl_tcp_dongle_info.h
 | 
			
		||||
    gnss_sdr_valve.h
 | 
			
		||||
    extra_data_file.h
 | 
			
		||||
    sensor_data_file.h
 | 
			
		||||
    sensor_data_source_configuration.h
 | 
			
		||||
    sensor_data_type.h
 | 
			
		||||
    sensor_identifier.h
 | 
			
		||||
    ${OPT_SIGNAL_SOURCE_LIB_HEADERS}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file extra_data_file.cc
 | 
			
		||||
 * \file sensor_data_file.cc
 | 
			
		||||
 * \brief  Provides a simple abstraction for reading contiguous binary data from a file
 | 
			
		||||
 * \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
 | 
			
		||||
 *
 | 
			
		||||
@@ -14,20 +14,26 @@
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "extra_data_file.h"
 | 
			
		||||
#include "sensor_data_file.h"
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
ExtraDataFile::ExtraDataFile(
 | 
			
		||||
SensorDataFile::SensorDataFile(
 | 
			
		||||
    const std::string& path,
 | 
			
		||||
    const std::size_t& sample_delay,
 | 
			
		||||
    const std::size_t& sample_period,
 | 
			
		||||
    const std::size_t& offset_in_file,
 | 
			
		||||
    const std::size_t& item_size,
 | 
			
		||||
    const bool& repeat)
 | 
			
		||||
    : path_(path),
 | 
			
		||||
      file_(path_),
 | 
			
		||||
      sample_delay_(sample_delay),
 | 
			
		||||
      sample_period_(sample_period),
 | 
			
		||||
      offset_in_file_(offset_in_file),
 | 
			
		||||
      item_size_(item_size),
 | 
			
		||||
      repeat_(repeat),
 | 
			
		||||
      done_(false),
 | 
			
		||||
      chunks_read_(0),
 | 
			
		||||
      last_sample_stamp_(sample_delay),
 | 
			
		||||
      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.
 | 
			
		||||
{
 | 
			
		||||
@@ -36,20 +42,20 @@ ExtraDataFile::ExtraDataFile(
 | 
			
		||||
    io_buffer_.resize(io_buffer_size_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExtraDataFile::reset()
 | 
			
		||||
void SensorDataFile::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()
 | 
			
		||||
bool SensorDataFile::read_item(std::vector<uint8_t>& buffer)
 | 
			
		||||
{
 | 
			
		||||
    if (offset_in_io_buffer_ >= io_buffer_size_)
 | 
			
		||||
        {
 | 
			
		||||
            if (done_)
 | 
			
		||||
                {
 | 
			
		||||
                    return {};
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                {
 | 
			
		||||
@@ -57,13 +63,30 @@ std::vector<uint8_t> ExtraDataFile::read_item()
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    std::vector<uint8_t> item_buf{};
 | 
			
		||||
    read_into_item_buffer(item_buf);
 | 
			
		||||
 | 
			
		||||
    return item_buf;
 | 
			
		||||
    chunks_read_++;
 | 
			
		||||
    read_into_item_buffer(buffer);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExtraDataFile::read_into_io_buffer()
 | 
			
		||||
bool SensorDataFile::read_until_sample(std::size_t end_sample, std::size_t& sample_stamp, std::vector<uint8_t>& buffer)
 | 
			
		||||
{
 | 
			
		||||
    if (last_sample_stamp_ + sample_period_ < end_sample)
 | 
			
		||||
        {
 | 
			
		||||
            last_sample_stamp_ += sample_period_;
 | 
			
		||||
            sample_stamp = last_sample_stamp_;
 | 
			
		||||
            read_item(buffer);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::size_t SensorDataFile::get_chunks_read() const
 | 
			
		||||
{
 | 
			
		||||
    return chunks_read_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SensorDataFile::read_into_io_buffer()
 | 
			
		||||
{
 | 
			
		||||
    file_.read(reinterpret_cast<char*>(&io_buffer_[0]), io_buffer_size_);
 | 
			
		||||
    const std::size_t bytes_read = file_.gcount();
 | 
			
		||||
@@ -85,7 +108,7 @@ void ExtraDataFile::read_into_io_buffer()
 | 
			
		||||
    offset_in_io_buffer_ = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ExtraDataFile::read_into_item_buffer(std::vector<uint8_t>& item_buf)
 | 
			
		||||
void SensorDataFile::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_);
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file extra_data_file.h
 | 
			
		||||
 * \file sensor_data_file.h
 | 
			
		||||
 * \brief  Provides a simple abstraction for reading contiguous binary data from a file
 | 
			
		||||
 * \author Victor Castillo, 2024. victorcastilloaguero(at).gmail.es
 | 
			
		||||
 *
 | 
			
		||||
@@ -15,12 +15,13 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef GNSS_SDR_EXTRA_DATA_FILE_H
 | 
			
		||||
#define GNSS_SDR_EXTRA_DATA_FILE_H
 | 
			
		||||
#ifndef GNSS_SDR_SENSOR_DATA_FILE_H
 | 
			
		||||
#define GNSS_SDR_SENSOR_DATA_FILE_H
 | 
			
		||||
 | 
			
		||||
#include <cstddef>  // for size_t
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
@@ -30,13 +31,18 @@
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ExtraDataFile
 | 
			
		||||
class SensorDataFile
 | 
			
		||||
{
 | 
			
		||||
    static constexpr std::size_t IO_BUFFER_CAPACITY = 1024;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    ExtraDataFile(
 | 
			
		||||
    using sptr = std::shared_ptr<SensorDataFile>;
 | 
			
		||||
    using id_type = std::size_t;
 | 
			
		||||
 | 
			
		||||
    SensorDataFile(
 | 
			
		||||
        const std::string& path,
 | 
			
		||||
        const std::size_t& sample_delay,
 | 
			
		||||
        const std::size_t& sample_period,
 | 
			
		||||
        const std::size_t& offset_in_file,
 | 
			
		||||
        const std::size_t& item_size,
 | 
			
		||||
        const bool& repeat);
 | 
			
		||||
@@ -44,9 +50,12 @@ public:
 | 
			
		||||
 | 
			
		||||
    void reset();
 | 
			
		||||
 | 
			
		||||
    std::vector<uint8_t> read_item();
 | 
			
		||||
    bool read_until_sample(std::size_t end_sample, std::size_t& sample_stamp, std::vector<uint8_t>& buffer);
 | 
			
		||||
 | 
			
		||||
    std::size_t get_chunks_read() const;
 | 
			
		||||
private:
 | 
			
		||||
    bool read_item(std::vector<uint8_t>& buffer);
 | 
			
		||||
 | 
			
		||||
    void read_into_io_buffer();
 | 
			
		||||
 | 
			
		||||
    void read_into_item_buffer(std::vector<uint8_t>& item_buf);
 | 
			
		||||
@@ -54,11 +63,15 @@ private:
 | 
			
		||||
private:
 | 
			
		||||
    std::string path_;
 | 
			
		||||
    std::ifstream file_;
 | 
			
		||||
    std::size_t sample_delay_;
 | 
			
		||||
    std::size_t sample_period_;
 | 
			
		||||
    std::size_t offset_in_file_;
 | 
			
		||||
    std::size_t item_size_;
 | 
			
		||||
    bool repeat_;
 | 
			
		||||
    bool done_;
 | 
			
		||||
 | 
			
		||||
    std::size_t chunks_read_;
 | 
			
		||||
    std::size_t last_sample_stamp_;
 | 
			
		||||
    std::vector<uint8_t> io_buffer_;
 | 
			
		||||
    std::size_t io_buffer_size_;
 | 
			
		||||
    std::size_t offset_in_io_buffer_;
 | 
			
		||||
@@ -66,4 +79,4 @@ private:
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
/** \} */
 | 
			
		||||
#endif  // GNSS_SDR_EXTRA_DATA_FILE_H
 | 
			
		||||
#endif  // GNSS_SDR_SENSOR_DATA_FILE_H
 | 
			
		||||
@@ -0,0 +1,152 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_data_source_configuration.cc
 | 
			
		||||
 * \brief
 | 
			
		||||
 * \author Victor Castillo, 2025. 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 "sensor_data_source_configuration.h"
 | 
			
		||||
 | 
			
		||||
SensorDataSourceConfiguration::SensorDataSourceConfiguration(const ConfigurationInterface* configuration, bool enabled)
 | 
			
		||||
    : enabled_(enabled), items_per_sample_(1)
 | 
			
		||||
{
 | 
			
		||||
    if (enabled_)
 | 
			
		||||
        {
 | 
			
		||||
            configure_files(configuration);
 | 
			
		||||
            configure_sensors(configuration);
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SensorDataSourceConfiguration::validate() const
 | 
			
		||||
{
 | 
			
		||||
    return validate_files() and validate_sensors();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SensorDataSourceConfiguration::is_enabled() const
 | 
			
		||||
{
 | 
			
		||||
    return enabled_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SensorDataSourceConfiguration::set_items_per_sample(uint64_t items_per_sample)
 | 
			
		||||
{
 | 
			
		||||
    items_per_sample_ = items_per_sample;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t SensorDataSourceConfiguration::get_items_per_sample() const
 | 
			
		||||
{
 | 
			
		||||
    return items_per_sample_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const std::unordered_map<uint64_t, SensorDataFileConfiguration>& SensorDataSourceConfiguration::files() const
 | 
			
		||||
{
 | 
			
		||||
    return files_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const std::vector<SensorDataConfiguration>& SensorDataSourceConfiguration::sensors() const
 | 
			
		||||
{
 | 
			
		||||
    return sensors_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SensorDataSourceConfiguration::configure_files(const ConfigurationInterface* configuration)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t file_count = configuration->property(CONFIGURATION_ROLE + ".file_count"s, 1UL);
 | 
			
		||||
    for (uint64_t id = 0; id < file_count; ++id)
 | 
			
		||||
        {
 | 
			
		||||
            std::string role = CONFIGURATION_ROLE + ".file" + std::to_string(id);
 | 
			
		||||
            files_.emplace(
 | 
			
		||||
                id,
 | 
			
		||||
                SensorDataFileConfiguration{
 | 
			
		||||
                    .id = id,
 | 
			
		||||
                    .filename = configuration->property(role + ".filename"s, std::string{""}),
 | 
			
		||||
                    .repeat = configuration->property(role + ".repeat"s, false),
 | 
			
		||||
                    .chunk_size = configuration->property(role + ".chunk_size"s, 0UL),
 | 
			
		||||
                    .file_offset = configuration->property(role + ".file_offset"s, 0UL),
 | 
			
		||||
                    .sample_offset = configuration->property(role + ".sample_offset"s, 0UL),
 | 
			
		||||
                    .sample_period = configuration->property(role + ".sample_period"s, 0UL)});
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SensorDataSourceConfiguration::configure_sensors(const ConfigurationInterface* configuration)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t sensor_count = configuration->property(CONFIGURATION_ROLE + ".sensor_count"s, 1UL);
 | 
			
		||||
    for (uint64_t id = 0; id < sensor_count; ++id)
 | 
			
		||||
        {
 | 
			
		||||
            std::string role = CONFIGURATION_ROLE + ".sensor" + std::to_string(id);
 | 
			
		||||
 | 
			
		||||
            // Configure sensor data type, default to same data type as previous sensor
 | 
			
		||||
            SensorDataType::value_type data_type = SensorDataType::FLOAT;
 | 
			
		||||
            if (id > 0 and not configuration->is_present(role + ".type"))
 | 
			
		||||
                {
 | 
			
		||||
                    data_type = sensors_[id - 1].type;
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                {
 | 
			
		||||
                    data_type = SensorDataType::from_string(configuration->property(role + ".type"s, std::string{"UNKNOWN"}));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Configure offset, default to previous sensor offset plus previous sensor size
 | 
			
		||||
            uint64_t offset = 0UL;
 | 
			
		||||
            if (id > 0 and not configuration->is_present(role + ".offset"))
 | 
			
		||||
                {
 | 
			
		||||
                    offset = sensors_[id - 1].offset + SensorDataType::get_size(sensors_[id - 1].type);
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                {
 | 
			
		||||
                    offset = configuration->property(role + ".offset"s, 0UL);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Configure file_id, default to previous sensor file_id
 | 
			
		||||
            uint64_t file_id = 0UL;
 | 
			
		||||
            if (id > 0 and not configuration->is_present(role + ".file"))
 | 
			
		||||
                {
 | 
			
		||||
                    file_id = sensors_[id - 1].file_id;
 | 
			
		||||
                }
 | 
			
		||||
            else
 | 
			
		||||
                {
 | 
			
		||||
                    file_id = configuration->property(role + ".file"s, 0UL);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // Find out which sensor this is
 | 
			
		||||
            const std::string sensor_identifier = configuration->property(role + ".data"s, std::string{"UNDEFINED"});
 | 
			
		||||
 | 
			
		||||
            if (sensor_identifier != "UNDEFINED")
 | 
			
		||||
                {
 | 
			
		||||
                    sensors_.emplace_back(SensorDataConfiguration{
 | 
			
		||||
                        .id = id,
 | 
			
		||||
                        .file_id = file_id,
 | 
			
		||||
                        .identifier = SensorIdentifier::from_string(sensor_identifier),
 | 
			
		||||
                        .type = data_type,
 | 
			
		||||
                        .offset = offset,
 | 
			
		||||
                        .tag_key = pmt::mp(sensor_identifier)});
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool SensorDataSourceConfiguration::validate_files() const
 | 
			
		||||
{
 | 
			
		||||
    for (const auto& file : files_)
 | 
			
		||||
        {
 | 
			
		||||
            // TODO - Implement
 | 
			
		||||
        }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SensorDataSourceConfiguration::validate_sensors() const
 | 
			
		||||
{
 | 
			
		||||
    for (const auto& sensor : sensors_)
 | 
			
		||||
        {
 | 
			
		||||
            // TODO - Implement
 | 
			
		||||
        }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,96 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_data_source_configuration.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_SENSOR_DATA_SOURCE_CONFIGURATION_H
 | 
			
		||||
#define GNSS_SDR_SENSOR_DATA_SOURCE_CONFIGURATION_H
 | 
			
		||||
 | 
			
		||||
#include "configuration_interface.h"
 | 
			
		||||
#include "sensor_data_type.h"
 | 
			
		||||
#include "sensor_identifier.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <unordered_map>
 | 
			
		||||
 | 
			
		||||
/** \addtogroup Signal_Source
 | 
			
		||||
 * \{ */
 | 
			
		||||
/** \addtogroup Signal_Source_gnuradio_blocks
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
using namespace std::string_literals;
 | 
			
		||||
 | 
			
		||||
static std::string CONFIGURATION_ROLE = "SensorData";
 | 
			
		||||
 | 
			
		||||
class ConfigurationInterface;
 | 
			
		||||
 | 
			
		||||
struct SensorDataFileConfiguration
 | 
			
		||||
{
 | 
			
		||||
    uint64_t id;
 | 
			
		||||
    std::string filename;
 | 
			
		||||
    bool repeat;
 | 
			
		||||
    uint64_t chunk_size;
 | 
			
		||||
    uint64_t file_offset;
 | 
			
		||||
    uint64_t sample_offset;
 | 
			
		||||
    uint64_t sample_period;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct SensorDataConfiguration
 | 
			
		||||
{
 | 
			
		||||
    uint64_t id;
 | 
			
		||||
    uint64_t file_id;
 | 
			
		||||
    SensorIdentifier::value_type identifier;
 | 
			
		||||
    SensorDataType::value_type type;
 | 
			
		||||
    uint64_t offset;
 | 
			
		||||
 | 
			
		||||
    pmt::pmt_t tag_key;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class SensorDataSourceConfiguration
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    explicit SensorDataSourceConfiguration(const ConfigurationInterface* configuration, bool enabled);
 | 
			
		||||
 | 
			
		||||
    bool validate() const;
 | 
			
		||||
 | 
			
		||||
    bool is_enabled() const;
 | 
			
		||||
 | 
			
		||||
    const std::unordered_map<uint64_t, SensorDataFileConfiguration>& files() const;
 | 
			
		||||
 | 
			
		||||
    const std::vector<SensorDataConfiguration>& sensors() const;
 | 
			
		||||
 | 
			
		||||
    void set_items_per_sample(uint64_t items_per_sample);
 | 
			
		||||
 | 
			
		||||
    uint64_t get_items_per_sample() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void configure_files(const ConfigurationInterface* configuration);
 | 
			
		||||
 | 
			
		||||
    void configure_sensors(const ConfigurationInterface* configuration);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    bool validate_files() const;
 | 
			
		||||
 | 
			
		||||
    bool validate_sensors() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    bool enabled_;
 | 
			
		||||
    std::unordered_map<uint64_t, SensorDataFileConfiguration> files_;
 | 
			
		||||
    std::vector<SensorDataConfiguration> sensors_;
 | 
			
		||||
    uint64_t items_per_sample_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
/** \} */
 | 
			
		||||
#endif  // GNSS_SDR_SENSOR_DATA_SOURCE_CONFIGURATION_H
 | 
			
		||||
							
								
								
									
										63
									
								
								src/algorithms/signal_source/libs/sensor_data_type.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/algorithms/signal_source/libs/sensor_data_type.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_data_type.cc
 | 
			
		||||
 * \brief
 | 
			
		||||
 * \author Victor Castillo, 2025. 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 "sensor_data_type.h"
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <pmt/pmt.h>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
SensorDataType::value_type SensorDataType::from_string(const std::string& s)
 | 
			
		||||
{
 | 
			
		||||
    if (s == "float" or s == "FLOAT")
 | 
			
		||||
        {
 | 
			
		||||
            return SensorDataType::FLOAT;
 | 
			
		||||
        }
 | 
			
		||||
    throw std::runtime_error{"Unknown sensor data type: " + s};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string SensorDataType::to_string(const SensorDataType::value_type& v)
 | 
			
		||||
{
 | 
			
		||||
    switch (v)
 | 
			
		||||
        {
 | 
			
		||||
        case SensorDataType::FLOAT:
 | 
			
		||||
            return "float";
 | 
			
		||||
        default:
 | 
			
		||||
            return "UNKNOWN SENSOR";
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint64_t SensorDataType::get_size(const SensorDataType::value_type& v)
 | 
			
		||||
{
 | 
			
		||||
    switch (v)
 | 
			
		||||
        {
 | 
			
		||||
        case SensorDataType::FLOAT:
 | 
			
		||||
            return sizeof(float);
 | 
			
		||||
        default:
 | 
			
		||||
            return 0UL;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pmt::pmt_t SensorDataType::make_value(const SensorDataType::value_type& v, void* value)
 | 
			
		||||
{
 | 
			
		||||
    switch (v)
 | 
			
		||||
        {
 | 
			
		||||
        case SensorDataType::FLOAT:
 | 
			
		||||
            return pmt::from_float(*static_cast<float*>(value));
 | 
			
		||||
        default:
 | 
			
		||||
            throw std::runtime_error{"Unknown sensor data type: " + to_string(v)};
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								src/algorithms/signal_source/libs/sensor_data_type.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/algorithms/signal_source/libs/sensor_data_type.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_data_type.h
 | 
			
		||||
 * \brief
 | 
			
		||||
 * \author Victor Castillo, 2025. 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_SENSOR_DATA_TYPE_H
 | 
			
		||||
#define GNSS_SDR_SENSOR_DATA_TYPE_H
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
#include <pmt/pmt.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
/** \addtogroup Signal_Source
 | 
			
		||||
 * \{ */
 | 
			
		||||
/** \addtogroup Signal_Source_libs
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
struct SensorDataType
 | 
			
		||||
{
 | 
			
		||||
    SensorDataType() = delete;
 | 
			
		||||
    enum value_type
 | 
			
		||||
    {
 | 
			
		||||
        FLOAT
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static value_type from_string(const std::string& s);
 | 
			
		||||
 | 
			
		||||
    static std::string to_string(const value_type& v);
 | 
			
		||||
 | 
			
		||||
    static uint64_t get_size(const value_type& v);
 | 
			
		||||
 | 
			
		||||
    static pmt::pmt_t make_value(const value_type& v, void* value);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
/** \} */
 | 
			
		||||
#endif  // GNSS_SDR_SENSOR_DATA_TYPE_H
 | 
			
		||||
							
								
								
									
										105
									
								
								src/algorithms/signal_source/libs/sensor_identifier.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/algorithms/signal_source/libs/sensor_identifier.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_identifier.cc
 | 
			
		||||
 * \brief
 | 
			
		||||
 * \author Victor Castillo, 2025. 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 "sensor_identifier.h"
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
SensorIdentifier::value_type SensorIdentifier::from_string(const std::string& s)
 | 
			
		||||
{
 | 
			
		||||
    if (s == "IMU_VEL_X")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_VEL_X;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_VEL_Y")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_VEL_Y;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_VEL_Z")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_VEL_Z;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ACC_X")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ACC_X;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ACC_Y")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ACC_Y;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ACC_Z")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ACC_Z;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_VEL_X")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_VEL_X;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_VEL_Y")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_VEL_Y;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_VEL_Z")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_VEL_Z;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_ACC_X")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_ACC_X;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_ACC_Y")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_ACC_Y;
 | 
			
		||||
        }
 | 
			
		||||
    else if (s == "IMU_ANG_ACC_Z")
 | 
			
		||||
        {
 | 
			
		||||
            return IMU_ANG_ACC_Z;
 | 
			
		||||
        }
 | 
			
		||||
    throw std::runtime_error{"Unknown sensor identifier: " + s};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string SensorIdentifier::to_string(const SensorIdentifier::value_type& v)
 | 
			
		||||
{
 | 
			
		||||
    switch (v)
 | 
			
		||||
        {
 | 
			
		||||
        case IMU_VEL_X:
 | 
			
		||||
            return "IMU_VEL_X";
 | 
			
		||||
        case IMU_VEL_Y:
 | 
			
		||||
            return "IMU_VEL_Y";
 | 
			
		||||
        case IMU_VEL_Z:
 | 
			
		||||
            return "IMU_VEL_Z";
 | 
			
		||||
        case IMU_ACC_X:
 | 
			
		||||
            return "IMU_ACC_X";
 | 
			
		||||
        case IMU_ACC_Y:
 | 
			
		||||
            return "IMU_ACC_Y";
 | 
			
		||||
        case IMU_ACC_Z:
 | 
			
		||||
            return "IMU_ACC_Z";
 | 
			
		||||
        case IMU_ANG_VEL_X:
 | 
			
		||||
            return "IMU_ANG_VEL_X";
 | 
			
		||||
        case IMU_ANG_VEL_Y:
 | 
			
		||||
            return "IMU_ANG_VEL_Y";
 | 
			
		||||
        case IMU_ANG_VEL_Z:
 | 
			
		||||
            return "IMU_ANG_VEL_Z";
 | 
			
		||||
        case IMU_ANG_ACC_X:
 | 
			
		||||
            return "IMU_ANG_ACC_X";
 | 
			
		||||
        case IMU_ANG_ACC_Y:
 | 
			
		||||
            return "IMU_ANG_ACC_Y";
 | 
			
		||||
        case IMU_ANG_ACC_Z:
 | 
			
		||||
            return "IMU_ANG_ACC_Z";
 | 
			
		||||
        default:
 | 
			
		||||
            return "UNKNOWN SENSOR";
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/algorithms/signal_source/libs/sensor_identifier.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/algorithms/signal_source/libs/sensor_identifier.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file sensor_identifier.h
 | 
			
		||||
 * \brief
 | 
			
		||||
 * \author Victor Castillo, 2025. 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_SENSOR_IDENTIFIER_H
 | 
			
		||||
#define GNSS_SDR_SENSOR_IDENTIFIER_H
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
/** \addtogroup Signal_Source
 | 
			
		||||
 * \{ */
 | 
			
		||||
/** \addtogroup Signal_Source_libs
 | 
			
		||||
 * \{ */
 | 
			
		||||
 | 
			
		||||
struct SensorIdentifier
 | 
			
		||||
{
 | 
			
		||||
    SensorIdentifier() = delete;
 | 
			
		||||
    enum value_type
 | 
			
		||||
    {
 | 
			
		||||
        IMU_VEL_X,
 | 
			
		||||
        IMU_VEL_Y,
 | 
			
		||||
        IMU_VEL_Z,
 | 
			
		||||
        IMU_ACC_X,
 | 
			
		||||
        IMU_ACC_Y,
 | 
			
		||||
        IMU_ACC_Z,
 | 
			
		||||
        IMU_ANG_VEL_X,
 | 
			
		||||
        IMU_ANG_VEL_Y,
 | 
			
		||||
        IMU_ANG_VEL_Z,
 | 
			
		||||
        IMU_ANG_ACC_X,
 | 
			
		||||
        IMU_ANG_ACC_Y,
 | 
			
		||||
        IMU_ANG_ACC_Z,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    static value_type from_string(const std::string& s);
 | 
			
		||||
 | 
			
		||||
    static std::string to_string(const value_type& v);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** \} */
 | 
			
		||||
/** \} */
 | 
			
		||||
#endif  // GNSS_SDR_SENSOR_IDENTIFIER_H
 | 
			
		||||
@@ -645,14 +645,7 @@ int gps_l1_ca_telemetry_decoder_gs::general_work(int noutput_items __attribute__
 | 
			
		||||
                    current_symbol.Flag_PLL_180_deg_phase_locked = false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // TODO - Merge these two loops
 | 
			
		||||
            std::vector<gr::tag_t> tags_vec;
 | 
			
		||||
            // 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"));
 | 
			
		||||
 
 | 
			
		||||
@@ -56,6 +56,7 @@ public:
 | 
			
		||||
    virtual float property(std::string property_name, float default_value) const = 0;
 | 
			
		||||
    virtual double property(std::string property_name, double default_value) const = 0;
 | 
			
		||||
    virtual void set_property(std::string property_name, std::string value) = 0;
 | 
			
		||||
    virtual bool is_present(const std::string& property_name) const = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -151,16 +151,16 @@ int gnss_sdr_sample_counter::work(int noutput_items __attribute__((unused)),
 | 
			
		||||
    out[0].Tracking_sample_counter = sample_counter;
 | 
			
		||||
    current_T_rx_ms += interval_ms;
 | 
			
		||||
 | 
			
		||||
    // *************** time tags ****************
 | 
			
		||||
    // *************** sensor tags ****************
 | 
			
		||||
    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
 | 
			
		||||
    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;
 | 
			
		||||
    get_tags_in_range(tags_vec, 0, nitems_read(0), nitems_read(0) + samples_per_output, pmt::mp("sensor_data"));
 | 
			
		||||
    for (const auto &tag : tags_vec)
 | 
			
		||||
        {
 | 
			
		||||
            add_item_tag(0, this->nitems_written(0) + 1, tag.key, tag.value);
 | 
			
		||||
            add_item_tag(0, nitems_written(0) + 1, tag.key, tag.value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // *************** time tags ****************
 | 
			
		||||
    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)
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ public:
 | 
			
		||||
    float property(std::string property_name, float default_value) const override;
 | 
			
		||||
    double property(std::string property_name, double default_value) const override;
 | 
			
		||||
    void set_property(std::string property_name, std::string value) override;
 | 
			
		||||
    bool is_present(const std::string& property_name) const;
 | 
			
		||||
    bool is_present(const std::string& property_name) const override;
 | 
			
		||||
    bool has_section() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ public:
 | 
			
		||||
    double property(std::string property_name, double default_value) const override;
 | 
			
		||||
    void set_property(std::string property_name, std::string value) override;
 | 
			
		||||
    void supersede_property(const std::string& property_name, const std::string& value);
 | 
			
		||||
    bool is_present(const std::string& property_name) const;
 | 
			
		||||
    bool is_present(const std::string& property_name) const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::map<std::string, std::string> properties_;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user