diff --git a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc index d970008da..6da2875c1 100644 --- a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc +++ b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.cc @@ -4,7 +4,7 @@ * \author Javier Arribas, 2011. jarribas(at)cttc.es * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -27,6 +27,7 @@ * ------------------------------------------------------------------------- */ +#include "gps_l1_ca_pvt_cc.h" #include #include #include @@ -38,9 +39,8 @@ #include #include #include -#include "gps_l1_ca_pvt_cc.h" #include "control_message_factory.h" -#include "rinex_2_1_printer.h" + using google::LogMessage; @@ -77,7 +77,7 @@ gps_l1_ca_pvt_cc::gps_l1_ca_pvt_cc(unsigned int nchannels, gr_msg_queue_sptr que d_sample_counter=0; b_rinex_header_writen = false; - rp = new rinex_printer(); + rp = new Rinex_Printer(); } gps_l1_ca_pvt_cc::~gps_l1_ca_pvt_cc() { @@ -127,25 +127,28 @@ int gps_l1_ca_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_ite gps_navigation_message nav_msg; while (d_nav_queue->try_pop(nav_msg)==true) { - std::cout<<"New ephemeris record has arrived from SAT ID "<d_ephemeris[nav_msg.d_channel_ID]=nav_msg; + d_ls_pvt->d_ephemeris[nav_msg.i_channel_ID]=nav_msg; // **** update pseudoranges clock **** - if (nav_msg.d_satellite_PRN==gnss_pseudoranges_iter->second.SV_ID) + if (nav_msg.i_satellite_PRN==gnss_pseudoranges_iter->second.SV_ID) { d_ephemeris_clock_s=d_last_nav_msg.d_TOW; d_ephemeris_timestamp_ms=d_last_nav_msg.d_subframe1_timestamp_ms; } - // **** write ephemeris to RINES NAV file - //d_rinex_printer.LogRinex2Nav(nav_msg); + // write ephemeris to RINES NAV file, if created. Put here another condition to separate anotations + if(b_rinex_header_writen) + { + rp->LogRinexNav(rp->navFile, d_last_nav_msg); + } } // ############ 2. COMPUTE THE PVT ################################ // write the pseudoranges to RINEX OBS file // 1- need a valid clock - if (d_ephemeris_clock_s>0 and d_last_nav_msg.d_satellite_PRN>0) + if (d_ephemeris_clock_s>0 and d_last_nav_msg.i_satellite_PRN>0) { - //d_rinex_printer.LogRinex2Obs(d_last_nav_msg,d_ephemeris_clock_s+((double)pseudoranges_timestamp_ms-d_ephemeris_timestamp_ms)/1000.0,pseudoranges); + //d_Rinex_Printer.LogRinex2Obs(d_last_nav_msg,d_ephemeris_clock_s+((double)pseudoranges_timestamp_ms-d_ephemeris_timestamp_ms)/1000.0,pseudoranges); // compute on the fly PVT solution //std::cout<<"diff_clock_ephemeris="<<(gnss_pseudoranges_iter->second.timestamp_ms-d_ephemeris_timestamp_ms)/1000.0<<"\r\n"; if (d_ls_pvt->get_PVT(gnss_pseudoranges_map, @@ -155,11 +158,11 @@ int gps_l1_ca_pvt_cc::general_work (int noutput_items, gr_vector_int &ninput_ite d_kml_dump.print_position(d_ls_pvt,d_flag_averaging); if (!b_rinex_header_writen) // & we have utc data in nav message! { - // rinex_printer rinex_printer(d_last_nav_msg); - rp->Rinex2NavHeader(rp->navFile, d_last_nav_msg); - rp->Rinex2ObsHeader(rp->obsFile, d_last_nav_msg); + rp->RinexNavHeader(rp->navFile, d_last_nav_msg); + rp->RinexObsHeader(rp->obsFile, d_last_nav_msg); b_rinex_header_writen=true; // do not write header anymore } + } } diff --git a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h index 6a0c31bda..e3641cf95 100644 --- a/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h +++ b/src/algorithms/PVT/gnuradio_blocks/gps_l1_ca_pvt_cc.h @@ -4,7 +4,7 @@ * \author Javier Arribas, 2011. jarribas(at)cttc.es * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -39,7 +39,7 @@ #include "concurrent_queue.h" #include "gps_navigation_message.h" #include "kml_printer.h" -#include "rinex_2_1_printer.h" +#include "rinex_printer.h" #include "gps_l1_ca_ls_pvt.h" #include "GPS_L1_CA.h" @@ -66,7 +66,7 @@ private: bool b_rinex_header_writen; //std::ofstream Rinex_Nav_File; //std::ofstream Rinex_Obs_File; - rinex_printer *rp; + Rinex_Printer *rp; unsigned int d_nchannels; @@ -86,7 +86,7 @@ private: double d_ephemeris_clock_s; double d_ephemeris_timestamp_ms; gps_l1_ca_ls_pvt *d_ls_pvt; - //rinex_printer d_rinex_printer; // RINEX printer class + public: diff --git a/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc b/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc index e4cf5eea6..ca8e3767a 100644 --- a/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc +++ b/src/algorithms/PVT/libs/gps_l1_ca_ls_pvt.cc @@ -220,7 +220,7 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map gnss_pseudoranges_ { if (d_ephemeris[i].satellite_validation()==true) { - gnss_pseudoranges_iter=gnss_pseudoranges_map.find(d_ephemeris[i].d_satellite_PRN); + gnss_pseudoranges_iter=gnss_pseudoranges_map.find(d_ephemeris[i].i_satellite_PRN); if (gnss_pseudoranges_iter!=gnss_pseudoranges_map.end()) { /*! @@ -242,7 +242,7 @@ bool gps_l1_ca_ls_pvt::get_PVT(std::map gnss_pseudoranges_ satpos(0,i)=d_ephemeris[i].d_satpos_X; satpos(1,i)=d_ephemeris[i].d_satpos_Y; satpos(2,i)=d_ephemeris[i].d_satpos_Z; - LOG_AT_LEVEL(INFO)<<"ECEF satellite SV ID="<second.pseudorange_m+d_ephemeris[i].d_satClkCorr*GPS_C_m_s; valid_obs++; diff --git a/src/algorithms/PVT/libs/jamfile.jam b/src/algorithms/PVT/libs/jamfile.jam index 443796f6d..fad9b10e8 100644 --- a/src/algorithms/PVT/libs/jamfile.jam +++ b/src/algorithms/PVT/libs/jamfile.jam @@ -1,5 +1,5 @@ project : build-dir ../../../../build ; -obj rinex_2_1_printer : rinex_2_1_printer.cc ; +obj rinex_printer : rinex_printer.cc ; obj gps_l1_ca_ls_pvt : gps_l1_ca_ls_pvt.cc ; obj kml_printer : kml_printer.cc ; \ No newline at end of file diff --git a/src/algorithms/PVT/libs/rinex_2_1_printer.cc b/src/algorithms/PVT/libs/rinex_printer.cc similarity index 50% rename from src/algorithms/PVT/libs/rinex_2_1_printer.cc rename to src/algorithms/PVT/libs/rinex_printer.cc index 57ee0abd2..37863bb8a 100644 --- a/src/algorithms/PVT/libs/rinex_2_1_printer.cc +++ b/src/algorithms/PVT/libs/rinex_printer.cc @@ -1,6 +1,6 @@ /*! - * \file rinex_2_1_printer.cc (temporal name) - * \brief Implementation of a RINEX 3.01 printer + * \file rinex_printer.cc + * \brief Implementation of a RINEX 2.11 / 3.01 printer * See http://igscb.jpl.nasa.gov/igscb/data/format/rinex301.pdf * \author Carles Fernandez Prades, 2011. cfernandez(at)cttc.es * ------------------------------------------------------------------------- @@ -28,7 +28,7 @@ * ------------------------------------------------------------------------- */ -#include "rinex_2_1_printer.h" +#include "rinex_printer.h" #include "gps_navigation_message.h" #include #include @@ -49,12 +49,15 @@ using google::LogMessage; +DEFINE_string(RINEX_version, "3.01", + "Specifies the RINEX version (2.11 or 3.01)"); -rinex_printer::rinex_printer() + +Rinex_Printer::Rinex_Printer() { - rinex_printer::navFile.open(rinex_printer::createFilename("RINEX_FILE_TYPE_GPS_NAV"), std::ios::out | std::ios::app); - rinex_printer::obsFile.open(rinex_printer::createFilename("RINEX_FILE_TYPE_OBS"), std::ios::out | std::ios::app); + Rinex_Printer::navFile.open(Rinex_Printer::createFilename("RINEX_FILE_TYPE_GPS_NAV"), std::ios::out | std::ios::app); + Rinex_Printer::obsFile.open(Rinex_Printer::createFilename("RINEX_FILE_TYPE_OBS"), std::ios::out | std::ios::app); satelliteSystem["GPS"]="G"; satelliteSystem["GLONASS"]="R"; @@ -123,21 +126,42 @@ rinex_printer::rinex_printer() observationType["DOPPLER"]="D"; observationType["SIGNAL_STRENGTH"]="S"; + if (FLAGS_RINEX_version.compare("3.01") == 0 ) + { + version = 3; + stringVersion="3.01"; + } + else if (FLAGS_RINEX_version.compare("2.11") == 0 ) + { + version = 2; + stringVersion="2.10"; + } + else if (FLAGS_RINEX_version.compare("2.10") == 0 ) + { + version = 2; + stringVersion="2.10"; + } + else + { + LOG_AT_LEVEL(ERROR) << "Unknown RINEX version " << FLAGS_RINEX_version << " (must be 2.11 or 3.01)" << std::endl; + } + + } -rinex_printer::~rinex_printer() +Rinex_Printer::~Rinex_Printer() { // close RINEX files - rinex_printer::navFile.close(); - rinex_printer::obsFile.close(); + Rinex_Printer::navFile.close(); + Rinex_Printer::obsFile.close(); } -void rinex_printer::lengthCheck(std::string line) +void Rinex_Printer::lengthCheck(std::string line) { if (line.length() != 80) { @@ -149,7 +173,7 @@ void rinex_printer::lengthCheck(std::string line) } -std::string rinex_printer::createFilename(std::string type){ +std::string Rinex_Printer::createFilename(std::string type){ const std::string stationName = "GSDR"; // 4-character station name designator boost::gregorian::date today = boost::gregorian::day_clock::local_day(); const int dayOfTheYear = today.day_of_year(); @@ -159,7 +183,6 @@ std::string rinex_printer::createFilename(std::string type){ strm0 << dayOfTheYear; std::string dayOfTheYearTag=strm0.str(); - std::map fileType; fileType.insert(std::pair("RINEX_FILE_TYPE_OBS","O")); // O - Observation file. fileType.insert(std::pair("RINEX_FILE_TYPE_GPS_NAV","N")); // N - GPS navigation message file. @@ -179,7 +202,6 @@ std::string rinex_printer::createFilename(std::string type){ strm << local_hour; std::map Hmap; - Hmap.insert(std::pair("0","a")); Hmap.insert(std::pair("1","b")); Hmap.insert(std::pair("2","c")); @@ -226,113 +248,204 @@ std::string rinex_printer::createFilename(std::string type){ } -std::string rinex_printer::getLocalTime() +std::string Rinex_Printer::getLocalTime() { std::string line; line +=std::string("GNSS-SDR"); line +=std::string(12,' '); - line += rinex_printer::leftJustify("CTTC", 20);//put a flag to let the user change this + line += Rinex_Printer::leftJustify("CTTC", 20); //put a flag to let the user change this boost::gregorian::date today = boost::gregorian::day_clock::local_day(); - line +=boost::gregorian::to_iso_string(today); - line +=std::string(1,' '); - boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone("UTC")); boost::local_time::local_date_time pt = boost::local_time::local_sec_clock::local_time(zone); tm pt_tm=boost::local_time::to_tm(pt); - std::stringstream strm0; + std::stringstream strmHour; int utc_hour=pt_tm.tm_hour; - if (utc_hour<10) strm0 << "0"; // two digits for hours - strm0 << utc_hour; - line += strm0.str(); + if (utc_hour<10) strmHour << "0"; // two digits for hours + strmHour << utc_hour; - std::stringstream strm1; + std::stringstream strmMin; int utc_minute=pt_tm.tm_min; - if (utc_minute<10) strm1 << "0"; // two digits for minutes - strm1 << utc_minute; - line += strm1.str(); + if (utc_minute<10) strmMin << "0"; // two digits for minutes + strmMin << utc_minute; + + if (version == 2) + { + int day= pt_tm.tm_mday; + line += Rinex_Printer::rightJustify(boost::lexical_cast(day),2); + line += std::string("-"); + + std::map months; + months[0]="JAN"; + months[1]="FEB"; + months[2]="MAR"; + months[3]="APR"; + months[4]="MAY"; + months[5]="JUN"; + months[6]="JUL"; + months[7]="AUG"; + months[8]="SEP"; + months[9]="OCT"; + months[10]="NOV"; + months[11]="DEC"; + + line += months[pt_tm.tm_mon]; + line += std::string("-"); + line += boost::lexical_cast(pt_tm.tm_year-100); + line +=std::string(1,' '); + line += strmHour.str(); + line +=std::string(":"); + line += strmMin.str(); + line +=std::string(5,' '); + } + + if (version == 3) + { + line +=std::string(1,' '); + line +=boost::gregorian::to_iso_string(today); + line += strmHour.str(); + line += strmMin.str(); + + std::stringstream strm2; + int utc_seconds=pt_tm.tm_sec; + if (utc_seconds<10) strm2 << "0"; // two digits for seconds + strm2 << utc_seconds; + line += strm2.str(); + line +=std::string(1,' '); + line +=std::string("UTC"); + line +=std::string(1,' '); + } - std::stringstream strm2; - int utc_seconds=pt_tm.tm_sec; - if (utc_seconds<10) strm2 << "0"; // two digits for seconds - strm2 << utc_seconds; - line += strm2.str(); - line +=std::string(1,' '); - line +=std::string("UTC"); - line +=std::string(1,' '); return line; } -void rinex_printer::Rinex2NavHeader(std::ofstream& out, gps_navigation_message nav_msg) +void Rinex_Printer::RinexNavHeader(std::ofstream& out, gps_navigation_message nav_msg) { std::string line; // -------- Line 1 - std::string version="3.01"; line = std::string(5,' '); - line += version; + line += stringVersion; line += std::string(11,' '); - line += std::string("N: GNSS NAV DATA"); - line += std::string(4,' '); - //! \todo Add here other systems... - line += std::string("G: GPS"); - line += std::string(14,' '); - // ... - line += std::string("RINEX VERSION / TYPE"); - rinex_printer::lengthCheck(line); + if (version == 2) + { + line += std::string("N: GPS NAV DATA"); + line += std::string(25,' '); + } + if (version == 3 ) + { + line += std::string("N: GNSS NAV DATA"); + line += std::string(4,' '); + //! \todo Add here other systems... + line += std::string("G: GPS"); + line += std::string(14,' '); + // ... + + } + + line += std::string("RINEX VERSION / TYPE"); + Rinex_Printer::lengthCheck(line); out << line << std::endl; + // -------- Line 2 line.clear(); - line += rinex_printer::getLocalTime(); + line += Rinex_Printer::getLocalTime(); line += std::string("PGM / RUN BY / DATE"); line += std::string(1,' '); - rinex_printer::lengthCheck(line); + Rinex_Printer::lengthCheck(line); out << line << std::endl; // -------- Line 3 line.clear(); - line += rinex_printer::leftJustify("GPS NAVIGATION MESSAGE FILE GENERATED BY GNSS-SDR",60); - line += rinex_printer::leftJustify("COMMENT",20); - rinex_printer::lengthCheck(line); - out << line << std::endl; - // -------- Line 4 ionospheric info - line.clear(); - line += std::string("GPSA"); - line += std::string(1,' '); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_alpha0, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_alpha1, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_alpha2, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_alpha3, 12, 2),12); - line += std::string(7,' '); - line += rinex_printer::leftJustify("IONOSPHERIC CORR",20); - rinex_printer::lengthCheck(line); + line += Rinex_Printer::leftJustify("GPS NAVIGATION MESSAGE FILE GENERATED BY GNSS-SDR",60); + line += Rinex_Printer::leftJustify("COMMENT",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; - // -------- Line 5 ionospheric info line.clear(); - line += std::string("GPSB"); - line += std::string(1,' '); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_beta0, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_beta1, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_beta2, 12, 2),12); - line += rinex_printer::rightJustify(rinex_printer::doub2for(nav_msg.d_beta3, 12, 2),12); - line += std::string(7,' '); - line += rinex_printer::leftJustify("IONOSPHERIC CORR",20); - rinex_printer::lengthCheck(line); + 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(); + if (version == 2) + { + line += std::string(2,' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha0, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha1, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha2, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha3, 10, 2),12); + line += std::string(10,' '); + line += Rinex_Printer::leftJustify("ION ALPHA",20); + } + if (version == 3) + { + line += std::string("GPSA"); + line += std::string(1,' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha0, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha1, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_alpha2, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.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 ionospheric info 1 + line.clear(); + if (version == 2) + { + line += std::string(2,' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta0, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta1, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta2, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta3, 10, 2),12); + line += std::string(10,' '); + line += Rinex_Printer::leftJustify("ION BETA",20); + } + + if (version == 3) + { + line += std::string("GPSB"); + line += std::string(1,' '); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta0, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta1, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta2, 10, 2),12); + line += Rinex_Printer::rightJustify(Rinex_Printer::doub2for(nav_msg.d_beta3, 10, 2),12); + line += std::string(7,' '); + line += Rinex_Printer::leftJustify("IONOSPHERIC CORR",20); + } + Rinex_Printer::lengthCheck(line); out << line << std::endl; // -------- Line 5 system time correction line.clear(); - line += std::string("GPUT"); - line += std::string(1,' '); - line += rinex_printer::doub2for(nav_msg.d_A0, 17, 2); - line += rinex_printer::doub2for(nav_msg.d_A1, 16, 2); - line += rinex_printer::rightJustify(boost::lexical_cast(nav_msg.d_t_OT),7); - line += rinex_printer::rightJustify(boost::lexical_cast(nav_msg.i_WN_T),5); - /* if ( SBAS ) + if (version == 2) + { + line += std::string(4,' '); + line += Rinex_Printer::doub2for(nav_msg.d_A0, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_A1, 18, 2); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.d_t_OT),9); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.i_WN_T),9); + line += std::string(1,' '); + line += Rinex_Printer::leftJustify("DELTA-UTC: A0,A1,T,W",20); + + } + if (version == 3) + { + line += std::string("GPUT"); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_A0, 17, 2); + line += Rinex_Printer::doub2for(nav_msg.d_A1, 16, 2); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.d_t_OT),7); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.i_WN_T),5); + /* if ( SBAS ) { line += string(1, ' '); line += leftJustify(asString(d_t_OT_SBAS),5); @@ -341,31 +454,39 @@ void rinex_printer::Rinex2NavHeader(std::ofstream& out, gps_navigation_message n line += string(1, ' '); } else - */ - line += std::string(10, ' '); - line += rinex_printer::leftJustify("TIME SYSTEM CORR",20); - rinex_printer::lengthCheck(line); + */ + 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(nav_msg.d_DeltaT_LS),6); - line += rinex_printer::rightJustify(boost::lexical_cast(nav_msg.d_DeltaT_LSF),6); - line += rinex_printer::rightJustify(boost::lexical_cast(nav_msg.i_WN_LSF),6); - line += rinex_printer::rightJustify(boost::lexical_cast(nav_msg.i_DN),6); - line += std::string(36, ' '); - line += rinex_printer::leftJustify("LEAP SECONDS",20); - rinex_printer::lengthCheck(line); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.d_DeltaT_LS),6); + if (version == 2) + { + line += std::string(54,' '); + } + if (version == 3) + { + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.d_DeltaT_LSF),6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.i_WN_LSF),6); + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.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); + line += Rinex_Printer::leftJustify("END OF HEADER",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; } @@ -378,100 +499,346 @@ void rinex_printer::Rinex2NavHeader(std::ofstream& out, gps_navigation_message n -void rinex_printer::LogRinex2Nav(std::ofstream& out, gps_navigation_message nav_msg){ +void Rinex_Printer::LogRinexNav(std::ofstream& out, gps_navigation_message nav_msg) +{ - /* - if(fp_rin2 != NULL) - { + std::string line; - //preparacio lines de efemerides per imprimir!!! - char linia0[256],linia1[256],linia2[256],linia3[256],linia4[256],linia5[256],linia6[256],linia7[256]; - char idef[256]; - sprintf(idef,"%2.0d",nav_msg.d_satellite_PRN); + boost::posix_time::ptime p_utc_time = Rinex_Printer::computeTime(nav_msg); + 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); + if (version == 2) + { + line += Rinex_Printer::rightJustify(boost::lexical_cast(nav_msg.i_satellite_PRN),2); + line += std::string(1,' '); + std::string year (timestring,2,2); + 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,'.'); + std::string decimal = std::string("0"); + if (timestring.size() > 16) + { + std::string decimal (timestring,16,1); + } + line += decimal; + line += std::string(1,' '); + line += doub2for(nav_msg.d_A_f0, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(nav_msg.d_A_f0, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(nav_msg.d_A_f0, 18, 2); + line += std::string(1, ' '); - sprintf(linia0,"%19.12E%19.12E%19.12E",nav_msg.d_A_f0,nav_msg.d_A_f1,nav_msg.d_A_f2); + } + if (version ==3 ) + { + line += satelliteSystem["GPS"]; + if (nav_msg.i_satellite_PRN < 10) line += std::string("0"); + line += boost::lexical_cast(nav_msg.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 += doub2for(nav_msg.d_A_f0, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(nav_msg.d_A_f0, 18, 2); + line += std::string(1, ' '); + line += Rinex_Printer::doub2for(nav_msg.d_A_f0, 18, 2); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - sprintf(linia1,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_IODE_SF2,nav_msg.d_Crs,nav_msg.d_Delta_n,nav_msg.d_M_0); - sprintf(linia2,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_Cuc,nav_msg.d_e_eccentricity,nav_msg.d_Cus,nav_msg.d_sqrt_A); - sprintf(linia3,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_Toe,nav_msg.d_Cic,nav_msg.d_OMEGA0,nav_msg.d_Cis); - sprintf(linia4,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_i_0,nav_msg.d_Crc,nav_msg.d_OMEGA,nav_msg.d_OMEGA_DOT); - sprintf(linia5,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_IDOT,0.0,nav_msg.d_GPS_week+1024.0,0.0);//CodeL2, L2pData - sprintf(linia6,"%19.12E%19.12E%19.12E%19.12E",nav_msg.d_SV_accuracy,nav_msg.d_SV_health,nav_msg.d_TGD,nav_msg.d_IODC); - sprintf(linia7,"%19.12E%19.12E",nav_msg.d_TOW,0.0); //fit interval is set to 0 + line.clear(); - fseek(fp_rin2, fp_rin_end2, SEEK_SET); + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + if (nav_msg.d_IODE_SF2 == nav_msg.d_IODE_SF3) + { + line += Rinex_Printer::doub2for(nav_msg.d_IODE_SF2, 18, 2); + } + else + { + LOG_AT_LEVEL(ERROR) << "Discontinued reception of Frame 2 and 3 " << std::endl; + } + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Crs, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Delta_n, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_M_0, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - fprintf(fp_rin2,"%s %s %s%s\n",idef,cad1,cad2,linia0); - fprintf(fp_rin2," %s\n",linia1); - fprintf(fp_rin2," %s\n",linia2); + line.clear(); - fprintf(fp_rin2," %s\n",linia3); + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for(nav_msg.d_Cuc, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_e_eccentricity, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Cus, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_sqrt_A, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; - fprintf(fp_rin2," %s\n",linia4); - fprintf(fp_rin2," %s\n",linia5); - fprintf(fp_rin2," %s\n",linia6); + line.clear(); - fprintf(fp_rin2," %s\n",linia7); - fp_rin_end2 = ftell(fp_rin2); - }*/ + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for(nav_msg.d_Toe, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Cic, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_OMEGA0, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Cis, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + + + + line.clear(); + + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for(nav_msg.d_i_0, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_Crc, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_OMEGA, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_OMEGA_DOT, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + + line.clear(); + + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for(nav_msg.d_IDOT, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for((double)(nav_msg.i_code_on_L2), 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for((double)(nav_msg.i_code_on_L2), 18, 2); + line += std::string(1,' '); + double GPS_week_continuous_number = (double)(nav_msg.i_GPS_week+1024); // valid until April 7, 2019 (check http://www.colorado.edu/geography/gcraft/notes/gps/gpseow.htm) + line += Rinex_Printer::doub2for(GPS_week_continuous_number, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + line.clear(); + + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for((double)(nav_msg.i_SV_accuracy), 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for((double)(nav_msg.i_SV_health), 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_TGD, 18, 2); + line += std::string(1,' '); + line += Rinex_Printer::doub2for(nav_msg.d_IODC, 18, 2); + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; + + + line.clear(); + + if (version == 2) + { + line += std::string(4, ' '); + } + if (version == 3) + { + line += std::string(5, ' '); + } + line += Rinex_Printer::doub2for(nav_msg.d_TOW, 18, 2); + line += std::string(1,' '); + double curve_fit_interval = 4; + + if (nav_msg.satelliteBlock[nav_msg.i_satellite_PRN].compare("IIA")) + { + // Block II/IIA (Table 20-XI IS-GPS-200E ) + if ( (nav_msg.d_IODC > 239) && (nav_msg.d_IODC < 248)) curve_fit_interval=8; + if ( ( (nav_msg.d_IODC > 247) && (nav_msg.d_IODC < 256)) || (nav_msg.d_IODC == 496) ) curve_fit_interval=14; + if ( (nav_msg.d_IODC > 496) && (nav_msg.d_IODC < 504)) curve_fit_interval=26; + if ( (nav_msg.d_IODC > 503) && (nav_msg.d_IODC < 511)) curve_fit_interval=50; + if ( ( (nav_msg.d_IODC > 751) && (nav_msg.d_IODC < 757)) || (nav_msg.d_IODC == 511) ) curve_fit_interval=74; + if ( (nav_msg.d_IODC == 757)) curve_fit_interval=98; + } + // Block IIR/IIR-M/IIF/IIIA (Table 20-XII IS-GPS-200E ) + if ((nav_msg.satelliteBlock[nav_msg.i_satellite_PRN].compare("IIR") == 0) || + (nav_msg.satelliteBlock[nav_msg.i_satellite_PRN].compare("IIR-M") == 0) || + (nav_msg.satelliteBlock[nav_msg.i_satellite_PRN].compare("IIF") == 0) || + (nav_msg.satelliteBlock[nav_msg.i_satellite_PRN].compare("IIIA") == 0) ) + { + if ( (nav_msg.d_IODC > 239) && (nav_msg.d_IODC < 248)) curve_fit_interval=8; + if ( ( (nav_msg.d_IODC > 247) && (nav_msg.d_IODC < 256)) || (nav_msg.d_IODC == 496) ) curve_fit_interval=14; + if ( ( (nav_msg.d_IODC > 496) && (nav_msg.d_IODC < 504)) ||( (nav_msg.d_IODC > 1020) && (nav_msg.d_IODC < 1024)) ) curve_fit_interval=26; + } + line += Rinex_Printer::doub2for(curve_fit_interval, 18, 2); + line += std::string(1,' '); + line += std::string(18,' '); // spare + line += std::string(1,' '); + line += std::string(18,' '); // spare + if (version == 2) + { + line += std::string(1, ' '); + } + Rinex_Printer::lengthCheck(line); + out << line << std::endl; } -void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message nav_msg) +void Rinex_Printer::RinexObsHeader(std::ofstream& out, gps_navigation_message nav_msg) { std::string line; // -------- Line 1 - std::string version="3.01"; line = std::string(5,' '); - line += version; + line += stringVersion; line +=std::string(11,' '); - line += rinex_printer::leftJustify("OBSERVATION DATA",20); + line += Rinex_Printer::leftJustify("OBSERVATION DATA",20); line +=satelliteSystem["GPS"]; line +=std::string(19,' '); line +=std::string("RINEX VERSION / TYPE"); - rinex_printer::lengthCheck(line); + 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); + 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 += Rinex_Printer::getLocalTime(); line +=std::string("PGM / RUN BY / DATE"); line +=std::string(1,' '); - rinex_printer::lengthCheck(line); + Rinex_Printer::lengthCheck(line); out << line << std::endl; // -------- Line 4 line.clear(); - line += rinex_printer::leftJustify("GPS OBSERVATION DATA FILE GENERATED BY GNSS-SDR",60); - line += rinex_printer::leftJustify("COMMENT",20); - rinex_printer::lengthCheck(line); - out << line << std::endl; - // -------- Line 5 - 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); + line += Rinex_Printer::leftJustify("GPS OBSERVATION DATA FILE GENERATED BY GNSS-SDR",60); + line += Rinex_Printer::leftJustify("COMMENT",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; line.clear(); - line += rinex_printer::leftJustify("GROUND_CRAFT",20); // put a flag or a property + 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.clear(); + line += Rinex_Printer::leftJustify("GROUND_CRAFT",20); // put a flag or a property line +=std::string(40,' '); - line += rinex_printer::leftJustify("MARKER TYPE",20); - rinex_printer::lengthCheck(line); + line += Rinex_Printer::leftJustify("MARKER TYPE",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; @@ -479,30 +846,30 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n line.clear(); std::string username=getenv("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); + 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 - line += rinex_printer::leftJustify("0.1",20); - line += rinex_printer::leftJustify("REC # / TYPE / VERS",20); + 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 + line += Rinex_Printer::leftJustify("0.1",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 += 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); + line += Rinex_Printer::leftJustify("ANT # / TYPE",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; // -------- APPROX POSITION (optional for moving platforms) @@ -514,12 +881,12 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n 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 = 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); + line += Rinex_Printer::leftJustify("ANTENNA: DELTA H/E/N",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; @@ -532,7 +899,7 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n int numberObservations=2; // Count the number of available types of observable in the system std::stringstream strm; strm << numberObservations; - line += rinex_printer::rightJustify(strm.str(),3); + line += Rinex_Printer::rightJustify(strm.str(),3); // per type of observation line += std::string(1,' '); line += observationType["PSEUDORANGE"]; @@ -542,21 +909,21 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n line += observationCode["GPS_L1_CA"]; line +=std::string(60-line.size(),' '); - line += rinex_printer::leftJustify("SYS / # / OBS TYPES",20); - rinex_printer::lengthCheck(line); + 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 += Rinex_Printer::leftJustify("DBHZ",20); line +=std::string(40,' '); - line += rinex_printer::leftJustify("SIGNAL STRENGTH UNIT",20); - rinex_printer::lengthCheck(line); + 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_utc_time = rinex_printer::computeTime(nav_msg); + boost::posix_time::ptime p_utc_time = Rinex_Printer::computeTime(nav_msg); std::string timestring=boost::posix_time::to_iso_string(p_utc_time); std::string year (timestring,0,4); std::string month (timestring,4,2); @@ -573,8 +940,8 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n line += rightJustify(asString(seconds,7), 13); line += rightJustify(std::string("GPS"), 8); line +=std::string(9,' '); - line += rinex_printer::leftJustify("TIME OF FIRST OBS",20); - rinex_printer::lengthCheck(line); + line += Rinex_Printer::leftJustify("TIME OF FIRST OBS",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; // -------- SYS /PHASE SHIFTS @@ -582,15 +949,15 @@ void rinex_printer::Rinex2ObsHeader(std::ofstream& out, gps_navigation_message n // -------- end of header line.clear(); line +=std::string(60,' '); - line += rinex_printer::leftJustify("END OF HEADER",20); - rinex_printer::lengthCheck(line); + line += Rinex_Printer::leftJustify("END OF HEADER",20); + Rinex_Printer::lengthCheck(line); out << line << std::endl; } -void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double pseudoranges_clock, std::map pseudoranges) +void Rinex_Printer::LogRinexObs(gps_navigation_message nav_msg,double pseudoranges_clock, std::map pseudoranges) { /* int ss; char sat_vis[36]; @@ -700,7 +1067,7 @@ void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double pseudoran -int rinex_printer::signalStrength(double snr) +int Rinex_Printer::signalStrength(double snr) { int ss; @@ -709,7 +1076,7 @@ int rinex_printer::signalStrength(double snr) } -boost::posix_time::ptime rinex_printer::computeTime(gps_navigation_message nav_msg) +boost::posix_time::ptime Rinex_Printer::computeTime(gps_navigation_message nav_msg) { // if we are processing a file -> wait to leap second to resolve the ambiguity else take the week from the local system time //: idea resolve the ambiguity with the leap second http://www.colorado.edu/geography/gcraft/notes/gps/gpseow.htm diff --git a/src/algorithms/PVT/libs/rinex_2_1_printer.h b/src/algorithms/PVT/libs/rinex_printer.h similarity index 84% rename from src/algorithms/PVT/libs/rinex_2_1_printer.h rename to src/algorithms/PVT/libs/rinex_printer.h index 31b1e9349..f647008b7 100644 --- a/src/algorithms/PVT/libs/rinex_2_1_printer.h +++ b/src/algorithms/PVT/libs/rinex_printer.h @@ -1,7 +1,27 @@ /*! - * \file rinex_2_1_printer.h (temporal name) - * \brief Interface of a RINEX 3.01 printer + * \file rinex_printer.h + * \brief Interface of a RINEX 2.11 / 3.01 printer * See http://igscb.jpl.nasa.gov/igscb/data/format/rinex301.pdf + * + * Receiver Independent EXchange Format (RINEX): + * The first proposal for the Receiver Independent Exchange Format RINEX + * was developed by the Astronomical Institute of the University of Berne + * for the easy exchange of the GPS data to be collected during the large + * European GPS campaign EUREF 89, which involved more than 60 GPS receivers + * of 4 different manufacturers. + * The governing aspect during the development was the fact that most geodetic + * processing software for GPS data use a well-defined set of observables: + * 1) The carrier-phase measurement at one or both carriers (actually being a + * measurement on the beat frequency between the received carrier of the + * satellite signal and a receiver-generated reference frequency). + * 2) The pseudorange (code) measuremen , equivalent to the difference + * of the time of reception (expressed in the time frame of the receiver) + * and the time of transmission (expressed in the time frame of the satellite) + * of a distinct satellite signal. + * 3) The observation time being the reading of the receiver clock at the + * instant of validity of the carrier-phase and/or the code measurements. + * Note: A collection of the formats currently used by the IGS can be found + * here: http://igscb.jpl.nasa.gov/components/formats.html * \author Carles Fernandez Prades, 2011. cfernandez(at)cttc.es * ------------------------------------------------------------------------- * @@ -43,11 +63,52 @@ * \brief Class that handles the generation of Receiver * INdependent EXchange format (RINEX) files */ -class rinex_printer +class Rinex_Printer { + + +public: + /*! + * \brief Default constructor. Creates GPS Navigation and Observables RINEX files and their headers + */ + Rinex_Printer(); + + /*! + * \brief Default destructor. Closes GPS Navigation and Observables RINEX files + */ + ~Rinex_Printer(); + + std::ofstream obsFile ; + std::ofstream navFile ; + + /*! + * \brief Generates the Navigation Data header + */ + void RinexNavHeader(std::ofstream& out, gps_navigation_message nav); + + /*! + * \brief Generates the Observation data header + */ + void RinexObsHeader(std::ofstream& out, gps_navigation_message nav); + + boost::posix_time::ptime computeTime(gps_navigation_message nav_msg); + + void LogRinexNav(std::ofstream& out, gps_navigation_message nav_msg); + void LogRinexObs(gps_navigation_message nav_msg, double interframe_seconds, std::map pseudoranges); + + std::map satelliteSystem; + std::map observationType; + std::map observationCode; + + + std::string stringVersion; // 0.87654E-0004 or -0.1234E00005. */ - inline std::string& sci2for(std::string& aStr, - const std::string::size_type startPos = 0, - const std::string::size_type length = std::string::npos, - const std::string::size_type expLen = 3, - const bool checkSwitch = true); + inline std::string& sci2for(std::string& aStr, + const std::string::size_type startPos = 0, + const std::string::size_type length = std::string::npos, + const std::string::size_type expLen = 3, + const bool checkSwitch = true); @@ -250,50 +311,13 @@ private: template inline std::string asString(const X x); - - - - -public: - /*! - * \brief Default constructor. Creates GPS Navigation and Observables RINEX files and their headers - */ - rinex_printer(); - - std::ofstream obsFile ; - std::ofstream navFile ; - - - /*! - * \brief Generates the Navigation Data header - */ - void Rinex2NavHeader(std::ofstream& out, gps_navigation_message nav); - - /*! - * \brief Generates the Observation data header - */ - void Rinex2ObsHeader(std::ofstream& out, gps_navigation_message nav); - - boost::posix_time::ptime computeTime(gps_navigation_message nav_msg); - - /*! - * \brief Default destructor. Closes GPS Navigation and Observables RINEX files - */ - ~rinex_printer(); - void LogRinex2Nav(std::ofstream& out, gps_navigation_message nav_msg); - void LogRinex2Obs(gps_navigation_message nav_msg, double interframe_seconds, std::map pseudoranges); - - std::map satelliteSystem; - std::map observationType; - std::map observationCode; - }; -// Implementation of inline functions +// Implementation of inline functions (modified versions from GPSTk http://www.gpstk.org) -inline std::string& rinex_printer::leftJustify(std::string& s, +inline std::string& Rinex_Printer::leftJustify(std::string& s, const std::string::size_type length, const char pad) { @@ -312,7 +336,7 @@ inline std::string& rinex_printer::leftJustify(std::string& s, // if the string is bigger than length, truncate it from the left. // otherwise, add pad characters to its left. -inline std::string& rinex_printer::rightJustify(std::string& s, +inline std::string& Rinex_Printer::rightJustify(std::string& s, const std::string::size_type length, const char pad) { @@ -331,7 +355,7 @@ inline std::string& rinex_printer::rightJustify(std::string& s, -inline std::string rinex_printer::doub2for(const double& d, +inline std::string Rinex_Printer::doub2for(const double& d, const std::string::size_type length, const std::string::size_type expLen, const bool checkSwitch) @@ -351,7 +375,7 @@ inline std::string rinex_printer::doub2for(const double& d, } -inline std::string rinex_printer::doub2sci(const double& d, +inline std::string Rinex_Printer::doub2sci(const double& d, const std::string::size_type length, const std::string::size_type expLen, const bool showSign, @@ -381,7 +405,7 @@ inline std::string rinex_printer::doub2sci(const double& d, return toReturn; } -inline std::string& rinex_printer::sci2for(std::string& aStr, +inline std::string& Rinex_Printer::sci2for(std::string& aStr, const std::string::size_type startPos, const std::string::size_type length, const std::string::size_type expLen, @@ -450,7 +474,7 @@ inline std::string& rinex_printer::sci2for(std::string& aStr, } else aStr += "+"; - aStr += rinex_printer::rightJustify(asString(iexp),expLen,'0'); + aStr += Rinex_Printer::rightJustify(asString(iexp),expLen,'0'); } @@ -484,7 +508,7 @@ inline std::string asString(const long double x, const std::string::size_type pr -inline std::string rinex_printer::asString(const double x, const std::string::size_type precision) +inline std::string Rinex_Printer::asString(const double x, const std::string::size_type precision) { std::ostringstream ss; ss << std::fixed << std::setprecision(precision) << x; @@ -492,7 +516,7 @@ inline std::string rinex_printer::asString(const double x, const std::string::si } template -inline std::string rinex_printer::asString(const X x) +inline std::string Rinex_Printer::asString(const X x) { std::ostringstream ss; ss << x; diff --git a/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.cc b/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.cc index f8b86798a..00c976e6a 100644 --- a/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.cc +++ b/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.cc @@ -5,7 +5,7 @@ * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver diff --git a/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.h b/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.h index a120974a8..26fe70e6d 100644 --- a/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.h +++ b/src/algorithms/channel/libs/gps_l1_ca_channel_fsm.h @@ -6,7 +6,7 @@ * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver diff --git a/src/algorithms/observables/gnuradio_blocks/gps_l1_ca_observables_cc.h b/src/algorithms/observables/gnuradio_blocks/gps_l1_ca_observables_cc.h index b776a8417..e2b162aa0 100644 --- a/src/algorithms/observables/gnuradio_blocks/gps_l1_ca_observables_cc.h +++ b/src/algorithms/observables/gnuradio_blocks/gps_l1_ca_observables_cc.h @@ -39,7 +39,7 @@ #include #include "concurrent_queue.h" #include "gps_navigation_message.h" -#include "rinex_2_1_printer.h" +#include "rinex_printer.h" #include "GPS_L1_CA.h" class gps_l1_ca_observables_cc; diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc index a62300117..21a4691f4 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc @@ -6,7 +6,7 @@ * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -51,73 +51,80 @@ using google::LogMessage; */ gps_l1_ca_telemetry_decoder_cc_sptr gps_l1_ca_make_telemetry_decoder_cc(unsigned int satellite, long if_freq, long fs_in, unsigned - int vector_length, gr_msg_queue_sptr queue, bool dump) { + int vector_length, gr_msg_queue_sptr queue, bool dump) +{ - return gps_l1_ca_telemetry_decoder_cc_sptr(new gps_l1_ca_telemetry_decoder_cc(satellite, if_freq, - fs_in, vector_length, queue, dump)); + return gps_l1_ca_telemetry_decoder_cc_sptr(new gps_l1_ca_telemetry_decoder_cc(satellite, if_freq, + fs_in, vector_length, queue, dump)); } void gps_l1_ca_telemetry_decoder_cc::forecast (int noutput_items, - gr_vector_int &ninput_items_required){ - for (unsigned i = 0; i < 3; i++) { - ninput_items_required[i] =d_samples_per_bit*8; //set the required sample history - } + gr_vector_int &ninput_items_required) +{ + for (unsigned i = 0; i < 3; i++) + { + ninput_items_required[i] =d_samples_per_bit*8; //set the required sample history + } } gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(unsigned int satellite, long if_freq, long fs_in, unsigned - int vector_length, gr_msg_queue_sptr queue, bool dump) : - gr_block ("gps_navigation_cc", gr_make_io_signature (5, 5, sizeof(double)), - gr_make_io_signature(1, 1, sizeof(gnss_synchro))) { - // initialize internal vars - d_queue = queue; - d_dump = dump; - d_satellite = satellite; - d_vector_length = vector_length; - d_samples_per_bit=20; // it is exactly 1000*(1/50)=20 - d_fs_in=fs_in; - d_preamble_duration_seconds=(1.0/(float)GPS_CA_TELEMETRY_RATE_BITS_SECOND)*(float)GPS_CA_PREAMBLE_LENGTH_BITS; - //std::cout<<"d_preamble_duration_seconds="<d_preambles_bits, (unsigned short int*)preambles_bits, 8* sizeof(unsigned short int)); + memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, 8* sizeof(unsigned short int)); - // preamble bits to sampled symbols - d_preambles_symbols=(signed int*)malloc(sizeof(signed int)*8*d_samples_per_bit); - int n=0; - for (int i=0;i<8;i++) - { - for (unsigned int j=0;j=160){ - //TODO: Rewrite with state machine - if (d_stat==0) - { - d_GPS_FSM.Event_gps_word_preamble(); - d_preamble_index=d_sample_counter;//record the preamble sample stamp - std::cout<<"Preamble detection for SAT "<6001){ - std::cout<<"Lost of frame sync SAT "<d_satellite<<" preamble_diff= "<0){ //symbol to bit - d_GPS_frame_4bytes+=1; //insert the telemetry bit in LSB - } - d_symbol_accumulator=0; - d_symbol_accumulator_counter=0; - - //******* bits to words ****** - d_frame_bit_index++; - if (d_frame_bit_index==30) - { - d_frame_bit_index=0; - //parity check - //Each word in wordbuff is composed of: - // Bits 0 to 29 = the GPS data word - // Bits 30 to 31 = 2 LSBs of the GPS word ahead. - // prepare the extended frame [-2 -1 0 ... 30] - if (d_prev_GPS_frame_4bytes & 0x00000001) + /*! + * \todo Check the HOW GPS time computation, taking into account that the preamble correlation last 160 symbols, which is 160 ms in GPS CA L1 + */ + // FIFO history to get the exact timestamp of the first symbol of the preamble + // if (d_prn_start_sample_history.size()<160) + // { + // // fill the queue + // d_prn_start_sample_history.push_front(in[2][0]); + // consume_each(1); //one by one + // return 1; + // }else{ + // d_prn_start_sample_history.pop_back(); + // d_prn_start_sample_history.push_front(in[2][0]); + // } + // TODO Optimize me! + //******* preamble correlation ******** + for (unsigned int i=0;i=160) { - d_GPS_frame_4bytes=d_GPS_frame_4bytes|0x80000000; + //TODO: Rewrite with state machine + if (d_stat==0) + { + d_GPS_FSM.Event_gps_word_preamble(); + d_preamble_index=d_sample_counter;//record the preamble sample stamp + std::cout<<"Preamble detection for SAT "<6001) + { + std::cout<<"Lost of frame sync SAT "<d_satellite<<" preamble_diff= "<0) + { //symbol to bit + d_GPS_frame_4bytes+=1; //insert the telemetry bit in LSB + } + d_symbol_accumulator=0; + d_symbol_accumulator_counter=0; + + //******* bits to words ****** + d_frame_bit_index++; + if (d_frame_bit_index==30) + { + d_frame_bit_index=0; + //parity check + //Each word in wordbuff is composed of: + // Bits 0 to 29 = the GPS data word + // Bits 30 to 31 = 2 LSBs of the GPS word ahead. + // prepare the extended frame [-2 -1 0 ... 30] + if (d_prev_GPS_frame_4bytes & 0x00000001) + { + d_GPS_frame_4bytes=d_GPS_frame_4bytes|0x40000000; + } + if (d_prev_GPS_frame_4bytes & 0x00000002) + { + d_GPS_frame_4bytes=d_GPS_frame_4bytes|0x80000000; + } + /* Check that the 2 most recently logged words pass parity. Have to first + invert the data bits according to bit 30 of the previous word. */ + if(d_GPS_frame_4bytes & 0x40000000) + { + d_GPS_frame_4bytes ^= 0x3FFFFFC0; // invert the data bits (using XOR) + } + if (gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(d_GPS_frame_4bytes)) + { + memcpy(&d_GPS_FSM.d_GPS_frame_4bytes,&d_GPS_frame_4bytes,sizeof(char)*4); + d_GPS_FSM.d_preamble_time_ms=d_preamble_time_seconds*1000.0; + d_GPS_FSM.Event_gps_word_valid(); + d_flag_parity=true; + } + else + { + d_GPS_FSM.Event_gps_word_invalid(); + d_flag_parity=false; + } + d_prev_GPS_frame_4bytes=d_GPS_frame_4bytes; // save the actual frame + d_GPS_frame_4bytes=d_GPS_frame_4bytes & 0; + } + else + { + d_GPS_frame_4bytes<<=1; //shift 1 bit left the telemetry word + } + } + + // output the frame + consume_each(1); //one by one + + gps_synchro.valid_word=(d_flag_frame_sync==true and d_flag_parity==true); + gps_synchro.flag_preamble=d_flag_preamble; + gps_synchro.preamble_delay_ms=d_preamble_time_seconds*1000.0; + gps_synchro.prn_delay_ms=(in[2][0]-d_preamble_duration_seconds)*1000.0; + gps_synchro.preamble_code_phase_ms=d_preamble_code_phase_seconds*1000.0; + gps_synchro.preamble_code_phase_correction_ms=(in[4][0]-d_preamble_code_phase_seconds)*1000.0; + gps_synchro.satellite_PRN=d_satellite; + gps_synchro.channel_ID=d_channel; + *out[0]=gps_synchro; + return 1; } -void gps_l1_ca_telemetry_decoder_cc::set_satellite(int satellite) { - d_satellite = satellite; - d_GPS_FSM.d_satellite_PRN=satellite; - LOG_AT_LEVEL(INFO) << "Navigation Satellite set to " << d_satellite; +void gps_l1_ca_telemetry_decoder_cc::set_satellite(int satellite) +{ + d_satellite = satellite; + d_GPS_FSM.i_satellite_PRN=satellite; + LOG_AT_LEVEL(INFO) << "Navigation Satellite set to " << d_satellite; } -void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel) { - d_channel = channel; - d_GPS_FSM.d_channel_ID=channel; - LOG_AT_LEVEL(INFO) << "Navigation channel set to " << channel; +void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel) +{ + d_channel = channel; + d_GPS_FSM.i_channel_ID=channel; + LOG_AT_LEVEL(INFO) << "Navigation channel set to " << channel; } diff --git a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc index 99af3c665..2d728aa95 100644 --- a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc +++ b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc @@ -225,12 +225,12 @@ void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg() int subframe_ID; // NEW GPS SUBFRAME HAS ARRIVED! subframe_ID=d_nav.subframe_decoder(this->d_subframe); //decode the subframe - std::cout<<"NAVIGATION FSM: received subframe "<d_preamble_time_ms; - //std::cout<<"NAVIGATION FSM: set subframe 1 preamble timestamp for satellite "< *d_nav_queue; diff --git a/src/core/system_parameters/gps_navigation_message.cc b/src/core/system_parameters/gps_navigation_message.cc index 901d5bb56..dfa4e2010 100644 --- a/src/core/system_parameters/gps_navigation_message.cc +++ b/src/core/system_parameters/gps_navigation_message.cc @@ -87,8 +87,8 @@ void gps_navigation_message::reset() d_satpos_Z=0; // info - d_channel_ID=0; - d_satellite_PRN=0; + i_channel_ID=0; + i_satellite_PRN=0; // time synchro d_subframe1_timestamp_ms=0; @@ -129,6 +129,45 @@ void gps_navigation_message::reset() d_satvel_X=0; d_satvel_Y=0; d_satvel_Z=0; + + //Plane A (info from http://www.navcen.uscg.gov/?Do=constellationStatus) + satelliteBlock[9] = "IIA"; + satelliteBlock[31] = "IIR-M"; + satelliteBlock[8] = "IIA"; + satelliteBlock[7] = "IIR-M"; + satelliteBlock[27] = "IIA"; + //Plane B + satelliteBlock[16] = "IIR"; + satelliteBlock[25] = "IIF"; + satelliteBlock[28] = "IIR"; + satelliteBlock[12] = "IIR-M"; + satelliteBlock[30] = "IIA"; + //Plane C + satelliteBlock[29] = "IIR-M"; + satelliteBlock[3] = "IIA"; + satelliteBlock[19] = "IIR"; + satelliteBlock[17] = "IIR-M"; + satelliteBlock[6] = "IIA"; + //Plane D + satelliteBlock[2] = "IIR"; + satelliteBlock[1] = "IIF"; + satelliteBlock[21] = "IIR"; + satelliteBlock[4] = "IIA"; + satelliteBlock[11] = "IIR"; + satelliteBlock[24] = "IIA"; // Decommissioned from active service on 04 Nov 2011 + //Plane E + satelliteBlock[20] = "IIR"; + satelliteBlock[22] = "IIR"; + satelliteBlock[5] = "IIR-M"; + satelliteBlock[18] = "IIR"; + satelliteBlock[32] = "IIA"; + satelliteBlock[10] = "IIA"; + //Plane F + satelliteBlock[14] = "IIR"; + satelliteBlock[15] = "IIR-M"; + satelliteBlock[13] = "IIR"; + satelliteBlock[23] = "IIR"; + satelliteBlock[26] = "IIA"; } @@ -340,7 +379,7 @@ void gps_navigation_message::satellitePosition(double transmitTime) // debug /* - if (this->d_channel_ID==0){ + if (this->i_channel_ID==0){ std::cout<<"tk"<