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:
commit
ca4614811c
1
AUTHORS
1
AUTHORS
@ -40,6 +40,7 @@ Antonio Ramos antonio.ramosdet@gmail.com Developer
|
||||
Marc Majoral marc.majoral@cttc.cat Developer
|
||||
Jordi Vilà-Valls jordi.vila@cttc.cat 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
|
||||
Anthony Arnold anthony.arnold@uqconnect.edu.au Contributor
|
||||
Carlos Avilés carlos.avilesr@googlemail.com Contributor
|
||||
|
@ -32,12 +32,11 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "galileo_pcps_8ms_acquisition_cc.h"
|
||||
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -123,6 +122,7 @@ public:
|
||||
* \brief Restart acquisition algorithm
|
||||
*/
|
||||
void reset() override;
|
||||
void set_state(int state __attribute__((unused))) override{};
|
||||
|
||||
private:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -58,31 +58,38 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000);
|
||||
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
acq_parameters.fs_in = fs_in_;
|
||||
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_;
|
||||
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)));
|
||||
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
|
||||
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_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_;
|
||||
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);
|
||||
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
|
||||
acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
|
||||
acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions
|
||||
|
||||
max_dwells_ = configuration_->property(role + ".max_dwells", 1);
|
||||
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);
|
||||
acq_parameters.dump_filename = dump_filename_;
|
||||
//--- 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)));
|
||||
acq_parameters.samples_per_code = code_length_;
|
||||
int samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
|
||||
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)));
|
||||
|
||||
float samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
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;
|
||||
|
||||
if (bit_transition_flag_)
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -32,12 +32,11 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_cccwsr_acquisition_cc.h"
|
||||
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -124,7 +123,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -32,11 +32,11 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_quicksync_acquisition_cc.h"
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
@ -127,7 +127,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -32,12 +32,11 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_tong_acquisition_cc.h"
|
||||
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -127,7 +126,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -38,10 +38,10 @@
|
||||
#ifndef GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_
|
||||
#define GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_
|
||||
|
||||
#include <string>
|
||||
#include "gnss_synchro.h"
|
||||
#include "acquisition_interface.h"
|
||||
#include "galileo_e5a_noncoherent_iq_acquisition_caf_cc.h"
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -129,7 +129,7 @@ public:
|
||||
* first available sample.
|
||||
* \param state - int=1 forces start of acquisition
|
||||
*/
|
||||
void set_state(int state);
|
||||
void set_state(int state) override;
|
||||
|
||||
private:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -57,6 +57,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000);
|
||||
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((1.0 / Galileo_E5a_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
|
||||
acq_pilot_ = configuration_->property(role + ".acquire_pilot", false);
|
||||
acq_iq_ = configuration_->property(role + ".acquire_iq", false);
|
||||
if (acq_iq_)
|
||||
@ -100,9 +101,10 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
|
||||
LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
}
|
||||
acq_parameters.it_size = item_size_;
|
||||
acq_parameters.samples_per_code = code_length_;
|
||||
acq_parameters.samples_per_ms = code_length_;
|
||||
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
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.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
|
@ -121,7 +121,7 @@ public:
|
||||
* first available sample.
|
||||
* \param state - int=1 forces start of acquisition
|
||||
*/
|
||||
void set_state(int state);
|
||||
void set_state(int state) override;
|
||||
|
||||
private:
|
||||
float calculate_threshold(float pfa);
|
||||
|
@ -59,6 +59,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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(GLONASS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
acq_parameters.dump = dump_;
|
||||
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
|
||||
@ -99,8 +100,9 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
|
||||
}
|
||||
acq_parameters.it_size = item_size_;
|
||||
acq_parameters.sampled_ms = sampled_ms_;
|
||||
acq_parameters.samples_per_ms = code_length_;
|
||||
acq_parameters.samples_per_code = code_length_;
|
||||
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
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.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
|
@ -130,7 +130,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -58,6 +58,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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(GLONASS_L2_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
acq_parameters.dump = dump_;
|
||||
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
|
||||
@ -98,8 +99,9 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
|
||||
}
|
||||
acq_parameters.it_size = item_size_;
|
||||
acq_parameters.sampled_ms = sampled_ms_;
|
||||
acq_parameters.samples_per_ms = code_length_;
|
||||
acq_parameters.samples_per_code = code_length_;
|
||||
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
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.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
|
@ -129,7 +129,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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);
|
||||
acq_parameters.dump = dump_;
|
||||
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
|
||||
@ -70,6 +71,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
acq_parameters.doppler_max = doppler_max_;
|
||||
sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1);
|
||||
acq_parameters.sampled_ms = sampled_ms_;
|
||||
acq_parameters.ms_per_code = 1;
|
||||
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
|
||||
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
|
||||
@ -82,15 +84,11 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
//--- 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)));
|
||||
|
||||
vector_length_ = code_length_ * sampled_ms_;
|
||||
|
||||
if (bit_transition_flag_)
|
||||
{
|
||||
vector_length_ *= 2;
|
||||
}
|
||||
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;
|
||||
acq_parameters.samples_per_code = acq_parameters.samples_per_ms * static_cast<float>(GPS_L1_CA_CODE_PERIOD * 1000.0);
|
||||
|
||||
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_];
|
||||
|
||||
if (item_type_.compare("cshort") == 0)
|
||||
@ -101,8 +99,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
||||
{
|
||||
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.blocking_on_standby = configuration_->property(role + ".blocking_on_standby", false);
|
||||
acquisition_ = pcps_make_acquisition(acq_parameters);
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -33,11 +33,12 @@
|
||||
*/
|
||||
|
||||
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
|
||||
#include <glog/logging.h>
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include "acq_conf.h"
|
||||
#include <glog/logging.h>
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
@ -49,29 +50,36 @@ GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler(
|
||||
std::string default_dump_filename = "./data/acquisition.dat";
|
||||
|
||||
DLOG(INFO) << "role " << role;
|
||||
Acq_Conf acq_parameters = Acq_Conf();
|
||||
|
||||
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
||||
long fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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);
|
||||
acq_parameters.dump = dump_;
|
||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||
acq_parameters.dump_filename = dump_filename_;
|
||||
doppler_max_ = configuration->property(role + ".doppler_max", 5000);
|
||||
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);
|
||||
acq_parameters.sampled_ms = sampled_ms_;
|
||||
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 -------------------------
|
||||
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_];
|
||||
|
||||
if (item_type_.compare("gr_complex") == 0)
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
acquisition_cc_ = pcps_make_acquisition_fine_doppler_cc(max_dwells_, sampled_ms_,
|
||||
doppler_max_, doppler_min_, fs_in_, vector_length_,
|
||||
dump_, dump_filename_);
|
||||
acquisition_cc_ = pcps_make_acquisition_fine_doppler_cc(acq_parameters);
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (top_block)
|
||||
|
@ -34,11 +34,10 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_acquisition_fine_doppler_cc.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -122,6 +121,11 @@ public:
|
||||
*/
|
||||
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:
|
||||
pcps_acquisition_fine_doppler_cc_sptr acquisition_cc_;
|
||||
size_t item_size_;
|
||||
@ -131,7 +135,6 @@ private:
|
||||
float threshold_;
|
||||
int doppler_max_;
|
||||
unsigned int doppler_step_;
|
||||
int doppler_min_;
|
||||
unsigned int sampled_ms_;
|
||||
int max_dwells_;
|
||||
long fs_in_;
|
||||
|
@ -60,6 +60,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||
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);
|
||||
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);
|
||||
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
|
||||
acq_parameters.doppler_max = doppler_max_;
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -34,11 +34,10 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_assisted_acquisition_cc.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -121,6 +120,7 @@ public:
|
||||
* \brief Restart acquisition algorithm
|
||||
*/
|
||||
void reset() override;
|
||||
void set_state(int state __attribute__((unused))) override{};
|
||||
|
||||
private:
|
||||
pcps_assisted_acquisition_cc_sptr acquisition_cc_;
|
||||
|
@ -32,12 +32,11 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_opencl_acquisition_cc.h"
|
||||
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -123,6 +122,7 @@ public:
|
||||
* \brief Restart acquisition algorithm
|
||||
*/
|
||||
void reset() override;
|
||||
void set_state(int state __attribute__((unused))) override{};
|
||||
|
||||
private:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -33,13 +33,12 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_quicksync_acquisition_cc.h"
|
||||
#include "configuration_interface.h"
|
||||
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -129,7 +128,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -32,12 +32,12 @@
|
||||
#ifndef 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 "acquisition_interface.h"
|
||||
#include "pcps_tong_acquisition_cc.h"
|
||||
#include "configuration_interface.h"
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -127,7 +127,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
|
@ -60,6 +60,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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((1.0 / GPS_L2_M_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
acq_parameters.dump = dump_;
|
||||
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);
|
||||
acq_parameters.dump_filename = dump_filename_;
|
||||
//--- 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)));
|
||||
|
||||
vector_length_ = code_length_;
|
||||
|
||||
if (bit_transition_flag_)
|
||||
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
acq_parameters.ms_per_code = 20;
|
||||
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)
|
||||
{
|
||||
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_];
|
||||
|
||||
if (item_type_.compare("cshort") == 0)
|
||||
@ -96,13 +101,13 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
|
||||
{
|
||||
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.sampled_ms = 20;
|
||||
|
||||
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.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);
|
||||
acquisition_ = pcps_make_acquisition(acq_parameters);
|
||||
DLOG(INFO) << "acquisition(" << acquisition_->unique_id() << ")";
|
||||
@ -120,6 +125,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
|
||||
threshold_ = 0.0;
|
||||
doppler_step_ = 0;
|
||||
gnss_synchro_ = 0;
|
||||
num_codes_ = acq_parameters.sampled_ms / acq_parameters.ms_per_code;
|
||||
if (in_streams_ > 1)
|
||||
{
|
||||
LOG(ERROR) << "This implementation only supports one input stream";
|
||||
@ -208,9 +214,18 @@ void GpsL2MPcpsAcquisition::init()
|
||||
|
||||
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_);
|
||||
delete[] code;
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
@ -160,6 +160,7 @@ private:
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
unsigned int num_codes_;
|
||||
|
||||
float calculate_threshold(float pfa);
|
||||
};
|
||||
|
@ -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
|
||||
* GPS L5i signals
|
||||
* \authors <ul>
|
||||
@ -59,6 +59,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
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((1.0 / GPS_L5i_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
acq_parameters.dump = dump_;
|
||||
acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
|
||||
@ -95,10 +96,12 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
|
||||
{
|
||||
item_size_ = sizeof(gr_complex);
|
||||
}
|
||||
acq_parameters.samples_per_code = code_length_;
|
||||
acq_parameters.samples_per_ms = code_length_;
|
||||
acq_parameters.samples_per_ms = static_cast<float>(fs_in_) * 0.001;
|
||||
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.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.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
@ -205,9 +208,18 @@ void GpsL5iPcpsAcquisition::init()
|
||||
|
||||
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_);
|
||||
delete[] code;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
* GPS L5i signals
|
||||
* \authors <ul>
|
||||
@ -132,7 +132,7 @@ public:
|
||||
/*!
|
||||
* \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:
|
||||
ConfigurationInterface* configuration_;
|
||||
@ -158,6 +158,7 @@ private:
|
||||
std::complex<float>* code_;
|
||||
Gnss_Synchro* gnss_synchro_;
|
||||
std::string role_;
|
||||
unsigned int num_codes_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
|
||||
|
@ -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",
|
||||
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(0, 0, 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))
|
||||
{
|
||||
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_state = 0;
|
||||
d_old_freq = 0;
|
||||
d_well_count = 0;
|
||||
d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms;
|
||||
d_num_noncoherent_integrations_counter = 0;
|
||||
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_input_power = 0.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.
|
||||
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
|
||||
}
|
||||
|
||||
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_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
|
||||
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_grid_doppler_wipeoffs = nullptr;
|
||||
d_grid_doppler_wipeoffs_step_two = nullptr;
|
||||
d_magnitude_grid = nullptr;
|
||||
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)
|
||||
{
|
||||
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
|
||||
{
|
||||
@ -124,6 +136,16 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
|
||||
d_step_two = false;
|
||||
d_dump_number = 0;
|
||||
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++)
|
||||
{
|
||||
volk_gnsssdr_free(d_grid_doppler_wipeoffs[i]);
|
||||
volk_gnsssdr_free(d_magnitude_grid[i]);
|
||||
}
|
||||
delete[] d_grid_doppler_wipeoffs;
|
||||
delete[] d_magnitude_grid;
|
||||
}
|
||||
if (acq_parameters.make_2_steps)
|
||||
{
|
||||
@ -147,6 +171,8 @@ pcps_acquisition::~pcps_acquisition()
|
||||
}
|
||||
volk_gnsssdr_free(d_fft_codes);
|
||||
volk_gnsssdr_free(d_magnitude);
|
||||
volk_gnsssdr_free(d_tmp_buffer);
|
||||
volk_gnsssdr_free(d_input_signal);
|
||||
delete d_ifft;
|
||||
delete d_fft_if;
|
||||
volk_gnsssdr_free(d_data_buffer);
|
||||
@ -179,7 +205,15 @@ void pcps_acquisition::set_local_code(std::complex<float>* code)
|
||||
}
|
||||
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
|
||||
@ -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_magnitude_grid = new float*[d_num_doppler_bins];
|
||||
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_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;
|
||||
update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_old_freq + doppler);
|
||||
}
|
||||
|
||||
d_worker_active = false;
|
||||
|
||||
if (acq_parameters.dump)
|
||||
@ -269,6 +311,7 @@ void pcps_acquisition::update_grid_doppler_wipeoffs()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pcps_acquisition::update_grid_doppler_wipeoffs_step2()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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_step = 0;
|
||||
d_gnss_synchro->Acq_samplestamp_samples = 0;
|
||||
d_well_count = 0;
|
||||
d_mag = 0.0;
|
||||
d_input_power = 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)
|
||||
{
|
||||
gr::thread::scoped_lock lk(d_setlock);
|
||||
|
||||
// initialize acquisition algorithm
|
||||
int doppler = 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);
|
||||
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_mag = 0.0;
|
||||
d_well_count++;
|
||||
d_num_noncoherent_integrations_counter++;
|
||||
|
||||
DLOG(INFO) << "Channel: " << d_channel
|
||||
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
|
||||
<< " ,sample stamp: " << samp_count << ", threshold: "
|
||||
<< d_threshold << ", doppler_max: " << acq_parameters.doppler_max
|
||||
<< ", 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();
|
||||
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
|
||||
volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size);
|
||||
volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size);
|
||||
// Compute the input signal power estimation
|
||||
volk_32fc_magnitude_squared_32f(d_tmp_buffer, in, 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);
|
||||
}
|
||||
// 2- Doppler frequency search loop
|
||||
|
||||
// Doppler frequency grid loop
|
||||
if (!d_step_two)
|
||||
{
|
||||
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
|
||||
{
|
||||
// doppler search steps
|
||||
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
|
||||
|
||||
// Remove Doppler
|
||||
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
|
||||
d_fft_if->execute();
|
||||
|
||||
// Multiply carrier wiped--off, Fourier transformed incoming signal
|
||||
// with the local FFT'd code reference using SIMD operations with VOLK library
|
||||
// Multiply carrier wiped--off, Fourier transformed incoming signal with the local FFT'd code reference
|
||||
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();
|
||||
|
||||
// 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);
|
||||
volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size);
|
||||
volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size);
|
||||
magt = d_magnitude[indext];
|
||||
|
||||
if (acq_parameters.use_CFAR_algorithm_flag)
|
||||
if (d_num_noncoherent_integrations_counter == 1)
|
||||
{
|
||||
// Normalize the maximum value to correct the scale factor introduced by FFTW
|
||||
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
|
||||
volk_32fc_magnitude_squared_32f(d_magnitude_grid[doppler_index], d_ifft->get_outbuf() + offset, effective_fft_size);
|
||||
}
|
||||
// 4- record the maximum peak and the associated synchronization parameters
|
||||
if (d_mag < magt)
|
||||
else
|
||||
{
|
||||
d_mag = magt;
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
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
|
||||
{
|
||||
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);
|
||||
|
||||
// 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
|
||||
d_ifft->execute();
|
||||
|
||||
// Search maximum
|
||||
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);
|
||||
volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size);
|
||||
magt = d_magnitude[indext];
|
||||
|
||||
if (acq_parameters.use_CFAR_algorithm_flag)
|
||||
if (d_num_noncoherent_integrations_counter == 1)
|
||||
{
|
||||
// Normalize the maximum value to correct the scale factor introduced by FFTW
|
||||
magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor);
|
||||
volk_32fc_magnitude_squared_32f(d_magnitude_grid[doppler_index], d_ifft->get_outbuf() + offset, effective_fft_size);
|
||||
}
|
||||
// 4- record the maximum peak and the associated synchronization parameters
|
||||
if (d_mag < magt)
|
||||
else
|
||||
{
|
||||
d_mag = magt;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
// Compute the test statistic
|
||||
if (d_use_CFAR_algorithm_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_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();
|
||||
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
|
||||
}
|
||||
}
|
||||
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_active = false;
|
||||
d_step_two = false;
|
||||
send_negative_acquisition();
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -659,11 +764,25 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
|
||||
}
|
||||
}
|
||||
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
|
||||
if (acq_parameters.dump and d_channel == d_dump_channel)
|
||||
{
|
||||
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
|
||||
* 6. Declare positive or negative acquisition using a message port
|
||||
*/
|
||||
|
||||
gr::thread::scoped_lock lk(d_setlock);
|
||||
if (!d_active or d_worker_active)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
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_doppler_hz = 0.0;
|
||||
d_gnss_synchro->Acq_samplestamp_samples = 0;
|
||||
d_well_count = 0;
|
||||
d_mag = 0.0;
|
||||
d_input_power = 0.0;
|
||||
d_test_statistics = 0.0;
|
||||
d_state = 1;
|
||||
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]);
|
||||
}
|
||||
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
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -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);
|
||||
d_worker_active = true;
|
||||
}
|
||||
d_sample_counter += d_fft_size;
|
||||
d_sample_counter += d_consumed_samples;
|
||||
consume_each(1);
|
||||
break;
|
||||
}
|
||||
|
@ -95,24 +95,33 @@ private:
|
||||
|
||||
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;
|
||||
bool d_active;
|
||||
bool d_worker_active;
|
||||
bool d_cshort;
|
||||
bool d_step_two;
|
||||
bool d_use_CFAR_algorithm_flag;
|
||||
int d_positive_acq;
|
||||
float d_threshold;
|
||||
float d_mag;
|
||||
float d_input_power;
|
||||
float d_test_statistics;
|
||||
float* d_magnitude;
|
||||
float** d_magnitude_grid;
|
||||
float* d_tmp_buffer;
|
||||
gr_complex* d_input_signal;
|
||||
uint32_t d_samplesPerChip;
|
||||
long d_old_freq;
|
||||
int d_state;
|
||||
unsigned int d_channel;
|
||||
unsigned int d_doppler_step;
|
||||
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_consumed_samples;
|
||||
unsigned int d_num_doppler_bins;
|
||||
unsigned long int d_sample_counter;
|
||||
gr_complex** d_grid_doppler_wipeoffs;
|
||||
@ -150,7 +159,7 @@ public:
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Initializes acquisition algorithm.
|
||||
* \brief Initializes acquisition algorithm and reserves memory.
|
||||
*/
|
||||
void init();
|
||||
|
||||
|
@ -40,46 +40,41 @@
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <algorithm> // std::rotate, std::fill_n
|
||||
#include <sstream>
|
||||
#include <matio.h>
|
||||
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
pcps_acquisition_fine_doppler_cc_sptr pcps_make_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)
|
||||
pcps_acquisition_fine_doppler_cc_sptr pcps_make_acquisition_fine_doppler_cc(const Acq_Conf &conf_)
|
||||
{
|
||||
return pcps_acquisition_fine_doppler_cc_sptr(
|
||||
new pcps_acquisition_fine_doppler_cc(max_dwells, sampled_ms, doppler_max, doppler_min,
|
||||
fs_in, samples_per_ms, dump, dump_filename));
|
||||
new pcps_acquisition_fine_doppler_cc(conf_));
|
||||
}
|
||||
|
||||
|
||||
pcps_acquisition_fine_doppler_cc::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) : gr::block("pcps_acquisition_fine_doppler_cc",
|
||||
pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(const Acq_Conf &conf_)
|
||||
: gr::block("pcps_acquisition_fine_doppler_cc",
|
||||
gr::io_signature::make(1, 1, sizeof(gr_complex)),
|
||||
gr::io_signature::make(0, 0, sizeof(gr_complex)))
|
||||
{
|
||||
this->message_port_register_out(pmt::mp("events"));
|
||||
acq_parameters = conf_;
|
||||
d_sample_counter = 0; // SAMPLE COUNTER
|
||||
d_active = false;
|
||||
d_fs_in = fs_in;
|
||||
d_samples_per_ms = samples_per_ms;
|
||||
d_sampled_ms = sampled_ms;
|
||||
d_config_doppler_max = doppler_max;
|
||||
d_config_doppler_min = doppler_min;
|
||||
d_fft_size = d_sampled_ms * d_samples_per_ms;
|
||||
d_fs_in = conf_.fs_in;
|
||||
d_samples_per_ms = conf_.samples_per_ms;
|
||||
d_config_doppler_max = conf_.doppler_max;
|
||||
d_fft_size = d_samples_per_ms;
|
||||
// HS Acquisition
|
||||
d_max_dwells = max_dwells;
|
||||
d_max_dwells = conf_.max_dwells;
|
||||
d_gnuradio_forecast_samples = d_fft_size;
|
||||
d_input_power = 0.0;
|
||||
d_state = 0;
|
||||
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_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
|
||||
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);
|
||||
|
||||
// For dumping samples into a file
|
||||
d_dump = dump;
|
||||
d_dump_filename = dump_filename;
|
||||
d_dump = conf_.dump;
|
||||
d_dump_filename = conf_.dump_filename;
|
||||
|
||||
d_doppler_resolution = 0;
|
||||
d_n_samples_in_buffer = 0;
|
||||
d_threshold = 0;
|
||||
d_num_doppler_points = 0;
|
||||
d_doppler_step = 0;
|
||||
@ -102,21 +97,46 @@ pcps_acquisition_fine_doppler_cc::pcps_acquisition_fine_doppler_cc(
|
||||
d_test_statistics = 0;
|
||||
d_well_count = 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)
|
||||
{
|
||||
d_doppler_step = doppler_step;
|
||||
// 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];
|
||||
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()));
|
||||
}
|
||||
|
||||
if (d_dump)
|
||||
{
|
||||
grid_ = arma::fmat(d_fft_size, d_num_doppler_points, arma::fill::zeros);
|
||||
}
|
||||
|
||||
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_fft_codes);
|
||||
volk_gnsssdr_free(d_magnitude);
|
||||
volk_gnsssdr_free(d_10_ms_buffer);
|
||||
delete d_ifft;
|
||||
delete d_fft_if;
|
||||
if (d_dump)
|
||||
{
|
||||
d_dump_file.close();
|
||||
}
|
||||
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_doppler_hz = 0.0;
|
||||
d_gnss_synchro->Acq_samplestamp_samples = 0;
|
||||
d_input_power = 0.0;
|
||||
d_state = 0;
|
||||
}
|
||||
|
||||
@ -187,6 +203,7 @@ void pcps_acquisition_fine_doppler_cc::reset_grid()
|
||||
d_well_count = 0;
|
||||
for (int i = 0; i < d_num_doppler_points; i++)
|
||||
{
|
||||
//todo: use memset here
|
||||
for (unsigned int j = 0; j < d_fft_size; j++)
|
||||
{
|
||||
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];
|
||||
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
|
||||
// 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);
|
||||
@ -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 fft_normalization_factor;
|
||||
float firstPeak = 0.0;
|
||||
int index_doppler = 0;
|
||||
uint32_t tmp_intex_t = 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++)
|
||||
{
|
||||
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];
|
||||
//std::cout<<magt<<std::endl;
|
||||
firstPeak = d_grid_data[i][tmp_intex_t];
|
||||
index_doppler = i;
|
||||
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
|
||||
fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
|
||||
magt = magt / (fft_normalization_factor * fft_normalization_factor);
|
||||
// -- - Find 1 chip wide code phase exclude range around the peak
|
||||
uint32_t samplesPerChip = ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(this->d_fs_in));
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@ -296,6 +331,7 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
|
||||
// doppler search steps
|
||||
// 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);
|
||||
|
||||
// 3- Perform the FFT-based convolution (parallel time search)
|
||||
// Compute the FFT of the carrier wiped--off incoming signal
|
||||
d_fft_if->execute();
|
||||
@ -308,29 +344,38 @@ int pcps_acquisition_fine_doppler_cc::compute_and_accumulate_grid(gr_vector_cons
|
||||
d_ifft->execute();
|
||||
|
||||
// save the grid matrix delay file
|
||||
|
||||
volk_32fc_magnitude_squared_32f(p_tmp_vector, d_ifft->get_outbuf(), d_fft_size);
|
||||
const float *old_vector = d_grid_data[doppler_index];
|
||||
volk_32f_x2_add_32f(d_grid_data[doppler_index], old_vector, p_tmp_vector, d_fft_size);
|
||||
//accumulate grid values
|
||||
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);
|
||||
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
|
||||
int zero_padding_factor = 2;
|
||||
int fft_size_extended = d_fft_size * zero_padding_factor;
|
||||
int zero_padding_factor = 8;
|
||||
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);
|
||||
|
||||
//zero padding the entire vector
|
||||
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
|
||||
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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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
|
||||
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(), in, code_replica, d_fft_size);
|
||||
volk_32fc_x2_multiply_32fc(fft_operator->get_inbuf(), d_10_ms_buffer, code_replica, signal_samples);
|
||||
|
||||
// 3. Perform the FFT (zero padded!)
|
||||
fft_operator->execute();
|
||||
@ -360,8 +407,8 @@ int pcps_acquisition_fine_doppler_cc::estimate_Doppler(gr_vector_const_void_star
|
||||
|
||||
//case even
|
||||
int counter = 0;
|
||||
float *fftFreqBins = new float[fft_size_extended];
|
||||
|
||||
float fftFreqBins[fft_size_extended];
|
||||
std::fill_n(fftFreqBins, fft_size_extended, 0.0);
|
||||
|
||||
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--)
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -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) << "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!!
|
||||
delete fft_operator;
|
||||
volk_gnsssdr_free(code_replica);
|
||||
volk_gnsssdr_free(p_tmp_vector);
|
||||
delete[] fftFreqBins;
|
||||
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,
|
||||
gr_vector_int &ninput_items __attribute__((unused)), gr_vector_const_void_star &input_items,
|
||||
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
|
||||
*/
|
||||
|
||||
int samples_remaining;
|
||||
switch (d_state)
|
||||
{
|
||||
case 0: // S0. StandBy
|
||||
//DLOG(INFO) <<"S0"<<std::endl;
|
||||
if (d_active == true)
|
||||
{
|
||||
reset_grid();
|
||||
d_n_samples_in_buffer = 0;
|
||||
d_state = 1;
|
||||
}
|
||||
if (!acq_parameters.blocking_on_standby)
|
||||
{
|
||||
d_sample_counter += d_fft_size; // sample counter
|
||||
consume_each(d_fft_size);
|
||||
}
|
||||
break;
|
||||
case 1: // S1. ComputeGrid
|
||||
//DLOG(INFO) <<"S1"<<std::endl;
|
||||
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++;
|
||||
if (d_well_count >= d_max_dwells)
|
||||
{
|
||||
d_state = 2;
|
||||
}
|
||||
d_sample_counter += d_fft_size; // sample counter
|
||||
consume_each(d_fft_size);
|
||||
break;
|
||||
case 2: // Compute test statistics and decide
|
||||
//DLOG(INFO) <<"S2"<<std::endl;
|
||||
d_input_power = estimate_input_power(input_items);
|
||||
d_test_statistics = search_maximum();
|
||||
d_test_statistics = compute_CAF();
|
||||
if (d_test_statistics > d_threshold)
|
||||
{
|
||||
d_state = 3; //perform fine doppler estimation
|
||||
@ -472,16 +532,34 @@ int pcps_acquisition_fine_doppler_cc::general_work(int noutput_items,
|
||||
else
|
||||
{
|
||||
d_state = 5; //negative acquisition
|
||||
d_n_samples_in_buffer = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
case 3: // Fine doppler estimation
|
||||
//DLOG(INFO) <<"S3"<<std::endl;
|
||||
DLOG(INFO) << "Performing fine Doppler estimation";
|
||||
estimate_Doppler(input_items); //disabled in repo
|
||||
samples_remaining = 10 * d_samples_per_ms - d_n_samples_in_buffer;
|
||||
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case 4: // Positive_Acq
|
||||
//DLOG(INFO) <<"S4"<<std::endl;
|
||||
DLOG(INFO) << "positive acquisition";
|
||||
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
|
||||
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) << "code phase " << d_gnss_synchro->Acq_delay_samples;
|
||||
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
|
||||
DLOG(INFO) << "input signal power " << d_input_power;
|
||||
|
||||
d_positive_acq = 1;
|
||||
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
|
||||
this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
|
||||
d_state = 0;
|
||||
if (!acq_parameters.blocking_on_standby)
|
||||
{
|
||||
d_sample_counter += noutput_items; // sample counter
|
||||
consume_each(noutput_items);
|
||||
}
|
||||
break;
|
||||
case 5: // Negative_Acq
|
||||
//DLOG(INFO) <<"S5"<<std::endl;
|
||||
DLOG(INFO) << "negative acquisition";
|
||||
DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN;
|
||||
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) << "code phase " << d_gnss_synchro->Acq_delay_samples;
|
||||
DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz;
|
||||
DLOG(INFO) << "input signal power " << d_input_power;
|
||||
|
||||
d_positive_acq = 0;
|
||||
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
|
||||
this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
|
||||
d_state = 0;
|
||||
if (!acq_parameters.blocking_on_standby)
|
||||
{
|
||||
d_sample_counter += noutput_items; // sample counter
|
||||
consume_each(noutput_items);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
d_state = 0;
|
||||
if (!acq_parameters.blocking_on_standby)
|
||||
{
|
||||
d_sample_counter += noutput_items; // sample counter
|
||||
consume_each(noutput_items);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
//DLOG(INFO)<<"d_sample_counter="<<d_sample_counter<<std::endl;
|
||||
d_sample_counter += d_fft_size; // sample counter
|
||||
consume_each(d_fft_size);
|
||||
return noutput_items;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcps_acquisition_fine_doppler_cc::dump_results(int effective_fft_size)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*!
|
||||
* \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
|
||||
* for GPS L1 C/A signal
|
||||
*
|
||||
* Acquisition strategy (Kay Borre book + CFAR threshold).
|
||||
* Acquisition strategy (Kay Borre book).
|
||||
* <ol>
|
||||
* <li> Compute the input signal power estimation
|
||||
* <li> Doppler serial search loop
|
||||
@ -49,6 +50,8 @@
|
||||
#define GNSS_SDR_PCPS_ACQUISITION_FINE_DOPPLER_CC_H_
|
||||
|
||||
#include "gnss_synchro.h"
|
||||
#include "acq_conf.h"
|
||||
#include <armadillo>
|
||||
#include <gnuradio/block.h>
|
||||
#include <gnuradio/gr_complex.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_make_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);
|
||||
pcps_make_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
|
||||
|
||||
/*!
|
||||
* \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
|
||||
{
|
||||
private:
|
||||
friend pcps_acquisition_fine_doppler_cc_sptr
|
||||
pcps_make_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);
|
||||
|
||||
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);
|
||||
pcps_make_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
|
||||
pcps_acquisition_fine_doppler_cc(const Acq_Conf& conf_);
|
||||
|
||||
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);
|
||||
double search_maximum();
|
||||
double compute_CAF();
|
||||
void reset_grid();
|
||||
void update_carrier_wipeoff();
|
||||
void free_grid_memory();
|
||||
bool start();
|
||||
|
||||
Acq_Conf acq_parameters;
|
||||
long d_fs_in;
|
||||
int d_samples_per_ms;
|
||||
int d_max_dwells;
|
||||
unsigned int d_doppler_resolution;
|
||||
int d_gnuradio_forecast_samples;
|
||||
float d_threshold;
|
||||
std::string d_satellite_str;
|
||||
int d_config_doppler_max;
|
||||
int d_config_doppler_min;
|
||||
|
||||
int d_num_doppler_points;
|
||||
int d_doppler_step;
|
||||
unsigned int d_sampled_ms;
|
||||
unsigned int d_fft_size;
|
||||
unsigned long int d_sample_counter;
|
||||
gr_complex* d_carrier;
|
||||
gr_complex* d_fft_codes;
|
||||
gr_complex* d_10_ms_buffer;
|
||||
float* d_magnitude;
|
||||
|
||||
float** d_grid_data;
|
||||
@ -124,17 +112,22 @@ private:
|
||||
Gnss_Synchro* d_gnss_synchro;
|
||||
unsigned int d_code_phase;
|
||||
float d_doppler_freq;
|
||||
float d_input_power;
|
||||
float d_test_statistics;
|
||||
std::ofstream d_dump_file;
|
||||
int d_positive_acq;
|
||||
|
||||
int d_state;
|
||||
bool d_active;
|
||||
int d_well_count;
|
||||
int d_n_samples_in_buffer;
|
||||
bool d_dump;
|
||||
unsigned int d_channel;
|
||||
|
||||
std::string d_dump_filename;
|
||||
|
||||
arma::fmat grid_;
|
||||
long int d_dump_number;
|
||||
unsigned int d_dump_channel;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \brief Default destructor.
|
||||
@ -187,6 +180,7 @@ public:
|
||||
inline void set_channel(unsigned int channel)
|
||||
{
|
||||
d_channel = channel;
|
||||
d_dump_channel = d_channel;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -214,6 +208,13 @@ public:
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -222,6 +223,14 @@ public:
|
||||
gr_vector_void_star& output_items);
|
||||
|
||||
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*/
|
||||
|
@ -35,13 +35,15 @@ Acq_Conf::Acq_Conf()
|
||||
{
|
||||
/* PCPS acquisition configuration */
|
||||
sampled_ms = 0;
|
||||
ms_per_code = 0;
|
||||
max_dwells = 0;
|
||||
samples_per_chip = 0;
|
||||
doppler_max = 0;
|
||||
num_doppler_bins_step2 = 0;
|
||||
doppler_step2 = 0.0;
|
||||
fs_in = 0;
|
||||
samples_per_ms = 0;
|
||||
samples_per_code = 0;
|
||||
samples_per_ms = 0.0;
|
||||
samples_per_code = 0.0;
|
||||
bit_transition_flag = false;
|
||||
use_CFAR_algorithm_flag = false;
|
||||
dump = false;
|
||||
|
@ -40,13 +40,15 @@ class Acq_Conf
|
||||
public:
|
||||
/* PCPS Acquisition configuration */
|
||||
unsigned int sampled_ms;
|
||||
unsigned int ms_per_code;
|
||||
unsigned int samples_per_chip;
|
||||
unsigned int max_dwells;
|
||||
unsigned int doppler_max;
|
||||
unsigned int num_doppler_bins_step2;
|
||||
float doppler_step2;
|
||||
long fs_in;
|
||||
int samples_per_ms;
|
||||
int samples_per_code;
|
||||
float samples_per_ms;
|
||||
float samples_per_code;
|
||||
bool bit_transition_flag;
|
||||
bool use_CFAR_algorithm_flag;
|
||||
bool dump;
|
||||
|
@ -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
|
||||
* 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)
|
||||
{
|
||||
|
@ -83,26 +83,20 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(
|
||||
}
|
||||
}
|
||||
d_stat = 0;
|
||||
d_symbol_accumulator = 0;
|
||||
d_symbol_accumulator_counter = 0;
|
||||
d_frame_bit_index = 0;
|
||||
d_flag_frame_sync = false;
|
||||
d_GPS_frame_4bytes = 0;
|
||||
d_prev_GPS_frame_4bytes = 0;
|
||||
d_flag_parity = false;
|
||||
d_TOW_at_Preamble_ms = 0;
|
||||
flag_TOW_set = false;
|
||||
d_flag_preamble = false;
|
||||
d_flag_new_tow_available = false;
|
||||
d_word_number = 0;
|
||||
d_channel = 0;
|
||||
flag_PLL_180_deg_phase_locked = false;
|
||||
d_preamble_time_samples = 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_make_correlation = true;
|
||||
d_symbol_counter_corr = 0;
|
||||
d_crc_error_synchronization_counter = 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)
|
||||
{
|
||||
d_nav.reset();
|
||||
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
d_channel = channel;
|
||||
d_GPS_FSM.i_channel_ID = channel;
|
||||
d_nav.i_channel_ID = channel;
|
||||
DLOG(INFO) << "Navigation channel set to " << channel;
|
||||
// ############# ENABLE DATA FILE LOG #################
|
||||
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)),
|
||||
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
|
||||
{
|
||||
int corr_value = 0;
|
||||
int preamble_diff_ms = 0;
|
||||
|
||||
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
|
||||
//1. Copy the current tracking output
|
||||
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
|
||||
consume_each(1);
|
||||
|
||||
unsigned int required_symbols = GPS_CA_PREAMBLE_LENGTH_SYMBOLS;
|
||||
d_flag_preamble = false;
|
||||
|
||||
if ((d_symbol_history.size() > required_symbols) and (d_make_correlation or !d_flag_frame_sync))
|
||||
{
|
||||
|
||||
//******* 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++)
|
||||
{
|
||||
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 ******************
|
||||
if (std::abs(corr_value) == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
|
||||
{
|
||||
//TODO: Rewrite with state machine
|
||||
if (d_stat == 0)
|
||||
{
|
||||
d_GPS_FSM.Event_gps_word_preamble();
|
||||
//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;
|
||||
//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
|
||||
}
|
||||
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);
|
||||
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;
|
||||
d_GPS_FSM.Event_gps_word_preamble();
|
||||
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
|
||||
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 "
|
||||
<< static_cast<double>(d_preamble_time_samples) / static_cast<double>(d_symbol_history.at(0).fs) << " [s]";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
//try to decode the subframe:
|
||||
if (decode_subframe() == false)
|
||||
{
|
||||
d_symbol_counter_corr++;
|
||||
if (d_symbol_counter_corr > (GPS_SUBFRAME_MS - GPS_CA_TELEMETRY_SYMBOLS_PER_BIT))
|
||||
d_crc_error_synchronization_counter++;
|
||||
if (d_crc_error_synchronization_counter > 3)
|
||||
{
|
||||
d_make_correlation = true;
|
||||
}
|
||||
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;
|
||||
DLOG(INFO) << "TOO MANY CRC ERRORS: Lost of frame sync SAT " << this->d_satellite << std::endl;
|
||||
d_stat = 0; //lost of frame sync
|
||||
d_flag_frame_sync = false;
|
||||
flag_TOW_set = false;
|
||||
d_make_correlation = true;
|
||||
d_symbol_counter_corr = 0;
|
||||
d_crc_error_synchronization_counter = 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
|
||||
{
|
||||
d_GPS_FSM.Event_gps_word_invalid();
|
||||
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
|
||||
if (d_stat == 1)
|
||||
{
|
||||
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
|
||||
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;
|
||||
flag_TOW_set = true;
|
||||
d_flag_new_tow_available = false;
|
||||
|
@ -32,7 +32,7 @@
|
||||
#define GNSS_SDR_GPS_L1_CA_TELEMETRY_DECODER_CC_H
|
||||
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "gps_l1_ca_subframe_fsm.h"
|
||||
#include "gps_navigation_message.h"
|
||||
#include "gnss_satellite.h"
|
||||
#include "gnss_synchro.h"
|
||||
#include <gnuradio/block.h>
|
||||
@ -72,7 +72,9 @@ private:
|
||||
|
||||
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;
|
||||
unsigned int d_stat;
|
||||
@ -80,26 +82,16 @@ private:
|
||||
|
||||
// symbols
|
||||
boost::circular_buffer<Gnss_Synchro> d_symbol_history;
|
||||
|
||||
double d_symbol_accumulator;
|
||||
short int d_symbol_accumulator_counter;
|
||||
|
||||
// symbol counting
|
||||
bool d_make_correlation;
|
||||
unsigned int d_symbol_counter_corr;
|
||||
float d_subframe_symbols[GPS_SUBFRAME_MS]; //symbols per subframe
|
||||
int d_current_subframe_symbol;
|
||||
|
||||
//bits and frame
|
||||
unsigned short int d_frame_bit_index;
|
||||
unsigned int d_GPS_frame_4bytes;
|
||||
unsigned int d_prev_GPS_frame_4bytes;
|
||||
bool d_flag_parity;
|
||||
bool d_flag_preamble;
|
||||
bool d_flag_new_tow_available;
|
||||
int d_word_number;
|
||||
|
||||
// navigation message vars
|
||||
Gps_Navigation_Message d_nav;
|
||||
GpsL1CaSubframeFsm d_GPS_FSM;
|
||||
|
||||
bool d_dump;
|
||||
Gnss_Satellite d_satellite;
|
||||
|
@ -19,7 +19,6 @@
|
||||
add_subdirectory(libswiftcnav)
|
||||
|
||||
set(TELEMETRY_DECODER_LIB_SOURCES
|
||||
gps_l1_ca_subframe_fsm.cc
|
||||
viterbi_decoder.cc
|
||||
)
|
||||
|
||||
|
@ -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());
|
||||
}
|
@ -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
|
@ -50,6 +50,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${ARMADILLO_INCLUDE_DIRS}
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
${GNURADIO_RUNTIME_INCLUDE_DIRS}
|
||||
|
@ -49,6 +49,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/core/receiver
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${ARMADILLO_INCLUDE_DIRS}
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
|
@ -2,6 +2,7 @@
|
||||
* \file dll_pll_veml_tracking.cc
|
||||
* \brief Implementation of a code DLL + carrier PLL tracking block.
|
||||
* \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:
|
||||
* [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->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
|
||||
d_veml = false;
|
||||
d_cloop = true;
|
||||
d_synchonizing = false;
|
||||
d_code_chip_rate = 0.0;
|
||||
d_secondary_code_length = 0;
|
||||
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;
|
||||
trk_parameters.track_pilot = 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)
|
||||
{
|
||||
@ -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_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_samples = T_prn_true_seconds * trk_parameters.fs_in;
|
||||
@ -520,7 +548,6 @@ void dll_pll_veml_tracking::start_tracking()
|
||||
|
||||
// enable tracking pull-in
|
||||
d_state = 1;
|
||||
d_synchonizing = false;
|
||||
d_cloop = true;
|
||||
d_Prompt_buffer_deque.clear();
|
||||
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()
|
||||
{
|
||||
if (signal_type.compare("1C") == 0)
|
||||
{
|
||||
volk_gnsssdr_free(d_gps_l1ca_preambles_symbols);
|
||||
}
|
||||
|
||||
if (d_dump_file.is_open())
|
||||
{
|
||||
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
|
||||
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;
|
||||
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 #################################################
|
||||
// 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_float;
|
||||
double tmp_double;
|
||||
unsigned long int tmp_long_int;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
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_Q), sizeof(float));
|
||||
// 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
|
||||
tmp_float = d_acc_carrier_phase_rad;
|
||||
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
|
||||
{
|
||||
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++;
|
||||
}
|
||||
else if (d_current_symbol > d_symbols_per_bit)
|
||||
for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
|
||||
{
|
||||
d_synchonizing = false;
|
||||
d_current_symbol = 1;
|
||||
if (d_symbol_history.at(i) < 0) // symbols clipping
|
||||
{
|
||||
corr_value -= d_gps_l1ca_preambles_symbols[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
d_current_symbol = 1;
|
||||
d_last_prompt = *d_Prompt;
|
||||
corr_value += d_gps_l1ca_preambles_symbols[i];
|
||||
}
|
||||
}
|
||||
else if (d_last_prompt.real() != 0.0)
|
||||
}
|
||||
if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
|
||||
{
|
||||
d_current_symbol++;
|
||||
if (d_current_symbol == d_symbols_per_bit) next_state = true;
|
||||
//std::cout << "Preamble detected at tracking!" << std::endl;
|
||||
next_state = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_last_prompt = *d_Prompt;
|
||||
d_synchonizing = true;
|
||||
d_current_symbol = 1;
|
||||
next_state = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
next_state = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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)
|
||||
{ // reset extended correlator
|
||||
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_Prompt_buffer_deque.clear();
|
||||
d_current_symbol = 0;
|
||||
d_synchonizing = false;
|
||||
|
||||
if (d_enable_extended_integration)
|
||||
{
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
|
||||
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_);
|
||||
|
||||
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 acquire_secondary();
|
||||
@ -102,9 +104,12 @@ private:
|
||||
std::string *d_secondary_code_string;
|
||||
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
|
||||
int d_state;
|
||||
bool d_synchonizing;
|
||||
//Integration period in samples
|
||||
int d_correlation_length_ms;
|
||||
int d_n_correlator_taps;
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "tracking_2nd_PLL_filter.h"
|
||||
#include <armadillo>
|
||||
#include "cpu_multicorrelator_real_codes.h"
|
||||
#include "bayesian_estimation.h"
|
||||
|
||||
class Gps_L1_Ca_Kf_Tracking_cc;
|
||||
|
||||
@ -133,6 +134,9 @@ private:
|
||||
arma::colvec kf_y_pre; //measurement vector
|
||||
arma::mat kf_K; //Kalman gain matrix
|
||||
|
||||
// Bayesian estimator
|
||||
Bayesian_estimator cov_est;
|
||||
|
||||
|
||||
// PLL and DLL filter library
|
||||
Tracking_2nd_DLL_filter d_code_loop_filter;
|
||||
|
@ -44,6 +44,7 @@ set(TRACKING_LIB_SOURCES
|
||||
tracking_FLL_PLL_filter.cc
|
||||
tracking_loop_filter.cc
|
||||
dll_pll_conf.cc
|
||||
bayesian_estimation.cc
|
||||
)
|
||||
|
||||
if(ENABLE_FPGA)
|
||||
@ -56,6 +57,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/core/interfaces
|
||||
${CMAKE_SOURCE_DIR}/src/core/receiver
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${ARMADILLO_INCLUDE_DIRS}
|
||||
${VOLK_INCLUDE_DIRS}
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
|
167
src/algorithms/tracking/libs/bayesian_estimation.cc
Normal file
167
src/algorithms/tracking/libs/bayesian_estimation.cc
Normal 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;
|
||||
}
|
||||
|
86
src/algorithms/tracking/libs/bayesian_estimation.h
Normal file
86
src/algorithms/tracking/libs/bayesian_estimation.h
Normal 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
|
@ -61,6 +61,7 @@ public:
|
||||
virtual void set_doppler_step(unsigned int doppler_step) = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void set_local_code() = 0;
|
||||
virtual void set_state(int state) = 0;
|
||||
virtual signed int mag() = 0;
|
||||
virtual void reset() = 0;
|
||||
};
|
||||
|
@ -27,6 +27,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/core/system_parameters
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
${GNURADIO_RUNTIME_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})
|
||||
source_group(Headers FILES ${CORE_MONITOR_LIBS_HEADERS})
|
||||
target_link_libraries(core_monitor_lib ${Boost_LIBRARIES})
|
||||
add_dependencies(core_monitor_lib glog-${glog_RELEASE})
|
||||
|
@ -418,7 +418,7 @@ void GNSSFlowgraph::connect()
|
||||
}
|
||||
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
|
||||
{
|
||||
@ -896,6 +896,43 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
|
||||
|
||||
case 1:
|
||||
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;
|
||||
acq_channels_count_--;
|
||||
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:
|
||||
result = available_GPS_1C_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GPS_1C_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GPS_1C_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1387,9 +1425,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGPS_2S:
|
||||
result = available_GPS_2S_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GPS_2S_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GPS_2S_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1417,9 +1456,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGPS_L5:
|
||||
result = available_GPS_L5_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GPS_L5_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GPS_L5_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1447,9 +1487,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGAL_1B:
|
||||
result = available_GAL_1B_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GAL_1B_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GAL_1B_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1471,9 +1512,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGAL_5X:
|
||||
result = available_GAL_5X_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GAL_5X_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GAL_5X_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1495,9 +1537,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGLO_1G:
|
||||
result = available_GLO_1G_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GLO_1G_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GLO_1G_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
@ -1519,9 +1562,10 @@ Gnss_Signal GNSSFlowgraph::search_next_signal(std::string searched_signal, bool
|
||||
|
||||
case evGLO_2G:
|
||||
result = available_GLO_2G_signals_.front();
|
||||
if (pop)
|
||||
{
|
||||
available_GLO_2G_signals_.pop_front();
|
||||
if (!pop)
|
||||
{
|
||||
available_GLO_2G_signals_.push_back(result);
|
||||
}
|
||||
if (tracked)
|
||||
{
|
||||
|
@ -84,6 +84,9 @@ public:
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
if (version)
|
||||
{
|
||||
};
|
||||
// Satellite and signal info
|
||||
ar& System;
|
||||
ar& Signal;
|
||||
|
@ -34,8 +34,15 @@
|
||||
#include <gflags/gflags.h>
|
||||
#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
|
||||
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_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]");
|
||||
@ -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_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_double(skip_trk_transitory_s, 1.0, "Skip the initial tracking output signal to avoid transitory results [s]");
|
||||
|
||||
//Emulated acquisition configuration
|
||||
|
||||
//Tracking configuration
|
||||
|
@ -600,6 +600,14 @@ void ObsSystemTest::compute_pseudorange_error(
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
Gnuplot g1("linespoints");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g1.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g1.disablescreen();
|
||||
}
|
||||
g1.set_title(signal_name + " Pseudorange error");
|
||||
g1.set_grid();
|
||||
g1.set_xlabel("PRN");
|
||||
@ -620,7 +628,6 @@ void ObsSystemTest::compute_pseudorange_error(
|
||||
}
|
||||
g1.savetops("Pseudorange_error_" + signal_name);
|
||||
g1.savetopdf("Pseudorange_error_" + signal_name, 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
@ -691,6 +698,14 @@ void ObsSystemTest::compute_carrierphase_error(
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
Gnuplot g1("linespoints");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g1.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g1.disablescreen();
|
||||
}
|
||||
g1.set_title(signal_name + " Carrier phase error");
|
||||
g1.set_grid();
|
||||
g1.set_xlabel("PRN");
|
||||
@ -711,7 +726,6 @@ void ObsSystemTest::compute_carrierphase_error(
|
||||
}
|
||||
g1.savetops("Carrier_phase_error_" + signal_name);
|
||||
g1.savetopdf("Carrier_phase_error_" + signal_name, 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
@ -782,6 +796,14 @@ void ObsSystemTest::compute_doppler_error(
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
Gnuplot g1("linespoints");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g1.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g1.disablescreen();
|
||||
}
|
||||
g1.set_title(signal_name + " Doppler error");
|
||||
g1.set_grid();
|
||||
g1.set_xlabel("PRN");
|
||||
@ -802,7 +824,6 @@ void ObsSystemTest::compute_doppler_error(
|
||||
}
|
||||
g1.savetops("Doppler_error_" + signal_name);
|
||||
g1.savetopdf("Doppler_error_" + signal_name, 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
|
@ -619,6 +619,14 @@ void StaticPositionSystemTest::print_results(const std::vector<double>& east,
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
Gnuplot g1("points");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g1.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g1.disablescreen();
|
||||
}
|
||||
g1.set_title("2D precision");
|
||||
g1.set_xlabel("East [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.savetopdf("Position_test_2D", 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
|
||||
Gnuplot g2("points");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g2.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g2.disablescreen();
|
||||
}
|
||||
g2.set_title("3D precision");
|
||||
g2.set_xlabel("East [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.savetopdf("Position_test_3D");
|
||||
if (FLAGS_show_plots) g2.showonscreen(); // window output
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
|
@ -145,10 +145,11 @@ DECLARE_string(log_dir);
|
||||
#if EXTRA_TESTS
|
||||
#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/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_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/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/observables/hybrid_observables_test.cc"
|
||||
#endif
|
||||
|
@ -116,6 +116,14 @@ TEST(FFTLengthTest, MeasureExecutionTime)
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
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_grid();
|
||||
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.savetops("FFT_execution_times_extended");
|
||||
g1.savetopdf("FFT_execution_times_extended", 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
|
||||
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_grid();
|
||||
g2.set_xlabel("FFT length");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* \file gps_l1_acq_performance_test.cc
|
||||
* \file acq_performance_test.cc
|
||||
* \brief This class implements an acquisition performance test
|
||||
* \author Carles Fernandez-Prades, 2018. cfernandez(at)cttc.cat
|
||||
*
|
||||
@ -29,26 +29,38 @@
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "test_flags.h"
|
||||
#include "signal_generator_flags.h"
|
||||
#include "tracking_true_obs_reader.h"
|
||||
#include "true_observables_reader.h"
|
||||
#include "gps_l1_ca_pcps_acquisition.h"
|
||||
#include "gps_l1_ca_pcps_acquisition_fine_doppler.h"
|
||||
#include "galileo_e1_pcps_ambiguous_acquisition.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 "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 <gnuradio/top_block.h>
|
||||
#include <glog/logging.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <gnuradio/blocks/skiphead.h>
|
||||
|
||||
|
||||
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_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_step, 125, "Doppler step, in Hz.");
|
||||
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_bool(acq_test_use_CFAR_algorithm, true, "Use CFAR algorithm");
|
||||
DEFINE_bool(acq_test_bit_transition_flag, false, "Bit transition flag");
|
||||
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_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_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_step, 3.0, "CN0 step, in dB.");
|
||||
|
||||
DEFINE_double(acq_test_threshold_init, 11.0, "Initial acquisition threshold");
|
||||
DEFINE_double(acq_test_threshold_final, 16.0, "Final acquisition threshold");
|
||||
DEFINE_double(acq_test_threshold_step, 1.0, "Acquisition threshold step");
|
||||
DEFINE_double(acq_test_threshold_init, 3.0, "Initial acquisition threshold");
|
||||
DEFINE_double(acq_test_threshold_final, 4.0, "Final acquisition threshold");
|
||||
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");
|
||||
|
||||
@ -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_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 #########
|
||||
class AcqPerfTest_msg_rx;
|
||||
@ -151,6 +164,84 @@ protected:
|
||||
{
|
||||
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();
|
||||
|
||||
if (FLAGS_acq_test_pfa_init > 0.0)
|
||||
@ -178,7 +269,7 @@ protected:
|
||||
|
||||
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))
|
||||
{
|
||||
num_of_measurements = static_cast<unsigned int>(FLAGS_acq_test_num_meas);
|
||||
@ -200,7 +291,6 @@ protected:
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::vector<double> cn0_vector;
|
||||
std::vector<float> pfa_vector;
|
||||
|
||||
@ -223,7 +313,7 @@ protected:
|
||||
|
||||
gr::msg_queue::sptr queue;
|
||||
gr::top_block_sptr top_block;
|
||||
std::shared_ptr<GpsL1CaPcpsAcquisition> acquisition;
|
||||
std::shared_ptr<AcquisitionInterface> acquisition;
|
||||
std::shared_ptr<InMemoryConfiguration> config;
|
||||
std::shared_ptr<FileConfiguration> config_f;
|
||||
Gnss_Synchro gnss_synchro;
|
||||
@ -235,10 +325,10 @@ protected:
|
||||
int message;
|
||||
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 int coherent_integration_time_ms = FLAGS_acq_test_coherent_time_ms;
|
||||
int coherent_integration_time_ms;
|
||||
const int in_acquisition = 1;
|
||||
const int dump_channel = 0;
|
||||
|
||||
@ -250,11 +340,14 @@ protected:
|
||||
std::string path_str = "./acq-perf-test";
|
||||
|
||||
int num_thresholds;
|
||||
unsigned int min_integration_ms;
|
||||
|
||||
std::vector<std::vector<float>> Pd;
|
||||
std::vector<std::vector<float>> Pfa;
|
||||
std::vector<std::vector<float>> Pd_correct;
|
||||
|
||||
std::string signal_id;
|
||||
|
||||
private:
|
||||
std::string generator_binary;
|
||||
std::string p1;
|
||||
@ -266,6 +359,7 @@ private:
|
||||
|
||||
std::string filename_rinex_obs = FLAGS_filename_rinex_obs;
|
||||
std::string filename_raw_data = FLAGS_filename_raw_data;
|
||||
char system_id;
|
||||
|
||||
double compute_stdev_precision(const std::vector<double>& vec);
|
||||
double compute_stdev_accuracy(const std::vector<double>& vec, double ref);
|
||||
@ -275,8 +369,8 @@ private:
|
||||
void AcquisitionPerformanceTest::init()
|
||||
{
|
||||
gnss_synchro.Channel_ID = 0;
|
||||
gnss_synchro.System = 'G';
|
||||
std::string signal = "1C";
|
||||
gnss_synchro.System = system_id;
|
||||
std::string signal = signal_id;
|
||||
signal.copy(gnss_synchro.Signal, 2, 0);
|
||||
gnss_synchro.PRN = observed_satellite;
|
||||
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));
|
||||
|
||||
// Set Acquisition
|
||||
config->set_property("Acquisition_1C.implementation", implementation);
|
||||
config->set_property("Acquisition_1C.item_type", "gr_complex");
|
||||
config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max));
|
||||
config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step));
|
||||
config->set_property("Acquisition.implementation", implementation);
|
||||
config->set_property("Acquisition.item_type", "gr_complex");
|
||||
config->set_property("Acquisition.doppler_max", std::to_string(doppler_max));
|
||||
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));
|
||||
//if (FLAGS_acq_test_pfa_init > 0.0) config->supersede_property("Acquisition_1C.pfa", 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.pfa", std::to_string(pfa));
|
||||
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)
|
||||
{
|
||||
config->set_property("Acquisition_1C.use_CFAR_algorithm", "true");
|
||||
config->set_property("Acquisition.use_CFAR_algorithm", "true");
|
||||
}
|
||||
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)
|
||||
{
|
||||
config->set_property("Acquisition_1C.bit_transition_flag", "true");
|
||||
config->set_property("Acquisition.bit_transition_flag", "true");
|
||||
}
|
||||
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_1C.make_two_steps", "false");
|
||||
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.blocking", "true");
|
||||
if (FLAGS_acq_test_make_two_steps)
|
||||
{
|
||||
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);
|
||||
config->set_property("Acquisition_1C.dump_filename", dump_file);
|
||||
config->set_property("Acquisition_1C.dump_channel", std::to_string(dump_channel));
|
||||
config->set_property("Acquisition_1C.blocking_on_standby", "true");
|
||||
config->set_property("Acquisition.dump_filename", dump_file);
|
||||
config->set_property("Acquisition.dump_channel", std::to_string(dump_channel));
|
||||
config->set_property("Acquisition.blocking_on_standby", "true");
|
||||
|
||||
config_f = 0;
|
||||
}
|
||||
@ -450,6 +553,7 @@ int AcquisitionPerformanceTest::run_receiver()
|
||||
|
||||
top_block = gr::make_top_block("Acquisition test");
|
||||
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);
|
||||
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);
|
||||
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_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_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->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(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->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
|
||||
|
||||
start_queue();
|
||||
|
||||
@ -534,9 +676,17 @@ void AcquisitionPerformanceTest::plot_results()
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
Gnuplot g1("linespoints");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g1.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g1.disablescreen();
|
||||
}
|
||||
g1.cmd("set font \"Times,18\"");
|
||||
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 yrange [0:1]");
|
||||
g1.cmd("set xrange[0.0001:1]");
|
||||
@ -560,12 +710,19 @@ void AcquisitionPerformanceTest::plot_results()
|
||||
g1.set_legend();
|
||||
g1.savetops("ROC");
|
||||
g1.savetopdf("ROC", 18);
|
||||
if (FLAGS_show_plots) g1.showonscreen(); // window output
|
||||
|
||||
Gnuplot g2("linespoints");
|
||||
if (FLAGS_show_plots)
|
||||
{
|
||||
g2.showonscreen(); // window output
|
||||
}
|
||||
else
|
||||
{
|
||||
g2.disablescreen();
|
||||
}
|
||||
g2.cmd("set font \"Times,18\"");
|
||||
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 yrange [0:1]");
|
||||
g2.cmd("set xrange[0.0001:1]");
|
||||
@ -589,7 +746,6 @@ void AcquisitionPerformanceTest::plot_results()
|
||||
g2.set_legend();
|
||||
g2.savetops("ROC-valid-detection");
|
||||
g2.savetopdf("ROC-valid-detection", 18);
|
||||
if (FLAGS_show_plots) g2.showonscreen(); // window output
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
@ -659,22 +815,40 @@ TEST_F(AcquisitionPerformanceTest, ROC)
|
||||
run_receiver();
|
||||
|
||||
// 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);
|
||||
|
||||
// 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_doppler = 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);
|
||||
|
||||
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;
|
||||
|
||||
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++)
|
||||
{
|
||||
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();
|
||||
if (acq_dump.positive_acq)
|
||||
{
|
||||
@ -794,7 +968,7 @@ TEST_F(AcquisitionPerformanceTest, ROC)
|
||||
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;
|
||||
}
|
@ -201,6 +201,14 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::plot_grid()
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
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_xlabel("Doppler [Hz]");
|
||||
g1.set_ylabel("Sample");
|
||||
@ -209,7 +217,6 @@ void GalileoE1PcpsAmbiguousAcquisitionTest::plot_grid()
|
||||
|
||||
g1.savetops("Galileo_E1_acq_grid");
|
||||
g1.savetopdf("Galileo_E1_acq_grid");
|
||||
if (FLAGS_show_plots) g1.showonscreen();
|
||||
}
|
||||
catch (const GnuplotException& ge)
|
||||
{
|
||||
|
@ -341,7 +341,7 @@ void GlonassL1CaPcpsAcquisitionGSoC2017Test::config_2()
|
||||
std::to_string(integration_time_ms));
|
||||
config->set_property("Acquisition.max_dwells", "1");
|
||||
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_step", "250");
|
||||
config->set_property("Acquisition.bit_transition_flag", "false");
|
||||
@ -496,7 +496,7 @@ TEST_F(GlonassL1CaPcpsAcquisitionGSoC2017Test, ValidationOfResults)
|
||||
}) << "Failure setting doppler_step.";
|
||||
|
||||
ASSERT_NO_THROW({
|
||||
acquisition->set_threshold(0.5);
|
||||
acquisition->set_threshold(0.05);
|
||||
}) << "Failure setting threshold.";
|
||||
|
||||
ASSERT_NO_THROW({
|
||||
|
@ -202,6 +202,14 @@ void GpsL1CaPcpsAcquisitionTest::plot_grid()
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
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_xlabel("Doppler [Hz]");
|
||||
g1.set_ylabel("Sample");
|
||||
@ -210,7 +218,6 @@ void GpsL1CaPcpsAcquisitionTest::plot_grid()
|
||||
|
||||
g1.savetops("GPS_L1_acq_grid");
|
||||
g1.savetopdf("GPS_L1_acq_grid");
|
||||
if (FLAGS_show_plots) g1.showonscreen();
|
||||
}
|
||||
catch (const GnuplotException &ge)
|
||||
{
|
||||
|
@ -205,6 +205,14 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
|
||||
Gnuplot::set_GNUPlotPath(gnuplot_path);
|
||||
|
||||
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_xlabel("Doppler [Hz]");
|
||||
g1.set_ylabel("Sample");
|
||||
@ -213,7 +221,6 @@ void GpsL2MPcpsAcquisitionTest::plot_grid()
|
||||
|
||||
g1.savetops("GPS_L2CM_acq_grid");
|
||||
g1.savetopdf("GPS_L2CM_acq_grid");
|
||||
if (FLAGS_show_plots) g1.showonscreen();
|
||||
}
|
||||
catch (const GnuplotException &ge)
|
||||
{
|
||||
|
@ -167,6 +167,20 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
|
||||
{
|
||||
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,
|
||||
sat_,
|
||||
doppler_max_,
|
||||
@ -176,6 +190,7 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
|
||||
execution);
|
||||
}
|
||||
|
||||
|
||||
acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
|
||||
unsigned int sat,
|
||||
unsigned int doppler_max,
|
||||
@ -197,6 +212,7 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
|
||||
positive_acq = 0;
|
||||
sample_counter = 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)));
|
||||
std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code));
|
||||
mag = mag_aux;
|
||||
|
@ -58,6 +58,8 @@
|
||||
#include "signal_generator_flags.h"
|
||||
#include "gnss_sdr_sample_counter.h"
|
||||
#include <matio.h>
|
||||
#include "test_flags.h"
|
||||
#include "gnuplot_i.h"
|
||||
|
||||
|
||||
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES #########
|
||||
@ -183,6 +185,7 @@ public:
|
||||
|
||||
int configure_generator();
|
||||
int generate_signal();
|
||||
bool save_mat_xy(std::vector<double>& x, std::vector<double>& y, std::string filename);
|
||||
void check_results_carrier_phase(
|
||||
arma::mat& true_ch0,
|
||||
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.dump", "true");
|
||||
config->set_property("Tracking_1C.dump_filename", "./tracking_ch_");
|
||||
config->set_property("Tracking_1C.pll_bw_hz", "35.0");
|
||||
config->set_property("Tracking_1C.dll_bw_hz", "0.5");
|
||||
config->set_property("Tracking_1C.pll_bw_hz", "5.0");
|
||||
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.unified", "true");
|
||||
|
||||
config->set_property("TelemetryDecoder_1C.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(
|
||||
arma::mat& true_ch0,
|
||||
arma::mat& true_ch1,
|
||||
@ -397,7 +437,12 @@ void HybridObservablesTest::check_results_code_psudorange(
|
||||
int size1 = measured_ch0.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));
|
||||
|
||||
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_ch1_dist_interp;
|
||||
@ -438,6 +483,31 @@ void HybridObservablesTest::check_results_code_psudorange(
|
||||
<< " [meters]" << std::endl;
|
||||
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(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;
|
||||
int test_satellite_PRN = FLAGS_test_satellite_PRN;
|
||||
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");
|
||||
true_obs_file.append(std::to_string(test_satellite_PRN));
|
||||
true_obs_file.append(".dat");
|
||||
@ -700,6 +770,21 @@ TEST_F(HybridObservablesTest, ValidationOfResults)
|
||||
}
|
||||
|
||||
//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");
|
||||
if ((index.size() > 0) and (index(0) > 0))
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <armadillo>
|
||||
#include <matio.h>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <gnuradio/top_block.h>
|
||||
#include <gnuradio/blocks/file_source.h>
|
||||
@ -136,20 +137,24 @@ public:
|
||||
arma::vec& meas_time_s,
|
||||
arma::vec& meas_value,
|
||||
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,
|
||||
arma::vec& true_value,
|
||||
arma::vec& meas_time_s,
|
||||
arma::vec& meas_value,
|
||||
double& mean_error,
|
||||
double& std_dev_error);
|
||||
double& std_dev_error,
|
||||
double& rmse);
|
||||
std::vector<double> check_results_codephase(arma::vec& true_time_s,
|
||||
arma::vec& true_value,
|
||||
arma::vec& meas_time_s,
|
||||
arma::vec& meas_value,
|
||||
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()
|
||||
{
|
||||
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_value,
|
||||
double& mean_error,
|
||||
double& std_dev_error)
|
||||
double& std_dev_error,
|
||||
double& rmse)
|
||||
{
|
||||
// 1. True value interpolation to match the measurement times
|
||||
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);
|
||||
|
||||
arma::vec err2 = arma::square(err);
|
||||
double rmse = sqrt(arma::mean(err2));
|
||||
rmse = sqrt(arma::mean(err2));
|
||||
|
||||
// 3. Mean err and variance
|
||||
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_value,
|
||||
double& mean_error,
|
||||
double& std_dev_error)
|
||||
double& std_dev_error,
|
||||
double& rmse)
|
||||
{
|
||||
// 1. True value interpolation to match the measurement times
|
||||
arma::vec true_value_interp;
|
||||
@ -332,12 +339,13 @@ std::vector<double> GpsL1CADllPllTrackingTest::check_results_acc_carrier_phase(a
|
||||
|
||||
// 2. RMSE
|
||||
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);
|
||||
//conversion between arma::vec and std:vector
|
||||
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
|
||||
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_value,
|
||||
double& mean_error,
|
||||
double& std_dev_error)
|
||||
double& std_dev_error,
|
||||
double& rmse)
|
||||
{
|
||||
// 1. True value interpolation to match the measurement times
|
||||
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);
|
||||
|
||||
arma::vec err2 = arma::square(err);
|
||||
double rmse = sqrt(arma::mean(err2));
|
||||
rmse = sqrt(arma::mean(err2));
|
||||
|
||||
// 3. Mean err and variance
|
||||
double error_mean = arma::mean(err);
|
||||
@ -420,12 +429,15 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
//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>> 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>> 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>> 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>> 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>> 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<double> mean_doppler_error;
|
||||
std::vector<double> std_dev_doppler_error;
|
||||
std::vector<double> rmse_doppler;
|
||||
std::vector<double> mean_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> std_dev_carrier_phase_error;
|
||||
std::vector<double> rmse_carrier_phase;
|
||||
std::vector<double> valid_CN0_values;
|
||||
|
||||
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> code_phase_error_chips;
|
||||
std::vector<double> code_phase_error_meters;
|
||||
std::vector<double> acc_carrier_phase_hz;
|
||||
|
||||
try
|
||||
@ -707,7 +724,7 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
epoch_counter++;
|
||||
}
|
||||
// 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");
|
||||
if (initial_meas_point.size() > 0 and tracking_last_msg != 3)
|
||||
@ -720,20 +737,28 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
|
||||
double mean_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)
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
std_dev_carrier_phase_error.push_back(std_dev_error);
|
||||
rmse_carrier_phase.push_back(rmse);
|
||||
|
||||
//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);
|
||||
@ -741,6 +766,7 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
|
||||
doppler_error_sweep.push_back(doppler_error_hz);
|
||||
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);
|
||||
}
|
||||
else
|
||||
@ -760,10 +786,16 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
{
|
||||
mean_doppler_error_sweep.push_back(mean_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);
|
||||
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);
|
||||
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
|
||||
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++)
|
||||
{
|
||||
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_grid();
|
||||
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);
|
||||
}
|
||||
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),
|
||||
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++)
|
||||
@ -840,7 +886,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
g3.set_legend();
|
||||
g3.savetops("CN0_output");
|
||||
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)
|
||||
@ -849,7 +902,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
if (FLAGS_plot_detail_level >= 1)
|
||||
{
|
||||
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_grid();
|
||||
g5.set_xlabel("Time [s]");
|
||||
@ -866,15 +926,61 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
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.savetops("Code_error_output");
|
||||
g5.savetopdf("Code_error_output", 18);
|
||||
g5.savetops("Code_error_chips");
|
||||
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");
|
||||
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_grid();
|
||||
g6.set_xlabel("Time [s]");
|
||||
@ -891,20 +997,31 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
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.savetops("Carrier_phase_error_output");
|
||||
g6.savetopdf("Carrier_phase_error_output", 18);
|
||||
g6.savetops("Acc_carrier_phase_error_cycles");
|
||||
g6.savetopdf("Acc_carrier_phase_error_cycles", 18);
|
||||
|
||||
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),
|
||||
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++)
|
||||
{
|
||||
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.cmd("set key box opaque");
|
||||
g4.set_xlabel("Time [s]");
|
||||
@ -917,10 +1034,15 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
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.savetops("Doppler_error_output");
|
||||
g4.savetopdf("Doppler_error_output", 18);
|
||||
g4.savetops("Doppler_error_hz");
|
||||
g4.savetopdf("Doppler_error_hz", 18);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -942,7 +1064,14 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
//plot metrics
|
||||
|
||||
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_grid();
|
||||
g7.set_xlabel("CN0 [dB-Hz]");
|
||||
@ -957,10 +1086,17 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
std_dev_doppler_error_sweep.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");
|
||||
|
||||
//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.savetopdf("Doppler_error_metrics", 18);
|
||||
|
||||
|
||||
Gnuplot g8("linespoints");
|
||||
g8.set_title("Accumulated carrier phase error metrics (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")");
|
||||
g8.set_grid();
|
||||
@ -976,6 +1112,11 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
std_dev_carrier_phase_error_sweep.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");
|
||||
//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.savetopdf("Carrier_error_metrics", 18);
|
||||
@ -995,6 +1136,11 @@ TEST_F(GpsL1CADllPllTrackingTest, ValidationOfResults)
|
||||
std_dev_code_phase_error_sweep.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");
|
||||
//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.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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
* implementation based on some input parameters.
|
||||
* \author Javier Arribas, 2018. jarribas(at)cttc.es
|
||||
@ -40,11 +40,17 @@
|
||||
#include <gnuradio/blocks/interleaved_char_to_complex.h>
|
||||
#include <gnuradio/blocks/null_sink.h>
|
||||
#include <gnuradio/blocks/skiphead.h>
|
||||
#include <gnuradio/blocks/head.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "gnss_block_factory.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 "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 "tracking_true_obs_reader.h"
|
||||
#include "tracking_dump_reader.h"
|
||||
@ -71,6 +77,7 @@ private:
|
||||
|
||||
public:
|
||||
int rx_message;
|
||||
gr::top_block_sptr top_block;
|
||||
~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);
|
||||
rx_message = message;
|
||||
top_block->stop(); //stop the flowgraph
|
||||
}
|
||||
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() {}
|
||||
// ######## 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:
|
||||
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);
|
||||
GpsL1CADllPllTrackingPullInTest_msg_rx();
|
||||
TrackingPullInTest_msg_rx();
|
||||
|
||||
public:
|
||||
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
|
||||
{
|
||||
@ -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->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;
|
||||
}
|
||||
|
||||
|
||||
GpsL1CADllPllTrackingPullInTest_msg_rx::~GpsL1CADllPllTrackingPullInTest_msg_rx()
|
||||
TrackingPullInTest_msg_rx::~TrackingPullInTest_msg_rx()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ###########################################################
|
||||
|
||||
class GpsL1CADllPllTrackingPullInTest : public ::testing::Test
|
||||
class TrackingPullInTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
std::string generator_binary;
|
||||
@ -172,7 +180,7 @@ public:
|
||||
std::string p4;
|
||||
std::string p5;
|
||||
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;
|
||||
|
||||
@ -204,7 +212,7 @@ public:
|
||||
double& mean_error,
|
||||
double& std_dev_error);
|
||||
|
||||
GpsL1CADllPllTrackingPullInTest()
|
||||
TrackingPullInTest()
|
||||
{
|
||||
factory = std::make_shared<GNSSBlockFactory>();
|
||||
config = std::make_shared<InMemoryConfiguration>();
|
||||
@ -212,7 +220,7 @@ public:
|
||||
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
|
||||
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;
|
||||
|
||||
@ -276,48 +284,104 @@ int GpsL1CADllPllTrackingPullInTest::generate_signal()
|
||||
}
|
||||
|
||||
|
||||
void GpsL1CADllPllTrackingPullInTest::configure_receiver(
|
||||
void TrackingPullInTest::configure_receiver(
|
||||
double PLL_wide_bw_hz,
|
||||
double DLL_wide_bw_hz,
|
||||
double PLL_narrow_bw_hz,
|
||||
double DLL_narrow_bw_hz,
|
||||
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;
|
||||
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';
|
||||
std::string signal = "1C";
|
||||
System_and_Signal = "GPS L1 CA";
|
||||
signal.copy(gnss_synchro.Signal, 2, 0);
|
||||
gnss_synchro.PRN = FLAGS_test_satellite_PRN;
|
||||
|
||||
config = std::make_shared<InMemoryConfiguration>();
|
||||
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
|
||||
// Set Tracking
|
||||
config->set_property("Tracking_1C.implementation", implementation);
|
||||
config->set_property("Tracking_1C.item_type", "gr_complex");
|
||||
config->set_property("Tracking_1C.pll_bw_hz", std::to_string(PLL_wide_bw_hz));
|
||||
config->set_property("Tracking_1C.dll_bw_hz", std::to_string(DLL_wide_bw_hz));
|
||||
config->set_property("Tracking_1C.early_late_space_chips", "0.5");
|
||||
config->set_property("Tracking_1C.extend_correlation_symbols", std::to_string(extend_correlation_symbols));
|
||||
config->set_property("Tracking_1C.pll_bw_narrow_hz", std::to_string(PLL_narrow_bw_hz));
|
||||
config->set_property("Tracking_1C.dll_bw_narrow_hz", std::to_string(DLL_narrow_bw_hz));
|
||||
config->set_property("Tracking_1C.early_late_space_narrow_chips", "0.5");
|
||||
config->set_property("Tracking_1C.dump", "true");
|
||||
config->set_property("Tracking_1C.dump_filename", "./tracking_ch_");
|
||||
config->set_property("Tracking.early_late_space_chips", "0.5");
|
||||
config->set_property("Tracking.early_late_space_narrow_chips", "0.5");
|
||||
}
|
||||
else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0)
|
||||
{
|
||||
gnss_synchro.System = 'E';
|
||||
std::string signal = "1B";
|
||||
System_and_Signal = "Galileo E1B";
|
||||
signal.copy(gnss_synchro.Signal, 2, 0);
|
||||
config->set_property("Tracking.early_late_space_chips", "0.15");
|
||||
config->set_property("Tracking.very_early_late_space_chips", "0.6");
|
||||
config->set_property("Tracking.early_late_space_narrow_chips", "0.15");
|
||||
config->set_property("Tracking.very_early_late_space_narrow_chips", "0.6");
|
||||
config->set_property("Tracking.track_pilot", "true");
|
||||
}
|
||||
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 << "*** Tracking configuration parameters ***\n";
|
||||
std::cout << "*****************************************\n";
|
||||
std::cout << "pll_bw_hz: " << config->property("Tracking_1C.pll_bw_hz", 0.0) << " Hz\n";
|
||||
std::cout << "dll_bw_hz: " << config->property("Tracking_1C.dll_bw_hz", 0.0) << " Hz\n";
|
||||
std::cout << "pll_bw_narrow_hz: " << config->property("Tracking_1C.pll_bw_narrow_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 << "extend_correlation_symbols: " << config->property("Tracking_1C.extend_correlation_symbols", 0) << " Symbols\n";
|
||||
std::cout << "Signal: " << System_and_Signal << "\n";
|
||||
std::cout << "implementation: " << config->property("Tracking.implementation", std::string("undefined")) << " \n";
|
||||
std::cout << "pll_bw_hz: " << config->property("Tracking.pll_bw_hz", 0.0) << " Hz\n";
|
||||
std::cout << "dll_bw_hz: " << config->property("Tracking.dll_bw_hz", 0.0) << " Hz\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";
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
gr::top_block_sptr top_block;
|
||||
@ -326,23 +390,110 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
|
||||
// Satellite signal definition
|
||||
Gnss_Synchro tmp_gnss_synchro;
|
||||
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';
|
||||
std::string signal = "1C";
|
||||
signal.copy(tmp_gnss_synchro.Signal, 2, 0);
|
||||
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>();
|
||||
config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq));
|
||||
else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 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.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_threshold(config->property("Acquisition.threshold", 0.005));
|
||||
acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000));
|
||||
acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 250));
|
||||
acquisition->set_channel(0);
|
||||
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", 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;
|
||||
try
|
||||
@ -355,15 +506,8 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
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);
|
||||
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"));
|
||||
msg_rx->top_block = top_block;
|
||||
top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
|
||||
|
||||
// 5. Run the flowgraph
|
||||
// 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();
|
||||
acq_samplestamp_map.clear();
|
||||
|
||||
|
||||
for (unsigned int PRN = 1; PRN < 33; PRN++)
|
||||
{
|
||||
tmp_gnss_synchro.PRN = PRN;
|
||||
@ -385,12 +530,13 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
|
||||
acquisition->init();
|
||||
acquisition->set_local_code();
|
||||
acquisition->reset();
|
||||
acquisition->set_state(1);
|
||||
msg_rx->rx_message = 0;
|
||||
top_block->run();
|
||||
if (start_msg == true)
|
||||
{
|
||||
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 << "[";
|
||||
start_msg = false;
|
||||
}
|
||||
@ -410,10 +556,16 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
|
||||
std::cout << " . ";
|
||||
}
|
||||
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 << "]" << 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
|
||||
end = std::chrono::system_clock::now();
|
||||
@ -424,7 +576,7 @@ bool GpsL1CADllPllTrackingPullInTest::acquire_GPS_L1CA_signal(int SV_ID)
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
|
||||
TEST_F(TrackingPullInTest, ValidationOfResults)
|
||||
{
|
||||
//*************************************************
|
||||
//***** 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_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;
|
||||
std::cout << "Estimated Initial Doppler " << true_acq_doppler_hz << "[Hz], estimated Initial code delay " << true_acq_delay_samples << " [Samples]" << std::endl;
|
||||
acq_samplestamp_samples = 0;
|
||||
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
|
||||
std::vector<std::vector<double>> pull_in_results_v_v;
|
||||
@ -552,9 +706,9 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
|
||||
|
||||
//create flowgraph
|
||||
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_);
|
||||
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({
|
||||
@ -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::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::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, 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->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events"));
|
||||
|
||||
file_source->seek(acq_samplestamp_samples, 0);
|
||||
file_source->seek(2 * FLAGS_skip_samples + acq_samplestamp_samples, 0); //skip head. ibyte, two bytes per complex sample
|
||||
}) << "Failure connecting the blocks of tracking test.";
|
||||
|
||||
|
||||
//********************************************************************
|
||||
//***** 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();
|
||||
std::chrono::time_point<std::chrono::system_clock> start, end;
|
||||
EXPECT_NO_THROW({
|
||||
@ -630,6 +785,8 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
|
||||
std::vector<double> prompt;
|
||||
std::vector<double> early;
|
||||
std::vector<double> late;
|
||||
std::vector<double> v_early;
|
||||
std::vector<double> v_late;
|
||||
std::vector<double> promptI;
|
||||
std::vector<double> promptQ;
|
||||
std::vector<double> CN0_dBHz;
|
||||
@ -647,6 +804,8 @@ TEST_F(GpsL1CADllPllTrackingPullInTest, ValidationOfResults)
|
||||
prompt.push_back(trk_dump.abs_P);
|
||||
early.push_back(trk_dump.abs_E);
|
||||
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);
|
||||
promptQ.push_back(trk_dump.prompt_Q);
|
||||
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, early, "Early", 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.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);
|
@ -33,6 +33,7 @@ include_directories(
|
||||
${CMAKE_SOURCE_DIR}/src/core/libs/supl/asn-supl
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs
|
||||
${CMAKE_SOURCE_DIR}/src/algorithms/libs
|
||||
${GLOG_INCLUDE_DIRS}
|
||||
${GFlags_INCLUDE_DIRS}
|
||||
|
@ -144,8 +144,6 @@ FrontEndCal_msg_rx::FrontEndCal_msg_rx() : gr::block("FrontEndCal_msg_rx", gr::i
|
||||
|
||||
|
||||
FrontEndCal_msg_rx::~FrontEndCal_msg_rx() {}
|
||||
|
||||
|
||||
void wait_message()
|
||||
{
|
||||
while (!stop)
|
||||
@ -353,13 +351,14 @@ int main(int argc, char** argv)
|
||||
gnss_synchro->PRN = 1;
|
||||
|
||||
long fs_in_ = configuration->property("GNSS-SDR.internal_fs_sps", 2048000);
|
||||
configuration->set_property("Acquisition.max_dwells", "10");
|
||||
|
||||
GNSSBlockFactory block_factory;
|
||||
acquisition = new GpsL1CaPcpsAcquisitionFineDoppler(configuration.get(), "Acquisition", 1, 1);
|
||||
|
||||
acquisition->set_channel(1);
|
||||
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_step(configuration->property("Acquisition.doppler_step", 250));
|
||||
|
||||
|
@ -85,7 +85,7 @@ Acquisition_2S.doppler_step=125
|
||||
|
||||
Acquisition_2S.use_CFAR_algorithm=false
|
||||
|
||||
Acquisition_2S.threshold=19.5
|
||||
Acquisition_2S.threshold=10
|
||||
|
||||
Acquisition_2S.blocking=true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user