mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 01: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:
		@@ -7,11 +7,11 @@ ControlThread.wait_for_flowgraph=false
 | 
			
		||||
 | 
			
		||||
;######### SIGNAL_SOURCE CONFIG ############
 | 
			
		||||
SignalSource.implementation=File_Signal_Source
 | 
			
		||||
;SignalSource.filename=/media/My Passport/spirent scenario 2/data/sc2_d8.dat
 | 
			
		||||
;SignalSource.filename=/home/luis/Project/signals/GPS_cap1.dat
 | 
			
		||||
SignalSource.filename=/media/My Passport/KINGSTON (G)/Project Luis/GPSL1_Fs_8MHz_ID_1_CN0_60.dat
 | 
			
		||||
;SignalSource.filename=/media/DATALOGGER/signals/spirent scenario 2/data/sc2_d8.dat
 | 
			
		||||
;SignalSource.filename=/media/My Passport/KINGSTON (G)/Project Luis/GPSL1_Fs_8MHz_ID_1_CN0_60.dat
 | 
			
		||||
SignalSource.filename=/media/DATALOGGER/signals/Agilent GPS Generator/cap2/agilent_cap2.dat
 | 
			
		||||
SignalSource.item_type=gr_complex
 | 
			
		||||
SignalSource.sampling_frequency=8000000
 | 
			
		||||
SignalSource.sampling_frequency=4000000
 | 
			
		||||
SignalSource.samples=0
 | 
			
		||||
SignalSource.repeat=false
 | 
			
		||||
SignalSource.dump=false
 | 
			
		||||
@@ -20,58 +20,72 @@ SignalSource.enable_throttle_control=true
 | 
			
		||||
;######### SIGNAL_CONDITIONER CONFIG ############
 | 
			
		||||
SignalConditioner.implementation=Pass_Through
 | 
			
		||||
SignalConditioner.item_type=gr_complex
 | 
			
		||||
SignalConditioner.sample_freq_in=8000000
 | 
			
		||||
SignalConditioner.sample_freq_out=8000000
 | 
			
		||||
SignalConditioner.sample_freq_in=4000000
 | 
			
		||||
SignalConditioner.sample_freq_out=4000000
 | 
			
		||||
SignalConditioner.dump=false
 | 
			
		||||
 | 
			
		||||
;######### CHANNELS CONFIGURATION CONFIG ############
 | 
			
		||||
Channels.count=1
 | 
			
		||||
Channels.count=6
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION CONFIG ############
 | 
			
		||||
 | 
			
		||||
Acquisition.dump=false
 | 
			
		||||
Acquisition.dump_filename=./acq_dump.dat
 | 
			
		||||
Acquisition.item_type=gr_complex
 | 
			
		||||
Acquisition.fs_in=8000000
 | 
			
		||||
Acquisition.fs_in=4000000
 | 
			
		||||
Acquisition.if=0
 | 
			
		||||
Acquisition.sampled_ms=1
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 0 CONFIG ############
 | 
			
		||||
Acquisition0.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition0.threshold=0.006
 | 
			
		||||
Acquisition0.threshold=0.06
 | 
			
		||||
Acquisition0.doppler_max=10000
 | 
			
		||||
Acquisition0.doppler_step=250
 | 
			
		||||
Acquisition0.satellite=1
 | 
			
		||||
Acquisition0.repeat_satellite=true
 | 
			
		||||
Acquisition0.doppler_step=500
 | 
			
		||||
Acquisition0.satellite=11
 | 
			
		||||
Acquisition0.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 1 CONFIG ############
 | 
			
		||||
Acquisition1.implementation=GPS_L1_CA_GPS_SDR_Acquisition
 | 
			
		||||
Acquisition1.threshold=30
 | 
			
		||||
Acquisition1.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition1.threshold=0.06
 | 
			
		||||
Acquisition1.doppler_max=10000
 | 
			
		||||
Acquisition1.doppler_step=250
 | 
			
		||||
Acquisition1.satellite=16
 | 
			
		||||
Acquisition1.repeat_satellite=true
 | 
			
		||||
Acquisition1.doppler_step=500
 | 
			
		||||
Acquisition1.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 2 CONFIG ############
 | 
			
		||||
Acquisition2.implementation=GPS_L1_CA_TONG_PCPS_Acquisition
 | 
			
		||||
Acquisition2.threshold=
 | 
			
		||||
Acquisition2.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition2.threshold=0.06
 | 
			
		||||
Acquisition2.doppler_max=10000
 | 
			
		||||
Acquisition2.doppler_step=250
 | 
			
		||||
Acquisition2.satellite=21
 | 
			
		||||
Acquisition2.repeat_satellite=true
 | 
			
		||||
 | 
			
		||||
Acquisition2.doppler_step=500
 | 
			
		||||
Acquisition2.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 3 CONFIG ############
 | 
			
		||||
Acquisition3.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition3.threshold=105000
 | 
			
		||||
Acquisition3.threshold=0.06
 | 
			
		||||
Acquisition3.doppler_max=10000
 | 
			
		||||
Acquisition3.doppler_step=500
 | 
			
		||||
Acquisition3.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 3 CONFIG ############
 | 
			
		||||
Acquisition4.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition4.threshold=0.06
 | 
			
		||||
Acquisition4.doppler_max=10000
 | 
			
		||||
Acquisition4.doppler_step=500
 | 
			
		||||
Acquisition4.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
;######### ACQUISITION 3 CONFIG ############
 | 
			
		||||
Acquisition5.implementation=GPS_L1_CA_PCPS_Acquisition
 | 
			
		||||
Acquisition5.threshold=0.06
 | 
			
		||||
Acquisition5.doppler_max=10000
 | 
			
		||||
Acquisition5.doppler_step=500
 | 
			
		||||
Acquisition5.repeat_satellite=false
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
;######### TRACKING CONFIG ############
 | 
			
		||||
Tracking.implementation=GPS_L1_CA_DLL_PLL_Tracking
 | 
			
		||||
Tracking.item_type=gr_complex
 | 
			
		||||
Tracking.vector_length=8000
 | 
			
		||||
Tracking.fs_in=8000000
 | 
			
		||||
Tracking.vector_length=4000
 | 
			
		||||
Tracking.fs_in=4000000
 | 
			
		||||
Tracking.if=0
 | 
			
		||||
Tracking.dump=true
 | 
			
		||||
Tracking.dump_filename=./trk_dump.dat
 | 
			
		||||
@@ -82,7 +96,7 @@ TelemetryDecoder.item_type=gr_complex
 | 
			
		||||
 | 
			
		||||
;######### OBSERVABLES CONFIG ############
 | 
			
		||||
Observables.implementation=GPS_L1_CA_Observables
 | 
			
		||||
Observables.fs_in=8000000;
 | 
			
		||||
Observables.fs_in=4000000;
 | 
			
		||||
 | 
			
		||||
;######### PVT CONFIG ############
 | 
			
		||||
PVT.implementation=Pass_Through
 | 
			
		||||
 
 | 
			
		||||
@@ -8,10 +8,12 @@ lib gnuradio-usrp ;
 | 
			
		||||
lib profiler ;
 | 
			
		||||
lib gsl ;
 | 
			
		||||
lib gslcblas ;
 | 
			
		||||
lib itpp ;
 | 
			
		||||
 | 
			
		||||
project : requirements
 | 
			
		||||
<define>OMNITHREAD_POSIX
 | 
			
		||||
<cxxflags>"-std=c++0x"
 | 
			
		||||
<cxxflags>"-std=c++0x `pkg-config --cflags itpp`"
 | 
			
		||||
<linkflags>"`pkg-config --libs itpp`"
 | 
			
		||||
# <include>src/utils
 | 
			
		||||
# <include>src/utils/INIReader
 | 
			
		||||
<include>src/algorithms/acquisition/adapters
 | 
			
		||||
 
 | 
			
		||||
