1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-01-30 02:44:50 +00:00

Modify RTKLIB PVT band selection and Tel. Dec. E5a

This commit is contained in:
Antonio Ramos 2017-11-20 12:31:49 +01:00
parent bc78416f52
commit 140b388066
10 changed files with 288 additions and 353 deletions

View File

@ -193,9 +193,8 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration,
int num_bands = 0; int num_bands = 0;
if ((gps_1C_count > 0) || (gal_1B_count > 0)) num_bands = 1; if ((gps_1C_count > 0) || (gal_1B_count > 0)) num_bands = 1;
if (((gps_1C_count > 0) || (gal_1B_count > 0)) && (gps_2S_count > 0) ) num_bands = 2; if (gps_2S_count > 0) num_bands = 2;
if (((gps_1C_count > 0) || (gal_1B_count > 0)) && ((gal_E5a_count > 0) || (gal_E5b_count > 0)) ) num_bands = 2; if ((gal_E5a_count > 0) || (gal_E5b_count > 0)) num_bands = 3;
if (((gps_1C_count > 0) || (gal_1B_count > 0)) && (gps_2S_count > 0) && ((gal_E5a_count > 0) || (gal_E5b_count > 0))) num_bands = 3;
int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */ int number_of_frequencies = configuration->property(role + ".num_bands", num_bands); /* (1:L1, 2:L1+L2, 3:L1+L2+L5) */
if( (number_of_frequencies < 1) || (number_of_frequencies > 3) ) if( (number_of_frequencies < 1) || (number_of_frequencies > 3) )
{ {

View File

@ -184,7 +184,10 @@ bool rtklib_solver::get_PVT(const std::map<int,Gnss_Synchro> & gnss_observables_
//convert ephemeris from GNSS-SDR class to RTKLIB structure //convert ephemeris from GNSS-SDR class to RTKLIB structure
eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second); eph_data[valid_obs] = eph_to_rtklib(galileo_ephemeris_iter->second);
//convert observation from GNSS-SDR class to RTKLIB structure //convert observation from GNSS-SDR class to RTKLIB structure
obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; unsigned char default_code_ = static_cast<unsigned char>(CODE_NONE);
obsd_t newobs = {{0,0}, '0', '0', {}, {},
{default_code_, default_code_, default_code_},
{}, {0.0, 0.0, 0.0}, {}};
obs_data[valid_obs] = insert_obs_to_rtklib(newobs, obs_data[valid_obs] = insert_obs_to_rtklib(newobs,
gnss_observables_iter->second, gnss_observables_iter->second,
galileo_ephemeris_iter->second.WN_5, galileo_ephemeris_iter->second.WN_5,

View File

@ -36,7 +36,18 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch
rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz; rtklib_obs.D[band] = gnss_synchro.Carrier_Doppler_hz;
rtklib_obs.P[band] = gnss_synchro.Pseudorange_m; rtklib_obs.P[band] = gnss_synchro.Pseudorange_m;
rtklib_obs.L[band] = gnss_synchro.Carrier_phase_rads / (2.0 * PI); rtklib_obs.L[band] = gnss_synchro.Carrier_phase_rads / (2.0 * PI);
switch(band)
{
case 0:
rtklib_obs.code[band] = static_cast<unsigned char>(CODE_L1C);
break;
case 1:
rtklib_obs.code[band] = static_cast<unsigned char>(CODE_L2S);
break;
case 2:
rtklib_obs.code[band] = static_cast<unsigned char>(CODE_L5X);
break;
}
double CN0_dB_Hz_est = gnss_synchro.CN0_dB_hz; double CN0_dB_Hz_est = gnss_synchro.CN0_dB_hz;
if (CN0_dB_Hz_est > 63.75) CN0_dB_Hz_est = 63.75; if (CN0_dB_Hz_est > 63.75) CN0_dB_Hz_est = 63.75;
if (CN0_dB_Hz_est < 0.0) CN0_dB_Hz_est = 0.0; if (CN0_dB_Hz_est < 0.0) CN0_dB_Hz_est = 0.0;
@ -56,7 +67,6 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch
} }
rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time); rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time);
rtklib_obs.rcv = 1; rtklib_obs.rcv = 1;
//printf("OBS RX TIME [%i]: %s,%f\n\r",rtklib_obs.sat,time_str(rtklib_obs.time,3),rtklib_obs.time.sec);
return rtklib_obs; return rtklib_obs;
} }
@ -88,8 +98,8 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph)
rtklib_sat.f0 = gal_eph.af0_4; rtklib_sat.f0 = gal_eph.af0_4;
rtklib_sat.f1 = gal_eph.af1_4; rtklib_sat.f1 = gal_eph.af1_4;
rtklib_sat.f2 = gal_eph.af2_4; rtklib_sat.f2 = gal_eph.af2_4;
rtklib_sat.tgd[0] = 0; rtklib_sat.tgd[0] = gal_eph.BGD_E1E5a_5;
rtklib_sat.tgd[1] = 0; rtklib_sat.tgd[1] = gal_eph.BGD_E1E5b_5;
rtklib_sat.tgd[2] = 0; rtklib_sat.tgd[2] = 0;
rtklib_sat.tgd[3] = 0; rtklib_sat.tgd[3] = 0;
rtklib_sat.toes = gal_eph.t0e_1; rtklib_sat.toes = gal_eph.t0e_1;

