From f85887ee10b93fdd3d212c995f870c96c39b7495 Mon Sep 17 00:00:00 2001 From: Damian Miralles Date: Fri, 22 Dec 2017 15:08:54 -0700 Subject: [PATCH 1/5] glonass pvt: Fix bug when in PPP_Static mode Fixes a bug in trk module to provide right observables for position solution computation using the accumulated carrier phase measurements. --- conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf | 8 ++++---- conf/gnss-sdr_GPS_L1_CA_ibyte.conf | 2 +- .../glonass_l1_ca_dll_pll_tracking_cc.cc | 14 +++++++------- .../glonass_l1_ca_dll_pll_tracking_cc.h | 1 + 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf b/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf index d6cbbf891..e5e3e4d3a 100644 --- a/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf +++ b/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf @@ -27,7 +27,7 @@ Resampler.item_type=gr_complex ;######### CHANNELS GLOBAL CONFIG ############ Channel.signal=1G Channels.in_acquisition=1 -Channels_1G.count=8 +Channels_1G.count=5 Channel0.satellite=24 ; k= Channel1.satellite=1 ; k=1 @@ -43,9 +43,9 @@ Acquisition_1G.pfa=0.0001 Acquisition_1G.if=0 Acquisition_1G.doppler_max=10000 Acquisition_1G.doppler_step=250 -Acquisition_1G.dump=true; +Acquisition_1G.dump=false; Acquisition_1G.dump_filename=/archive/glo_acquisition.dat -Acquisition_1G.coherent_integration_time_ms=1 +;Acquisition_1G.coherent_integration_time_ms=1 ;Acquisition_1G.max_dwells = 5 ;######### TRACKING GLOBAL CONFIG ############ @@ -72,7 +72,7 @@ PVT.positioning_mode=Single PVT.output_rate_ms=100 PVT.display_rate_ms=500 PVT.trop_model=Saastamoinen -PVT.flag_rtcm_server=true +PVT.flag_rtcm_server=false PVT.flag_rtcm_tty_port=false PVT.rtcm_dump_devname=/dev/pts/1 PVT.rtcm_tcp_port=2101 diff --git a/conf/gnss-sdr_GPS_L1_CA_ibyte.conf b/conf/gnss-sdr_GPS_L1_CA_ibyte.conf index ecb652dca..9de3c4e6b 100644 --- a/conf/gnss-sdr_GPS_L1_CA_ibyte.conf +++ b/conf/gnss-sdr_GPS_L1_CA_ibyte.conf @@ -78,7 +78,7 @@ Observables.dump_filename=/archive/gps_observables.dat ;######### PVT CONFIG ############ PVT.implementation=RTKLIB_PVT -PVT.positioning_mode=Single +PVT.positioning_mode=PPP_Static PVT.output_rate_ms=100 PVT.display_rate_ms=500 PVT.trop_model=Saastamoinen diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc index 89c6b5cfe..c7926ac3b 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.cc @@ -54,9 +54,6 @@ #include "control_message_factory.h" -/*! - * \todo Include in definition header file - */ #define CN0_ESTIMATION_SAMPLES 10 #define MINIMUM_VALID_CN0 25 #define MAXIMUM_LOCK_FAIL_COUNTER 50 @@ -175,6 +172,7 @@ Glonass_L1_Ca_Dll_Pll_Tracking_cc::Glonass_L1_Ca_Dll_Pll_Tracking_cc( d_acq_code_phase_samples = 0.0; d_acq_carrier_doppler_hz = 0.0; d_carrier_doppler_hz = 0.0; + d_carrier_doppler_phase_step_rad = 0.0; d_carrier_frequency_hz = 0.0; d_acc_carrier_phase_rad = 0.0; d_code_phase_samples = 0.0; @@ -235,6 +233,7 @@ void Glonass_L1_Ca_Dll_Pll_Tracking_cc::start_tracking() d_carrier_frequency_hz = d_acq_carrier_doppler_hz + d_if_freq + (DFRQ1_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN)); d_carrier_doppler_hz = d_acq_carrier_doppler_hz; d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast(d_fs_in); + d_carrier_doppler_phase_step_rad = GLONASS_TWO_PI * (d_carrier_doppler_hz) / static_cast(d_fs_in); // DLL/PLL filter initialization d_carrier_loop_filter.initialize(); // initialize the carrier filter @@ -554,9 +553,9 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribu d_sample_counter = d_sample_counter + samples_offset; // count for the processed samples d_pull_in = false; // take into account the carrier cycles accumulated in the pull in signal alignment - d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * samples_offset; + d_acc_carrier_phase_rad -= d_carrier_doppler_phase_step_rad * samples_offset; current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = d_carrier_frequency_hz; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; current_synchro_data.fs = d_fs_in; current_synchro_data.correlation_length_ms = 1; *out[0] = current_synchro_data; @@ -605,12 +604,13 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribu //################### PLL COMMANDS ################################################# // carrier phase step (NCO phase increment per sample) [rads/sample] + d_carrier_doppler_phase_step_rad = GLONASS_TWO_PI * d_carrier_doppler_hz / static_cast(d_fs_in); d_carrier_phase_step_rad = GLONASS_TWO_PI * d_carrier_frequency_hz / static_cast(d_fs_in); // remnant carrier phase to prevent overflow in the code NCO d_rem_carr_phase_rad = d_rem_carr_phase_rad + d_carrier_phase_step_rad * d_current_prn_length_samples; d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, GLONASS_TWO_PI); // carrier phase accumulator - d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * d_current_prn_length_samples; + d_acc_carrier_phase_rad -= d_carrier_doppler_phase_step_rad * d_current_prn_length_samples; //################### DLL COMMANDS ################################################# // code phase step (Code resampler phase increment per sample) [chips/sample] @@ -657,7 +657,7 @@ int Glonass_L1_Ca_Dll_Pll_Tracking_cc::general_work (int noutput_items __attribu current_synchro_data.Tracking_sample_counter = d_sample_counter + d_current_prn_length_samples; current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = d_carrier_frequency_hz; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; current_synchro_data.Flag_valid_symbol_output = true; current_synchro_data.correlation_length_ms = 1; diff --git a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h index 4e080fae2..3e7a0cb14 100644 --- a/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/glonass_l1_ca_dll_pll_tracking_cc.h @@ -140,6 +140,7 @@ private: double d_code_freq_chips; double d_code_phase_step_chips; double d_carrier_doppler_hz; + double d_carrier_doppler_phase_step_rad; double d_carrier_frequency_hz; double d_carrier_phase_step_rad; double d_acc_carrier_phase_rad; From ad07c8940b88cc17dec29ae25f0db25181dd5769 Mon Sep 17 00:00:00 2001 From: Damian Miralles Date: Mon, 25 Dec 2017 17:05:35 -0700 Subject: [PATCH 2/5] glonass_rinex: Fixes bugs in RINEX files for GLONASS processing Fixes bugs with observation and navigation header time logs. It forces the log to be in UTC time as the dault when in GLONASS. --- .../PVT/gnuradio_blocks/rtklib_pvt_cc.cc | 8 +- src/algorithms/PVT/libs/rinex_printer.cc | 159 +++++++++++------- src/algorithms/PVT/libs/rinex_printer.h | 12 +- .../glonass_gnav_ephemeris.cc | 90 +++++----- 4 files changed, 156 insertions(+), 113 deletions(-) diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index b4a312895..6c2936e21 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -843,7 +843,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) { rp->rinex_obs_header(rp->obsFile, glonass_gnav_ephemeris_iter->second, d_rx_time, signal); - rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); b_rinex_header_written = true; // do not write header anymore } } @@ -852,8 +852,8 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite std::string signal("2G"); if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) { - rp->rinex_obs_header(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time, signal); - rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + rp->rinex_obs_header(rp->obsFile, glonass_gnav_ephemeris_iter->second, d_rx_time, signal); + rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); b_rinex_header_written = true; // do not write header anymore } } @@ -863,7 +863,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite if (glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) { rp->rinex_obs_header(rp->obsFile, glonass_gnav_ephemeris_iter->second, d_rx_time, signal); - rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); b_rinex_header_written = true; // do not write header anymore } } diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index 555ccc728..3e5b8fd97 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -143,6 +143,7 @@ Rinex_Printer::Rinex_Printer(int conf_version) observationType["DOPPLER_v2"] = "D"; observationType["SIGNAL_STRENGTH_v2"] = "S"; observationCode["GPS_L1_CA_v2"] = "1"; + observationCode["GLONASS_G1_CA_v2"] = "1"; if ( FLAGS_RINEX_version.compare("3.01") == 0 ) { @@ -415,9 +416,8 @@ std::string Rinex_Printer::getLocalTime() } -void Rinex_Printer::rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) +void Rinex_Printer::rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Ephemeris& glonass_gnav_eph) { - if(glonass_gnav_almanac.i_satellite_freq_channel){} std::string line; // -------- Line 1 @@ -464,44 +464,53 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_M out << line << std::endl; // -------- Line system time correction - line.clear(); - line += std::string("GLUT"); - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_c, 16, 2), 17); - line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); - line += std::string(10, ' '); - line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + if (version == 3) + { + line.clear(); + line += std::string("GLUT"); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_c, 16, 2), 17); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line += std::string(10, ' '); + line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - // -------- Line system time correction 2 - line.clear(); - line += std::string("GLGP"); - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_gps, 16, 2), 17); - line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); - line += std::string(10, ' '); - line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + // -------- Line system time correction 2 + line.clear(); + line += std::string("GLGP"); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_gps, 16, 2), 17); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line += std::string(10, ' '); + line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } + if (version == 2) + { + // Set reference time and its clock corrections + boost::posix_time::ptime p_utc_ref_time = glonass_gnav_eph.glot_to_utc(glonass_gnav_eph.d_t_b, 0.0); + std::string timestring = boost::posix_time::to_iso_string(p_utc_ref_time); + std::string year (timestring, 0, 4); + std::string month (timestring, 4, 2); + std::string day (timestring, 6, 2); - - // -------- Line 6 leap seconds - // For leap second information, see http://www.endruntechnologies.com/leap.htm - line.clear(); - // TODO hOW TO MAKE THIS IN GLONASS, the leap second is internally given - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 6); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 6); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 6); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 6); - line += std::string(36, ' '); - line += Rinex_Printer::leftJustify("LEAP SECONDS", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + line.clear(); + line += Rinex_Printer::rightJustify(year, 6); + line += Rinex_Printer::rightJustify(month, 6); + line += Rinex_Printer::rightJustify(day, 6); + line += std::string(3, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_c, 16, 2), 19); + line += std::string(20, ' '); + line += Rinex_Printer::leftJustify("CORR TO SYSTEM TIME", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } // -------- End of Header line.clear(); @@ -511,7 +520,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Glonass_Gnav_Utc_M out << line << std::endl; } - void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -1391,6 +1399,7 @@ void Rinex_Printer::rinex_sbs_header(std::fstream& out) } + void Rinex_Printer::update_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -2144,6 +2153,7 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& gal } + void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& eph_map) { std::string line; @@ -2827,7 +2837,7 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::mapsecond, glonass_gnav_ephemeris_iter->second.d_t_k); + boost::posix_time::ptime p_utc_time = glonass_gnav_ephemeris_iter->second.glot_to_utc(glonass_gnav_ephemeris_iter->second.d_t_b, 0.0); std::string timestring = boost::posix_time::to_iso_string(p_utc_time); std::string month (timestring, 4, 2); std::string day (timestring, 6, 2); @@ -3017,7 +3027,6 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& gps_eph_map, const std::map& galileo_eph_map) { version = 3; @@ -3045,6 +3054,7 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& observables, const std::string glonass_band) { // RINEX observations timestamps are GPS timestamps. @@ -5416,7 +5428,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri // Avoid compiler warning if(glonass_band.size()){} - boost::posix_time::ptime p_glonass_time = Rinex_Printer::compute_GLONASS_time(eph, obs_time); + boost::posix_time::ptime p_glonass_time = Rinex_Printer::compute_UTC_time(eph, obs_time); std::string timestring = boost::posix_time::to_iso_string(p_glonass_time); //double utc_t = nav_msg.utc_time(nav_msg.sv_clock_correction(obs_time)); //double gps_t = eph.sv_clock_correction(obs_time); @@ -5499,7 +5511,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri std::string lineObs; lineObs.clear(); line.clear(); - // GPS L1 PSEUDORANGE + // GLONASS L1 PSEUDORANGE line += std::string(2, ' '); lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Pseudorange_m, 3), 14); @@ -5517,8 +5529,8 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri // Signal Strength Indicator (SSI) int ssi = Rinex_Printer::signalStrength(observables_iter->second.CN0_dB_hz); lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - // GPS L1 CA PHASE - lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_phase_rads/GPS_TWO_PI, 3), 14); + // GLONASS L1 CA PHASE + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_phase_rads/GLONASS_TWO_PI, 3), 14); if (lli == 0) { lineObs += std::string(1, ' '); @@ -5528,7 +5540,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); } lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - // GPS L1 CA DOPPLER + // GLONASS L1 CA DOPPLER lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_Doppler_hz, 3), 14); if (lli == 0) { @@ -5539,7 +5551,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); } lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - //GPS L1 SIGNAL STRENGTH + //GLONASS L1 SIGNAL STRENGTH lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.CN0_dB_hz, 3), 14); if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); out << lineObs << std::endl; @@ -5653,9 +5665,6 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Glonass_Gnav_Ephemeri } - - - void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double gps_obs_time, const std::map& observables) { if(glonass_gnav_eph.d_m){} // avoid warning, not needed @@ -7171,6 +7180,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_ep } + void Rinex_Printer::to_date_time(int gps_week, int gps_tow, int &year, int &month, int &day, int &hour, int &minute, int &second) { // represents GPS time (week, TOW) in the date time format of the Gregorian calendar. @@ -7381,11 +7391,42 @@ boost::posix_time::ptime Rinex_Printer::compute_Galileo_time(const Galileo_Ephem } -boost::posix_time::ptime Rinex_Printer::compute_GLONASS_time(const Glonass_Gnav_Ephemeris& eph, const double obs_time) +boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephemeris& eph, const double obs_time) { - boost::posix_time::ptime p_time = eph.compute_GLONASS_time(obs_time); - return p_time; + double tod = 0.0; + double glot2utc = 3*3600; + double obs_time_utc = 0.0, obs_time_glot = 0.0; + int i = 0; + + // GLONASST already includes leap second addition or deletion + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + if (eph.d_yr >= GLONASS_LEAP_SECONDS[i][0]) + { + // We substract the leap second when going from gpst to utc + obs_time_utc = obs_time - fabs(GLONASS_LEAP_SECONDS[i][6]); + break; + } + } + // Get observation time in GLONASS time + obs_time_glot = obs_time_utc + glot2utc; + + // Get seconds of day in glonass time + tod = fmod (obs_time_glot, 86400); + + // Form date and time duration types + boost::posix_time::time_duration t1(0, 0, tod); + boost::gregorian::date d1(eph.d_yr, 1, 1); + boost::gregorian::days d2(eph.d_N_T-1); + boost::posix_time::ptime glo_time(d1 + d2, t1); + + // Convert to utc + boost::posix_time::time_duration t2(0, 0, glot2utc); + boost::posix_time::ptime utc_time = glo_time - t2; + + return utc_time; } + /* enum RINEX_enumMarkerType { diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index 901fd0a60..74f7b1262 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -116,7 +116,7 @@ public: /*! * \brief Generates the GLONASS L1, L2 C/A Navigation Data header */ - void rinex_nav_header(std::fstream & out, const Glonass_Gnav_Utc_Model & utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); + void rinex_nav_header(std::fstream & out, const Glonass_Gnav_Utc_Model & utc_model, const Glonass_Gnav_Ephemeris & glonass_gnav_eph); /*! * \brief Generates the Mixed (Galileo/GLONASS) Navigation Data header @@ -194,9 +194,13 @@ public: boost::posix_time::ptime compute_Galileo_time(const Galileo_Ephemeris & eph, const double obs_time); /*! - * \brief Computes the GLONASS System Time and returns a boost::posix_time::ptime object - */ - boost::posix_time::ptime compute_GLONASS_time(const Glonass_Gnav_Ephemeris & eph, const double obs_time); + * \brief Computes the UTC Time and returns a boost::posix_time::ptime object + * \details Function used as a method to convert the observation time into UTC time which is used + * as the default time for RINEX files + * \param eph GLONASS GNAV Ephemeris object + * \param obs_time Observation time in GPS seconds of week + */ + boost::posix_time::ptime compute_UTC_time(const Glonass_Gnav_Ephemeris & eph, const double obs_time); /*! * \brief Writes data from the GPS L1 C/A navigation message into the RINEX file diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.cc b/src/core/system_parameters/glonass_gnav_ephemeris.cc index c557c6a6f..2ac9294db 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.cc +++ b/src/core/system_parameters/glonass_gnav_ephemeris.cc @@ -82,7 +82,6 @@ Glonass_Gnav_Ephemeris::Glonass_Gnav_Ephemeris() 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 + d_tau_n); @@ -93,68 +92,67 @@ boost::posix_time::ptime Glonass_Gnav_Ephemeris::compute_GLONASS_time(const doub 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 glot2utc = 3*3600; + double tod = 0.0; + double glot2utc = 3*3600; - tod = offset_time - glot2utc + 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); + tod = offset_time - glot2utc + 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; + 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 glot2utc = 3*3600; - double days = 0.0; - double total_sec = 0.0, sec_of_day = 0.0; - int i = 0; + double tod = 0.0; + double glot2utc = 3*3600; + double days = 0.0; + double total_sec = 0.0, sec_of_day = 0.0; + int i = 0; - boost::gregorian::date gps_epoch { 1980, 1, 6 }; + 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 - glot2utc ; + // 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 - glot2utc ; - 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 glonass_time(d1+d2, t); - boost::gregorian::date utc_date = glonass_time.date(); + 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 glonass_time(d1+d2, 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 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; + // Total number of seconds + sec_of_day = static_cast((glonass_time.time_of_day()).total_seconds()); + total_sec = days*86400 + sec_of_day; - // GLONASST already includes leap second addition or deletion - 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; - } - } + // GLONASST already includes leap second addition or deletion + 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 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; + // 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; } From aa2464cc28631b40cec925eb52eba7c1c8f41e44 Mon Sep 17 00:00:00 2001 From: Damian Miralles Date: Tue, 26 Dec 2017 10:29:09 -0700 Subject: [PATCH 3/5] glonass bug fix: Adds more reliable GPST 2 UTC conversion Adds logic to check for exact epoch when performing leap second correction and also fixes unit test in code for GLONASS --- src/algorithms/PVT/libs/rinex_printer.cc | 28 ++++++++------- src/algorithms/PVT/libs/rinex_printer.h | 2 +- src/core/system_parameters/GLONASS_L1_CA.h | 12 ++++--- .../glonass_gnav_ephemeris.cc | 34 +++++++++++-------- .../pvt/rinex_printer_test.cc | 5 +-- .../glonass_gnav_ephemeris_test.cc | 2 +- .../glonass_gnav_nav_message_test.cc | 3 ++ 7 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index 3e5b8fd97..0a14e63cb 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -7398,18 +7398,8 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephe double obs_time_utc = 0.0, obs_time_glot = 0.0; int i = 0; - // GLONASST already includes leap second addition or deletion - for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) - { - if (eph.d_yr >= GLONASS_LEAP_SECONDS[i][0]) - { - // We substract the leap second when going from gpst to utc - obs_time_utc = obs_time - fabs(GLONASS_LEAP_SECONDS[i][6]); - break; - } - } - // Get observation time in GLONASS time - obs_time_glot = obs_time_utc + glot2utc; + // Get observation time in nearly GLONASS time. Correction for leap seconds done at the end + obs_time_glot = obs_time + glot2utc; // Get seconds of day in glonass time tod = fmod (obs_time_glot, 86400); @@ -7424,6 +7414,20 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephe boost::posix_time::time_duration t2(0, 0, glot2utc); boost::posix_time::ptime utc_time = glo_time - t2; + // Adjust for leap second correction + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]); + boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]); + boost::posix_time::ptime ls_time(d3, t3); + if (utc_time >= ls_time) + { + // We subtract the leap second when going from gpst to utc + utc_time = utc_time - boost::posix_time::time_duration(0,0,fabs(GLONASS_LEAP_SECONDS[i][6])); + break; + } + } + return utc_time; } diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index 74f7b1262..f061a93f4 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -156,7 +156,7 @@ public: /*! * \brief Generates the GLONASS GNAV Observation data header. Example: bands("1C"), bands("1C 2C"), bands("2C"), ... Default: "1C". */ - void rinex_obs_header(std::fstream & out, const Glonass_Gnav_Ephemeris & eph, const double d_TOW_first_observation, const std::string bands = "1C"); + void rinex_obs_header(std::fstream & out, const Glonass_Gnav_Ephemeris & eph, const double d_TOW_first_observation, const std::string bands = "1G"); /*! * \brief Generates the Mixed (GPS L1 C/A /GLONASS) Observation data header. Example: galileo_bands("1C"), galileo_bands("1B 5X"), galileo_bands("5X"), ... Default: "1B". diff --git a/src/core/system_parameters/GLONASS_L1_CA.h b/src/core/system_parameters/GLONASS_L1_CA.h index 4e97fe121..28c634ff3 100644 --- a/src/core/system_parameters/GLONASS_L1_CA.h +++ b/src/core/system_parameters/GLONASS_L1_CA.h @@ -89,8 +89,12 @@ const double GLONASS_L1_CA_CHIP_PERIOD = 1.9569e-06; //!< GLONASS L1 C/ const double GLONASS_L1_CA_SYMBOL_RATE_BPS = 1000; const int GLONASS_L1_CA_NBR_SATS = 24; // STRING DATA WITHOUT PREAMBLE -//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) */ +/*! + * \brief Record of leap seconds definition for GLOT to GPST conversion and vice versa + * \details Each entry is defined by an array of 7 elements consisting of yr,month,day,hr,min,sec,utc-gpst + * \note Ideally should use leap seconds definitions of rtklib + */ +const double GLONASS_LEAP_SECONDS[19][7] = { {2017, 1, 1, 0, 0, 0, -18}, {2015, 7, 1, 0, 0, 0, -17}, {2012, 7, 1, 0, 0, 0, -16}, @@ -112,7 +116,7 @@ const double GLONASS_LEAP_SECONDS[21][7] = { /* leap seconds (y,m,d,h,m,s,utc-gp {} }; -// GLONASS SV's orbital slots PRN = (orbital_slot - 1) +//!< GLONASS SV's orbital slots PRN = (orbital_slot - 1) const std::map GLONASS_PRN = {{ 0, 8,}, //For test { 1, 1,}, //Plane 1 @@ -134,7 +138,7 @@ const std::map GLONASS_PRN = {17, 4,}, //Plane 3 {18,-3,}, //Plane 3 {19, 3,}, //Plane 3 - {20, -5,}, //Plane 3 + {20,-5,}, //Plane 3 {21, 4,}, //Plane 3 {22,-3,}, //Plane 3 {23, 3,}, //Plane 3 diff --git a/src/core/system_parameters/glonass_gnav_ephemeris.cc b/src/core/system_parameters/glonass_gnav_ephemeris.cc index 2ac9294db..6cd530c59 100644 --- a/src/core/system_parameters/glonass_gnav_ephemeris.cc +++ b/src/core/system_parameters/glonass_gnav_ephemeris.cc @@ -124,28 +124,32 @@ void Glonass_Gnav_Ephemeris::glot_to_gpst(double tod_offset, double glot2utc_cor 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 glonass_time(d1+d2, t); - boost::gregorian::date utc_date = glonass_time.date(); + boost::posix_time::ptime utc_time(d1+d2, t); + boost::gregorian::date utc_date = utc_time.date(); + boost::posix_time::ptime gps_time; + + // Adjust for leap second correction + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]); + boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]); + boost::posix_time::ptime ls_time(d3, t3); + if (utc_time >= ls_time) + { + // We add the leap second when going from utc to gpst + gps_time = utc_time + boost::posix_time::time_duration(0,0,fabs(GLONASS_LEAP_SECONDS[i][6])); + break; + } + } // Total number of days - std::string fdat = boost::posix_time::to_simple_string(glonass_time); + std::string fdat = boost::posix_time::to_simple_string(gps_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()); + sec_of_day = static_cast((gps_time.time_of_day()).total_seconds()); total_sec = days*86400 + sec_of_day; - // GLONASST already includes leap second addition or deletion - 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); diff --git a/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc b/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc index 33ed3965c..ceb2d8373 100644 --- a/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/pvt/rinex_printer_test.cc @@ -95,8 +95,9 @@ TEST(RinexPrinterTest, GlonassObsHeader) const Glonass_Gnav_Ephemeris eph = Glonass_Gnav_Ephemeris(); std::shared_ptr rp1; - rp1 = std::make_shared(); - rp1->rinex_obs_header(rp1->obsFile, eph, 0.0); + rp1 = std::make_shared(3); + const std::string bands = "1G"; + rp1->rinex_obs_header(rp1->obsFile, eph, 0.0, bands); rp1->obsFile.seekp(0); while(!rp1->obsFile.eof()) 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 da5571399..7026903e2 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 @@ -130,7 +130,7 @@ TEST(GlonassGnavEphemerisTest, ConvertGlonassT2GpsT3) double tow = 0.0; double true_leap_sec = 17; double true_week = 1886; - double true_tow = 259200+true_leap_sec; + double true_tow = 259200+true_leap_sec+tod; gnav_eph.glot_to_gpst(tod + glo2utc, 0.0, 0.0, &week, &tow); diff --git a/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc b/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc index 5fabb4676..595b1fa2f 100644 --- a/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc +++ b/src/tests/unit-tests/system-parameters/glonass_gnav_nav_message_test.cc @@ -172,6 +172,7 @@ TEST(GlonassGnavNavigationMessageTest, String3Decoder) gnav_ephemeris.d_Zn = 19929.2377929688; // Call target test method + gnav_nav_message.flag_ephemeris_str_2 = true; gnav_nav_message.string_decoder(str3); // Perform assertions of decoded fields @@ -209,6 +210,7 @@ TEST(GlonassGnavNavigationMessageTest, String4Decoder) gnav_ephemeris.d_M = 1; // Call target test method + gnav_nav_message.flag_ephemeris_str_3 = true; gnav_nav_message.string_decoder(str4); // Perform assertions of decoded fields @@ -243,6 +245,7 @@ TEST(GlonassGnavNavigationMessageTest, String5Decoder) gnav_utc_model.d_tau_gps = 9.313225746154785e-08; // Call target test method + gnav_nav_message.flag_ephemeris_str_4 = true; gnav_nav_message.string_decoder(str5); // Perform assertions of decoded fields From 78eaa76a6097a6a663002fd784077d7388382a2f Mon Sep 17 00:00:00 2001 From: Damian Miralles Date: Wed, 27 Dec 2017 11:57:25 -0700 Subject: [PATCH 4/5] glonass rinex: Bug fixes in RINEX formats 2.11 and 3.02 Fixes a couple of bugs for RINEX file generation depending on the active version to be use. --- conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf | 6 +- conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf | 8 +- conf/gnss-sdr_GPS_L1_CA_ibyte.conf | 2 +- .../PVT/gnuradio_blocks/rtklib_pvt_cc.cc | 22 +- .../PVT/gnuradio_blocks/rtklib_pvt_cc.h | 1 + src/algorithms/PVT/libs/rinex_printer.cc | 881 +++++++++++------- src/algorithms/PVT/libs/rinex_printer.h | 7 + 7 files changed, 566 insertions(+), 361 deletions(-) diff --git a/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf b/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf index e5e3e4d3a..4d51b83a1 100644 --- a/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf +++ b/conf/gnss-sdr_GLONASS_L1_CA_ibyte.conf @@ -55,7 +55,7 @@ Tracking_1G.if=0 Tracking_1G.early_late_space_chips=0.5 Tracking_1G.pll_bw_hz=25.0; Tracking_1G.dll_bw_hz=3.0; -Tracking_1G.dump=true; +Tracking_1G.dump=false; Tracking_1G.dump_filename=/archive/glo_tracking_ch_ ;######### TELEMETRY DECODER GPS CONFIG ############ @@ -63,7 +63,7 @@ TelemetryDecoder_1G.implementation=GLONASS_L1_CA_Telemetry_Decoder ;######### OBSERVABLES CONFIG ############ Observables.implementation=Hybrid_Observables -Observables.dump=true; +Observables.dump=false; Observables.dump_filename=/archive/glo_observables.dat ;######### PVT CONFIG ############ @@ -80,4 +80,4 @@ PVT.rtcm_MT1019_rate_ms=5000 PVT.rtcm_MT1045_rate_ms=5000 PVT.rtcm_MT1097_rate_ms=1000 PVT.rtcm_MT1077_rate_ms=1000 -PVT.rinex_version=2 +PVT.rinex_version=3 diff --git a/conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf b/conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf index 0435d6ff2..ffabae821 100644 --- a/conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf +++ b/conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf @@ -107,7 +107,7 @@ Tracking_1C.if=0 Tracking_1C.early_late_space_chips=0.5 Tracking_1C.pll_bw_hz=20.0; Tracking_1C.dll_bw_hz=2.0; -Tracking_1C.dump=true; +Tracking_1C.dump=false; Tracking_1C.dump_filename=/archive/gps_tracking_ch_ Tracking_1G.implementation=GLONASS_L1_CA_DLL_PLL_Tracking @@ -125,7 +125,7 @@ TelemetryDecoder_1G.implementation=GLONASS_L1_CA_Telemetry_Decoder ;######### OBSERVABLES CONFIG ############ Observables.implementation=Hybrid_Observables -Observables.dump=true; +Observables.dump=false; Observables.dump_filename=/archive/gnss_observables.dat ;######### PVT CONFIG ############ @@ -133,7 +133,7 @@ PVT.implementation=RTKLIB_PVT PVT.output_rate_ms=100 PVT.display_rate_ms=500 PVT.trop_model=Saastamoinen -PVT.flag_rtcm_server=true +PVT.flag_rtcm_server=false PVT.flag_rtcm_tty_port=false PVT.rtcm_dump_devname=/dev/pts/1 PVT.rtcm_tcp_port=2101 @@ -141,4 +141,4 @@ PVT.rtcm_MT1019_rate_ms=5000 PVT.rtcm_MT1045_rate_ms=5000 PVT.rtcm_MT1097_rate_ms=1000 PVT.rtcm_MT1077_rate_ms=1000 -PVT.rinex_version=2 +PVT.rinex_version=3 diff --git a/conf/gnss-sdr_GPS_L1_CA_ibyte.conf b/conf/gnss-sdr_GPS_L1_CA_ibyte.conf index 9de3c4e6b..d2d501308 100644 --- a/conf/gnss-sdr_GPS_L1_CA_ibyte.conf +++ b/conf/gnss-sdr_GPS_L1_CA_ibyte.conf @@ -90,4 +90,4 @@ PVT.rtcm_MT1019_rate_ms=5000 PVT.rtcm_MT1045_rate_ms=5000 PVT.rtcm_MT1097_rate_ms=1000 PVT.rtcm_MT1077_rate_ms=1000 -PVT.rinex_version=2 +PVT.rinex_version=3 diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index 6c2936e21..6583fede1 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -345,7 +345,8 @@ rtklib_pvt_cc::rtklib_pvt_cc(unsigned int nchannels, bool dump, std::string dump b_rinex_header_written = false; b_rinex_header_updated = false; - rp = std::make_shared(rinex_version); + d_rinex_version = rinex_version; + rp = std::make_shared(d_rinex_version); d_last_status_print_seg = 0; @@ -874,7 +875,13 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { std::string glo_signal("1G"); rp->rinex_obs_header(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal); - rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + if(d_rinex_version == 3) + rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + if(d_rinex_version == 2) + { + rp->rinex_nav_header(rp->navFile, d_ls_pvt->gps_iono, d_ls_pvt->gps_utc_model); + rp->rinex_nav_header(rp->navGloFile, d_ls_pvt->glonass_gnav_utc_model, glonass_gnav_ephemeris_iter->second); + } b_rinex_header_written = true; // do not write header anymore } } @@ -924,7 +931,14 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite } if(type_of_rx == 26) // GPS L1 C/A + GLONASS L1 C/A { - rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); + if(d_rinex_version == 3) + rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); + if(d_rinex_version == 2) + { + rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map); + rp->log_rinex_nav(rp->navGloFile, d_ls_pvt->glonass_gnav_ephemeris_map); + } + } if(type_of_rx == 27) // Galileo E1B + GLONASS L1 C/A { @@ -1099,7 +1113,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end()) ) { - rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); } if (!b_rinex_header_updated && (d_ls_pvt->gps_utc_model.d_A0 != 0)) { diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.h b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.h index a46d26180..7e71b21a0 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.h +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.h @@ -98,6 +98,7 @@ private: bool d_dump; bool b_rinex_header_written; bool b_rinex_header_updated; + double d_rinex_version; bool b_rtcm_writing_started; int d_rtcm_MT1045_rate_ms; //!< Galileo Broadcast Ephemeris int d_rtcm_MT1019_rate_ms; //!< GPS Broadcast Ephemeris (orbits) diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index 0a14e63cb..0e1bc7245 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -3038,8 +3038,6 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& gps_eph_map, const std::map& glonass_gnav_eph_map) { - version = 3; - stringVersion = "3.02"; Rinex_Printer::log_rinex_nav(out, gps_eph_map); Rinex_Printer::log_rinex_nav(out, glonass_gnav_eph_map); } @@ -3199,19 +3197,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem Rinex_Printer::lengthCheck(line); out << line << std::endl; - if (version == 2) - { - // --------- WAVELENGHT FACTOR - // put here real data! - line.clear(); - line +=Rinex_Printer::rightJustify("1",6); - line +=Rinex_Printer::rightJustify("1",6); - line += std::string(48, ' '); - line += Rinex_Printer::leftJustify("WAVELENGTH FACT L1/2", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; - } - + // -------- SYS / OBS TYPES if (version == 3) { // -------- SYS / OBS TYPES @@ -3266,7 +3252,6 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem Rinex_Printer::lengthCheck(line); out << line << std::endl; } - if (version == 2) { // -------- SYS / OBS TYPES @@ -3293,6 +3278,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem out << line << std::endl; } + // -------- Signal Strength units (Only version 3) if (version == 3) { // -------- Signal Strength units @@ -3314,7 +3300,6 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem std::string minutes (timestring, 11, 2); double intpart = 0; double seconds = p_utc_time.time_of_day().seconds() + modf (d_TOW_first_observation , &intpart); - line.clear(); line += Rinex_Printer::rightJustify(year, 6); line += Rinex_Printer::rightJustify(month, 6); @@ -3328,50 +3313,52 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- SYS /PHASE SHIFTS - // -------- GLONASS SLOT / FRQ # - line.clear(); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 3); - line += std::string(1, ' '); + // -------- GLONASS SLOT / FRQ # (On;y version 3) + if (version == 3) + { + // -------- GLONASS SLOT / FRQ # + // TODO Need to provide system with list of all satellites and update this accordingly + line.clear(); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 3); // Number of satellites in list + line += std::string(1, ' '); + line += satelliteSystem["GLONASS"]; + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Slot Number + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Frequency Number + line += std::string(1, ' '); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS SLOT / FRQ #", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - // TODO Add this here, we need to know all satellites in system to get this done - line += satelliteSystem["GLONASS"]; - line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Slot Number - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Frequency Number - line += std::string(1, ' '); - line += std::string(60-line.size(), ' '); - line += Rinex_Printer::leftJustify("GLONASS SLOT / FRQ #", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; - - // -------- GLONASS CODE/PHS/BIS - // TODO This needs more study, not really suer on what those values are. Setting it to zero to advance in code. - line.clear(); - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G1_CA"]; - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G1_P"]; - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G2_CA"]; - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G2_P"]; - line += std::string(1, ' '); - line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); - line += std::string(60-line.size(), ' '); - line += Rinex_Printer::leftJustify("GLONASS COD/PHS/BIS", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + // -------- GLONASS CODE/PHS/BIS + // No GLONASS Phase bias correction used to align code and phase observations. + line.clear(); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS COD/PHS/BIS", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } // -------- END OF HEADER line.clear(); @@ -3386,11 +3373,10 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps { if(glonass_gnav_eph.d_m){} // avoid warning, not needed std::string line; - version = 3; // -------- Line 1 line = std::string(5, ' '); - line += "3.02"; + line += stringVersion; line += std::string(11, ' '); line += Rinex_Printer::leftJustify("OBSERVATION DATA", 20); line += satelliteSystem["Mixed"]; @@ -3416,7 +3402,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps // -------- Line COMMENT line.clear(); - line += Rinex_Printer::leftJustify("MIXED (GPS/GLONASS) OBSERVATION DATA FILE GENERATED BY GNSS-SDR", 60); + line += Rinex_Printer::leftJustify("MIXED (GPS/GLO) OBSERVATION DATA FILE GENERATED BY GNSS-SDR", 60); line += Rinex_Printer::leftJustify("COMMENT", 20); Rinex_Printer::lengthCheck(line); out << line << std::endl; @@ -3520,100 +3506,127 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps out << line << std::endl; // -------- SYS / OBS TYPES - // one line per available system - line.clear(); - line += satelliteSystem["GPS"]; - line += std::string(2, ' '); - std::stringstream strm; - numberTypesObservations = 4; - strm << numberTypesObservations; - line += Rinex_Printer::rightJustify(strm.str(), 3); - // per type of observation - // GPS L1 PSEUDORANGE - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GPS_L1_CA"]; - // GPS L1 PHASE - line += std::string(1, ' '); - line += observationType["CARRIER_PHASE"]; - line += observationCode["GPS_L1_CA"]; - // GPS DOPPLER L1 - line += std::string(1, ' '); - line += observationType["DOPPLER"]; - line += observationCode["GPS_L1_CA"]; - // GPS L1 CA SIGNAL STRENGTH - line += std::string(1, ' '); - line += observationType["SIGNAL_STRENGTH"]; - line += observationCode["GPS_L1_CA"]; - line += std::string(60-line.size(), ' '); - line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + if(version == 3) + { + // one line per available system + line.clear(); + line += satelliteSystem["GPS"]; + line += std::string(2, ' '); + std::stringstream strm; + numberTypesObservations = 4; + strm << numberTypesObservations; + line += Rinex_Printer::rightJustify(strm.str(), 3); + // per type of observation + // GPS L1 PSEUDORANGE + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GPS_L1_CA"]; + // GPS L1 PHASE + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GPS_L1_CA"]; + // GPS DOPPLER L1 + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GPS_L1_CA"]; + // GPS L1 CA SIGNAL STRENGTH + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GPS_L1_CA"]; + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - // Find GLONASS Signal in Mixed file - unsigned int number_of_observations_glo = 0; - std::string signal_("1G"); - std::size_t found_1C = glonass_bands.find(signal_); - if(found_1C != std::string::npos) + // Find GLONASS Signal in Mixed file + unsigned int number_of_observations_glo = 0; + std::string signal_("1G"); + std::size_t found_1C = glonass_bands.find(signal_); + if(found_1C != std::string::npos) + { + number_of_observations_glo = number_of_observations_glo + 4; + } + signal_ = "2G"; + std::size_t found_2C = glonass_bands.find(signal_); + if(found_2C != std::string::npos) + { + number_of_observations_glo = number_of_observations_glo + 4; + } + line.clear(); + line += satelliteSystem["GLONASS"]; + line += std::string(2, ' '); + line += Rinex_Printer::rightJustify(std::to_string(number_of_observations_glo), 3); + if(found_1C != std::string::npos) + { + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GLONASS_G1_CA"]; + } + if(found_2C != std::string::npos) + { + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GLONASS_G2_CA"]; + } + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } + if(version == 2) { - number_of_observations_glo = number_of_observations_glo + 4; - } - signal_ = "2G"; - std::size_t found_2C = glonass_bands.find(signal_); - if(found_2C != std::string::npos) - { - number_of_observations_glo = number_of_observations_glo + 4; + // -------- SYS / OBS TYPES + line.clear(); + std::stringstream strm; + strm << numberTypesObservations; + line += Rinex_Printer::rightJustify(strm.str(), 6); + // per type of observation + // GLONASS L1 C/A PSEUDORANGE + line += Rinex_Printer::rightJustify(observationType["PSEUDORANGE_CA_v2"], 5); + line += observationCode["GLONASS_G1_CA_v2"]; + // GLONASS L1 PHASE + line += Rinex_Printer::rightJustify(observationType["CARRIER_PHASE_CA_v2"], 5); + line += observationCode["GLONASS_G1_CA_v2"]; + // GLONASS DOPPLER L1 + line += Rinex_Printer::rightJustify(observationType["DOPPLER_v2"], 5); + line += observationCode["GLONASS_G1_CA_v2"]; + // GLONASS L1 SIGNAL STRENGTH + line += Rinex_Printer::rightJustify(observationType["SIGNAL_STRENGTH_v2"], 5); + line += observationCode["GLONASS_G1_CA_v2"]; + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("# / TYPES OF OBSERV", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; } - line.clear(); - line += satelliteSystem["GLONASS"]; - line += std::string(2, ' '); - line += Rinex_Printer::rightJustify(std::to_string(number_of_observations_glo), 3); - - if(found_1C != std::string::npos) - { - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G1_CA"]; - line += std::string(1, ' '); - line += observationType["CARRIER_PHASE"]; - line += observationCode["GLONASS_G1_CA"]; - line += std::string(1, ' '); - line += observationType["DOPPLER"]; - line += observationCode["GLONASS_G1_CA"]; - line += std::string(1, ' '); - line += observationType["SIGNAL_STRENGTH"]; - line += observationCode["GLONASS_G1_CA"]; - } - - if(found_2C != std::string::npos) - { - line += std::string(1, ' '); - line += observationType["PSEUDORANGE"]; - line += observationCode["GLONASS_G2_CA"]; - line += std::string(1, ' '); - line += observationType["CARRIER_PHASE"]; - line += observationCode["GLONASS_G2_CA"]; - line += std::string(1, ' '); - line += observationType["DOPPLER"]; - line += observationCode["GLONASS_G2_CA"]; - line += std::string(1, ' '); - line += observationType["SIGNAL_STRENGTH"]; - line += observationCode["GLONASS_G2_CA"]; - } - - line += std::string(60-line.size(), ' '); - line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; - - // -------- Signal Strength units - line.clear(); - line += Rinex_Printer::leftJustify("DBHZ", 20); - line += std::string(40, ' '); - line += Rinex_Printer::leftJustify("SIGNAL STRENGTH UNIT", 20); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; + // -------- Signal Strength units (only version 3) + if(version == 3) + { + line.clear(); + line += Rinex_Printer::leftJustify("DBHZ", 20); + line += std::string(40, ' '); + line += Rinex_Printer::leftJustify("SIGNAL STRENGTH UNIT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } // -------- TIME OF FIRST OBS line.clear(); @@ -3638,6 +3651,53 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps Rinex_Printer::lengthCheck(line); out << line << std::endl; + // -------- GLONASS SLOT / FRQ # (On;y version 3) + if (version == 3) + { + // -------- GLONASS SLOT / FRQ # + // TODO Need to provide system with list of all satellites and update this accordingly + line.clear(); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 3); // Number of satellites in list + line += std::string(1, ' '); + line += satelliteSystem["GLONASS"]; + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Slot Number + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Frequency Number + line += std::string(1, ' '); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS SLOT / FRQ #", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- GLONASS CODE/PHS/BIS + // No GLONASS Phase bias correction used to align code and phase observations. + line.clear(); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS COD/PHS/BIS", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + } + // -------- end of header line.clear(); line += std::string(60, ' '); @@ -5670,6 +5730,7 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_ep if(glonass_gnav_eph.d_m){} // avoid warning, not needed std::string line; + // -------- EPOCH record boost::posix_time::ptime p_gps_time = Rinex_Printer::compute_GPS_time(gps_eph, gps_obs_time); std::string timestring = boost::posix_time::to_iso_string(p_gps_time); //double utc_t = nav_msg.utc_time(nav_msg.sv_clock_correction(obs_time)); @@ -5681,221 +5742,303 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_ep std::string hour (timestring, 9, 2); std::string minutes (timestring, 11, 2); - std::string year (timestring, 0, 4); - line += std::string(1, '>'); - line += std::string(1, ' '); - line += year; - line += std::string(1, ' '); - line += month; - line += std::string(1, ' '); - line += day; - line += std::string(1, ' '); - line += hour; - line += std::string(1, ' '); - line += minutes; - - line += std::string(1, ' '); - double seconds = fmod(gps_t, 60); - // Add extra 0 if seconds are < 10 - if (seconds < 10) + if (version == 2) { - line +=std::string(1, '0'); - } - line += Rinex_Printer::asString(seconds, 7); - line += std::string(2, ' '); - // Epoch flag 0: OK 1: power failure between previous and current epoch <1: Special event - line += std::string(1, '0'); - - //Number of satellites observed in current epoch - - //Get maps with observations - std::map observablesG1C; - std::map observablesR1C; - std::map observablesR2C; - std::map::const_iterator observables_iter; - - for(observables_iter = observables.begin(); - observables_iter != observables.end(); - observables_iter++) - { - std::string system_(&observables_iter->second.System, 1); - std::string sig_(observables_iter->second.Signal); - if((system_.compare("R") == 0) && (sig_.compare("1C") == 0)) + line.clear(); + std::string year (timestring, 2, 2); + line += std::string(1, ' '); + line += year; + line += std::string(1, ' '); + if (month.compare(0, 1 , "0") == 0) { - observablesR1C.insert(std::pair(observables_iter->first, observables_iter->second)); - } - if((system_.compare("R") == 0) && (sig_.compare("1C") == 0)) - { - observablesR2C.insert(std::pair(observables_iter->first, observables_iter->second)); - } - if((system_.compare("G") == 0) && (sig_.compare("1C") == 0)) - { - observablesG1C.insert(std::pair(observables_iter->first, observables_iter->second)); - } - } - - std::multimap total_glo_map; - std::set available_glo_prns; - std::set::iterator it; - for(observables_iter = observablesR1C.begin(); - observables_iter != observablesR1C.end(); - observables_iter++) - { - unsigned int prn_ = observables_iter->second.PRN; - total_glo_map.insert(std::pair(prn_, observables_iter->second)); - it = available_glo_prns.find(prn_); - if(it == available_glo_prns.end()) - { - available_glo_prns.insert(prn_); - } - } - - for(observables_iter = observablesR2C.begin(); - observables_iter != observablesR2C.end(); - observables_iter++) - { - unsigned int prn_ = observables_iter->second.PRN; - total_glo_map.insert(std::pair(prn_, observables_iter->second)); - it = available_glo_prns.find(prn_); - if(it == available_glo_prns.end()) - { - available_glo_prns.insert(prn_); - } - } - - int numGloSatellitesObserved = available_glo_prns.size(); - int numGpsSatellitesObserved = observablesG1C.size(); - int numSatellitesObserved = numGloSatellitesObserved + numGpsSatellitesObserved; - line += Rinex_Printer::rightJustify(boost::lexical_cast(numSatellitesObserved), 3); - - // Receiver clock offset (optional) - //line += rightJustify(asString(clockOffset, 12), 15); - - line += std::string(80 - line.size(), ' '); - Rinex_Printer::lengthCheck(line); - out << line << std::endl; - - std::string s; - std::string lineObs; - for(observables_iter = observablesG1C.begin(); - observables_iter != observablesG1C.end(); - observables_iter++) - { - lineObs.clear(); - - s.assign(1, observables_iter->second.System); - if(s.compare("G") == 0) lineObs += satelliteSystem["GPS"]; - if(s.compare("R") == 0) lineObs += satelliteSystem["GLONASS"]; // should not happen - if (static_cast(observables_iter->second.PRN) < 10) lineObs += std::string(1, '0'); - lineObs += boost::lexical_cast(static_cast(observables_iter->second.PRN)); - lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Pseudorange_m, 3), 14); - - //Loss of lock indicator (LLI) - int lli = 0; // Include in the observation!! - if (lli == 0) - { - lineObs += std::string(1, ' '); + line += std::string(1, ' '); + line += month.substr(1, 1); } else { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + line += month; } - - // Signal Strength Indicator (SSI) - int ssi = Rinex_Printer::signalStrength(observables_iter->second.CN0_dB_hz); - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - - // PHASE - lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_phase_rads/GPS_TWO_PI, 3), 14); - if (lli == 0) + line += std::string(1, ' '); + if (day.compare(0, 1 , "0") == 0) { - lineObs += std::string(1, ' '); + line += std::string(1, ' '); + line += day.substr(1, 1); } else { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + line += day; } - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - - // DOPPLER - lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_Doppler_hz, 3), 14); - if (lli == 0) + line += std::string(1, ' '); + line += hour; + line += std::string(1, ' '); + line += minutes; + line += std::string(1, ' '); + double second_ = fmod(gps_t, 60); + if (second_ < 10) { - lineObs += std::string(1, ' '); + line += std::string(1, ' '); } - else - { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); - } - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); - - // SIGNAL STRENGTH - lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.CN0_dB_hz, 3), 14); - - if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); - out << lineObs << std::endl; + line += Rinex_Printer::asString(second_, 7); + line += std::string(2, ' '); + // Epoch flag 0: OK 1: power failure between previous and current epoch <1: Special event + line += std::string(1, '0'); } + if (version == 3) + { + std::string year (timestring, 0, 4); + line += std::string(1, '>'); + line += std::string(1, ' '); + line += year; + line += std::string(1, ' '); + line += month; + line += std::string(1, ' '); + line += day; + line += std::string(1, ' '); + line += hour; + line += std::string(1, ' '); + line += minutes; - std::pair ::iterator, std::multimap::iterator> ret; - for(it = available_glo_prns.begin(); - it != available_glo_prns.end(); - it++) - { - lineObs.clear(); - lineObs += satelliteSystem["GLONASS"]; - if (static_cast(*it) < 10) lineObs += std::string(1, '0'); - lineObs += boost::lexical_cast(static_cast(*it)); - ret = total_glo_map.equal_range(*it); - for (std::multimap::iterator iter = ret.first; iter != ret.second; ++iter) - { - lineObs += Rinex_Printer::rightJustify(asString(iter->second.Pseudorange_m, 3), 14); + line += std::string(1, ' '); + double seconds = fmod(gps_t, 60); + // Add extra 0 if seconds are < 10 + if (seconds < 10) + { + line +=std::string(1, '0'); + } + line += Rinex_Printer::asString(seconds, 7); + line += std::string(2, ' '); + // Epoch flag 0: OK 1: power failure between previous and current epoch <1: Special event + line += std::string(1, '0'); - //Loss of lock indicator (LLI) - int lli = 0; // Include in the observation!! - if (lli == 0) - { - lineObs += std::string(1, ' '); - } - else - { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); - } + } + //Number of satellites observed in current epoch + //Get maps with observations + std::map observablesG1C; + std::map observablesR1C; + std::map observablesR2C; + std::map::const_iterator observables_iter; - // Signal Strength Indicator (SSI) - int ssi = Rinex_Printer::signalStrength(iter->second.CN0_dB_hz); - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + for(observables_iter = observables.begin(); + observables_iter != observables.end(); + observables_iter++) + { + std::string system_(&observables_iter->second.System, 1); + std::string sig_(observables_iter->second.Signal); + if((system_.compare("R") == 0) && (sig_.compare("1G") == 0)) + { + observablesR1C.insert(std::pair(observables_iter->first, observables_iter->second)); + } + if((system_.compare("R") == 0) && (sig_.compare("2G") == 0)) + { + observablesR2C.insert(std::pair(observables_iter->first, observables_iter->second)); + } + if((system_.compare("G") == 0) && (sig_.compare("1C") == 0)) + { + observablesG1C.insert(std::pair(observables_iter->first, observables_iter->second)); + } + } - // GLONASS CARRIER PHASE - lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_phase_rads / (GALILEO_TWO_PI), 3), 14); - if (lli == 0) - { - lineObs += std::string(1, ' '); - } - else - { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); - } - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + std::multimap total_glo_map; + std::set available_glo_prns; + std::set::iterator it; + for(observables_iter = observablesR1C.begin(); + observables_iter != observablesR1C.end(); + observables_iter++) + { + unsigned int prn_ = observables_iter->second.PRN; + total_glo_map.insert(std::pair(prn_, observables_iter->second)); + it = available_glo_prns.find(prn_); + if(it == available_glo_prns.end()) + { + available_glo_prns.insert(prn_); + } + } - // GLONASS DOPPLER - lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_Doppler_hz, 3), 14); - if (lli == 0) - { - lineObs += std::string(1, ' '); - } - else - { - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); - } - lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + for(observables_iter = observablesR2C.begin(); + observables_iter != observablesR2C.end(); + observables_iter++) + { + unsigned int prn_ = observables_iter->second.PRN; + total_glo_map.insert(std::pair(prn_, observables_iter->second)); + it = available_glo_prns.find(prn_); + if(it == available_glo_prns.end()) + { + available_glo_prns.insert(prn_); + } + } - // GLONASS SIGNAL STRENGTH - lineObs += Rinex_Printer::rightJustify(asString(iter->second.CN0_dB_hz, 3), 14); - } + int numGloSatellitesObserved = available_glo_prns.size(); + int numGpsSatellitesObserved = observablesG1C.size(); + int numSatellitesObserved = numGloSatellitesObserved + numGpsSatellitesObserved; + line += Rinex_Printer::rightJustify(boost::lexical_cast(numSatellitesObserved), 3); + if(version == 2) + { + // Add list of GPS satellites + for(observables_iter = observablesG1C.begin(); + observables_iter != observablesG1C.end(); + observables_iter++) + { + line += satelliteSystem["GPS"]; + if (static_cast(observables_iter->second.PRN) < 10) line += std::string(1, '0'); + line += boost::lexical_cast(static_cast(observables_iter->second.PRN)); + } + // Add list of GLONASS L1 satellites + for(observables_iter = observablesR1C.begin(); + observables_iter != observablesR1C.end(); + observables_iter++) + { + line += satelliteSystem["GLONASS"]; + if (static_cast(observables_iter->second.PRN) < 10) line += std::string(1, '0'); + line += boost::lexical_cast(static_cast(observables_iter->second.PRN)); + } + // Add list of GLONASS L2 satellites + for(observables_iter = observablesR2C.begin(); + observables_iter != observablesR2C.end(); + observables_iter++) + { + line += satelliteSystem["GLONASS"]; + if (static_cast(observables_iter->second.PRN) < 10) line += std::string(1, '0'); + line += boost::lexical_cast(static_cast(observables_iter->second.PRN)); + } + } + line += std::string(80 - line.size(), ' '); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- OBSERVATION record + std::string s; + std::string lineObs; + for(observables_iter = observablesG1C.begin(); + observables_iter != observablesG1C.end(); + observables_iter++) + { + lineObs.clear(); + + s.assign(1, observables_iter->second.System); + if(version == 3) + { + // Specify system only if in version 3 + if(s.compare("G") == 0) lineObs += satelliteSystem["GPS"]; + if(s.compare("R") == 0) lineObs += satelliteSystem["GLONASS"]; // should not happen + if (static_cast(observables_iter->second.PRN) < 10) lineObs += std::string(1, '0'); + lineObs += boost::lexical_cast(static_cast(observables_iter->second.PRN)); + } + + // Pseudorange Measurements + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Pseudorange_m, 3), 14); + + //Loss of lock indicator (LLI) + int lli = 0; // Include in the observation!! + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + + // Signal Strength Indicator (SSI) + int ssi = Rinex_Printer::signalStrength(observables_iter->second.CN0_dB_hz); + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // PHASE + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_phase_rads/GPS_TWO_PI, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // DOPPLER + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_Doppler_hz, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // SIGNAL STRENGTH + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.CN0_dB_hz, 3), 14); + + if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); + out << lineObs << std::endl; + } + + std::pair ::iterator, std::multimap::iterator> ret; + for(it = available_glo_prns.begin(); + it != available_glo_prns.end(); + it++) + { + lineObs.clear(); + if(version == 3) + { + lineObs += satelliteSystem["GLONASS"]; + if (static_cast(*it) < 10) lineObs += std::string(1, '0'); + lineObs += boost::lexical_cast(static_cast(*it)); + } + ret = total_glo_map.equal_range(*it); + for (std::multimap::iterator iter = ret.first; iter != ret.second; ++iter) + { + /// \todo Need to account for pseudorange correction for glonass + double leap_seconds = Rinex_Printer::get_leap_second(glonass_gnav_eph, gps_obs_time); + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Pseudorange_m, 3), 14); + + //Loss of lock indicator (LLI) + int lli = 0; // Include in the observation!! + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + + // Signal Strength Indicator (SSI) + int ssi = Rinex_Printer::signalStrength(iter->second.CN0_dB_hz); + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS CARRIER PHASE + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_phase_rads / (GLONASS_TWO_PI), 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS DOPPLER + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_Doppler_hz, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS SIGNAL STRENGTH + lineObs += Rinex_Printer::rightJustify(asString(iter->second.CN0_dB_hz, 3), 14); + } + + if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); + out << lineObs << std::endl; + } - if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); - out << lineObs << std::endl; - } } @@ -5954,11 +6097,11 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Galileo_Ephemeris& ga { std::string system_(&observables_iter->second.System, 1); std::string sig_(observables_iter->second.Signal); - if((system_.compare("R") == 0) && (sig_.compare("1C") == 0)) + if((system_.compare("R") == 0) && (sig_.compare("1G") == 0)) { observablesR1C.insert(std::pair(observables_iter->first, observables_iter->second)); } - if((system_.compare("R") == 0) && (sig_.compare("2C") == 0)) + if((system_.compare("R") == 0) && (sig_.compare("2G") == 0)) { observablesR2C.insert(std::pair(observables_iter->first, observables_iter->second)); } @@ -7431,6 +7574,46 @@ boost::posix_time::ptime Rinex_Printer::compute_UTC_time(const Glonass_Gnav_Ephe return utc_time; } +double Rinex_Printer::get_leap_second(const Glonass_Gnav_Ephemeris& eph, const double gps_obs_time) +{ + double tod = 0.0; + double glot2utc = 3*3600; + double obs_time_utc = 0.0, obs_time_glot = 0.0; + int i = 0; + double leap_second = 0; + + // Get observation time in nearly GLONASS time. Correction for leap seconds done at the end + obs_time_glot = gps_obs_time + glot2utc; + + // Get seconds of day in glonass time + tod = fmod (obs_time_glot, 86400); + + // Form date and time duration types + boost::posix_time::time_duration t1(0, 0, tod); + boost::gregorian::date d1(eph.d_yr, 1, 1); + boost::gregorian::days d2(eph.d_N_T-1); + boost::posix_time::ptime glo_time(d1 + d2, t1); + + // Convert to utc + boost::posix_time::time_duration t2(0, 0, glot2utc); + boost::posix_time::ptime utc_time = glo_time - t2; + + // Adjust for leap second correction + for (i = 0; GLONASS_LEAP_SECONDS[i][0]>0; i++) + { + boost::posix_time::time_duration t3(GLONASS_LEAP_SECONDS[i][3], GLONASS_LEAP_SECONDS[i][4], GLONASS_LEAP_SECONDS[i][5]); + boost::gregorian::date d3(GLONASS_LEAP_SECONDS[i][0], GLONASS_LEAP_SECONDS[i][1], GLONASS_LEAP_SECONDS[i][2]); + boost::posix_time::ptime ls_time(d3, t3); + if (utc_time >= ls_time) + { + // We subtract the leap second when going from gpst to utc + leap_second = fabs(GLONASS_LEAP_SECONDS[i][6]); + break; + } + } + + return leap_second; +} /* enum RINEX_enumMarkerType { diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index f061a93f4..fb6ee27b5 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -202,6 +202,13 @@ public: */ boost::posix_time::ptime compute_UTC_time(const Glonass_Gnav_Ephemeris & eph, const double obs_time); + /*! + * \brief Computes number of leap seconds of GPS relative to UTC + * \param eph GLONASS GNAV Ephemeris object + * \param gps_obs_time Observation time in GPS seconds of week + */ + double get_leap_second(const Glonass_Gnav_Ephemeris& eph, const double gps_obs_time); + /*! * \brief Writes data from the GPS L1 C/A navigation message into the RINEX file */ From 1cc72b810264a9c813f5d0fac399de38a7361dea Mon Sep 17 00:00:00 2001 From: Damian Miralles Date: Wed, 27 Dec 2017 19:10:08 -0700 Subject: [PATCH 5/5] glonass: Adding RINEX support for rcv type 28 (GPS L2C + GLO L1 C/A) Adds RINEX support for receiver type 28 which combines GPS L2C and GLONASS L2C. Fixes a couple of bugs in RINEX file generation and adds new configuration files for L2C processing --- ...ss-sdr_GLONASS_L1_CA_GPS_L1_CA_ibyte.conf} | 0 .../gnss-sdr_GLONASS_L1_CA_GPS_L2C_ibyte.conf | 147 ++++ src/algorithms/PVT/adapters/rtklib_pvt.cc | 2 + .../PVT/gnuradio_blocks/rtklib_pvt_cc.cc | 28 + src/algorithms/PVT/libs/rinex_printer.cc | 815 +++++++++++++++++- src/algorithms/PVT/libs/rinex_printer.h | 22 + 6 files changed, 991 insertions(+), 23 deletions(-) rename conf/{gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf => gnss-sdr_GLONASS_L1_CA_GPS_L1_CA_ibyte.conf} (100%) create mode 100644 conf/gnss-sdr_GLONASS_L1_CA_GPS_L2C_ibyte.conf diff --git a/conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf b/conf/gnss-sdr_GLONASS_L1_CA_GPS_L1_CA_ibyte.conf similarity index 100% rename from conf/gnss-sdr_GPS_GLONASS_L1_CA_ibyte.conf rename to conf/gnss-sdr_GLONASS_L1_CA_GPS_L1_CA_ibyte.conf diff --git a/conf/gnss-sdr_GLONASS_L1_CA_GPS_L2C_ibyte.conf b/conf/gnss-sdr_GLONASS_L1_CA_GPS_L2C_ibyte.conf new file mode 100644 index 000000000..b36bb6e31 --- /dev/null +++ b/conf/gnss-sdr_GLONASS_L1_CA_GPS_L2C_ibyte.conf @@ -0,0 +1,147 @@ +[GNSS-SDR] + +;######### GLOBAL OPTIONS ################## +GNSS-SDR.internal_fs_sps=6625000 +Receiver.sources_count=2 +SignalSource.repeat=false + +;######### SIGNAL_SOURCE CONFIG ############ +SignalSource0.implementation=File_Signal_Source +SignalSource0.filename=/archive/NT1065_L2_20160923_fs6625e6_if60e3_schar.bin ; <- PUT YOUR FILE HERE +SignalSource0.item_type=ibyte +SignalSource0.sampling_frequency=6625000 +SignalSource0.samples=0 +SignalSource0.dump=false; +SignalSource0.dump_filename=/archive/signal_glonass.bin + +SignalSource1.implementation=File_Signal_Source +SignalSource1.filename=/archive/NT1065_GLONASS_L1_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE +SignalSource1.item_type=ibyte +SignalSource1.sampling_frequency=6625000 +SignalSource1.samples=0 +SignalSource1.dump=false; +SignalSource1.dump_filename=/archive/signal_glonass.bin + +;######### SIGNAL_CONDITIONER CONFIG ############ +SignalConditioner0.implementation=Signal_Conditioner +DataTypeAdapter0.implementation=Ibyte_To_Complex +InputFilter0.implementation=Freq_Xlating_Fir_Filter +InputFilter0.item_type=gr_complex +InputFilter0.output_item_type=gr_complex +InputFilter0.taps_item_type=float +InputFilter0.number_of_taps=5 +InputFilter0.number_of_bands=2 +InputFilter0.band1_begin=0.0 +InputFilter0.band1_end=0.70 +InputFilter0.band2_begin=0.80 +InputFilter0.band2_end=1.0 +InputFilter0.ampl1_begin=1.0 +InputFilter0.ampl1_end=1.0 +InputFilter0.ampl2_begin=0.0 +InputFilter0.ampl2_end=0.0 +InputFilter0.band1_error=1.0 +InputFilter0.band2_error=1.0 +InputFilter0.filter_type=bandpass +InputFilter0.grid_density=16 +InputFilter0.sampling_frequency=6625000 +InputFilter0.IF=60000 +Resampler0.implementation=Direct_Resampler +Resampler0.sample_freq_in=6625000 +Resampler0.sample_freq_out=6625000 +Resampler0.item_type=gr_complex + +SignalConditioner1.implementation=Signal_Conditioner +DataTypeAdapter1.implementation=Ibyte_To_Complex +InputFilter1.implementation=Pass_Through +InputFilter1.item_type=gr_complex +Resampler1.implementation=Direct_Resampler +Resampler1.sample_freq_in=6625000 +Resampler1.sample_freq_out=6625000 +Resampler1.item_type=gr_complex + +;######### CHANNELS GLOBAL CONFIG ############ +Channels.in_acquisition=5 +Channels_2S.count=5 +Channels_1G.count=5 + +;# Defining GLONASS satellites +Channel0.RF_channel_ID=0 +Channel0.signal=2S +Channel1.RF_channel_ID=0 +Channel1.signal=2S +Channel2.RF_channel_ID=0 +Channel2.signal=2S +Channel3.RF_channel_ID=0 +Channel3.signal=2S +Channel4.RF_channel_ID=0 +Channel4.signal=2S +Channel5.RF_channel_ID=1 +Channel6.RF_channel_ID=1 +Channel7.RF_channel_ID=1 +Channel8.RF_channel_ID=1 +Channel9.RF_channel_ID=1 + + +;######### ACQUISITION GLOBAL CONFIG ############ +Acquisition_2S.implementation=GPS_L2_M_PCPS_Acquisition +Acquisition_2S.item_type=gr_complex +Acquisition_2S.threshold=0.0 +Acquisition_2S.pfa=0.00001 +Acquisition_2S.if=0 +Acquisition_2S.doppler_max=10000 +Acquisition_2S.doppler_step=60 +Acquisition_2S.max_dwells=1 + +Acquisition_1G.implementation=GLONASS_L1_CA_PCPS_Acquisition +Acquisition_1G.item_type=gr_complex +Acquisition_1G.threshold=0.0 +Acquisition_1G.pfa=0.00001 +Acquisition_1G.if=0 +Acquisition_1G.doppler_max=10000 +Acquisition_1G.doppler_step=250 +Acquisition_1G.dump=false; +Acquisition_1G.dump_filename=/archive/glo_acquisition.dat + +;######### TRACKING GLOBAL CONFIG ############ +Tracking_2S.implementation=GPS_L2_M_DLL_PLL_Tracking +Tracking_2S.item_type=gr_complex +Tracking_2S.if=0 +Tracking_2S.early_late_space_chips=0.5 +Tracking_2S.pll_bw_hz=2.0; +Tracking_2S.dll_bw_hz=0.250; +Tracking_2S.order=2; +Tracking_2S.dump=false; +Tracking_2S.dump_filename=/archive/gps_tracking_ch_ + +Tracking_1G.implementation=GLONASS_L1_CA_DLL_PLL_Tracking +Tracking_1G.item_type=gr_complex +Tracking_1G.if=0 +Tracking_1G.early_late_space_chips=0.5 +Tracking_1G.pll_bw_hz=25.0; +Tracking_1G.dll_bw_hz=3.0; +Tracking_1G.dump=true; +Tracking_1G.dump_filename=/archive/glo_tracking_ch_ + +;######### TELEMETRY DECODER GPS CONFIG ############ +TelemetryDecoder_2S.implementation=GPS_L2C_Telemetry_Decoder +TelemetryDecoder_1G.implementation=GLONASS_L1_CA_Telemetry_Decoder + +;######### OBSERVABLES CONFIG ############ +Observables.implementation=Hybrid_Observables +Observables.dump=false; +Observables.dump_filename=/archive/gnss_observables.dat + +;######### PVT CONFIG ############ +PVT.implementation=RTKLIB_PVT +PVT.output_rate_ms=100 +PVT.display_rate_ms=500 +PVT.trop_model=Saastamoinen +PVT.flag_rtcm_server=true +PVT.flag_rtcm_tty_port=false +PVT.rtcm_dump_devname=/dev/pts/1 +PVT.rtcm_tcp_port=2101 +PVT.rtcm_MT1019_rate_ms=5000 +PVT.rtcm_MT1045_rate_ms=5000 +PVT.rtcm_MT1097_rate_ms=1000 +PVT.rtcm_MT1077_rate_ms=1000 +PVT.rinex_version=3 diff --git a/src/algorithms/PVT/adapters/rtklib_pvt.cc b/src/algorithms/PVT/adapters/rtklib_pvt.cc index 2dbd59145..08bd7e57b 100644 --- a/src/algorithms/PVT/adapters/rtklib_pvt.cc +++ b/src/algorithms/PVT/adapters/rtklib_pvt.cc @@ -150,6 +150,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, * 25 | GLONASS L1 C/A + GLONASS L2 C/A * 26 | GPS L1 C/A + GLONASS L1 C/A * 27 | Galileo E1B + GLONASS L1 C/A + * 28 | GPS L2C + GLONASS L1 C/A */ int gps_1C_count = configuration->property("Channels_1C.count", 0); int gps_2S_count = configuration->property("Channels_2S.count", 0); @@ -187,6 +188,7 @@ RtklibPvt::RtklibPvt(ConfigurationInterface* configuration, //if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0) && (glo_1G_count != 0)) type_of_receiver = 25; if( (gps_1C_count != 0) && (gps_2S_count == 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 26; if( (gps_1C_count == 0) && (gps_2S_count == 0) && (gal_1B_count != 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 27; + if( (gps_1C_count == 0) && (gps_2S_count != 0) && (gal_1B_count == 0) && (gal_E5a_count == 0) && (gal_E5b_count == 0) && (glo_1G_count != 0)) type_of_receiver = 28; //RTKLIB PVT solver options // Settings 1 int positioning_mode = -1; diff --git a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc index 6583fede1..9b6169e50 100644 --- a/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/rtklib_pvt_cc.cc @@ -713,6 +713,7 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite * 25 | GLONASS L1 C/A + GLONASS L2 C/A * 26 | GPS L1 C/A + GLONASS L1 C/A * 27 | Galileo E1B + GLONASS L1 C/A + * 28 | GPS L2C + GLONASS L1 C/A */ // ####################### RINEX FILES ################# @@ -896,6 +897,16 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_written = true; // do not write header anymore } } + if(type_of_rx == 28) // GPS L2C + GLONASS L1 C/A + { + if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.cend()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.cend()) ) + { + std::string glo_signal("1G"); + rp->rinex_obs_header(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, glo_signal); + rp->rinex_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + b_rinex_header_written = true; // do not write header anymore + } + } } if(b_rinex_header_written) // The header is already written, we can now log the navigation message data { @@ -944,6 +955,10 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite { rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->galileo_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); } + if(type_of_rx == 28) // GPS L2C + GLONASS L1 C/A + { + rp->log_rinex_nav(rp->navMixFile, d_ls_pvt->gps_cnav_ephemeris_map, d_ls_pvt->glonass_gnav_ephemeris_map); + } } galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.cbegin(); gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.cbegin(); @@ -1136,6 +1151,19 @@ int rtklib_pvt_cc::work (int noutput_items, gr_vector_const_void_star &input_ite b_rinex_header_updated = true; // do not write header anymore } } + if(type_of_rx == 28) // GPS L2C + GLONASS L1 C/A + { + if ((glonass_gnav_ephemeris_iter != d_ls_pvt->glonass_gnav_ephemeris_map.end()) && (gps_cnav_ephemeris_iter != d_ls_pvt->gps_cnav_ephemeris_map.end()) ) + { + rp->log_rinex_obs(rp->obsFile, gps_cnav_ephemeris_iter->second, glonass_gnav_ephemeris_iter->second, d_rx_time, gnss_observables_map); + } + if (!b_rinex_header_updated && (d_ls_pvt->gps_cnav_utc_model.d_A0 != 0)) + { + rp->update_obs_header(rp->obsFile, d_ls_pvt->gps_cnav_utc_model); + rp->update_nav_header(rp->navMixFile, d_ls_pvt->gps_cnav_iono, d_ls_pvt->gps_cnav_utc_model, d_ls_pvt->glonass_gnav_utc_model, d_ls_pvt->glonass_gnav_almanac); + b_rinex_header_updated = true; // do not write header anymore + } + } } } diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index 0e1bc7245..4a53b2525 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -642,6 +642,127 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono out << line << std::endl; } +void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_iono, const Gps_CNAV_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) +{ + if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning + std::string line; + stringVersion = "3.02"; + version = 3; + + // -------- Line 1 + line = std::string(5, ' '); + line += stringVersion; + line += std::string(11, ' '); + line += std::string("N: GNSS NAV DATA"); + line += std::string(4, ' '); + line += std::string("M: MIXED"); + line += std::string(12, ' '); + line += std::string("RINEX VERSION / TYPE"); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line 2 + line.clear(); + line += Rinex_Printer::getLocalTime(); + line += std::string("PGM / RUN BY / DATE"); + line += std::string(1, ' '); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + line += Rinex_Printer::leftJustify("GNSS NAVIGATION MESSAGE FILE GENERATED BY GNSS-SDR", 60); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + std::string gnss_sdr_version(GNSS_SDR_VERSION); + line += "GNSS-SDR VERSION "; + line += Rinex_Printer::leftJustify(gnss_sdr_version, 43); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + line += Rinex_Printer::leftJustify("See http://gnss-sdr.org", 60); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line ionospheric info 1 + line.clear(); + line += std::string("GPSA"); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha0, 10, 2), 12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha1, 10, 2), 12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha2, 10, 2), 12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha3, 10, 2), 12); + line += std::string(7, ' '); + line += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line system time correction 1 + line.clear(); + line += std::string("GLUT"); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_c, 16, 2), 17); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line += std::string(10, ' '); + line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line system time correction 2 + line.clear(); + line += std::string("GLGP"); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_gps, 16, 2), 17); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line += std::string(10, ' '); + line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line system time correction 3 + line.clear(); + line += std::string("GPUT"); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_utc_model.d_A0, 16, 2), 18); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_utc_model.d_A1, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_t_OT), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_WN_T + 1024), 5); // valid until 2019 + line += std::string(10, ' '); + line += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- Line 6 leap seconds + // For leap second information, see http://www.endruntechnologies.com/leap.htm + line.clear(); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_DeltaT_LS), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_DeltaT_LSF), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_WN_LSF), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_DN), 6); + line += std::string(36, ' '); + line += Rinex_Printer::leftJustify("LEAP SECONDS", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- End of Header + line.clear(); + line += std::string(60, ' '); + line += Rinex_Printer::leftJustify("END OF HEADER", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; +} void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { @@ -753,7 +874,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& gali out << line << std::endl; } - void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono, const Galileo_Utc_Model& utc_model, const Galileo_Almanac& galileo_almanac) { std::string line; @@ -862,7 +982,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Galileo_Iono& iono out << line << std::endl; } - void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono & iono, const Gps_CNAV_Utc_Model & utc_model) { std::string line; @@ -978,7 +1097,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_CNAV_Iono & io out << line << std::endl; } - void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, const Gps_Utc_Model& utc_model) { std::string line; @@ -1157,7 +1275,6 @@ void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& iono, co out << line << std::endl; } - void Rinex_Printer::rinex_nav_header(std::fstream& out, const Gps_Iono& gps_iono, const Gps_Utc_Model& gps_utc_model, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac) { std::string line; @@ -1399,7 +1516,6 @@ void Rinex_Printer::rinex_sbs_header(std::fstream& out) } - void Rinex_Printer::update_nav_header(std::fstream& out, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -1473,7 +1589,6 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Glonass_Gnav_Utc_ std::cout << "The RINEX Navigation file header has been updated with UTC info." << std::endl; } - void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& utc_model, const Galileo_Almanac& galileo_almanac) { std::vector data; @@ -1569,7 +1684,6 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& gal std::cout << "The RINEX Navigation file header has been updated with UTC and IONO info." << std::endl; } - void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_Utc_Model& utc_model, const Gps_Iono& iono) { std::vector data; @@ -2054,6 +2168,112 @@ void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_Iono& gps_ion } +void Rinex_Printer::update_nav_header(std::fstream& out, const Gps_CNAV_Iono& gps_iono, const Gps_CNAV_Utc_Model& gps_utc_model, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) +{ + if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning + std::vector data; + std::string line_aux; + + long pos = out.tellp(); + out.seekp(0); + data.clear(); + + bool no_more_finds = false; + std::string line_str; + + while(!out.eof()) + { + std::getline(out, line_str); + + if(!no_more_finds) + { + line_aux.clear(); + + if (line_str.find("GPSA", 0) != std::string::npos) + { + line_aux += std::string("GPSA"); + line_aux += std::string(1, ' '); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha0, 10, 2), 12); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha1, 10, 2), 12); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha2, 10, 2), 12); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_iono.d_alpha3, 10, 2), 12); + line_aux += std::string(7, ' '); + line_aux += Rinex_Printer::leftJustify("IONOSPHERIC CORR", 20); + data.push_back(line_aux); + } + else if ((line_str.find("GPUT", 0) != std::string::npos) && (line_str.find("TIME SYSTEM CORR", 59) != std::string::npos)) + { + line_aux += std::string("GPUT"); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_utc_model.d_A0, 16, 2), 18); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(gps_utc_model.d_A1, 15, 2), 16); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_t_OT), 7); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_WN_T + 1024), 5); // valid until 2019 + line_aux += std::string(10, ' '); + line_aux += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + data.push_back(line_aux); + } + else if ((line_str.find("GLUT", 0) != std::string::npos) && (line_str.find("TIME SYSTEM CORR", 59) != std::string::npos)) + { + line_aux += std::string("GLUT"); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_c, 16, 2), 18); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line_aux += std::string(10, ' '); + line_aux += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + data.push_back(line_aux); + } + else if ((line_str.find("GLGP", 0) != std::string::npos) && (line_str.find("TIME SYSTEM CORR", 59) != std::string::npos)) + { + line_aux += std::string("GLGP"); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(glonass_gnav_utc_model.d_tau_gps, 16, 2), 18); + line_aux += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(0.0, 15, 2), 16); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 7); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(0.0), 5); + line_aux += std::string(10, ' '); + line_aux += Rinex_Printer::leftJustify("TIME SYSTEM CORR", 20); + data.push_back(line_aux); + } + else if (line_str.find("LEAP SECONDS", 59) != std::string::npos) + { + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_DeltaT_LS), 6); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.d_DeltaT_LSF), 6); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_WN_LSF), 6); + line_aux += Rinex_Printer::rightJustify(boost::lexical_cast(gps_utc_model.i_DN), 6); + line_aux += std::string(36, ' '); + line_aux += Rinex_Printer::leftJustify("LEAP SECONDS", 20); + data.push_back(line_aux); + } + else if (line_str.find("END OF HEADER", 59) != std::string::npos) + { + data.push_back(line_str); + no_more_finds = true; + } + else + { + data.push_back(line_str); + } + + } + else + { + data.push_back(line_str); + } + } + + out.close(); + out.open(navMixfilename, std::ios::out | std::ios::trunc); + out.seekp(0); + for (int i = 0; i < (int) data.size() - 1; i++) + { + out << data[i] << std::endl; + } + out.close(); + out.open(navMixfilename, std::ios::out | std::ios::app); + out.seekp(pos); + std::cout << "The RINEX Navigation file header has been updated with UTC and IONO info." << std::endl; +} + void Rinex_Printer::update_nav_header(std::fstream& out, const Galileo_Iono& galileo_iono, const Galileo_Utc_Model& galileo_utc_model, const Galileo_Almanac& galileo_almanac, const Glonass_Gnav_Utc_Model& glonass_gnav_utc_model, const Glonass_Gnav_Almanac& glonass_gnav_almanac) { if(glonass_gnav_almanac.i_satellite_freq_channel){} //Avoid compiler warning @@ -3042,6 +3262,11 @@ void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& gps_eph_map, const std::map& glonass_gnav_eph_map) +{ + Rinex_Printer::log_rinex_nav(out, gps_eph_map); + Rinex_Printer::log_rinex_nav(out, glonass_gnav_eph_map); +} void Rinex_Printer::log_rinex_nav(std::fstream& out, const std::map& galileo_eph_map, const std::map& glonass_gnav_eph_map) { @@ -3211,11 +3436,11 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem line += Rinex_Printer::rightJustify(strm.str(), 3); std::string signal_ = "1G"; - std::size_t found_1C = glonass_bands.find(signal_); + std::size_t found_1G = glonass_bands.find(signal_); signal_ = "2G"; - std::size_t found_2C = glonass_bands.find(signal_); + std::size_t found_2G = glonass_bands.find(signal_); - if(found_1C != std::string::npos) + if(found_1G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -3231,7 +3456,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Glonass_Gnav_Ephem line += observationCode["GLONASS_G1_CA"]; } - if(found_2C != std::string::npos) + if(found_2G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -3541,14 +3766,14 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps // Find GLONASS Signal in Mixed file unsigned int number_of_observations_glo = 0; std::string signal_("1G"); - std::size_t found_1C = glonass_bands.find(signal_); - if(found_1C != std::string::npos) + std::size_t found_1G = glonass_bands.find(signal_); + if(found_1G != std::string::npos) { number_of_observations_glo = number_of_observations_glo + 4; } signal_ = "2G"; - std::size_t found_2C = glonass_bands.find(signal_); - if(found_2C != std::string::npos) + std::size_t found_2G = glonass_bands.find(signal_); + if(found_2G != std::string::npos) { number_of_observations_glo = number_of_observations_glo + 4; } @@ -3556,7 +3781,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps line += satelliteSystem["GLONASS"]; line += std::string(2, ' '); line += Rinex_Printer::rightJustify(std::to_string(number_of_observations_glo), 3); - if(found_1C != std::string::npos) + if(found_1G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -3571,7 +3796,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps line += observationType["SIGNAL_STRENGTH"]; line += observationCode["GLONASS_G1_CA"]; } - if(found_2C != std::string::npos) + if(found_2G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -3707,6 +3932,310 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_Ephemeris& gps } +void Rinex_Printer::rinex_obs_header(std::fstream& out, const Gps_CNAV_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const double d_TOW_first_observation, const std::string glonass_bands) +{ + if(glonass_gnav_eph.d_m){} // avoid warning, not needed + std::string line; + + // -------- Line 1 + line = std::string(5, ' '); + line += stringVersion; + line += std::string(11, ' '); + line += Rinex_Printer::leftJustify("OBSERVATION DATA", 20); + line += satelliteSystem["Mixed"]; + line += std::string(19, ' '); + line += std::string("RINEX VERSION / TYPE"); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line 2 + line.clear(); + line += Rinex_Printer::leftJustify("G = GPS R = GLONASS E = GALILEO S = GEO M = MIXED", 60); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line 3 + line.clear(); + line += Rinex_Printer::getLocalTime(); + line += std::string("PGM / RUN BY / DATE"); + line += std::string(1, ' '); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + line += Rinex_Printer::leftJustify("MIXED (GPS/GLO) OBSERVATION DATA FILE GENERATED BY GNSS-SDR", 60); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + std::string gnss_sdr_version(GNSS_SDR_VERSION); + line += "GNSS-SDR VERSION "; + line += Rinex_Printer::leftJustify(gnss_sdr_version, 43); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line COMMENT + line.clear(); + line += Rinex_Printer::leftJustify("See http://gnss-sdr.org", 60); + line += Rinex_Printer::leftJustify("COMMENT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line MARKER NAME + line.clear(); + line += Rinex_Printer::leftJustify("DEFAULT MARKER NAME", 60); // put a flag or a property, + line += Rinex_Printer::leftJustify("MARKER NAME", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line MARKER TYPE + line.clear(); + line += Rinex_Printer::leftJustify("NON_GEODETIC", 20); // put a flag or a property + line += std::string(40, ' '); + line += Rinex_Printer::leftJustify("MARKER TYPE", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line OBSERVER / AGENCY + line.clear(); + std::string username; + char c_username[20] = {0}; + int nGet = getlogin_r(c_username, sizeof(c_username) - 1); + if (nGet == 0) + { + username = c_username; + } + else + { + username = "UNKNOWN USER"; + } + line += leftJustify(username, 20); + line += Rinex_Printer::leftJustify("CTTC", 40); // add flag and property + line += Rinex_Printer::leftJustify("OBSERVER / AGENCY", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Line REC / TYPE VERS + line.clear(); + line += Rinex_Printer::leftJustify("GNSS-SDR", 20); // add flag and property + line += Rinex_Printer::leftJustify("Software Receiver", 20); // add flag and property + //line += Rinex_Printer::leftJustify(google::VersionString(), 20); // add flag and property + if(gnss_sdr_version.length() > 20) gnss_sdr_version.resize(9, ' '); + line += Rinex_Printer::leftJustify(gnss_sdr_version, 20); + line += Rinex_Printer::leftJustify("REC # / TYPE / VERS", 20); + lengthCheck(line); + out << line << std::endl; + + // -------- ANTENNA TYPE + line.clear(); + line += Rinex_Printer::leftJustify("Antenna number", 20); // add flag and property + line += Rinex_Printer::leftJustify("Antenna type", 20); // add flag and property + line += std::string(20, ' '); + line += Rinex_Printer::leftJustify("ANT # / TYPE", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- APPROX POSITION (optional for moving platforms) + // put here real data! + double antena_x = 0.0; + double antena_y = 0.0; + double antena_z = 0.0; + line.clear(); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_x, 4), 14); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_y, 4), 14); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_z, 4), 14); + line += std::string(18, ' '); + line += Rinex_Printer::leftJustify("APPROX POSITION XYZ", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- ANTENNA: DELTA H/E/N + // put here real data! + double antena_h = 0.0; + double antena_e = 0.0; + double antena_n = 0.0; + line.clear(); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_h, 4), 14); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_e, 4), 14); + line += Rinex_Printer::rightJustify(Rinex_Printer::asString(antena_n, 4), 14); + line += std::string(18, ' '); + line += Rinex_Printer::leftJustify("ANTENNA: DELTA H/E/N", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- SYS / OBS TYPES + // one line per available system + line.clear(); + line += satelliteSystem["GPS"]; + line += std::string(2, ' '); + std::stringstream strm; + numberTypesObservations = 4; + strm << numberTypesObservations; + line += Rinex_Printer::rightJustify(strm.str(), 3); + // per type of observation + // GPS L1 PSEUDORANGE + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GPS_L2_L2CM"]; + // GPS L1 PHASE + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GPS_L2_L2CM"]; + // GPS DOPPLER L1 + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GPS_L2_L2CM"]; + // GPS L1 CA SIGNAL STRENGTH + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GPS_L2_L2CM"]; + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // Find GLONASS Signal in Mixed file + unsigned int number_of_observations_glo = 0; + std::string signal_("1G"); + std::size_t found_1G = glonass_bands.find(signal_); + if(found_1G != std::string::npos) + { + number_of_observations_glo = number_of_observations_glo + 4; + } + signal_ = "2G"; + std::size_t found_2G = glonass_bands.find(signal_); + if(found_2G != std::string::npos) + { + number_of_observations_glo = number_of_observations_glo + 4; + } + line.clear(); + line += satelliteSystem["GLONASS"]; + line += std::string(2, ' '); + line += Rinex_Printer::rightJustify(std::to_string(number_of_observations_glo), 3); + if(found_1G != std::string::npos) + { + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GLONASS_G1_CA"]; + } + if(found_2G != std::string::npos) + { + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["CARRIER_PHASE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["DOPPLER"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += observationType["SIGNAL_STRENGTH"]; + line += observationCode["GLONASS_G2_CA"]; + } + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("SYS / # / OBS TYPES", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- Signal Strength units (only version 3) + line.clear(); + line += Rinex_Printer::leftJustify("DBHZ", 20); + line += std::string(40, ' '); + line += Rinex_Printer::leftJustify("SIGNAL STRENGTH UNIT", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- TIME OF FIRST OBS + line.clear(); + boost::posix_time::ptime p_gps_time = Rinex_Printer::compute_GPS_time(gps_eph, d_TOW_first_observation); + std::string timestring=boost::posix_time::to_iso_string(p_gps_time); + std::string year (timestring, 0, 4); + std::string month (timestring, 4, 2); + std::string day (timestring, 6, 2); + std::string hour (timestring, 9, 2); + std::string minutes (timestring, 11, 2); + double gps_t = d_TOW_first_observation; + double seconds = fmod(gps_t, 60); + line += Rinex_Printer::rightJustify(year, 6); + line += Rinex_Printer::rightJustify(month, 6); + line += Rinex_Printer::rightJustify(day, 6); + line += Rinex_Printer::rightJustify(hour, 6); + line += Rinex_Printer::rightJustify(minutes, 6); + line += Rinex_Printer::rightJustify(asString(seconds, 7), 13); + line += Rinex_Printer::rightJustify(std::string("GPS"), 8); + line += std::string(9, ' '); + line += Rinex_Printer::leftJustify("TIME OF FIRST OBS", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- GLONASS SLOT / FRQ # + // TODO Need to provide system with list of all satellites and update this accordingly + line.clear(); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 3); // Number of satellites in list + line += std::string(1, ' '); + line += satelliteSystem["GLONASS"]; + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Slot Number + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(boost::lexical_cast(0), 2); // Frequency Number + line += std::string(1, ' '); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS SLOT / FRQ #", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- GLONASS CODE/PHS/BIS + // No GLONASS Phase bias correction used to align code and phase observations. + line.clear(); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G1_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_CA"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(1, ' '); + line += observationType["PSEUDORANGE"]; + line += observationCode["GLONASS_G2_P"]; + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(asString(0.0, 3), 8); + line += std::string(60-line.size(), ' '); + line += Rinex_Printer::leftJustify("GLONASS COD/PHS/BIS", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- end of header + line.clear(); + line += std::string(60, ' '); + line += Rinex_Printer::leftJustify("END OF HEADER", 20); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; +} + void Rinex_Printer::rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& galileo_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, const double d_TOW_first_observation, const std::string galileo_bands, const std::string glonass_bands) { if(glonass_gnav_eph.d_m){} // avoid warning, not needed @@ -3929,14 +4458,14 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& line.clear(); unsigned int number_of_observations_glo = 0; signal_ = "1G"; - std::size_t found_1C = glonass_bands.find(signal_); - if(found_1C != std::string::npos) + std::size_t found_1G = glonass_bands.find(signal_); + if(found_1G != std::string::npos) { number_of_observations_glo = number_of_observations_glo + 4; } signal_ = "2G"; - std::size_t found_2C = glonass_bands.find(signal_); - if(found_2C != std::string::npos) + std::size_t found_2G = glonass_bands.find(signal_); + if(found_2G != std::string::npos) { number_of_observations_glo = number_of_observations_glo + 4; } @@ -3945,7 +4474,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& line += std::string(2, ' '); line += Rinex_Printer::rightJustify(std::to_string(number_of_observations_glo), 3); - if(found_1C != std::string::npos) + if(found_1G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -3961,7 +4490,7 @@ void Rinex_Printer::rinex_obs_header(std::fstream& out, const Galileo_Ephemeris& line += observationCode["GLONASS_L1_CA"]; } - if(found_2C != std::string::npos) + if(found_2G != std::string::npos) { line += std::string(1, ' '); line += observationType["PSEUDORANGE"]; @@ -6042,6 +6571,246 @@ void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_Ephemeris& gps_ep } +void Rinex_Printer::log_rinex_obs(std::fstream& out, const Gps_CNAV_Ephemeris& gps_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double gps_obs_time, const std::map& observables) +{ + if(glonass_gnav_eph.d_m){} // avoid warning, not needed + std::string line; + + // -------- EPOCH record + boost::posix_time::ptime p_gps_time = Rinex_Printer::compute_GPS_time(gps_eph, gps_obs_time); + std::string timestring = boost::posix_time::to_iso_string(p_gps_time); + //double utc_t = nav_msg.utc_time(nav_msg.sv_clock_correction(obs_time)); + //double gps_t = eph.sv_clock_correction(obs_time); + double gps_t = gps_obs_time; + + std::string month (timestring, 4, 2); + std::string day (timestring, 6, 2); + std::string hour (timestring, 9, 2); + std::string minutes (timestring, 11, 2); + + std::string year (timestring, 0, 4); + line += std::string(1, '>'); + line += std::string(1, ' '); + line += year; + line += std::string(1, ' '); + line += month; + line += std::string(1, ' '); + line += day; + line += std::string(1, ' '); + line += hour; + line += std::string(1, ' '); + line += minutes; + + line += std::string(1, ' '); + double seconds = fmod(gps_t, 60); + // Add extra 0 if seconds are < 10 + if (seconds < 10) + { + line +=std::string(1, '0'); + } + line += Rinex_Printer::asString(seconds, 7); + line += std::string(2, ' '); + // Epoch flag 0: OK 1: power failure between previous and current epoch <1: Special event + line += std::string(1, '0'); + + + //Number of satellites observed in current epoch + //Get maps with observations + std::map observablesG2S; + std::map observablesR1C; + std::map observablesR2C; + std::map::const_iterator observables_iter; + + for(observables_iter = observables.begin(); + observables_iter != observables.end(); + observables_iter++) + { + std::string system_(&observables_iter->second.System, 1); + std::string sig_(observables_iter->second.Signal); + if((system_.compare("R") == 0) && (sig_.compare("1G") == 0)) + { + observablesR1C.insert(std::pair(observables_iter->first, observables_iter->second)); + } + if((system_.compare("R") == 0) && (sig_.compare("2G") == 0)) + { + observablesR2C.insert(std::pair(observables_iter->first, observables_iter->second)); + } + if((system_.compare("G") == 0) && (sig_.compare("2S") == 0)) + { + observablesG2S.insert(std::pair(observables_iter->first, observables_iter->second)); + } + } + + std::multimap total_glo_map; + std::set available_glo_prns; + std::set::iterator it; + for(observables_iter = observablesR1C.begin(); + observables_iter != observablesR1C.end(); + observables_iter++) + { + unsigned int prn_ = observables_iter->second.PRN; + total_glo_map.insert(std::pair(prn_, observables_iter->second)); + it = available_glo_prns.find(prn_); + if(it == available_glo_prns.end()) + { + available_glo_prns.insert(prn_); + } + } + + for(observables_iter = observablesR2C.begin(); + observables_iter != observablesR2C.end(); + observables_iter++) + { + unsigned int prn_ = observables_iter->second.PRN; + total_glo_map.insert(std::pair(prn_, observables_iter->second)); + it = available_glo_prns.find(prn_); + if(it == available_glo_prns.end()) + { + available_glo_prns.insert(prn_); + } + } + + int numGloSatellitesObserved = available_glo_prns.size(); + int numGpsSatellitesObserved = observablesG2S.size(); + int numSatellitesObserved = numGloSatellitesObserved + numGpsSatellitesObserved; + line += Rinex_Printer::rightJustify(boost::lexical_cast(numSatellitesObserved), 3); + + line += std::string(80 - line.size(), ' '); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + // -------- OBSERVATION record + std::string s; + std::string lineObs; + for(observables_iter = observablesG2S.begin(); + observables_iter != observablesG2S.end(); + observables_iter++) + { + lineObs.clear(); + + s.assign(1, observables_iter->second.System); + // Specify system only if in version 3 + if(s.compare("G") == 0) lineObs += satelliteSystem["GPS"]; + if(s.compare("R") == 0) lineObs += satelliteSystem["GLONASS"]; // should not happen + if (static_cast(observables_iter->second.PRN) < 10) lineObs += std::string(1, '0'); + lineObs += boost::lexical_cast(static_cast(observables_iter->second.PRN)); + + + // Pseudorange Measurements + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Pseudorange_m, 3), 14); + + //Loss of lock indicator (LLI) + int lli = 0; // Include in the observation!! + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + + // Signal Strength Indicator (SSI) + int ssi = Rinex_Printer::signalStrength(observables_iter->second.CN0_dB_hz); + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // PHASE + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_phase_rads/GPS_TWO_PI, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // DOPPLER + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.Carrier_Doppler_hz, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // SIGNAL STRENGTH + lineObs += Rinex_Printer::rightJustify(asString(observables_iter->second.CN0_dB_hz, 3), 14); + + if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); + out << lineObs << std::endl; + } + + std::pair ::iterator, std::multimap::iterator> ret; + for(it = available_glo_prns.begin(); + it != available_glo_prns.end(); + it++) + { + lineObs.clear(); + lineObs += satelliteSystem["GLONASS"]; + if (static_cast(*it) < 10) lineObs += std::string(1, '0'); + lineObs += boost::lexical_cast(static_cast(*it)); + + ret = total_glo_map.equal_range(*it); + for (std::multimap::iterator iter = ret.first; iter != ret.second; ++iter) + { + /// \todo Need to account for pseudorange correction for glonass + double leap_seconds = Rinex_Printer::get_leap_second(glonass_gnav_eph, gps_obs_time); + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Pseudorange_m, 3), 14); + + //Loss of lock indicator (LLI) + int lli = 0; // Include in the observation!! + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + + // Signal Strength Indicator (SSI) + int ssi = Rinex_Printer::signalStrength(iter->second.CN0_dB_hz); + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS CARRIER PHASE + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_phase_rads / (GLONASS_TWO_PI), 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS DOPPLER + lineObs += Rinex_Printer::rightJustify(asString(iter->second.Carrier_Doppler_hz, 3), 14); + if (lli == 0) + { + lineObs += std::string(1, ' '); + } + else + { + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(lli), 1); + } + lineObs += Rinex_Printer::rightJustify(Rinex_Printer::asString(ssi), 1); + + // GLONASS SIGNAL STRENGTH + lineObs += Rinex_Printer::rightJustify(asString(iter->second.CN0_dB_hz, 3), 14); + } + + if (lineObs.size() < 80) lineObs += std::string(80 - lineObs.size(), ' '); + out << lineObs << std::endl; + } + +} + void Rinex_Printer::log_rinex_obs(std::fstream& out, const Galileo_Ephemeris& galileo_eph, const Glonass_Gnav_Ephemeris& glonass_gnav_eph, double galileo_obs_time, const std::map& observables) { if(glonass_gnav_eph.d_m){} // avoid warning, not needed diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index fb6ee27b5..ee90ef3a4 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -128,6 +128,11 @@ public: */ void rinex_nav_header(std::fstream & out, const Gps_Iono & gps_iono, const Gps_Utc_Model & gps_utc_model, const Glonass_Gnav_Utc_Model & glonass_gnav_utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); + /*! + * \brief Generates the Mixed (GPS L2C C/A/GLONASS L1, L2) Navigation Data header + */ + void rinex_nav_header(std::fstream & out, const Gps_CNAV_Iono & gps_iono, const Gps_CNAV_Utc_Model & gps_utc_model, const Glonass_Gnav_Utc_Model & glonass_gnav_utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); + /*! * \brief Generates the GPS Observation data header */ @@ -168,6 +173,11 @@ public: */ void rinex_obs_header(std::fstream & out, const Galileo_Ephemeris & galileo_eph, const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const double d_TOW_first_observation, const std::string galileo_bands = "1B", const std::string glo_bands = "1C"); + /*! + * \brief Generates the Mixed (GPS L2C/GLONASS) Observation data header. Example: galileo_bands("1G")... Default: "1G". + */ + void rinex_obs_header(std::fstream & out, const Gps_CNAV_Ephemeris & gps_cnav_eph, const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const double d_TOW_first_observation, const std::string glo_bands = "1G"); + /*! * \brief Generates the SBAS raw data header */ @@ -239,6 +249,11 @@ public: */ void log_rinex_nav(std::fstream & out, const std::map & gps_eph_map, const std::map & glonass_gnav_eph_map); + /*! + * \brief Writes data from the Mixed (GPS/GLONASS GNAV) navigation message into the RINEX file + */ + void log_rinex_nav(std::fstream & out, const std::map & gps_cnav_eph_map, const std::map & glonass_gnav_eph_map); + /*! * \brief Writes data from the Mixed (Galileo/ GLONASS GNAV) navigation message into the RINEX file */ @@ -279,6 +294,11 @@ public: */ void log_rinex_obs(std::fstream & out, const Gps_Ephemeris & gps_eph, const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const double gps_obs_time, const std::map & observables); + /*! + * \brief Writes Mixed GPS L2C - GLONASS observables into the RINEX file + */ + void log_rinex_obs(std::fstream & out, const Gps_CNAV_Ephemeris & gps_cnav_eph, const Glonass_Gnav_Ephemeris & glonass_gnav_eph, const double gps_obs_time, const std::map & observables); + /*! * \brief Writes Mixed Galileo/GLONASS observables into the RINEX file */ @@ -306,6 +326,8 @@ public: void update_nav_header(std::fstream & out, const Gps_Iono & gps_iono, const Gps_Utc_Model & gps_utc, const Glonass_Gnav_Utc_Model & glonass_gnav_utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); + void update_nav_header(std::fstream & out, const Gps_CNAV_Iono & gps_cnav_iono, const Gps_CNAV_Utc_Model & gps_cnav_utc, const Glonass_Gnav_Utc_Model & glonass_gnav_utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); + void update_nav_header(std::fstream & out, const Galileo_Iono & galileo_iono, const Galileo_Utc_Model & galileo_utc_model, const Galileo_Almanac& galileo_almanac, const Glonass_Gnav_Utc_Model & glonass_gnav_utc_model, const Glonass_Gnav_Almanac & glonass_gnav_almanac); void update_obs_header(std::fstream & out, const Gps_Utc_Model & utc_model);