@@ -195,6 +195,7 @@ int gps_l1_ca_pcps_acquisition_cc::general_work(int noutput_items,
 | 
			
		||||
        int doppler;
 | 
			
		||||
        unsigned int indext = 0;
 | 
			
		||||
        float magt = 0.0;
 | 
			
		||||
        float tmp_magt = 0.0;
 | 
			
		||||
        const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer
 | 
			
		||||
        bool positive_acquisition = false;
 | 
			
		||||
        int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
 | 
			
		||||
@@ -215,8 +216,8 @@ int gps_l1_ca_pcps_acquisition_cc::general_work(int noutput_items,
 | 
			
		||||
        {
 | 
			
		||||
            d_input_power += std::abs(in[i]) * std::abs(in[i]);
 | 
			
		||||
        }
 | 
			
		||||
        d_input_power = d_input_power / ((float)d_fft_size
 | 
			
		||||
                * (float)d_fft_size);
 | 
			
		||||
        //d_input_power = d_input_power / ((float)d_fft_size * (float)d_fft_size);
 | 
			
		||||
        d_input_power = d_input_power / (float)d_fft_size;
 | 
			
		||||
 | 
			
		||||
        // 2º- Doppler frequency search loop
 | 
			
		||||
        for (doppler = (int)(-d_doppler_max); doppler < (int)d_doppler_max; doppler
 | 
			
		||||
@@ -238,11 +239,23 @@ int gps_l1_ca_pcps_acquisition_cc::general_work(int noutput_items,
 | 
			
		||||
            }
 | 
			
		||||
            d_ifft->execute();
 | 
			
		||||
 | 
			
		||||
            x86_gr_complex_mag(d_ifft->get_outbuf(), d_fft_size); // d_ifft->get_outbuf()=|abs(·)|^2 and the array is converted from CPX->Float
 | 
			
		||||
            x86_float_max((float*)d_ifft->get_outbuf(), &indext, &magt,
 | 
			
		||||
                    d_fft_size); // find max of |abs(·)|^2 -> index and magt
 | 
			
		||||
            // ASM accelerated version
 | 
			
		||||
            //x86_gr_complex_mag(d_ifft->get_outbuf(), d_fft_size); // d_ifft->get_outbuf()=|abs(·)|^2 and the array is converted from CPX->Float
 | 
			
		||||
            //x86_float_max((float*)d_ifft->get_outbuf(), &indext, &magt,
 | 
			
		||||
            //        d_fft_size); // find max of |abs(·)|^2 -> index and magt
 | 
			
		||||
 | 
			
		||||
            magt = magt / (float)d_fft_size;
 | 
			
		||||
            // C++ version
 | 
			
		||||
            indext=0;
 | 
			
		||||
            magt=0;
 | 
			
		||||
            for (i = 0; i < d_fft_size; i++)
 | 
			
		||||
            {
 | 
			
		||||
				tmp_magt=std::norm(d_ifft->get_outbuf()[i]);
 | 
			
		||||
				if (tmp_magt>magt){
 | 
			
		||||
					magt=tmp_magt;
 | 
			
		||||
					indext=i;
 | 
			
		||||
				}
 | 
			
		||||
            }
 | 
			
		||||
            //magt = magt / (float)d_fft_size;
 | 
			
		||||
            // Record results to files
 | 
			
		||||
            if (d_dump)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -128,6 +128,8 @@ void Channel::connect(gr_top_block_sptr top_block)
 | 
			
		||||
    top_block->connect(trk_->get_right_block(), 0, nav_->get_left_block(), 0); // channel 1
 | 
			
		||||
    top_block->connect(trk_->get_right_block(), 1, nav_->get_left_block(), 1); // channel 2
 | 
			
		||||
    top_block->connect(trk_->get_right_block(), 2, nav_->get_left_block(), 2); // channel 3
 | 
			
		||||
    top_block->connect(trk_->get_right_block(), 3, nav_->get_left_block(), 3); // channel 4
 | 
			
		||||
    top_block->connect(trk_->get_right_block(), 4, nav_->get_left_block(), 4); // channel 5
 | 
			
		||||
    DLOG(INFO) << "tracking -> telemetry_decoder";
 | 
			
		||||
 | 
			
		||||
    connected_ = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -45,13 +45,6 @@
 | 
			
		||||
#include <glog/log_severity.h>
 | 
			
		||||
#include <glog/logging.h>
 | 
			
		||||
 | 
			
		||||
/* The extern keyword declares a variable or function and specifies
 | 
			
		||||
 * that it has external linkage (its name is visible from files other
 | 
			
		||||
 * than the one in which it's defined). When modifying a variable,
 | 
			
		||||
 * extern specifies that the variable has static duration (it is allocated
 | 
			
		||||
 * when the program begins and deallocated when the program ends).
 | 
			
		||||
 * The variable is defined in main.cc
 | 
			
		||||
 */
 | 
			
		||||
extern concurrent_queue<gps_navigation_message> global_gps_nav_msg_queue;
 | 
			
		||||
 | 
			
		||||
using google::LogMessage;
 | 
			
		||||
 
 | 
			
		||||
@@ -52,18 +52,34 @@ gps_l1_ca_observables_cc::gps_l1_ca_observables_cc(unsigned int nchannels, gr_ms
 | 
			
		||||
  d_dump = dump;
 | 
			
		||||
  d_nchannels = nchannels;
 | 
			
		||||
  d_rinex_printer.set_headers("GNSS-SDR"); //TODO: read filename from config
 | 
			
		||||
  d_ls_pvt=new gps_l1_ca_ls_pvt(nchannels);
 | 
			
		||||
  d_ephemeris_clock_s=0.0;
 | 
			
		||||
  if (d_dump==true)
 | 
			
		||||
  {
 | 
			
		||||
      std::stringstream d_dump_filename_str;//create a stringstream to form the dump filename
 | 
			
		||||
      d_dump_filename_str<<"./data/obs.dat"; //TODO: get filename and path from config in the adapter
 | 
			
		||||
      d_dump_filename=d_dump_filename_str.str();
 | 
			
		||||
      d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gps_l1_ca_observables_cc::~gps_l1_ca_observables_cc() {
 | 
			
		||||
 | 
			
		||||
    delete d_ls_pvt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool pairCompare( pair<int,gnss_synchro> a, pair<int,gnss_synchro> b)
 | 
			
		||||
bool pairCompare_min( pair<int,gnss_synchro> a, pair<int,gnss_synchro> b)
 | 
			
		||||
{
 | 
			
		||||
  return a.second.last_preamble_index < b.second.last_preamble_index;
 | 
			
		||||
  return (a.second.preamble_delay_ms+a.second.prn_delay_ms) < (b.second.preamble_delay_ms+b.second.prn_delay_ms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool pairCompare_max( pair<int,gnss_synchro> a, pair<int,gnss_synchro> b)
 | 
			
		||||
{
 | 
			
		||||
    return (a.second.preamble_delay_ms+a.second.prn_delay_ms) > (b.second.preamble_delay_ms+b.second.prn_delay_ms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int gps_l1_ca_observables_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
 | 
			
		||||
    gr_vector_const_void_star &input_items,	gr_vector_void_star &output_items) {
 | 
			
		||||
 | 
			
		||||
@@ -71,7 +87,7 @@ int gps_l1_ca_observables_cc::general_work (int noutput_items, gr_vector_int &ni
 | 
			
		||||
 | 
			
		||||
  // CONSTANTS TODO: place in a file
 | 
			
		||||
  const float code_length_s=0.001; //1 ms
 | 
			
		||||
  const float C_m_ms= GPS_C_m_s/1000;    // The speed of light, [m/ms]
 | 
			
		||||
  const float C_m_ms= GPS_C_m_s/1000.0;    // The speed of light, [m/ms]
 | 
			
		||||
 | 
			
		||||
  const float nav_sol_period_ms=1000;
 | 
			
		||||
  //--- Find number of samples per spreading code ----------------------------
 | 
			
		||||
@@ -84,46 +100,60 @@ int gps_l1_ca_observables_cc::general_work (int noutput_items, gr_vector_int &ni
 | 
			
		||||
 | 
			
		||||
  map<int,float> pseudoranges;
 | 
			
		||||
  map<int,float>::iterator pseudoranges_iter;
 | 
			
		||||
  map<int,float> pseudoranges_dump;
 | 
			
		||||
 | 
			
		||||
  float min_preamble_delay_ms;
 | 
			
		||||
  float max_preamble_delay_ms;
 | 
			
		||||
  bool  flag_valid_pseudoranges=false;
 | 
			
		||||
 | 
			
		||||
  unsigned long int min_preamble_index;
 | 
			
		||||
 | 
			
		||||
  float prn_delay_ms;
 | 
			
		||||
  float pseudoranges_timestamp_ms;
 | 
			
		||||
  float traveltime_ms;
 | 
			
		||||
  float pseudorange_m;
 | 
			
		||||
 | 
			
		||||
  int pseudoranges_reference_sat_ID=0;
 | 
			
		||||
 | 
			
		||||
  for (unsigned int i=0; i<d_nchannels ; i++)
 | 
			
		||||
    {
 | 
			
		||||
    if (in[i][0].valid_word) //if this channel have valid word
 | 
			
		||||
      {
 | 
			
		||||
      gps_words.insert(pair<int,gnss_synchro>(in[i][0].satellite_PRN,in[i][0])); //record the word structure in a map for pseudoranges
 | 
			
		||||
      gps_words.insert(pair<int,gnss_synchro>(in[i][0].channel_ID,in[i][0])); //record the word structure in a map for pseudoranges
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if(gps_words.size()>0)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
      // find the minimum index (nearest satellite, will be the reference)
 | 
			
		||||
    gps_words_iter=min_element(gps_words.begin(),gps_words.end(),pairCompare);
 | 
			
		||||
    min_preamble_index=gps_words_iter->second.last_preamble_index;
 | 
			
		||||
      gps_words_iter=min_element(gps_words.begin(),gps_words.end(),pairCompare_min);
 | 
			
		||||
      min_preamble_delay_ms=gps_words_iter->second.preamble_delay_ms+gps_words_iter->second.prn_delay_ms; //[ms]
 | 
			
		||||
      pseudoranges_timestamp_ms=min_preamble_delay_ms; //save the shortest pseudorange timestamp to compute the RINEX timestamp
 | 
			
		||||
      pseudoranges_reference_sat_ID=gps_words_iter->second.satellite_PRN;
 | 
			
		||||
      gps_words_iter=max_element(gps_words.begin(),gps_words.end(),pairCompare_max);
 | 
			
		||||
      max_preamble_delay_ms=gps_words_iter->second.preamble_delay_ms; //[ms]
 | 
			
		||||
 | 
			
		||||
      if ((max_preamble_delay_ms-min_preamble_delay_ms)<70) flag_valid_pseudoranges=true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      //compute the pseudoranges
 | 
			
		||||
      for(gps_words_iter = gps_words.begin(); gps_words_iter != gps_words.end(); gps_words_iter++)
 | 
			
		||||
        {
 | 
			
		||||
      prn_delay_ms=gps_words_iter->second.prn_delay/(float)samples_per_code;
 | 
			
		||||
      traveltime_ms=(float)(1000*(gps_words_iter->second.last_preamble_index-min_preamble_index))/(float)samples_per_code+GPS_STARTOFFSET_ms+prn_delay_ms;
 | 
			
		||||
      //cout<<"traveltime ms"<<gps_words_iter->first<<" ="<<traveltime_ms<<endl;
 | 
			
		||||
      pseudorange_m=traveltime_ms*C_m_ms;
 | 
			
		||||
      pseudoranges.insert(pair<int,float>(gps_words_iter->first,pseudorange_m)); //record the preamble index in a map
 | 
			
		||||
        std::cout<<"prn_delay="<<gps_words_iter->second.prn_delay_ms<<std::endl;
 | 
			
		||||
        traveltime_ms=gps_words_iter->second.preamble_delay_ms+gps_words_iter->second.prn_delay_ms-min_preamble_delay_ms+GPS_STARTOFFSET_ms; //[ms]
 | 
			
		||||
        pseudorange_m=traveltime_ms*C_m_ms; // [m]
 | 
			
		||||
        pseudoranges.insert(pair<int,float>(gps_words_iter->second.satellite_PRN,pseudorange_m)); //record the preamble index in a map
 | 
			
		||||
        if (d_dump==true)
 | 
			
		||||
        {
 | 
			
		||||
            pseudoranges_dump.insert(pair<int,float>(gps_words_iter->second.channel_ID,pseudorange_m));
 | 
			
		||||
        }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    // write the pseudoranges to RINEX OBS file
 | 
			
		||||
    // 1- need a valid clock
 | 
			
		||||
    if (d_last_nav_msg.d_satellite_PRN>0)
 | 
			
		||||
    if (flag_valid_pseudoranges==true and d_last_nav_msg.d_satellite_PRN>0)
 | 
			
		||||
      {
 | 
			
		||||
        std::cout<<"d_inter_frame_sec_counter="<<d_inter_frame_sec_counter<<std::endl;
 | 
			
		||||
        d_rinex_printer.LogRinex2Obs(d_last_nav_msg,d_inter_frame_sec_counter,pseudoranges);
 | 
			
		||||
        //d_rinex_printer.LogRinex2Obs(d_last_nav_msg,d_ephemeris_clock_s+((double)pseudoranges_timestamp_ms-d_ephemeris_timestamp_ms)/1000.0,pseudoranges);
 | 
			
		||||
        // compute on the fly PVT solution
 | 
			
		||||
        d_ls_pvt->get_PVT(pseudoranges,d_ephemeris_clock_s+((double)pseudoranges_timestamp_ms-d_ephemeris_timestamp_ms)/1000.0);
 | 
			
		||||
      }
 | 
			
		||||
    d_inter_frame_sec_counter+=((float)NAVIGATION_OUTPUT_RATE_MS)/1000.0; //TODO: synchronize the gps time of the ephemeris with the obs
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  //debug
 | 
			
		||||
@@ -134,29 +164,36 @@ int gps_l1_ca_observables_cc::general_work (int noutput_items, gr_vector_int &ni
 | 
			
		||||
    {
 | 
			
		||||
    cout<<"Pseudoranges =("<<pseudoranges_iter->first<<","<<pseudoranges_iter->second<<")"<<endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  gps_navigation_message nav_msg;
 | 
			
		||||
  if (d_nav_queue->try_pop(nav_msg)==true)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
    cout<<"New ephemeris record has arrived!"<<endl;
 | 
			
		||||
    cout<<"d_channel_ID="<<nav_msg.d_channel_ID<<endl;
 | 
			
		||||
    cout<<"d_satellite_PRN="<<nav_msg.d_satellite_PRN<<endl;
 | 
			
		||||
    cout<<"d_satpos_X="<<nav_msg.d_satpos_X<<endl;
 | 
			
		||||
    cout<<"d_satpos_Y="<<nav_msg.d_satpos_Y<<endl;
 | 
			
		||||
    cout<<"d_satpos_Z="<<nav_msg.d_satpos_Z<<endl;
 | 
			
		||||
    cout<<"d_master_clock="<<nav_msg.d_master_clock<<endl;
 | 
			
		||||
    cout<<"d_satClkCorr="<<nav_msg.d_satClkCorr<<endl;
 | 
			
		||||
    cout<<"d_dtr="<<nav_msg.d_dtr<<endl;
 | 
			
		||||
 | 
			
		||||
    // write ephemeris to RINES NAV file
 | 
			
		||||
    // TODO: check operation ok
 | 
			
		||||
    cout<<"New ephemeris record has arrived from SAT ID "<<nav_msg.d_satellite_PRN<<endl;
 | 
			
		||||
    d_last_nav_msg=nav_msg;
 | 
			
		||||
    d_inter_frame_sec_counter=0; //reset the interframe seconds counter
 | 
			
		||||
    d_rinex_printer.LogRinex2Nav(nav_msg);
 | 
			
		||||
    d_ls_pvt->d_ephemeris[nav_msg.d_channel_ID]=nav_msg;
 | 
			
		||||
    // **** update pseudoranges clock ****
 | 
			
		||||
    if (nav_msg.d_satellite_PRN==pseudoranges_reference_sat_ID)
 | 
			
		||||
    {
 | 
			
		||||
        d_ephemeris_clock_s=d_last_nav_msg.d_TOW;
 | 
			
		||||
        d_ephemeris_timestamp_ms=d_last_nav_msg.d_subframe1_timestamp_ms;
 | 
			
		||||
    }
 | 
			
		||||
    // **** write ephemeris to RINES NAV file
 | 
			
		||||
    //d_rinex_printer.LogRinex2Nav(nav_msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (d_dump==true)
 | 
			
		||||
  {
 | 
			
		||||
      float tmp_float=0.0;
 | 
			
		||||
      for (int i=0;i<d_nchannels;i++)
 | 
			
		||||
      {
 | 
			
		||||
        pseudoranges_iter=pseudoranges_dump.find(i);
 | 
			
		||||
        if (pseudoranges_iter!=pseudoranges_dump.end())
 | 
			
		||||
        {
 | 
			
		||||
            d_dump_file.write((char*)&pseudoranges_iter->second, sizeof(float));
 | 
			
		||||
        }else{
 | 
			
		||||
            d_dump_file.write((char*)&tmp_float, sizeof(float));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
  consume_each(1); //one by one
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
#include "gps_navigation_message.h"
 | 
			
		||||
 | 
			
		||||
#include "rinex_2_1_printer.h"
 | 
			
		||||
#include "gps_l1_ca_ls_pvt.h"
 | 
			
		||||
 | 
			
		||||
#include "GPS_L1_CA.h"
 | 
			
		||||
 | 
			
		||||
@@ -56,10 +57,14 @@ private:
 | 
			
		||||
 | 
			
		||||
  rinex_printer d_rinex_printer; // RINEX printer class
 | 
			
		||||
 | 
			
		||||
  double d_inter_frame_sec_counter; // counter for seconds between GPS frames
 | 
			
		||||
 | 
			
		||||
  gps_navigation_message d_last_nav_msg; //last navigation message
 | 
			
		||||
 | 
			
		||||
  double d_ephemeris_clock_s;
 | 
			
		||||
  double d_ephemeris_timestamp_ms;
 | 
			
		||||
 | 
			
		||||
  gps_l1_ca_ls_pvt *d_ls_pvt;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
  ~gps_l1_ca_observables_cc ();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										316
									
								
								src/algorithms/observables/libs/gps_l1_ca_ls_pvt.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										316
									
								
								src/algorithms/observables/libs/gps_l1_ca_ls_pvt.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,316 @@
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright notice
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Author: Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <itpp/itbase.h>
 | 
			
		||||
#include <itpp/stat/misc_stat.h>
 | 
			
		||||
#include <itpp/base/matfunc.h>
 | 
			
		||||
 | 
			
		||||
using namespace itpp;
 | 
			
		||||
 | 
			
		||||
#include "gps_l1_ca_ls_pvt.h"
 | 
			
		||||
 | 
			
		||||
gps_l1_ca_ls_pvt::gps_l1_ca_ls_pvt(int nchannels)
 | 
			
		||||
{
 | 
			
		||||
    // init empty ephemerids for all the available GNSS channels
 | 
			
		||||
    d_nchannels=nchannels;
 | 
			
		||||
    d_ephemeris=new gps_navigation_message[nchannels];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gps_l1_ca_ls_pvt::~gps_l1_ca_ls_pvt()
 | 
			
		||||
{
 | 
			
		||||
    delete d_ephemeris;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vec gps_l1_ca_ls_pvt::e_r_corr(double traveltime, vec X_sat) {
 | 
			
		||||
    /*
 | 
			
		||||
     %E_R_CORR  Returns rotated satellite ECEF coordinates due to Earth
 | 
			
		||||
     %rotation during signal travel time
 | 
			
		||||
     %
 | 
			
		||||
     %X_sat_rot = e_r_corr(traveltime, X_sat);
 | 
			
		||||
     %
 | 
			
		||||
     %   Inputs:
 | 
			
		||||
     %       travelTime  - signal travel time
 | 
			
		||||
     %       X_sat       - satellite's ECEF coordinates
 | 
			
		||||
     %
 | 
			
		||||
     %   Outputs:
 | 
			
		||||
     %       X_sat_rot   - rotated satellite's coordinates (ECEF)
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    double Omegae_dot = 7.292115147e-5; //  rad/sec
 | 
			
		||||
 | 
			
		||||
    //--- Find rotation angle --------------------------------------------------
 | 
			
		||||
    double omegatau;
 | 
			
		||||
    omegatau = Omegae_dot * traveltime;
 | 
			
		||||
 | 
			
		||||
    //--- Make a rotation matrix -----------------------------------------------
 | 
			
		||||
    mat R3=zeros(3,3);
 | 
			
		||||
    R3(0, 0)= cos(omegatau);
 | 
			
		||||
    R3(0, 1)= sin(omegatau);
 | 
			
		||||
    R3(0, 2)= 0.0;
 | 
			
		||||
    R3(1, 0)=-sin(omegatau);
 | 
			
		||||
    R3(1, 1)= cos(omegatau);
 | 
			
		||||
    R3(1, 2)=0.0;
 | 
			
		||||
    R3(2, 0)= 0.0;
 | 
			
		||||
    R3(2, 1)= 0.0;
 | 
			
		||||
    R3(2, 2)= 1;
 | 
			
		||||
    //--- Do the rotation ------------------------------------------------------
 | 
			
		||||
    vec X_sat_rot;
 | 
			
		||||
    X_sat_rot = R3 * X_sat;
 | 
			
		||||
    return X_sat_rot;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
vec gps_l1_ca_ls_pvt::leastSquarePos(mat satpos, vec obs, mat w) {
 | 
			
		||||
    //Function calculates the Least Square Solution.
 | 
			
		||||
 | 
			
		||||
    //pos= leastSquarePos(satpos, obs, w);
 | 
			
		||||
 | 
			
		||||
    //   Inputs:
 | 
			
		||||
    //       satpos      - Satellites positions (in ECEF system: [X; Y; Z;]
 | 
			
		||||
    //       obs         - Observations - the pseudorange measurements to each
 | 
			
		||||
    //                   satellite
 | 
			
		||||
    //       w           - weigths vector
 | 
			
		||||
 | 
			
		||||
    //   Outputs:
 | 
			
		||||
    //       pos         - receiver position and receiver clock error
 | 
			
		||||
    //                   (in ECEF system: [X, Y, Z, dt])
 | 
			
		||||
 | 
			
		||||
    //////////////////////////////////////////////////////////////////////////
 | 
			
		||||
    //       el          - Satellites elevation angles (degrees)
 | 
			
		||||
    //       az          - Satellites azimuth angles (degrees)
 | 
			
		||||
    //       dop         - Dilutions Of Precision ([GDOP PDOP HDOP VDOP TDOP])
 | 
			
		||||
 | 
			
		||||
    //=== Initialization =======================================================
 | 
			
		||||
    int nmbOfIterations = 10; // TODO: include in config
 | 
			
		||||
 | 
			
		||||
    //double dtr = GPS_PI / 180.0;
 | 
			
		||||
 | 
			
		||||
    int nmbOfSatellites;
 | 
			
		||||
    nmbOfSatellites = satpos.cols();
 | 
			
		||||
    vec pos = "0.0 0.0 0.0 0.0";
 | 
			
		||||
    mat A;
 | 
			
		||||
    mat omc;
 | 
			
		||||
    mat az;
 | 
			
		||||
    mat el;
 | 
			
		||||
    A=zeros(nmbOfSatellites,4);
 | 
			
		||||
    omc=zeros(nmbOfSatellites,1);
 | 
			
		||||
    az=zeros(1,nmbOfSatellites);
 | 
			
		||||
    el=zeros(1,nmbOfSatellites);
 | 
			
		||||
    for (int i = 0; i < nmbOfSatellites; i++) {
 | 
			
		||||
        for (int j = 0; j < 4; j++) {
 | 
			
		||||
            A.set(i, j, 0.0);
 | 
			
		||||
        }
 | 
			
		||||
        omc(i, 0)=0.0;
 | 
			
		||||
        az(0, i)=0.0;
 | 
			
		||||
    }
 | 
			
		||||
    el = az;
 | 
			
		||||
    mat X = satpos;
 | 
			
		||||
 | 
			
		||||
    vec Rot_X;
 | 
			
		||||
    double rho2;
 | 
			
		||||
    double traveltime;
 | 
			
		||||
    double trop;
 | 
			
		||||
    mat mat_tmp;
 | 
			
		||||
    vec x;
 | 
			
		||||
    //=== Iteratively find receiver position ===================================
 | 
			
		||||
    for (int iter = 0; iter < nmbOfIterations; iter++) {
 | 
			
		||||
        for (int i = 0; i < nmbOfSatellites; i++) {
 | 
			
		||||
            if (iter == 0) {
 | 
			
		||||
                //--- Initialize variables at the first iteration --------------
 | 
			
		||||
                Rot_X=X.get_col(i);
 | 
			
		||||
                trop = 0.0;
 | 
			
		||||
            } else {
 | 
			
		||||
                //--- Update equations -----------------------------------------
 | 
			
		||||
                rho2 = (X(0, i) - pos(0))*(X(0, i) - pos(0))  + (X(1, i) - pos(1))*(X(1, i) - pos(1))+ (X(2,i) - pos(2))*(X(2,i) - pos(2));
 | 
			
		||||
                traveltime = sqrt(rho2) / GPS_C_m_s;
 | 
			
		||||
                //--- Correct satellite position (do to earth rotation) --------
 | 
			
		||||
                Rot_X = e_r_corr(traveltime, X.get_col(i));
 | 
			
		||||
 | 
			
		||||
                //--- Find the elevation angel of the satellite ----------------
 | 
			
		||||
                //[az(i), el(i), dist] = topocent(pos(1:3, :), Rot_X - pos(1:3, :));
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //--- Apply the corrections ----------------------------------------
 | 
			
		||||
            omc(i) = (obs(i) - norm(Rot_X - pos.left(3)) - pos(4) - trop);
 | 
			
		||||
            //--- Construct the A matrix ---------------------------------------
 | 
			
		||||
            A.set(i, 0, (-(Rot_X(0) - pos(0))) / obs(i));
 | 
			
		||||
            A.set(i, 1, (-(Rot_X(1) - pos(1))) / obs(i));
 | 
			
		||||
            A.set(i, 2, (-(Rot_X(2) - pos(2))) / obs(i));
 | 
			
		||||
            A.set(i, 3, 1.0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // These lines allow the code to exit gracefully in case of any errors
 | 
			
		||||
        //if (rank(A) != 4) {
 | 
			
		||||
        //  pos.clear();
 | 
			
		||||
        //  return pos;
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //--- Find position update ---------------------------------------------
 | 
			
		||||
        x = ls_solve_od(w*A,w*omc);
 | 
			
		||||
 | 
			
		||||
        //--- Apply position update --------------------------------------------
 | 
			
		||||
        pos = pos + x;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    return pos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gps_l1_ca_ls_pvt::get_PVT(std::map<int,float> pseudoranges,double GPS_current_time)
 | 
			
		||||
{
 | 
			
		||||
    std::map<int,float>::iterator pseudoranges_iter;
 | 
			
		||||
    mat satpos;
 | 
			
		||||
    mat W=eye(d_nchannels); //channels weights matrix
 | 
			
		||||
    vec obs=zeros(d_nchannels); // pseudoranges observation vector
 | 
			
		||||
    satpos=zeros(3,d_nchannels); //satellite positions matrix
 | 
			
		||||
    int valid_obs=0; //valid observations counter
 | 
			
		||||
    for (int i=0; i<d_nchannels; i++)
 | 
			
		||||
    {
 | 
			
		||||
        if (d_ephemeris[i].satellite_validation()==true)
 | 
			
		||||
        {
 | 
			
		||||
            pseudoranges_iter=pseudoranges.find(d_ephemeris[i].d_satellite_PRN);
 | 
			
		||||
            if (pseudoranges_iter!=pseudoranges.end())
 | 
			
		||||
            {
 | 
			
		||||
                W(i,i)=1; // TODO: Place here the satellite CN0 (power level, or weight factor)
 | 
			
		||||
                // compute the GPS master clock
 | 
			
		||||
                d_ephemeris[i].master_clock(GPS_current_time);
 | 
			
		||||
                // compute the satellite current ECEF position
 | 
			
		||||
                d_ephemeris[i].satpos();
 | 
			
		||||
                // compute the clock error including relativistic effects
 | 
			
		||||
                d_ephemeris[i].relativistic_clock_correction(GPS_current_time);
 | 
			
		||||
                satpos(0,i)=d_ephemeris[i].d_satpos_X;
 | 
			
		||||
                satpos(1,i)=d_ephemeris[i].d_satpos_Y;
 | 
			
		||||
                satpos(2,i)=d_ephemeris[i].d_satpos_Z;
 | 
			
		||||
                obs(i)=pseudoranges_iter->second+d_ephemeris[i].d_satClkCorr*GPS_C_m_s;
 | 
			
		||||
                valid_obs++;
 | 
			
		||||
            }else{
 | 
			
		||||
                // no valid pseudorange for the current channel
 | 
			
		||||
                W(i,i)=0; // channel de-activated
 | 
			
		||||
                obs(i)=1; // to avoid algorithm problems (divide by zero)
 | 
			
		||||
            }
 | 
			
		||||
        }else{
 | 
			
		||||
            // no valid ephemeris for the current channel
 | 
			
		||||
            W(i,i)=0; // channel de-activated
 | 
			
		||||
            obs(i)=1; // to avoid algorithm problems (divide by zero)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    std::cout<<"PVT: valid observations="<<valid_obs<<std::endl;
 | 
			
		||||
    if (valid_obs>=4)
 | 
			
		||||
    {
 | 
			
		||||
        vec mypos;
 | 
			
		||||
        mypos=leastSquarePos(satpos,obs,W);
 | 
			
		||||
        std::cout << "Position ("<<GPS_current_time<<") ECEF = " << mypos << std::endl;
 | 
			
		||||
        cart2geo(mypos(0), mypos(1), mypos(2), 4);
 | 
			
		||||
        std::cout << "Position ("<<GPS_current_time<<") Lat = " << d_latitude_d << " Long ="<< d_longitude_d <<" Height="<<d_height_m<< std::endl;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
void gps_l1_ca_ls_pvt::cart2geo(double X, double Y, double Z, int elipsoid_selection)
 | 
			
		||||
{
 | 
			
		||||
    //function [phi, lambda, h] = cart2geo(X, Y, Z, i)
 | 
			
		||||
    //CART2GEO Conversion of Cartesian coordinates (X,Y,Z) to geographical
 | 
			
		||||
    //coordinates (phi, lambda, h) on a selected reference ellipsoid.
 | 
			
		||||
    //
 | 
			
		||||
    //[phi, lambda, h] = cart2geo(X, Y, Z, i);
 | 
			
		||||
    //
 | 
			
		||||
    //   Choices i of Reference Ellipsoid for Geographical Coordinates
 | 
			
		||||
    //             0. International Ellipsoid 1924
 | 
			
		||||
    //             1. International Ellipsoid 1967
 | 
			
		||||
    //             2. World Geodetic System 1972
 | 
			
		||||
    //             3. Geodetic Reference System 1980
 | 
			
		||||
    //             4. World Geodetic System 1984
 | 
			
		||||
 | 
			
		||||
    double a[5] = {6378388, 6378160, 6378135, 6378137, 6378137};
 | 
			
		||||
    double f[5] = {1/297, 1/298.247, 1/298.26, 1/298.257222101, 1/298.257223563};
 | 
			
		||||
 | 
			
		||||
    double lambda;
 | 
			
		||||
    lambda = atan2(Y,X);
 | 
			
		||||
    double ex2;
 | 
			
		||||
    ex2 = (2-f[elipsoid_selection])*f[elipsoid_selection]/((1-f[elipsoid_selection])*(1-f[elipsoid_selection]));
 | 
			
		||||
    double c;
 | 
			
		||||
    c = a[elipsoid_selection]*sqrt(1+ex2);
 | 
			
		||||
    double phi;
 | 
			
		||||
    phi = atan(Z/((sqrt(X*X+Y*Y)*(1-(2-f[elipsoid_selection]))*f[elipsoid_selection])));
 | 
			
		||||
 | 
			
		||||
    double h = 0.1;
 | 
			
		||||
    double oldh = 0;
 | 
			
		||||
    double N;
 | 
			
		||||
    int iterations = 0;
 | 
			
		||||
    do{
 | 
			
		||||
       oldh = h;
 | 
			
		||||
       N = c/sqrt(1+ex2*(cos(phi)*cos(phi)));
 | 
			
		||||
       phi = atan(Z/((sqrt(X*X+Y*Y)*(1-(2-f[elipsoid_selection])*f[elipsoid_selection]*N/(N+h)))));
 | 
			
		||||
       h = sqrt(X*X+Y*Y)/cos(phi)-N;
 | 
			
		||||
       iterations = iterations + 1;
 | 
			
		||||
       if (iterations > 100)
 | 
			
		||||
       {
 | 
			
		||||
           std::cout<<"Failed to approximate h with desired precision. h-oldh= "<<h-oldh<<std::endl;
 | 
			
		||||
           break;
 | 
			
		||||
       }
 | 
			
		||||
    }while (abs(h-oldh) > 1.0e-12);
 | 
			
		||||
    d_latitude_d = phi*180.0/GPS_PI;
 | 
			
		||||
    d_longitude_d = lambda*180/pi;
 | 
			
		||||
    d_height_m = h;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//void gps_l1_ca_ls_pvt::topocent(traveltime, X_sat)
 | 
			
		||||
//{
 | 
			
		||||
    /*
 | 
			
		||||
%function [Az, El, D] = topocent(X, dx)
 | 
			
		||||
%TOPOCENT  Transformation of vector dx into topocentric coordinate
 | 
			
		||||
%          system with origin at X.
 | 
			
		||||
%          Both parameters are 3 by 1 vectors.
 | 
			
		||||
%
 | 
			
		||||
%[Az, El, D] = topocent(X, dx);
 | 
			
		||||
%
 | 
			
		||||
%   Inputs:
 | 
			
		||||
%       X           - vector origin corrdinates (in ECEF system [X; Y; Z;])
 | 
			
		||||
%       dx          - vector ([dX; dY; dZ;]).
 | 
			
		||||
%
 | 
			
		||||
%   Outputs:
 | 
			
		||||
%       D           - vector length. Units like units of the input
 | 
			
		||||
%       Az          - azimuth from north positive clockwise, degrees
 | 
			
		||||
%       El          - elevation angle, degrees
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
dtr = pi/180;
 | 
			
		||||
 | 
			
		||||
[phi, lambda, h] = togeod(6378137, 298.257223563, X(1), X(2), X(3));
 | 
			
		||||
 | 
			
		||||
cl  = cos(lambda * dtr);
 | 
			
		||||
sl  = sin(lambda * dtr);
 | 
			
		||||
cb  = cos(phi * dtr);
 | 
			
		||||
sb  = sin(phi * dtr);
 | 
			
		||||
 | 
			
		||||
F   = [-sl -sb*cl cb*cl;
 | 
			
		||||
        cl -sb*sl cb*sl;
 | 
			
		||||
        0    cb   sb];
 | 
			
		||||
 | 
			
		||||
local_vector = F' * dx;
 | 
			
		||||
E   = local_vector(1);
 | 
			
		||||
N   = local_vector(2);
 | 
			
		||||
U   = local_vector(3);
 | 
			
		||||
 | 
			
		||||
hor_dis = sqrt(E^2 + N^2);
 | 
			
		||||
 | 
			
		||||
if hor_dis < 1.e-20
 | 
			
		||||
    Az = 0;
 | 
			
		||||
    El = 90;
 | 
			
		||||
else
 | 
			
		||||
    Az = atan2(E, N)/dtr;
 | 
			
		||||
    El = atan2(U, hor_dis)/dtr;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
if Az < 0
 | 
			
		||||
    Az = Az + 360;
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
D   = sqrt(dx(1)^2 + dx(2)^2 + dx(3)^2);
 | 
			
		||||
%%%%%%%%% end topocent.m %%%%%%%%%
 | 
			
		||||
*/
 | 
			
		||||
//}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/algorithms/observables/libs/gps_l1_ca_ls_pvt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/algorithms/observables/libs/gps_l1_ca_ls_pvt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright notice
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Author: Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 *         Luis Esteve, 2011. luis(at)epsilon-formacion.com
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GPS_L1_CA_LS_PVT_H_
 | 
			
		||||
#define GPS_L1_CA_LS_PVT_H_
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include "gps_navigation_message.h"
 | 
			
		||||
#include "GPS_L1_CA.h"
 | 
			
		||||
 | 
			
		||||
#include <itpp/itbase.h>
 | 
			
		||||
#include <itpp/stat/misc_stat.h>
 | 
			
		||||
#include <itpp/base/matfunc.h>
 | 
			
		||||
 | 
			
		||||
using namespace itpp;
 | 
			
		||||
 | 
			
		||||
class gps_l1_ca_ls_pvt
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    vec leastSquarePos(mat satpos, vec obs, mat w);
 | 
			
		||||
    vec e_r_corr(double traveltime, vec X_sat);
 | 
			
		||||
    //void cart2geo();
 | 
			
		||||
    //void topocent();
 | 
			
		||||
public:
 | 
			
		||||
    int d_nchannels;
 | 
			
		||||
    gps_navigation_message* d_ephemeris;
 | 
			
		||||
    double d_pseudoranges_time_ms;
 | 
			
		||||
    double d_latitude_d;
 | 
			
		||||
    double d_longitude_d;
 | 
			
		||||
    double d_height_m;
 | 
			
		||||
    double d_x_m;
 | 
			
		||||
    double d_y_m;
 | 
			
		||||
    double d_z_m;
 | 
			
		||||
 | 
			
		||||
    gps_l1_ca_ls_pvt(int nchannels);
 | 
			
		||||
    ~gps_l1_ca_ls_pvt();
 | 
			
		||||
 | 
			
		||||
    void get_PVT(std::map<int,float> pseudoranges,double GPS_current_time);
 | 
			
		||||
    void cart2geo(double X, double Y, double Z, int elipsoid_selection);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
project : build-dir ../../../../build ;
 | 
			
		||||
 | 
			
		||||
obj rinex_2_1_printer : rinex_2_1_printer.cc ;
 | 
			
		||||
obj gps_l1_ca_ls_pvt : gps_l1_ca_ls_pvt.cc ;
 | 
			
		||||
@@ -192,7 +192,7 @@ void rinex_printer::Rinex2ObsHeader()
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double interframe_seconds, std::map<int,float> pseudoranges)
 | 
			
		||||
void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double pseudoranges_clock, std::map<int,float> pseudoranges)
 | 
			
		||||
{
 | 
			
		||||
	int ss;
 | 
			
		||||
	char sat_vis[36];
 | 
			
		||||
@@ -224,7 +224,7 @@ void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double interfram
 | 
			
		||||
		double decimalday,daydecimalhour,decimalhour,decimalmin,decimalsec;
 | 
			
		||||
		double day,hour,minutes,seconds,enterseconds,a;
 | 
			
		||||
		double gpstime;
 | 
			
		||||
		gpstime=nav_msg.d_master_clock;
 | 
			
		||||
		gpstime=pseudoranges_clock; //[s]
 | 
			
		||||
		//calculate date of gps time:
 | 
			
		||||
		//Days & weeks between 00h 1 Jan 1970 and 00h 6 Jan 1980
 | 
			
		||||
		//520 weeks and 12 days.
 | 
			
		||||
@@ -233,7 +233,7 @@ void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double interfram
 | 
			
		||||
		tmPtr = gmtime(&temps);
 | 
			
		||||
		strftime( cad1, 20, " %y %m %d", tmPtr );
 | 
			
		||||
		strftime( cad2, 20, "  %Y    %m    %d", tmPtr );
 | 
			
		||||
		decimalday=((gpstime+interframe_seconds)/(24*3600));//Dies dins de la semana
 | 
			
		||||
		decimalday=(gpstime/(24*3600));//Dies dins de la semana
 | 
			
		||||
		daydecimalhour=modf(decimalday,&day);//day=#dies sencers, daydecimalhour=porcio de dia
 | 
			
		||||
		daydecimalhour=daydecimalhour*24;//porcio de dia en hores
 | 
			
		||||
		decimalhour=modf(daydecimalhour,&hour);//hour=hora del dia; decimalhour=porcio d'hora
 | 
			
		||||
 
 | 
			
		||||
@@ -45,13 +45,6 @@
 | 
			
		||||
#include <glog/log_severity.h>
 | 
			
		||||
#include <glog/logging.h>
 | 
			
		||||
 | 
			
		||||
/* The extern keyword declares a variable or function and specifies
 | 
			
		||||
 * that it has external linkage (its name is visible from files other
 | 
			
		||||
 * than the one in which it's defined). When modifying a variable,
 | 
			
		||||
 * extern specifies that the variable has static duration (it is allocated
 | 
			
		||||
 * when the program begins and deallocated when the program ends).
 | 
			
		||||
 * The variable is defined in main.cc
 | 
			
		||||
 */
 | 
			
		||||
extern concurrent_queue<gps_navigation_message> global_gps_nav_msg_queue;
 | 
			
		||||
 | 
			
		||||
using google::LogMessage;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ void gps_l1_ca_telemetry_decoder_cc::forecast (int noutput_items,
 | 
			
		||||
 | 
			
		||||
gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(unsigned int satellite, long if_freq, long fs_in, unsigned
 | 
			
		||||
    int vector_length, gr_msg_queue_sptr queue, bool dump) :
 | 
			
		||||
    gr_block ("gps_navigation_cc", gr_make_io_signature (3, 3, sizeof(float)),
 | 
			
		||||
    gr_block ("gps_navigation_cc", gr_make_io_signature (5, 5, sizeof(float)),
 | 
			
		||||
        gr_make_io_signature(1, 1, sizeof(gnss_synchro))) {
 | 
			
		||||
  // initialize internal vars
 | 
			
		||||
  d_queue = queue;
 | 
			
		||||
@@ -106,10 +106,6 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
  d_sample_counter++; //count for the processed samples
 | 
			
		||||
 | 
			
		||||
  const float **in = (const float **)  &input_items[0]; //Get the input samples pointer
 | 
			
		||||
  //std::cout<<"CH1="<<in[0][0]; // Q
 | 
			
		||||
  //std::cout<<"CH2="<<in[1][0]; // I
 | 
			
		||||
  //std::cout<<"CH3="<<in[2][0]; // Delay
 | 
			
		||||
  //std::cout<<"N_input_streams="<<ninput_items.size();
 | 
			
		||||
 | 
			
		||||
  // TODO Optimize me!
 | 
			
		||||
  //******* preamble correlation ********
 | 
			
		||||
@@ -123,13 +119,13 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //******* frame sync ******************
 | 
			
		||||
  if (abs(corr_value)>=153){
 | 
			
		||||
  if (abs(corr_value)>=160){
 | 
			
		||||
    //TODO: Rewrite with state machine
 | 
			
		||||
    if (d_stat==0)
 | 
			
		||||
      {
 | 
			
		||||
      d_GPS_FSM.Event_gps_word_preamble();
 | 
			
		||||
      d_preamble_index=d_sample_counter;//record the preamble sample stamp
 | 
			
		||||
      std::cout<<"Pre-detection"<<std::endl;
 | 
			
		||||
      std::cout<<"Pre-detection SAT "<<this->d_satellite+1<<std::endl;
 | 
			
		||||
      d_symbol_accumulator=0; //sync the symbol to bits integrator
 | 
			
		||||
      d_symbol_accumulator_counter=0;
 | 
			
		||||
      d_frame_bit_index=8;
 | 
			
		||||
@@ -140,15 +136,17 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
        if (abs(preamble_diff-6000)<1)
 | 
			
		||||
          {
 | 
			
		||||
          d_GPS_FSM.Event_gps_word_preamble();
 | 
			
		||||
          d_preamble_index=d_sample_counter;//record the preamble sample stamp
 | 
			
		||||
          d_preamble_index=d_sample_counter;//record the preamble sample stamp (t_P)
 | 
			
		||||
          d_preamble_phase=in[2][0]; //record the PRN start sample index associated to the preamble
 | 
			
		||||
 | 
			
		||||
          if (!d_flag_frame_sync){
 | 
			
		||||
            d_flag_frame_sync=true;
 | 
			
		||||
            std::cout<<" Frame sync with phase "<<in[2][0]<<std::endl;
 | 
			
		||||
            std::cout<<" Frame sync SAT "<<this->d_satellite+1<<" with preamble start at "<<in[2][0]<<" [ms]"<<std::endl;
 | 
			
		||||
          }
 | 
			
		||||
          }else
 | 
			
		||||
            {
 | 
			
		||||
            if (preamble_diff>7000){
 | 
			
		||||
              std::cout<<"lost of frame sync"<<std::endl;
 | 
			
		||||
              std::cout<<"lost of frame sync SAT "<<this->d_satellite+1<<std::endl;
 | 
			
		||||
              d_stat=0; //lost of frame sync
 | 
			
		||||
              d_flag_frame_sync=false;
 | 
			
		||||
            }
 | 
			
		||||
@@ -156,6 +154,8 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
        }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //******* code error accumulator *****
 | 
			
		||||
  //d_preamble_phase-=in[3][0];
 | 
			
		||||
  //******* SYMBOL TO BIT *******
 | 
			
		||||
 | 
			
		||||
  d_symbol_accumulator+=in[1][d_samples_per_bit*8-1]; // accumulate the input value in d_symbol_accumulator
 | 
			
		||||
@@ -194,6 +194,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
        }
 | 
			
		||||
      if (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_phase;
 | 
			
		||||
        d_GPS_FSM.Event_gps_word_valid();
 | 
			
		||||
        d_flag_parity=true;
 | 
			
		||||
      }else{
 | 
			
		||||
@@ -213,8 +214,9 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
 | 
			
		||||
  if ((d_sample_counter%NAVIGATION_OUTPUT_RATE_MS)==0)
 | 
			
		||||
    {
 | 
			
		||||
    gps_synchro.valid_word=(d_flag_frame_sync==true and d_flag_parity==true);
 | 
			
		||||
    gps_synchro.last_preamble_index=d_preamble_index;
 | 
			
		||||
    gps_synchro.prn_delay=in[2][0];
 | 
			
		||||
    //gps_synchro.preamble_delay_ms=(float)d_preamble_index;
 | 
			
		||||
    gps_synchro.preamble_delay_ms=(float)d_preamble_index;
 | 
			
		||||
    gps_synchro.prn_delay_ms=in[3][0];
 | 
			
		||||
    gps_synchro.satellite_PRN=d_satellite+1;
 | 
			
		||||
    gps_synchro.channel_ID=d_channel;
 | 
			
		||||
    *out[0]=gps_synchro;
 | 
			
		||||
 
 | 
			
		||||
@@ -76,6 +76,8 @@ private:
 | 
			
		||||
  int d_satellite;
 | 
			
		||||
  int d_channel;
 | 
			
		||||
 | 
			
		||||
  float d_preamble_phase;
 | 
			
		||||
 | 
			
		||||
  std::string d_dump_filename;
 | 
			
		||||
  std::ofstream d_dump_file;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ public:
 | 
			
		||||
  // sc::transition(evento,estado_destino)
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S0 "<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
struct gps_subframe_fsm_S1: public sc::state<gps_subframe_fsm_S1, GpsL1CaSubframeFsm > {
 | 
			
		||||
@@ -21,7 +21,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S1 "<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -31,7 +31,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S2 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(0);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -41,7 +41,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S3 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(1);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -51,7 +51,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S4 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(2);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -61,7 +61,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S5 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(3);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -71,7 +71,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S6 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(4);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -81,7 +81,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S7 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(5);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -91,7 +91,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S8 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(6);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -101,7 +101,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S9 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(7);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -111,7 +111,7 @@ public:
 | 
			
		||||
  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;
 | 
			
		||||
    //std::cout<<"Enter S10 "<<std::endl;
 | 
			
		||||
    context< GpsL1CaSubframeFsm >().gps_word_to_subframe(8);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -120,11 +120,11 @@ 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;
 | 
			
		||||
    //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;
 | 
			
		||||
    //std::cout<<"Enter S11"<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -149,17 +149,14 @@ void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
 | 
			
		||||
 | 
			
		||||
  d_nav.d_satellite_PRN=d_satellite_PRN+1;
 | 
			
		||||
  d_nav.d_channel_ID=d_channel_ID;
 | 
			
		||||
 | 
			
		||||
  if (subframe_ID==1) {
 | 
			
		||||
    d_nav.d_subframe1_timestamp_ms=this->d_preamble_time_ms-6002;
 | 
			
		||||
    std::cout<<"FSM: set subframe1 preamble timestamp for sat "<<d_nav.d_satellite_PRN<<std::endl;
 | 
			
		||||
  }
 | 
			
		||||
  //TODO: change to subframe 5
 | 
			
		||||
  if (subframe_ID==3) { // if the subframe is the 5th, then
 | 
			
		||||
    if (d_nav.satellite_validation()) // if all the satellite ephemeris parameters are good, then
 | 
			
		||||
      {
 | 
			
		||||
        // compute the GPS master clock
 | 
			
		||||
        d_nav.master_clock();
 | 
			
		||||
        // compute the satellite current ECEF position
 | 
			
		||||
        d_nav.satpos();
 | 
			
		||||
        // compute the clock error including relativistic effects
 | 
			
		||||
        d_nav.relativistic_clock_correction();
 | 
			
		||||
        // Send the procesed satellite ephemeris packet
 | 
			
		||||
        d_nav_queue->push(d_nav);
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,8 @@ public:
 | 
			
		||||
  char d_subframe[GPS_SUBFRAME_LENGTH];
 | 
			
		||||
  char d_GPS_frame_4bytes[GPS_WORD_LENGTH];
 | 
			
		||||
 | 
			
		||||
  double d_preamble_time_ms;
 | 
			
		||||
 | 
			
		||||
  void gps_word_to_subframe(int position);
 | 
			
		||||
  void gps_subframe_to_nav_msg();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,96 +126,44 @@ 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_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::update_local_code_refs()
 | 
			
		||||
{
 | 
			
		||||
	float tcode;
 | 
			
		||||
	float max_tcode;
 | 
			
		||||
	unsigned int i=0;
 | 
			
		||||
	int tmp_index;
 | 
			
		||||
	float block_correction;
 | 
			
		||||
 | 
			
		||||
//	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;
 | 
			
		||||
 | 
			
		||||
	// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gps_l1_ca_dll_pll_tracking_cc::update_local_carrier()
 | 
			
		||||
{
 | 
			
		||||
		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);
 | 
			
		||||
}
 | 
			
		||||
gps_l1_ca_dll_pll_tracking_cc::~gps_l1_ca_dll_pll_tracking_cc() {
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
@@ -221,60 +181,139 @@ void gps_l1_ca_dll_pll_tracking_cc::start_tracking(){
 | 
			
		||||
    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_chips=(float)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);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	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 ";
 | 
			
		||||
 | 
			
		||||
    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 << std::endl;
 | 
			
		||||
    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;
 | 
			
		||||
	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];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //**** 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;
 | 
			
		||||
 | 
			
		||||
    //**** 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;
 | 
			
		||||
 | 
			
		||||
        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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*! 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,6 +471,7 @@ 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);
 | 
			
		||||
 | 
			
		||||
	      	try {
 | 
			
		||||
				// EPR
 | 
			
		||||
				d_dump_file.write((char*)&tmp_E, sizeof(float));
 | 
			
		||||
				d_dump_file.write((char*)&tmp_P, sizeof(float));
 | 
			
		||||
@@ -369,13 +482,24 @@ int gps_l1_ca_dll_pll_tracking_cc::work (int noutput_items,gr_vector_const_void_
 | 
			
		||||
				//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!
 | 
			
		||||
 | 
			
		||||
			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" << std::endl;
 | 
			
		||||
					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);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// SEPARATE FILE GPS.H
 | 
			
		||||
const float GPS_C_m_s= 299792458;    // The speed of light, [m/ms]
 | 
			
		||||
const float GPS_C_m_s= 299792458.0;    // The speed of light, [m/ms]
 | 
			
		||||
const float GPS_STARTOFFSET_ms= 68.802; //[ms] Initial sign. travel time
 | 
			
		||||
const float GPS_PI = 3.1415926535898; // Pi used in the GPS coordinate system
 | 
			
		||||
//-- Constants for satellite position calculation -------------------------
 | 
			
		||||
@@ -60,8 +60,7 @@ const double  F              = -4.442807633e-10; // Constant, [sec/(meter)^(1/2)
 | 
			
		||||
 | 
			
		||||
/*! @ingroup GPS_DEFINES
 | 
			
		||||
 *  @brief Navigation message bits slice structure: A portion of bits is indicated by
 | 
			
		||||
 *  the start position inside the subframe and the length in number of bits
 | 
			
		||||
 */
 | 
			
		||||
 *  the start position inside the subframe and the length in number of bits  */
 | 
			
		||||
typedef struct bits_slice{
 | 
			
		||||
        int position;
 | 
			
		||||
        int length;
 | 
			
		||||
@@ -74,12 +73,12 @@ typedef struct bits_slice{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*! @ingroup GPS_DEFINES
 | 
			
		||||
 *  @brief Demodulator gnss_synchro structure, used to feed the pseudorange block
 | 
			
		||||
 */
 | 
			
		||||
 *  @brief Demodulator gnss_synchro structure, used to feed the pseudorange block */
 | 
			
		||||
 | 
			
		||||
typedef struct gnss_synchro
 | 
			
		||||
{
 | 
			
		||||
  unsigned long int last_preamble_index;
 | 
			
		||||
  float prn_delay;
 | 
			
		||||
  float preamble_delay_ms;
 | 
			
		||||
  float prn_delay_ms;
 | 
			
		||||
  int satellite_PRN;
 | 
			
		||||
  int channel_ID;
 | 
			
		||||
  bool valid_word;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file gps_navigation_message.cc
 | 
			
		||||
 * \brief  Implementation of GPS L1 C/A navigation message decoding
 | 
			
		||||
 * \brief  Navigation message structure for GPS L1 C/A signal
 | 
			
		||||
 * \author Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
@@ -30,7 +30,6 @@
 | 
			
		||||
 | 
			
		||||
#include "gps_navigation_message.h"
 | 
			
		||||
 | 
			
		||||
//! Sets all the ephemeris parameters to zero
 | 
			
		||||
void gps_navigation_message::reset()
 | 
			
		||||
{
 | 
			
		||||
  d_TOW=0;
 | 
			
		||||
@@ -65,9 +64,9 @@ void gps_navigation_message::reset()
 | 
			
		||||
  d_SV_accuracy=0;
 | 
			
		||||
  d_SV_health=0;
 | 
			
		||||
  d_TGD=0;
 | 
			
		||||
  d_IODC=0;
 | 
			
		||||
  d_IODC=-1;
 | 
			
		||||
  //broadcast orbit 7
 | 
			
		||||
  d_transmission_time=0;
 | 
			
		||||
 | 
			
		||||
  d_fit_interval=0;
 | 
			
		||||
  d_spare1=0;
 | 
			
		||||
  d_spare2=0;
 | 
			
		||||
@@ -89,15 +88,17 @@ void gps_navigation_message::reset()
 | 
			
		||||
  // info
 | 
			
		||||
  d_channel_ID=0;
 | 
			
		||||
  d_satellite_PRN=0;
 | 
			
		||||
 | 
			
		||||
  // time synchro
 | 
			
		||||
  d_subframe1_timestamp_ms=0;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Default constructor
 | 
			
		||||
gps_navigation_message::gps_navigation_message()
 | 
			
		||||
{
 | 
			
		||||
  reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Read unsigned values
 | 
			
		||||
}
 | 
			
		||||
unsigned long int gps_navigation_message::read_navigation_unsigned(std::bitset<GPS_SUBFRAME_BITS> bits, const bits_slice *slices, int num_of_slices)
 | 
			
		||||
{
 | 
			
		||||
  unsigned long int value;
 | 
			
		||||
@@ -117,7 +118,6 @@ unsigned long int gps_navigation_message::read_navigation_unsigned(std::bitset<G
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Read signed values
 | 
			
		||||
signed long int gps_navigation_message::read_navigation_signed(std::bitset<GPS_SUBFRAME_BITS> bits, const bits_slice *slices, int num_of_slices)
 | 
			
		||||
{
 | 
			
		||||
  signed long int value=0;
 | 
			
		||||
@@ -145,13 +145,7 @@ signed long int gps_navigation_message::read_navigation_signed(std::bitset<GPS_S
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief Accounts for beginning or end of week crossover
 | 
			
		||||
 *
 | 
			
		||||
 * Inspired in a Matlab function by Kai Borre
 | 
			
		||||
 * \param[in] time (in seconds)
 | 
			
		||||
 * \result Returns corrected time
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
double gps_navigation_message::check_t(double time)
 | 
			
		||||
{
 | 
			
		||||
  /*
 | 
			
		||||
@@ -163,6 +157,13 @@ corrTime = check_t(time);
 | 
			
		||||
 | 
			
		||||
   Outputs:
 | 
			
		||||
       corrTime    - corrected time (seconds)
 | 
			
		||||
 | 
			
		||||
Kai Borre 04-01-96
 | 
			
		||||
Copyright (c) by Kai Borre
 | 
			
		||||
 | 
			
		||||
 CVS record:
 | 
			
		||||
 $Id: check_t.m,v 1.1.1.1.2.4 2006/08/22 13:45:59 dpl Exp $
 | 
			
		||||
==========================================================================
 | 
			
		||||
   */
 | 
			
		||||
  double corrTime;
 | 
			
		||||
  double half_week = 302400;     // seconds
 | 
			
		||||
@@ -177,23 +178,21 @@ corrTime = check_t(time);
 | 
			
		||||
  return corrTime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gps_navigation_message::master_clock()
 | 
			
		||||
void gps_navigation_message::master_clock(double transmitTime)
 | 
			
		||||
{
 | 
			
		||||
  double dt;
 | 
			
		||||
  double satClkCorr;
 | 
			
		||||
  // Find initial satellite clock correction --------------------------------
 | 
			
		||||
 | 
			
		||||
  // --- Find time difference ---------------------------------------------
 | 
			
		||||
  dt = check_t(d_TOW - d_Toc);
 | 
			
		||||
  dt = check_t(transmitTime - d_Toc);
 | 
			
		||||
 | 
			
		||||
  //--- Calculate clock correction ---------------------------------------
 | 
			
		||||
  satClkCorr = (d_A_f2 * dt + d_A_f1) * dt +  d_A_f0 - d_TGD;
 | 
			
		||||
 | 
			
		||||
  d_master_clock = d_TOW - satClkCorr;
 | 
			
		||||
  d_master_clock = transmitTime - satClkCorr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//! Computes satellite position from ephemeris data
 | 
			
		||||
void gps_navigation_message::satpos()
 | 
			
		||||
{
 | 
			
		||||
  double tk;
 | 
			
		||||
@@ -239,7 +238,7 @@ void gps_navigation_message::satpos()
 | 
			
		||||
    E_old   = E;
 | 
			
		||||
    E       = M + d_e_eccentricity * sin(E);
 | 
			
		||||
    dE      = fmod(E - E_old,2*GPS_PI);
 | 
			
		||||
    std::cout<<"dE="<<dE<<std::endl;
 | 
			
		||||
    //std::cout<<"dE="<<dE<<std::endl;
 | 
			
		||||
    if (abs(dE) < 1E-12)
 | 
			
		||||
      {
 | 
			
		||||
      //Necessary precision is reached, exit from the loop
 | 
			
		||||
@@ -289,19 +288,17 @@ void gps_navigation_message::satpos()
 | 
			
		||||
  d_satpos_Z = sin(u)*r * sin(i);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void gps_navigation_message::relativistic_clock_correction()
 | 
			
		||||
void gps_navigation_message::relativistic_clock_correction(double transmitTime)
 | 
			
		||||
{
 | 
			
		||||
  double dt;
 | 
			
		||||
  // Find initial satellite clock correction --------------------------------
 | 
			
		||||
  // Find final satellite clock correction --------------------------------
 | 
			
		||||
 | 
			
		||||
  // --- Find time difference ---------------------------------------------
 | 
			
		||||
  dt = check_t(d_TOW - d_Toc);
 | 
			
		||||
  dt = check_t(transmitTime - d_Toc);
 | 
			
		||||
 | 
			
		||||
  //Include relativistic correction in clock correction --------------------
 | 
			
		||||
  d_satClkCorr = (d_A_f2 * dt + d_A_f1) * dt + d_A_f0 -d_TGD + d_dtr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//! Subframe decoder
 | 
			
		||||
int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
{
 | 
			
		||||
  int subframe_ID=0;
 | 
			
		||||
@@ -333,7 +330,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    }
 | 
			
		||||
   */
 | 
			
		||||
  subframe_ID=(int)read_navigation_unsigned(subframe_bits,SUBFRAME_ID,num_of_slices(SUBFRAME_ID));
 | 
			
		||||
  std::cout<<"subframe ID="<<subframe_ID<<std::endl;
 | 
			
		||||
  //std::cout<<"subframe ID="<<subframe_ID<<std::endl;
 | 
			
		||||
 | 
			
		||||
  // Decode all 5 sub-frames
 | 
			
		||||
  switch (subframe_ID){
 | 
			
		||||
@@ -371,6 +368,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    d_A_f2=d_A_f2*A_F2_LSB;
 | 
			
		||||
 | 
			
		||||
    /* debug print */
 | 
			
		||||
    /*
 | 
			
		||||
    std::cout<<"d_TOW="<<d_TOW<<std::endl;
 | 
			
		||||
    std::cout<<"GPS week="<<d_GPS_week<<std::endl;
 | 
			
		||||
    std::cout<<"SV_accuracy="<<d_SV_accuracy<<std::endl;
 | 
			
		||||
@@ -381,7 +379,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    std::cout<<"A_F0="<<d_A_f0<<std::endl;
 | 
			
		||||
    std::cout<<"A_F1="<<d_A_f1<<std::endl;
 | 
			
		||||
    std::cout<<"A_F2="<<d_A_f2<<std::endl;
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
    /*
 | 
			
		||||
        eph.weekNumber  = bin2dec(subframe(61:70)) + 1024;
 | 
			
		||||
        eph.accuracy    = bin2dec(subframe(73:76));
 | 
			
		||||
@@ -396,13 +394,10 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    break;
 | 
			
		||||
 | 
			
		||||
  case 2:
 | 
			
		||||
 | 
			
		||||
    tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    tmp_TOW=tmp_TOW*6-6; //we are in the first subframe (need no correction) !
 | 
			
		||||
    std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    //tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    //std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    // --- It is subframe 2 -------------------------------------
 | 
			
		||||
    // It contains first part of ephemeris parameters
 | 
			
		||||
 | 
			
		||||
    d_IODE_SF2=(double)read_navigation_unsigned(subframe_bits,IODE_SF2,num_of_slices(IODE_SF2));
 | 
			
		||||
    d_Crs=(double)read_navigation_signed(subframe_bits,C_RS,num_of_slices(C_RS));
 | 
			
		||||
    d_Crs=d_Crs*C_RS_LSB;
 | 
			
		||||
@@ -422,6 +417,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    d_Toe=d_Toe*T_OE_LSB;
 | 
			
		||||
 | 
			
		||||
    /* debug print */
 | 
			
		||||
    /*
 | 
			
		||||
    std::cout<<"d_IODE_SF2="<<d_IODE_SF2<<std::endl;
 | 
			
		||||
    std::cout<<"d_Crs="<<d_Crs<<std::endl;
 | 
			
		||||
    std::cout<<"d_Delta_n="<<d_Delta_n<<std::endl;
 | 
			
		||||
@@ -431,7 +427,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    std::cout<<"d_Cus="<<d_Cus<<std::endl;
 | 
			
		||||
    std::cout<<"d_sqrt_A="<<d_sqrt_A<<std::endl;
 | 
			
		||||
    std::cout<<"d_Toe="<<d_Toe<<std::endl;
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
    break;
 | 
			
		||||
    /*
 | 
			
		||||
        eph.IODE_sf2    = bin2dec(subframe(61:68));
 | 
			
		||||
@@ -445,9 +441,8 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
        eph.t_oe        = bin2dec(subframe(271:286)) * 2^4;
 | 
			
		||||
     */
 | 
			
		||||
  case 3:
 | 
			
		||||
    tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    tmp_TOW=tmp_TOW*6-6; //we are in the first subframe (need no correction) !
 | 
			
		||||
    std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    //tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    //std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    // --- It is subframe 3 -------------------------------------
 | 
			
		||||
    // It contains second part of ephemeris parameters
 | 
			
		||||
    d_Cic=(double)read_navigation_signed(subframe_bits,C_IC,num_of_slices(C_IC));
 | 
			
		||||
@@ -469,6 +464,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    d_IDOT=d_IDOT*I_DOT_LSB;
 | 
			
		||||
 | 
			
		||||
    /* debug print */
 | 
			
		||||
    /*
 | 
			
		||||
    std::cout<<"d_Cic="<<d_Cic<<std::endl;
 | 
			
		||||
    std::cout<<"d_OMEGA0="<<d_OMEGA0<<std::endl;
 | 
			
		||||
    std::cout<<"d_Cis="<<d_Cis<<std::endl;
 | 
			
		||||
@@ -478,6 +474,7 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    std::cout<<"d_OMEGA_DOT="<<d_OMEGA_DOT<<std::endl;
 | 
			
		||||
    std::cout<<"d_IODE_SF3="<<d_IODE_SF3<<std::endl;
 | 
			
		||||
    std::cout<<"d_IDOT="<<d_IDOT<<std::endl;
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    break;
 | 
			
		||||
    /*
 | 
			
		||||
@@ -492,9 +489,8 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
        eph.iDot        = twosComp2dec(subframe(279:292)) * 2^(-43) * gpsPi;
 | 
			
		||||
     */
 | 
			
		||||
  case 4:
 | 
			
		||||
    tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    tmp_TOW=tmp_TOW*6-6; //we are in the first subframe (need no correction) !
 | 
			
		||||
    std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    //tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    //std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    // --- It is subframe 4 -------------------------------------
 | 
			
		||||
    // Almanac, ionospheric model, UTC parameters.
 | 
			
		||||
    // SV health (PRN: 25-32)
 | 
			
		||||
@@ -502,14 +498,14 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    SV_page=(int)read_navigation_unsigned(subframe_bits,SV_PAGE,num_of_slices(SV_PAGE));
 | 
			
		||||
 | 
			
		||||
    /* debug print */
 | 
			
		||||
    /*
 | 
			
		||||
    std::cout<<"SF4 SV_data_ID="<<SV_data_ID<<std::endl;
 | 
			
		||||
    std::cout<<"SF4 SV_page="<<SV_page<<std::endl;
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
    break;
 | 
			
		||||
  case 5:
 | 
			
		||||
    tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    tmp_TOW=tmp_TOW*6-6; //we are in the first subframe (need no correction) !
 | 
			
		||||
    std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    //tmp_TOW=(double)read_navigation_unsigned(subframe_bits,TOW,num_of_slices(TOW));
 | 
			
		||||
    //std::cout<<"tmp_TOW="<<tmp_TOW<<std::endl;
 | 
			
		||||
    //--- It is subframe 5 -------------------------------------
 | 
			
		||||
    // SV almanac and health (PRN: 1-24).
 | 
			
		||||
    // Almanac reference week number and time.
 | 
			
		||||
@@ -517,8 +513,10 @@ int gps_navigation_message::subframe_decoder(char *subframe)
 | 
			
		||||
    SV_page=(int)read_navigation_unsigned(subframe_bits,SV_PAGE,num_of_slices(SV_PAGE));
 | 
			
		||||
 | 
			
		||||
    /* debug print */
 | 
			
		||||
    /*
 | 
			
		||||
    std::cout<<"SF5 SV_data_ID="<<SV_data_ID<<std::endl;
 | 
			
		||||
    std::cout<<"SF5 SV_page="<<SV_page<<std::endl;
 | 
			
		||||
    */
 | 
			
		||||
    break;
 | 
			
		||||
  default:
 | 
			
		||||
    break;
 | 
			
		||||
@@ -534,7 +532,7 @@ bool gps_navigation_message::satellite_validation()
 | 
			
		||||
 | 
			
		||||
  // first step: check Issue Of Ephemeris Data (IODE IODC..) to find a possible interrupted reception
 | 
			
		||||
  //             and check if the data has been filled (!=0)
 | 
			
		||||
  if (d_IODE_SF2 == d_IODE_SF3 and d_IODC == d_IODE_SF2 and d_IODC!=0)
 | 
			
		||||
  if (d_IODE_SF2 == d_IODE_SF3 and d_IODC == d_IODE_SF2 and d_IODC!=-1)
 | 
			
		||||
    {
 | 
			
		||||
    flag_data_valid=true;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file gps_navigation_message.h
 | 
			
		||||
 * \brief  This class implements GPS L1 C/A navigation message decoding
 | 
			
		||||
 * \brief  Navigation message structure for GPS L1 C/A signal
 | 
			
		||||
 * \author Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
@@ -28,6 +28,7 @@
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef GPS_NAVIGATION_MESSAGE_H
 | 
			
		||||
#define GPS_NAVIGATION_MESSAGE_H
 | 
			
		||||
 | 
			
		||||
@@ -44,13 +45,6 @@ using namespace boost::assign;
 | 
			
		||||
 | 
			
		||||
#include "GPS_L1_CA.h"
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
 * \brief  This class implements GPS L1 C/A navigation message decoding
 | 
			
		||||
 * and computes satellite position
 | 
			
		||||
 *
 | 
			
		||||
 * It defines the specific GPS navigation (NAV) data structure,
 | 
			
		||||
 * as defined in the document Interface Specification IS-GPS-200 Revision E, Appendix II
 | 
			
		||||
 */
 | 
			
		||||
class gps_navigation_message
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +87,7 @@ public:
 | 
			
		||||
    double d_TGD;
 | 
			
		||||
    double d_IODC;
 | 
			
		||||
    //broadcast orbit 7
 | 
			
		||||
    double d_transmission_time;
 | 
			
		||||
 | 
			
		||||
    double d_fit_interval;
 | 
			
		||||
    double d_spare1;
 | 
			
		||||
    double d_spare2;
 | 
			
		||||
@@ -118,12 +112,15 @@ public:
 | 
			
		||||
    int d_channel_ID;
 | 
			
		||||
    int d_satellite_PRN;
 | 
			
		||||
 | 
			
		||||
    // time synchro
 | 
			
		||||
    double d_subframe1_timestamp_ms; //[ms]
 | 
			
		||||
 | 
			
		||||
    // public functions
 | 
			
		||||
    void reset();
 | 
			
		||||
    int subframe_decoder(char *subframe);
 | 
			
		||||
    void master_clock();
 | 
			
		||||
    void master_clock(double transmitTime);
 | 
			
		||||
    void satpos();
 | 
			
		||||
    void relativistic_clock_correction();
 | 
			
		||||
    void relativistic_clock_correction(double transmitTime);
 | 
			
		||||
    bool satellite_validation();
 | 
			
		||||
    gps_navigation_message();
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file gps_telemetry.cc
 | 
			
		||||
 * \brief  Implementation of low-levels functions for GPS L1 C/A
 | 
			
		||||
 * navigation message decoding
 | 
			
		||||
 * \brief GPS L1 C/A telemetry processing
 | 
			
		||||
 * \author Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
/*!
 | 
			
		||||
 * \file gps_telemetry.h
 | 
			
		||||
 * \brief  Define low-level constants and functions for GPS L1 C/A
 | 
			
		||||
 * navigation message decoding
 | 
			
		||||
 * \brief GPS L1 C/A telemetry processing
 | 
			
		||||
 * \author Javier Arribas, 2011. jarribas(at)cttc.es
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
@@ -28,7 +27,6 @@
 | 
			
		||||
 *
 | 
			
		||||
 * -------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef GPS_TELEMETRY_H_
 | 
			
		||||
#define GPS_TELEMETRY_H_
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ exe mercurio : main.cc
 | 
			
		||||
../algorithms/observables/adapters//gps_l1_ca_observables
 | 
			
		||||
../algorithms/observables/gnuradio_blocks//gps_l1_ca_observables_cc
 | 
			
		||||
../algorithms/observables/libs//rinex_2_1_printer
 | 
			
		||||
../algorithms/observables/libs//gps_l1_ca_ls_pvt
 | 
			
		||||
../algorithms/output_filter/adapters//file_output_filter
 | 
			
		||||
../algorithms/output_filter/adapters//null_sink_output_filter
 | 
			
		||||
../algorithms/signal_source/adapters//file_signal_source
 | 
			
		||||
 
 | 
			
		||||
@@ -71,5 +71,5 @@ int main(int argc, char** argv)
 | 
			
		||||
    control_thread->run();
 | 
			
		||||
 | 
			
		||||
    delete control_thread;
 | 
			
		||||
    google::ShutDownCommandLineFlags();
 | 
			
		||||
    //google::ShutDownCommandLineFlags();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user