View File

@ -84,7 +84,7 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
int iter, const prcopt_t *opt, double *var) int iter, const prcopt_t *opt, double *var)
{ {
const double *lam = nav->lam[obs->sat - 1]; const double *lam = nav->lam[obs->sat - 1];
double PC, P1, P2, P1_P2, P1_C1, P2_C2, gamma; double PC, P1, P2, P1_P2, P1_C1, P2_C2, gamma_;
int i = 0, j = 1, sys; int i = 0, j = 1, sys;
*var = 0.0; *var = 0.0;
@ -124,7 +124,7 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
} }
} }
} }
gamma = std::pow(lam[j], 2.0) / std::pow(lam[i], 2.0); /* f1^2/f2^2 */ gamma_ = std::pow(lam[j], 2.0) / std::pow(lam[i], 2.0); /* f1^2/f2^2 */
P1 = obs->P[i]; P1 = obs->P[i];
P2 = obs->P[j]; P2 = obs->P[j];
P1_P2 = nav->cbias[obs->sat-1][0]; P1_P2 = nav->cbias[obs->sat-1][0];
@ -134,7 +134,7 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
/* if no P1-P2 DCB, use TGD instead */ /* if no P1-P2 DCB, use TGD instead */
if (P1_P2 == 0.0 && (sys & (SYS_GPS | SYS_GAL | SYS_QZS))) if (P1_P2 == 0.0 && (sys & (SYS_GPS | SYS_GAL | SYS_QZS)))
{ {
P1_P2 = (1.0 - gamma) * gettgd(obs->sat, nav); P1_P2 = (1.0 - gamma_) * gettgd(obs->sat, nav);
} }
if (opt->ionoopt == IONOOPT_IFLC) if (opt->ionoopt == IONOOPT_IFLC)
{ /* dual-frequency */ { /* dual-frequency */
@ -144,15 +144,30 @@ double prange(const obsd_t *obs, const nav_t *nav, const double *azel,
if (obs->code[j] == CODE_L2C) P2 += P2_C2; /* C2->P2 */ if (obs->code[j] == CODE_L2C) P2 += P2_C2; /* C2->P2 */
/* iono-free combination */ /* iono-free combination */
PC = (gamma * P1 - P2) / (gamma - 1.0); PC = (gamma_ * P1 - P2) / (gamma_ - 1.0);
} }
else else
{ /* single-frequency */ { /* single-frequency */
if((obs->code[i] == CODE_NONE) && (obs->code[j] == CODE_NONE)){return 0.0;}
if (P1 == 0.0) return 0.0; else if((obs->code[i] != CODE_NONE) && (obs->code[j] == CODE_NONE))
if (obs->code[i] == CODE_L1C) P1 += P1_C1; /* C1->P1 */ {
PC = P1 - P1_P2 / (1.0 - gamma); P1 += P1_C1; /* C1->P1 */
} PC = P1 - P1_P2 / (1.0 - gamma_);
}
else if((obs->code[i] == CODE_NONE) && (obs->code[j] != CODE_NONE))
{
P2 += P2_C2; /* C2->P2 */
PC = P2 - gamma_ * P1_P2 / (1.0 - gamma_);
}
/* dual-frequency */
else
{
P1 += P1_C1;
P2 += P2_C2;
PC = (gamma_ * P1 - P2) / (gamma_ - 1.0);
}
}
if (opt->sateph == EPHOPT_SBAS) PC -= P1_C1; /* sbas clock based C1 */ if (opt->sateph == EPHOPT_SBAS) PC -= P1_C1; /* sbas clock based C1 */
*var = std::pow(ERR_CBIAS, 2.0); *var = std::pow(ERR_CBIAS, 2.0);
@ -285,12 +300,17 @@ int rescode(int iter, const obsd_t *obs, int n, const double *rs,
continue; continue;
} }
/* geometric distance/azimuth/elevation angle */ /* geometric distance/azimuth/elevation angle */
if ((r = geodist(rs + i * 6, rr, e)) <= 0.0 || satazel(pos, e, azel + i * 2) < opt->elmin) if ((r = geodist(rs + i * 6, rr, e)) <= 0.0)
{ {
trace(4, "geodist / satazel error\n"); trace(4, "geodist error\n");
continue;
}
double elaux = satazel(pos, e, azel + i * 2);
if(elaux < opt->elmin)
{
trace(4, "satazel error. el = %lf , elmin = %lf\n", elaux, opt->elmin);
continue; continue;
} }
/* psudorange with code bias correction */ /* psudorange with code bias correction */
if ((P = prange(obs+i, nav, azel+i*2, iter, opt, &vmeas)) == 0.0) if ((P = prange(obs+i, nav, azel+i*2, iter, opt, &vmeas)) == 0.0)
{ {
@ -671,53 +691,6 @@ int pntpos(const obsd_t *obs, int n, const nav_t *nav,
const prcopt_t *opt, sol_t *sol, double *azel, ssat_t *ssat, const prcopt_t *opt, sol_t *sol, double *azel, ssat_t *ssat,
char *msg) char *msg)
{ {
// int k = 0;
// for (k = 0;k<n;k++)
// {
// printf("OBS[%i]: sat %i, P:%f ,LLI:%s \r\n",k,obs[k].sat,obs[k].P[0], obs[k].LLI);
// }
//
// for (k = 0;k<nav->n;k++)
// {
// printf("NAV[%i]: sat %i, %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f , %f \r\n",
// k,
// nav->eph[k].sat,
// nav->eph[k].A,
// nav->eph[k].Adot,
// nav->eph[k].M0,
// nav->eph[k].OMG0,
// nav->eph[k].OMGd,
// nav->eph[k].cic,
// nav->eph[k].cis,
// nav->eph[k].code,
// nav->eph[k].crc,
// nav->eph[k].crs,
// nav->eph[k].cuc,
// nav->eph[k].cus,
// nav->eph[k].deln,
// nav->eph[k].e,
// nav->eph[k].f0,
// nav->eph[k].f1,
// nav->eph[k].f2,
// nav->eph[k].fit,
// nav->eph[k].flag,
// nav->eph[k].i0,
// nav->eph[k].idot,
// nav->eph[k].iodc,
// nav->eph[k].iode,
// nav->eph[k].ndot,
// nav->eph[k].omg,
// nav->eph[k].sat,
// nav->eph[k].sva,
// nav->eph[k].svh,
// nav->eph[k].tgd[0],
// nav->eph[k].toc.sec,
// nav->eph[k].toe.sec,
// nav->eph[k].toes,
// nav->eph[k].ttr.sec,
// nav->eph[k].week);
// }
prcopt_t opt_ = *opt; prcopt_t opt_ = *opt;
double *rs, *dts, *var, *azel_, *resp; double *rs, *dts, *var, *azel_, *resp;
int i, stat, vsat[MAXOBS] = {0}, svh[MAXOBS]; int i, stat, vsat[MAXOBS] = {0}, svh[MAXOBS];

View File

@ -3461,7 +3461,7 @@ double geodist(const double *rs, const double *rr, double *e)
/* satellite azimuth/elevation angle ------------------------------------------- /* satellite azimuth/elevation angle -------------------------------------------
* compute satellite azimuth/elevation angle * compute satellite azimuth/elevation angle
* args : double *pos I geodetic position {lat,lon,h} (rad,m) * args : double *pos I geodetic position {lat,lon,h} (rad,m)
* double *e I receiver-to-satellilte unit vevtor (ecef) * double *e I receiver-to-satellilte unit vector (ecef)
* double *azel IO azimuth/elevation {az,el} (rad) (NULL: no output) * double *azel IO azimuth/elevation {az,el} (rad) (NULL: no output)
* (0.0<=azel[0]<2*pi,-pi/2<=azel[1]<=pi/2) * (0.0<=azel[0]<2*pi,-pi/2<=azel[1]<=pi/2)
* return : elevation angle (rad) * return : elevation angle (rad)

View File

@ -358,11 +358,6 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused
{ {
d_gnss_synchro_history_queue[i].push_back(in[i][j]); d_gnss_synchro_history_queue[i].push_back(in[i][j]);
} }
//std::cout<<"push["<<i<<"] items "<<n_consume[i]
/// <<" latest T_rx: "<<(double)in[i][ninput_items[i]-1].Tracking_sample_counter/(double)in[i][ninput_items[i]-1].fs
// <<" [s] q size: "
// <<d_gnss_synchro_history_queue[i].size()
// <<std::endl;
} }
bool channel_history_ok; bool channel_history_ok;
@ -448,10 +443,6 @@ int hybrid_observables_cc::general_work (int noutput_items __attribute__((unused
} }
} }
else
{
//std::cout<<"ch["<<i<<"] delta_T_rx:"<<delta_T_rx_s*1000.0<<std::endl;
}
} }
} }
} }

View File

@ -39,8 +39,8 @@
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include <glog/logging.h> #include <glog/logging.h>
#include <cmath>
#include "control_message_factory.h" #include "control_message_factory.h"
#include "gnss_synchro.h"
#include "convolutional.h" #include "convolutional.h"
@ -114,7 +114,7 @@ void galileo_e5a_telemetry_decoder_cc::decode_word(double *page_symbols, int fra
double page_symbols_deint[frame_length]; double page_symbols_deint[frame_length];
// 1. De-interleave // 1. De-interleave
galileo_e5a_telemetry_decoder_cc::deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint); deinterleaver(GALILEO_FNAV_INTERLEAVER_ROWS, GALILEO_FNAV_INTERLEAVER_COLS, page_symbols, page_symbols_deint);
// 2. Viterbi decoder // 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
@ -127,7 +127,7 @@ void galileo_e5a_telemetry_decoder_cc::decode_word(double *page_symbols, int fra
} }
} }
int page_bits[frame_length/2]; int page_bits[frame_length/2];
galileo_e5a_telemetry_decoder_cc::viterbi_decoder(page_symbols_deint, page_bits); viterbi_decoder(page_symbols_deint, page_bits);
// 3. Call the Galileo page decoder // 3. Call the Galileo page decoder
std::string page_String; std::string page_String;
@ -197,32 +197,37 @@ galileo_e5a_telemetry_decoder_cc::galileo_e5a_telemetry_decoder_cc(
{ {
if (GALILEO_FNAV_PREAMBLE.at(i) == '0') if (GALILEO_FNAV_PREAMBLE.at(i) == '0')
{ {
d_preamble_bits[i] = 1; d_preambles_bits[i] = 1;
} }
else else
{ {
d_preamble_bits[i] = -1; d_preambles_bits[i] = -1;
}
}
for (int i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
for (int k = 0; k < GALILEO_FNAV_CODES_PER_SYMBOL; k++)
{
d_preamble_samples[(i * GALILEO_FNAV_CODES_PER_SYMBOL) + k] = d_preambles_bits[i];
} }
} }
d_sample_counter = 0; d_sample_counter = 0;
d_state = 0; d_stat = 0;
d_preamble_lock = false; corr_value = 0;
d_flag_preamble = false;
d_preamble_index = 0; d_preamble_index = 0;
d_flag_frame_sync = false; d_flag_frame_sync = false;
d_current_symbol = 0; d_TOW_at_current_symbol = 0.0;
d_prompt_counter = 0;
d_symbol_counter = 0;
d_TOW_at_Preamble = 0;
d_TOW_at_current_symbol = 0;
d_CRC_error_counter = 0;
d_sign_init = 0;
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false; flag_TOW_set = false;
d_CRC_error_counter = 0;
d_channel = 0;
delta_t = 0.0;
d_symbol_counter = 0;
d_prompt_acum = 0.0;
flag_bit_start = false;
new_symbol = false;
required_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
} }
@ -245,265 +250,222 @@ galileo_e5a_telemetry_decoder_cc::~galileo_e5a_telemetry_decoder_cc()
int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)), int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{ {
Gnss_Synchro *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]); // Get the output buffer pointer int preamble_diff = 0;
const Gnss_Synchro *in = reinterpret_cast<const Gnss_Synchro *>(input_items[0]); // Get the input buffer pointer
/* Terminology: Prompt: output from tracking Prompt correlator (Prompt samples) Gnss_Synchro* out = reinterpret_cast<Gnss_Synchro*>(output_items[0]); // Get the output buffer pointer
* Symbol: encoded navigation bits. 1 symbol = 20 samples in E5a const Gnss_Synchro* in = reinterpret_cast<const Gnss_Synchro*>(input_items[0]); // Get the input buffer pointer
* Bit: decoded navigation bits forming words as described in Galileo ICD
* States: 0 Receiving dummy samples. Gnss_Synchro current_sample; //structure to save the synchronization information and send the output object to the next block
* 1 Preamble not locked //1. Copy the current tracking output
* 3 Preamble lock current_sample = in[0];
*/ d_symbol_counter++;
switch (d_state) if(flag_bit_start)
{ {
case 0: d_prompt_acum += current_sample.Prompt_I;
{ if(d_symbol_counter == GALILEO_FNAV_CODES_PER_SYMBOL)
if (in[0].Prompt_I != 0) {
{ current_sample.Prompt_I = d_prompt_acum / static_cast<double>(GALILEO_FNAV_CODES_PER_SYMBOL);
d_current_symbol += in[0].Prompt_I; d_symbol_history.push_back(current_sample); //add new symbol to the symbol queue
if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1) d_prompt_acum = 0.0;
{ d_symbol_counter = 0;
if (d_current_symbol > 0) new_symbol = true;
{ }
d_page_symbols[d_symbol_counter] = 1; }
} else
else {
{ if(current_sample.Prompt_I < 0.0)
d_page_symbols[d_symbol_counter] = -1; {
} d_preamble_init.push_back(1);
d_current_symbol = 0; }
d_symbol_counter++; else
d_prompt_counter = 0; {
if (d_symbol_counter == GALILEO_FNAV_PREAMBLE_LENGTH_BITS - 1) d_preamble_init.push_back(-1);
{ }
d_state = 1;
}
}
else
{
d_prompt_counter++;
}
}
break;
}
case 1:
{
d_current_symbol += in[0].Prompt_I;
if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1)
{
if (d_current_symbol > 0)
{
d_page_symbols[d_symbol_counter] = 1;
}
else
{
d_page_symbols[d_symbol_counter] = -1;
}
// d_page_symbols[d_symbol_counter] = d_current_symbol_float/(float)GALILEO_FNAV_CODES_PER_SYMBOL;
d_current_symbol = 0;
d_symbol_counter++;
d_prompt_counter = 0;
// **** Attempt Preamble correlation ****
bool corr_flag = true;
int corr_sign = 0; // sequence can be found inverted
// check if the preamble starts positive correlated or negative correlated
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS] < 0) // symbols clipping
{
corr_sign = -d_preamble_bits[0];
}
else
{
corr_sign = d_preamble_bits[0];
}
// the preamble is fully correlated only if maintains corr_sign along the whole sequence
for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] < 0 && d_preamble_bits[i]+corr_sign != 0)
{
//exit for
corr_flag = false;
break;
}
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] > 0 && d_preamble_bits[i]+corr_sign == 0)
{
//exit for
corr_flag = false;
break;
}
}
//
if (corr_flag == true) // preamble fully correlates
{
d_preamble_index = d_sample_counter - GALILEO_FNAV_CODES_PER_PREAMBLE;//record the preamble sample stamp. Remember correlation appears at the end of the preamble in this design
LOG(INFO) << "Preamble detection in E5a for Galileo satellite " << this->d_satellite << std::endl;
d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble.
d_state = 2; // preamble lock
}
if (d_symbol_counter >= GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{
d_symbol_counter = GALILEO_FNAV_PREAMBLE_LENGTH_BITS; // prevents overflow
}
}
else
{
d_prompt_counter++;
}
break;
}
case 2:
{
d_current_symbol += in[0].Prompt_I;
if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1)
{
if (d_current_symbol > 0)
{
d_page_symbols[d_symbol_counter] = 1;
}
else
{
d_page_symbols[d_symbol_counter] = -1;
}
// d_page_symbols[d_symbol_counter] = d_current_symbol_float/(float)GALILEO_FNAV_CODES_PER_SYMBOL;
d_current_symbol = 0;
d_symbol_counter++;
d_prompt_counter = 0;
// At the right sample stamp, check preamble synchro
if (d_sample_counter == d_preamble_index + GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE)
{
// **** Attempt Preamble correlation ****
bool corr_flag = true;
int corr_sign = 0; // sequence can be found inverted
// check if the preamble starts positive correlated or negative correlated
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS] < 0) // symbols clipping
{
corr_sign = -d_preamble_bits[0];
}
else
{
corr_sign = d_preamble_bits[0];
}
// the preamble is fully correlated only if maintains corr_sign along the whole sequence
for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
{
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] < 0 && d_preamble_bits[i]+corr_sign != 0)
{
//exit for
corr_flag = false;
break;
}
if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] > 0 && d_preamble_bits[i]+corr_sign == 0)
{
//exit for
corr_flag = false;
break;
}
}
if (corr_flag == true) // NEW PREAMBLE RECEIVED. DECODE PAGE if (d_preamble_init.size() == GALILEO_FNAV_CODES_PER_PREAMBLE)
{ {
d_preamble_index = d_sample_counter - GALILEO_FNAV_CODES_PER_PREAMBLE;//record the preamble sample stamp std::deque<int>::iterator iter;
// DECODE WORD int k = 0;
decode_word(d_page_symbols, GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS); corr_value = 0;
// CHECK CRC for (iter = d_preamble_init.begin(); iter != d_preamble_init.end(); iter++)
if (d_nav.flag_CRC_test == true) {
{ corr_value += *iter * d_preamble_samples[k];
d_CRC_error_counter = 0; k++;
d_flag_preamble = true; //valid preamble indicator (initialized to false every work()) }
if (!d_flag_frame_sync) if(abs(corr_value) == GALILEO_FNAV_CODES_PER_PREAMBLE)
{ {
d_flag_frame_sync = true; d_symbol_counter = 0;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at " flag_bit_start = true;
<< in[0].Tracking_sample_counter << " [samples]"; corr_value = 0;
} while(d_preamble_init.size() > 0)
d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble. { //Clear preamble correlating queue
} d_preamble_init.pop_front();
else }
{ while(d_symbol_history.size() > 0)
d_CRC_error_counter++; { //Clear symbol queue in order to prevent possible symbol discontinuities
if (d_CRC_error_counter > GALILEO_E5a_CRC_ERROR_LIMIT) d_symbol_history.pop_front();
{ }
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite; LOG(INFO) << "Bit start sync for Galileo E5a satellite " << d_satellite;
d_state = 1; }
d_symbol_counter = GALILEO_FNAV_PREAMBLE_LENGTH_BITS; // prevents overflow else
d_flag_frame_sync = false; {
} d_preamble_init.pop_front();
else }
{ }
d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble. }
} d_sample_counter++; //count for the processed samples
} consume_each(1);
}
} d_flag_preamble = false;
}
else if ((d_symbol_history.size() > required_symbols) && new_symbol)
{ {
d_prompt_counter++; //******* preamble correlation ********
} corr_value = 0;
break; for (int i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++)
} {
if (d_symbol_history.at(i).Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_bits[i];
}
else
{
corr_value += d_preambles_bits[i];
}
}
} }
//******* frame sync ******************
if ((d_stat == 0) && new_symbol) //no preamble information
{
if (abs(corr_value) >= GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{
d_preamble_index = d_sample_counter;//record the preamble sample stamp
LOG(INFO) << "Preamble detection for Galileo E5a satellite " << d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
}
else if ((d_stat == 1) && new_symbol) // posible preamble lock
{
if (abs(corr_value) >= GALILEO_FNAV_PREAMBLE_LENGTH_BITS)
{
//check preamble separation
preamble_diff = d_sample_counter - d_preamble_index;
if (preamble_diff == GALILEO_FNAV_CODES_PER_PAGE)
{
//try to decode frame
LOG(INFO) << "Starting page decoder for Galileo E5a satellite " << d_satellite;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
d_stat = 2;
}
else if (preamble_diff > GALILEO_FNAV_CODES_PER_PAGE)
{
d_stat = 0; // start again
flag_bit_start = false;
LOG(INFO) << "Preamble diff = " << preamble_diff;
}
}
}
else if ((d_stat == 2) && new_symbol)
{
if (d_sample_counter == (d_preamble_index + GALILEO_FNAV_CODES_PER_PAGE))
{
// NEW Galileo page part is received
// 0. fetch the symbols into an array
int frame_length = GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS;
double corr_sign = 0.0;
if(corr_value > 0)
{
corr_sign = -1.0;
}
else
{
corr_sign = 1.0;
}
for (int i = 0; i < frame_length; i++)
{
page_symbols[i] = corr_sign * d_symbol_history.at(i + GALILEO_FNAV_PREAMBLE_LENGTH_BITS).Prompt_I; // because last symbol of the preamble is just received now!
}
//call the decoder
decode_word(page_symbols, frame_length);
if (d_nav.flag_CRC_test == true)
{
d_CRC_error_counter = 0;
d_flag_preamble = true; //valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; //record the preamble sample stamp
if (d_CRC_error_counter > GALILEO_E5A_CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
flag_bit_start = false;
}
}
}
}
new_symbol = false;
// UPDATE GNSS SYNCHRO DATA // UPDATE GNSS SYNCHRO DATA
Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block //Add the telemetry decoder information
//1. Copy the current tracking output if (d_flag_preamble and d_nav.flag_TOW_set)
current_synchro_data = in[0];
//2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_nav.flag_TOW_set == true)
//update TOW at the preamble instant //update TOW at the preamble instant
//We expect a preamble each 10 seconds (FNAV page period) //We expect a preamble each 10 seconds (FNAV page period)
{ {
if (d_nav.flag_TOW_1 == true) if (d_nav.flag_TOW_1 == true)
{ {
d_TOW_at_Preamble = d_nav.FNAV_TOW_1; d_TOW_at_current_symbol = d_nav.FNAV_TOW_1 + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_TOW_at_current_symbol = d_TOW_at_Preamble + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_nav.flag_TOW_1 = false; d_nav.flag_TOW_1 = false;
} }
if (d_nav.flag_TOW_2 == true) else if (d_nav.flag_TOW_2 == true)
{ {
d_TOW_at_Preamble = d_nav.FNAV_TOW_2; d_TOW_at_current_symbol = d_nav.FNAV_TOW_2 + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_TOW_at_current_symbol = d_TOW_at_Preamble + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_nav.flag_TOW_2 = false; d_nav.flag_TOW_2 = false;
} }
if (d_nav.flag_TOW_3 == true) else if (d_nav.flag_TOW_3 == true)
{ {
d_TOW_at_Preamble = d_nav.FNAV_TOW_3; d_TOW_at_current_symbol = d_nav.FNAV_TOW_3 + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_TOW_at_current_symbol = d_TOW_at_Preamble + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_nav.flag_TOW_3 = false; d_nav.flag_TOW_3 = false;
} }
if (d_nav.flag_TOW_4 == true) else if (d_nav.flag_TOW_4 == true)
{ {
d_TOW_at_Preamble = d_nav.FNAV_TOW_4; d_TOW_at_current_symbol = d_nav.FNAV_TOW_4 + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_TOW_at_current_symbol = d_TOW_at_Preamble + (static_cast<double>(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD);
d_nav.flag_TOW_4 = false; d_nav.flag_TOW_4 = false;
} }
else else
{ {
//this page has no timming information d_TOW_at_current_symbol += GALILEO_E5a_CODE_PERIOD;
d_TOW_at_Preamble = d_TOW_at_Preamble + GALILEO_FNAV_SECONDS_PER_PAGE;
d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD;
} }
} }
else //if there is not a new preamble, we define the TOW of the current symbol else //if there is not a new preamble, we define the TOW of the current symbol
{ {
d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD; d_TOW_at_current_symbol += GALILEO_E5a_CODE_PERIOD;
} }
//if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true) //if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true)
if (d_flag_frame_sync == true and d_nav.flag_TOW_set == true) if (d_flag_frame_sync and d_nav.flag_TOW_set)
{ {
current_synchro_data.Flag_valid_word = true; current_sample.Flag_valid_word = true;
} }
else else
{ {
current_synchro_data.Flag_valid_word = false; current_sample.Flag_valid_word = false;
} }
current_synchro_data.TOW_at_current_symbol_s = floor(d_TOW_at_current_symbol*1000.0)/1000.0; current_sample.TOW_at_current_symbol_s = floor(d_TOW_at_current_symbol*1000.0)/1000.0;
if(d_dump == true) if(d_dump)
{ {
// MULTIPLEXED FILE RECORDING - Record results to file // MULTIPLEXED FILE RECORDING - Record results to file
try try
@ -512,20 +474,23 @@ int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items __attribut
unsigned long int tmp_ulong_int; unsigned long int tmp_ulong_int;
tmp_double = d_TOW_at_current_symbol; tmp_double = d_TOW_at_current_symbol;
d_dump_file.write(reinterpret_cast<char*>(&tmp_double), sizeof(double)); d_dump_file.write(reinterpret_cast<char*>(&tmp_double), sizeof(double));
tmp_ulong_int = current_synchro_data.Tracking_sample_counter; tmp_ulong_int = current_sample.Tracking_sample_counter;
d_dump_file.write(reinterpret_cast<char*>(&tmp_ulong_int), sizeof(unsigned long int)); d_dump_file.write(reinterpret_cast<char*>(&tmp_ulong_int), sizeof(unsigned long int));
tmp_double = d_TOW_at_Preamble; tmp_double = 0.0;
d_dump_file.write(reinterpret_cast<char*>(&tmp_double), sizeof(double)); d_dump_file.write(reinterpret_cast<char*>(&tmp_double), sizeof(double));
} }
catch (const std::ifstream::failure & e) catch (const std::ifstream::failure & e)
{ {
LOG(WARNING) << "Exception writing observables dump file " << e.what(); LOG(WARNING) << "Exception writing Galileo E5a Telemetry Decoder dump file " << e.what();
} }
} }
d_sample_counter++; //count for the processed samples // remove used symbols from history
//3. Make the output (copy the object contents to the GNURadio reserved memory) while (d_symbol_history.size() > required_symbols)
out[0] = current_synchro_data; {
consume_each(1); d_symbol_history.pop_front();
}
//3. Make the output
out[0] = current_sample;
return 1; return 1;
} }

