1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 20:50:33 +00:00

Merge branch 'glamountain-kf' into kf

This commit is contained in:
Carles Fernandez 2018-07-20 13:20:04 +02:00
commit ca4614811c
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
69 changed files with 2209 additions and 1122 deletions

View File

@ -40,6 +40,7 @@ Antonio Ramos antonio.ramosdet@gmail.com Developer
Marc Majoral marc.majoral@cttc.cat Developer Marc Majoral marc.majoral@cttc.cat Developer
Jordi Vilà-Valls jordi.vila@cttc.cat Consultant Jordi Vilà-Valls jordi.vila@cttc.cat Consultant
Pau Closas pau.closas@northeastern.edu Consultant Pau Closas pau.closas@northeastern.edu Consultant
Álvaro Cebrián Juan acebrianjuan@gmail.com Contributor
Andres Cecilia Luque a.cecilia.luque@gmail.com Contributor Andres Cecilia Luque a.cecilia.luque@gmail.com Contributor
Anthony Arnold anthony.arnold@uqconnect.edu.au Contributor Anthony Arnold anthony.arnold@uqconnect.edu.au Contributor
Carlos Avilés carlos.avilesr@googlemail.com Contributor Carlos Avilés carlos.avilesr@googlemail.com Contributor

View File

@ -32,12 +32,11 @@
#ifndef GNSS_SDR_GALILEO_E1_PCPS_8MS_AMBIGUOUS_ACQUISITION_H_ #ifndef GNSS_SDR_GALILEO_E1_PCPS_8MS_AMBIGUOUS_ACQUISITION_H_
#define GNSS_SDR_GALILEO_E1_PCPS_8MS_AMBIGUOUS_ACQUISITION_H_ #define GNSS_SDR_GALILEO_E1_PCPS_8MS_AMBIGUOUS_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "galileo_pcps_8ms_acquisition_cc.h" #include "galileo_pcps_8ms_acquisition_cc.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -123,6 +122,7 @@ public:
* \brief Restart acquisition algorithm * \brief Restart acquisition algorithm
*/ */
void reset() override; void reset() override;
void set_state(int state __attribute__((unused))) override{};
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -58,31 +58,38 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
dump_ = configuration_->property(role + ".dump", false); acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil((1.0 / Galileo_E1_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
blocking_ = configuration_->property(role + ".blocking", true);
acq_parameters.blocking = blocking_;
doppler_max_ = configuration_->property(role + ".doppler_max", 5000); doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_; acq_parameters.doppler_max = doppler_max_;
sampled_ms_ = 4; acq_parameters.ms_per_code = 4;
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters.ms_per_code);
acq_parameters.sampled_ms = sampled_ms_; acq_parameters.sampled_ms = sampled_ms_;
if ((acq_parameters.sampled_ms % acq_parameters.ms_per_code) != 0)
{
LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 4. Setting it to 4";
acq_parameters.sampled_ms = acq_parameters.ms_per_code;
}
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
acq_parameters.bit_transition_flag = bit_transition_flag_; acq_parameters.bit_transition_flag = bit_transition_flag_;
use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions
max_dwells_ = configuration_->property(role + ".max_dwells", 1); max_dwells_ = configuration_->property(role + ".max_dwells", 1);
acq_parameters.max_dwells = max_dwells_; acq_parameters.max_dwells = max_dwells_;
dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
blocking_ = configuration_->property(role + ".blocking", true);
acq_parameters.blocking = blocking_;
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
acq_parameters.dump_filename = dump_filename_; acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code (4 ms) ----------------- //--- Find number of samples per spreading code (4 ms) -----------------
code_length_ = static_cast<unsigned int>(std::round(static_cast<double>(fs_in_) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); code_length_ = static_cast<unsigned int>(std::floor(static_cast<double>(fs_in_) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)));
acq_parameters.samples_per_code = code_length_;
int samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001)); float samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.samples_per_ms = samples_per_ms; acq_parameters.samples_per_ms = samples_per_ms;
acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(Galileo_E1_CODE_PERIOD_MS);
vector_length_ = sampled_ms_ * samples_per_ms; vector_length_ = sampled_ms_ * samples_per_ms;
if (bit_transition_flag_) if (bit_transition_flag_)

View File

@ -130,7 +130,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -32,12 +32,11 @@
#ifndef GNSS_SDR_GALILEO_E1_PCPS_CCCWSR_AMBIGUOUS_ACQUISITION_H_ #ifndef GNSS_SDR_GALILEO_E1_PCPS_CCCWSR_AMBIGUOUS_ACQUISITION_H_
#define GNSS_SDR_GALILEO_E1_PCPS_CCCWSR_AMBIGUOUS_ACQUISITION_H_ #define GNSS_SDR_GALILEO_E1_PCPS_CCCWSR_AMBIGUOUS_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_cccwsr_acquisition_cc.h" #include "pcps_cccwsr_acquisition_cc.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -124,7 +123,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -32,11 +32,11 @@
#ifndef GNSS_SDR_GALILEO_E1_PCPS_QUICKSYNC_AMBIGUOUS_ACQUISITION_H_ #ifndef GNSS_SDR_GALILEO_E1_PCPS_QUICKSYNC_AMBIGUOUS_ACQUISITION_H_
#define GNSS_SDR_GALILEO_E1_PCPS_QUICKSYNC_AMBIGUOUS_ACQUISITION_H_ #define GNSS_SDR_GALILEO_E1_PCPS_QUICKSYNC_AMBIGUOUS_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_quicksync_acquisition_cc.h" #include "pcps_quicksync_acquisition_cc.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -127,7 +127,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -32,12 +32,11 @@
#ifndef GNSS_SDR_GALILEO_E1_PCPS_TONG_AMBIGUOUS_ACQUISITION_H_ #ifndef GNSS_SDR_GALILEO_E1_PCPS_TONG_AMBIGUOUS_ACQUISITION_H_
#define GNSS_SDR_GALILEO_E1_PCPS_TONG_AMBIGUOUS_ACQUISITION_H_ #define GNSS_SDR_GALILEO_E1_PCPS_TONG_AMBIGUOUS_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_tong_acquisition_cc.h" #include "pcps_tong_acquisition_cc.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -127,7 +126,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -38,10 +38,10 @@
#ifndef GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_ #ifndef GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_
#define GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_ #define GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_
#include <string>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "galileo_e5a_noncoherent_iq_acquisition_caf_cc.h" #include "galileo_e5a_noncoherent_iq_acquisition_caf_cc.h"
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -129,7 +129,7 @@ public:
* first available sample. * first available sample.
* \param state - int=1 forces start of acquisition * \param state - int=1 forces start of acquisition
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -57,6 +57,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
acq_pilot_ = configuration_->property(role + ".acquire_pilot", false); acq_pilot_ = configuration_->property(role + ".acquire_pilot", false);
acq_iq_ = configuration_->property(role + ".acquire_iq", false); acq_iq_ = configuration_->property(role + ".acquire_iq", false);
if (acq_iq_) if (acq_iq_)
@ -100,9 +101,10 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
LOG(WARNING) << item_type_ << " unknown acquisition item type"; LOG(WARNING) << item_type_ << " unknown acquisition item type";
} }
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.samples_per_code = code_length_; acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.samples_per_ms = code_length_;
acq_parameters.sampled_ms = sampled_ms_; acq_parameters.sampled_ms = sampled_ms_;
acq_parameters.ms_per_code = 1;
acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GALILEO_E5a_CODE_PERIOD_MS);
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);

View File

@ -121,7 +121,7 @@ public:
* first available sample. * first available sample.
* \param state - int=1 forces start of acquisition * \param state - int=1 forces start of acquisition
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
float calculate_threshold(float pfa); float calculate_threshold(float pfa);

View File

@ -59,6 +59,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil(GLONASS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false); dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_; acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -99,8 +100,9 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
} }
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = sampled_ms_; acq_parameters.sampled_ms = sampled_ms_;
acq_parameters.samples_per_ms = code_length_; acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.samples_per_code = code_length_; acq_parameters.ms_per_code = 1;
acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GLONASS_L1_CA_CODE_PERIOD * 1000.0);
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);

View File

@ -130,7 +130,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -58,6 +58,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil(GLONASS_L2_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false); dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_; acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -98,8 +99,9 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
} }
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = sampled_ms_; acq_parameters.sampled_ms = sampled_ms_;
acq_parameters.samples_per_ms = code_length_; acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.samples_per_code = code_length_; acq_parameters.ms_per_code = 1;
acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GLONASS_L2_CA_CODE_PERIOD * 1000.0);
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);

View File

@ -129,7 +129,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false); dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_; acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -70,6 +71,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
acq_parameters.doppler_max = doppler_max_; acq_parameters.doppler_max = doppler_max_;
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms_; acq_parameters.sampled_ms = sampled_ms_;
acq_parameters.ms_per_code = 1;
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
acq_parameters.bit_transition_flag = bit_transition_flag_; acq_parameters.bit_transition_flag = bit_transition_flag_;
use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
@ -82,15 +84,11 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
//--- Find number of samples per spreading code ------------------------- //--- Find number of samples per spreading code -------------------------
code_length_ = static_cast<unsigned int>(std::round(static_cast<double>(fs_in_) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); code_length_ = static_cast<unsigned int>(std::floor(static_cast<double>(fs_in_) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)));
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
vector_length_ = code_length_ * sampled_ms_; acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GPS_L1_CA_CODE_PERIOD * 1000.0);
if (bit_transition_flag_)
{
vector_length_ *= 2;
}
vector_length_ = std::floor(acq_parameters.sampled_ms * acq_parameters.samples_per_ms) * (acq_parameters.bit_transition_flag ? 2 : 1);
code_ = new gr_complex[vector_length_]; code_ = new gr_complex[vector_length_];
if (item_type_.compare("cshort") == 0) if (item_type_.compare("cshort") == 0)
@ -101,8 +99,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
{ {
item_size_ = sizeof(gr_complex); item_size_ = sizeof(gr_complex);
} }
acq_parameters.samples_per_ms = code_length_;
acq_parameters.samples_per_code = code_length_;
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false);
acquisition_ = pcps_make_acquisition(acq_parameters); acquisition_ = pcps_make_acquisition(acq_parameters);

View File

@ -134,7 +134,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -33,11 +33,12 @@
*/ */
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h" #include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include <glog/logging.h>
#include "gps_sdr_signal_processing.h" #include "gps_sdr_signal_processing.h"
#include "GPS_L1_CA.h" #include "GPS_L1_CA.h"
#include "configuration_interface.h" #include "configuration_interface.h"
#include "gnss_sdr_flags.h" #include "gnss_sdr_flags.h"
#include "acq_conf.h"
#include <glog/logging.h>
using google::LogMessage; using google::LogMessage;
@ -49,29 +50,36 @@ GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler(
std::string default_dump_filename = "./data/acquisition.dat"; std::string default_dump_filename = "./data/acquisition.dat";
DLOG(INFO) << "role " << role; DLOG(INFO) << "role " << role;
Acq_Conf acq_parameters = Acq_Conf();
item_type_ = configuration->property(role + ".item_type", default_item_type); item_type_ = configuration->property(role + ".item_type", default_item_type);
long fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration->property(role + ".dump", false); dump_ = configuration->property(role + ".dump", false);
acq_parameters.dump = dump_;
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename); dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
acq_parameters.dump_filename = dump_filename_;
doppler_max_ = configuration->property(role + ".doppler_max", 5000); doppler_max_ = configuration->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
doppler_min_ = configuration->property(role + ".doppler_min", -doppler_max_); acq_parameters.doppler_max = doppler_max_;
sampled_ms_ = configuration->property(role + ".coherent_integration_time_ms", 1); sampled_ms_ = configuration->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms_;
max_dwells_ = configuration->property(role + ".max_dwells", 1); max_dwells_ = configuration->property(role + ".max_dwells", 1);
acq_parameters.max_dwells = max_dwells_;
acq_parameters.blocking_on_standby = configuration->property(role + ".blocking_on_standby", false);
//--- Find number of samples per spreading code ------------------------- //--- Find number of samples per spreading code -------------------------
vector_length_ = round(fs_in_ / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); vector_length_ = round(fs_in_ / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
acq_parameters.samples_per_ms = vector_length_;
code_ = new gr_complex[vector_length_]; code_ = new gr_complex[vector_length_];
if (item_type_.compare("gr_complex") == 0) if (item_type_.compare("gr_complex") == 0)
{ {
item_size_ = sizeof(gr_complex); item_size_ = sizeof(gr_complex);
acquisition_cc_ = pcps_make_acquisition_fine_doppler_cc(max_dwells_, sampled_ms_, acquisition_cc_ = pcps_make_acquisition_fine_doppler_cc(acq_parameters);
doppler_max_, doppler_min_, fs_in_, vector_length_,
dump_, dump_filename_);
} }
else else
{ {
@ -161,6 +169,12 @@ void GpsL1CaPcpsAcquisitionFineDoppler::reset()
} }
void GpsL1CaPcpsAcquisitionFineDoppler::set_state(int state)
{
acquisition_cc_->set_state(state);
}
void GpsL1CaPcpsAcquisitionFineDoppler::connect(boost::shared_ptr<gr::top_block> top_block) void GpsL1CaPcpsAcquisitionFineDoppler::connect(boost::shared_ptr<gr::top_block> top_block)
{ {
if (top_block) if (top_block)

View File

@ -34,11 +34,10 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FINE_DOPPLER_H_
#include <string>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_acquisition_fine_doppler_cc.h" #include "pcps_acquisition_fine_doppler_cc.h"
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -122,6 +121,11 @@ public:
*/ */
void reset() override; void reset() override;
/*!
* \brief If state = 1, it forces the block to start acquiring from the first sample
*/
void set_state(int state) override;
private: private:
pcps_acquisition_fine_doppler_cc_sptr acquisition_cc_; pcps_acquisition_fine_doppler_cc_sptr acquisition_cc_;
size_t item_size_; size_t item_size_;
@ -131,7 +135,6 @@ private:
float threshold_; float threshold_;
int doppler_max_; int doppler_max_;
unsigned int doppler_step_; unsigned int doppler_step_;
int doppler_min_;
unsigned int sampled_ms_; unsigned int sampled_ms_;
int max_dwells_; int max_dwells_;
long fs_in_; long fs_in_;

View File

@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in; acq_parameters.fs_in = fs_in;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
doppler_max_ = configuration_->property(role + ".doppler_max", 5000); doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_; acq_parameters.doppler_max = doppler_max_;

View File

@ -132,7 +132,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -34,11 +34,10 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_ASSISTED_ACQUISITION_H_
#include <string>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_assisted_acquisition_cc.h" #include "pcps_assisted_acquisition_cc.h"
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -121,6 +120,7 @@ public:
* \brief Restart acquisition algorithm * \brief Restart acquisition algorithm
*/ */
void reset() override; void reset() override;
void set_state(int state __attribute__((unused))) override{};
private: private:
pcps_assisted_acquisition_cc_sptr acquisition_cc_; pcps_assisted_acquisition_cc_sptr acquisition_cc_;

View File

@ -32,12 +32,11 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_OPENCL_ACQUISITION_H_ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_OPENCL_ACQUISITION_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_OPENCL_ACQUISITION_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_OPENCL_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_opencl_acquisition_cc.h" #include "pcps_opencl_acquisition_cc.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -123,6 +122,7 @@ public:
* \brief Restart acquisition algorithm * \brief Restart acquisition algorithm
*/ */
void reset() override; void reset() override;
void set_state(int state __attribute__((unused))) override{};
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -33,13 +33,12 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_QUICKSYNC_ACQUISITION_H_ #ifndef GNSS_SDR_GPS_L1_CA_PCPS_QUICKSYNC_ACQUISITION_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_QUICKSYNC_ACQUISITION_H_ #define GNSS_SDR_GPS_L1_CA_PCPS_QUICKSYNC_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_quicksync_acquisition_cc.h" #include "pcps_quicksync_acquisition_cc.h"
#include "configuration_interface.h" #include "configuration_interface.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -129,7 +128,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -32,12 +32,12 @@
#ifndef GNSS_SDR_GPS_L1_CA_TONG_ACQUISITION_H_ #ifndef GNSS_SDR_GPS_L1_CA_TONG_ACQUISITION_H_
#define GNSS_SDR_GPS_L1_CA_TONG_ACQUISITION_H_ #define GNSS_SDR_GPS_L1_CA_TONG_ACQUISITION_H_
#include <string>
#include <gnuradio/blocks/stream_to_vector.h>
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acquisition_interface.h" #include "acquisition_interface.h"
#include "pcps_tong_acquisition_cc.h" #include "pcps_tong_acquisition_cc.h"
#include "configuration_interface.h" #include "configuration_interface.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <string>
class ConfigurationInterface; class ConfigurationInterface;
@ -127,7 +127,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;

View File

@ -60,6 +60,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false); dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_; acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -77,15 +78,19 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
acq_parameters.dump_filename = dump_filename_; acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code ------------------------- //--- Find number of samples per spreading code -------------------------
code_length_ = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS))); acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.ms_per_code = 20;
vector_length_ = code_length_; acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", acq_parameters.ms_per_code);
if ((acq_parameters.sampled_ms % acq_parameters.ms_per_code) != 0)
if (bit_transition_flag_)
{ {
vector_length_ *= 2; LOG(WARNING) << "Parameter coherent_integration_time_ms should be a multiple of 20. Setting it to 20";
acq_parameters.sampled_ms = acq_parameters.ms_per_code;
} }
code_length_ = acq_parameters.ms_per_code * acq_parameters.samples_per_ms;
vector_length_ = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1);
code_ = new gr_complex[vector_length_]; code_ = new gr_complex[vector_length_];
if (item_type_.compare("cshort") == 0) if (item_type_.compare("cshort") == 0)
@ -96,13 +101,13 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
{ {
item_size_ = sizeof(gr_complex); item_size_ = sizeof(gr_complex);
} }
acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
acq_parameters.samples_per_code = code_length_; acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GPS_L2_M_PERIOD * 1000.0);
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = 20;
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", true); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false); acq_parameters.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false);
acquisition_ = pcps_make_acquisition(acq_parameters); acquisition_ = pcps_make_acquisition(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")"; DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")";
@ -120,6 +125,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
threshold_ = 0.0; threshold_ = 0.0;
doppler_step_ = 0; doppler_step_ = 0;
gnss_synchro_ = 0; gnss_synchro_ = 0;
num_codes_ = acq_parameters.sampled_ms / acq_parameters.ms_per_code;
if (in_streams_ > 1) if (in_streams_ > 1)
{ {
LOG(ERROR) << "This implementation only supports one input stream"; LOG(ERROR) << "This implementation only supports one input stream";
@ -208,9 +214,18 @@ void GpsL2MPcpsAcquisition::init()
void GpsL2MPcpsAcquisition::set_local_code() void GpsL2MPcpsAcquisition::set_local_code()
{ {
gps_l2c_m_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_); std::complex<float>* code = new std::complex<float>[code_length_];
gps_l2c_m_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_);
for (unsigned int i = 0; i < num_codes_; i++)
{
memcpy(&(code_[i * code_length_]), code,
sizeof(gr_complex) * code_length_);
}
acquisition_->set_local_code(code_); acquisition_->set_local_code(code_);
delete[] code;
} }

View File

@ -132,7 +132,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;
@ -160,6 +160,7 @@ private:
std::string role_; std::string role_;
unsigned int in_streams_; unsigned int in_streams_;
unsigned int out_streams_; unsigned int out_streams_;
unsigned int num_codes_;
float calculate_threshold(float pfa); float calculate_threshold(float pfa);
}; };

View File

@ -1,5 +1,5 @@
/*! /*!
* \file gps_l5i pcps_acquisition.cc * \file gps_l5i_pcps_acquisition.cc
* \brief Adapts a PCPS acquisition block to an Acquisition Interface for * \brief Adapts a PCPS acquisition block to an Acquisition Interface for
* GPS L5i signals * GPS L5i signals
* \authors <ul> * \authors <ul>
@ -59,6 +59,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_; acq_parameters.fs_in = fs_in_;
acq_parameters.samples_per_chip = static_cast<unsigned int>(ceil((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
dump_ = configuration_->property(role + ".dump", false); dump_ = configuration_->property(role + ".dump", false);
acq_parameters.dump = dump_; acq_parameters.dump = dump_;
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0); acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
@ -95,10 +96,12 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
{ {
item_size_ = sizeof(gr_complex); item_size_ = sizeof(gr_complex);
} }
acq_parameters.samples_per_code = code_length_; acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
acq_parameters.samples_per_ms = code_length_; acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GPS_L5i_PERIOD * 1000.0);
acq_parameters.ms_per_code = 1;
acq_parameters.it_size = item_size_; acq_parameters.it_size = item_size_;
acq_parameters.sampled_ms = 1; acq_parameters.sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
num_codes_ = acq_parameters.sampled_ms;
acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
@ -205,9 +208,18 @@ void GpsL5iPcpsAcquisition::init()
void GpsL5iPcpsAcquisition::set_local_code() void GpsL5iPcpsAcquisition::set_local_code()
{ {
gps_l5i_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_); std::complex<float>* code = new std::complex<float>[code_length_];
gps_l5i_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_);
for (unsigned int i = 0; i < num_codes_; i++)
{
memcpy(&(code_[i * code_length_]), code,
sizeof(gr_complex) * code_length_);
}
acquisition_->set_local_code(code_); acquisition_->set_local_code(code_);
delete[] code;
} }

View File

@ -1,5 +1,5 @@
/*! /*!
* \file GPS_L5i_PCPS_Acquisition.h * \file gps_l5i_pcps_acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L5i signals * GPS L5i signals
* \authors <ul> * \authors <ul>
@ -132,7 +132,7 @@ public:
/*! /*!
* \brief If state = 1, it forces the block to start acquiring from the first sample * \brief If state = 1, it forces the block to start acquiring from the first sample
*/ */
void set_state(int state); void set_state(int state) override;
private: private:
ConfigurationInterface* configuration_; ConfigurationInterface* configuration_;
@ -158,6 +158,7 @@ private:
std::complex<float>* code_; std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_; Gnss_Synchro* gnss_synchro_;
std::string role_; std::string role_;
unsigned int num_codes_;
unsigned int in_streams_; unsigned int in_streams_;
unsigned int out_streams_; unsigned int out_streams_;

View File

