mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-11-06 02:03:04 +00:00
Added J.Arribas contributions: PVT with basic least squares and rinex 2.1 output is now enabled, tracking channels now estimate the CN0 and performs a basic carrier lock detector and returns to acquisition if the tracking loss the lock.
git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@75 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
@@ -19,12 +19,11 @@
|
||||
#include "gps_l1_ca_dll_pll_tracking_cc.h"
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
|
||||
//#include "gps_sdr_signaldef.h"
|
||||
#include "gps_sdr_simd.h"
|
||||
#include "gps_sdr_x86.h"
|
||||
|
||||
#include "control_message_factory.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
@@ -37,6 +36,11 @@
|
||||
#include <glog/log_severity.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
/*!
|
||||
* \todo Include in definition header file
|
||||
*/
|
||||
#define CN0_ESTIMATION_SAMPLES 10
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
gps_l1_ca_dll_pll_tracking_cc_sptr
|
||||
@@ -47,11 +51,18 @@ gps_l1_ca_dll_pll_make_tracking_cc(unsigned int satellite, long if_freq, long fs
|
||||
fs_in, vector_length, queue, dump));
|
||||
}
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::forecast (int noutput_items,
|
||||
gr_vector_int &ninput_items_required){
|
||||
ninput_items_required[0] =d_vector_length*2; //set the required available samples in each call
|
||||
}
|
||||
|
||||
gps_l1_ca_dll_pll_tracking_cc::gps_l1_ca_dll_pll_tracking_cc(unsigned int satellite, long if_freq, long fs_in, unsigned
|
||||
int vector_length, gr_msg_queue_sptr queue, bool dump) :
|
||||
gr_sync_decimator ("gps_l1_ca_dll_pll_tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)),
|
||||
gr_make_io_signature(3, 3, sizeof(float)),vector_length) {
|
||||
gr_block ("gps_l1_ca_dll_pll_tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)),
|
||||
gr_make_io_signature(5, 5, sizeof(float))) {
|
||||
|
||||
//gr_sync_decimator ("gps_l1_ca_dll_pll_tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)),
|
||||
// gr_make_io_signature(3, 3, sizeof(float)),vector_length) {
|
||||
// initialize internal vars
|
||||
d_queue = queue;
|
||||
d_dump = dump;
|
||||
@@ -61,38 +72,39 @@ gps_l1_ca_dll_pll_tracking_cc::gps_l1_ca_dll_pll_tracking_cc(unsigned int satell
|
||||
d_vector_length = vector_length;
|
||||
|
||||
// Initialize tracking variables ==========================================
|
||||
//TODO: Include this setting in configuration file
|
||||
/*!
|
||||
* \todo Include PLL and DLL filter setting in configuration file
|
||||
*/
|
||||
|
||||
//--- DLL variables --------------------------------------------------------
|
||||
d_early_late_spc = 0.5; // Define early-late offset (in chips)
|
||||
d_pdi_code = 0.001;// Summation interval for code
|
||||
d_dllnoisebandwidth=2.0; //Hz
|
||||
d_dllnoisebandwidth=1; //Hz
|
||||
d_dlldampingratio=0.7;
|
||||
calculate_lopp_coef(&d_tau1_code, &d_tau2_code, d_dllnoisebandwidth, d_dlldampingratio,1.0);// Calculate filter coefficient values
|
||||
|
||||
//--- PLL variables --------------------------------------------------------
|
||||
d_pdi_carr = 0.001;// Summation interval for carrier
|
||||
d_plldampingratio=0.7;
|
||||
d_pllnoisebandwidth=25;
|
||||
d_pllnoisebandwidth=50;
|
||||
|
||||
//Calculate filter coefficient values
|
||||
calculate_lopp_coef(&d_tau1_carr, &d_tau2_carr, d_pllnoisebandwidth, d_plldampingratio,0.25);// Calculate filter coefficient values
|
||||
|
||||
// Initialization of local code replica
|
||||
|
||||
// Get a vector with the C/A code sampled 1x/chip
|
||||
d_code_length=1023;
|
||||
d_ca_code=(gr_complex*)malloc(sizeof(gr_complex)*(d_code_length+2));
|
||||
// Get space for a vector with the C/A code replica sampled 1x/chip
|
||||
d_ca_code=new gr_complex[d_code_length+2];
|
||||
|
||||
// Get space for the resampled early / prompt / late local replicas
|
||||
d_early_code=(gr_complex*)malloc(sizeof(gr_complex)*d_vector_length);
|
||||
// Get space for the resampled early / prompt / late local replicas
|
||||
d_prompt_code=(gr_complex*)malloc(sizeof(gr_complex)*d_vector_length);
|
||||
// Get space for the resampled early / prompt / late local replicas
|
||||
d_late_code=(gr_complex*)malloc(sizeof(gr_complex)*d_vector_length);
|
||||
d_early_code= new gr_complex[d_vector_length*2];
|
||||
d_prompt_code=new gr_complex[d_vector_length*2];
|
||||
d_late_code=new gr_complex[d_vector_length*2];
|
||||
|
||||
d_carr_sign=(gr_complex*)malloc(sizeof(gr_complex)*d_vector_length);
|
||||
d_bb_sign=(gr_complex*)malloc(sizeof(gr_complex)*d_vector_length);
|
||||
// space for carrier wipeoff and signal baseband vectors
|
||||
d_carr_sign=new gr_complex[d_vector_length*2];
|
||||
d_bb_sign=new gr_complex[d_vector_length*2];
|
||||
|
||||
//--- Perform initializations ------------------------------
|
||||
|
||||
@@ -114,167 +126,194 @@ gps_l1_ca_dll_pll_tracking_cc::gps_l1_ca_dll_pll_tracking_cc(unsigned int satell
|
||||
d_old_carr_nco = 0.0;
|
||||
d_old_carr_error = 0.0;
|
||||
|
||||
d_absolute_code_phase_chips = 0;
|
||||
d_absolute_code_phase_samples = 0;
|
||||
|
||||
// sample synchronization
|
||||
d_sample_counter=0;
|
||||
d_acq_sample_stamp=0;
|
||||
|
||||
d_dump_filename="./data/trk_epr.dat";
|
||||
d_enable_tracking=false;
|
||||
d_last_seg=0;
|
||||
d_pull_in=false;
|
||||
d_last_seg=0;
|
||||
|
||||
d_blksize=d_vector_length;
|
||||
d_loops_count=0;
|
||||
|
||||
// CN0 estimation and lock detector buffers
|
||||
d_cn0_estimation_counter=0;
|
||||
d_P_I_buffer=new float[CN0_ESTIMATION_SAMPLES];
|
||||
d_P_Q_buffer=new float[CN0_ESTIMATION_SAMPLES];
|
||||
d_carrier_lock_test=1;
|
||||
d_SNR_SNV=0;
|
||||
d_SNR_SNV_dB_Hz=0;
|
||||
d_SNR_MM=0;
|
||||
d_carrier_lock_fail_counter=0;
|
||||
d_carrier_lock_threshold=5;
|
||||
|
||||
}
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::calculate_lopp_coef(float* tau1,float* tau2, float lbw, float zeta, float k){
|
||||
// Solve natural frequency
|
||||
float Wn;
|
||||
Wn = lbw*8*zeta / (4*zeta*zeta + 1);
|
||||
|
||||
// solve for t1 & t2
|
||||
*tau1 = k / (Wn * Wn);
|
||||
*tau2 = (2.0 * zeta) / Wn;
|
||||
//std::cout<<"Tau1= "<<*tau1<<std::endl;
|
||||
//std::cout<<"Tau2= "<<*tau2<<std::endl;
|
||||
}
|
||||
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::start_tracking(){
|
||||
|
||||
unsigned long int acq_sample_difference;
|
||||
int trk_corrected_code_phase;
|
||||
|
||||
acq_sample_difference=this->d_sample_counter-d_acq_sample_stamp-d_vector_length;
|
||||
|
||||
float velocity_ratio,code_freq_mod,T_prn,T_prn_mod,T_chip_mod;
|
||||
|
||||
const float carrier_freq=1575420000;
|
||||
velocity_ratio=(carrier_freq+d_carrier_doppler)/carrier_freq;
|
||||
|
||||
code_freq_mod=velocity_ratio*d_code_freq;
|
||||
|
||||
T_prn=(1/d_code_freq)*(float)d_code_length;
|
||||
|
||||
T_chip_mod=1/code_freq_mod;
|
||||
T_prn_mod=T_chip_mod*(float)d_code_length;
|
||||
|
||||
//compute the code phase chips prediction
|
||||
trk_corrected_code_phase=round(fmod((d_code_phase+(float)acq_sample_difference+(T_prn-T_prn_mod)*((float)acq_sample_difference/(float)d_vector_length)*(float)d_fs_in),(float)d_vector_length));
|
||||
|
||||
if (trk_corrected_code_phase<0)
|
||||
{
|
||||
trk_corrected_code_phase=d_vector_length+trk_corrected_code_phase;
|
||||
}
|
||||
d_absolute_code_phase_samples=(float)trk_corrected_code_phase;
|
||||
|
||||
// generate local reference ALWAYS starting at chip 1, not corrected
|
||||
code_gen_conplex(&d_ca_code[1],d_satellite,0);
|
||||
|
||||
// Then make it possible to do early and late versions
|
||||
d_ca_code[0]=d_ca_code[1023];
|
||||
d_ca_code[1024]=d_ca_code[1];
|
||||
|
||||
DLOG(INFO) << "Start tracking for satellite "<<this->d_satellite<<" received ";
|
||||
|
||||
if (d_dump==true)
|
||||
{
|
||||
//std::stringstream d_dump_filename_str;//create a stringstream to form the dump filename
|
||||
//d_dump_filename_str<<"./data/trk_epl_CH_"<<this->d_channel<<"_SAT_"<<this->d_satellite<<".dat";
|
||||
//d_dump_filename=d_dump_filename_str.str();
|
||||
if (d_dump_file.is_open()==false)
|
||||
{
|
||||
try {
|
||||
d_dump_filename="track_ch"; //base path and name for the tracking log file
|
||||
d_dump_filename.append(boost::lexical_cast<std::string>(d_channel));
|
||||
d_dump_filename.append(".dat");
|
||||
d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
|
||||
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
|
||||
std::cout<<"Tracking dump enabled on channel "<<d_channel<<" Log file: "<<d_dump_filename.c_str()<<std::endl;
|
||||
}
|
||||
catch (std::ifstream::failure e) {
|
||||
std::cout << "channel "<<d_channel <<" Exception opening trk dump file "<<e.what()<<"\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
d_carrier_lock_fail_counter=0;
|
||||
d_pull_in=true;
|
||||
d_enable_tracking=true;
|
||||
std::cout<<"Tracking start on channel "<<d_channel<<" for satellite ID "<< this->d_satellite+1 << std::endl;
|
||||
}
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::update_local_code_refs()
|
||||
{
|
||||
float tcode;
|
||||
float max_tcode;
|
||||
unsigned int i=0;
|
||||
int tmp_index;
|
||||
float block_correction;
|
||||
int associated_chip_index;
|
||||
// unified loop for E, P, L code vectors
|
||||
for (unsigned int i=0;i<d_blksize;i++)
|
||||
{
|
||||
tcode=i*d_code_phase_step+d_rem_code_phase-d_early_late_spc;
|
||||
associated_chip_index=ceil(fmod(tcode,d_code_length));
|
||||
d_early_code[i] = d_ca_code[associated_chip_index];
|
||||
tcode += d_early_late_spc;
|
||||
associated_chip_index = ceil(fmod(tcode, d_code_length));
|
||||
d_prompt_code[i] = d_ca_code[associated_chip_index];
|
||||
tcode += d_early_late_spc;
|
||||
associated_chip_index = ceil(fmod(tcode, d_code_length));
|
||||
d_late_code[i] = d_ca_code[associated_chip_index];
|
||||
}
|
||||
|
||||
// std::cout<<"d_code_phase_step"<<d_code_phase_step<<std::endl;
|
||||
// std::cout<<"d_rem_code_phase"<<d_rem_code_phase<<std::endl;
|
||||
// std::cout<<"d_blk_size"<<d_blk_size<<std::endl;
|
||||
//**** Option 1: Keep the number of samples per PRN period constant and equal to the nominal value
|
||||
//**** and record the size mismatch in a var: d_rem_code_phase
|
||||
//max_tcode=((float)d_vector_length-1.0)*d_code_phase_step+d_rem_code_phase;
|
||||
//d_rem_code_phase = (max_tcode + d_code_phase_step) - 1023.0;
|
||||
//d_rem_code_phase = d_rem_code_phase+((float)d_vector_length-1023.0*(1.0/d_code_freq)*(float)d_fs_in)*d_code_phase_step;
|
||||
|
||||
// Define index into early code vector
|
||||
max_tcode=((float)d_blk_size-1.0)*d_code_phase_step+d_rem_code_phase-d_early_late_spc;
|
||||
|
||||
for (tcode=d_rem_code_phase-d_early_late_spc;tcode<max_tcode;tcode+=d_code_phase_step)
|
||||
{
|
||||
tmp_index=ceil(fmod(tcode,d_code_length));
|
||||
d_early_code[i]=d_ca_code[tmp_index];
|
||||
i++;
|
||||
// if (i==d_vector_length){
|
||||
// std::cout<<"Break "<<std::endl;
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
// Define index into late code vector
|
||||
i=0;
|
||||
max_tcode=((float)d_blk_size-1.0)*d_code_phase_step+d_rem_code_phase+d_early_late_spc;
|
||||
for (tcode=d_rem_code_phase+d_early_late_spc;tcode<max_tcode;tcode+=d_code_phase_step)
|
||||
{
|
||||
tmp_index=ceil(fmod(tcode,d_code_length));
|
||||
d_late_code[i]=d_ca_code[tmp_index];
|
||||
i++;
|
||||
}
|
||||
// Define index into prompt code vector
|
||||
i=0;
|
||||
max_tcode=((float)d_blk_size-1.0)*d_code_phase_step+d_rem_code_phase;
|
||||
for (tcode=d_rem_code_phase;tcode<max_tcode;tcode+=d_code_phase_step)
|
||||
{
|
||||
tmp_index=ceil(fmod(tcode,d_code_length));
|
||||
d_prompt_code[i]=d_ca_code[tmp_index];
|
||||
i++;
|
||||
}
|
||||
|
||||
block_correction=(float)d_blk_size*(1/(float)d_fs_in)-(float)d_code_length*(1/d_code_freq);
|
||||
d_rem_code_phase = (max_tcode + d_code_phase_step - block_correction) - 1023.0;
|
||||
//std::cout<<"d_rem_code_phase="<<d_rem_code_phase<<std::endl;
|
||||
//**** Option 2: Each loop, compute the new PRN sequence code length according to the estimated Doppler
|
||||
tcode=d_blksize*d_code_phase_step+d_rem_code_phase;
|
||||
d_rem_code_phase = tcode - 1023.0; //prompt remaining code phase
|
||||
}
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::update_local_carrier()
|
||||
{
|
||||
float phase, phase_step;
|
||||
float phase, phase_step;
|
||||
|
||||
phase_step = (float)TWO_PI*d_carrier_doppler/d_fs_in;
|
||||
phase=d_rem_carr_phase;
|
||||
for(unsigned int i = 0; i < d_vector_length; i++) {
|
||||
d_carr_sign[i] = std::complex<float>(cos(phase),sin(phase));
|
||||
phase += phase_step;
|
||||
}
|
||||
d_rem_carr_phase=fmod(phase,TWO_PI);
|
||||
phase_step = (float)TWO_PI*d_carrier_doppler/d_fs_in;
|
||||
phase=d_rem_carr_phase;
|
||||
for(unsigned int i = 0; i < d_blksize; i++) {
|
||||
d_carr_sign[i] = std::complex<float>(cos(phase),sin(phase));
|
||||
phase += phase_step;
|
||||
}
|
||||
d_rem_carr_phase=fmod(phase,TWO_PI);
|
||||
}
|
||||
|
||||
gps_l1_ca_dll_pll_tracking_cc::~gps_l1_ca_dll_pll_tracking_cc() {
|
||||
/*!
|
||||
* \todo free memory!!
|
||||
*/
|
||||
d_dump_file.close();
|
||||
|
||||
}
|
||||
|
||||
void gps_l1_ca_dll_pll_tracking_cc::start_tracking(){
|
||||
unsigned long int acq_sample_difference;
|
||||
int trk_corrected_code_phase;
|
||||
|
||||
acq_sample_difference=this->d_sample_counter-d_acq_sample_stamp-d_vector_length;
|
||||
|
||||
float velocity_ratio,code_freq_mod,T_prn,T_prn_mod,T_chip_mod;
|
||||
|
||||
const float carrier_freq=1575420000;
|
||||
velocity_ratio=(carrier_freq+d_carrier_doppler)/carrier_freq;
|
||||
|
||||
code_freq_mod=velocity_ratio*d_code_freq;
|
||||
|
||||
T_prn=(1/d_code_freq)*(float)d_code_length;
|
||||
|
||||
T_chip_mod=1/code_freq_mod;
|
||||
T_prn_mod=T_chip_mod*(float)d_code_length;
|
||||
|
||||
trk_corrected_code_phase=round(fmod((d_code_phase+(float)acq_sample_difference+(T_prn-T_prn_mod)*((float)acq_sample_difference/(float)d_vector_length)*(float)d_fs_in),(float)d_vector_length));
|
||||
|
||||
if (trk_corrected_code_phase<0)
|
||||
{
|
||||
trk_corrected_code_phase=d_vector_length+trk_corrected_code_phase;
|
||||
}
|
||||
d_absolute_code_phase_chips=(float)trk_corrected_code_phase;
|
||||
|
||||
/*
|
||||
std::cout<<"Acq sample stamp"<<d_acq_sample_stamp<<std::endl;
|
||||
std::cout<<"Acq - Trk sample difference "<<acq_sample_difference<<std::endl;
|
||||
std::cout<<"Trk local code correction "<<trk_corrected_code_phase<<std::endl;
|
||||
std::cout<<"Rounded"<<round((float)d_code_length*(float)trk_corrected_code_phase/(float)d_vector_length);
|
||||
*/
|
||||
// generate local reference with the acquisition shift corrected
|
||||
code_gen_conplex(&d_ca_code[1],d_satellite,1023-round((float)d_code_length*(float)trk_corrected_code_phase/(float)d_vector_length));
|
||||
// Then make it possible to do early and late versions
|
||||
d_ca_code[0]=d_ca_code[1023];
|
||||
d_ca_code[1024]=d_ca_code[1];
|
||||
|
||||
DLOG(INFO) << "Start tracking for satellite "<<this->d_satellite<<" received ";
|
||||
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
|
||||
d_enable_tracking=true;
|
||||
std::cout<<"Tracking start on channel "<<d_channel<<" for satellite ID "<< this->d_satellite << std::endl;
|
||||
}
|
||||
|
||||
/*! Tracking signal processing
|
||||
* Notice that this is a class derived from gr_sync_decimator, so each of the ninput_items has vector_length samples
|
||||
*/
|
||||
int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) {
|
||||
|
||||
d_sample_counter+=d_vector_length; //count for the processed samples
|
||||
int gps_l1_ca_dll_pll_tracking_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) {
|
||||
d_loops_count++;
|
||||
if (d_enable_tracking==true){
|
||||
|
||||
if (d_pull_in==true)
|
||||
{
|
||||
int samples_offset=ceil(d_absolute_code_phase_samples);
|
||||
d_code_phase_ms=(d_absolute_code_phase_samples*1000.0)/(float)d_fs_in;
|
||||
consume_each(samples_offset); //shift input to perform alignement with local replica
|
||||
d_sample_counter+=samples_offset; //count for the processed samples
|
||||
d_pull_in=false;
|
||||
return 1;
|
||||
}
|
||||
float carr_error;
|
||||
float carr_nco;
|
||||
float code_error;
|
||||
float code_nco;
|
||||
float tmp_E,tmp_P,tmp_L;
|
||||
|
||||
const gr_complex* in = (gr_complex*) input_items[0];
|
||||
const gr_complex* in = (gr_complex*) input_items[0]; //PRN start block alignement
|
||||
|
||||
float **out = (float **) &output_items[0];
|
||||
|
||||
// Find the size of a "block" or code period in whole samples
|
||||
|
||||
// Update the phasestep based on code freq (variable) and
|
||||
// sampling frequency (fixed)
|
||||
d_code_phase_step = d_code_freq / d_fs_in;
|
||||
// code_phase_step_per_sample = T_sample/T_chip
|
||||
d_code_phase_step = d_code_freq / (float)d_fs_in; //[chips]
|
||||
// variable code PRN sample block size
|
||||
d_blksize=ceil((1023.0-d_rem_code_phase) / d_code_phase_step); //[samples]
|
||||
|
||||
// original variable block size (MATLAB)
|
||||
//d_blk_size = ceil(((float)d_code_length-d_rem_code_phase) / d_code_phase_step);
|
||||
|
||||
// fixed block size (Javi)
|
||||
d_blk_size = ceil((float)d_code_length*(1/1023000.0)*(float)d_fs_in);
|
||||
//float rem_code_phase_samples=d_rem_code_phase/d_code_phase_step;
|
||||
//d_absolute_code_phase_samples-=floor(rem_code_phase_samples);
|
||||
|
||||
//d_rem_code_phase=d_code_phase_step*(rem_code_phase_samples-floor(rem_code_phase_samples));
|
||||
|
||||
this->update_local_code_refs();
|
||||
this->update_local_carrier();
|
||||
@@ -287,7 +326,8 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
|
||||
d_P_Q=0.0;
|
||||
d_L_Q=0.0;
|
||||
|
||||
for(unsigned int i=0;i<d_vector_length;i++) {
|
||||
// perform Early, Prompt and Late correlation
|
||||
for(unsigned int i=0;i<d_blksize;i++) {
|
||||
//Perform the carrier wipe-off
|
||||
d_bb_sign[i] = in[i] * d_carr_sign[i];
|
||||
// Now get early, late, and prompt values for each
|
||||
@@ -302,11 +342,14 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
|
||||
d_L_I += d_late_code[i].real()*d_bb_sign[i].imag();
|
||||
}
|
||||
|
||||
//float block_error_samples;
|
||||
//block_error_samples=(float)d_vector_length-d_blksize;
|
||||
//d_absolute_code_phase_samples=d_absolute_code_phase_samples+block_error_samples;
|
||||
// Find PLL error and update carrier NCO -
|
||||
// Implement carrier loop discriminator (phase detector)
|
||||
//carr_error = atan(d_P.imag() / d_P.real()) / TWO_PI;
|
||||
|
||||
carr_error = atan(d_P_Q / d_P_I) / TWO_PI;
|
||||
carr_error = atan(d_P_Q / d_P_I) / (float)TWO_PI;
|
||||
|
||||
// Implement carrier loop filter and generate NCO command
|
||||
|
||||
@@ -325,33 +368,102 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
|
||||
// Implement code loop filter and generate NCO command
|
||||
code_nco = d_old_code_nco + (d_tau2_code/d_tau1_code)*(code_error - d_old_code_error) + code_error * (d_pdi_code/d_tau1_code);
|
||||
d_old_code_nco = code_nco;
|
||||
d_old_code_error = code_error;
|
||||
|
||||
d_absolute_code_phase_chips+=d_old_code_error; //accumulate the error to get the pseudorange
|
||||
d_old_code_error = code_error; //[chips]
|
||||
|
||||
// Modify code freq based on NCO command
|
||||
d_code_freq = 1023000 - code_nco;
|
||||
|
||||
// Output the tracking data to navigation and PVT
|
||||
|
||||
d_code_phase_ms+=(1023000/d_code_freq)-1.0;
|
||||
|
||||
/*!
|
||||
* \todo Code lock detector
|
||||
*/
|
||||
|
||||
// ####### CN0 ESTIMATION AND LOCK DETECTORS ######
|
||||
if (d_cn0_estimation_counter<CN0_ESTIMATION_SAMPLES)
|
||||
{
|
||||
// fill buffer with prompt correlator output values
|
||||
d_P_I_buffer[d_cn0_estimation_counter]=d_P_I;
|
||||
d_P_Q_buffer[d_cn0_estimation_counter]=d_P_Q;
|
||||
d_cn0_estimation_counter++;
|
||||
}else{
|
||||
// estimate CN0 and lock status using buffered values
|
||||
// MATLAB CODE
|
||||
//Psig=((1/N)*sum(abs(imag(x((n-N+1):n)))))^2;
|
||||
//Ptot=(1/N)*sum(abs(x((n-N+1):n)).^2);
|
||||
//M2=Ptot;
|
||||
//M4=(1/N)*sum(abs(x((n-N+1):n)).^4);
|
||||
//SNR_SNV(count)=Psig/(Ptot-Psig);
|
||||
//SNR_MM(count)=sqrt(2*M2^2-M4)/(M2-Psig);
|
||||
// lock detector operation
|
||||
//NBD=sum(abs(imag(x((n-N+1):n))))^2 + sum(abs(real(x((n-N+1):n))))^2;
|
||||
//NBP=sum(imag(x((n-N+1):n)).^2) - sum(real(x((n-N+1):n)).^2);
|
||||
//LOCK(count)=NBD/NBP;
|
||||
//CN0_SNV_dB=10*log10(SNR_SNV)+10*log10(BW)-10*log10(PRN_length);
|
||||
float tmp_abs_I,tmp_abs_Q;
|
||||
float tmp_sum_abs_I,tmp_sum_abs_Q;
|
||||
float tmp_sum_sqr_I,tmp_sum_sqr_Q;
|
||||
float Psig,Ptot,M2,M4;
|
||||
float NBD,NBP;
|
||||
Psig=0;
|
||||
Ptot=0;
|
||||
NBD=0;
|
||||
NBP=0;
|
||||
tmp_sum_abs_I=0;
|
||||
tmp_sum_abs_Q=0;
|
||||
tmp_sum_sqr_I=0;
|
||||
tmp_sum_sqr_Q=0;
|
||||
for (int i=0;i<CN0_ESTIMATION_SAMPLES;i++)
|
||||
{
|
||||
tmp_abs_I=std::abs(d_P_I_buffer[i]);
|
||||
tmp_abs_Q=std::abs(d_P_Q_buffer[i]);
|
||||
Psig+=tmp_abs_I;
|
||||
Ptot+=d_P_I_buffer[i]*d_P_I_buffer[i]+d_P_Q_buffer[i]*d_P_Q_buffer[i];
|
||||
tmp_sum_abs_I+=tmp_abs_I;
|
||||
tmp_sum_abs_Q+=tmp_abs_Q;
|
||||
tmp_sum_sqr_I+=(d_P_I_buffer[i]*d_P_I_buffer[i]);
|
||||
tmp_sum_sqr_Q+=(d_P_Q_buffer[i]*d_P_Q_buffer[i]);
|
||||
}
|
||||
Psig=Psig/(float)CN0_ESTIMATION_SAMPLES;
|
||||
Psig=Psig*Psig;
|
||||
d_SNR_SNV=Psig/(Ptot/(float)CN0_ESTIMATION_SAMPLES-Psig);
|
||||
d_SNR_SNV_dB_Hz=10*std::log10(d_SNR_SNV)+10*log10(d_fs_in/2)-10*log10(d_code_length);
|
||||
NBD=tmp_sum_abs_I*tmp_sum_abs_I+tmp_sum_abs_Q*tmp_sum_abs_Q;
|
||||
NBP=tmp_sum_sqr_I-tmp_sum_sqr_Q;
|
||||
d_carrier_lock_test=NBD/NBP;
|
||||
d_cn0_estimation_counter=0;
|
||||
|
||||
}
|
||||
// ###### TRACKING UNLOCK NOTIFICATION #####
|
||||
int tracking_message;
|
||||
if (d_carrier_lock_test<d_carrier_lock_threshold or d_carrier_lock_test>30)
|
||||
{
|
||||
d_carrier_lock_fail_counter++;
|
||||
}else{
|
||||
d_carrier_lock_fail_counter--;
|
||||
}
|
||||
if (d_carrier_lock_fail_counter>200)
|
||||
{
|
||||
std::cout<<"Channel "<<d_channel << " loss of lock!\r\n";
|
||||
tracking_message=3; //loss of lock
|
||||
d_channel_internal_queue->push(tracking_message);
|
||||
d_carrier_lock_fail_counter=0;
|
||||
d_enable_tracking=false; // TODO: check if disabling tranking is consistent with the channel state machine
|
||||
|
||||
}
|
||||
//std::cout<<"d_carrier_lock_fail_counter"<<d_carrier_lock_fail_counter<<"\r\n";
|
||||
|
||||
// Output the tracking data to navigation and PVT
|
||||
// Output channel 1: Prompt correlator output Q
|
||||
*out[0]=d_P_Q;
|
||||
// Output channel 2: Prompt correlator output I
|
||||
*out[1]=d_P_I;
|
||||
// Output channel 3: Prompt correlator output
|
||||
*out[2]=d_absolute_code_phase_chips;
|
||||
|
||||
//Equivalent to the "absolute spreading code starting position" information of the matlab tracking algorithm
|
||||
|
||||
// std::cout<<"tmp_E= "<<tmp_E<<std::endl;
|
||||
// std::cout<<"tmp_P= "<<tmp_P<<std::endl;
|
||||
// std::cout<<"tmp_L= "<<tmp_L<<std::endl;
|
||||
//
|
||||
// std::cout<<"trk pllDiscr carr_error= "<<carr_error<<std::endl;
|
||||
// std::cout<<"trk dllDiscr code error= "<<code_error<<std::endl;
|
||||
// std::cout<<"trk dllDiscrFilt code_nco= "<<code_nco<<std::endl;
|
||||
// std::cout<<"trk pllDiscrFilt carr_nco= "<<carr_nco<<std::endl;
|
||||
// Output channel 3: PRN absolute delay [ms]
|
||||
*out[2]=(float)(((double)d_sample_counter/(double)d_fs_in)*1000.0);
|
||||
|
||||
// Output channel 4: PRN code error [ms]
|
||||
*out[3]=d_code_phase_ms;//(code_error*1000.0)/d_code_freq;
|
||||
|
||||
if(d_dump) {
|
||||
// MULTIPLEXED FILE RECORDING - Record results to file
|
||||
@@ -359,23 +471,35 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
|
||||
tmp_P=sqrt(d_P_I*d_P_I+d_P_Q*d_P_Q);
|
||||
tmp_L=sqrt(d_L_I*d_L_I+d_L_Q*d_L_Q);
|
||||
|
||||
// EPR
|
||||
d_dump_file.write((char*)&tmp_E, sizeof(float));
|
||||
d_dump_file.write((char*)&tmp_P, sizeof(float));
|
||||
d_dump_file.write((char*)&tmp_L, sizeof(float));
|
||||
// DLL
|
||||
d_dump_file.write((char*)&code_error, sizeof(float));
|
||||
d_dump_file.write((char*)&code_nco, sizeof(float));
|
||||
//PLL
|
||||
d_dump_file.write((char*)&carr_error, sizeof(float));
|
||||
d_dump_file.write((char*)&carr_nco, sizeof(float));
|
||||
//FREQ AND PHASE
|
||||
d_dump_file.write((char*)&d_code_freq, sizeof(float));
|
||||
d_dump_file.write((char*)&d_carrier_doppler, sizeof(float));
|
||||
// PROMPT I and Q (to analyze navigation symbols)
|
||||
d_dump_file.write((char*)&d_P_I, sizeof(float));
|
||||
d_dump_file.write((char*)&d_P_Q, sizeof(float));
|
||||
try {
|
||||
// EPR
|
||||
d_dump_file.write((char*)&tmp_E, sizeof(float));
|
||||
d_dump_file.write((char*)&tmp_P, sizeof(float));
|
||||
d_dump_file.write((char*)&tmp_L, sizeof(float));
|
||||
// DLL
|
||||
d_dump_file.write((char*)&code_error, sizeof(float));
|
||||
d_dump_file.write((char*)&code_nco, sizeof(float));
|
||||
//PLL
|
||||
d_dump_file.write((char*)&carr_error, sizeof(float));
|
||||
d_dump_file.write((char*)&carr_nco, sizeof(float));
|
||||
|
||||
//FREQ AND PHASE
|
||||
d_dump_file.write((char*)&d_code_freq, sizeof(float));
|
||||
d_dump_file.write((char*)&d_carrier_doppler, sizeof(float));
|
||||
|
||||
// PROMPT I and Q (to analyze navigation symbols)
|
||||
d_dump_file.write((char*)&d_P_I, sizeof(float));
|
||||
d_dump_file.write((char*)&d_P_Q, sizeof(float));
|
||||
|
||||
// Absolute PRN start sample (MATLAB version)
|
||||
//d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int));
|
||||
//d_dump_file.write((char*)&d_loops_count, sizeof(unsigned long int));
|
||||
d_dump_file.write((char*)&d_SNR_SNV_dB_Hz, sizeof(float));
|
||||
d_dump_file.write((char*)&d_carrier_lock_test, sizeof(float));
|
||||
}
|
||||
catch (std::ifstream::failure e) {
|
||||
std::cout << "Exception writing trk dump file "<<e.what()<<"\r\n";
|
||||
}
|
||||
}
|
||||
// debug: Second counter in channel 0
|
||||
if (d_channel==0)
|
||||
@@ -384,21 +508,33 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
|
||||
{
|
||||
d_last_seg=floor(d_sample_counter/d_fs_in);
|
||||
std::cout<<"t="<<d_last_seg<<std::endl;
|
||||
std::cout<<"TRK CH "<<d_channel<<" CN0="<<d_SNR_SNV_dB_Hz<< std::endl;
|
||||
std::cout<<"TRK CH "<<d_channel<<" Carrier_lock_test="<<d_carrier_lock_test<< std::endl;
|
||||
}
|
||||
}
|
||||
if (d_sample_counter>round((float)this->d_fs_in*39)){ //stop after some seconds debug only!
|
||||
d_enable_tracking=false;
|
||||
std::cout<<"Stop tracking at sample "<<d_sample_counter<<" and acq at sample "<<d_acq_sample_stamp<<std::endl;
|
||||
if(d_queue != gr_msg_queue_sptr()) {
|
||||
ControlMessageFactory* cmf = new ControlMessageFactory();
|
||||
d_queue->handle(cmf->GetQueueMessage(200,0)); //send stop to the control_thread
|
||||
delete cmf;
|
||||
std::cout<<"stop sent from tracking" << std::endl;
|
||||
|
||||
if (d_sample_counter>round((float)this->d_fs_in*70)){ //stop after some seconds debug only!
|
||||
d_enable_tracking=false;
|
||||
std::cout<<"Stop tracking at sample "<<d_sample_counter<<" and acq at sample "<<d_acq_sample_stamp<<std::endl;
|
||||
if(d_queue != gr_msg_queue_sptr()) {
|
||||
ControlMessageFactory* cmf = new ControlMessageFactory();
|
||||
d_queue->handle(cmf->GetQueueMessage(200,0)); //send stop to the control_thread
|
||||
delete cmf;
|
||||
std::cout<<"stop sent from tracking";
|
||||
}
|
||||
}
|
||||
}else
|
||||
{
|
||||
if (floor(d_sample_counter/d_fs_in)!=d_last_seg)
|
||||
{
|
||||
d_last_seg=floor(d_sample_counter/d_fs_in);
|
||||
std::cout<<"TRK CH "<<d_channel<<" CN0="<<d_SNR_SNV_dB_Hz<< std::endl;
|
||||
std::cout<<"TRK CH "<<d_channel<<" Carrier_lock_test="<<d_carrier_lock_test<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
//consume_each(1); //not necesary for gr_sync_block derivates
|
||||
return 1; //one group of d_vector_lenght samples at time, and output one set of results ALWAYS even in the case of d_enable_tracking==false
|
||||
consume_each(d_blksize); // this is necesary in gr_block derivates
|
||||
d_sample_counter+=d_blksize; //count for the processed samples
|
||||
return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
#include <gnuradio/gr_block.h>
|
||||
#include <gnuradio/gr_msg_queue.h>
|
||||
#include <gnuradio/gr_sync_decimator.h>
|
||||
//#include <gnuradio/gr_sync_decimator.h>
|
||||
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
|
||||
@@ -59,7 +59,8 @@ gps_l1_ca_dll_pll_make_tracking_cc(unsigned int satellite, long if_freq,
|
||||
int vector_length,
|
||||
gr_msg_queue_sptr queue, bool dump);
|
||||
|
||||
class gps_l1_ca_dll_pll_tracking_cc: public gr_sync_decimator
|
||||
//class gps_l1_ca_dll_pll_tracking_cc: public gr_sync_decimator
|
||||
class gps_l1_ca_dll_pll_tracking_cc: public gr_block
|
||||
{
|
||||
|
||||
private:
|
||||
@@ -143,11 +144,30 @@ private:
|
||||
float d_L_I;
|
||||
float d_L_Q;
|
||||
|
||||
float d_absolute_code_phase_chips;
|
||||
float d_absolute_code_phase_samples;
|
||||
float d_code_phase_ms;
|
||||
|
||||
unsigned int d_blksize;
|
||||
|
||||
unsigned long int d_sample_counter;
|
||||
unsigned long int d_acq_sample_stamp;
|
||||
unsigned long int d_loops_count;
|
||||
|
||||
// CN0 estimation and lock detector
|
||||
int d_cn0_estimation_counter;
|
||||
float* d_P_I_buffer;
|
||||
float* d_P_Q_buffer;
|
||||
float d_carrier_lock_test;
|
||||
float d_SNR_SNV;
|
||||
float d_SNR_MM;
|
||||
float d_SNR_SNV_dB_Hz;
|
||||
|
||||
float d_carrier_lock_threshold;
|
||||
|
||||
int d_carrier_lock_fail_counter;
|
||||
|
||||
bool d_enable_tracking;
|
||||
bool d_pull_in;
|
||||
|
||||
std::string d_dump_filename;
|
||||
std::ofstream d_dump_file;
|
||||
@@ -181,8 +201,12 @@ public:
|
||||
// gr_vector_const_void_star &input_items,
|
||||
// gr_vector_void_star &output_items) = 0;
|
||||
|
||||
int work(int noutput_items, gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
//int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
|
||||
|
||||
int general_work (int noutput_items, gr_vector_int &ninput_items,
|
||||
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
|
||||
|
||||
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user