View File

@ -39,6 +39,7 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <deque>
#include <gnuradio/block.h> #include <gnuradio/block.h>
#include "Galileo_E5a.h" #include "Galileo_E5a.h"
#include "concurrent_queue.h" #include "concurrent_queue.h"
@ -48,8 +49,7 @@
#include "galileo_almanac.h" #include "galileo_almanac.h"
#include "galileo_iono.h" #include "galileo_iono.h"
#include "galileo_utc_model.h" #include "galileo_utc_model.h"
#include "gnss_synchro.h"
//#include "convolutional.h"
class galileo_e5a_telemetry_decoder_cc; class galileo_e5a_telemetry_decoder_cc;
@ -85,38 +85,33 @@ private:
void decode_word(double *page_symbols, int frame_length); void decode_word(double *page_symbols, int frame_length);
int d_preamble_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; int d_preambles_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS];
double d_page_symbols[GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; int d_preamble_samples[GALILEO_FNAV_CODES_PER_PREAMBLE];
std::deque<int> d_preamble_init;
double d_current_symbol; int d_stat;
long unsigned int d_symbol_counter; int d_CRC_error_counter;
int d_prompt_counter; int d_channel;
int d_sign_init; int d_symbol_counter;
int corr_value;
unsigned int required_symbols;
long unsigned int d_sample_counter; long unsigned int d_sample_counter;
long unsigned int d_preamble_index; long unsigned int d_preamble_index;
bool d_preamble_lock;
bool d_flag_frame_sync; bool d_flag_frame_sync;
int d_state;
bool d_flag_preamble; bool d_flag_preamble;
int d_CRC_error_counter;
// navigation message vars
Galileo_Fnav_Message d_nav;
bool d_dump; bool d_dump;
Gnss_Satellite d_satellite;
int d_channel;
double d_TOW_at_Preamble;
double d_TOW_at_current_symbol;
bool flag_TOW_set; bool flag_TOW_set;
bool flag_bit_start;
bool new_symbol;
double d_prompt_acum;
double page_symbols[GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS];
double d_TOW_at_current_symbol;
double delta_t; //GPS-GALILEO time offset
std::string d_dump_filename; std::string d_dump_filename;
std::ofstream d_dump_file; std::ofstream d_dump_file;
std::deque<Gnss_Synchro> d_symbol_history;
Gnss_Satellite d_satellite;
// navigation message vars
Galileo_Fnav_Message d_nav;
}; };
#endif /* GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_CC_H_ */ #endif /* GNSS_SDR_GALILEO_E5A_TELEMETRY_DECODER_CC_H_ */

