From f6a55955aeb96f484eae38ffcb2b9b8f9d4c596f Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 31 Aug 2014 15:58:09 +0200 Subject: [PATCH] Introducing RINEX Galileo navigation data file. --- .../PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc | 56 ++-- src/algorithms/PVT/libs/rinex_printer.cc | 285 +++++++++++++++++- src/algorithms/PVT/libs/rinex_printer.h | 14 +- 3 files changed, 318 insertions(+), 37 deletions(-) diff --git a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc index 163bc0a0d..87042d8f7 100644 --- a/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/galileo_e1_pvt_cc.cc @@ -177,35 +177,35 @@ int galileo_e1_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_it { d_kml_dump->print_position_galileo(d_ls_pvt, d_flag_averaging); //ToDo: Implement Galileo RINEX and Galileo NMEA outputs - // d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging); + // d_nmea_printer->Print_Nmea_Line(d_ls_pvt, d_flag_averaging); // - // if (!b_rinex_header_writen) // & we have utc data in nav message! - // { - // std::map::iterator galileo_ephemeris_iter; - // galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin(); - // if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) - // { - // rp->rinex_obs_header(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time); - // rp->rinex_nav_header(rp->navFile, d_ls_pvt->galielo_iono, d_ls_pvt->galileo_utc_model); - // b_rinex_header_writen = true; // do not write header anymore - // } - // } - // if(b_rinex_header_writen) // Put here another condition to separate annotations (e.g 30 s) - // { - // // Limit the RINEX navigation output rate to 1/6 seg - // // Notice that d_sample_counter period is 1ms (for GPS correlators) - // if ((d_sample_counter-d_last_sample_nav_output)>=6000) - // { - // rp->log_rinex_nav(rp->navFile, d_ls_pvt->gps_ephemeris_map); - // d_last_sample_nav_output=d_sample_counter; - // } - // std::map::iterator gps_ephemeris_iter; - // gps_ephemeris_iter = d_ls_pvt->gps_ephemeris_map.begin(); - // if (gps_ephemeris_iter != d_ls_pvt->gps_ephemeris_map.end()) - // { - // rp->log_rinex_obs(rp->obsFile, gps_ephemeris_iter->second, d_rx_time, gnss_pseudoranges_map); - // } - // } + if (!b_rinex_header_writen) // & we have utc data in nav message! + { + std::map::iterator galileo_ephemeris_iter; + galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin(); + if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) + { + //rp->rinex_obs_header(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time); + rp->rinex_nav_header(rp->navGalFile, d_ls_pvt->galileo_iono, d_ls_pvt->galileo_utc_model); + b_rinex_header_writen = true; // do not write header anymore + } + } + if(b_rinex_header_writen) // Put here another condition to separate annotations (e.g 30 s) + { + // Limit the RINEX navigation output rate to 1/6 seg + // Notice that d_sample_counter period is 4ms (for Galileo correlators) + if ((d_sample_counter - d_last_sample_nav_output) >= 6000) + { + rp->log_rinex_nav(rp->navGalFile, d_ls_pvt->galileo_ephemeris_map); + d_last_sample_nav_output = d_sample_counter; + } + // std::map::iterator galileo_ephemeris_iter; + // galileo_ephemeris_iter = d_ls_pvt->galileo_ephemeris_map.begin(); + // if (galileo_ephemeris_iter != d_ls_pvt->galileo_ephemeris_map.end()) + // { + // rp->log_rinex_obs(rp->obsFile, galileo_ephemeris_iter->second, d_rx_time, gnss_pseudoranges_map); + // } + } } } diff --git a/src/algorithms/PVT/libs/rinex_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc index 2fb50a119..e8b8de1aa 100644 --- a/src/algorithms/PVT/libs/rinex_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -42,10 +42,7 @@ #include #include #include "sbas_telemetry_data.h" -#include "gps_navigation_message.h" -#include "gps_ephemeris.h" -#include "gps_iono.h" -#include "gps_utc_model.h" + using google::LogMessage; @@ -58,10 +55,13 @@ Rinex_Printer::Rinex_Printer() navfilename = Rinex_Printer::createFilename("RINEX_FILE_TYPE_GPS_NAV"); obsfilename = Rinex_Printer::createFilename("RINEX_FILE_TYPE_OBS"); sbsfilename = Rinex_Printer::createFilename("RINEX_FILE_TYPE_SBAS"); + navGalfilename = Rinex_Printer::createFilename("RINEX_FILE_TYPE_GAL_NAV"); + Rinex_Printer::navFile.open(navfilename, std::ios::out | std::ios::app); Rinex_Printer::obsFile.open(obsfilename, std::ios::out | std::ios::app); Rinex_Printer::sbsFile.open(sbsfilename, std::ios::out | std::ios::app); + Rinex_Printer::navGalFile.open(navGalfilename, std::ios::out | std::ios::app); // RINEX v3.00 codes satelliteSystem["GPS"] = "G"; @@ -167,13 +167,15 @@ Rinex_Printer::Rinex_Printer() Rinex_Printer::~Rinex_Printer() { // close RINEX files - long posn, poso, poss; + long posn, poso, poss, posng; posn = navFile.tellp(); poso = obsFile.tellp(); poss = obsFile.tellp(); + posng = navGalFile.tellp(); Rinex_Printer::navFile.close(); Rinex_Printer::obsFile.close(); Rinex_Printer::sbsFile.close(); + Rinex_Printer::navGalFile.close(); // If nothing written, erase the files. if (posn == 0) { @@ -187,6 +189,10 @@ Rinex_Printer::~Rinex_Printer() { remove(sbsfilename.c_str()); } + if (posng == 0) + { + remove(navGalfilename.c_str()); + } } @@ -353,6 +359,108 @@ std::string Rinex_Printer::getLocalTime() } +void Rinex_Printer::rinex_nav_header(std::ofstream& out, Galileo_Iono iono, Galileo_Utc_Model utc_model) +{ + + std::string line; + stringVersion = "3.01"; + 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("E: GALILEO"); + line += std::string(10, ' '); + 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("GALILEO 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(); + 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("GAL "); + line += std::string(1, ' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.ai0_5, 10, 2), 12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.ai1_5, 10, 2), 12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(iono.ai2_5, 10, 2), 12); + double zero = 0.0; + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(zero, 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 + line.clear(); + line += std::string("GAUT"); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.A0_6, 16, 2), 18); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.A1_6, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.t0t_6), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.WNot_6), 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("GPGA"); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.XXX, 16, 2), 18); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(utc_model.XXX, 15, 2), 16); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.XXX), 7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.XXX), 5); + 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(utc_model.Delta_tLS_6), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.Delta_tLSF_6), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.WN_LSF_6), 6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(utc_model.DN_6), 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::ofstream& out, Gps_Iono iono, Gps_Utc_Model utc_model) { @@ -524,7 +632,6 @@ void Rinex_Printer::rinex_nav_header(std::ofstream& out, Gps_Iono iono, Gps_Utc_ } - void Rinex_Printer::rinex_sbs_header(std::ofstream& out) { std::string line; @@ -911,6 +1018,158 @@ void Rinex_Printer::log_rinex_nav(std::ofstream& out, std::map eph_map) +{ + std::string line; + std::map::iterator galileo_ephemeris_iter; + line.clear(); + for(galileo_ephemeris_iter = eph_map.begin(); + galileo_ephemeris_iter != eph_map.end(); + galileo_ephemeris_iter++) + { + // -------- SV / EPOCH / SV CLK + boost::posix_time::ptime p_utc_time = Rinex_Printer::compute_Galileo_time(galileo_ephemeris_iter->second, galileo_ephemeris_iter->second.TOW_5); + std::string timestring = boost::posix_time::to_iso_string(p_utc_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 seconds (timestring, 13, 2); + + line += satelliteSystem["Galileo"]; + if (galileo_ephemeris_iter->second.i_satellite_PRN < 10) line += std::string("0"); + line += boost::lexical_cast(galileo_ephemeris_iter->second.i_satellite_PRN); + std::string year (timestring, 0, 4); + 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, ' '); + line += seconds; + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.af0_4, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.af1_4, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.af2_4, 18, 2); + + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- BROADCAST ORBIT - 1 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.IOD_ephemeris, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_rs_3, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.delta_n_3, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.M0_1, 18, 2); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- BROADCAST ORBIT - 2 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_uc_3, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.e_1, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_us_3, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.A_1, 18, 2); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + + // -------- BROADCAST ORBIT - 3 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.t0e_1, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_ic_4, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.OMEGA_0_2, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_is_4, 18, 2); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + + + // -------- BROADCAST ORBIT - 4 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.i_0_2, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.C_rc_3, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.omega_2, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.OMEGA_dot_3, 18, 2); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + + // -------- BROADCAST ORBIT - 5 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.iDot_2, 18, 2); + line += std::string(1, ' '); + double zero = 0.0; + line += Rinex_Printer::doub2for(zero, 18, 2); + line += std::string(1, ' '); + double Galileo_week_continuous_number = (double)(galileo_ephemeris_iter->second.WN_5); + line += Rinex_Printer::doub2for(Galileo_week_continuous_number, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- BROADCAST ORBIT - 6 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); // + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); // + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); // + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + // -------- BROADCAST ORBIT - 7 + line.clear(); + line += std::string(5, ' '); + line += Rinex_Printer::doub2for(galileo_ephemeris_iter->second.TOW_5, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(zero, 18, 2); + line += std::string(1, ' '); + line += std::string(18, ' '); // spare + line += std::string(1, ' '); + line += std::string(18, ' '); // spare + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + line.clear(); + } +} + + void Rinex_Printer::rinex_obs_header(std::ofstream& out, Gps_Ephemeris eph, double d_TOW_first_observation) { @@ -1529,6 +1788,20 @@ boost::posix_time::ptime Rinex_Printer::compute_GPS_time(Gps_Ephemeris eph, doub return p_time; } + + +boost::posix_time::ptime Rinex_Printer::compute_Galileo_time(Galileo_Ephemeris eph, double obs_time) +{ + // The RINEX v2.11 v3.00 format uses GPS time for the observations epoch, not UTC time, thus, no leap seconds needed here. + // (see Section 3 in http://igscb.jpl.nasa.gov/igscb/data/format/rinex211.txt) + // (see Pag. 17 in http://igscb.jpl.nasa.gov/igscb/data/format/rinex300.pdf) + // --??? No time correction here, since it will be done in the RINEX processor + double galileo_t = obs_time; + boost::posix_time::time_duration t = boost::posix_time::millisec((galileo_t + 604800*(double)(eph.WN_5))*1000); + boost::posix_time::ptime p_time(boost::gregorian::date(1999, 8, 22), t); + return p_time; +} + /* enum RINEX_enumMarkerType { diff --git a/src/algorithms/PVT/libs/rinex_printer.h b/src/algorithms/PVT/libs/rinex_printer.h index ae86eb43f..9f3ec1e81 100644 --- a/src/algorithms/PVT/libs/rinex_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -57,9 +57,11 @@ #include // for stringstream #include // for setprecision #include +#include #include "gps_navigation_message.h" -#include "boost/date_time/posix_time/posix_time.hpp" +#include "galileo_navigation_message.h" #include "GPS_L1_CA.h" +#include "Galileo_E1.h" #include "gnss_synchro.h" class Sbas_Raw_Msg; @@ -84,12 +86,15 @@ public: std::ofstream obsFile ; // eph_map); + void log_rinex_nav(std::ofstream& out, std::map eph_map); + + void log_rinex_nav(std::ofstream& out, std::map eph_map); /*! * \brief Writes observables into the RINEX file @@ -165,6 +172,7 @@ private: std::string navfilename; std::string obsfilename; std::string sbsfilename; + std::string navGalfilename; /* * Generates the data for the PGM / RUN BY / DATE line