@ -52,8 +52,8 @@ pcps_acquisition_sptr pcps_make_acquisition(const Acq_Conf& conf_)
pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acquisition", pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acquisition",
gr::io_signature::make(1, 1, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1)), gr::io_signature::make(1, 1, conf_.it_size * std::floor(conf_.sampled_ms * conf_.samples_per_ms) * (conf_.bit_transition_flag ? 2 : 1)),
gr::io_signature::make(0, 0, conf_.it_size * conf_.sampled_ms * conf_.samples_per_ms * (conf_.bit_transition_flag ? 2 : 1))) gr::io_signature::make(0, 0, conf_.it_size))
{ {
this->message_port_register_out(pmt::mp("events")); this->message_port_register_out(pmt::mp("events"));
@ -63,8 +63,17 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_positive_acq = 0; d_positive_acq = 0;
d_state = 0; d_state = 0;
d_old_freq = 0; d_old_freq = 0;
d_well_count = 0; d_num_noncoherent_integrations_counter = 0;
d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms; d_consumed_samples = acq_parameters.sampled_ms * acq_parameters.samples_per_ms * (acq_parameters.bit_transition_flag ? 2 : 1);
if (acq_parameters.sampled_ms == acq_parameters.ms_per_code)
{
d_fft_size = d_consumed_samples;
}
else
{
d_fft_size = d_consumed_samples * 2;
}
//d_fft_size = next power of two? ////
d_mag = 0; d_mag = 0;
d_input_power = 0.0; d_input_power = 0.0;
d_num_doppler_bins = 0; d_num_doppler_bins = 0;
@ -94,12 +103,14 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
// size of the input buffer and padding the code with zeros. // size of the input buffer and padding the code with zeros.
if (acq_parameters.bit_transition_flag) if (acq_parameters.bit_transition_flag)
{ {
d_fft_size *= 2; d_fft_size = d_consumed_samples * 2;
acq_parameters.max_dwells = 1; // Activation of acq_parameters.bit_transition_flag invalidates the value of acq_parameters.max_dwells acq_parameters.max_dwells = 1; // Activation of acq_parameters.bit_transition_flag invalidates the value of acq_parameters.max_dwells
} }
d_tmp_buffer = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_fft_codes = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_fft_codes = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); d_magnitude = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_input_signal = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
// Direct FFT // Direct FFT
d_fft_if = new gr::fft::fft_complex(d_fft_size, true); d_fft_if = new gr::fft::fft_complex(d_fft_size, true);
@ -110,11 +121,12 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_gnss_synchro = 0; d_gnss_synchro = 0;
d_grid_doppler_wipeoffs = nullptr; d_grid_doppler_wipeoffs = nullptr;
d_grid_doppler_wipeoffs_step_two = nullptr; d_grid_doppler_wipeoffs_step_two = nullptr;
d_magnitude_grid = nullptr;
d_worker_active = false; d_worker_active = false;
d_data_buffer = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_data_buffer = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_consumed_samples * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
if (d_cshort) if (d_cshort)
{ {
d_data_buffer_sc = static_cast<lv_16sc_t*>(volk_gnsssdr_malloc(d_fft_size * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment())); d_data_buffer_sc = static_cast<lv_16sc_t*>(volk_gnsssdr_malloc(d_consumed_samples * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment()));
} }
else else
{ {
@ -124,6 +136,16 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
d_step_two = false; d_step_two = false;
d_dump_number = 0; d_dump_number = 0;
d_dump_channel = acq_parameters.dump_channel; d_dump_channel = acq_parameters.dump_channel;
d_samplesPerChip = acq_parameters.samples_per_chip;
// todo: CFAR statistic not available for non-coherent integration
if (acq_parameters.max_dwells == 1)
{
d_use_CFAR_algorithm_flag = acq_parameters.use_CFAR_algorithm_flag;
}
else
{
d_use_CFAR_algorithm_flag = false;
}
} }
@ -134,8 +156,10 @@ pcps_acquisition::~pcps_acquisition()
for (unsigned int i = 0; i < d_num_doppler_bins; i++) for (unsigned int i = 0; i < d_num_doppler_bins; i++)
{ {
volk_gnsssdr_free(d_grid_doppler_wipeoffs[i]); volk_gnsssdr_free(d_grid_doppler_wipeoffs[i]);
volk_gnsssdr_free(d_magnitude_grid[i]);
} }
delete[] d_grid_doppler_wipeoffs; delete[] d_grid_doppler_wipeoffs;
delete[] d_magnitude_grid;
} }
if (acq_parameters.make_2_steps) if (acq_parameters.make_2_steps)
{ {
@ -147,6 +171,8 @@ pcps_acquisition::~pcps_acquisition()
} }
volk_gnsssdr_free(d_fft_codes); volk_gnsssdr_free(d_fft_codes);
volk_gnsssdr_free(d_magnitude); volk_gnsssdr_free(d_magnitude);
volk_gnsssdr_free(d_tmp_buffer);
volk_gnsssdr_free(d_input_signal);
delete d_ifft; delete d_ifft;
delete d_fft_if; delete d_fft_if;
volk_gnsssdr_free(d_data_buffer); volk_gnsssdr_free(d_data_buffer);
@ -179,7 +205,15 @@ void pcps_acquisition::set_local_code(std::complex<float>* code)
} }
else else
{ {
memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_fft_size); if (acq_parameters.sampled_ms == acq_parameters.ms_per_code)
{
memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_consumed_samples);
}
else
{
std::fill_n(d_fft_if->get_inbuf(), d_fft_size - d_consumed_samples, gr_complex(0.0, 0.0));
memcpy(d_fft_if->get_inbuf() + d_consumed_samples, code, sizeof(gr_complex) * d_consumed_samples);
}
} }
d_fft_if->execute(); // We need the FFT of local code d_fft_if->execute(); // We need the FFT of local code
@ -244,12 +278,20 @@ void pcps_acquisition::init()
d_grid_doppler_wipeoffs_step_two[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_grid_doppler_wipeoffs_step_two[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
} }
} }
d_magnitude_grid = new float*[d_num_doppler_bins];
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{ {
d_grid_doppler_wipeoffs[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_grid_doppler_wipeoffs[doppler_index] = static_cast<gr_complex*>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude_grid[doppler_index] = static_cast<float*>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
for (unsigned k = 0; k < d_fft_size; k++)
{
d_magnitude_grid[doppler_index][k] = 0.0;
}
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index; int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_old_freq + doppler); update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_old_freq + doppler);
} }
d_worker_active = false; d_worker_active = false;
if (acq_parameters.dump) if (acq_parameters.dump)
@ -269,6 +311,7 @@ void pcps_acquisition::update_grid_doppler_wipeoffs()
} }
} }
void pcps_acquisition::update_grid_doppler_wipeoffs_step2() void pcps_acquisition::update_grid_doppler_wipeoffs_step2()
{ {
for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++) for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++)
@ -278,6 +321,7 @@ void pcps_acquisition::update_grid_doppler_wipeoffs_step2()
} }
} }
void pcps_acquisition::set_state(int state) void pcps_acquisition::set_state(int state)
{ {
gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
@ -288,7 +332,6 @@ void pcps_acquisition::set_state(int state)
d_gnss_synchro->Acq_doppler_hz = 0.0; d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_doppler_step = 0; d_gnss_synchro->Acq_doppler_step = 0;
d_gnss_synchro->Acq_samplestamp_samples = 0; d_gnss_synchro->Acq_samplestamp_samples = 0;
d_well_count = 0;
d_mag = 0.0; d_mag = 0.0;
d_input_power = 0.0; d_input_power = 0.0;
d_test_statistics = 0.0; d_test_statistics = 0.0;
@ -419,117 +462,202 @@ void pcps_acquisition::dump_results(int effective_fft_size)
} }
float pcps_acquisition::max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power, unsigned int num_doppler_bins, int doppler_max, int doppler_step)
{
float grid_maximum = 0.0;
unsigned int index_doppler = 0;
uint32_t tmp_intex_t = 0;
uint32_t index_time = 0;
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
// Find the correlation peak and the carrier frequency
for (unsigned int i = 0; i < num_doppler_bins; i++)
{
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_magnitude_grid[i], d_fft_size);
if (d_magnitude_grid[i][tmp_intex_t] > grid_maximum)
{
grid_maximum = d_magnitude_grid[i][tmp_intex_t];
index_doppler = i;
index_time = tmp_intex_t;
}
}
indext = index_time;
if (!d_step_two)
{
doppler = -static_cast<int>(doppler_max) + doppler_step * static_cast<int>(index_doppler);
}
else
{
doppler = static_cast<int>(d_doppler_center_step_two + (index_doppler - (acq_parameters.num_doppler_bins_step2 / 2.0) * acq_parameters.doppler_step2));
}
float magt = grid_maximum / (fft_normalization_factor * fft_normalization_factor);
return magt / input_power;
}
float pcps_acquisition::first_vs_second_peak_statistic(uint32_t& indext, int& doppler, unsigned int num_doppler_bins, int doppler_max, int doppler_step)
{
// Look for correlation peaks in the results
// Find the highest peak and compare it to the second highest peak
// The second peak is chosen not closer than 1 chip to the highest peak
float firstPeak = 0.0;
unsigned int index_doppler = 0;
uint32_t tmp_intex_t = 0;
uint32_t index_time = 0;
// Find the correlation peak and the carrier frequency
for (unsigned int i = 0; i < num_doppler_bins; i++)
{
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_magnitude_grid[i], d_fft_size);
if (d_magnitude_grid[i][tmp_intex_t] > firstPeak)
{
firstPeak = d_magnitude_grid[i][tmp_intex_t];
index_doppler = i;
index_time = tmp_intex_t;
}
}
indext = index_time;
if (!d_step_two)
{
doppler = -static_cast<int>(doppler_max) + doppler_step * static_cast<int>(index_doppler);
}
else
{
doppler = static_cast<int>(d_doppler_center_step_two + (index_doppler - (acq_parameters.num_doppler_bins_step2 / 2.0) * acq_parameters.doppler_step2));
}
// Find 1 chip wide code phase exclude range around the peak
int32_t excludeRangeIndex1 = index_time - d_samplesPerChip;
int32_t excludeRangeIndex2 = index_time + d_samplesPerChip;
// Correct code phase exclude range if the range includes array boundaries
if (excludeRangeIndex1 < 0)
{
excludeRangeIndex1 = d_fft_size + excludeRangeIndex1;
}
else if (excludeRangeIndex2 >= static_cast<int>(d_fft_size))
{
excludeRangeIndex2 = excludeRangeIndex2 - d_fft_size;
}
int32_t idx = excludeRangeIndex1;
memcpy(d_tmp_buffer, d_magnitude_grid[index_doppler], d_fft_size);
do
{
d_tmp_buffer[idx] = 0.0;
idx++;
if (idx == static_cast<int>(d_fft_size)) idx = 0;
}
while (idx != excludeRangeIndex2);
// Find the second highest correlation peak in the same freq. bin ---
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_tmp_buffer, d_fft_size);
float secondPeak = d_tmp_buffer[tmp_intex_t];
// Compute the test statistics and compare to the threshold
return firstPeak / secondPeak;
}
void pcps_acquisition::acquisition_core(unsigned long int samp_count) void pcps_acquisition::acquisition_core(unsigned long int samp_count)
{ {
gr::thread::scoped_lock lk(d_setlock); gr::thread::scoped_lock lk(d_setlock);
// initialize acquisition algorithm // initialize acquisition algorithm
int doppler = 0;
uint32_t indext = 0; uint32_t indext = 0;
float magt = 0.0;
const gr_complex* in = d_data_buffer; // Get the input samples pointer
int effective_fft_size = (acq_parameters.bit_transition_flag ? d_fft_size / 2 : d_fft_size); int effective_fft_size = (acq_parameters.bit_transition_flag ? d_fft_size / 2 : d_fft_size);
if (d_cshort) if (d_cshort)
{ {
volk_gnsssdr_16ic_convert_32fc(d_data_buffer, d_data_buffer_sc, d_fft_size); volk_gnsssdr_16ic_convert_32fc(d_data_buffer, d_data_buffer_sc, d_consumed_samples);
} }
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size); memcpy(d_input_signal, d_data_buffer, d_consumed_samples * sizeof(gr_complex));
if (d_fft_size > d_consumed_samples)
{
for (unsigned int i = d_consumed_samples; i < d_fft_size; i++)
{
d_input_signal[i] = gr_complex(0.0, 0.0);
}
}
const gr_complex* in = d_input_signal; // Get the input samples pointer
d_input_power = 0.0; d_input_power = 0.0;
d_mag = 0.0; d_mag = 0.0;
d_well_count++; d_num_noncoherent_integrations_counter++;
DLOG(INFO) << "Channel: " << d_channel DLOG(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< " ,sample stamp: " << samp_count << ", threshold: " << " ,sample stamp: " << samp_count << ", threshold: "
<< d_threshold << ", doppler_max: " << acq_parameters.doppler_max << d_threshold << ", doppler_max: " << acq_parameters.doppler_max
<< ", doppler_step: " << d_doppler_step << ", doppler_step: " << d_doppler_step
<< ", use_CFAR_algorithm_flag: " << (acq_parameters.use_CFAR_algorithm_flag ? "true" : "false"); << ", use_CFAR_algorithm_flag: " << (d_use_CFAR_algorithm_flag ? "true" : "false");
lk.unlock(); lk.unlock();
if (acq_parameters.use_CFAR_algorithm_flag)
if (d_use_CFAR_algorithm_flag or acq_parameters.bit_transition_flag)
{ {
// 1- (optional) Compute the input signal power estimation // Compute the input signal power estimation
volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); volk_32fc_magnitude_squared_32f(d_tmp_buffer, in, d_fft_size);
volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); volk_32f_accumulator_s32f(&d_input_power, d_tmp_buffer, d_fft_size);
d_input_power /= static_cast<float>(d_fft_size); d_input_power /= static_cast<float>(d_fft_size);
} }
// 2- Doppler frequency search loop
// Doppler frequency grid loop
if (!d_step_two) if (!d_step_two)
{ {
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{ {
// doppler search steps // Remove Doppler
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size); volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
// 3- Perform the FFT-based convolution (parallel time search) // Perform the FFT-based convolution (parallel time search)
// Compute the FFT of the carrier wiped--off incoming signal // Compute the FFT of the carrier wiped--off incoming signal
d_fft_if->execute(); d_fft_if->execute();
// Multiply carrier wiped--off, Fourier transformed incoming signal // Multiply carrier wiped--off, Fourier transformed incoming signal with the local FFT'd code reference
// with the local FFT'd code reference using SIMD operations with VOLK library
volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), d_fft_if->get_outbuf(), d_fft_codes, d_fft_size);
// compute the inverse FFT // Compute the inverse FFT
d_ifft->execute(); d_ifft->execute();
// Search maximum // Compute squared magnitude (and accumulate in case of non-coherent integration)
size_t offset = (acq_parameters.bit_transition_flag ? effective_fft_size : 0); size_t offset = (acq_parameters.bit_transition_flag ? effective_fft_size : 0);
volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); if (d_num_noncoherent_integrations_counter == 1)
volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size);
magt = d_magnitude[indext];
if (acq_parameters.use_CFAR_algorithm_flag)
{ {
// Normalize the maximum value to correct the scale factor introduced by FFTW volk_32fc_magnitude_squared_32f(d_magnitude_grid[doppler_index], d_ifft->get_outbuf() + offset, effective_fft_size);
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
} }
// 4- record the maximum peak and the associated synchronization parameters else
if (d_mag < magt)
{ {
d_mag = magt; volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_ifft->get_outbuf() + offset, effective_fft_size);
volk_32f_x2_add_32f(d_magnitude_grid[doppler_index], d_magnitude_grid[doppler_index], d_tmp_buffer, effective_fft_size);
if (!acq_parameters.use_CFAR_algorithm_flag)
{
// Search grid noise floor approximation for this doppler line
volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size);
d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1);
}
// In case that acq_parameters.bit_transition_flag = true, we compare the potentially
// new maximum test statistics (d_mag/d_input_power) with the value in
// d_test_statistics. When the second dwell is being processed, the value
// of d_mag/d_input_power could be lower than d_test_statistics (i.e,
// the maximum test statistics in the previous dwell is greater than
// current d_mag/d_input_power). Note that d_test_statistics is not
// restarted between consecutive dwells in multidwell operation.
if (d_test_statistics < (d_mag / d_input_power) or !acq_parameters.bit_transition_flag)
{
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext % acq_parameters.samples_per_code);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_gnss_synchro->Acq_samplestamp_samples = samp_count;
// 5- Compute the test statistics and compare to the threshold
//d_test_statistics = 2 * d_fft_size * d_mag / d_input_power;
d_test_statistics = d_mag / d_input_power;
}
} }
// Record results to file if required // Record results to file if required
if (acq_parameters.dump and d_channel == d_dump_channel) if (acq_parameters.dump and d_channel == d_dump_channel)
{ {
memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size); memcpy(grid_.colptr(doppler_index), d_magnitude_grid[doppler_index], sizeof(float) * effective_fft_size);
} }
} }
// Compute the test statistic
if (d_use_CFAR_algorithm_flag)
{
d_test_statistics = max_to_input_power_statistic(indext, doppler, d_input_power, d_num_doppler_bins, acq_parameters.doppler_max, d_doppler_step);
}
else
{
d_test_statistics = first_vs_second_peak_statistic(indext, doppler, d_num_doppler_bins, acq_parameters.doppler_max, d_doppler_step);
}
d_gnss_synchro->Acq_delay_samples = static_cast<double>(std::fmod(static_cast<float>(indext), acq_parameters.samples_per_code));
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_gnss_synchro->Acq_samplestamp_samples = samp_count;
} }
else else
{ {
for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++) for (unsigned int doppler_index = 0; doppler_index < acq_parameters.num_doppler_bins_step2; doppler_index++)
{ {
// doppler search steps
float doppler = d_doppler_center_step_two + (static_cast<float>(doppler_index) - static_cast<float>(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2;
volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs_step_two[doppler_index], d_fft_size); volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs_step_two[doppler_index], d_fft_size);
// 3- Perform the FFT-based convolution (parallel time search) // 3- Perform the FFT-based convolution (parallel time search)
@ -543,55 +671,31 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
// compute the inverse FFT // compute the inverse FFT
d_ifft->execute(); d_ifft->execute();
// Search maximum
size_t offset = (acq_parameters.bit_transition_flag ? effective_fft_size : 0); size_t offset = (acq_parameters.bit_transition_flag ? effective_fft_size : 0);
volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); if (d_num_noncoherent_integrations_counter == 1)
volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size);
magt = d_magnitude[indext];
if (acq_parameters.use_CFAR_algorithm_flag)
{ {
// Normalize the maximum value to correct the scale factor introduced by FFTW volk_32fc_magnitude_squared_32f(d_magnitude_grid[doppler_index], d_ifft->get_outbuf() + offset, effective_fft_size);
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
} }
// 4- record the maximum peak and the associated synchronization parameters else
if (d_mag < magt)
{ {
d_mag = magt; volk_32fc_magnitude_squared_32f(d_tmp_buffer, d_ifft->get_outbuf() + offset, effective_fft_size);
volk_32f_x2_add_32f(d_magnitude_grid[doppler_index], d_magnitude_grid[doppler_index], d_tmp_buffer, effective_fft_size);
if (!acq_parameters.use_CFAR_algorithm_flag)
{
// Search grid noise floor approximation for this doppler line
volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size);
d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1);
} }
}
// In case that acq_parameters.bit_transition_flag = true, we compare the potentially // Compute the test statistic
// new maximum test statistics (d_mag/d_input_power) with the value in if (d_use_CFAR_algorithm_flag)
// d_test_statistics. When the second dwell is being processed, the value
// of d_mag/d_input_power could be lower than d_test_statistics (i.e,
// the maximum test statistics in the previous dwell is greater than
// current d_mag/d_input_power). Note that d_test_statistics is not
// restarted between consecutive dwells in multidwell operation.
if (d_test_statistics < (d_mag / d_input_power) or !acq_parameters.bit_transition_flag)
{ {
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext % acq_parameters.samples_per_code); d_test_statistics = max_to_input_power_statistic(indext, doppler, d_input_power, acq_parameters.num_doppler_bins_step2, static_cast<int>(d_doppler_center_step_two - (static_cast<float>(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2), acq_parameters.doppler_step2);
}
else
{
d_test_statistics = first_vs_second_peak_statistic(indext, doppler, acq_parameters.num_doppler_bins_step2, static_cast<int>(d_doppler_center_step_two - (static_cast<float>(acq_parameters.num_doppler_bins_step2) / 2.0) * acq_parameters.doppler_step2), acq_parameters.doppler_step2);
}
d_gnss_synchro->Acq_delay_samples = static_cast<double>(std::fmod(static_cast<float>(indext), acq_parameters.samples_per_code));
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler); d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_gnss_synchro->Acq_samplestamp_samples = samp_count; d_gnss_synchro->Acq_samplestamp_samples = samp_count;
}
// 5- Compute the test statistics and compare to the threshold
//d_test_statistics = 2 * d_fft_size * d_mag / d_input_power;
d_test_statistics = d_mag / d_input_power;
}
}
// Record results to file if required
if (acq_parameters.dump and d_channel == d_dump_channel)
{
memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size);
}
}
}
lk.lock(); lk.lock();
if (!acq_parameters.bit_transition_flag) if (!acq_parameters.bit_transition_flag)
{ {
@ -618,12 +722,13 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
d_state = 0; // Positive acquisition d_state = 0; // Positive acquisition
} }
} }
else if (d_well_count == acq_parameters.max_dwells)
if (d_num_noncoherent_integrations_counter == acq_parameters.max_dwells)
{ {
if (d_state != 0) send_negative_acquisition();
d_state = 0; d_state = 0;
d_active = false; d_active = false;
d_step_two = false; d_step_two = false;
send_negative_acquisition();
} }
} }
else else
@ -659,11 +764,25 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
} }
} }
d_worker_active = false; d_worker_active = false;
if ((d_num_noncoherent_integrations_counter == acq_parameters.max_dwells) or (d_positive_acq == 1))
{
// Record results to file if required // Record results to file if required
if (acq_parameters.dump and d_channel == d_dump_channel) if (acq_parameters.dump and d_channel == d_dump_channel)
{ {
pcps_acquisition::dump_results(effective_fft_size); pcps_acquisition::dump_results(effective_fft_size);
} }
d_num_noncoherent_integrations_counter = 0;
d_positive_acq = 0;
// Reset grid
for (unsigned int i = 0; i < d_num_doppler_bins; i++)
{
for (unsigned k = 0; k < d_fft_size; k++)
{
d_magnitude_grid[i][k] = 0.0;
}
}
}
} }
@ -681,13 +800,12 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
* 5. Compute the test statistics and compare to the threshold * 5. Compute the test statistics and compare to the threshold
* 6. Declare positive or negative acquisition using a message port * 6. Declare positive or negative acquisition using a message port
*/ */
gr::thread::scoped_lock lk(d_setlock); gr::thread::scoped_lock lk(d_setlock);
if (!d_active or d_worker_active) if (!d_active or d_worker_active)
{ {
if (!acq_parameters.blocking_on_standby) if (!acq_parameters.blocking_on_standby)
{ {
d_sample_counter += d_fft_size * ninput_items[0]; d_sample_counter += d_consumed_samples * ninput_items[0];
consume_each(ninput_items[0]); consume_each(ninput_items[0]);
} }
if (d_step_two) if (d_step_two)
@ -708,14 +826,13 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
d_gnss_synchro->Acq_delay_samples = 0.0; d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0; d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0; d_gnss_synchro->Acq_samplestamp_samples = 0;
d_well_count = 0;
d_mag = 0.0; d_mag = 0.0;
d_input_power = 0.0; d_input_power = 0.0;
d_test_statistics = 0.0; d_test_statistics = 0.0;
d_state = 1; d_state = 1;
if (!acq_parameters.blocking_on_standby) if (!acq_parameters.blocking_on_standby)
{ {
d_sample_counter += d_fft_size * ninput_items[0]; // sample counter d_sample_counter += d_consumed_samples * ninput_items[0]; // sample counter
consume_each(ninput_items[0]); consume_each(ninput_items[0]);
} }
break; break;
@ -726,11 +843,11 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
// Copy the data to the core and let it know that new data is available // Copy the data to the core and let it know that new data is available
if (d_cshort) if (d_cshort)
{ {
memcpy(d_data_buffer_sc, input_items[0], d_fft_size * sizeof(lv_16sc_t)); memcpy(d_data_buffer_sc, input_items[0], d_consumed_samples * sizeof(lv_16sc_t));
} }
else else
{ {
memcpy(d_data_buffer, input_items[0], d_fft_size * sizeof(gr_complex)); memcpy(d_data_buffer, input_items[0], d_consumed_samples * sizeof(gr_complex));
} }
if (acq_parameters.blocking) if (acq_parameters.blocking)
{ {
@ -742,7 +859,7 @@ int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
gr::thread::thread d_worker(&pcps_acquisition::acquisition_core, this, d_sample_counter); gr::thread::thread d_worker(&pcps_acquisition::acquisition_core, this, d_sample_counter);
d_worker_active = true; d_worker_active = true;
} }
d_sample_counter += d_fft_size; d_sample_counter += d_consumed_samples;
consume_each(1); consume_each(1);
break; break;
} }

View File

@ -95,24 +95,33 @@ private:
void dump_results(int effective_fft_size); void dump_results(int effective_fft_size);
float first_vs_second_peak_statistic(uint32_t& indext, int& doppler, unsigned int num_doppler_bins, int doppler_max, int doppler_step);
float max_to_input_power_statistic(uint32_t& indext, int& doppler, float input_power, unsigned int num_doppler_bins, int doppler_max, int doppler_step);
Acq_Conf acq_parameters; Acq_Conf acq_parameters;
bool d_active; bool d_active;
bool d_worker_active; bool d_worker_active;
bool d_cshort; bool d_cshort;
bool d_step_two; bool d_step_two;
bool d_use_CFAR_algorithm_flag;
int d_positive_acq; int d_positive_acq;
float d_threshold; float d_threshold;
float d_mag; float d_mag;
float d_input_power; float d_input_power;
float d_test_statistics; float d_test_statistics;
float* d_magnitude; float* d_magnitude;
float** d_magnitude_grid;
float* d_tmp_buffer;
gr_complex* d_input_signal;
uint32_t d_samplesPerChip;
long d_old_freq; long d_old_freq;
int d_state; int d_state;
unsigned int d_channel; unsigned int d_channel;
unsigned int d_doppler_step; unsigned int d_doppler_step;
float d_doppler_center_step_two; float d_doppler_center_step_two;
unsigned int d_well_count; unsigned int d_num_noncoherent_integrations_counter;
unsigned int d_fft_size; unsigned int d_fft_size;
unsigned int d_consumed_samples;
unsigned int d_num_doppler_bins; unsigned int d_num_doppler_bins;
unsigned long int d_sample_counter; unsigned long int d_sample_counter;
gr_complex** d_grid_doppler_wipeoffs; gr_complex** d_grid_doppler_wipeoffs;
@ -150,7 +159,7 @@ public:
} }
/*! /*!
* \brief Initializes acquisition algorithm. * \brief Initializes acquisition algorithm and reserves memory.
*/ */
void init(); void init();

View File