View File

@ -84,7 +84,6 @@ const int GALILEO_PAGE_TYPE_BITS = 6;
const int GALILEO_DATA_JK_BITS = 128; const int GALILEO_DATA_JK_BITS = 128;
const int GALILEO_DATA_FRAME_BITS = 196; const int GALILEO_DATA_FRAME_BITS = 196;
const int GALILEO_DATA_FRAME_BYTES = 25; const int GALILEO_DATA_FRAME_BYTES = 25;
//const double GALIELO_E1_CODE_PERIOD = 0.004;
const double GALILEO_E1_CODE_PERIOD = 0.004; const double GALILEO_E1_CODE_PERIOD = 0.004;
const std::vector<std::pair<int,int>> type({{1,6}}); const std::vector<std::pair<int,int>> type({{1,6}});

View File

@ -52,9 +52,9 @@ const int Galileo_E5a_SYMBOL_RATE_BPS = 50; //!< Galileo E5a symbo
const int Galileo_E5a_NUMBER_OF_CODES = 50; const int Galileo_E5a_NUMBER_OF_CODES = 50;
// OBSERVABLE HISTORY DEEP FOR INTERPOLATION // OBSERVABLE HISTORY DEEP FOR INTERPOLATION AND CRC ERROR LIMIT
const int GALILEO_E5A_HISTORY_DEEP = 20; const int GALILEO_E5A_HISTORY_DEEP = 20;
const int GALILEO_E5A_CRC_ERROR_LIMIT = 6;
// F/NAV message structure // F/NAV message structure
@ -103,7 +103,7 @@ const double FNAV_BGD_1_LSB = TWO_N32;
const std::vector<std::pair<int,int>> FNAV_E5ahs_1_bit({{154,2}}); const std::vector<std::pair<int,int>> FNAV_E5ahs_1_bit({{154,2}});
const std::vector<std::pair<int,int>> FNAV_WN_1_bit({{156,12}}); const std::vector<std::pair<int,int>> FNAV_WN_1_bit({{156,12}});
const std::vector<std::pair<int,int>> FNAV_TOW_1_bit({{168,20}}); const std::vector<std::pair<int,int>> FNAV_TOW_1_bit({{168,20}});
const std::vector<std::pair<int,int>> FNAV_E5advs_1_bit({{189,1}}); const std::vector<std::pair<int,int>> FNAV_E5advs_1_bit({{188,1}});
// WORD 2 Ephemeris (1/3) // WORD 2 Ephemeris (1/3)
const std::vector<std::pair<int,int>> FNAV_IODnav_2_bit({{7,10}}); const std::vector<std::pair<int,int>> FNAV_IODnav_2_bit({{7,10}});
@ -145,7 +145,7 @@ const std::vector<std::pair<int,int>> FNAV_TOW_3_bit({{187,20}});
// WORD 4 Ephemeris (3/3) // WORD 4 Ephemeris (3/3)
const std::vector<std::pair<int,int>> FNAV_IODnav_4_bit({{7,10}}); const std::vector<std::pair<int,int>> FNAV_IODnav_4_bit({{7,10}});
const std::vector<std::pair<int,int>> FNAV_Cic_4_bit({{18,16}}); const std::vector<std::pair<int,int>> FNAV_Cic_4_bit({{17,16}});
const double FNAV_Cic_4_LSB = TWO_N29; const double FNAV_Cic_4_LSB = TWO_N29;
const std::vector<std::pair<int,int>> FNAV_Cis_4_bit({{33,16}}); const std::vector<std::pair<int,int>> FNAV_Cis_4_bit({{33,16}});
const double FNAV_Cis_4_LSB = TWO_N29; const double FNAV_Cis_4_LSB = TWO_N29;