diff --git a/CMakeLists.txt b/CMakeLists.txt index 265e79ec5..b49ad4217 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -271,7 +271,7 @@ endif(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "") # Append -O2 optimization flag for Debug builds -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O2") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") # allow 'large' files in 32 bit builds if(UNIX) diff --git a/conf/gnss-sdr_GPS_L1_ishort.conf b/conf/gnss-sdr_GPS_L1_ishort.conf index a5cce5189..f496c9eff 100644 --- a/conf/gnss-sdr_GPS_L1_ishort.conf +++ b/conf/gnss-sdr_GPS_L1_ishort.conf @@ -13,7 +13,7 @@ ControlThread.wait_for_flowgraph=false ;######### SIGNAL_SOURCE CONFIG ############ SignalSource.implementation=File_Signal_Source -SignalSource.filename=/Users/carlesfernandez/Documents/workspace/code2/trunk/data/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ;/datalogger/signals/CTTC/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE +SignalSource.filename=/archive/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ;/datalogger/signals/CTTC/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN/2013_04_04_GNSS_SIGNAL_at_CTTC_SPAIN.dat ; <- PUT YOUR FILE HERE SignalSource.item_type=ishort SignalSource.sampling_frequency=4000000 SignalSource.freq=1575420000 diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index 3e6758e58..b0c0c5666 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -190,8 +190,8 @@ void rtklib_pvt_cc::msg_handler_telemetry(pmt::pmt_t msg) // TODO Add GLONASS with gps week number and tow, // insert new ephemeris record DLOG(INFO) << "GLONASS GNAV New Ephemeris record inserted in global map with TOW =" << glonass_gnav_eph->d_TOW - << ", GLONASS GNAV Week Number =" << glonass_gnav_eph->d_WN - << " and Ephemeris IOD = " << glonass_gnav_eph->compute_GLONASS_time(glonass_gnav_eph->d_t_b) + << ", Week Number =" << glonass_gnav_eph->d_WN + << " and Ephemeris IOD in UTC = " << glonass_gnav_eph->compute_GLONASS_time(glonass_gnav_eph->d_t_b) << " from SV = " << glonass_gnav_eph->i_satellite_slot_number; // update/insert new ephemeris record to the global ephemeris map d_ls_pvt->glonass_gnav_ephemeris_map[glonass_gnav_eph->i_satellite_PRN] = *glonass_gnav_eph; @@ -542,7 +542,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite std::map::const_iterator tmp_eph_iter_gps = d_ls_pvt->gps_ephemeris_map.find(in[i][epoch].PRN); std::map::const_iterator tmp_eph_iter_gal = d_ls_pvt->galileo_ephemeris_map.find(in[i][epoch].PRN); std::map::const_iterator tmp_eph_iter_cnav = d_ls_pvt->gps_cnav_ephemeris_map.find(in[i][epoch].PRN); - std::map::const_iterator tmp_eph_iter_glo_gnav = d_ls_pvt->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN); + std::map::const_iterator tmp_eph_iter_glo_gnav = d_ls_pvt->glonass_gnav_ephemeris_map.find(in[i][epoch].PRN); if(((tmp_eph_iter_gps->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1C") == 0)) || ((tmp_eph_iter_cnav->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("2S") == 0)) || ((tmp_eph_iter_gal->second.i_satellite_PRN == in[i][epoch].PRN) && (std::string(in[i][epoch].Signal).compare("1B") == 0)) diff --git a/src/algorithms/PVT/libs/rtklib_solver.cc b/src/algorithms/PVT/libs/rtklib_solver.cc index de34231d7..30766ca0c 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.cc +++ b/src/algorithms/PVT/libs/rtklib_solver.cc @@ -116,6 +116,7 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ std::map::const_iterator gps_ephemeris_iter; std::map::const_iterator gps_cnav_ephemeris_iter; std::map::const_iterator glonass_gnav_ephemeris_iter; + const Glonass_Gnav_Utc_Model gnav_utc = this->glonass_gnav_utc_model; this->set_averaging_flag(flag_averaging); @@ -279,75 +280,75 @@ bool rtklib_solver::get_PVT(const std::map & gnss_observables_ } break; } - case 'R': //TODO This should be using rtk lib nomenclature - { - std::string sig_(gnss_observables_iter->second.Signal); - // GLONASS GNAV L1 - if(sig_.compare("1G") == 0) - { - // 1 Glo - find the ephemeris for the current GLONASS SV observation. The SV Slot Number (PRN ID) is the map key - glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend()) - { - //convert ephemeris from GNSS-SDR class to RTKLIB structure - geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second); - //convert observation from GNSS-SDR class to RTKLIB structure - obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; - obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs, - gnss_observables_iter->second, - glonass_gnav_ephemeris_iter->second.d_WN, - 0);//Band 0 (L1) - glo_valid_obs++; - } - else // the ephemeris are not available for this SV - { - DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; - } + case 'R': //TODO This should be using rtk lib nomenclature + { + std::string sig_(gnss_observables_iter->second.Signal); + // GLONASS GNAV L1 + if(sig_.compare("1G") == 0) + { + // 1 Glo - find the ephemeris for the current GLONASS SV observation. The SV Slot Number (PRN ID) is the map key + glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend()) + { + //convert ephemeris from GNSS-SDR class to RTKLIB structure + geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second, gnav_utc); + //convert observation from GNSS-SDR class to RTKLIB structure + obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; + obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs, + gnss_observables_iter->second, + glonass_gnav_ephemeris_iter->second.d_WN, + 0);//Band 0 (L1) + glo_valid_obs++; + } + else // the ephemeris are not available for this SV + { + DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; + } - } - // GLONASS GNAV L2 - if(sig_.compare("2G") == 0) - { - // 1 GLONASS - find the ephemeris for the current GLONASS SV observation. The SV PRN ID is the map key - glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); - if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend()) - { - bool found_L1_obs=false; - for (int i = 0; i < glo_valid_obs; i++) - { - if (geph_data[i].sat == (static_cast(gnss_observables_iter->second.PRN+NSATGPS))) - { - obs_data[i] = insert_obs_to_rtklib(obs_data[i], - gnss_observables_iter->second, - glonass_gnav_ephemeris_iter->second.d_WN, - 1);//Band 1 (L2) - found_L1_obs=true; - break; - } - } - if (!found_L1_obs) + } + // GLONASS GNAV L2 + if(sig_.compare("2G") == 0) + { + // 1 GLONASS - find the ephemeris for the current GLONASS SV observation. The SV PRN ID is the map key + glonass_gnav_ephemeris_iter = glonass_gnav_ephemeris_map.find(gnss_observables_iter->second.PRN); + if (glonass_gnav_ephemeris_iter != glonass_gnav_ephemeris_map.cend()) + { + bool found_L1_obs=false; + for (int i = 0; i < glo_valid_obs; i++) + { + if (geph_data[i].sat == (static_cast(gnss_observables_iter->second.PRN+NSATGPS))) { - //insert GLONASS GNAV L2 obs as new obs and also insert its ephemeris - //convert ephemeris from GNSS-SDR class to RTKLIB structure - geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second); - //convert observation from GNSS-SDR class to RTKLIB structure - obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; - obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs, + obs_data[i] = insert_obs_to_rtklib(obs_data[i], gnss_observables_iter->second, glonass_gnav_ephemeris_iter->second.d_WN, - 1); //Band 1 (L2) - glo_valid_obs++; + 1);//Band 1 (L2) + found_L1_obs=true; + break; } - } - else // the ephemeris are not available for this SV - { - DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; - } - - + } + if (!found_L1_obs) + { + //insert GLONASS GNAV L2 obs as new obs and also insert its ephemeris + //convert ephemeris from GNSS-SDR class to RTKLIB structure + geph_data[glo_valid_obs] = eph_to_rtklib(glonass_gnav_ephemeris_iter->second, gnav_utc); + //convert observation from GNSS-SDR class to RTKLIB structure + obsd_t newobs = {{0,0}, '0', '0', {}, {}, {}, {}, {}, {}}; + obs_data[glo_valid_obs] = insert_obs_to_rtklib(newobs, + gnss_observables_iter->second, + glonass_gnav_ephemeris_iter->second.d_WN, + 1); //Band 1 (L2) + glo_valid_obs++; } - break; - } + } + else // the ephemeris are not available for this SV + { + DLOG(INFO) << "No ephemeris data for SV " << gnss_observables_iter->second.PRN; + } + + + } + break; + } default : DLOG(INFO) << "Hybrid observables: Unknown GNSS"; break; diff --git a/src/algorithms/PVT/libs/rtklib_solver.h b/src/algorithms/PVT/libs/rtklib_solver.h index 40e0ab250..d8703548e 100644 --- a/src/algorithms/PVT/libs/rtklib_solver.h +++ b/src/algorithms/PVT/libs/rtklib_solver.h @@ -87,7 +87,7 @@ public: std::map galileo_ephemeris_map; //!< Map storing new Galileo_Ephemeris std::map gps_ephemeris_map; //!< Map storing new GPS_Ephemeris std::map gps_cnav_ephemeris_map; //!< Map storing new GPS_CNAV_Ephemeris - std::map glonass_gnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris + std::map glonass_gnav_ephemeris_map; //!< Map storing new GLONASS GNAV Ephmeris Galileo_Utc_Model galileo_utc_model; Galileo_Iono galileo_iono; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.cc b/src/algorithms/libs/rtklib/rtklib_conversions.cc index bf30141d2..8f267454c 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.cc +++ b/src/algorithms/libs/rtklib/rtklib_conversions.cc @@ -45,18 +45,18 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch //Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris switch(gnss_synchro.System) { - case 'G': - rtklib_obs.sat = gnss_synchro.PRN; - break; - case 'E': - rtklib_obs.sat = gnss_synchro.PRN+NSATGPS+NSATGLO; - break; - case 'R': - rtklib_obs.sat = gnss_synchro.PRN+NSATGPS; - break; + case 'G': + rtklib_obs.sat = gnss_synchro.PRN; + break; + case 'E': + rtklib_obs.sat = gnss_synchro.PRN+NSATGPS+NSATGLO; + break; + case 'R': + rtklib_obs.sat = gnss_synchro.PRN+NSATGPS; + break; - default: - rtklib_obs.sat = gnss_synchro.PRN; + default: + rtklib_obs.sat = gnss_synchro.PRN; } rtklib_obs.time = gpst2time(adjgpsweek(week), gnss_synchro.RX_time); rtklib_obs.rcv = 1; @@ -64,14 +64,12 @@ obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synch return rtklib_obs; } - -geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph) +geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const Glonass_Gnav_Utc_Model & gnav_clock_model) { - int week; + double week, sec; + int adj_week; geph_t rtklib_sat = {0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0.0, 0.0, 0.0}, {0.0, 0.0, - 0.0}, {0.0, 0.0, 0.0}, 0.0, 0.0, 0.0}; - gtime_t t_utc; - struct tm utcinfo; + 0.0}, {0.0, 0.0, 0.0}, 0.0, 0.0, 0.0}; rtklib_sat.sat = glonass_gnav_eph.i_satellite_slot_number + NSATGPS; /* satellite number */ rtklib_sat.iode = static_cast(glonass_gnav_eph.d_t_b); /* IODE (0-6 bit of tb field) */ @@ -92,25 +90,15 @@ geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph) rtklib_sat.gamn = glonass_gnav_eph.d_gamma_n; /* SV relative freq bias */ rtklib_sat.age = static_cast(glonass_gnav_eph.d_Delta_tau_n); /* delay between L1 and L2 (s) */ - utcinfo.tm_mon = 0; - utcinfo.tm_mday = glonass_gnav_eph.d_N_T; - utcinfo.tm_year = glonass_gnav_eph.d_yr - 1900; - utcinfo.tm_hour = -6; - utcinfo.tm_min = 0; - utcinfo.tm_sec = glonass_gnav_eph.d_tod; - t_utc.time = mktime(&utcinfo); - t_utc.sec = glonass_gnav_eph.d_tau_c; - rtklib_sat.toe = utc2gpst(t_utc); /* message frame time (gpst) */ + // Time expressed in GPS Time but using RTKLib format + glonass_gnav_eph.glot_to_gpst(glonass_gnav_eph.d_tod, gnav_clock_model.d_tau_c, gnav_clock_model.d_tau_gps, &week, &sec); + adj_week = adjgpsweek(static_cast(week)); + rtklib_sat.toe = gpst2time(adj_week, sec); - utcinfo.tm_mon = 0; - utcinfo.tm_mday = glonass_gnav_eph.d_N_T; - utcinfo.tm_year = glonass_gnav_eph.d_yr - 1900; - utcinfo.tm_hour = -6; - utcinfo.tm_min = 0; - utcinfo.tm_sec = glonass_gnav_eph.d_t_k; - t_utc.time = mktime(&utcinfo); - t_utc.sec = glonass_gnav_eph.d_tau_c; - rtklib_sat.tof = utc2gpst(t_utc); /* message frame time (gpst) */ + // Time expressed in GPS Time but using RTKLib format + glonass_gnav_eph.glot_to_gpst(glonass_gnav_eph.d_t_k, gnav_clock_model.d_tau_c, gnav_clock_model.d_tau_gps, &week, &sec); + adj_week = adjgpsweek(static_cast(week)); + rtklib_sat.tof = gpst2time(adj_week, sec); return rtklib_sat; } @@ -119,7 +107,7 @@ geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph) eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph) { eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; //Galileo is the third satellite system for RTKLIB, so, add the required offset to discriminate Galileo ephemeris rtklib_sat.sat = gal_eph.i_satellite_PRN+NSATGPS+NSATGLO; rtklib_sat.A = gal_eph.A_1 * gal_eph.A_1; @@ -169,7 +157,7 @@ eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph) eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph) { eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; rtklib_sat.sat = gps_eph.i_satellite_PRN; rtklib_sat.A = gps_eph.d_sqrt_A * gps_eph.d_sqrt_A; rtklib_sat.M0 = gps_eph.d_M_0; @@ -220,7 +208,7 @@ eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph) eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph) { eph_t rtklib_sat = {0, 0, 0, 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, {}, 0.0, 0.0 }; rtklib_sat.sat = gps_cnav_eph.i_satellite_PRN; const double A_REF = 26559710.0; // See IS-GPS-200H, pp. 170 rtklib_sat.A = A_REF + gps_cnav_eph.d_DELTA_A; diff --git a/src/algorithms/libs/rtklib/rtklib_conversions.h b/src/algorithms/libs/rtklib/rtklib_conversions.h index e620adaaa..e5a73e88d 100644 --- a/src/algorithms/libs/rtklib/rtklib_conversions.h +++ b/src/algorithms/libs/rtklib/rtklib_conversions.h @@ -37,6 +37,7 @@ #include "gps_ephemeris.h" #include "gps_cnav_ephemeris.h" #include "glonass_gnav_ephemeris.h" +#include "glonass_gnav_utc_model.h" eph_t eph_to_rtklib(const Galileo_Ephemeris & gal_eph); eph_t eph_to_rtklib(const Gps_Ephemeris & gps_eph); @@ -46,7 +47,7 @@ eph_t eph_to_rtklib(const Gps_CNAV_Ephemeris & gps_cnav_eph); * \param glonass_gnav_eph GLONASS GNAV Ephemeris structure * \return Ephemeris structure for RTKLIB parsing */ -geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph); +geph_t eph_to_rtklib(const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const Glonass_Gnav_Utc_Model & gnav_clock_model); obsd_t insert_obs_to_rtklib(obsd_t & rtklib_obs, const Gnss_Synchro & gnss_synchro, int week, int band); diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc index 5a61f5b5a..2edbd447c 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/glonass_l1_ca_telemetry_decoder_cc.cc @@ -221,7 +221,8 @@ void glonass_l1_ca_telemetry_decoder_cc::decode_string(double *frame_symbols,int if(d_nav.flag_update_slot_number == true) { LOG(INFO) << "GLONASS GNAV Slot Number Identified on channel " << d_channel; - d_satellite.what_block(d_satellite.get_system(), d_nav.get_ephemeris().d_n); + d_satellite.update_PRN(d_nav.gnav_ephemeris.d_n); + d_satellite.what_block(d_satellite.get_system(), d_nav.gnav_ephemeris.d_n); d_nav.flag_update_slot_number = false; } } @@ -354,7 +355,8 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work (int noutput_items __attrib if (this->d_flag_preamble == true and d_nav.flag_TOW_new == true) //update TOW at the preamble instant { - d_TOW_at_current_symbol = floor((d_nav.d_TOW - GLONASS_GNAV_PREAMBLE_DURATION_S)*1000.0)/1000.0; + double dummy_dtow = d_nav.get_TOW() - GLONASS_GNAV_PREAMBLE_DURATION_S; + d_TOW_at_current_symbol = d_nav.gnav_ephemeris.d_TOW - GLONASS_GNAV_PREAMBLE_DURATION_S; d_nav.flag_TOW_new = false; } diff --git a/src/core/system_parameters/GLONASS_L1_CA.h b/src/core/system_parameters/GLONASS_L1_CA.h index 83a768c93..4e97fe121 100644 --- a/src/core/system_parameters/GLONASS_L1_CA.h +++ b/src/core/system_parameters/GLONASS_L1_CA.h @@ -91,8 +91,6 @@ const int GLONASS_L1_CA_NBR_SATS = 24; // STRING DATA WITHOUT PREAMB //FIXME Probably should use leap seconds definitions of rtklib const double GLONASS_LEAP_SECONDS[21][7] = { /* leap seconds (y,m,d,h,m,s,utc-gpst) */ - {2019, 1, 1, 0, 0, 0, -20}, - {2018, 1, 1, 0, 0, 0, -19}, {2017, 1, 1, 0, 0, 0, -18}, {2015, 7, 1, 0, 0, 0, -17}, {2012, 7, 1, 0, 0, 0, -16}, @@ -149,7 +147,7 @@ const int GLONASS_L1_CA_HISTORY_DEEP = 100; // NAVIGATION MESSAGE DEMODULATION AND DECODING #define GLONASS_GNAV_PREAMBLE {1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0} -const double GLONASS_GNAV_PREAMBLE_DURATION_S = 0.3; +const double GLONASS_GNAV_PREAMBLE_DURATION_S = 0.300; const int GLONASS_GNAV_PREAMBLE_LENGTH_BITS = 30; const int GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS = 300; const int GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS = 2000; diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.cc b/src/core/system_parameters/glonass_gnav_ephemeris.cc index b7b8e2d3a..43d337cc4 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.cc +++ b/src/core/system_parameters/glonass_gnav_ephemeris.cc @@ -79,20 +79,94 @@ Glonass_Gnav_Ephemeris::Glonass_Gnav_Ephemeris() d_tau_c = 0.0; d_TOW = 0.0; // tow of the start of frame d_WN = 0.0; // week number of the start of frame + d_tod = 0.0; } boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const double offset_time) const { - boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c); + boost::posix_time::time_duration t(0, 0, offset_time + d_tau_c + d_tau_n); boost::gregorian::date d1(d_yr, 1, 1); - boost::gregorian::days d2(d_N_T); + boost::gregorian::days d2(d_N_T - 1); boost::posix_time::ptime glonass_time(d1+d2, t); return glonass_time; } +boost::posix_time::ptime Glonass_Gnav_Ephemeris::glot_to_utc(const double offset_time, const double glot2utc_corr) const +{ + double tod = 0.0; + double utcsu2utc = 3*3600; + double glot2utcsu = 3*3600; + + tod = offset_time - glot2utcsu - utcsu2utc + glot2utc_corr + d_tau_n; + boost::posix_time::time_duration t(0, 0, tod); + boost::gregorian::date d1(d_yr, 1, 1); + boost::gregorian::days d2(d_N_T - 1); + boost::posix_time::ptime utc_time(d1+d2, t); + + return utc_time; +} + +void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, double * wn, double * tow) const +{ + double tod = 0.0; + double dayofweek = 0.0; + double utcsu2utc = 3*3600; + double glot2utcsu = 3*3600; + double days = 0.0; + double total_sec = 0.0, sec_of_day = 0.0; + int i = 0; + boost::gregorian::days d3(0); + + boost::gregorian::date gps_epoch { 1980, 1, 6 }; + + // tk is relative to UTC(SU) + 3.00 hrs, so we need to convert to utc and add corrections + // tk plus 10 sec is the true tod since get_TOW is called when in str5 + tod = tod_offset - glot2utcsu - utcsu2utc; + + + boost::posix_time::time_duration t(0, 0, tod); + boost::gregorian::date d1(d_yr, 1, 1); + boost::gregorian::days d2(d_N_T); + + if(tod < 0) + { + d3 = boost::gregorian::days(-1); + } + + boost::posix_time::ptime glonass_time(d1+d2+d3, t); + boost::gregorian::date utc_date = glonass_time.date(); + + // Total number of days + std::string fdat = boost::posix_time::to_simple_string(glonass_time); + days = static_cast((utc_date - gps_epoch).days()); + + // Total number of seconds + sec_of_day = static_cast((glonass_time.time_of_day()).total_seconds()); + total_sec = days*86400 + sec_of_day; + + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + if (d_yr >= GLONASS_LEAP_SECONDS[i][0]) + { + // We add the leap second when going from utc to gpst + total_sec += fabs(GLONASS_LEAP_SECONDS[i][6]); + break; + } + } + + // Compute Week number + *wn = floor(total_sec/604800); + + // Compute the arithmetic modules to wrap around range + *tow = total_sec - 604800*floor(total_sec/604800); + // Perform corrections from fractional seconds + *tow += glot2utc_corr + glot2gpst_corr; + +} + double Glonass_Gnav_Ephemeris::check_t(double time) { double corrTime; diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.h b/src/core/system_parameters/glonass_gnav_ephemeris.h index 46ece9f95..929fa7262 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.h +++ b/src/core/system_parameters/glonass_gnav_ephemeris.h @@ -159,6 +159,17 @@ public: */ boost::posix_time::ptime compute_GLONASS_time(const double offset_time) const; + /*! + * \brief Converts from GLONASST to UTC + * \ param [I] + * \ param offset_time Is the start of day offset to compute the time + * \ returns UTC time as a boost::posix_time::ptime object + */ + boost::posix_time::ptime glot_to_utc(const double offset_time, const double glot2utc_corr) const; + + + void glot_to_gpst(double tod_offset, double glot2utc_corr, double glot2gpst_corr, double * WN, double * TOW) const; + /*! * Default constructor */ diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.cc b/src/core/system_parameters/glonass_gnav_navigation_message.cc index adb35c141..d87f49f8d 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.cc +++ b/src/core/system_parameters/glonass_gnav_navigation_message.cc @@ -43,6 +43,7 @@ void Glonass_Gnav_Navigation_Message::reset() { //!< Satellite Identification + i_satellite_PRN = 0; i_alm_satellite_slot_number = 0; //!< SV Orbit Slot Number flag_update_slot_number = false; @@ -74,7 +75,6 @@ void Glonass_Gnav_Navigation_Message::reset() //broadcast orbit 1 flag_TOW_set = false; flag_TOW_new = false; - d_TOW = 0.0; //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s] flag_CRC_test = false; d_frame_ID = 0; @@ -325,7 +325,7 @@ double Glonass_Gnav_Navigation_Message::get_WN() boost::gregorian::date gps_epoch { 1980, 1, 6 }; // Map to UTC boost::gregorian::date glo_date(gnav_ephemeris.d_yr, 1, 1); - boost::gregorian::days d2(gnav_ephemeris.d_N_T); + boost::gregorian::days d2(gnav_ephemeris.d_N_T-1); glo_date = glo_date + d2; @@ -363,7 +363,7 @@ double Glonass_Gnav_Navigation_Message::get_TOW() // tk is relative to UTC(SU) + 3.00 hrs, so we need to convert to utc and add corrections // tk plus 10 sec is the true tod since get_TOW is called when in str5 - TOD = (gnav_ephemeris.d_t_k + 10) - glot2utcsu - utcsu2utc + gnav_utc_model.d_tau_c + gnav_utc_model.d_tau_gps; + TOD = (gnav_ephemeris.d_t_k + 10) - glot2utcsu - utcsu2utc;// + gnav_utc_model.d_tau_c + gnav_utc_model.d_tau_gps; boost::gregorian::date glo_date(gnav_ephemeris.d_yr, 1, 1); @@ -375,10 +375,10 @@ double Glonass_Gnav_Navigation_Message::get_TOW() for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) { - if (GLONASS_LEAP_SECONDS[i][0] == gnav_ephemeris.d_yr) + if (gnav_ephemeris.d_yr >= GLONASS_LEAP_SECONDS[i][0]) { // We add the leap second when going from utc to gpst - TOW += GLONASS_LEAP_SECONDS[i][6]; + TOW += fabs(GLONASS_LEAP_SECONDS[i][6]); } } // Compute the arithmetic modules to wrap around range @@ -513,18 +513,18 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) // 3). Set TOW once the year has been defined, it helps with leap second determination if (flag_ephemeris_str_1 == true) - { - d_TOW = get_TOW(); - gnav_ephemeris.d_TOW = d_TOW; - gnav_ephemeris.d_WN = get_WN(); - flag_TOW_set = true; - flag_TOW_new = true; - } + { + gnav_ephemeris.glot_to_gpst(gnav_ephemeris.d_t_k+10, gnav_utc_model.d_tau_c, gnav_utc_model.d_tau_gps, &gnav_ephemeris.d_WN, &gnav_ephemeris.d_TOW); + flag_TOW_set = true; + flag_TOW_new = true; + } // 4) Set time of day (tod) when ephemeris data is complety decoded gnav_ephemeris.d_tod = gnav_ephemeris.d_t_k + 2*d_string_ID; + } + break; case 6: @@ -573,8 +573,8 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_7 = true; } - break; + break; case 8: // --- It is string 8 ---------------------------------------------- i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); @@ -594,7 +594,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_8 = true; break; - case 9: // --- It is string 9 ---------------------------------------------- if (flag_almanac_str_8 == true) @@ -617,7 +616,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_9 = true; } break; - case 10: // --- It is string 10 --------------------------------------------- i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); @@ -660,7 +658,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_11 = true; } break; - case 12: // --- It is string 12 --------------------------------------------- i_alm_satellite_slot_number = static_cast(read_navigation_unsigned(string_bits, n_A)); @@ -702,7 +699,6 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_13 = true; } break; - case 14: // --- It is string 14 --------------------------------------------- if (d_frame_ID == 5) @@ -750,14 +746,15 @@ int Glonass_Gnav_Navigation_Message::string_decoder(std::string frame_string) flag_almanac_str_15 = true; } break; - default: LOG(INFO) << "GLONASS GNAV: Invalid String ID of received. Received " << d_string_ID << ", but acceptable range is from 1-15"; + break; } // switch string ID ... + return d_string_ID; } diff --git a/src/core/system_parameters/glonass_gnav_navigation_message.h b/src/core/system_parameters/glonass_gnav_navigation_message.h index 743f4cefa..062d99693 100644 --- a/src/core/system_parameters/glonass_gnav_navigation_message.h +++ b/src/core/system_parameters/glonass_gnav_navigation_message.h @@ -65,6 +65,10 @@ public: unsigned int d_string_ID; bool flag_update_slot_number; + // satellite identification info + int i_channel_ID; + unsigned int i_satellite_PRN; + Glonass_Gnav_Ephemeris gnav_ephemeris; //!< Ephemeris information decoded Glonass_Gnav_Utc_Model gnav_utc_model; //!< UTC model information Glonass_Gnav_Almanac gnav_almanac[GLONASS_L1_CA_NBR_SATS]; //!< Almanac information for all 24 satellites @@ -97,7 +101,6 @@ public: bool flag_TOW_set; //!< Flag indicating when the TOW has been set bool flag_TOW_new; //!< Flag indicating when a new TOW has been computed - double d_TOW; //!< Time of GPS Week of the ephemeris set (taken from subframes TOW) [s] // Clock terms double d_satClkCorr; // Satellite clock error diff --git a/src/core/system_parameters/gnss_satellite.cc b/src/core/system_parameters/gnss_satellite.cc index 7fb9c38ec..4f96af9f5 100644 --- a/src/core/system_parameters/gnss_satellite.cc +++ b/src/core/system_parameters/gnss_satellite.cc @@ -135,6 +135,27 @@ void Gnss_Satellite::set_system(const std::string& system_) } +void Gnss_Satellite::update_PRN(unsigned int PRN_) +{ + if (system.compare("Glonass") != 0) + { + DLOG(INFO) << "Trying to update PRN for not GLONASS system"; + PRN = 0; + } + else + { + if (PRN_ < 1 or PRN_ > 24) + { + DLOG(INFO) << "This PRN is not defined"; + // Adjusting for PRN 26, now used in + PRN = PRN_; + } + else + { + PRN = PRN_; + } + } +} void Gnss_Satellite::set_PRN(unsigned int PRN_) diff --git a/src/core/system_parameters/gnss_satellite.h b/src/core/system_parameters/gnss_satellite.h index cfdf1369f..1db5691c2 100644 --- a/src/core/system_parameters/gnss_satellite.h +++ b/src/core/system_parameters/gnss_satellite.h @@ -50,6 +50,7 @@ public: Gnss_Satellite(); //!< Default Constructor. Gnss_Satellite(const std::string& system_, unsigned int PRN_); //!< Concrete GNSS satellite Constructor. ~Gnss_Satellite(); //!< Default Destructor. + void update_PRN(unsigned int PRN); //!< Updates the PRN Number when information is decoded, only applies to GLONASS GNAV messages unsigned int get_PRN() const; //!< Gets satellite's PRN std::string get_system() const; //!< Gets the satellite system {"GPS", "GLONASS", "SBAS", "Galileo", "Beidou"} std::string get_system_short() const; //!< Gets the satellite system {"G", "R", "SBAS", "E", "C"} diff --git a/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc b/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc index b87cba16a..1d084ab4b 100644 --- a/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc +++ b/src/tests/unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc @@ -63,3 +63,23 @@ TEST(GlonassGnavEphemerisTest, ComputeGlonassTime) ASSERT_TRUE(expected_gtime.minutes() - t.minutes() < FLT_EPSILON ); ASSERT_TRUE(expected_gtime.seconds() - t.seconds() < FLT_EPSILON ); } + +TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT) +{ + Glonass_Gnav_Ephemeris gnav_eph; + gnav_eph.d_yr = 2005; + gnav_eph.d_N_T = 32; + + double tod = 70200; + double week = 0.0; + double tow = 0.0; + double true_leap_sec = 13; + double true_week = 1307; + double true_tow = 480600+true_leap_sec; + + gnav_eph.glot_to_gpst(tod, 0.0, 0.0, &week, &tow); + + // Perform assertions of decoded fields + ASSERT_TRUE(week - true_week < FLT_EPSILON ); + ASSERT_TRUE(tow - true_week < FLT_EPSILON ); +} diff --git a/src/utils/matlab/hybrid_observables_plot_sample.m b/src/utils/matlab/hybrid_observables_plot_sample.m index 538575bee..45b6bf31d 100644 --- a/src/utils/matlab/hybrid_observables_plot_sample.m +++ b/src/utils/matlab/hybrid_observables_plot_sample.m @@ -41,76 +41,76 @@ title('Doppler frequency') xlabel('TOW [s]') ylabel('[Hz]'); - -%read true obs from simulator (optional) -GPS_STARTOFFSET_s = 68.802e-3; - -true_observables_log_path='/home/javier/git/gnss-sdr/build/obs_out.bin'; -GNSS_true_observables= read_true_sim_observables_dump(true_observables_log_path); - -%correct the clock error using true values (it is not possible for a receiver to correct -%the receiver clock offset error at the observables level because it is required the -%decoding of the ephemeris data and solve the PVT equations) - -SPEED_OF_LIGHT_M_S = 299792458.0; - -%find the reference satellite -[~,ref_sat_ch]=min(GNSS_observables.Pseudorange_m(:,min_idx+1)); -shift_time_s=GNSS_true_observables.Pseudorange_m(ref_sat_ch,:)/SPEED_OF_LIGHT_M_S-GPS_STARTOFFSET_s; - - -%Compute deltas if required and interpolate to measurement time -delta_true_psudorange_m=GNSS_true_observables.Pseudorange_m(1,:)-GNSS_true_observables.Pseudorange_m(2,:); -delta_true_interp_psudorange_m=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... - delta_true_psudorange_m,GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap'); -true_interp_acc_carrier_phase_ch1_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... - GNSS_true_observables.Carrier_phase_hz(1,:),GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap'); -true_interp_acc_carrier_phase_ch2_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... - GNSS_true_observables.Carrier_phase_hz(2,:),GNSS_observables.RX_time(2,min_idx+1:end),'lineal','extrap'); - -%Compute measurement errors - -delta_measured_psudorange_m=GNSS_observables.Pseudorange_m(1,min_idx+1:end)-GNSS_observables.Pseudorange_m(2,min_idx+1:end); -psudorange_error_m=delta_measured_psudorange_m-delta_true_interp_psudorange_m; -psudorange_rms_m=sqrt(sum(psudorange_error_m.^2)/length(psudorange_error_m)) - -acc_carrier_error_ch1_hz=GNSS_observables.Carrier_phase_hz(1,min_idx+1:end)-true_interp_acc_carrier_phase_ch1_hz... - -GNSS_observables.Carrier_phase_hz(1,min_idx+1)+true_interp_acc_carrier_phase_ch1_hz(1); - -acc_phase_rms_ch1_hz=sqrt(sum(acc_carrier_error_ch1_hz.^2)/length(acc_carrier_error_ch1_hz)) - -acc_carrier_error_ch2_hz=GNSS_observables.Carrier_phase_hz(2,min_idx+1:end)-true_interp_acc_carrier_phase_ch2_hz... - -GNSS_observables.Carrier_phase_hz(2,min_idx+1)+true_interp_acc_carrier_phase_ch2_hz(1); -acc_phase_rms_ch2_hz=sqrt(sum(acc_carrier_error_ch2_hz.^2)/length(acc_carrier_error_ch2_hz)) - - -%plot results -figure; -plot(GNSS_true_observables.RX_time(1,:),delta_true_psudorange_m,'g'); -hold on; -plot(GNSS_observables.RX_time(1,min_idx+1:end),delta_measured_psudorange_m,'b'); -title('TRUE vs. measured Pseudoranges [m]') -xlabel('TOW [s]') -ylabel('[m]'); - -figure; -plot(GNSS_observables.RX_time(1,min_idx+1:end),psudorange_error_m) -title('Pseudoranges error [m]') -xlabel('TOW [s]') -ylabel('[m]'); - -figure; -plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch1_hz) -title('Accumulated carrier phase error CH1 [hz]') -xlabel('TOW [s]') -ylabel('[hz]'); - -figure; -plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch2_hz) -title('Accumulated carrier phase error CH2 [hz]') -xlabel('TOW [s]') -ylabel('[hz]'); - - - - +% +% %read true obs from simulator (optional) +% GPS_STARTOFFSET_s = 68.802e-3; +% +% true_observables_log_path='/home/javier/git/gnss-sdr/build/obs_out.bin'; +% GNSS_true_observables= read_true_sim_observables_dump(true_observables_log_path); +% +% %correct the clock error using true values (it is not possible for a receiver to correct +% %the receiver clock offset error at the observables level because it is required the +% %decoding of the ephemeris data and solve the PVT equations) +% +% SPEED_OF_LIGHT_M_S = 299792458.0; +% +% %find the reference satellite +% [~,ref_sat_ch]=min(GNSS_observables.Pseudorange_m(:,min_idx+1)); +% shift_time_s=GNSS_true_observables.Pseudorange_m(ref_sat_ch,:)/SPEED_OF_LIGHT_M_S-GPS_STARTOFFSET_s; +% +% +% %Compute deltas if required and interpolate to measurement time +% delta_true_psudorange_m=GNSS_true_observables.Pseudorange_m(1,:)-GNSS_true_observables.Pseudorange_m(2,:); +% delta_true_interp_psudorange_m=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... +% delta_true_psudorange_m,GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap'); +% true_interp_acc_carrier_phase_ch1_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... +% GNSS_true_observables.Carrier_phase_hz(1,:),GNSS_observables.RX_time(1,min_idx+1:end),'lineal','extrap'); +% true_interp_acc_carrier_phase_ch2_hz=interp1(GNSS_true_observables.RX_time(1,:)-shift_time_s, ... +% GNSS_true_observables.Carrier_phase_hz(2,:),GNSS_observables.RX_time(2,min_idx+1:end),'lineal','extrap'); +% +% %Compute measurement errors +% +% delta_measured_psudorange_m=GNSS_observables.Pseudorange_m(1,min_idx+1:end)-GNSS_observables.Pseudorange_m(2,min_idx+1:end); +% psudorange_error_m=delta_measured_psudorange_m-delta_true_interp_psudorange_m; +% psudorange_rms_m=sqrt(sum(psudorange_error_m.^2)/length(psudorange_error_m)) +% +% acc_carrier_error_ch1_hz=GNSS_observables.Carrier_phase_hz(1,min_idx+1:end)-true_interp_acc_carrier_phase_ch1_hz... +% -GNSS_observables.Carrier_phase_hz(1,min_idx+1)+true_interp_acc_carrier_phase_ch1_hz(1); +% +% acc_phase_rms_ch1_hz=sqrt(sum(acc_carrier_error_ch1_hz.^2)/length(acc_carrier_error_ch1_hz)) +% +% acc_carrier_error_ch2_hz=GNSS_observables.Carrier_phase_hz(2,min_idx+1:end)-true_interp_acc_carrier_phase_ch2_hz... +% -GNSS_observables.Carrier_phase_hz(2,min_idx+1)+true_interp_acc_carrier_phase_ch2_hz(1); +% acc_phase_rms_ch2_hz=sqrt(sum(acc_carrier_error_ch2_hz.^2)/length(acc_carrier_error_ch2_hz)) +% +% +% %plot results +% figure; +% plot(GNSS_true_observables.RX_time(1,:),delta_true_psudorange_m,'g'); +% hold on; +% plot(GNSS_observables.RX_time(1,min_idx+1:end),delta_measured_psudorange_m,'b'); +% title('TRUE vs. measured Pseudoranges [m]') +% xlabel('TOW [s]') +% ylabel('[m]'); +% +% figure; +% plot(GNSS_observables.RX_time(1,min_idx+1:end),psudorange_error_m) +% title('Pseudoranges error [m]') +% xlabel('TOW [s]') +% ylabel('[m]'); +% +% figure; +% plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch1_hz) +% title('Accumulated carrier phase error CH1 [hz]') +% xlabel('TOW [s]') +% ylabel('[hz]'); +% +% figure; +% plot(GNSS_observables.RX_time(1,min_idx+1:end),acc_carrier_error_ch2_hz) +% title('Accumulated carrier phase error CH2 [hz]') +% xlabel('TOW [s]') +% ylabel('[hz]'); +% +% +% +%