@ -40,46 +40,41 @@
#include <volk_gnsssdr/volk_gnsssdr.h> #include <volk_gnsssdr/volk_gnsssdr.h>
#include <algorithm> // std::rotate, std::fill_n #include <algorithm> // std::rotate, std::fill_n
#include <sstream> #include <sstream>
#include <matio.h>
using google::LogMessage; using google::LogMessage;
pcps_acquisition_fine_doppler_cc_sptr pcps_make_acquisition_fine_doppler_cc( pcps_acquisition_fine_doppler_cc_sptr pcps_make_acquisition_fine_doppler_cc(const Acq_Conf &conf_)
int max_dwells, unsigned int sampled_ms, int doppler_max, int doppler_min,
long fs_in, int samples_per_ms, bool dump,
std::string dump_filename)
{ {
return pcps_acquisition_fine_doppler_cc_sptr( return pcps_acquisition_fine_doppler_cc_sptr(
new pcps_acquisition_fine_doppler_cc(max_dwells, sampled_ms, doppler_max, doppler_min, new pcps_acquisition_fine_doppler_cc(conf_));
fs_in, samples_per_ms, dump, dump_filename));
} }
pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc( pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(const Acq_Conf &conf_)
int max_dwells, unsigned int sampled_ms, int doppler_max, int doppler_min, : gr::block("pcps_acquisition_fine_doppler_cc",
long fs_in, int samples_per_ms, bool dump,
std::string dump_filename) : gr::block("pcps_acquisition_fine_doppler_cc",
gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(0, 0, sizeof(gr_complex))) gr::io_signature::make(0, 0, sizeof(gr_complex)))
{ {
this->message_port_register_out(pmt::mp("events")); this->message_port_register_out(pmt::mp("events"));
acq_parameters = conf_;
d_sample_counter = 0; // SAMPLE COUNTER d_sample_counter = 0; // SAMPLE COUNTER
d_active = false; d_active = false;
d_fs_in = fs_in; d_fs_in = conf_.fs_in;
d_samples_per_ms = samples_per_ms; d_samples_per_ms = conf_.samples_per_ms;
d_sampled_ms = sampled_ms; d_config_doppler_max = conf_.doppler_max;
d_config_doppler_max = doppler_max; d_fft_size = d_samples_per_ms;
d_config_doppler_min = doppler_min;
d_fft_size = d_sampled_ms * d_samples_per_ms;
// HS Acquisition // HS Acquisition
d_max_dwells = max_dwells; d_max_dwells = conf_.max_dwells;
d_gnuradio_forecast_samples = d_fft_size; d_gnuradio_forecast_samples = d_fft_size;
d_input_power = 0.0;
d_state = 0; d_state = 0;
d_carrier = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_carrier = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_fft_codes = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_fft_codes = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_magnitude = static_cast<float *>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); d_magnitude = static_cast<float *>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
d_10_ms_buffer = static_cast<gr_complex *>(volk_gnsssdr_malloc(50 * d_samples_per_ms * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
// Direct FFT // Direct FFT
d_fft_if = new gr::fft::fft_complex(d_fft_size, true); d_fft_if = new gr::fft::fft_complex(d_fft_size, true);
@ -87,10 +82,10 @@ pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(
d_ifft = new gr::fft::fft_complex(d_fft_size, false); d_ifft = new gr::fft::fft_complex(d_fft_size, false);
// For dumping samples into a file // For dumping samples into a file
d_dump = dump; d_dump = conf_.dump;
d_dump_filename = dump_filename; d_dump_filename = conf_.dump_filename;
d_doppler_resolution = 0; d_n_samples_in_buffer = 0;
d_threshold = 0; d_threshold = 0;
d_num_doppler_points = 0; d_num_doppler_points = 0;
d_doppler_step = 0; d_doppler_step = 0;
@ -102,21 +97,46 @@ pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(
d_test_statistics = 0; d_test_statistics = 0;
d_well_count = 0; d_well_count = 0;
d_channel = 0; d_channel = 0;
d_positive_acq = 0;
d_dump_number = 0;
d_dump_channel = 0; // this implementation can only produce dumps in channel 0
//todo: migrate config parameters to the unified acquisition config class
} }
// Finds next power of two
// for n. If n itself is a
// power of two then returns n
unsigned int pcps_acquisition_fine_doppler_cc::nextPowerOf2(unsigned int n)
{
n--;
n |= n >> 1;
n |= n >> 2;
n |= n >> 4;
n |= n >> 8;
n |= n >> 16;
n++;
return n;
}
void pcps_acquisition_fine_doppler_cc::set_doppler_step(unsigned int doppler_step) void pcps_acquisition_fine_doppler_cc::set_doppler_step(unsigned int doppler_step)
{ {
d_doppler_step = doppler_step; d_doppler_step = doppler_step;
// Create the search grid array // Create the search grid array
d_num_doppler_points = floor(std::abs(d_config_doppler_max - d_config_doppler_min) / d_doppler_step); d_num_doppler_points = floor(std::abs(2 * d_config_doppler_max) / d_doppler_step);
d_grid_data = new float *[d_num_doppler_points]; d_grid_data = new float *[d_num_doppler_points];
for (int i = 0; i < d_num_doppler_points; i++) for (int i = 0; i < d_num_doppler_points; i++)
{ {
d_grid_data[i] = static_cast<float *>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); d_grid_data[i] = static_cast<float *>(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment()));
} }
if (d_dump)
{
grid_ = arma::fmat(d_fft_size, d_num_doppler_points, arma::fill::zeros);
}
update_carrier_wipeoff(); update_carrier_wipeoff();
} }
@ -138,12 +158,9 @@ pcps_acquisition_fine_doppler_cc::~pcps_acquisition_fine_doppler_cc()
volk_gnsssdr_free(d_carrier); volk_gnsssdr_free(d_carrier);
volk_gnsssdr_free(d_fft_codes); volk_gnsssdr_free(d_fft_codes);
volk_gnsssdr_free(d_magnitude); volk_gnsssdr_free(d_magnitude);
volk_gnsssdr_free(d_10_ms_buffer);
delete d_ifft; delete d_ifft;
delete d_fft_if; delete d_fft_if;
if (d_dump)
{
d_dump_file.close();
}
free_grid_memory(); free_grid_memory();
} }
@ -167,7 +184,6 @@ void pcps_acquisition_fine_doppler_cc::init()
d_gnss_synchro->Acq_delay_samples = 0.0; d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0; d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0; d_gnss_synchro->Acq_samplestamp_samples = 0;
d_input_power = 0.0;
d_state = 0; d_state = 0;
} }
@ -187,6 +203,7 @@ void pcps_acquisition_fine_doppler_cc::reset_grid()
d_well_count = 0; d_well_count = 0;
for (int i = 0; i < d_num_doppler_points; i++) for (int i = 0; i < d_num_doppler_points; i++)
{ {
//todo: use memset here
for (unsigned int j = 0; j < d_fft_size; j++) for (unsigned int j = 0; j < d_fft_size; j++)
{ {
d_grid_data[i][j] = 0.0; d_grid_data[i][j] = 0.0;
@ -203,7 +220,7 @@ void pcps_acquisition_fine_doppler_cc::update_carrier_wipeoff()
d_grid_doppler_wipeoffs = new gr_complex *[d_num_doppler_points]; d_grid_doppler_wipeoffs = new gr_complex *[d_num_doppler_points];
for (int doppler_index = 0; doppler_index < d_num_doppler_points; doppler_index++) for (int doppler_index = 0; doppler_index < d_num_doppler_points; doppler_index++)
{ {
doppler_hz = d_config_doppler_min + d_doppler_step * doppler_index; doppler_hz = d_doppler_step * doppler_index - d_config_doppler_max;
// doppler search steps // doppler search steps
// compute the carrier doppler wipe-off signal and store it // compute the carrier doppler wipe-off signal and store it
phase_step_rad = static_cast<float>(GPS_TWO_PI) * doppler_hz / static_cast<float>(d_fs_in); phase_step_rad = static_cast<float>(GPS_TWO_PI) * doppler_hz / static_cast<float>(d_fs_in);
@ -215,52 +232,70 @@ void pcps_acquisition_fine_doppler_cc::update_carrier_wipeoff()
} }
double pcps_acquisition_fine_doppler_cc::search_maximum() double pcps_acquisition_fine_doppler_cc::compute_CAF()
{ {
float magt = 0.0; float firstPeak = 0.0;
float fft_normalization_factor;
int index_doppler = 0; int index_doppler = 0;
uint32_t tmp_intex_t = 0; uint32_t tmp_intex_t = 0;
uint32_t index_time = 0; uint32_t index_time = 0;
// Look for correlation peaks in the results ==============================
// Find the highest peak and compare it to the second highest peak
// The second peak is chosen not closer than 1 chip to the highest peak
//--- Find the correlation peak and the carrier frequency --------------
for (int i = 0; i < d_num_doppler_points; i++) for (int i = 0; i < d_num_doppler_points; i++)
{ {
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_grid_data[i], d_fft_size); volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_grid_data[i], d_fft_size);
if (d_grid_data[i][tmp_intex_t] > magt) if (d_grid_data[i][tmp_intex_t] > firstPeak)
{ {
magt = d_grid_data[i][tmp_intex_t]; firstPeak = d_grid_data[i][tmp_intex_t];
//std::cout<<magt<<std::endl;
index_doppler = i; index_doppler = i;
index_time = tmp_intex_t; index_time = tmp_intex_t;
} }
// Record results to file if required
if (d_dump and d_channel == d_dump_channel)
{
memcpy(grid_.colptr(i), d_grid_data[i], sizeof(float) * d_fft_size);
}
} }
// Normalize the maximum value to correct the scale factor introduced by FFTW // -- - Find 1 chip wide code phase exclude range around the peak
fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size); uint32_t samplesPerChip = ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(this->d_fs_in));
magt = magt / (fft_normalization_factor * fft_normalization_factor); int32_t excludeRangeIndex1 = index_time - samplesPerChip;
int32_t excludeRangeIndex2 = index_time + samplesPerChip;
// -- - Correct code phase exclude range if the range includes array boundaries
if (excludeRangeIndex1 < 0)
{
excludeRangeIndex1 = d_fft_size + excludeRangeIndex1;
}
else if (excludeRangeIndex2 >= static_cast<int>(d_fft_size))
{
excludeRangeIndex2 = excludeRangeIndex2 - d_fft_size;
}
int32_t idx = excludeRangeIndex1;
do
{
d_grid_data[index_doppler][idx] = 0.0;
idx++;
if (idx == static_cast<int>(d_fft_size)) idx = 0;
}
while (idx != excludeRangeIndex2);
//--- Find the second highest correlation peak in the same freq. bin ---
volk_gnsssdr_32f_index_max_32u(&tmp_intex_t, d_grid_data[index_doppler], d_fft_size);
float secondPeak = d_grid_data[index_doppler][tmp_intex_t];
// 5- Compute the test statistics and compare to the threshold // 5- Compute the test statistics and compare to the threshold
d_test_statistics = magt / (d_input_power * std::sqrt(d_well_count)); d_test_statistics = firstPeak / secondPeak;
// 4- record the maximum peak and the associated synchronization parameters // 4- record the maximum peak and the associated synchronization parameters
d_gnss_synchro->Acq_delay_samples = static_cast<double>(index_time); d_gnss_synchro->Acq_delay_samples = static_cast<double>(index_time);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(index_doppler * d_doppler_step + d_config_doppler_min); d_gnss_synchro->Acq_doppler_hz = static_cast<double>(index_doppler * d_doppler_step - d_config_doppler_max);
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
// Record results to file if required
if (d_dump)
{
std::stringstream filename;
std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write
filename.str("");
filename << "../data/test_statistics_" << d_gnss_synchro->System
<< "_" << d_gnss_synchro->Signal << "_sat_"
<< d_gnss_synchro->PRN << "_doppler_" << d_gnss_synchro->Acq_doppler_hz << ".dat";
d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary);
d_dump_file.write(reinterpret_cast<char *>(d_grid_data[index_doppler]), n); //write directly |abs(x)|^2 in this Doppler bin?
d_dump_file.close();
}
return d_test_statistics; return d_test_statistics;
} }
@ -296,6 +331,7 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
// doppler search steps // doppler search steps
// Perform the carrier wipe-off // Perform the carrier wipe-off
volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size); volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, d_grid_doppler_wipeoffs[doppler_index], d_fft_size);
// 3- Perform the FFT-based convolution (parallel time search) // 3- Perform the FFT-based convolution (parallel time search)
// Compute the FFT of the carrier wiped--off incoming signal // Compute the FFT of the carrier wiped--off incoming signal
d_fft_if->execute(); d_fft_if->execute();
@ -308,29 +344,38 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
d_ifft->execute(); d_ifft->execute();
// save the grid matrix delay file // save the grid matrix delay file
volk_32fc_magnitude_squared_32f(p_tmp_vector, d_ifft->get_outbuf(), d_fft_size); volk_32fc_magnitude_squared_32f(p_tmp_vector, d_ifft->get_outbuf(), d_fft_size);
const float *old_vector = d_grid_data[doppler_index]; //accumulate grid values
volk_32f_x2_add_32f(d_grid_data[doppler_index], old_vector, p_tmp_vector, d_fft_size); volk_32f_x2_add_32f(d_grid_data[doppler_index], d_grid_data[doppler_index], p_tmp_vector, d_fft_size);
} }
volk_gnsssdr_free(p_tmp_vector); volk_gnsssdr_free(p_tmp_vector);
return d_fft_size; return d_fft_size;
//debug
// std::cout << "iff=[";
// for (int n = 0; n < d_fft_size; n++)
// {
// std::cout << std::real(d_ifft->get_outbuf()[n]) << "+" << std::imag(d_ifft->get_outbuf()[n]) << "i,";
// }
// std::cout << "]\n";
// getchar();
} }
int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star &input_items) int pcps_acquisition_fine_doppler_cc::estimate_Doppler()
{ {
// Direct FFT // Direct FFT
int zero_padding_factor = 2; int zero_padding_factor = 8;
int fft_size_extended = d_fft_size * zero_padding_factor; int prn_replicas = 10;
int signal_samples = prn_replicas * d_fft_size;
//int fft_size_extended = nextPowerOf2(signal_samples * zero_padding_factor);
int fft_size_extended = signal_samples * zero_padding_factor;
gr::fft::fft_complex *fft_operator = new gr::fft::fft_complex(fft_size_extended, true); gr::fft::fft_complex *fft_operator = new gr::fft::fft_complex(fft_size_extended, true);
//zero padding the entire vector //zero padding the entire vector
std::fill_n(fft_operator->get_inbuf(), fft_size_extended, gr_complex(0.0, 0.0)); std::fill_n(fft_operator->get_inbuf(), fft_size_extended, gr_complex(0.0, 0.0));
//1. generate local code aligned with the acquisition code phase estimation //1. generate local code aligned with the acquisition code phase estimation
gr_complex *code_replica = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); gr_complex *code_replica = static_cast<gr_complex *>(volk_gnsssdr_malloc(signal_samples * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
gps_l1_ca_code_gen_complex_sampled(code_replica, d_gnss_synchro->PRN, d_fs_in, 0); gps_l1_ca_code_gen_complex_sampled(code_replica, d_gnss_synchro->PRN, d_fs_in, 0);
@ -342,10 +387,12 @@ int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star
std::rotate(code_replica, code_replica + (d_fft_size - shift_index), code_replica + d_fft_size - 1); std::rotate(code_replica, code_replica + (d_fft_size - shift_index), code_replica + d_fft_size - 1);
} }
for (int n = 0; n < prn_replicas - 1; n++)
{
memcpy(&code_replica[(n + 1) * d_fft_size], code_replica, d_fft_size * sizeof(gr_complex));
}
//2. Perform code wipe-off //2. Perform code wipe-off
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]); //Get the input samples pointer volk_32fc_x2_multiply_32fc(fft_operator->get_inbuf(), d_10_ms_buffer, code_replica, signal_samples);
volk_32fc_x2_multiply_32fc(fft_operator->get_inbuf(), in, code_replica, d_fft_size);
// 3. Perform the FFT (zero padded!) // 3. Perform the FFT (zero padded!)
fft_operator->execute(); fft_operator->execute();
@ -360,8 +407,8 @@ int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star
//case even //case even
int counter = 0; int counter = 0;
float *fftFreqBins = new float[fft_size_extended];
float fftFreqBins[fft_size_extended];
std::fill_n(fftFreqBins, fft_size_extended, 0.0); std::fill_n(fftFreqBins, fft_size_extended, 0.0);
for (int k = 0; k < (fft_size_extended / 2); k++) for (int k = 0; k < (fft_size_extended / 2); k++)
@ -372,7 +419,7 @@ int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star
for (int k = fft_size_extended / 2; k > 0; k--) for (int k = fft_size_extended / 2; k > 0; k--)
{ {
fftFreqBins[counter] = ((-static_cast<float>(d_fs_in) / 2) * static_cast<float>(k)) / (static_cast<float>(fft_size_extended) / 2.0); fftFreqBins[counter] = ((-static_cast<float>(d_fs_in) / 2.0) * static_cast<float>(k)) / (static_cast<float>(fft_size_extended) / 2.0);
counter++; counter++;
} }
@ -386,44 +433,50 @@ int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star
{ {
DLOG(INFO) << "Abs(Grid Doppler - FFT Doppler)=" << std::abs(fftFreqBins[tmp_index_freq] - d_gnss_synchro->Acq_doppler_hz); DLOG(INFO) << "Abs(Grid Doppler - FFT Doppler)=" << std::abs(fftFreqBins[tmp_index_freq] - d_gnss_synchro->Acq_doppler_hz);
DLOG(INFO) << "Error estimating fine frequency Doppler"; DLOG(INFO) << "Error estimating fine frequency Doppler";
//debug log
//
// std::cout<<"FFT maximum present at "<<fftFreqBins[tmp_index_freq]<<" [Hz]"<<std::endl;
// std::stringstream filename;
// std::streamsize n = sizeof(gr_complex) * (d_fft_size);
//
// filename.str("");
// filename << "../data/code_prn_" << d_gnss_synchro->PRN << ".dat";
// d_dump_file.open(filename.str().c_str(), std::ios::out
// | std::ios::binary);
// d_dump_file.write(reinterpret_cast<char*>(code_replica), n); //write directly |abs(x)|^2 in this Doppler bin?
// d_dump_file.close();
//
// filename.str("");
// filename << "../data/signal_prn_" << d_gnss_synchro->PRN << ".dat";
// d_dump_file.open(filename.str().c_str(), std::ios::out
// | std::ios::binary);
// d_dump_file.write(reinterpret_cast<char*>(in), n); //write directly |abs(x)|^2 in this Doppler bin?
// d_dump_file.close();
//
//
// n = sizeof(float) * (fft_size_extended);
// filename.str("");
// filename << "../data/fft_prn_" << d_gnss_synchro->PRN << ".dat";
// d_dump_file.open(filename.str().c_str(), std::ios::out
// | std::ios::binary);
// d_dump_file.write(reinterpret_cast<char*>(p_tmp_vector), n); //write directly |abs(x)|^2 in this Doppler bin?
// d_dump_file.close();
} }
// free memory!! // free memory!!
delete fft_operator; delete fft_operator;
volk_gnsssdr_free(code_replica); volk_gnsssdr_free(code_replica);
volk_gnsssdr_free(p_tmp_vector); volk_gnsssdr_free(p_tmp_vector);
delete[] fftFreqBins;
return d_fft_size; return d_fft_size;
} }
// Called by gnuradio to enable drivers, etc for i/o devices.
bool pcps_acquisition_fine_doppler_cc::start()
{
d_sample_counter = 0;
return true;
}
void pcps_acquisition_fine_doppler_cc::set_state(int state)
{
//gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler
d_state = state;
if (d_state == 1)
{
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0;
d_well_count = 0;
d_test_statistics = 0.0;
d_active = true;
reset_grid();
}
else if (d_state == 0)
{
}
else
{
LOG(ERROR) << "State can only be set to 0 or 1";
}
}
int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items, int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
gr_vector_int &ninput_items __attribute__((unused)), gr_vector_const_void_star &input_items, gr_vector_int &ninput_items __attribute__((unused)), gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items __attribute__((unused))) gr_vector_void_star &output_items __attribute__((unused)))
@ -442,29 +495,36 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
* S5. Negative_Acq: Send message and stop acq -> S0 * S5. Negative_Acq: Send message and stop acq -> S0
*/ */
int samples_remaining;
switch (d_state) switch (d_state)
{ {
case 0: // S0. StandBy case 0: // S0. StandBy
//DLOG(INFO) <<"S0"<<std::endl;
if (d_active == true) if (d_active == true)
{ {
reset_grid(); reset_grid();
d_n_samples_in_buffer = 0;
d_state = 1; d_state = 1;
} }
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += d_fft_size; // sample counter
consume_each(d_fft_size);
}
break; break;
case 1: // S1. ComputeGrid case 1: // S1. ComputeGrid
//DLOG(INFO) <<"S1"<<std::endl;
compute_and_accumulate_grid(input_items); compute_and_accumulate_grid(input_items);
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), d_fft_size * sizeof(gr_complex));
d_n_samples_in_buffer += d_fft_size;
d_well_count++; d_well_count++;
if (d_well_count >= d_max_dwells) if (d_well_count >= d_max_dwells)
{ {
d_state = 2; d_state = 2;
} }
d_sample_counter += d_fft_size; // sample counter
consume_each(d_fft_size);
break; break;
case 2: // Compute test statistics and decide case 2: // Compute test statistics and decide
//DLOG(INFO) <<"S2"<<std::endl; d_test_statistics = compute_CAF();
d_input_power = estimate_input_power(input_items);
d_test_statistics = search_maximum();
if (d_test_statistics > d_threshold) if (d_test_statistics > d_threshold)
{ {
d_state = 3; //perform fine doppler estimation d_state = 3; //perform fine doppler estimation
@ -472,16 +532,34 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
else else
{ {
d_state = 5; //negative acquisition d_state = 5; //negative acquisition
d_n_samples_in_buffer = 0;
} }
break; break;
case 3: // Fine doppler estimation case 3: // Fine doppler estimation
//DLOG(INFO) <<"S3"<<std::endl; samples_remaining = 10 * d_samples_per_ms - d_n_samples_in_buffer;
DLOG(INFO) << "Performing fine Doppler estimation";
estimate_Doppler(input_items); //disabled in repo if (samples_remaining > noutput_items)
{
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), noutput_items * sizeof(gr_complex));
d_n_samples_in_buffer += noutput_items;
d_sample_counter += noutput_items; // sample counter
consume_each(noutput_items);
}
else
{
if (samples_remaining > 0)
{
memcpy(&d_10_ms_buffer[d_n_samples_in_buffer], reinterpret_cast<const gr_complex *>(input_items[0]), samples_remaining * sizeof(gr_complex));
d_sample_counter += samples_remaining; // sample counter
consume_each(samples_remaining);
}
estimate_Doppler(); //disabled in repo
d_n_samples_in_buffer = 0;
d_state = 4; d_state = 4;
}
break; break;
case 4: // Positive_Acq case 4: // Positive_Acq
//DLOG(INFO) <<"S4"<<std::endl;
DLOG(INFO) << "positive acquisition"; DLOG(INFO) << "positive acquisition";
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
DLOG(INFO) << "sample_stamp " << d_sample_counter; DLOG(INFO) << "sample_stamp " << d_sample_counter;
@ -489,15 +567,23 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
DLOG(INFO) << "test statistics threshold " << d_threshold; DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
DLOG(INFO) << "input signal power " << d_input_power; d_positive_acq = 1;
d_active = false; d_active = false;
// Record results to file if required
if (d_dump and d_channel == d_dump_channel)
{
dump_results(d_fft_size);
}
// Send message to channel port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL // Send message to channel port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
d_state = 0; d_state = 0;
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += noutput_items; // sample counter
consume_each(noutput_items);
}
break; break;
case 5: // Negative_Acq case 5: // Negative_Acq
//DLOG(INFO) <<"S5"<<std::endl;
DLOG(INFO) << "negative acquisition"; DLOG(INFO) << "negative acquisition";
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
DLOG(INFO) << "sample_stamp " << d_sample_counter; DLOG(INFO) << "sample_stamp " << d_sample_counter;
@ -505,20 +591,108 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
DLOG(INFO) << "test statistics threshold " << d_threshold; DLOG(INFO) << "test statistics threshold " << d_threshold;
DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples;
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
DLOG(INFO) << "input signal power " << d_input_power; d_positive_acq = 0;
d_active = false; d_active = false;
// Record results to file if required
if (d_dump and d_channel == d_dump_channel)
{
dump_results(d_fft_size);
}
// Send message to channel port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL // Send message to channel port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
d_state = 0; d_state = 0;
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += noutput_items; // sample counter
consume_each(noutput_items);
}
break; break;
default: default:
d_state = 0; d_state = 0;
if (!acq_parameters.blocking_on_standby)
{
d_sample_counter += noutput_items; // sample counter
consume_each(noutput_items);
}
break; break;
} }
return 0;
//DLOG(INFO)<<"d_sample_counter="<<d_sample_counter<<std::endl; }
d_sample_counter += d_fft_size; // sample counter
consume_each(d_fft_size); void pcps_acquisition_fine_doppler_cc::dump_results(int effective_fft_size)
return noutput_items; {
d_dump_number++;
std::string filename = d_dump_filename;
filename.append("_");
filename.append(1, d_gnss_synchro->System);
filename.append("_");
filename.append(1, d_gnss_synchro->Signal[0]);
filename.append(1, d_gnss_synchro->Signal[1]);
filename.append("_ch_");
filename.append(std::to_string(d_channel));
filename.append("_");
filename.append(std::to_string(d_dump_number));
filename.append("_sat_");
filename.append(std::to_string(d_gnss_synchro->PRN));
filename.append(".mat");
mat_t *matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73);
if (matfp == NULL)
{
std::cout << "Unable to create or open Acquisition dump file" << std::endl;
d_dump = false;
}
else
{
size_t dims[2] = {static_cast<size_t>(effective_fft_size), static_cast<size_t>(d_num_doppler_points)};
matvar_t *matvar = Mat_VarCreate("acq_grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
dims[0] = static_cast<size_t>(1);
dims[1] = static_cast<size_t>(1);
matvar = Mat_VarCreate("doppler_max", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &d_config_doppler_max, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("doppler_step", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &d_doppler_step, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("d_positive_acq", MAT_C_INT32, MAT_T_INT32, 1, dims, &d_positive_acq, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
float aux = static_cast<float>(d_gnss_synchro->Acq_doppler_hz);
matvar = Mat_VarCreate("acq_doppler_hz", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &aux, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
aux = static_cast<float>(d_gnss_synchro->Acq_delay_samples);
matvar = Mat_VarCreate("acq_delay_samples", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &aux, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("test_statistic", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &d_test_statistics, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("threshold", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &d_threshold, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
aux = 0.0;
matvar = Mat_VarCreate("input_power", MAT_C_SINGLE, MAT_T_SINGLE, 1, dims, &aux, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("sample_counter", MAT_C_UINT64, MAT_T_UINT64, 1, dims, &d_sample_counter, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("PRN", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &d_gnss_synchro->PRN, 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
Mat_Close(matfp);
}
} }

View File

@ -1,8 +1,9 @@
/*! /*!
* \file pcps_acquisition_fine_doppler_acquisition_cc.h * \file pcps_acquisition_fine_doppler_acquisition_cc.h
* \brief This class implements a Parallel Code Phase Search Acquisition with multi-dwells and fine Doppler estimation * \brief This class implements a Parallel Code Phase Search Acquisition with multi-dwells and fine Doppler estimation
* for GPS L1 C/A signal
* *
* Acquisition strategy (Kay Borre book + CFAR threshold). * Acquisition strategy (Kay Borre book).
* <ol> * <ol>
* <li> Compute the input signal power estimation * <li> Compute the input signal power estimation
* <li> Doppler serial search loop * <li> Doppler serial search loop
@ -49,6 +50,8 @@
#define GNSS_SDR_PCPS_ACQUISITION_FINE_DOPPLER_CC_H_ #define GNSS_SDR_PCPS_ACQUISITION_FINE_DOPPLER_CC_H_
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "acq_conf.h"
#include <armadillo>
#include <gnuradio/block.h> #include <gnuradio/block.h>
#include <gnuradio/gr_complex.h> #include <gnuradio/gr_complex.h>
#include <gnuradio/fft/fft.h> #include <gnuradio/fft/fft.h>
@ -61,59 +64,44 @@ typedef boost::shared_ptr<pcps_acquisition_fine_doppler_cc>
pcps_acquisition_fine_doppler_cc_sptr; pcps_acquisition_fine_doppler_cc_sptr;
pcps_acquisition_fine_doppler_cc_sptr pcps_acquisition_fine_doppler_cc_sptr
pcps_make_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms, pcps_make_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
int doppler_max, int doppler_min, long fs_in, int samples_per_ms,
bool dump, std::string dump_filename);
/*! /*!
* \brief This class implements a Parallel Code Phase Search Acquisition. * \brief This class implements a Parallel Code Phase Search Acquisition.
* *
* Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver",
* Algorithm 1, for a pseudocode description of this implementation.
*/ */
class pcps_acquisition_fine_doppler_cc : public gr::block class pcps_acquisition_fine_doppler_cc : public gr::block
{ {
private: private:
friend pcps_acquisition_fine_doppler_cc_sptr friend pcps_acquisition_fine_doppler_cc_sptr
pcps_make_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms, pcps_make_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
int doppler_max, int doppler_min, long fs_in, pcps_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
int samples_per_ms, bool dump,
std::string dump_filename);
pcps_acquisition_fine_doppler_cc(int max_dwells, unsigned int sampled_ms,
int doppler_max, int doppler_min, long fs_in,
int samples_per_ms, bool dump,
std::string dump_filename);
void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift,
int doppler_offset);
int compute_and_accumulate_grid(gr_vector_const_void_star& input_items); int compute_and_accumulate_grid(gr_vector_const_void_star& input_items);
int estimate_Doppler(gr_vector_const_void_star& input_items); int estimate_Doppler();
float estimate_input_power(gr_vector_const_void_star& input_items); float estimate_input_power(gr_vector_const_void_star& input_items);
double search_maximum(); double compute_CAF();
void reset_grid(); void reset_grid();
void update_carrier_wipeoff(); void update_carrier_wipeoff();
void free_grid_memory(); void free_grid_memory();
bool start();
Acq_Conf acq_parameters;
long d_fs_in; long d_fs_in;
int d_samples_per_ms; int d_samples_per_ms;
int d_max_dwells; int d_max_dwells;
unsigned int d_doppler_resolution;
int d_gnuradio_forecast_samples; int d_gnuradio_forecast_samples;
float d_threshold; float d_threshold;
std::string d_satellite_str; std::string d_satellite_str;
int d_config_doppler_max; int d_config_doppler_max;
int d_config_doppler_min;
int d_num_doppler_points; int d_num_doppler_points;
int d_doppler_step; int d_doppler_step;
unsigned int d_sampled_ms;
unsigned int d_fft_size; unsigned int d_fft_size;
unsigned long int d_sample_counter; unsigned long int d_sample_counter;
gr_complex* d_carrier; gr_complex* d_carrier;
gr_complex* d_fft_codes; gr_complex* d_fft_codes;
gr_complex* d_10_ms_buffer;
float* d_magnitude; float* d_magnitude;
float** d_grid_data; float** d_grid_data;
@ -124,17 +112,22 @@ private:
Gnss_Synchro* d_gnss_synchro; Gnss_Synchro* d_gnss_synchro;
unsigned int d_code_phase; unsigned int d_code_phase;
float d_doppler_freq; float d_doppler_freq;
float d_input_power;
float d_test_statistics; float d_test_statistics;
std::ofstream d_dump_file; int d_positive_acq;
int d_state; int d_state;
bool d_active; bool d_active;
int d_well_count; int d_well_count;
int d_n_samples_in_buffer;
bool d_dump; bool d_dump;
unsigned int d_channel; unsigned int d_channel;
std::string d_dump_filename; std::string d_dump_filename;
arma::fmat grid_;
long int d_dump_number;
unsigned int d_dump_channel;
public: public:
/*! /*!
* \brief Default destructor. * \brief Default destructor.
@ -187,6 +180,7 @@ public:
inline void set_channel(unsigned int channel) inline void set_channel(unsigned int channel)
{ {
d_channel = channel; d_channel = channel;
d_dump_channel = d_channel;
} }
/*! /*!
@ -214,6 +208,13 @@ public:
*/ */
void set_doppler_step(unsigned int doppler_step); void set_doppler_step(unsigned int doppler_step);
/*!
* \brief If set to 1, ensures that acquisition starts at the
* first available sample.
* \param state - int=1 forces start of acquisition
*/
void set_state(int state);
/*! /*!
* \brief Parallel Code Phase Search Acquisition signal processing. * \brief Parallel Code Phase Search Acquisition signal processing.
*/ */
@ -222,6 +223,14 @@ public:
gr_vector_void_star& output_items); gr_vector_void_star& output_items);
void forecast(int noutput_items, gr_vector_int& ninput_items_required); void forecast(int noutput_items, gr_vector_int& ninput_items_required);
/*!
* \brief Obtains the next power of 2 greater or equal to the input parameter
* \param n - Integer value to obtain the next power of 2.
*/
unsigned int nextPowerOf2(unsigned int n);
void dump_results(int effective_fft_size);
}; };
#endif /* pcps_acquisition_fine_doppler_cc*/ #endif /* pcps_acquisition_fine_doppler_cc*/

View File

@ -35,13 +35,15 @@ Acq_Conf::Acq_Conf()
{ {
/* PCPS acquisition configuration */ /* PCPS acquisition configuration */
sampled_ms = 0; sampled_ms = 0;
ms_per_code = 0;
max_dwells = 0; max_dwells = 0;
samples_per_chip = 0;
doppler_max = 0; doppler_max = 0;
num_doppler_bins_step2 = 0; num_doppler_bins_step2 = 0;
doppler_step2 = 0.0; doppler_step2 = 0.0;
fs_in = 0; fs_in = 0;
samples_per_ms = 0; samples_per_ms = 0.0;
samples_per_code = 0; samples_per_code = 0.0;
bit_transition_flag = false; bit_transition_flag = false;
use_CFAR_algorithm_flag = false; use_CFAR_algorithm_flag = false;
dump = false; dump = false;

View File

@ -40,13 +40,15 @@ class Acq_Conf
public: public:
/* PCPS Acquisition configuration */ /* PCPS Acquisition configuration */
unsigned int sampled_ms; unsigned int sampled_ms;
unsigned int ms_per_code;
unsigned int samples_per_chip;
unsigned int max_dwells; unsigned int max_dwells;
unsigned int doppler_max; unsigned int doppler_max;
unsigned int num_doppler_bins_step2; unsigned int num_doppler_bins_step2;
float doppler_step2; float doppler_step2;
long fs_in; long fs_in;
int samples_per_ms; float samples_per_ms;
int samples_per_code; float samples_per_code;
bool bit_transition_flag; bool bit_transition_flag;
bool use_CFAR_algorithm_flag; bool use_CFAR_algorithm_flag;
bool dump; bool dump;

View File

@ -144,6 +144,7 @@ void gps_l1_ca_code_gen_complex(std::complex<float>* _dest, signed int _prn, uns
/* /*
* Generates complex GPS L1 C/A code for the desired SV ID and sampled to specific sampling frequency * Generates complex GPS L1 C/A code for the desired SV ID and sampled to specific sampling frequency
* NOTICE: the number of samples is rounded towards zero (integer truncation)
*/ */
void gps_l1_ca_code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, signed int _fs, unsigned int _chip_shift) void gps_l1_ca_code_gen_complex_sampled(std::complex<float>* _dest, unsigned int _prn, signed int _fs, unsigned int _chip_shift)
{ {

View File

@ -83,26 +83,20 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(
} }
} }
d_stat = 0; d_stat = 0;
d_symbol_accumulator = 0;
d_symbol_accumulator_counter = 0;
d_frame_bit_index = 0;
d_flag_frame_sync = false; d_flag_frame_sync = false;
d_GPS_frame_4bytes = 0;
d_prev_GPS_frame_4bytes = 0; d_prev_GPS_frame_4bytes = 0;
d_flag_parity = false;
d_TOW_at_Preamble_ms = 0; d_TOW_at_Preamble_ms = 0;
flag_TOW_set = false; flag_TOW_set = false;
d_flag_preamble = false; d_flag_preamble = false;
d_flag_new_tow_available = false; d_flag_new_tow_available = false;
d_word_number = 0;
d_channel = 0; d_channel = 0;
flag_PLL_180_deg_phase_locked = false; flag_PLL_180_deg_phase_locked = false;
d_preamble_time_samples = 0; d_preamble_time_samples = 0;
d_TOW_at_current_symbol_ms = 0; d_TOW_at_current_symbol_ms = 0;
d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS + 1); // Change fixed buffer size d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size
d_symbol_history.clear(); // Clear all the elements in the buffer d_symbol_history.clear(); // Clear all the elements in the buffer
d_make_correlation = true; d_crc_error_synchronization_counter = 0;
d_symbol_counter_corr = 0; d_current_subframe_symbol = 0;
} }
@ -150,9 +144,10 @@ bool gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(unsigned int gpsword)
void gps_l1_ca_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite) void gps_l1_ca_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{ {
d_nav.reset();
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite; DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite;
d_GPS_FSM.i_satellite_PRN = d_satellite.get_PRN(); d_nav.i_satellite_PRN = d_satellite.get_PRN();
DLOG(INFO) << "Navigation Satellite set to " << d_satellite; DLOG(INFO) << "Navigation Satellite set to " << d_satellite;
} }
@ -160,7 +155,7 @@ void gps_l1_ca_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satelli
void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel) void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel)
{ {
d_channel = channel; d_channel = channel;
d_GPS_FSM.i_channel_ID = channel; d_nav.i_channel_ID = channel;
DLOG(INFO) << "Navigation channel set to " << channel; DLOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG ################# // ############# ENABLE DATA FILE LOG #################
if (d_dump == true) if (d_dump == true)
@ -186,10 +181,127 @@ void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel)
} }
bool gps_l1_ca_telemetry_decoder_cc::decode_subframe()
{
char subframe[GPS_SUBFRAME_LENGTH];
int symbol_accumulator_counter = 0;
int frame_bit_index = 0;
int word_index = 0;
uint32_t GPS_frame_4bytes = 0;
float symbol_accumulator = 0;
bool subframe_synchro_confirmation = false;
bool CRC_ok = true;
for (int n = 0; n < GPS_SUBFRAME_MS; n++)
{
//******* SYMBOL TO BIT *******
// extended correlation to bit period is enabled in tracking!
symbol_accumulator += d_subframe_symbols[n]; // accumulate the input value in d_symbol_accumulator
symbol_accumulator_counter++;
if (symbol_accumulator_counter == 20)
{
//symbol to bit
if (symbol_accumulator > 0) GPS_frame_4bytes += 1; //insert the telemetry bit in LSB
symbol_accumulator = 0;
symbol_accumulator_counter = 0;
//******* bits to words ******
frame_bit_index++;
if (frame_bit_index == 30)
{
frame_bit_index = 0;
// parity check
// Each word in wordbuff is composed of:
// Bits 0 to 29 = the GPS data word
// Bits 30 to 31 = 2 LSBs of the GPS word ahead.
// prepare the extended frame [-2 -1 0 ... 30]
if (d_prev_GPS_frame_4bytes & 0x00000001)
{
GPS_frame_4bytes = GPS_frame_4bytes | 0x40000000;
}
if (d_prev_GPS_frame_4bytes & 0x00000002)
{
GPS_frame_4bytes = GPS_frame_4bytes | 0x80000000;
}
/* Check that the 2 most recently logged words pass parity. Have to first
invert the data bits according to bit 30 of the previous word. */
if (GPS_frame_4bytes & 0x40000000)
{
GPS_frame_4bytes ^= 0x3FFFFFC0; // invert the data bits (using XOR)
}
if (gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(GPS_frame_4bytes))
{
subframe_synchro_confirmation = true;
}
else
{
//std::cout << "word invalid sat " << this->d_satellite << std::endl;
CRC_ok = false;
}
//add word to subframe
// insert the word in the correct position of the subframe
std::memcpy(&subframe[word_index * GPS_WORD_LENGTH], &GPS_frame_4bytes, sizeof(uint32_t));
word_index++;
d_prev_GPS_frame_4bytes = GPS_frame_4bytes; // save the actual frame
GPS_frame_4bytes = 0;
}
else
{
GPS_frame_4bytes <<= 1; //shift 1 bit left the telemetry word
}
}
}
//decode subframe
// NEW GPS SUBFRAME HAS ARRIVED!
if (CRC_ok)
{
int subframe_ID = d_nav.subframe_decoder(subframe); //decode the subframe
std::cout << "New GPS NAV message received in channel " << this->d_channel << ": "
<< "subframe "
<< subframe_ID << " from satellite "
<< Gnss_Satellite(std::string("GPS"), d_nav.i_satellite_PRN) << std::endl;
switch (subframe_ID)
{
case 3: //we have a new set of ephemeris data for the current SV
if (d_nav.satellite_validation() == true)
{
// get ephemeris object for this SV (mandatory)
std::shared_ptr<Gps_Ephemeris> tmp_obj = std::make_shared<Gps_Ephemeris>(d_nav.get_ephemeris());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
case 4: // Possible IONOSPHERE and UTC model update (page 18)
if (d_nav.flag_iono_valid == true)
{
std::shared_ptr<Gps_Iono> tmp_obj = std::make_shared<Gps_Iono>(d_nav.get_iono());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_nav.flag_utc_model_valid == true)
{
std::shared_ptr<Gps_Utc_Model> tmp_obj = std::make_shared<Gps_Utc_Model>(d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
case 5:
// get almanac (if available)
//TODO: implement almanac reader in navigation_message
break;
default:
break;
}
d_flag_new_tow_available = true;
}
return subframe_synchro_confirmation;
}
int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)), int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{ {
int corr_value = 0;
int preamble_diff_ms = 0; int preamble_diff_ms = 0;
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
@ -198,15 +310,25 @@ int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__
Gnss_Synchro current_symbol; //structure to save the synchronization information and send the output object to the next block Gnss_Synchro current_symbol; //structure to save the synchronization information and send the output object to the next block
//1. Copy the current tracking output //1. Copy the current tracking output
current_symbol = in[0][0]; current_symbol = in[0][0];
//record the oldest subframe symbol before inserting a new symbol into the circular buffer
if (d_current_subframe_symbol < GPS_SUBFRAME_MS and d_symbol_history.size() > 0)
{
d_subframe_symbols[d_current_subframe_symbol] = d_symbol_history.at(0).Prompt_I;
d_current_subframe_symbol++;
}
d_symbol_history.push_back(current_symbol); //add new symbol to the symbol queue d_symbol_history.push_back(current_symbol); //add new symbol to the symbol queue
consume_each(1); consume_each(1);
unsigned int required_symbols = GPS_CA_PREAMBLE_LENGTH_SYMBOLS;
d_flag_preamble = false; d_flag_preamble = false;
if ((d_symbol_history.size() > required_symbols) and (d_make_correlation or !d_flag_frame_sync))
{
//******* preamble correlation ******** //******* preamble correlation ********
int corr_value = 0;
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync))
{
// std::cout << "-------\n";
for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++) for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
{ {
if (d_symbol_history.at(i).Flag_valid_symbol_output == true) if (d_symbol_history.at(i).Flag_valid_symbol_output == true)
@ -221,38 +343,27 @@ int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__
} }
} }
} }
if (std::abs(corr_value) >= GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
{
d_symbol_counter_corr++;
}
} }
//******* frame sync ****************** //******* frame sync ******************
if (std::abs(corr_value) == GPS_CA_PREAMBLE_LENGTH_SYMBOLS) if (std::abs(corr_value) == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
{ {
//TODO: Rewrite with state machine //TODO: Rewrite with state machine
if (d_stat == 0) if (d_stat == 0)
{ {
d_GPS_FSM.Event_gps_word_preamble();
//record the preamble sample stamp //record the preamble sample stamp
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp
DLOG(INFO) << "Preamble detection for SAT " << this->d_satellite << "d_symbol_history.at(0).Tracking_sample_counter=" << d_symbol_history.at(0).Tracking_sample_counter; DLOG(INFO) << "Preamble detection for SAT " << this->d_satellite << "d_symbol_history.at(0).Tracking_sample_counter=" << d_symbol_history.at(0).Tracking_sample_counter;
//sync the symbol to bits integrator
d_symbol_accumulator = 0;
d_symbol_accumulator_counter = 0;
d_frame_bit_index = 0;
d_stat = 1; // enter into frame pre-detection status d_stat = 1; // enter into frame pre-detection status
} }
else if (d_stat == 1) //check 6 seconds of preamble separation else if (d_stat == 1) //check 6 seconds of preamble separation
{ {
preamble_diff_ms = std::round(((static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter) - d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs)) * 1000.0); preamble_diff_ms = std::round(((static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter) - d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs)) * 1000.0);
if (std::abs(preamble_diff_ms - GPS_SUBFRAME_MS) < 1) if (std::abs(preamble_diff_ms - GPS_SUBFRAME_MS) % GPS_SUBFRAME_MS == 0)
{ {
DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite; DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite;
d_GPS_FSM.Event_gps_word_preamble();
d_flag_preamble = true; d_flag_preamble = true;
d_make_correlation = false;
d_symbol_counter_corr = 0;
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the PRN start sample index associated to the preamble d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the PRN start sample index associated to the preamble
if (!d_flag_frame_sync) if (!d_flag_frame_sync)
{ {
@ -269,131 +380,46 @@ int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at " DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< static_cast<double>(d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs) << " [s]"; << static_cast<double>(d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs) << " [s]";
} }
}
} //try to decode the subframe:
} if (decode_subframe() == false)
else
{ {
d_symbol_counter_corr++; d_crc_error_synchronization_counter++;
if (d_symbol_counter_corr > (GPS_SUBFRAME_MS - GPS_CA_TELEMETRY_SYMBOLS_PER_BIT)) if (d_crc_error_synchronization_counter > 3)
{ {
d_make_correlation = true; DLOG(INFO) << "TOO MANY CRC ERRORS: Lost of frame sync SAT " << this->d_satellite << std::endl;
}
if (d_stat == 1)
{
preamble_diff_ms = round(((static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter) - static_cast<double>(d_preamble_time_samples)) / static_cast<double>(d_symbol_history.at(0).fs)) * 1000.0);
if (preamble_diff_ms > GPS_SUBFRAME_MS + 1)
{
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms;
d_stat = 0; //lost of frame sync d_stat = 0; //lost of frame sync
d_flag_frame_sync = false; d_flag_frame_sync = false;
flag_TOW_set = false; flag_TOW_set = false;
d_make_correlation = true; d_crc_error_synchronization_counter = 0;
d_symbol_counter_corr = 0;
} }
} }
d_current_subframe_symbol = 0;
} }
//******* SYMBOL TO BIT *******
if (d_symbol_history.at(0).Flag_valid_symbol_output == true)
{
// extended correlation to bit period is enabled in tracking!
d_symbol_accumulator += d_symbol_history.at(0).Prompt_I; // accumulate the input value in d_symbol_accumulator
d_symbol_accumulator_counter += d_symbol_history.at(0).correlation_length_ms;
} }
if (d_symbol_accumulator_counter >= 20)
{
if (d_symbol_accumulator > 0)
{ //symbol to bit
d_GPS_frame_4bytes += 1; //insert the telemetry bit in LSB
}
d_symbol_accumulator = 0;
d_symbol_accumulator_counter = 0;
//******* bits to words ******
d_frame_bit_index++;
if (d_frame_bit_index == 30)
{
d_frame_bit_index = 0;
// parity check
// Each word in wordbuff is composed of:
// Bits 0 to 29 = the GPS data word
// Bits 30 to 31 = 2 LSBs of the GPS word ahead.
// prepare the extended frame [-2 -1 0 ... 30]
if (d_prev_GPS_frame_4bytes & 0x00000001)
{
d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x40000000;
}
if (d_prev_GPS_frame_4bytes & 0x00000002)
{
d_GPS_frame_4bytes = d_GPS_frame_4bytes | 0x80000000;
}
/* Check that the 2 most recently logged words pass parity. Have to first
invert the data bits according to bit 30 of the previous word. */
if (d_GPS_frame_4bytes & 0x40000000)
{
d_GPS_frame_4bytes ^= 0x3FFFFFC0; // invert the data bits (using XOR)
}
if (gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(d_GPS_frame_4bytes))
{
memcpy(&d_GPS_FSM.d_GPS_frame_4bytes, &d_GPS_frame_4bytes, sizeof(char) * 4);
//d_GPS_FSM.d_preamble_time_ms = d_preamble_time_seconds * 1000.0;
d_GPS_FSM.Event_gps_word_valid();
// send TLM data to PVT using asynchronous message queues
if (d_GPS_FSM.d_flag_new_subframe == true)
{
switch (d_GPS_FSM.d_subframe_ID)
{
case 3: //we have a new set of ephemeris data for the current SV
if (d_GPS_FSM.d_nav.satellite_validation() == true)
{
// get ephemeris object for this SV (mandatory)
std::shared_ptr<Gps_Ephemeris> tmp_obj = std::make_shared<Gps_Ephemeris>(d_GPS_FSM.d_nav.get_ephemeris());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
case 4: // Possible IONOSPHERE and UTC model update (page 18)
if (d_GPS_FSM.d_nav.flag_iono_valid == true)
{
std::shared_ptr<Gps_Iono> tmp_obj = std::make_shared<Gps_Iono>(d_GPS_FSM.d_nav.get_iono());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
if (d_GPS_FSM.d_nav.flag_utc_model_valid == true)
{
std::shared_ptr<Gps_Utc_Model> tmp_obj = std::make_shared<Gps_Utc_Model>(d_GPS_FSM.d_nav.get_utc_model());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
}
break;
case 5:
// get almanac (if available)
//TODO: implement almanac reader in navigation_message
break;
default:
break;
}
d_GPS_FSM.clear_flag_new_subframe();
d_flag_new_tow_available = true;
}
d_flag_parity = true;
} }
else else
{ {
d_GPS_FSM.Event_gps_word_invalid(); if (d_stat == 1)
d_flag_parity = false;
}
d_prev_GPS_frame_4bytes = d_GPS_frame_4bytes; // save the actual frame
d_GPS_frame_4bytes = d_GPS_frame_4bytes & 0;
}
else
{ {
d_GPS_frame_4bytes <<= 1; //shift 1 bit left the telemetry word preamble_diff_ms = round(((static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter) - static_cast<double>(d_preamble_time_samples)) / static_cast<double>(d_symbol_history.at(0).fs)) * 1000.0);
if (preamble_diff_ms > GPS_SUBFRAME_MS)
{
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms;
// std::cout << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms << std::endl;
d_stat = 0; //lost of frame sync
d_flag_frame_sync = false;
flag_TOW_set = false;
d_current_subframe_symbol = 0;
d_crc_error_synchronization_counter = 0;
}
} }
} }
//2. Add the telemetry decoder information //2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_flag_new_tow_available == true) if (this->d_flag_preamble == true and d_flag_new_tow_available == true)
{ {
d_TOW_at_current_symbol_ms = static_cast<unsigned int>(d_GPS_FSM.d_nav.d_TOW) * 1000 + GPS_L1_CA_CODE_PERIOD_MS + GPS_CA_PREAMBLE_DURATION_MS; d_TOW_at_current_symbol_ms = static_cast<unsigned int>(d_nav.d_TOW) * 1000 + GPS_L1_CA_CODE_PERIOD_MS + GPS_CA_PREAMBLE_DURATION_MS;
d_TOW_at_Preamble_ms = d_TOW_at_current_symbol_ms; d_TOW_at_Preamble_ms = d_TOW_at_current_symbol_ms;
flag_TOW_set = true; flag_TOW_set = true;
d_flag_new_tow_available = false; d_flag_new_tow_available = false;

View File

@ -32,7 +32,7 @@
#define GNSS_SDR_GPS_L1_CA_TELEMETRY_DECODER_CC_H #define GNSS_SDR_GPS_L1_CA_TELEMETRY_DECODER_CC_H
#include "GPS_L1_CA.h" #include "GPS_L1_CA.h"
#include "gps_l1_ca_subframe_fsm.h" #include "gps_navigation_message.h"
#include "gnss_satellite.h" #include "gnss_satellite.h"
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include <gnuradio/block.h> #include <gnuradio/block.h>
@ -72,7 +72,9 @@ private:
bool gps_word_parityCheck(unsigned int gpsword); bool gps_word_parityCheck(unsigned int gpsword);
// class private vars bool decode_subframe();
bool new_decoder();
int d_crc_error_synchronization_counter;
int *d_preambles_symbols; int *d_preambles_symbols;
unsigned int d_stat; unsigned int d_stat;
@ -80,26 +82,16 @@ private:
// symbols // symbols
boost::circular_buffer<Gnss_Synchro> d_symbol_history; boost::circular_buffer<Gnss_Synchro> d_symbol_history;
float d_subframe_symbols[GPS_SUBFRAME_MS]; //symbols per subframe
double d_symbol_accumulator; int d_current_subframe_symbol;
short int d_symbol_accumulator_counter;
// symbol counting
bool d_make_correlation;
unsigned int d_symbol_counter_corr;
//bits and frame //bits and frame
unsigned short int d_frame_bit_index;
unsigned int d_GPS_frame_4bytes;
unsigned int d_prev_GPS_frame_4bytes; unsigned int d_prev_GPS_frame_4bytes;
bool d_flag_parity;
bool d_flag_preamble; bool d_flag_preamble;
bool d_flag_new_tow_available; bool d_flag_new_tow_available;
int d_word_number;
// navigation message vars // navigation message vars
Gps_Navigation_Message d_nav; Gps_Navigation_Message d_nav;
GpsL1CaSubframeFsm d_GPS_FSM;
bool d_dump; bool d_dump;
Gnss_Satellite d_satellite; Gnss_Satellite d_satellite;

View File

@ -19,7 +19,6 @@
add_subdirectory(libswiftcnav) add_subdirectory(libswiftcnav)
set(TELEMETRY_DECODER_LIB_SOURCES set(TELEMETRY_DECODER_LIB_SOURCES
gps_l1_ca_subframe_fsm.cc
viterbi_decoder.cc viterbi_decoder.cc
) )

View File

@ -1,289 +0,0 @@
/*!
* \file gps_l1_ca_subframe_fsm.cc
* \brief Implementation of a GPS NAV message word-to-subframe decoder state machine
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l1_ca_subframe_fsm.h"
#include "gnss_satellite.h"
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <boost/mpl/list.hpp>
#include <string>
//************ GPS WORD TO SUBFRAME DECODER STATE MACHINE **********
struct Ev_gps_word_valid : sc::event<Ev_gps_word_valid>
{
};
struct Ev_gps_word_invalid : sc::event<Ev_gps_word_invalid>
{
};
struct Ev_gps_word_preamble : sc::event<Ev_gps_word_preamble>
{
};
struct gps_subframe_fsm_S0 : public sc::state<gps_subframe_fsm_S0, GpsL1CaSubframeFsm>
{
public:
// sc::transition(event,next_status)
typedef sc::transition<Ev_gps_word_preamble, gps_subframe_fsm_S1> reactions;
gps_subframe_fsm_S0(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S0 "<<std::endl;
}
};
struct gps_subframe_fsm_S1 : public sc::state<gps_subframe_fsm_S1, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S2> >
reactions;
gps_subframe_fsm_S1(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S1 "<<std::endl;
}
};
struct gps_subframe_fsm_S2 : public sc::state<gps_subframe_fsm_S2, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S3> >
reactions;
gps_subframe_fsm_S2(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S2 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(0);
}
};
struct gps_subframe_fsm_S3 : public sc::state<gps_subframe_fsm_S3, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S4> >
reactions;
gps_subframe_fsm_S3(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S3 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(1);
}
};
struct gps_subframe_fsm_S4 : public sc::state<gps_subframe_fsm_S4, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S5> >
reactions;
gps_subframe_fsm_S4(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S4 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(2);
}
};
struct gps_subframe_fsm_S5 : public sc::state<gps_subframe_fsm_S5, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S6> >
reactions;
gps_subframe_fsm_S5(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S5 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(3);
}
};
struct gps_subframe_fsm_S6 : public sc::state<gps_subframe_fsm_S6, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S7> >
reactions;
gps_subframe_fsm_S6(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S6 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(4);
}
};
struct gps_subframe_fsm_S7 : public sc::state<gps_subframe_fsm_S7, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S8> >
reactions;
gps_subframe_fsm_S7(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S7 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(5);
}
};
struct gps_subframe_fsm_S8 : public sc::state<gps_subframe_fsm_S8, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S9> >
reactions;
gps_subframe_fsm_S8(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S8 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(6);
}
};
struct gps_subframe_fsm_S9 : public sc::state<gps_subframe_fsm_S9, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S10> >
reactions;
gps_subframe_fsm_S9(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S9 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(7);
}
};
struct gps_subframe_fsm_S10 : public sc::state<gps_subframe_fsm_S10, GpsL1CaSubframeFsm>
{
public:
typedef mpl::list<sc::transition<Ev_gps_word_invalid, gps_subframe_fsm_S0>,
sc::transition<Ev_gps_word_valid, gps_subframe_fsm_S11> >
reactions;
gps_subframe_fsm_S10(my_context ctx) : my_base(ctx)
{
//std::cout<<"Enter S10 "<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(8);
}
};
struct gps_subframe_fsm_S11 : public sc::state<gps_subframe_fsm_S11, GpsL1CaSubframeFsm>
{
public:
typedef sc::transition<Ev_gps_word_preamble, gps_subframe_fsm_S1> reactions;
gps_subframe_fsm_S11(my_context ctx) : my_base(ctx)
{
//std::cout<<"Completed GPS Subframe!"<<std::endl;
context<GpsL1CaSubframeFsm>().gps_word_to_subframe(9);
context<GpsL1CaSubframeFsm>().gps_subframe_to_nav_msg(); //decode the subframe
// DECODE SUBFRAME
//std::cout<<"Enter S11"<<std::endl;
}
};
GpsL1CaSubframeFsm::GpsL1CaSubframeFsm()
{
d_nav.reset();
i_channel_ID = 0;
i_satellite_PRN = 0;
d_subframe_ID = 0;
d_flag_new_subframe = false;
initiate(); //start the FSM
}
void GpsL1CaSubframeFsm::gps_word_to_subframe(int position)
{
// insert the word in the correct position of the subframe
std::memcpy(&d_subframe[position * GPS_WORD_LENGTH], &d_GPS_frame_4bytes, sizeof(char) * GPS_WORD_LENGTH);
}
void GpsL1CaSubframeFsm::clear_flag_new_subframe()
{
d_flag_new_subframe = false;
}
void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
{
//int subframe_ID;
// NEW GPS SUBFRAME HAS ARRIVED!
d_subframe_ID = d_nav.subframe_decoder(this->d_subframe); //decode the subframe
std::cout << "New GPS NAV message received in channel " << i_channel_ID << ": "
<< "subframe "
<< d_subframe_ID << " from satellite "
<< Gnss_Satellite(std::string("GPS"), i_satellite_PRN) << std::endl;
d_nav.i_satellite_PRN = i_satellite_PRN;
d_nav.i_channel_ID = i_channel_ID;
d_flag_new_subframe = true;
}
void GpsL1CaSubframeFsm::Event_gps_word_valid()
{
this->process_event(Ev_gps_word_valid());
}
void GpsL1CaSubframeFsm::Event_gps_word_invalid()
{
this->process_event(Ev_gps_word_invalid());
}
void GpsL1CaSubframeFsm::Event_gps_word_preamble()
{
this->process_event(Ev_gps_word_preamble());
}

View File

@ -1,100 +0,0 @@
/*!
* \file gps_l1_ca_subframe_fsm.h
* \brief Interface of a GPS NAV message word-to-subframe decoder state machine
* \author Javier Arribas, 2011. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L1_CA_SUBFRAME_FSM_H_
#define GNSS_SDR_GPS_L1_CA_SUBFRAME_FSM_H_
#include "GPS_L1_CA.h"
#include "gps_navigation_message.h"
#include "gps_ephemeris.h"
#include "gps_iono.h"
#include "gps_almanac.h"
#include "gps_utc_model.h"
#include <boost/statechart/state_machine.hpp>
namespace sc = boost::statechart;
namespace mpl = boost::mpl;
struct gps_subframe_fsm_S0;
struct gps_subframe_fsm_S1;
struct gps_subframe_fsm_S2;
struct gps_subframe_fsm_S3;
struct gps_subframe_fsm_S4;
struct gps_subframe_fsm_S5;
struct gps_subframe_fsm_S6;
struct gps_subframe_fsm_S7;
struct gps_subframe_fsm_S8;
struct gps_subframe_fsm_S9;
struct gps_subframe_fsm_S10;
struct gps_subframe_fsm_S11;
/*!
* \brief This class implements a Finite State Machine that handles the decoding
* of the GPS L1 C/A NAV message
*/
class GpsL1CaSubframeFsm : public sc::state_machine<GpsL1CaSubframeFsm, gps_subframe_fsm_S0>
{
public:
GpsL1CaSubframeFsm(); //!< The constructor starts the Finite State Machine
void clear_flag_new_subframe();
// channel and satellite info
int i_channel_ID; //!< Channel id
unsigned int i_satellite_PRN; //!< Satellite PRN number
Gps_Navigation_Message d_nav; //!< GPS L1 C/A navigation message object
// GPS SV and System parameters
Gps_Ephemeris ephemeris; //!< Object that handles GPS ephemeris parameters
Gps_Almanac almanac; //!< Object that handles GPS almanac data
Gps_Utc_Model utc_model; //!< Object that handles UTM model parameters
Gps_Iono iono; //!< Object that handles ionospheric parameters
char d_subframe[GPS_SUBFRAME_LENGTH];
int d_subframe_ID;
bool d_flag_new_subframe;
char d_GPS_frame_4bytes[GPS_WORD_LENGTH];
//double d_preamble_time_ms;
void gps_word_to_subframe(int position); //!< inserts the word in the correct position of the subframe
/*!
* \brief This function decodes a NAv message subframe and pushes the information to the right queues
*/
void gps_subframe_to_nav_msg();
//FSM EVENTS
void Event_gps_word_valid(); //!< FSM event: the received word is valid
void Event_gps_word_invalid(); //!< FSM event: the received word is not valid
void Event_gps_word_preamble(); //!< FSM event: word preamble detected
};
#endif

View File

@ -50,6 +50,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs
${ARMADILLO_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS}
${GNURADIO_RUNTIME_INCLUDE_DIRS} ${GNURADIO_RUNTIME_INCLUDE_DIRS}

View File

@ -49,6 +49,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/receiver ${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs
${ARMADILLO_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}

View File

@ -2,6 +2,7 @@
* \file dll_pll_veml_tracking.cc * \file dll_pll_veml_tracking.cc
* \brief Implementation of a code DLL + carrier PLL tracking block. * \brief Implementation of a code DLL + carrier PLL tracking block.
* \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com * \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
* Javier Arribas, 2018. jarribas(at)cttc.es
* *
* Code DLL + carrier PLL according to the algorithms described in: * Code DLL + carrier PLL according to the algorithms described in:
* [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
@ -84,10 +85,12 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
this->message_port_register_out(pmt::mp("events")); this->message_port_register_out(pmt::mp("events"));
this->set_relative_rate(1.0 / static_cast<double>(trk_parameters.vector_length)); this->set_relative_rate(1.0 / static_cast<double>(trk_parameters.vector_length));
// Telemetry bit synchronization message port input (mainly for GPS L1 CA)
this->message_port_register_in(pmt::mp("preamble_samplestamp"));
// initialize internal vars // initialize internal vars
d_veml = false; d_veml = false;
d_cloop = true; d_cloop = true;
d_synchonizing = false;
d_code_chip_rate = 0.0; d_code_chip_rate = 0.0;
d_secondary_code_length = 0; d_secondary_code_length = 0;
d_secondary_code_string = nullptr; d_secondary_code_string = nullptr;
@ -120,6 +123,30 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
d_secondary = false; d_secondary = false;
trk_parameters.track_pilot = false; trk_parameters.track_pilot = false;
interchange_iq = false; interchange_iq = false;
// set the preamble
unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
// preamble bits to sampled symbols
d_gps_l1ca_preambles_symbols = static_cast<int *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment()));
int n = 0;
for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++)
{
for (unsigned int j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
{
if (preambles_bits[i] == 1)
{
d_gps_l1ca_preambles_symbols[n] = 1;
}
else
{
d_gps_l1ca_preambles_symbols[n] = -1;
}
n++;
}
}
d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size
d_symbol_history.clear(); // Clear all the elements in the buffer
} }
else if (signal_type.compare("2S") == 0) else if (signal_type.compare("2S") == 0)
{ {
@ -399,7 +426,8 @@ void dll_pll_veml_tracking::start_tracking()
double T_prn_mod_seconds = T_chip_mod_seconds * static_cast<double>(d_code_length_chips); double T_prn_mod_seconds = T_chip_mod_seconds * static_cast<double>(d_code_length_chips);
double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in; double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in;
d_current_prn_length_samples = std::round(T_prn_mod_samples); //d_current_prn_length_samples = std::round(T_prn_mod_samples);
d_current_prn_length_samples = std::floor(T_prn_mod_samples);
double T_prn_true_seconds = static_cast<double>(d_code_length_chips) / d_code_chip_rate; double T_prn_true_seconds = static_cast<double>(d_code_length_chips) / d_code_chip_rate;
double T_prn_true_samples = T_prn_true_seconds * trk_parameters.fs_in; double T_prn_true_samples = T_prn_true_seconds * trk_parameters.fs_in;
@ -520,7 +548,6 @@ void dll_pll_veml_tracking::start_tracking()
// enable tracking pull-in // enable tracking pull-in
d_state = 1; d_state = 1;
d_synchonizing = false;
d_cloop = true; d_cloop = true;
d_Prompt_buffer_deque.clear(); d_Prompt_buffer_deque.clear();
d_last_prompt = gr_complex(0.0, 0.0); d_last_prompt = gr_complex(0.0, 0.0);
@ -532,6 +559,11 @@ void dll_pll_veml_tracking::start_tracking()
dll_pll_veml_tracking::~dll_pll_veml_tracking() dll_pll_veml_tracking::~dll_pll_veml_tracking()
{ {
if (signal_type.compare("1C") == 0)
{
volk_gnsssdr_free(d_gps_l1ca_preambles_symbols);
}
if (d_dump_file.is_open()) if (d_dump_file.is_open())
{ {
try try
@ -753,7 +785,8 @@ void dll_pll_veml_tracking::update_tracking_vars()
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
T_prn_samples = T_prn_seconds * trk_parameters.fs_in; T_prn_samples = T_prn_seconds * trk_parameters.fs_in;
K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * trk_parameters.fs_in; K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * trk_parameters.fs_in;
d_current_prn_length_samples = static_cast<int>(round(K_blk_samples)); // round to a discrete number of samples //d_current_prn_length_samples = static_cast<int>(round(K_blk_samples)); // round to a discrete number of samples
d_current_prn_length_samples = static_cast<int>(std::floor(K_blk_samples)); // round to a discrete number of samples
//################### PLL COMMANDS ################################################# //################### PLL COMMANDS #################################################
// carrier phase step (NCO phase increment per sample) [rads/sample] // carrier phase step (NCO phase increment per sample) [rads/sample]
@ -834,6 +867,7 @@ void dll_pll_veml_tracking::log_data(bool integrating)
float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL; float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL;
float tmp_float; float tmp_float;
double tmp_double; double tmp_double;
unsigned long int tmp_long_int;
if (trk_parameters.track_pilot) if (trk_parameters.track_pilot)
{ {
if (interchange_iq) if (interchange_iq)
@ -900,7 +934,8 @@ void dll_pll_veml_tracking::log_data(bool integrating)
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float)); d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float)); d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
// PRN start sample stamp // PRN start sample stamp
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(unsigned long int)); tmp_long_int = d_sample_counter + d_current_prn_length_samples;
d_dump_file.write(reinterpret_cast<char *>(&tmp_long_int), sizeof(unsigned long int));
// accumulated carrier phase // accumulated carrier phase
tmp_float = d_acc_carrier_phase_rad; tmp_float = d_acc_carrier_phase_rad;
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float)); d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
@ -1277,39 +1312,82 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
} }
else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change
{ {
if (d_synchonizing) float current_tracking_time_s = static_cast<float>(d_sample_counter - d_acq_sample_stamp) / trk_parameters.fs_in;
if (current_tracking_time_s > 10)
{ {
if (d_Prompt->real() * d_last_prompt.real() > 0.0) d_symbol_history.push_back(d_Prompt->real());
//******* preamble correlation ********
int corr_value = 0;
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync))
{ {
d_current_symbol++; for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
}
else if (d_current_symbol > d_symbols_per_bit)
{ {
d_synchonizing = false; if (d_symbol_history.at(i) < 0) // symbols clipping
d_current_symbol = 1; {
corr_value -= d_gps_l1ca_preambles_symbols[i];
} }
else else
{ {
d_current_symbol = 1; corr_value += d_gps_l1ca_preambles_symbols[i];
d_last_prompt = *d_Prompt;
} }
} }
else if (d_last_prompt.real() != 0.0) }
if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
{ {
d_current_symbol++; //std::cout << "Preamble detected at tracking!" << std::endl;
if (d_current_symbol == d_symbols_per_bit) next_state = true; next_state = true;
} }
else else
{ {
d_last_prompt = *d_Prompt; next_state = false;
d_synchonizing = true; }
d_current_symbol = 1; }
else
{
next_state = false;
} }
} }
else else
{ {
next_state = true; next_state = true;
} }
// ########### Output the tracking results to Telemetry block ##########
if (interchange_iq)
{
if (trk_parameters.track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
}
}
else
{
if (trk_parameters.track_pilot)
{
// Note that data and pilot components are in quadrature. I and Q are interchanged
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
}
else
{
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
}
}
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
current_synchro_data.Flag_valid_symbol_output = true;
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
if (next_state) if (next_state)
{ // reset extended correlator { // reset extended correlator
d_VE_accu = gr_complex(0.0, 0.0); d_VE_accu = gr_complex(0.0, 0.0);
@ -1320,7 +1398,6 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
d_last_prompt = gr_complex(0.0, 0.0); d_last_prompt = gr_complex(0.0, 0.0);
d_Prompt_buffer_deque.clear(); d_Prompt_buffer_deque.clear();
d_current_symbol = 0; d_current_symbol = 0;
d_synchonizing = false;
if (d_enable_extended_integration) if (d_enable_extended_integration)
{ {

View File

@ -41,6 +41,7 @@
#include <string> #include <string>
#include <map> #include <map>
#include <queue> #include <queue>
#include <boost/circular_buffer.hpp>
class dll_pll_veml_tracking; class dll_pll_veml_tracking;
@ -69,6 +70,7 @@ private:
friend dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_); friend dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(const Dll_Pll_Conf &conf_);
dll_pll_veml_tracking(const Dll_Pll_Conf &conf_); dll_pll_veml_tracking(const Dll_Pll_Conf &conf_);
void msg_handler_preamble_index(pmt::pmt_t msg);
bool cn0_and_tracking_lock_status(double coh_integration_time_s); bool cn0_and_tracking_lock_status(double coh_integration_time_s);
bool acquire_secondary(); bool acquire_secondary();
@ -102,9 +104,12 @@ private:
std::string *d_secondary_code_string; std::string *d_secondary_code_string;
std::string signal_pretty_name; std::string signal_pretty_name;
uint64_t d_preamble_sample_counter;
int *d_gps_l1ca_preambles_symbols;
boost::circular_buffer<float> d_symbol_history;
//tracking state machine //tracking state machine
int d_state; int d_state;
bool d_synchonizing;
//Integration period in samples //Integration period in samples
int d_correlation_length_ms; int d_correlation_length_ms;
int d_n_correlator_taps; int d_n_correlator_taps;

View File

@ -49,6 +49,7 @@
#include "tracking_2nd_PLL_filter.h" #include "tracking_2nd_PLL_filter.h"
#include <armadillo> #include <armadillo>
#include "cpu_multicorrelator_real_codes.h" #include "cpu_multicorrelator_real_codes.h"
#include "bayesian_estimation.h"
class Gps_L1_Ca_Kf_Tracking_cc; class Gps_L1_Ca_Kf_Tracking_cc;
@ -133,6 +134,9 @@ private:
arma::colvec kf_y_pre; //measurement vector arma::colvec kf_y_pre; //measurement vector
arma::mat kf_K; //Kalman gain matrix arma::mat kf_K; //Kalman gain matrix
// Bayesian estimator
Bayesian_estimator cov_est;
// PLL and DLL filter library // PLL and DLL filter library
Tracking_2nd_DLL_filter d_code_loop_filter; Tracking_2nd_DLL_filter d_code_loop_filter;

View File

@ -44,6 +44,7 @@ set(TRACKING_LIB_SOURCES
tracking_FLL_PLL_filter.cc tracking_FLL_PLL_filter.cc
tracking_loop_filter.cc tracking_loop_filter.cc
dll_pll_conf.cc dll_pll_conf.cc
bayesian_estimation.cc
) )
if(ENABLE_FPGA) if(ENABLE_FPGA)
@ -56,6 +57,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/interfaces ${CMAKE_SOURCE_DIR}/src/core/interfaces
${CMAKE_SOURCE_DIR}/src/core/receiver ${CMAKE_SOURCE_DIR}/src/core/receiver
${CMAKE_SOURCE_DIR}/src/algorithms/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs
${ARMADILLO_INCLUDE_DIRS}
${VOLK_INCLUDE_DIRS} ${VOLK_INCLUDE_DIRS}
${GLOG_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS}

View File

@ -0,0 +1,167 @@
/*!
* \file bayesian_estimation.cc
* \brief Interface of a library with Bayesian noise statistic estimation
*
* Bayesian_estimator is a Bayesian estimator which attempts to estimate
* the properties of a stochastic process based on a sequence of
* discrete samples of the sequence.
*
* [1] TODO: Refs
*
* \authors <ul>
* <li> Gerald LaMountain, 2018. gerald(at)ece.neu.edu
* <li> Jordi Vila-Valls 2018. jvila(at)cttc.es
* </ul>
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "bayesian_estimation.h"
#include <armadillo>
Bayesian_estimator::Bayesian_estimator()
{
kappa_prior = 0;
nu_prior = 0;
}
Bayesian_estimator::Bayesian_estimator(int ny)
{
mu_prior = arma::zeros(ny,1);
kappa_prior = 0;
nu_prior = 0;
Psi_prior = arma::eye(ny,ny) * (nu_prior + ny + 1);
}
Bayesian_estimator::Bayesian_estimator(arma::vec mu_prior_0, int kappa_prior_0, int nu_prior_0, arma::mat Psi_prior_0)
{
mu_prior = mu_prior_0;
kappa_prior = kappa_prior_0;
nu_prior = nu_prior_0;
Psi_prior = Psi_prior_0;
}
Bayesian_estimator::~Bayesian_estimator()
{
}
/*
* Perform Bayesian noise estimation using the normal-inverse-Wishart priors stored in
* the class structure, and update the priors according to the computed posteriors
*/
void Bayesian_estimator::update_sequential(arma::vec data)
{
int K = data.n_cols;
int ny = data.n_rows;
if (mu_prior.is_empty())
{
mu_prior = arma::zeros(ny,1);
}
if (Psi_prior.is_empty())
{
Psi_prior = arma::zeros(ny,ny);
}
arma::vec y_mean = arma::mean(data, 1);
arma::mat Psi_N = arma::zeros(ny, ny);
for (int kk = 0; kk < K; kk++)
{
Psi_N = Psi_N + (data.col(kk)-y_mean)*((data.col(kk)-y_mean).t());
}
arma::vec mu_posterior = (kappa_prior*mu_prior + K*y_mean) / (kappa_prior + K);
int kappa_posterior = kappa_prior + K;
int nu_posterior = nu_prior + K;
arma::mat Psi_posterior = Psi_prior + Psi_N + (kappa_prior*K)/(kappa_prior + K)*(y_mean - mu_prior)*((y_mean - mu_prior).t());
mu_est = mu_posterior;
if ((nu_posterior - ny - 1) > 0)
{
Psi_est = Psi_posterior / (nu_posterior - ny - 1);
}
else
{
Psi_est = Psi_posterior / (nu_posterior + ny + 1);
}
mu_prior = mu_posterior;
kappa_prior = kappa_posterior;
nu_prior = nu_posterior;
Psi_prior = Psi_posterior;
}
/*
* Perform Bayesian noise estimation using a new set of normal-inverse-Wishart priors
* and update the priors according to the computed posteriors
*/
void Bayesian_estimator::update_sequential(arma::vec data, arma::vec mu_prior_0, int kappa_prior_0, int nu_prior_0, arma::mat Psi_prior_0)
{
int K = data.n_cols;
int ny = data.n_rows;
arma::vec y_mean = arma::mean(data, 1);
arma::mat Psi_N = arma::zeros(ny, ny);
for (int kk = 0; kk < K; kk++)
{
Psi_N = Psi_N + (data.col(kk)-y_mean)*((data.col(kk)-y_mean).t());
}
arma::vec mu_posterior = (kappa_prior_0*mu_prior_0 + K*y_mean) / (kappa_prior_0 + K);
int kappa_posterior = kappa_prior_0 + K;
int nu_posterior = nu_prior_0 + K;
arma::mat Psi_posterior = Psi_prior_0 + Psi_N + (kappa_prior_0*K)/(kappa_prior_0 + K)*(y_mean - mu_prior_0)*((y_mean - mu_prior_0).t());
mu_est = mu_posterior;
if ((nu_posterior - ny - 1) > 0)
{
Psi_est = Psi_posterior / (nu_posterior - ny - 1);
}
else
{
Psi_est = Psi_posterior / (nu_posterior + ny + 1);
}
mu_prior = mu_posterior;
kappa_prior = kappa_posterior;
nu_prior = nu_posterior;
Psi_prior = Psi_posterior;
}
arma::vec Bayesian_estimator::get_mu_est()
{
return mu_est;
}
arma::mat Bayesian_estimator::get_Psi_est()
{
return Psi_est;
}

View File

@ -0,0 +1,86 @@
/*!
* \file bayesian_estimation.h
* \brief Interface of a library with Bayesian noise statistic estimation
*
* Bayesian_estimator is a Bayesian estimator which attempts to estimate
* the properties of a stochastic process based on a sequence of
* discrete samples of the sequence.
*
* [1] TODO: Refs
*
* \authors <ul>
* <li> Gerald LaMountain, 2018. gerald(at)ece.neu.edu
* <li> Jordi Vila-Valls 2018. jvila(at)cttc.es
* </ul>
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BAYESIAN_ESTIMATION_H_
#define GNSS_SDR_BAYESIAN_ESTIMATION_H_
#include <gnuradio/gr_complex.h>
#include <armadillo>
/*! \brief Bayesian_estimator is an estimator of noise characteristics (i.e. mean, covariance)
*
* Bayesian_estimator is an estimator which performs estimation of noise characteristics from
* a sequence of identically and independently distributed (IID) samples of a stationary
* stochastic process by way of Bayesian inference using conjugate priors. The posterior
* distribution is assumed to be Gaussian with mean \mathbf{\mu} and covariance \hat{\mathbf{C}},
* which has a conjugate prior given by a normal-inverse-Wishart distribution with paramemters
* \mathbf{\mu}_{0}, \kappa_{0}, \nu_{0}, and \mathbf{\Psi}.
*
* [1] TODO: Ref1
*
*/
class Bayesian_estimator
{
public:
Bayesian_estimator();
Bayesian_estimator(int ny);
Bayesian_estimator(arma::vec mu_prior_0, int kappa_prior_0, int nu_prior_0, arma::mat Psi_prior_0);
~Bayesian_estimator();
void update_sequential(arma::vec data);
void update_sequential(arma::vec data, arma::vec mu_prior_0, int kappa_prior_0, int nu_prior_0, arma::mat Psi_prior_0);
arma::vec get_mu_est();
arma::mat get_Psi_est();
private:
arma::vec mu_est;
arma::mat Psi_est;
arma::vec mu_prior;
int kappa_prior;
int nu_prior;
arma::mat Psi_prior;
};
#endif

View File

@ -61,6 +61,7 @@ public:
virtual void set_doppler_step(unsigned int doppler_step) = 0; virtual void set_doppler_step(unsigned int doppler_step) = 0;
virtual void init() = 0; virtual void init() = 0;
virtual void set_local_code() = 0; virtual void set_local_code() = 0;
virtual void set_state(int state) = 0;
virtual signed int mag() = 0; virtual signed int mag() = 0;
virtual void reset() = 0; virtual void reset() = 0;
}; };

View File

@ -27,6 +27,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/system_parameters ${CMAKE_SOURCE_DIR}/src/core/system_parameters
${GLOG_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS}
${GNURADIO_RUNTIME_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
) )
@ -35,3 +36,4 @@ list(SORT CORE_MONITOR_LIBS_HEADERS)
add_library(core_monitor_lib ${CORE_MONITOR_LIBS_SOURCES} ${CORE_MONITOR_LIBS_HEADERS}) add_library(core_monitor_lib ${CORE_MONITOR_LIBS_SOURCES} ${CORE_MONITOR_LIBS_HEADERS})
source_group(Headers FILES ${CORE_MONITOR_LIBS_HEADERS}) source_group(Headers FILES ${CORE_MONITOR_LIBS_HEADERS})
target_link_libraries(core_monitor_lib ${Boost_LIBRARIES}) target_link_libraries(core_monitor_lib ${Boost_LIBRARIES})
add_dependencies(core_monitor_lib glog-${glog_RELEASE})

View File

@ -418,7 +418,7 @@ void GNSSFlowgraph::connect()
} }
if (sat == 0) if (sat == 0)
{ {
channels_.at(i)->set_signal(search_next_signal(gnss_signal, true)); channels_.at(i)->set_signal(search_next_signal(gnss_signal, false));
} }
else else
{ {
@ -896,6 +896,43 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
case 1: case 1:
LOG(INFO) << "Channel " << who << " ACQ SUCCESS satellite " << channels_[who]->get_signal().get_satellite(); LOG(INFO) << "Channel " << who << " ACQ SUCCESS satellite " << channels_[who]->get_signal().get_satellite();
// If the satellite is in the list of available ones, remove it.
switch (mapStringValues_[channels_[who]->get_signal().get_signal_str()])
{
case evGPS_1C:
available_GPS_1C_signals_.remove(channels_[who]->get_signal());
break;
case evGPS_2S:
available_GPS_2S_signals_.remove(channels_[who]->get_signal());
break;
case evGPS_L5:
available_GPS_L5_signals_.remove(channels_[who]->get_signal());
break;
case evGAL_1B:
available_GAL_1B_signals_.remove(channels_[who]->get_signal());
break;
case evGAL_5X:
available_GAL_5X_signals_.remove(channels_[who]->get_signal());
break;
case evGLO_1G:
available_GLO_1G_signals_.remove(channels_[who]->get_signal());
break;
case evGLO_2G:
available_GLO_2G_signals_.remove(channels_[who]->get_signal());
break;
default:
LOG(ERROR) << "This should not happen :-(";
break;
}
channels_state_[who] = 2; channels_state_[who] = 2;
acq_channels_count_--; acq_channels_count_--;
for (unsigned int i = 0; i < channels_count_; i++) for (unsigned int i = 0; i < channels_count_; i++)
@ -1357,9 +1394,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
{ {
case evGPS_1C: case evGPS_1C:
result = available_GPS_1C_signals_.front(); result = available_GPS_1C_signals_.front();
if (pop)
{
available_GPS_1C_signals_.pop_front(); available_GPS_1C_signals_.pop_front();
if (!pop)
{
available_GPS_1C_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1387,9 +1425,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGPS_2S: case evGPS_2S:
result = available_GPS_2S_signals_.front(); result = available_GPS_2S_signals_.front();
if (pop)
{
available_GPS_2S_signals_.pop_front(); available_GPS_2S_signals_.pop_front();
if (!pop)
{
available_GPS_2S_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1417,9 +1456,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGPS_L5: case evGPS_L5:
result = available_GPS_L5_signals_.front(); result = available_GPS_L5_signals_.front();
if (pop)
{
available_GPS_L5_signals_.pop_front(); available_GPS_L5_signals_.pop_front();
if (!pop)
{
available_GPS_L5_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1447,9 +1487,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGAL_1B: case evGAL_1B:
result = available_GAL_1B_signals_.front(); result = available_GAL_1B_signals_.front();
if (pop)
{
available_GAL_1B_signals_.pop_front(); available_GAL_1B_signals_.pop_front();
if (!pop)
{
available_GAL_1B_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1471,9 +1512,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGAL_5X: case evGAL_5X:
result = available_GAL_5X_signals_.front(); result = available_GAL_5X_signals_.front();
if (pop)
{
available_GAL_5X_signals_.pop_front(); available_GAL_5X_signals_.pop_front();
if (!pop)
{
available_GAL_5X_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1495,9 +1537,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGLO_1G: case evGLO_1G:
result = available_GLO_1G_signals_.front(); result = available_GLO_1G_signals_.front();
if (pop)
{
available_GLO_1G_signals_.pop_front(); available_GLO_1G_signals_.pop_front();
if (!pop)
{
available_GLO_1G_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {
@ -1519,9 +1562,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
case evGLO_2G: case evGLO_2G:
result = available_GLO_2G_signals_.front(); result = available_GLO_2G_signals_.front();
if (pop)
{
available_GLO_2G_signals_.pop_front(); available_GLO_2G_signals_.pop_front();
if (!pop)
{
available_GLO_2G_signals_.push_back(result);
} }
if (tracked) if (tracked)
{ {

View File

@ -84,6 +84,9 @@ public:
template <class Archive> template <class Archive>
void serialize(Archive& ar, const unsigned int version) void serialize(Archive& ar, const unsigned int version)
{ {
if (version)
{
};
// Satellite and signal info // Satellite and signal info
ar& System; ar& System;
ar& Signal; ar& Signal;

View File

@ -34,8 +34,15 @@
#include <gflags/gflags.h> #include <gflags/gflags.h>
#include <limits> #include <limits>
DEFINE_string(trk_test_implementation, std::string("GPS_L1_CA_DLL_PLL_Tracking"), "Tracking block implementation under test, defaults to GPS_L1_CA_DLL_PLL_Tracking");
// Input signal configuration // Input signal configuration
DEFINE_bool(enable_external_signal_file, false, "Use an external signal file capture instead of the software-defined signal generator"); DEFINE_bool(enable_external_signal_file, false, "Use an external signal file capture instead of the software-defined signal generator");
DEFINE_double(external_signal_acquisition_threshold, 2.5, "Threshold for satellite acquisition when external file is used");
DEFINE_int32(external_signal_acquisition_dwells, 5, "Maximum dwells count for satellite acquisition when external file is used");
DEFINE_double(external_signal_acquisition_doppler_max_hz, 5000.0, "Doppler max for satellite acquisition when external file is used");
DEFINE_double(external_signal_acquisition_doppler_step_hz, 125, "Doppler step for satellite acquisition when external file is used");
DEFINE_string(signal_file, std::string("signal_out.bin"), "Path of the external signal capture file"); DEFINE_string(signal_file, std::string("signal_out.bin"), "Path of the external signal capture file");
DEFINE_double(CN0_dBHz_start, std::numeric_limits<double>::infinity(), "Enable noise generator and set the CN0 start sweep value [dB-Hz]"); DEFINE_double(CN0_dBHz_start, std::numeric_limits<double>::infinity(), "Enable noise generator and set the CN0 start sweep value [dB-Hz]");
DEFINE_double(CN0_dBHz_stop, std::numeric_limits<double>::infinity(), "Enable noise generator and set the CN0 stop sweep value [dB-Hz]"); DEFINE_double(CN0_dBHz_stop, std::numeric_limits<double>::infinity(), "Enable noise generator and set the CN0 stop sweep value [dB-Hz]");
@ -60,9 +67,12 @@ DEFINE_double(acq_Delay_error_chips_start, 2.0, "Acquisition Code Delay error st
DEFINE_double(acq_Delay_error_chips_stop, -2.0, "Acquisition Code Delay error stop sweep value [Chips]"); DEFINE_double(acq_Delay_error_chips_stop, -2.0, "Acquisition Code Delay error stop sweep value [Chips]");
DEFINE_double(acq_Delay_error_chips_step, -0.1, "Acquisition Code Delay error sweep step value [Chips]"); DEFINE_double(acq_Delay_error_chips_step, -0.1, "Acquisition Code Delay error sweep step value [Chips]");
DEFINE_int64(skip_samples, 0, "Skip an initial transitory in the processed signal file capture [samples]");
DEFINE_int32(plot_detail_level, 0, "Specify the desired plot detail (0,1,2): 0 - Minimum plots (default) 2 - Plot all tracking parameters"); DEFINE_int32(plot_detail_level, 0, "Specify the desired plot detail (0,1,2): 0 - Minimum plots (default) 2 - Plot all tracking parameters");
DEFINE_double(skip_trk_transitory_s, 1.0, "Skip the initial tracking output signal to avoid transitory results [s]");
//Emulated acquisition configuration //Emulated acquisition configuration
//Tracking configuration //Tracking configuration

View File

@ -600,6 +600,14 @@ void ObsSystemTest::compute_pseudorange_error(
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title(signal_name + " Pseudorange error"); g1.set_title(signal_name + " Pseudorange error");
g1.set_grid(); g1.set_grid();
g1.set_xlabel("PRN"); g1.set_xlabel("PRN");
@ -620,7 +628,6 @@ void ObsSystemTest::compute_pseudorange_error(
} }
g1.savetops("Pseudorange_error_" + signal_name); g1.savetops("Pseudorange_error_" + signal_name);
g1.savetopdf("Pseudorange_error_" + signal_name, 18); g1.savetopdf("Pseudorange_error_" + signal_name, 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
@ -691,6 +698,14 @@ void ObsSystemTest::compute_carrierphase_error(
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title(signal_name + " Carrier phase error"); g1.set_title(signal_name + " Carrier phase error");
g1.set_grid(); g1.set_grid();
g1.set_xlabel("PRN"); g1.set_xlabel("PRN");
@ -711,7 +726,6 @@ void ObsSystemTest::compute_carrierphase_error(
} }
g1.savetops("Carrier_phase_error_" + signal_name); g1.savetops("Carrier_phase_error_" + signal_name);
g1.savetopdf("Carrier_phase_error_" + signal_name, 18); g1.savetopdf("Carrier_phase_error_" + signal_name, 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
@ -782,6 +796,14 @@ void ObsSystemTest::compute_doppler_error(
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title(signal_name + " Doppler error"); g1.set_title(signal_name + " Doppler error");
g1.set_grid(); g1.set_grid();
g1.set_xlabel("PRN"); g1.set_xlabel("PRN");
@ -802,7 +824,6 @@ void ObsSystemTest::compute_doppler_error(
} }
g1.savetops("Doppler_error_" + signal_name); g1.savetops("Doppler_error_" + signal_name);
g1.savetopdf("Doppler_error_" + signal_name, 18); g1.savetopdf("Doppler_error_" + signal_name, 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {

View File

@ -619,6 +619,14 @@ void StaticPositionSystemTest::print_results(const std::vector<double>& east,
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("points"); Gnuplot g1("points");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title("2D precision"); g1.set_title("2D precision");
g1.set_xlabel("East [m]"); g1.set_xlabel("East [m]");
g1.set_ylabel("North [m]"); g1.set_ylabel("North [m]");
@ -635,9 +643,16 @@ void StaticPositionSystemTest::print_results(const std::vector<double>& east,
g1.savetops("Position_test_2D"); g1.savetops("Position_test_2D");
g1.savetopdf("Position_test_2D", 18); g1.savetopdf("Position_test_2D", 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
Gnuplot g2("points"); Gnuplot g2("points");
if (FLAGS_show_plots)
{
g2.showonscreen(); // window output
}
else
{
g2.disablescreen();
}
g2.set_title("3D precision"); g2.set_title("3D precision");
g2.set_xlabel("East [m]"); g2.set_xlabel("East [m]");
g2.set_ylabel("North [m]"); g2.set_ylabel("North [m]");
@ -656,7 +671,6 @@ void StaticPositionSystemTest::print_results(const std::vector<double>& east,
g2.savetops("Position_test_3D"); g2.savetops("Position_test_3D");
g2.savetopdf("Position_test_3D"); g2.savetopdf("Position_test_3D");
if (FLAGS_show_plots) g2.showonscreen(); // window output
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {

View File

@ -145,10 +145,11 @@ DECLARE_string(log_dir);
#if EXTRA_TESTS #if EXTRA_TESTS
#include "unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc"
#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_acq_performance_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_kf_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_kf_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc"
#include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc" #include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc"
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc" #include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc"
#endif #endif

View File

@ -116,6 +116,14 @@ TEST(FFTLengthTest, MeasureExecutionTime)
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title("FFT execution times for different lengths"); g1.set_title("FFT execution times for different lengths");
g1.set_grid(); g1.set_grid();
g1.set_xlabel("FFT length"); g1.set_xlabel("FFT length");
@ -124,9 +132,16 @@ TEST(FFTLengthTest, MeasureExecutionTime)
g1.set_style("points").plot_xy(powers_of_two, execution_times_powers_of_two, "Power of 2"); g1.set_style("points").plot_xy(powers_of_two, execution_times_powers_of_two, "Power of 2");
g1.savetops("FFT_execution_times_extended"); g1.savetops("FFT_execution_times_extended");
g1.savetopdf("FFT_execution_times_extended", 18); g1.savetopdf("FFT_execution_times_extended", 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
Gnuplot g2("linespoints"); Gnuplot g2("linespoints");
if (FLAGS_show_plots)
{
g2.showonscreen(); // window output
}
else
{
g2.disablescreen();
}
g2.set_title("FFT execution times for different lengths (up to 2^{14}=16384)"); g2.set_title("FFT execution times for different lengths (up to 2^{14}=16384)");
g2.set_grid(); g2.set_grid();
g2.set_xlabel("FFT length"); g2.set_xlabel("FFT length");

View File

@ -1,5 +1,5 @@
/*! /*!
* \file gps_l1_acq_performance_test.cc * \file acq_performance_test.cc
* \brief This class implements an acquisition performance test * \brief This class implements an acquisition performance test
* \author Carles Fernandez-Prades, 2018. cfernandez(at)cttc.cat * \author Carles Fernandez-Prades, 2018. cfernandez(at)cttc.cat
* *
@ -29,26 +29,38 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#include "test_flags.h" #include "gps_l1_ca_pcps_acquisition.h"
#include "signal_generator_flags.h" #include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include "tracking_true_obs_reader.h" #include "galileo_e1_pcps_ambiguous_acquisition.h"
#include "true_observables_reader.h" #include "galileo_e5a_pcps_acquisition.h"
#include "glonass_l1_ca_pcps_acquisition.h"
#include "glonass_l2_ca_pcps_acquisition.h"
#include "gps_l2_m_pcps_acquisition.h"
#include "gps_l5i_pcps_acquisition.h"
#include "display.h" #include "display.h"
#include "gnuplot_i.h" #include "gnuplot_i.h"
#include "signal_generator_flags.h"
#include "test_flags.h"
#include "tracking_true_obs_reader.h"
#include "true_observables_reader.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <gnuradio/top_block.h> #include <gnuradio/top_block.h>
#include <glog/logging.h> #include <gnuradio/blocks/skiphead.h>
#include <gtest/gtest.h>
DEFINE_string(config_file_ptest, std::string(""), "File containing alternative configuration parameters for the acquisition performance test."); DEFINE_string(config_file_ptest, std::string(""), "File containing alternative configuration parameters for the acquisition performance test.");
DEFINE_string(acq_test_input_file, std::string(""), "File containing raw signal data, must be in int8_t format. The signal generator will not be used."); DEFINE_string(acq_test_input_file, std::string(""), "File containing raw signal data, must be in int8_t format. The signal generator will not be used.");
DEFINE_string(acq_test_implementation, std::string("GPS_L1_CA_PCPS_Acquisition"), "Acquisition block implementation under test. Alternatives: GPS_L1_CA_PCPS_Acquisition, GPS_L1_CA_PCPS_Acquisition_Fine_Doppler, Galileo_E1_PCPS_Ambiguous_Acquisition, GLONASS_L1_CA_PCPS_Acquisition, GLONASS_L2_CA_PCPS_Acquisition, GPS_L2_M_PCPS_Acquisition, Galileo_E5a_Pcps_Acquisition, GPS_L5i_PCPS_Acquisition");
DEFINE_int32(acq_test_doppler_max, 5000, "Maximum Doppler, in Hz"); DEFINE_int32(acq_test_doppler_max, 5000, "Maximum Doppler, in Hz");
DEFINE_int32(acq_test_doppler_step, 125, "Doppler step, in Hz."); DEFINE_int32(acq_test_doppler_step, 125, "Doppler step, in Hz.");
DEFINE_int32(acq_test_coherent_time_ms, 1, "Acquisition coherent time, in ms"); DEFINE_int32(acq_test_coherent_time_ms, 1, "Acquisition coherent time, in ms");
DEFINE_int32(acq_test_max_dwells, 1, "Number of non-coherent integrations"); DEFINE_int32(acq_test_max_dwells, 1, "Number of non-coherent integrations.");
DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm"); DEFINE_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm.");
DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag"); DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag.");
DEFINE_bool(acq_test_make_two_steps, false, "Perform second step in a thinner grid.");
DEFINE_int32(acq_test_second_nbins, 4, "If --acq_test_make_two_steps is set to true, this parameter sets the number of bins done in the acquisition refinement stage.");
DEFINE_int32(acq_test_second_doppler_step, 10, "If --acq_test_make_two_steps is set to true, this parameter sets the Doppler step applied in the acquisition refinement stage, in Hz.");
DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s"); DEFINE_int32(acq_test_signal_duration_s, 2, "Generated signal duration, in s");
DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file."); DEFINE_int32(acq_test_num_meas, 0, "Number of measurements per run. 0 means the complete file.");
@ -56,9 +68,9 @@ DEFINE_double(acq_test_cn0_init, 33.0, "Initial CN0, in dBHz.");
DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz."); DEFINE_double(acq_test_cn0_final, 45.0, "Final CN0, in dBHz.");
DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB."); DEFINE_double(acq_test_cn0_step, 3.0, "CN0 step, in dB.");
DEFINE_double(acq_test_threshold_init, 11.0, "Initial acquisition threshold"); DEFINE_double(acq_test_threshold_init, 3.0, "Initial acquisition threshold");
DEFINE_double(acq_test_threshold_final, 16.0, "Final acquisition threshold"); DEFINE_double(acq_test_threshold_final, 4.0, "Final acquisition threshold");
DEFINE_double(acq_test_threshold_step, 1.0, "Acquisition threshold step"); DEFINE_double(acq_test_threshold_step, 0.5, "Acquisition threshold step");
DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm. Disable with -1.0"); DEFINE_double(acq_test_pfa_init, 1e-5, "Set initial threshold via probability of false alarm. Disable with -1.0");
@ -67,6 +79,7 @@ DEFINE_int32(acq_test_fake_PRN, 33, "PRN number of a non-present satellite");
DEFINE_int32(acq_test_iterations, 1, "Number of iterations (same signal, different noise realization)"); DEFINE_int32(acq_test_iterations, 1, "Number of iterations (same signal, different noise realization)");
DEFINE_bool(plot_acq_test, false, "Plots results with gnuplot, if available"); DEFINE_bool(plot_acq_test, false, "Plots results with gnuplot, if available");
DEFINE_int32(acq_test_skiphead, 0, "Number of samples to skip in the input file");
// ######## GNURADIO BLOCK MESSAGE RECEVER ######### // ######## GNURADIO BLOCK MESSAGE RECEVER #########
class AcqPerfTest_msg_rx; class AcqPerfTest_msg_rx;
@ -151,6 +164,84 @@ protected:
{ {
cn0_vector = {0.0}; cn0_vector = {0.0};
} }
if (implementation.compare("GPS_L1_CA_PCPS_Acquisition") == 0)
{
signal_id = "1C";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fine_Doppler") == 0)
{
signal_id = "1C";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{
signal_id = "1B";
system_id = 'E';
min_integration_ms = 4;
if (FLAGS_acq_test_coherent_time_ms == 1)
{
coherent_integration_time_ms = 4;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
}
else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
{
signal_id = "1G";
system_id = 'R';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
else if (implementation.compare("GLONASS_L2_CA_PCPS_Acquisition") == 0)
{
signal_id = "2G";
system_id = 'R';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition") == 0)
{
signal_id = "2S";
system_id = 'G';
if (FLAGS_acq_test_coherent_time_ms == 1)
{
coherent_integration_time_ms = 20;
}
else
{
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
min_integration_ms = 20;
}
else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0)
{
signal_id = "5X";
system_id = 'E';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{
signal_id = "L5";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
}
else
{
signal_id = "1C";
system_id = 'G';
coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
min_integration_ms = 1;
}
init(); init();
if (FLAGS_acq_test_pfa_init > 0.0) if (FLAGS_acq_test_pfa_init > 0.0)
@ -178,7 +269,7 @@ protected:
num_thresholds = pfa_vector.size(); num_thresholds = pfa_vector.size();
int aux2 = ((generated_signal_duration_s * 1000 - FLAGS_acq_test_coherent_time_ms) / FLAGS_acq_test_coherent_time_ms); int aux2 = ((generated_signal_duration_s * 1000 - (FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells)) / (FLAGS_acq_test_coherent_time_ms * FLAGS_acq_test_max_dwells));
if ((FLAGS_acq_test_num_meas > 0) and (FLAGS_acq_test_num_meas < aux2)) if ((FLAGS_acq_test_num_meas > 0) and (FLAGS_acq_test_num_meas < aux2))
{ {
num_of_measurements = static_cast<unsigned int>(FLAGS_acq_test_num_meas); num_of_measurements = static_cast<unsigned int>(FLAGS_acq_test_num_meas);
@ -200,7 +291,6 @@ protected:
{ {
} }
std::vector<double> cn0_vector; std::vector<double> cn0_vector;
std::vector<float> pfa_vector; std::vector<float> pfa_vector;
@ -223,7 +313,7 @@ protected:
gr::msg_queue::sptr queue; gr::msg_queue::sptr queue;
gr::top_block_sptr top_block; gr::top_block_sptr top_block;
std::shared_ptr<GpsL1CaPcpsAcquisition> acquisition; std::shared_ptr<AcquisitionInterface> acquisition;
std::shared_ptr<InMemoryConfiguration> config; std::shared_ptr<InMemoryConfiguration> config;
std::shared_ptr<FileConfiguration> config_f; std::shared_ptr<FileConfiguration> config_f;
Gnss_Synchro gnss_synchro; Gnss_Synchro gnss_synchro;
@ -235,10 +325,10 @@ protected:
int message; int message;
boost::thread ch_thread; boost::thread ch_thread;
std::string implementation = "GPS_L1_CA_PCPS_Acquisition"; std::string implementation = FLAGS_acq_test_implementation;
const double baseband_sampling_freq = static_cast<double>(FLAGS_fs_gen_sps); const double baseband_sampling_freq = static_cast<double>(FLAGS_fs_gen_sps);
const int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms; int coherent_integration_time_ms;
const int in_acquisition = 1; const int in_acquisition = 1;
const int dump_channel = 0; const int dump_channel = 0;
@ -250,11 +340,14 @@ protected:
std::string path_str = "./acq-perf-test"; std::string path_str = "./acq-perf-test";
int num_thresholds; int num_thresholds;
unsigned int min_integration_ms;
std::vector<std::vector<float>> Pd; std::vector<std::vector<float>> Pd;
std::vector<std::vector<float>> Pfa; std::vector<std::vector<float>> Pfa;
std::vector<std::vector<float>> Pd_correct; std::vector<std::vector<float>> Pd_correct;
std::string signal_id;
private: private:
std::string generator_binary; std::string generator_binary;
std::string p1; std::string p1;
@ -266,6 +359,7 @@ private:
std::string filename_rinex_obs = FLAGS_filename_rinex_obs; std::string filename_rinex_obs = FLAGS_filename_rinex_obs;
std::string filename_raw_data = FLAGS_filename_raw_data; std::string filename_raw_data = FLAGS_filename_raw_data;
char system_id;
double compute_stdev_precision(const std::vector<double>& vec); double compute_stdev_precision(const std::vector<double>& vec);
double compute_stdev_accuracy(const std::vector<double>& vec, double ref); double compute_stdev_accuracy(const std::vector<double>& vec, double ref);
@ -275,8 +369,8 @@ private:
void AcquisitionPerformanceTest::init() void AcquisitionPerformanceTest::init()
{ {
gnss_synchro.Channel_ID = 0; gnss_synchro.Channel_ID = 0;
gnss_synchro.System = 'G'; gnss_synchro.System = system_id;
std::string signal = "1C"; std::string signal = signal_id;
signal.copy(gnss_synchro.Signal, 2, 0); signal.copy(gnss_synchro.Signal, 2, 0);
gnss_synchro.PRN = observed_satellite; gnss_synchro.PRN = observed_satellite;
message = 0; message = 0;
@ -376,50 +470,59 @@ int AcquisitionPerformanceTest::configure_receiver(double cn0, float pfa, unsign
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal)); config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(sampling_rate_internal));
// Set Acquisition // Set Acquisition
config->set_property("Acquisition_1C.implementation", implementation); config->set_property("Acquisition.implementation", implementation);
config->set_property("Acquisition_1C.item_type", "gr_complex"); config->set_property("Acquisition.item_type", "gr_complex");
config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max)); config->set_property("Acquisition.doppler_max", std::to_string(doppler_max));
config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step)); config->set_property("Acquisition.doppler_min", std::to_string(-doppler_max));
config->set_property("Acquisition.doppler_step", std::to_string(doppler_step));
config->set_property("Acquisition_1C.threshold", std::to_string(pfa)); config->set_property("Acquisition.threshold", std::to_string(pfa));
//if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); //if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition.pfa", std::to_string(pfa));
if (FLAGS_acq_test_pfa_init > 0.0) if (FLAGS_acq_test_pfa_init > 0.0)
{ {
config->supersede_property("Acquisition_1C.pfa", std::to_string(pfa)); config->supersede_property("Acquisition.pfa", std::to_string(pfa));
} }
if (FLAGS_acq_test_use_CFAR_algorithm) if (FLAGS_acq_test_use_CFAR_algorithm)
{ {
config->set_property("Acquisition_1C.use_CFAR_algorithm", "true"); config->set_property("Acquisition.use_CFAR_algorithm", "true");
} }
else else
{ {
config->set_property("Acquisition_1C.use_CFAR_algorithm", "false"); config->set_property("Acquisition.use_CFAR_algorithm", "false");
} }
config->set_property("Acquisition_1C.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms)); config->set_property("Acquisition.coherent_integration_time_ms", std::to_string(coherent_integration_time_ms));
if (FLAGS_acq_test_bit_transition_flag) if (FLAGS_acq_test_bit_transition_flag)
{ {
config->set_property("Acquisition_1C.bit_transition_flag", "true"); config->set_property("Acquisition.bit_transition_flag", "true");
} }
else else
{ {
config->set_property("Acquisition_1C.bit_transition_flag", "false"); config->set_property("Acquisition.bit_transition_flag", "false");
} }
config->set_property("Acquisition_1C.max_dwells", std::to_string(FLAGS_acq_test_max_dwells)); config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_acq_test_max_dwells));
config->set_property("Acquisition_1C.repeat_satellite", "true"); config->set_property("Acquisition.repeat_satellite", "true");
config->set_property("Acquisition_1C.blocking", "true"); config->set_property("Acquisition.blocking", "true");
config->set_property("Acquisition_1C.make_two_steps", "false"); if (FLAGS_acq_test_make_two_steps)
config->set_property("Acquisition_1C.second_nbins", std::to_string(4)); {
config->set_property("Acquisition_1C.second_doppler_step", std::to_string(125)); config->set_property("Acquisition.make_two_steps", "true");
config->set_property("Acquisition.second_nbins", std::to_string(FLAGS_acq_test_second_nbins));
config->set_property("Acquisition.second_doppler_step", std::to_string(FLAGS_acq_test_second_doppler_step));
}
else
{
config->set_property("Acquisition.make_two_steps", "false");
}
config->set_property("Acquisition_1C.dump", "true");
config->set_property("Acquisition.dump", "true");
std::string dump_file = path_str + std::string("/acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter) + "_" + std::to_string(pfa); std::string dump_file = path_str + std::string("/acquisition_") + std::to_string(cn0) + "_" + std::to_string(iter) + "_" + std::to_string(pfa);
config->set_property("Acquisition_1C.dump_filename", dump_file); config->set_property("Acquisition.dump_filename", dump_file);
config->set_property("Acquisition_1C.dump_channel", std::to_string(dump_channel)); config->set_property("Acquisition.dump_channel", std::to_string(dump_channel));
config->set_property("Acquisition_1C.blocking_on_standby", "true"); config->set_property("Acquisition.blocking_on_standby", "true");
config_f = 0; config_f = 0;
} }
@ -450,6 +553,7 @@ int AcquisitionPerformanceTest::run_receiver()
top_block = gr::make_top_block("Acquisition test"); top_block = gr::make_top_block("Acquisition test");
boost::shared_ptr<AcqPerfTest_msg_rx> msg_rx = AcqPerfTest_msg_rx_make(channel_internal_queue); boost::shared_ptr<AcqPerfTest_msg_rx> msg_rx = AcqPerfTest_msg_rx_make(channel_internal_queue);
gr::blocks::skiphead::sptr skiphead = gr::blocks::skiphead::make(sizeof(gr_complex), FLAGS_acq_test_skiphead);
queue = gr::msg_queue::make(0); queue = gr::msg_queue::make(0);
gnss_synchro = Gnss_Synchro(); gnss_synchro = Gnss_Synchro();
@ -457,23 +561,61 @@ int AcquisitionPerformanceTest::run_receiver()
int nsamples = floor(config->property("GNSS-SDR.internal_fs_sps", 2000000) * generated_signal_duration_s); int nsamples = floor(config->property("GNSS-SDR.internal_fs_sps", 2000000) * generated_signal_duration_s);
boost::shared_ptr<gr::block> valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); boost::shared_ptr<gr::block> valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue);
if (implementation.compare("GPS_L1_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fine_Doppler") == 0)
{
acquisition = std::make_shared<GpsL1CaPcpsAcquisitionFineDoppler>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{
acquisition = std::make_shared<GalileoE1PcpsAmbiguousAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GlonassL1CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GLONASS_L2_CA_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GlonassL2CaPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL2MPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0)
{
acquisition = std::make_shared<GalileoE5aPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{
acquisition = std::make_shared<GpsL5iPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else
{
bool aux = false;
EXPECT_EQ(true, aux);
}
acquisition = std::make_shared<GpsL1CaPcpsAcquisition>(config.get(), "Acquisition_1C", 1, 0);
acquisition->set_gnss_synchro(&gnss_synchro); acquisition->set_gnss_synchro(&gnss_synchro);
acquisition->set_channel(0); acquisition->set_channel(0);
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000));
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500));
acquisition->set_threshold(config->property("Acquisition.threshold", 0.0));
acquisition->init();
acquisition->set_local_code(); acquisition->set_local_code();
acquisition->set_doppler_max(config->property("Acquisition_1C.doppler_max", 10000));
acquisition->set_doppler_step(config->property("Acquisition_1C.doppler_step", 500));
acquisition->set_threshold(config->property("Acquisition_1C.threshold", 0.0));
acquisition->set_state(1); // Ensure that acquisition starts at the first sample acquisition->set_state(1); // Ensure that acquisition starts at the first sample
acquisition->connect(top_block); acquisition->connect(top_block);
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
acquisition->init();
acquisition->reset();
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, valve, 0); top_block->connect(gr_interleaved_char_to_complex, 0, skiphead, 0);
top_block->connect(skiphead, 0, valve, 0);
top_block->connect(valve, 0, acquisition->get_left_block(), 0); top_block->connect(valve, 0, acquisition->get_left_block(), 0);
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
start_queue(); start_queue();
@ -534,9 +676,17 @@ void AcquisitionPerformanceTest::plot_results()
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.cmd("set font \"Times,18\""); g1.cmd("set font \"Times,18\"");
g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition"); g1.set_title("Receiver Operating Characteristic for GPS L1 C/A acquisition");
g1.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition_1C.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\""); g1.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g1.cmd("set logscale x"); g1.cmd("set logscale x");
g1.cmd("set yrange [0:1]"); g1.cmd("set yrange [0:1]");
g1.cmd("set xrange[0.0001:1]"); g1.cmd("set xrange[0.0001:1]");
@ -560,12 +710,19 @@ void AcquisitionPerformanceTest::plot_results()
g1.set_legend(); g1.set_legend();
g1.savetops("ROC"); g1.savetops("ROC");
g1.savetopdf("ROC", 18); g1.savetopdf("ROC", 18);
if (FLAGS_show_plots) g1.showonscreen(); // window output
Gnuplot g2("linespoints"); Gnuplot g2("linespoints");
if (FLAGS_show_plots)
{
g2.showonscreen(); // window output
}
else
{
g2.disablescreen();
}
g2.cmd("set font \"Times,18\""); g2.cmd("set font \"Times,18\"");
g2.set_title("Receiver Operating Characteristic for GPS L1 C/A valid acquisition"); g2.set_title("Receiver Operating Characteristic for GPS L1 C/A valid acquisition");
g2.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition_1C.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition_1C.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\""); g2.cmd("set label 1 \"" + std::string("Coherent integration time: ") + std::to_string(config->property("Acquisition.coherent_integration_time_ms", 1)) + " ms, Non-coherent integrations: " + std::to_string(config->property("Acquisition.max_dwells", 1)) + " \" at screen 0.12, 0.83 font \"Times,16\"");
g2.cmd("set logscale x"); g2.cmd("set logscale x");
g2.cmd("set yrange [0:1]"); g2.cmd("set yrange [0:1]");
g2.cmd("set xrange[0.0001:1]"); g2.cmd("set xrange[0.0001:1]");
@ -589,7 +746,6 @@ void AcquisitionPerformanceTest::plot_results()
g2.set_legend(); g2.set_legend();
g2.savetops("ROC-valid-detection"); g2.savetops("ROC-valid-detection");
g2.savetopdf("ROC-valid-detection", 18); g2.savetopdf("ROC-valid-detection", 18);
if (FLAGS_show_plots) g2.showonscreen(); // window output
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
@ -659,22 +815,40 @@ TEST_F(AcquisitionPerformanceTest, ROC)
run_receiver(); run_receiver();
// count executions // count executions
std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_vector[pfa_iter]) + "_" + gnss_synchro.System + "_1C"; std::string basename = path_str + std::string("/acquisition_") + std::to_string(*it) + "_" + std::to_string(iter) + "_" + std::to_string(pfa_vector[pfa_iter]) + "_" + gnss_synchro.System + "_" + signal_id;
int num_executions = count_executions(basename, observed_satellite); int num_executions = count_executions(basename, observed_satellite);
// Read measured data // Read measured data
int ch = config->property("Acquisition_1C.dump_channel", 0); int ch = config->property("Acquisition.dump_channel", 0);
arma::vec meas_timestamp_s = arma::zeros(num_executions, 1); arma::vec meas_timestamp_s = arma::zeros(num_executions, 1);
arma::vec meas_doppler = arma::zeros(num_executions, 1); arma::vec meas_doppler = arma::zeros(num_executions, 1);
arma::vec positive_acq = arma::zeros(num_executions, 1); arma::vec positive_acq = arma::zeros(num_executions, 1);
arma::vec meas_acq_delay_chips = arma::zeros(num_executions, 1); arma::vec meas_acq_delay_chips = arma::zeros(num_executions, 1);
double coh_time_ms = config->property("Acquisition_1C.coherent_integration_time_ms", 1); double coh_time_ms = config->property("Acquisition.coherent_integration_time_ms", 1);
std::cout << "Num executions: " << num_executions << std::endl; std::cout << "Num executions: " << num_executions << std::endl;
unsigned int fft_size = 0;
unsigned int d_consumed_samples = coh_time_ms * config->property("GNSS-SDR.internal_fs_sps", 0) * 0.001; // * (config->property("Acquisition.bit_transition_flag", false) ? 2 : 1);
if (coh_time_ms == min_integration_ms)
{
fft_size = d_consumed_samples;
}
else
{
fft_size = d_consumed_samples * 2;
}
for (int execution = 1; execution <= num_executions; execution++) for (int execution = 1; execution <= num_executions; execution++)
{ {
acquisition_dump_reader acq_dump(basename, observed_satellite, config->property("Acquisition_1C.doppler_max", 0), config->property("Acquisition_1C.doppler_step", 0), config->property("GNSS-SDR.internal_fs_sps", 0) * GPS_L1_CA_CODE_PERIOD * static_cast<double>(coh_time_ms), ch, execution); acquisition_dump_reader acq_dump(basename,
observed_satellite,
config->property("Acquisition.doppler_max", 0),
config->property("Acquisition.doppler_step", 0),
fft_size,
ch,
execution);
acq_dump.read_binary_acq(); acq_dump.read_binary_acq();
if (acq_dump.positive_acq) if (acq_dump.positive_acq)
{ {
@ -794,7 +968,7 @@ TEST_F(AcquisitionPerformanceTest, ROC)
for (int i = 0; i < num_clean_executions - 1; i++) for (int i = 0; i < num_clean_executions - 1; i++)
{ {
if (abs(clean_delay_estimation_error(i)) < 0.5 and abs(clean_doppler_estimation_error(i)) < static_cast<float>(config->property("Acquisition_1C.doppler_step", 1)) / 2.0) if (abs(clean_delay_estimation_error(i)) < 0.5 and abs(clean_doppler_estimation_error(i)) < static_cast<float>(config->property("Acquisition.doppler_step", 1)) / 2.0)
{ {
correctly_detected = correctly_detected + 1.0; correctly_detected = correctly_detected + 1.0;
} }

View File

@ -201,6 +201,14 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::plot_grid()
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("lines"); Gnuplot g1("lines");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title("Galileo E1b/c signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); g1.set_title("Galileo E1b/c signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN));
g1.set_xlabel("Doppler [Hz]"); g1.set_xlabel("Doppler [Hz]");
g1.set_ylabel("Sample"); g1.set_ylabel("Sample");
@ -209,7 +217,6 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::plot_grid()
g1.savetops("Galileo_E1_acq_grid"); g1.savetops("Galileo_E1_acq_grid");
g1.savetopdf("Galileo_E1_acq_grid"); g1.savetopdf("Galileo_E1_acq_grid");
if (FLAGS_show_plots) g1.showonscreen();
} }
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {

View File

@ -341,7 +341,7 @@ void GlonassL1CaPcpsAcquisitionGSoC2017Test::config_2()
std::to_string(integration_time_ms)); std::to_string(integration_time_ms));
config->set_property("Acquisition.max_dwells", "1"); config->set_property("Acquisition.max_dwells", "1");
config->set_property("Acquisition.implementation", "GLONASS_L1_CA_PCPS_Acquisition"); config->set_property("Acquisition.implementation", "GLONASS_L1_CA_PCPS_Acquisition");
config->set_property("Acquisition.pfa", "0.1"); //config->set_property("Acquisition.pfa", "0.1");
config->set_property("Acquisition.doppler_max", "10000"); config->set_property("Acquisition.doppler_max", "10000");
config->set_property("Acquisition.doppler_step", "250"); config->set_property("Acquisition.doppler_step", "250");
config->set_property("Acquisition.bit_transition_flag", "false"); config->set_property("Acquisition.bit_transition_flag", "false");
@ -496,7 +496,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults)
}) << "Failure setting doppler_step."; }) << "Failure setting doppler_step.";
ASSERT_NO_THROW({ ASSERT_NO_THROW({
acquisition->set_threshold(0.5); acquisition->set_threshold(0.05);
}) << "Failure setting threshold."; }) << "Failure setting threshold.";
ASSERT_NO_THROW({ ASSERT_NO_THROW({

View File

@ -202,6 +202,14 @@ void GpsL1CaPcpsAcquisitionTest::plot_grid()
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("lines"); Gnuplot g1("lines");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title("GPS L1 C/A signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); g1.set_title("GPS L1 C/A signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN));
g1.set_xlabel("Doppler [Hz]"); g1.set_xlabel("Doppler [Hz]");
g1.set_ylabel("Sample"); g1.set_ylabel("Sample");
@ -210,7 +218,6 @@ void GpsL1CaPcpsAcquisitionTest::plot_grid()
g1.savetops("GPS_L1_acq_grid"); g1.savetops("GPS_L1_acq_grid");
g1.savetopdf("GPS_L1_acq_grid"); g1.savetopdf("GPS_L1_acq_grid");
if (FLAGS_show_plots) g1.showonscreen();
} }
catch (const GnuplotException &ge) catch (const GnuplotException &ge)
{ {

View File

@ -205,6 +205,14 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
Gnuplot::set_GNUPlotPath(gnuplot_path); Gnuplot::set_GNUPlotPath(gnuplot_path);
Gnuplot g1("impulses"); Gnuplot g1("impulses");
if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title("GPS L2CM signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN)); g1.set_title("GPS L2CM signal acquisition for satellite PRN #" + std::to_string(gnss_synchro.PRN));
g1.set_xlabel("Doppler [Hz]"); g1.set_xlabel("Doppler [Hz]");
g1.set_ylabel("Sample"); g1.set_ylabel("Sample");
@ -213,7 +221,6 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
g1.savetops("GPS_L2CM_acq_grid"); g1.savetops("GPS_L2CM_acq_grid");
g1.savetopdf("GPS_L2CM_acq_grid"); g1.savetopdf("GPS_L2CM_acq_grid");
if (FLAGS_show_plots) g1.showonscreen();
} }
catch (const GnuplotException &ge) catch (const GnuplotException &ge)
{ {

View File

@ -167,6 +167,20 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
{ {
std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl; std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl;
} }
acq_doppler_hz = 0.0;
acq_delay_samples = 0.0;
test_statistic = 0.0;
input_power = 0.0;
threshold = 0.0;
positive_acq = 0;
sample_counter = 0;
PRN = 0;
d_sat = 0;
d_doppler_max = doppler_max_;
d_doppler_step = doppler_step_;
d_samples_per_code = samples_per_code_;
d_num_doppler_bins = 0;
acquisition_dump_reader(basename, acquisition_dump_reader(basename,
sat_, sat_,
doppler_max_, doppler_max_,
@ -176,6 +190,7 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
execution); execution);
} }
acquisition_dump_reader::acquisition_dump_reader(const std::string& basename, acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
unsigned int sat, unsigned int sat,
unsigned int doppler_max, unsigned int doppler_max,
@ -197,6 +212,7 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
positive_acq = 0; positive_acq = 0;
sample_counter = 0; sample_counter = 0;
PRN = 0; PRN = 0;
if (d_doppler_step == 0) d_doppler_step = 1;
d_num_doppler_bins = static_cast<unsigned int>(ceil(static_cast<double>(static_cast<int>(d_doppler_max) - static_cast<int>(-d_doppler_max)) / static_cast<double>(d_doppler_step))); d_num_doppler_bins = static_cast<unsigned int>(ceil(static_cast<double>(static_cast<int>(d_doppler_max) - static_cast<int>(-d_doppler_max)) / static_cast<double>(d_doppler_step)));
std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code)); std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code));
mag = mag_aux; mag = mag_aux;

View File

@ -58,6 +58,8 @@
#include "signal_generator_flags.h" #include "signal_generator_flags.h"
#include "gnss_sdr_sample_counter.h" #include "gnss_sdr_sample_counter.h"
#include <matio.h> #include <matio.h>
#include "test_flags.h"
#include "gnuplot_i.h"
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES ######### // ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES #########
@ -183,6 +185,7 @@ public:
int configure_generator(); int configure_generator();
int generate_signal(); int generate_signal();
bool save_mat_xy(std::vector<double>& x, std::vector<double>& y, std::string filename);
void check_results_carrier_phase( void check_results_carrier_phase(
arma::mat& true_ch0, arma::mat& true_ch0,
arma::mat& true_ch1, arma::mat& true_ch1,
@ -283,10 +286,12 @@ void HybridObservablesTest::configure_receiver()
config->set_property("Tracking_1C.item_type", "gr_complex"); config->set_property("Tracking_1C.item_type", "gr_complex");
config->set_property("Tracking_1C.dump", "true"); config->set_property("Tracking_1C.dump", "true");
config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); config->set_property("Tracking_1C.dump_filename", "./tracking_ch_");
config->set_property("Tracking_1C.pll_bw_hz", "35.0"); config->set_property("Tracking_1C.pll_bw_hz", "5.0");
config->set_property("Tracking_1C.dll_bw_hz", "0.5"); config->set_property("Tracking_1C.dll_bw_hz", "0.20");
config->set_property("Tracking_1C.pll_bw_narrow_hz", "1.0");
config->set_property("Tracking_1C.dll_bw_narrow_hz", "0.1");
config->set_property("Tracking_1C.extend_correlation_symbols", "20");
config->set_property("Tracking_1C.early_late_space_chips", "0.5"); config->set_property("Tracking_1C.early_late_space_chips", "0.5");
config->set_property("Tracking_1C.unified", "true");
config->set_property("TelemetryDecoder_1C.dump", "true"); config->set_property("TelemetryDecoder_1C.dump", "true");
config->set_property("Observables.dump", "true"); config->set_property("Observables.dump", "true");
@ -384,6 +389,41 @@ void HybridObservablesTest::check_results_carrier_phase(
} }
bool HybridObservablesTest::save_mat_xy(std::vector<double>& x, std::vector<double>& y, std::string filename)
{
try
{
// WRITE MAT FILE
mat_t* matfp;
matvar_t* matvar;
filename.append(".mat");
std::cout << "save_mat_xy write " << filename << std::endl;
matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT5);
if (reinterpret_cast<long*>(matfp) != NULL)
{
size_t dims[2] = {1, x.size()};
matvar = Mat_VarCreate("x", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, &x[0], 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("y", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, &y[0], 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
}
else
{
std::cout << "save_mat_xy: error creating file" << std::endl;
}
Mat_Close(matfp);
return true;
}
catch (const std::exception& ex)
{
std::cout << "save_mat_xy: " << ex.what() << std::endl;
return false;
}
}
void HybridObservablesTest::check_results_code_psudorange( void HybridObservablesTest::check_results_code_psudorange(
arma::mat& true_ch0, arma::mat& true_ch0,
arma::mat& true_ch1, arma::mat& true_ch1,
@ -397,7 +437,12 @@ void HybridObservablesTest::check_results_code_psudorange(
int size1 = measured_ch0.col(0).n_rows; int size1 = measured_ch0.col(0).n_rows;
int size2 = measured_ch1.col(0).n_rows; int size2 = measured_ch1.col(0).n_rows;
double t1 = std::min(measured_ch0(size1 - 1, 0), measured_ch1(size2 - 1, 0)); double t1 = std::min(measured_ch0(size1 - 1, 0), measured_ch1(size2 - 1, 0));
arma::vec t = arma::linspace<arma::vec>(t0, t1, floor((t1 - t0) * 1e3)); arma::vec t = arma::linspace<arma::vec>(t0, t1, floor((t1 - t0) * 1e3));
//conversion between arma::vec and std:vector
arma::vec t_from_start = arma::linspace<arma::vec>(0, t1 - t0, floor((t1 - t0) * 1e3));
std::vector<double> time_vector(t_from_start.colptr(0), t_from_start.colptr(0) + t_from_start.n_rows);
arma::vec true_ch0_dist_interp; arma::vec true_ch0_dist_interp;
arma::vec true_ch1_dist_interp; arma::vec true_ch1_dist_interp;
@ -438,6 +483,31 @@ void HybridObservablesTest::check_results_code_psudorange(
<< " [meters]" << std::endl; << " [meters]" << std::endl;
std::cout.precision(ss); std::cout.precision(ss);
//plots
Gnuplot g3("linespoints");
g3.set_title("Delta Pseudorange error [m]");
g3.set_grid();
g3.set_xlabel("Time [s]");
g3.set_ylabel("Pseudorange error [m]");
//conversion between arma::vec and std:vector
std::vector<double> range_error_m(err.colptr(0), err.colptr(0) + err.n_rows);
g3.cmd("set key box opaque");
g3.plot_xy(time_vector, range_error_m,
"Delta pseudorrange error");
g3.set_legend();
g3.savetops("Delta_pseudorrange_error");
g3.savetopdf("Delta_pseudorrange_error", 18);
if (FLAGS_show_plots)
{
g3.showonscreen(); // window output
}
else
{
g3.disablescreen();
}
//check results against the test tolerance
ASSERT_LT(rmse, 0.5); ASSERT_LT(rmse, 0.5);
ASSERT_LT(error_mean, 0.5); ASSERT_LT(error_mean, 0.5);
ASSERT_GT(error_mean, -0.5); ASSERT_GT(error_mean, -0.5);
@ -468,7 +538,7 @@ TEST_F(HybridObservablesTest, ValidationOfResults)
tracking_true_obs_reader true_obs_data_ch1; tracking_true_obs_reader true_obs_data_ch1;
int test_satellite_PRN = FLAGS_test_satellite_PRN; int test_satellite_PRN = FLAGS_test_satellite_PRN;
int test_satellite_PRN2 = FLAGS_test_satellite_PRN2; int test_satellite_PRN2 = FLAGS_test_satellite_PRN2;
std::cout << "Testing satellite PRNs " << test_satellite_PRN << "," << test_satellite_PRN << std::endl; std::cout << "Testing satellite PRNs " << test_satellite_PRN << "," << test_satellite_PRN2 << std::endl;
std::string true_obs_file = std::string("./gps_l1_ca_obs_prn"); std::string true_obs_file = std::string("./gps_l1_ca_obs_prn");
true_obs_file.append(std::to_string(test_satellite_PRN)); true_obs_file.append(std::to_string(test_satellite_PRN));
true_obs_file.append(".dat"); true_obs_file.append(".dat");
@ -700,6 +770,21 @@ TEST_F(HybridObservablesTest, ValidationOfResults)
} }
//Cut measurement initial transitory of the measurements //Cut measurement initial transitory of the measurements
double initial_transitory_s = 30.0;
index = arma::find(measured_ch0.col(0) >= (measured_ch0(0, 0) + initial_transitory_s), 1, "first");
if ((index.size() > 0) and (index(0) > 0))
{
measured_ch0.shed_rows(0, index(0));
}
index = arma::find(measured_ch1.col(0) >= (measured_ch1(0, 0) + initial_transitory_s), 1, "first");
if ((index.size() > 0) and (index(0) > 0))
{
measured_ch1.shed_rows(0, index(0));
}
index = arma::find(measured_ch0.col(0) >= true_ch0(0, 0), 1, "first"); index = arma::find(measured_ch0.col(0) >= true_ch0(0, 0), 1, "first");
if ((index.size() > 0) and (index(0) > 0)) if ((index.size() > 0) and (index(0) > 0))
{ {

View File

@ -34,6 +34,7 @@
#include <unistd.h> #include <unistd.h>
#include <vector> #include <vector>
#include <armadillo> #include <armadillo>
#include <matio.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <gnuradio/top_block.h> #include <gnuradio/top_block.h>
#include <gnuradio/blocks/file_source.h> #include <gnuradio/blocks/file_source.h>
@ -136,20 +137,24 @@ public:
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error); double& std_dev_error,
double& rmse);
std::vector<double> check_results_acc_carrier_phase(arma::vec& true_time_s, std::vector<double> check_results_acc_carrier_phase(arma::vec& true_time_s,
arma::vec& true_value, arma::vec& true_value,
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error); double& std_dev_error,
double& rmse);
std::vector<double> check_results_codephase(arma::vec& true_time_s, std::vector<double> check_results_codephase(arma::vec& true_time_s,
arma::vec& true_value, arma::vec& true_value,
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error); double& std_dev_error,
double& rmse);
bool save_mat_xy(std::vector<double>& x, std::vector<double>& y, std::string filename);
GpsL1CADllPllTrackingTest() GpsL1CADllPllTrackingTest()
{ {
factory = std::make_shared<GNSSBlockFactory>(); factory = std::make_shared<GNSSBlockFactory>();
@ -267,7 +272,8 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec&
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error) double& std_dev_error,
double& rmse)
{ {
// 1. True value interpolation to match the measurement times // 1. True value interpolation to match the measurement times
arma::vec true_value_interp; arma::vec true_value_interp;
@ -289,7 +295,7 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_doppler(arma::vec&
std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows);
arma::vec err2 = arma::square(err); arma::vec err2 = arma::square(err);
double rmse = sqrt(arma::mean(err2)); rmse = sqrt(arma::mean(err2));
// 3. Mean err and variance // 3. Mean err and variance
double error_mean = arma::mean(err); double error_mean = arma::mean(err);
@ -317,7 +323,8 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(a
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error) double& std_dev_error,
double& rmse)
{ {
// 1. True value interpolation to match the measurement times // 1. True value interpolation to match the measurement times
arma::vec true_value_interp; arma::vec true_value_interp;
@ -332,12 +339,13 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(a
// 2. RMSE // 2. RMSE
arma::vec err; arma::vec err;
err = meas_value - true_value_interp; //it is required to remove the initial offset in the accumulated carrier phase error
err = (meas_value - meas_value(0)) - (true_value_interp - true_value_interp(0));
arma::vec err2 = arma::square(err); arma::vec err2 = arma::square(err);
//conversion between arma::vec and std:vector //conversion between arma::vec and std:vector
std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows);
double rmse = sqrt(arma::mean(err2)); rmse = sqrt(arma::mean(err2));
// 3. Mean err and variance // 3. Mean err and variance
double error_mean = arma::mean(err); double error_mean = arma::mean(err);
@ -364,7 +372,8 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec
arma::vec& meas_time_s, arma::vec& meas_time_s,
arma::vec& meas_value, arma::vec& meas_value,
double& mean_error, double& mean_error,
double& std_dev_error) double& std_dev_error,
double& rmse)
{ {
// 1. True value interpolation to match the measurement times // 1. True value interpolation to match the measurement times
arma::vec true_value_interp; arma::vec true_value_interp;
@ -385,7 +394,7 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_codephase(arma::vec
std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows); std::vector<double> err_std_vector(err.colptr(0), err.colptr(0) + err.n_rows);
arma::vec err2 = arma::square(err); arma::vec err2 = arma::square(err);
double rmse = sqrt(arma::mean(err2)); rmse = sqrt(arma::mean(err2));
// 3. Mean err and variance // 3. Mean err and variance
double error_mean = arma::mean(err); double error_mean = arma::mean(err);
@ -420,12 +429,15 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
//data containers for config param sweep //data containers for config param sweep
std::vector<std::vector<double>> mean_doppler_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> mean_doppler_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> std_dev_doppler_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> std_dev_doppler_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> rmse_doppler_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> mean_code_phase_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> mean_code_phase_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> std_dev_code_phase_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> std_dev_code_phase_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> rmse_code_phase_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> mean_carrier_phase_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> mean_carrier_phase_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> std_dev_carrier_phase_error_sweep; //swep config param and cn0 sweep std::vector<std::vector<double>> std_dev_carrier_phase_error_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> rmse_carrier_phase_sweep; //swep config param and cn0 sweep
std::vector<std::vector<double>> trk_valid_timestamp_s_sweep; std::vector<std::vector<double>> trk_valid_timestamp_s_sweep;
std::vector<std::vector<double>> generator_CN0_values_sweep_copy; std::vector<std::vector<double>> generator_CN0_values_sweep_copy;
@ -528,14 +540,18 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
std::vector<std::vector<double>> doppler_error_sweep; std::vector<std::vector<double>> doppler_error_sweep;
std::vector<std::vector<double>> code_phase_error_sweep; std::vector<std::vector<double>> code_phase_error_sweep;
std::vector<std::vector<double>> code_phase_error_meters_sweep;
std::vector<std::vector<double>> acc_carrier_phase_error_sweep; std::vector<std::vector<double>> acc_carrier_phase_error_sweep;
std::vector<double> mean_doppler_error; std::vector<double> mean_doppler_error;
std::vector<double> std_dev_doppler_error; std::vector<double> std_dev_doppler_error;
std::vector<double> rmse_doppler;
std::vector<double> mean_code_phase_error; std::vector<double> mean_code_phase_error;
std::vector<double> std_dev_code_phase_error; std::vector<double> std_dev_code_phase_error;
std::vector<double> rmse_code_phase;
std::vector<double> mean_carrier_phase_error; std::vector<double> mean_carrier_phase_error;
std::vector<double> std_dev_carrier_phase_error; std::vector<double> std_dev_carrier_phase_error;
std::vector<double> rmse_carrier_phase;
std::vector<double> valid_CN0_values; std::vector<double> valid_CN0_values;
configure_receiver(PLL_wide_bw_values.at(config_idx), configure_receiver(PLL_wide_bw_values.at(config_idx),
@ -682,6 +698,7 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
{ {
std::vector<double> doppler_error_hz; std::vector<double> doppler_error_hz;
std::vector<double> code_phase_error_chips; std::vector<double> code_phase_error_chips;
std::vector<double> code_phase_error_meters;
std::vector<double> acc_carrier_phase_hz; std::vector<double> acc_carrier_phase_hz;
try try
@ -707,7 +724,7 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
epoch_counter++; epoch_counter++;
} }
// Align initial measurements and cut the tracking pull-in transitory // Align initial measurements and cut the tracking pull-in transitory
double pull_in_offset_s = 1.0; double pull_in_offset_s = FLAGS_skip_trk_transitory_s;
arma::uvec initial_meas_point = arma::find(trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first"); arma::uvec initial_meas_point = arma::find(trk_timestamp_s >= (true_timestamp_s(0) + pull_in_offset_s), 1, "first");
if (initial_meas_point.size() > 0 and tracking_last_msg != 3) if (initial_meas_point.size() > 0 and tracking_last_msg != 3)
@ -720,20 +737,28 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
double mean_error; double mean_error;
double std_dev_error; double std_dev_error;
double rmse;
valid_CN0_values.push_back(generator_CN0_values.at(current_cn0_idx)); //save the current cn0 value (valid tracking) valid_CN0_values.push_back(generator_CN0_values.at(current_cn0_idx)); //save the current cn0 value (valid tracking)
doppler_error_hz = check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz, mean_error, std_dev_error); doppler_error_hz = check_results_doppler(true_timestamp_s, true_Doppler_Hz, trk_timestamp_s, trk_Doppler_Hz, mean_error, std_dev_error, rmse);
mean_doppler_error.push_back(mean_error); mean_doppler_error.push_back(mean_error);
std_dev_doppler_error.push_back(std_dev_error); std_dev_doppler_error.push_back(std_dev_error);
rmse_doppler.push_back(rmse);
code_phase_error_chips = check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips, mean_error, std_dev_error); code_phase_error_chips = check_results_codephase(true_timestamp_s, true_prn_delay_chips, trk_timestamp_s, trk_prn_delay_chips, mean_error, std_dev_error, rmse);
for (unsigned int ii = 0; ii < code_phase_error_chips.size(); ii++)
{
code_phase_error_meters.push_back(GPS_L1_CA_CHIP_PERIOD * code_phase_error_chips.at(ii) * GPS_C_m_s);
}
mean_code_phase_error.push_back(mean_error); mean_code_phase_error.push_back(mean_error);
std_dev_code_phase_error.push_back(std_dev_error); std_dev_code_phase_error.push_back(std_dev_error);
rmse_code_phase.push_back(rmse);
acc_carrier_phase_hz = check_results_acc_carrier_phase(true_timestamp_s, true_acc_carrier_phase_cycles, trk_timestamp_s, trk_acc_carrier_phase_cycles, mean_error, std_dev_error); acc_carrier_phase_hz = check_results_acc_carrier_phase(true_timestamp_s, true_acc_carrier_phase_cycles, trk_timestamp_s, trk_acc_carrier_phase_cycles, mean_error, std_dev_error, rmse);
mean_carrier_phase_error.push_back(mean_error); mean_carrier_phase_error.push_back(mean_error);
std_dev_carrier_phase_error.push_back(std_dev_error); std_dev_carrier_phase_error.push_back(std_dev_error);
rmse_carrier_phase.push_back(rmse);
//save tracking measurement timestamps to std::vector //save tracking measurement timestamps to std::vector
std::vector<double> vector_trk_timestamp_s(trk_timestamp_s.colptr(0), trk_timestamp_s.colptr(0) + trk_timestamp_s.n_rows); std::vector<double> vector_trk_timestamp_s(trk_timestamp_s.colptr(0), trk_timestamp_s.colptr(0) + trk_timestamp_s.n_rows);
@ -741,6 +766,7 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
doppler_error_sweep.push_back(doppler_error_hz); doppler_error_sweep.push_back(doppler_error_hz);
code_phase_error_sweep.push_back(code_phase_error_chips); code_phase_error_sweep.push_back(code_phase_error_chips);
code_phase_error_meters_sweep.push_back(code_phase_error_meters);
acc_carrier_phase_error_sweep.push_back(acc_carrier_phase_hz); acc_carrier_phase_error_sweep.push_back(acc_carrier_phase_hz);
} }
else else
@ -760,10 +786,16 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
{ {
mean_doppler_error_sweep.push_back(mean_doppler_error); mean_doppler_error_sweep.push_back(mean_doppler_error);
std_dev_doppler_error_sweep.push_back(std_dev_doppler_error); std_dev_doppler_error_sweep.push_back(std_dev_doppler_error);
rmse_doppler_sweep.push_back(rmse_doppler);
mean_code_phase_error_sweep.push_back(mean_code_phase_error); mean_code_phase_error_sweep.push_back(mean_code_phase_error);
std_dev_code_phase_error_sweep.push_back(std_dev_code_phase_error); std_dev_code_phase_error_sweep.push_back(std_dev_code_phase_error);
rmse_code_phase_sweep.push_back(rmse_code_phase);
mean_carrier_phase_error_sweep.push_back(mean_carrier_phase_error); mean_carrier_phase_error_sweep.push_back(mean_carrier_phase_error);
std_dev_carrier_phase_error_sweep.push_back(std_dev_carrier_phase_error); std_dev_carrier_phase_error_sweep.push_back(std_dev_carrier_phase_error);
rmse_carrier_phase_sweep.push_back(rmse_carrier_phase);
//make a copy of the CN0 vector for each configuration parameter in order to filter the loss of lock events //make a copy of the CN0 vector for each configuration parameter in order to filter the loss of lock events
generator_CN0_values_sweep_copy.push_back(valid_CN0_values); generator_CN0_values_sweep_copy.push_back(valid_CN0_values);
} }
@ -795,7 +827,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++)
{ {
Gnuplot g1("linespoints"); Gnuplot g1("linespoints");
if (FLAGS_show_plots) g1.showonscreen(); // window output if (FLAGS_show_plots)
{
g1.showonscreen(); // window output
}
else
{
g1.disablescreen();
}
g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz" + "GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g1.set_grid(); g1.set_grid();
g1.set_xlabel("Time [s]"); g1.set_xlabel("Time [s]");
@ -809,7 +848,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18); g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18);
} }
Gnuplot g2("points"); Gnuplot g2("points");
if (FLAGS_show_plots) g2.showonscreen(); // window output if (FLAGS_show_plots)
{
g2.showonscreen(); // window output
}
else
{
g2.disablescreen();
}
g2.set_multiplot(ceil(static_cast<float>(generator_CN0_values.size()) / 2.0), g2.set_multiplot(ceil(static_cast<float>(generator_CN0_values.size()) / 2.0),
ceil(static_cast<float>(generator_CN0_values.size()) / 2)); ceil(static_cast<float>(generator_CN0_values.size()) / 2));
for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++)
@ -840,7 +886,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
g3.set_legend(); g3.set_legend();
g3.savetops("CN0_output"); g3.savetops("CN0_output");
g3.savetopdf("CN0_output", 18); g3.savetopdf("CN0_output", 18);
if (FLAGS_show_plots) g3.showonscreen(); // window output if (FLAGS_show_plots)
{
g3.showonscreen(); // window output
}
else
{
g3.disablescreen();
}
} }
//PLOT ERROR FIGURES (only if it is used the signal generator) //PLOT ERROR FIGURES (only if it is used the signal generator)
@ -849,7 +902,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
if (FLAGS_plot_detail_level >= 1) if (FLAGS_plot_detail_level >= 1)
{ {
Gnuplot g5("points"); Gnuplot g5("points");
if (FLAGS_show_plots) g5.showonscreen(); // window output if (FLAGS_show_plots)
{
g5.showonscreen(); // window output
}
else
{
g5.disablescreen();
}
g5.set_title("Code delay error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g5.set_title("Code delay error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g5.set_grid(); g5.set_grid();
g5.set_xlabel("Time [s]"); g5.set_xlabel("Time [s]");
@ -866,15 +926,61 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
} }
save_mat_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx),
code_phase_error_sweep.at(current_cn0_idx),
"Code_error_chips" + std::to_string(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)) +
std::to_string(PLL_wide_bw_values.at(config_idx)) + "_" + std::to_string(DLL_wide_bw_values.at(config_idx)));
} }
g5.set_legend(); g5.set_legend();
g5.set_legend(); g5.set_legend();
g5.savetops("Code_error_output"); g5.savetops("Code_error_chips");
g5.savetopdf("Code_error_output", 18); g5.savetopdf("Code_error_chips", 18);
Gnuplot g5b("points");
if (FLAGS_show_plots)
{
g5b.showonscreen(); // window output
}
else
{
g5b.disablescreen();
}
g5b.set_title("Code delay error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g5b.set_grid();
g5b.set_xlabel("Time [s]");
g5b.set_ylabel("Code delay error [meters]");
for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values_sweep_copy.at(config_idx).size(); current_cn0_idx++)
{
try
{
g5b.plot_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx), code_phase_error_meters_sweep.at(current_cn0_idx),
std::to_string(static_cast<int>(round(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)))) + "[dB-Hz]", decimate);
}
catch (const GnuplotException& ge)
{
}
save_mat_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx),
code_phase_error_sweep.at(current_cn0_idx),
"Code_error_meters" + std::to_string(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)) +
std::to_string(PLL_wide_bw_values.at(config_idx)) + "_" + std::to_string(DLL_wide_bw_values.at(config_idx)));
}
g5b.set_legend();
g5b.set_legend();
g5b.savetops("Code_error_meters");
g5b.savetopdf("Code_error_meters", 18);
Gnuplot g6("points"); Gnuplot g6("points");
if (FLAGS_show_plots) g6.showonscreen(); // window output if (FLAGS_show_plots)
{
g6.showonscreen(); // window output
}
else
{
g6.disablescreen();
}
g6.set_title("Accumulated carrier phase error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g6.set_title("Accumulated carrier phase error, PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g6.set_grid(); g6.set_grid();
g6.set_xlabel("Time [s]"); g6.set_xlabel("Time [s]");
@ -891,20 +997,31 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
} }
save_mat_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx),
acc_carrier_phase_error_sweep.at(current_cn0_idx),
"Carrier_phase_error" + std::to_string(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)) +
std::to_string(PLL_wide_bw_values.at(config_idx)) + "_" + std::to_string(DLL_wide_bw_values.at(config_idx)));
} }
g6.set_legend(); g6.set_legend();
g6.set_legend(); g6.set_legend();
g6.savetops("Carrier_phase_error_output"); g6.savetops("Acc_carrier_phase_error_cycles");
g6.savetopdf("Carrier_phase_error_output", 18); g6.savetopdf("Acc_carrier_phase_error_cycles", 18);
Gnuplot g4("points"); Gnuplot g4("points");
if (FLAGS_show_plots) g4.showonscreen(); // window output if (FLAGS_show_plots)
{
g4.showonscreen(); // window output
}
else
{
g4.disablescreen();
}
g4.set_multiplot(ceil(static_cast<float>(generator_CN0_values.size()) / 2.0), g4.set_multiplot(ceil(static_cast<float>(generator_CN0_values.size()) / 2.0),
ceil(static_cast<float>(generator_CN0_values.size()) / 2)); ceil(static_cast<float>(generator_CN0_values.size()) / 2));
for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values_sweep_copy.at(config_idx).size(); current_cn0_idx++) for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values_sweep_copy.at(config_idx).size(); current_cn0_idx++)
{ {
g4.reset_plot(); g4.reset_plot();
g4.set_title(std::to_string(static_cast<int>(round(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)))) + "[dB-Hz], PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g4.set_title("Dopper error" + std::to_string(static_cast<int>(round(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)))) + "[dB-Hz], PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_idx)) + "," + std::to_string(DLL_wide_bw_values.at(config_idx)) + " Hz (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g4.set_grid(); g4.set_grid();
//g4.cmd("set key box opaque"); //g4.cmd("set key box opaque");
g4.set_xlabel("Time [s]"); g4.set_xlabel("Time [s]");
@ -917,10 +1034,15 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
catch (const GnuplotException& ge) catch (const GnuplotException& ge)
{ {
} }
save_mat_xy(trk_valid_timestamp_s_sweep.at(current_cn0_idx),
doppler_error_sweep.at(current_cn0_idx),
"Doppler_error" + std::to_string(generator_CN0_values_sweep_copy.at(config_idx).at(current_cn0_idx)) +
std::to_string(PLL_wide_bw_values.at(config_idx)) + "_" + std::to_string(DLL_wide_bw_values.at(config_idx)));
} }
g4.unset_multiplot(); g4.unset_multiplot();
g4.savetops("Doppler_error_output"); g4.savetops("Doppler_error_hz");
g4.savetopdf("Doppler_error_output", 18); g4.savetopdf("Doppler_error_hz", 18);
} }
} }
} }
@ -942,7 +1064,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
//plot metrics //plot metrics
Gnuplot g7("linespoints"); Gnuplot g7("linespoints");
if (FLAGS_show_plots) g7.showonscreen(); // window output if (FLAGS_show_plots)
{
g7.showonscreen(); // window output
}
else
{
g7.disablescreen();
}
g7.set_title("Doppler error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g7.set_title("Doppler error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g7.set_grid(); g7.set_grid();
g7.set_xlabel("CN0 [dB-Hz]"); g7.set_xlabel("CN0 [dB-Hz]");
@ -957,10 +1086,17 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
std_dev_doppler_error_sweep.at(config_sweep_idx), std_dev_doppler_error_sweep.at(config_sweep_idx),
"PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz");
//matlab save
save_mat_xy(generator_CN0_values_sweep_copy.at(config_sweep_idx),
rmse_doppler_sweep.at(config_sweep_idx),
"RMSE_Doppler_CN0_Sweep_PLL_DLL" + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"_" + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)));
} }
g7.savetops("Doppler_error_metrics"); g7.savetops("Doppler_error_metrics");
g7.savetopdf("Doppler_error_metrics", 18); g7.savetopdf("Doppler_error_metrics", 18);
Gnuplot g8("linespoints"); Gnuplot g8("linespoints");
g8.set_title("Accumulated carrier phase error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); g8.set_title("Accumulated carrier phase error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
g8.set_grid(); g8.set_grid();
@ -976,6 +1112,11 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
std_dev_carrier_phase_error_sweep.at(config_sweep_idx), std_dev_carrier_phase_error_sweep.at(config_sweep_idx),
"PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz");
//matlab save
save_mat_xy(generator_CN0_values_sweep_copy.at(config_sweep_idx),
rmse_carrier_phase_sweep.at(config_sweep_idx),
"RMSE_Carrier_Phase_CN0_Sweep_PLL_DLL" + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"_" + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)));
} }
g8.savetops("Carrier_error_metrics"); g8.savetops("Carrier_error_metrics");
g8.savetopdf("Carrier_error_metrics", 18); g8.savetopdf("Carrier_error_metrics", 18);
@ -995,6 +1136,11 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
std_dev_code_phase_error_sweep.at(config_sweep_idx), std_dev_code_phase_error_sweep.at(config_sweep_idx),
"PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) + "PLL/DLL BW: " + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz"); +"," + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)) + " Hz");
//matlab save
save_mat_xy(generator_CN0_values_sweep_copy.at(config_sweep_idx),
rmse_code_phase_sweep.at(config_sweep_idx),
"RMSE_Code_Phase_CN0_Sweep_PLL_DLL" + std::to_string(PLL_wide_bw_values.at(config_sweep_idx)) +
+"_" + std::to_string(DLL_wide_bw_values.at(config_sweep_idx)));
} }
g9.savetops("Code_error_metrics"); g9.savetops("Code_error_metrics");
g9.savetopdf("Code_error_metrics", 18); g9.savetopdf("Code_error_metrics", 18);
@ -1006,3 +1152,33 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
} }
} }
} }
bool GpsL1CADllPllTrackingTest::save_mat_xy(std::vector<double>& x, std::vector<double>& y, std::string filename)
{
try
{
// WRITE MAT FILE
mat_t* matfp;
matvar_t* matvar;
filename.erase(filename.length() - 4, 4);
filename.append(".mat");
matfp = Mat_CreateVer(filename.c_str(), NULL, MAT_FT_MAT73);
if (reinterpret_cast<long*>(matfp) != NULL)
{
size_t dims[2] = {1, x.size()};
matvar = Mat_VarCreate("x", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, &x[0], 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
matvar = Mat_VarCreate("y", MAT_C_DOUBLE, MAT_T_DOUBLE, 2, dims, &y[0], 0);
Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB); // or MAT_COMPRESSION_NONE
Mat_VarFree(matvar);
}
Mat_Close(matfp);
return true;
}
catch (const std::exception& ex)
{
return false;
}
}

View File

@ -1,5 +1,5 @@
/*! /*!
* \file gps_l1_ca_dll_pll_tracking_test.cc * \file tracking_test.cc
* \brief This class implements a tracking Pull-In test for GPS_L1_CA_DLL_PLL_Tracking * \brief This class implements a tracking Pull-In test for GPS_L1_CA_DLL_PLL_Tracking
* implementation based on some input parameters. * implementation based on some input parameters.
* \author Javier Arribas, 2018. jarribas(at)cttc.es * \author Javier Arribas, 2018. jarribas(at)cttc.es
@ -40,11 +40,17 @@
#include <gnuradio/blocks/interleaved_char_to_complex.h> #include <gnuradio/blocks/interleaved_char_to_complex.h>
#include <gnuradio/blocks/null_sink.h> #include <gnuradio/blocks/null_sink.h>
#include <gnuradio/blocks/skiphead.h> #include <gnuradio/blocks/skiphead.h>
#include <gnuradio/blocks/head.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "GPS_L1_CA.h" #include "GPS_L1_CA.h"
#include "gnss_block_factory.h" #include "gnss_block_factory.h"
#include "tracking_interface.h" #include "tracking_interface.h"
#include "gps_l2_m_pcps_acquisition.h"
#include "gps_l1_ca_pcps_acquisition.h"
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h" #include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
#include "galileo_e5a_noncoherent_iq_acquisition_caf.h"
#include "galileo_e5a_pcps_acquisition.h"
#include "gps_l5i_pcps_acquisition.h"
#include "in_memory_configuration.h" #include "in_memory_configuration.h"
#include "tracking_true_obs_reader.h" #include "tracking_true_obs_reader.h"
#include "tracking_dump_reader.h" #include "tracking_dump_reader.h"
@ -71,6 +77,7 @@ private:
public: public:
int rx_message; int rx_message;
gr::top_block_sptr top_block;
~Acquisition_msg_rx(); //!< Default destructor ~Acquisition_msg_rx(); //!< Default destructor
}; };
@ -87,6 +94,7 @@ void Acquisition_msg_rx::msg_handler_events(pmt::pmt_t msg)
{ {
long int message = pmt::to_long(msg); long int message = pmt::to_long(msg);
rx_message = message; rx_message = message;
top_block->stop(); //stop the flowgraph
} }
catch (boost::bad_any_cast& e) catch (boost::bad_any_cast& e)
{ {
@ -106,32 +114,32 @@ Acquisition_msg_rx::Acquisition_msg_rx() : gr::block("Acquisition_msg_rx", gr::i
Acquisition_msg_rx::~Acquisition_msg_rx() {} Acquisition_msg_rx::~Acquisition_msg_rx() {}
// ######## GNURADIO TRACKING BLOCK MESSAGE RECEVER ######### // ######## GNURADIO TRACKING BLOCK MESSAGE RECEVER #########
class GpsL1CADllPllTrackingPullInTest_msg_rx; class TrackingPullInTest_msg_rx;
typedef boost::shared_ptr<GpsL1CADllPllTrackingPullInTest_msg_rx> GpsL1CADllPllTrackingPullInTest_msg_rx_sptr; typedef boost::shared_ptr<TrackingPullInTest_msg_rx> TrackingPullInTest_msg_rx_sptr;
GpsL1CADllPllTrackingPullInTest_msg_rx_sptr GpsL1CADllPllTrackingPullInTest_msg_rx_make(); TrackingPullInTest_msg_rx_sptr TrackingPullInTest_msg_rx_make();
class GpsL1CADllPllTrackingPullInTest_msg_rx : public gr::block class TrackingPullInTest_msg_rx : public gr::block
{ {
private: private:
friend GpsL1CADllPllTrackingPullInTest_msg_rx_sptr GpsL1CADllPllTrackingPullInTest_msg_rx_make(); friend TrackingPullInTest_msg_rx_sptr TrackingPullInTest_msg_rx_make();
void msg_handler_events(pmt::pmt_t msg); void msg_handler_events(pmt::pmt_t msg);
GpsL1CADllPllTrackingPullInTest_msg_rx(); TrackingPullInTest_msg_rx();
public: public:
int rx_message; int rx_message;
~GpsL1CADllPllTrackingPullInTest_msg_rx(); //!< Default destructor ~TrackingPullInTest_msg_rx(); //!< Default destructor
}; };
GpsL1CADllPllTrackingPullInTest_msg_rx_sptr GpsL1CADllPllTrackingPullInTest_msg_rx_make() TrackingPullInTest_msg_rx_sptr TrackingPullInTest_msg_rx_make()
{ {
return GpsL1CADllPllTrackingPullInTest_msg_rx_sptr(new GpsL1CADllPllTrackingPullInTest_msg_rx()); return TrackingPullInTest_msg_rx_sptr(new TrackingPullInTest_msg_rx());
} }
void GpsL1CADllPllTrackingPullInTest_msg_rx::msg_handler_events(pmt::pmt_t msg) void TrackingPullInTest_msg_rx::msg_handler_events(pmt::pmt_t msg)
{ {
try try
{ {
@ -147,22 +155,22 @@ void GpsL1CADllPllTrackingPullInTest_msg_rx::msg_handler_events(pmt::pmt_t msg)
} }
GpsL1CADllPllTrackingPullInTest_msg_rx::GpsL1CADllPllTrackingPullInTest_msg_rx() : gr::block("GpsL1CADllPllTrackingPullInTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) TrackingPullInTest_msg_rx::TrackingPullInTest_msg_rx() : gr::block("TrackingPullInTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0))
{ {
this->message_port_register_in(pmt::mp("events")); this->message_port_register_in(pmt::mp("events"));
this->set_msg_handler(pmt::mp("events"), boost::bind(&GpsL1CADllPllTrackingPullInTest_msg_rx::msg_handler_events, this, _1)); this->set_msg_handler(pmt::mp("events"), boost::bind(&TrackingPullInTest_msg_rx::msg_handler_events, this, _1));
rx_message = 0; rx_message = 0;
} }
GpsL1CADllPllTrackingPullInTest_msg_rx::~GpsL1CADllPllTrackingPullInTest_msg_rx() TrackingPullInTest_msg_rx::~TrackingPullInTest_msg_rx()
{ {
} }
// ########################################################### // ###########################################################
class GpsL1CADllPllTrackingPullInTest : public ::testing::Test class TrackingPullInTest : public ::testing::Test
{ {
public: public:
std::string generator_binary; std::string generator_binary;
@ -172,7 +180,7 @@ public:
std::string p4; std::string p4;
std::string p5; std::string p5;
std::string p6; std::string p6;
std::string implementation = "GPS_L1_CA_DLL_PLL_Tracking"; //"GPS_L1_CA_DLL_PLL_C_Aid_Tracking"; std::string implementation = FLAGS_trk_test_implementation;
const int baseband_sampling_freq = FLAGS_fs_gen_sps; const int baseband_sampling_freq = FLAGS_fs_gen_sps;
@ -204,7 +212,7 @@ public:
double& mean_error, double& mean_error,
double& std_dev_error); double& std_dev_error);
GpsL1CADllPllTrackingPullInTest() TrackingPullInTest()
{ {
factory = std::make_shared<GNSSBlockFactory>(); factory = std::make_shared<GNSSBlockFactory>();
config = std::make_shared<InMemoryConfiguration>(); config = std::make_shared<InMemoryConfiguration>();
@ -212,7 +220,7 @@ public:
gnss_synchro = Gnss_Synchro(); gnss_synchro = Gnss_Synchro();
} }
~GpsL1CADllPllTrackingPullInTest() ~TrackingPullInTest()
{ {
} }
@ -231,7 +239,7 @@ public:
}; };
int GpsL1CADllPllTrackingPullInTest::configure_generator(double CN0_dBHz, int file_idx) int TrackingPullInTest::configure_generator(double CN0_dBHz, int file_idx)
{ {
// Configure signal generator // Configure signal generator
generator_binary = FLAGS_generator_binary; generator_binary = FLAGS_generator_binary;
@ -253,7 +261,7 @@ int GpsL1CADllPllTrackingPullInTest::configure_generator(double CN0_dBHz, int fi
} }
int GpsL1CADllPllTrackingPullInTest::generate_signal() int TrackingPullInTest::generate_signal()
{ {
int child_status; int child_status;
@ -276,48 +284,104 @@ int GpsL1CADllPllTrackingPullInTest::generate_signal()
} }
void GpsL1CADllPllTrackingPullInTest::configure_receiver( void TrackingPullInTest::configure_receiver(
double PLL_wide_bw_hz, double PLL_wide_bw_hz,
double DLL_wide_bw_hz, double DLL_wide_bw_hz,
double PLL_narrow_bw_hz, double PLL_narrow_bw_hz,
double DLL_narrow_bw_hz, double DLL_narrow_bw_hz,
int extend_correlation_symbols) int extend_correlation_symbols)
{ {
config = std::make_shared<InMemoryConfiguration>();
config->set_property("Tracking.dump", "true");
config->set_property("Tracking.dump_filename", "./tracking_ch_");
config->set_property("Tracking.implementation", implementation);
config->set_property("Tracking.item_type", "gr_complex");
config->set_property("Tracking.pll_bw_hz", std::to_string(PLL_wide_bw_hz));
config->set_property("Tracking.dll_bw_hz", std::to_string(DLL_wide_bw_hz));
config->set_property("Tracking.extend_correlation_symbols", std::to_string(extend_correlation_symbols));
config->set_property("Tracking.pll_bw_narrow_hz", std::to_string(PLL_narrow_bw_hz));
config->set_property("Tracking.dll_bw_narrow_hz", std::to_string(DLL_narrow_bw_hz));
gnss_synchro.PRN = FLAGS_test_satellite_PRN;
gnss_synchro.Channel_ID = 0; gnss_synchro.Channel_ID = 0;
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
std::string System_and_Signal;
if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0)
{
gnss_synchro.System = 'G'; gnss_synchro.System = 'G';
std::string signal = "1C"; std::string signal = "1C";
System_and_Signal = "GPS L1 CA";
signal.copy(gnss_synchro.Signal, 2, 0); signal.copy(gnss_synchro.Signal, 2, 0);
gnss_synchro.PRN = FLAGS_test_satellite_PRN; config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.early_late_space_narrow_chips", "0.5");
config = std::make_shared<InMemoryConfiguration>(); }
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0)
// Set Tracking {
config->set_property("Tracking_1C.implementation", implementation); gnss_synchro.System = 'E';
config->set_property("Tracking_1C.item_type", "gr_complex"); std::string signal = "1B";
config->set_property("Tracking_1C.pll_bw_hz", std::to_string(PLL_wide_bw_hz)); System_and_Signal = "Galileo E1B";
config->set_property("Tracking_1C.dll_bw_hz", std::to_string(DLL_wide_bw_hz)); signal.copy(gnss_synchro.Signal, 2, 0);
config->set_property("Tracking_1C.early_late_space_chips", "0.5"); config->set_property("Tracking.early_late_space_chips", "0.15");
config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_symbols)); config->set_property("Tracking.very_early_late_space_chips", "0.6");
config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(PLL_narrow_bw_hz)); config->set_property("Tracking.early_late_space_narrow_chips", "0.15");
config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(DLL_narrow_bw_hz)); config->set_property("Tracking.very_early_late_space_narrow_chips", "0.6");
config->set_property("Tracking_1C.early_late_space_narrow_chips", "0.5"); config->set_property("Tracking.track_pilot", "true");
config->set_property("Tracking_1C.dump", "true"); }
config->set_property("Tracking_1C.dump_filename", "./tracking_ch_"); else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0)
{
gnss_synchro.System = 'G';
std::string signal = "2S";
System_and_Signal = "GPS L2CM";
signal.copy(gnss_synchro.Signal, 2, 0);
config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false");
}
else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0 or implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0)
{
gnss_synchro.System = 'E';
std::string signal = "5X";
System_and_Signal = "Galileo E5a";
signal.copy(gnss_synchro.Signal, 2, 0);
if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0)
{
config->supersede_property("Tracking.implementation", std::string("Galileo_E5a_DLL_PLL_Tracking"));
}
config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false");
config->set_property("Tracking.order", "2");
}
else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0)
{
gnss_synchro.System = 'G';
std::string signal = "L5";
System_and_Signal = "GPS L5I";
signal.copy(gnss_synchro.Signal, 2, 0);
config->set_property("Tracking.early_late_space_chips", "0.5");
config->set_property("Tracking.track_pilot", "false");
config->set_property("Tracking.order", "2");
}
else
{
std::cout << "The test can not run with the selected tracking implementation\n ";
throw(std::exception());
}
std::cout << "*****************************************\n"; std::cout << "*****************************************\n";
std::cout << "*** Tracking configuration parameters ***\n"; std::cout << "*** Tracking configuration parameters ***\n";
std::cout << "*****************************************\n"; std::cout << "*****************************************\n";
std::cout << "pll_bw_hz: " << config->property("Tracking_1C.pll_bw_hz", 0.0) << " Hz\n"; std::cout << "Signal: " << System_and_Signal << "\n";
std::cout << "dll_bw_hz: " << config->property("Tracking_1C.dll_bw_hz", 0.0) << " Hz\n"; std::cout << "implementation: " << config->property("Tracking.implementation", std::string("undefined")) << " \n";
std::cout << "pll_bw_narrow_hz: " << config->property("Tracking_1C.pll_bw_narrow_hz", 0.0) << " Hz\n"; std::cout << "pll_bw_hz: " << config->property("Tracking.pll_bw_hz", 0.0) << " Hz\n";
std::cout << "dll_bw_narrow_hz: " << config->property("Tracking_1C.dll_bw_narrow_hz", 0.0) << " Hz\n"; std::cout << "dll_bw_hz: " << config->property("Tracking.dll_bw_hz", 0.0) << " Hz\n";
std::cout << "extend_correlation_symbols: " << config->property("Tracking_1C.extend_correlation_symbols", 0) << " Symbols\n"; std::cout << "pll_bw_narrow_hz: " << config->property("Tracking.pll_bw_narrow_hz", 0.0) << " Hz\n";
std::cout << "dll_bw_narrow_hz: " << config->property("Tracking.dll_bw_narrow_hz", 0.0) << " Hz\n";
std::cout << "extend_correlation_symbols: " << config->property("Tracking.extend_correlation_symbols", 0) << " Symbols\n";
std::cout << "*****************************************\n"; std::cout << "*****************************************\n";
std::cout << "*****************************************\n"; std::cout << "*****************************************\n";
} }
bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID) bool TrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
{ {
// 1. Setup GNU Radio flowgraph (file_source -> Acquisition_10m) // 1. Setup GNU Radio flowgraph (file_source -> Acquisition_10m)
gr::top_block_sptr top_block; gr::top_block_sptr top_block;
@ -326,23 +390,110 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
// Satellite signal definition // Satellite signal definition
Gnss_Synchro tmp_gnss_synchro; Gnss_Synchro tmp_gnss_synchro;
tmp_gnss_synchro.Channel_ID = 0; tmp_gnss_synchro.Channel_ID = 0;
config = std::make_shared<InMemoryConfiguration>();
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
config->set_property("Acquisition.blocking_on_standby", "true");
config->set_property("Acquisition.blocking", "true");
config->set_property("Acquisition.dump", "false");
config->set_property("Acquisition.dump_filename", "./data/acquisition.dat");
config->set_property("Acquisition.use_CFAR_algorithm", "false");
std::shared_ptr<AcquisitionInterface> acquisition;
std::string System_and_Signal;
//create the correspondign acquisition block according to the desired tracking signal
if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0)
{
tmp_gnss_synchro.System = 'G'; tmp_gnss_synchro.System = 'G';
std::string signal = "1C"; std::string signal = "1C";
signal.copy(tmp_gnss_synchro.Signal, 2, 0); signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID; tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L1 CA";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
acquisition = std::make_shared<GpsL1CaPcpsAcquisitionFineDoppler>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0)
{
tmp_gnss_synchro.System = 'E';
std::string signal = "1B";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E1B";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
acquisition = std::make_shared<GalileoE1PcpsAmbiguousAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0)
{
tmp_gnss_synchro.System = 'G';
std::string signal = "2S";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L2CM";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
acquisition = std::make_shared<GpsL2MPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0)
{
tmp_gnss_synchro.System = 'E';
std::string signal = "5X";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E5a";
config->set_property("Acquisition_5X.coherent_integration_time_ms", "1");
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
config->set_property("Acquisition.CAF_window_hz", "0"); // **Only for E5a** Resolves doppler ambiguity averaging the specified BW in the winner code delay. If set to 0 CAF filter is desactivated. Recommended value 3000 Hz
config->set_property("Acquisition.Zero_padding", "0"); //**Only for E5a** Avoids power loss and doppler ambiguity in bit transitions by correlating one code with twice the input data length, ensuring that at least one full code is present without transitions. If set to 1 it is ON, if set to 0 it is OFF.
config->set_property("Acquisition.bit_transition_flag", "false");
acquisition = std::make_shared<GalileoE5aNoncoherentIQAcquisitionCaf>(config.get(), "Acquisition", 1, 0);
}
config = std::make_shared<InMemoryConfiguration>(); else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0)
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); {
tmp_gnss_synchro.System = 'E';
std::string signal = "5X";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "Galileo E5a";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
acquisition = std::make_shared<GalileoE5aPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0)
{
tmp_gnss_synchro.System = 'G';
std::string signal = "L5";
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
tmp_gnss_synchro.PRN = SV_ID;
System_and_Signal = "GPS L5I";
config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells));
acquisition = std::make_shared<GpsL5iPcpsAcquisition>(config.get(), "Acquisition", 1, 0);
}
else
{
std::cout << "The test can not run with the selected tracking implementation\n ";
throw(std::exception());
}
GNSSBlockFactory block_factory;
GpsL1CaPcpsAcquisitionFineDoppler* acquisition;
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(config.get(), "Acquisition", 1, 1);
acquisition->set_channel(1);
acquisition->set_gnss_synchro(&tmp_gnss_synchro); acquisition->set_gnss_synchro(&tmp_gnss_synchro);
acquisition->set_threshold(config->property("Acquisition.threshold", 0.005)); acquisition->set_channel(0);
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000)); acquisition->set_doppler_max(config->property("Acquisition.doppler_max", FLAGS_external_signal_acquisition_doppler_max_hz));
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 250)); acquisition->set_doppler_step(config->property("Acquisition.doppler_step", FLAGS_external_signal_acquisition_doppler_step_hz));
acquisition->set_threshold(config->property("Acquisition.threshold", FLAGS_external_signal_acquisition_threshold));
acquisition->init();
acquisition->set_local_code();
acquisition->set_state(1); // Ensure that acquisition starts at the first sample
acquisition->connect(top_block);
gr::blocks::file_source::sptr file_source;
std::string file = FLAGS_signal_file;
const char* file_name = file.c_str();
file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
//gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration);
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0);
//top_block->connect(head_samples, 0, acquisition->get_left_block(), 0);
boost::shared_ptr<Acquisition_msg_rx> msg_rx; boost::shared_ptr<Acquisition_msg_rx> msg_rx;
try try
@ -355,15 +506,8 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
exit(0); exit(0);
} }
gr::blocks::file_source::sptr file_source; msg_rx->top_block = top_block;
std::string file = FLAGS_signal_file; top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
const char* file_name = file.c_str();
file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro));
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0);
top_block->msg_connect(acquisition->get_left_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
// 5. Run the flowgraph // 5. Run the flowgraph
// Get visible GPS satellites (positive acquisitions with Doppler measurements) // Get visible GPS satellites (positive acquisitions with Doppler measurements)
@ -378,6 +522,7 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
code_delay_measurements_map.clear(); code_delay_measurements_map.clear();
acq_samplestamp_map.clear(); acq_samplestamp_map.clear();
for (unsigned int PRN = 1; PRN < 33; PRN++) for (unsigned int PRN = 1; PRN < 33; PRN++)
{ {
tmp_gnss_synchro.PRN = PRN; tmp_gnss_synchro.PRN = PRN;
@ -385,12 +530,13 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
acquisition->init(); acquisition->init();
acquisition->set_local_code(); acquisition->set_local_code();
acquisition->reset(); acquisition->reset();
acquisition->set_state(1);
msg_rx->rx_message = 0; msg_rx->rx_message = 0;
top_block->run(); top_block->run();
if (start_msg == true) if (start_msg == true)
{ {
std::cout << "Reading external signal file: " << FLAGS_signal_file << std::endl; std::cout << "Reading external signal file: " << FLAGS_signal_file << std::endl;
std::cout << "Searching for GPS Satellites in L1 band..." << std::endl; std::cout << "Searching for " << System_and_Signal << " Satellites..." << std::endl;
std::cout << "["; std::cout << "[";
start_msg = false; start_msg = false;
} }
@ -410,10 +556,16 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
std::cout << " . "; std::cout << " . ";
} }
top_block->stop(); top_block->stop();
file_source->seek(0, 0); file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample
std::cout.flush(); std::cout.flush();
} }
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
std::cout << "-------------------------------------------\n";
for (auto& x : doppler_measurements_map)
{
std::cout << "DETECTED SATELLITE " << System_and_Signal << " PRN: " << x.first << " with Doppler: " << x.second << " [Hz], code phase: " << code_delay_measurements_map.at(x.first) << " [samples] at signal SampleStamp " << acq_samplestamp_map.at(x.first) << "\n";
}
// report the elapsed time // report the elapsed time
end = std::chrono::system_clock::now(); end = std::chrono::system_clock::now();
@ -424,7 +576,7 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
return true; return true;
} }
TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults) TEST_F(TrackingPullInTest, ValidationOfResults)
{ {
//************************************************* //*************************************************
//***** STEP 1: Prepare the parameters sweep ****** //***** STEP 1: Prepare the parameters sweep ******
@ -531,8 +683,10 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
{ {
true_acq_doppler_hz = doppler_measurements_map.find(FLAGS_test_satellite_PRN)->second; true_acq_doppler_hz = doppler_measurements_map.find(FLAGS_test_satellite_PRN)->second;
true_acq_delay_samples = code_delay_measurements_map.find(FLAGS_test_satellite_PRN)->second; true_acq_delay_samples = code_delay_measurements_map.find(FLAGS_test_satellite_PRN)->second;
acq_samplestamp_samples = 0; //acq_samplestamp_map.find(FLAGS_test_satellite_PRN)->second; acq_samplestamp_samples = 0;
std::cout << "Estimated Initial Doppler " << true_acq_doppler_hz << "[Hz], estimated Initial code delay " << true_acq_delay_samples << " [Samples]" << std::endl; std::cout << "Estimated Initial Doppler " << true_acq_doppler_hz
<< " [Hz], estimated Initial code delay " << true_acq_delay_samples << " [Samples]"
<< " Acquisition SampleStamp is " << acq_samplestamp_map.find(FLAGS_test_satellite_PRN)->second << std::endl;
} }
//CN0 LOOP //CN0 LOOP
std::vector<std::vector<double>> pull_in_results_v_v; std::vector<std::vector<double>> pull_in_results_v_v;
@ -552,9 +706,9 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
//create flowgraph //create flowgraph
top_block = gr::make_top_block("Tracking test"); top_block = gr::make_top_block("Tracking test");
std::shared_ptr<GNSSBlockInterface> trk_ = factory->GetBlock(config, "Tracking_1C", implementation, 1, 1); std::shared_ptr<GNSSBlockInterface> trk_ = factory->GetBlock(config, "Tracking", config->property("Tracking.implementation", std::string("undefined")), 1, 1);
std::shared_ptr<TrackingInterface> tracking = std::dynamic_pointer_cast<TrackingInterface>(trk_); std::shared_ptr<TrackingInterface> tracking = std::dynamic_pointer_cast<TrackingInterface>(trk_);
boost::shared_ptr<GpsL1CADllPllTrackingPullInTest_msg_rx> msg_rx = GpsL1CADllPllTrackingPullInTest_msg_rx_make(); boost::shared_ptr<TrackingPullInTest_msg_rx> msg_rx = TrackingPullInTest_msg_rx_make();
ASSERT_NO_THROW({ ASSERT_NO_THROW({
@ -583,19 +737,20 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false);
gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make();
gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro)); gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro));
gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration);
top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0);
top_block->connect(gr_interleaved_char_to_complex, 0, tracking->get_left_block(), 0); top_block->connect(gr_interleaved_char_to_complex, 0, head_samples, 0);
top_block->connect(head_samples, 0, tracking->get_left_block(), 0);
top_block->connect(tracking->get_right_block(), 0, sink, 0); top_block->connect(tracking->get_right_block(), 0, sink, 0);
top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
file_source->seek(2 * FLAGS_skip_samples + acq_samplestamp_samples, 0); //skip head. ibyte, two bytes per complex sample
file_source->seek(acq_samplestamp_samples, 0);
}) << "Failure connecting the blocks of tracking test."; }) << "Failure connecting the blocks of tracking test.";
//******************************************************************** //********************************************************************
//***** STEP 5: Perform the signal tracking and read the results ***** //***** STEP 5: Perform the signal tracking and read the results *****
//******************************************************************** //********************************************************************
std::cout << "------------ START TRACKING -------------" << std::endl; std::cout << "--- START TRACKING WITH PULL-IN ERROR: " << acq_doppler_error_hz_values.at(current_acq_doppler_error_idx) << " [Hz] and " << acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) << " [Chips] ---" << std::endl;
tracking->start_tracking(); tracking->start_tracking();
std::chrono::time_point<std::chrono::system_clock> start, end; std::chrono::time_point<std::chrono::system_clock> start, end;
EXPECT_NO_THROW({ EXPECT_NO_THROW({
@ -630,6 +785,8 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
std::vector<double> prompt; std::vector<double> prompt;
std::vector<double> early; std::vector<double> early;
std::vector<double> late; std::vector<double> late;
std::vector<double> v_early;
std::vector<double> v_late;
std::vector<double> promptI; std::vector<double> promptI;
std::vector<double> promptQ; std::vector<double> promptQ;
std::vector<double> CN0_dBHz; std::vector<double> CN0_dBHz;
@ -647,6 +804,8 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
prompt.push_back(trk_dump.abs_P); prompt.push_back(trk_dump.abs_P);
early.push_back(trk_dump.abs_E); early.push_back(trk_dump.abs_E);
late.push_back(trk_dump.abs_L); late.push_back(trk_dump.abs_L);
v_early.push_back(trk_dump.abs_VE);
v_late.push_back(trk_dump.abs_VL);
promptI.push_back(trk_dump.prompt_I); promptI.push_back(trk_dump.prompt_I);
promptQ.push_back(trk_dump.prompt_Q); promptQ.push_back(trk_dump.prompt_Q);
CN0_dBHz.push_back(trk_dump.CN0_SNV_dB_Hz); CN0_dBHz.push_back(trk_dump.CN0_SNV_dB_Hz);
@ -692,6 +851,11 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
g1.plot_xy(trk_timestamp_s, prompt, "Prompt", decimate); g1.plot_xy(trk_timestamp_s, prompt, "Prompt", decimate);
g1.plot_xy(trk_timestamp_s, early, "Early", decimate); g1.plot_xy(trk_timestamp_s, early, "Early", decimate);
g1.plot_xy(trk_timestamp_s, late, "Late", decimate); g1.plot_xy(trk_timestamp_s, late, "Late", decimate);
if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0)
{
g1.plot_xy(trk_timestamp_s, v_early, "Very Early", decimate);
g1.plot_xy(trk_timestamp_s, v_late, "Very Late", decimate);
}
g1.set_legend(); g1.set_legend();
//g1.savetops("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx))); //g1.savetops("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)));
//g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18); //g1.savetopdf("Correlators_outputs" + std::to_string(generator_CN0_values.at(current_cn0_idx)), 18);

View File

@ -33,6 +33,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/core/libs/supl/asn-supl ${CMAKE_SOURCE_DIR}/src/core/libs/supl/asn-supl
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs
${CMAKE_SOURCE_DIR}/src/algorithms/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs
${GLOG_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS}
${GFlags_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS}

View File

@ -144,8 +144,6 @@ FrontEndCal_msg_rx::FrontEndCal_msg_rx() : gr::block("FrontEndCal_msg_rx", gr::i
FrontEndCal_msg_rx::~FrontEndCal_msg_rx() {} FrontEndCal_msg_rx::~FrontEndCal_msg_rx() {}
void wait_message() void wait_message()
{ {
while (!stop) while (!stop)
@ -353,13 +351,14 @@ int main(int argc, char** argv)
gnss_synchro->PRN = 1; gnss_synchro->PRN = 1;
long fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", 2048000); long fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", 2048000);
configuration->set_property("Acquisition.max_dwells", "10");
GNSSBlockFactory block_factory; GNSSBlockFactory block_factory;
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(configuration.get(), "Acquisition", 1, 1); acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(configuration.get(), "Acquisition", 1, 1);
acquisition->set_channel(1); acquisition->set_channel(1);
acquisition->set_gnss_synchro(gnss_synchro); acquisition->set_gnss_synchro(gnss_synchro);
acquisition->set_threshold(configuration->property("Acquisition.threshold", 0.0)); acquisition->set_threshold(configuration->property("Acquisition.threshold", 2.0));
acquisition->set_doppler_max(configuration->property("Acquisition.doppler_max", 10000)); acquisition->set_doppler_max(configuration->property("Acquisition.doppler_max", 10000));
acquisition->set_doppler_step(configuration->property("Acquisition.doppler_step", 250)); acquisition->set_doppler_step(configuration->property("Acquisition.doppler_step", 250));

View File

@ -85,7 +85,7 @@ Acquisition_2S.doppler_step=125
Acquisition_2S.use_CFAR_algorithm=false Acquisition_2S.use_CFAR_algorithm=false
Acquisition_2S.threshold=19.5 Acquisition_2S.threshold=10
Acquisition_2S.blocking=true Acquisition_2S.blocking=true