From ca5463e2d8bdf7d1f0fef86a55abf31b538b7faf Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 3 Jan 2012 05:38:45 +0000 Subject: [PATCH] Improvements in the decodification of NAV message; Some advances in the implementation of a RINEX printer (remains deactivated) git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@105 64b25241-fba3-4117-9849-534c7e92360d --- jamroot.jam | 2 +- src/algorithms/PVT/libs/rinex_2_1_printer.cc | 664 ++++++++++++-- src/algorithms/PVT/libs/rinex_2_1_printer.h | 186 +++- src/core/system_parameters/GPS_L1_CA.h | 179 ++-- .../gps_navigation_message.cc | 843 ++++++++++-------- .../gps_navigation_message.h | 148 ++- 6 files changed, 1407 insertions(+), 615 deletions(-) diff --git a/jamroot.jam b/jamroot.jam index 3cd3b91e7..e7c97f2bd 100644 --- a/jamroot.jam +++ b/jamroot.jam @@ -7,7 +7,7 @@ lib gnuradio-core ; project : requirements OMNITHREAD_POSIX "-std=c++0x -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free" -"-larmadillo -lboost_system -lboost_filesystem -lboost_thread -llapack -lblas -lprofiler -ltcmalloc" +"-larmadillo -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -llapack -lblas -lprofiler -ltcmalloc" src/algorithms/acquisition/adapters src/algorithms/acquisition/gnuradio_blocks src/algorithms/channel/adapters diff --git a/src/algorithms/PVT/libs/rinex_2_1_printer.cc b/src/algorithms/PVT/libs/rinex_2_1_printer.cc index 5f46a9843..8fd8b7cb8 100644 --- a/src/algorithms/PVT/libs/rinex_2_1_printer.cc +++ b/src/algorithms/PVT/libs/rinex_2_1_printer.cc @@ -1,60 +1,269 @@ +/*! + * \file rinex_2_1_printer.cc (temporal name) + * \brief Implementation of a RINEX 3.01 printer + * See http://igscb.jpl.nasa.gov/igscb/data/format/rinex301.pdf + * \author Carles Fernandez Prades, 2011. cfernandez(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + #include "rinex_2_1_printer.h" +#include +#include +#include +#include // for getenv() +#include "boost/date_time/time_zone_base.hpp" +#include "boost/date_time/gregorian/gregorian.hpp" +#include "boost/date_time/local_time/local_time.hpp" +#include "boost/date_time/posix_time/posix_time.hpp" +#include +#include +#include -void rinex_printer::set_headers(std::string file_name) + +using google::LogMessage; + + +rinex_printer::rinex_printer() { - correccio_primera_obs=1; - - fp_rin = fopen((file_name+".09o").c_str(),"wt"); - fp_rin_end = ftell(fp_rin); - - fp_rin2 = fopen((file_name+".09n").c_str(),"wt"); - fp_rin_end2 = ftell(fp_rin2); - - // write RINEX headers - Rinex2ObsHeader(); - Rinex2NavHeader(); + rinex_printer::navFile.open(rinex_printer::createFilename("RINEX_FILE_TYPE_GPS_NAV")); + rinex_printer::obsFile.open(rinex_printer::createFilename("RINEX_FILE_TYPE_OBS")); + rinex_printer::Rinex2NavHeader(rinex_printer::navFile); } -rinex_printer::rinex_printer () +rinex_printer::~rinex_printer() { + // close RINEX files + rinex_printer::navFile.close(); + rinex_printer::obsFile.close(); } -rinex_printer::~rinex_printer () + + + +void rinex_printer::lengthCheck(std::string line) { - fclose(fp_rin); - fclose(fp_rin2); + if (line.length() != 80) + { + LOG_AT_LEVEL(ERROR) << "Bad defined RINEX line: " + << line.length() << " characters (must be 80)"<< std::endl + << line << std::endl + << "----|---1|0---|---2|0---|---3|0---|---4|0---|---5|0---|---6|0---|---7|0---|---8|"<< std::endl; + } } -void rinex_printer::Rinex2NavHeader() + +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(); + std::stringstream strm0; + if (dayOfTheYear<100) strm0 << "0"; // three digits for day of the year + if (dayOfTheYear<10) strm0 << "0"; // three digits for day of the year + 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. + fileType.insert(std::pair("RINEX_FILE_TYPE_MET","M")); // M - Meteorological data file. + fileType.insert(std::pair("RINEX_FILE_TYPE_GLO_NAV","G")); // G - GLONASS navigation file. + fileType.insert(std::pair("RINEX_FILE_TYPE_GAL_NAV","L")); // L - Galileo navigation message file. + fileType.insert(std::pair("RINEX_FILE_TYPE_MIXED_NAV","P")); // P - Mixed GNSS navigation message file. + fileType.insert(std::pair("RINEX_FILE_TYPE_GEO_NAV","H")); // H - SBAS Payload navigation message file. + fileType.insert(std::pair("RINEX_FILE_TYPE_SBAS","B")); // B - SBAS broadcast data file. + fileType.insert(std::pair("RINEX_FILE_TYPE_CLK","C")); // C - Clock file. + fileType.insert(std::pair("RINEX_FILE_TYPE_SUMMARY","S")); // S - Summary file (used e.g., by IGS, not a standard!). + + boost::posix_time::ptime pt=boost::posix_time::second_clock::local_time(); + tm pt_tm=boost::posix_time::to_tm(pt); + int local_hour=pt_tm.tm_hour; + std::stringstream strm; + strm << local_hour; + + std::map Hmap; + + Hmap.insert(std::pair("0","a")); + Hmap.insert(std::pair("1","b")); + Hmap.insert(std::pair("2","c")); + Hmap.insert(std::pair("3","d")); + Hmap.insert(std::pair("4","e")); + Hmap.insert(std::pair("5","f")); + Hmap.insert(std::pair("6","g")); + Hmap.insert(std::pair("7","h")); + Hmap.insert(std::pair("8","i")); + Hmap.insert(std::pair("9","j")); + Hmap.insert(std::pair("10","k")); + Hmap.insert(std::pair("11","l")); + Hmap.insert(std::pair("12","m")); + Hmap.insert(std::pair("13","n")); + Hmap.insert(std::pair("14","o")); + Hmap.insert(std::pair("15","p")); + Hmap.insert(std::pair("16","q")); + Hmap.insert(std::pair("17","r")); + Hmap.insert(std::pair("8","s")); + Hmap.insert(std::pair("19","t")); + Hmap.insert(std::pair("20","u")); + Hmap.insert(std::pair("21","v")); + Hmap.insert(std::pair("22","w")); + Hmap.insert(std::pair("23","x")); + + std::string hourTag = Hmap[strm.str()]; + + int local_minute=pt_tm.tm_min; + std::stringstream strm2; + if (local_minute<10) strm2 << "0"; // at least two digits for minutes + strm2 << local_minute; + + std::string minTag = strm2.str(); + + int local_year=pt_tm.tm_year-100; // 2012 is 112 + std::stringstream strm3; + strm3 << local_year; + std::string yearTag = strm3.str(); + + std::string typeOfFile=fileType[type]; + + std::string filename(stationName +dayOfTheYearTag+ hourTag + minTag + "." + yearTag + typeOfFile); + return filename; +} + + +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 + 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; + int utc_hour=pt_tm.tm_hour; + if (utc_hour<10) strm0 << "0"; // two digits for hours + strm0 << utc_hour; + line += strm0.str(); + + std::stringstream strm1; + int utc_minute=pt_tm.tm_min; + if (utc_minute<10) strm1 << "0"; // two digits for minutes + strm1 << utc_minute; + line += strm1.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,' '); + return line; +} + + +void rinex_printer::Rinex2NavHeader(std::ofstream& out) { - if(fp_rin2 != NULL) - { - //calculate UTC_TIME - time_t tiempo; - char cad[80]; - struct tm *tmPtr; - tiempo = time(NULL); - tmPtr = gmtime(&tiempo); - strftime( cad, 20, "%d-%b-%y %H:%M", tmPtr ); + std::string line; - fseek(fp_rin2, fp_rin_end2, SEEK_SET); - //fprintf(fp_rin2,"----|---1|0---|---2|0---|---3|0---|---4|0---|---5|0---|---6|0---|---7|0---|---8|\n\n"); - fprintf(fp_rin2," 2.10 NAVIGATION DATA RINEX VERSION / TYPE\n"); - fprintf(fp_rin2,"GNSS-SDR-mercurio CTTC %s PGM / RUN BY / DATE\n",cad); - //fprintf(fp_rin2,"CTTC MARKER NAME\n"); - //fprintf(fp_rin2,"0000 MARKERNUMBER\n"); - fp_rin_end2 = ftell(fp_rin2); - correccio_primera_obs=1; - } + // -------- Line 1 + std::string version="3.01"; + line = std::string(5,' '); + line += version; + 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); + + 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 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(4,' '); + + // IONOSPHERIC INFORMATION + + // For leap second information, see See http://www.endruntechnologies.com/leap.htm + line.clear(); + line +=std::string(4,' '); + line +=std::string("15"); // Page 18 of subframe 4 Delta_T_LSF + line +=std::string(54,' '); + line +=std::string("LEAP SECONDS"); + line +=std::string(8,' '); + 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::LogRinex2Nav(gps_navigation_message nav_msg){ - +/* if(fp_rin2 != NULL) { //double decimalday,daydecimalhour,decimalhour,decimalmin,decimalsec; @@ -85,9 +294,9 @@ void rinex_printer::LogRinex2Nav(gps_navigation_message nav_msg){ fseek(fp_rin2, fp_rin_end2, SEEK_SET); char correction[256],correction2[256]; double A0,A1; - /* 8.3819D-09 -7.4506D-09 -5.9605D-08 5.9605D-08 ION ALPHA - 8.8 064D+04 -3.2768D+04 -1.9661D+05 1.9661D+05 ION BETA - 5. 587935447693D-09 8.881784197001D-15 233472 1518 DELTA-UTC: A0,A1,T,W*/ + // 8.3819D-09 -7.4506D-09 -5.9605D-08 5.9605D-08 ION ALPHA + //8.8 064D+04 -3.2768D+04 -1.9661D+05 1.9661D+05 ION BETA + // 5. 587935447693D-09 8.881784197001D-15 233472 1518 DELTA-UTC: A0,A1,T,W A0=587.935447693E-09; A1=8.881784197001E-15; sprintf(correction,"%19.12E",A0); @@ -149,52 +358,135 @@ void rinex_printer::LogRinex2Nav(gps_navigation_message nav_msg){ fprintf(fp_rin2," %s\n",linia7); fp_rin_end2 = ftell(fp_rin2); - } + }*/ } -void rinex_printer::Rinex2ObsHeader() +void rinex_printer::Rinex2ObsHeader(std::ofstream& out) { - //Clock_S *pClock = &tNav.master_clock; /* Clock solution */ - if(fp_rin != NULL) - { - //calculate UTC_TIME - time_t tiempo; - char cad[80]; - struct tm *tmPtr; - tiempo = time(NULL); - tmPtr = gmtime(&tiempo); - strftime( cad, 24, "%d/%m/%Y %H:%M:%S", tmPtr ); + std::map satelliteSystem; + satelliteSystem.insert(std::pair("GPS","G")); + satelliteSystem.insert(std::pair("GLONASS","R")); + satelliteSystem.insert(std::pair("Galileo","E")); + satelliteSystem.insert(std::pair("SBAS payload","S")); + satelliteSystem.insert(std::pair("Mixed","M")); + satelliteSystem.insert(std::pair("Compass","C")); - fseek(fp_rin, fp_rin_end, SEEK_SET); - //fprintf(fp_rin,"----|---1|0---|---2|0---|---3|0---|---4|0---|---5|0---|---6|0---|---7|0---|---8|\n\n"); - fprintf(fp_rin," 2.10 Observation G (GPS) RINEX VERSION / TYPE\n"); - fprintf(fp_rin,"GNSS-SDR-mercurio CTTC %s PGM / RUN BY / DATE\n",cad); - fprintf(fp_rin,"CTTC MARKER NAME\n"); - //fprintf(fp_rin,"0000 MARKERNUMBER\n"); + std::string line; - fprintf(fp_rin,"JAVIER ARRIBAS CTTC OBSERVER / AGENCY\n"); - fprintf(fp_rin,"GNSS-SDR-mercurio SDR 1.0 REC # / TYPE / VERS\n"); - fprintf(fp_rin,"0000000000 CTTC00000.00 ANT # / TYPE\n"); - fprintf(fp_rin," 4797642.2790 166436.1500 4185504.6370 APPROX POSITION XYZ\n"); - fprintf(fp_rin," 0.0000 0.0000 0.0000 ANTENNA: DELTA H/E/N\n"); - fprintf(fp_rin," 1 0 WAVELENGTH FACT L1/2\n"); - fprintf(fp_rin," 2 C1 L1 # / TYPES OF OBSERV\n"); + // -------- Line 1 + std::string version="3.01"; + line = std::string(5,' '); + line += version; + line +=std::string(11,' '); + line += rinex_printer::leftJustify("OBSERVATION DATA",20); + line +=satelliteSystem["GPS"]; + line +=std::string(19,' '); + line +=std::string("RINEX VERSION / TYPE"); + rinex_printer::lengthCheck(line); + out << line << std::endl; - fprintf(fp_rin," 0.1000 INTERVAL\n"); - //INTRODUIR HORA PRIMERA OBSERVACIO - //ho escriure un cop hagi adquirit dades - //fprintf(fp_rin," 2001 3 24 13 10 36.0000000 TIME OF FIRST OBS\n"); - //fprintf(fp_rin," END OF HEADER\n"); - fp_rin_end = ftell(fp_rin); - temps_primera_obs=1; - } + // -------- 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 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); + 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); + out << line << std::endl; + + + // -------- Line 6 + 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); + out << line << std::endl; + + + + // -------- Line 6 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("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) + + + // -------- ANTENNA: DELTA H/E/N + + + // -------- SYS / OBS TYPES + + // -------- 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; + + // -------- TIME OF FIRST OBS + + + // -------- SYS /PHASE SHIFTS + + + // -------- 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::LogRinex2Obs(gps_navigation_message nav_msg,double pseudoranges_clock, std::map pseudoranges) { - int ss; + /* int ss; char sat_vis[36]; for(int i=0;i<36;i++) sat_vis[i]=' '; char packet[80]; @@ -294,21 +586,221 @@ void rinex_printer::LogRinex2Obs(gps_navigation_message nav_msg,double pseudoran fprintf(fp_rin,"%14.3f %14.3f %d\n",pseudoranges_iter->second,0.0,ss); //TODO: include the carrier phase fp_rin_end = ftell(fp_rin); } - } + }*/ } -int rinex_printer::signalstrength( double snr) + + + + +int rinex_printer::signalStrength(double snr) { - int ss; - if(snr<=12.00) ss=1; - else if(snr>12.00 && snr<=18.00) ss=2; - else if(snr>18.00 && snr<=24.00) ss=3; - else if(snr>24.00 && snr<=30.00) ss=4; - else if(snr>30.00 && snr<=36.00) ss=5; - else if(snr>36.00 && snr<=42.00) ss=6; - else if(snr>42.00 && snr<=48.00) ss=7; - else if(snr>48.00 && snr<=54) ss=8; - else if(snr>=54.00) ss=9; - return (ss); + int ss; + if(snr<12.00) ss=1; + else if(snr>=12.00 && snr<18.00) ss=2; + else if(snr>=18.00 && snr<24.00) ss=3; + else if(snr>=24.00 && snr<30.00) ss=4; + else if(snr>=30.00 && snr<36.00) ss=5; + else if(snr>=36.00 && snr<42.00) ss=6; + else if(snr>=42.00 && snr<48.00) ss=7; + else if(snr>=48.00 && snr<54) ss=8; + else if(snr>=54.00) ss=9; + return (ss); } + + + + +/* + + + + +enum RINEX_enumObservationType +{ + RINEX_OBS_TYPE_PSEUDORANGE = 'C', //!< 'C' Pseudorange observation + RINEX_OBS_TYPE_CARRIER_PHASE = 'L', //!< 'L' Carrier Phase observation + RINEX_OBS_TYPE_DOPPLER = 'D', //!< 'L' Doppler observation + RINEX_OBS_TYPE_SIGNAL_STRENGTH = 'S' //!< 'S' Signal strength observation +} ; + +enum RINEX_enumBand +{ + RINEX_BAND_1 = 1, + RINEX_BAND_2 = 2, + RINEX_BAND_3 = 3, + RINEX_BAND_4 = 4, + RINEX_BAND_5 = 5, + RINEX_BAND_6 = 6, + RINEX_BAND_7 = 7, + RINEX_BAND_8 = 8 +}; + + +enum RINEX_enumChannel +{ + RINEX_GPS_L1_CA = "1C", //!< "1C" GPS L1 C/A + RINEX_GPS_L1_P = "1P", //!< "1P" GPS L1 P + RINEX_GPS_L1_Z_TRACKING = "1W", //!< "1W" GPS L1 Z-tracking and similar (AS on) + RINEX_GPS_L1_Y = "1Y", //!< "1Y" GPS L1 Y + RINEX_GPS_L1_M = "1M", //!< "1M" GPS L1 M + RINEX_GPS_L1_CODELESS = "1N", //!< "1N" GPS L1 codeless + RINEX_GPS_L2_CA = "2C", //!< "2C" GPS L2 C/A + RINEX_GPS_L2_SEMI_CODELESS = "2D", //!< "2D" GPS L2 L1(C/A)+(P2-P1) semi-codeless + RINEX_GPS_L2_L2CM = "2S", //!< "2S" GPS L2 L2C (M) + RINEX_GPS_L2_L2CL = "2L", //!< "2L" GPS L2 L2C (L) + RINEX_GPS_L2_L2CML = "2X", //!< "2X" GPS L2 L2C (M+L) + RINEX_GPS_L2_P = "2P", //!< "2P" GPS L2 P + RINEX_GPS_L2_Z_TRACKING = "2W", //!< "2W" GPS L2 Z-tracking and similar (AS on) + RINEX_GPS_L2_Y = "2Y", //!< "2Y" GPS L2 Y + RINEX_GPS_L2_M = "2M", //!< "2M" GPS GPS L2 M + RINEX_GPS_L2_codeless = "2N", //!< "2N" GPS L2 codeless + RINEX_GPS_L5_I = "5I", //!< "5I" GPS L5 I + RINEX_GPS_L5_Q = "5Q", //!< "5Q" GPS L5 Q + RINEX_GPS_L5_IQ = "5X", //!< "5X" GPS L5 I+Q + RINEX_GLONASS_G1_CA = "1C", //!< "1C" GLONASS G1 C/A + RINEX_GLONASS_G1_P= "1P", //!< "1P" GLONASS G1 P + RINEX_GLONASS_G2_CA= "2C", //!< "2C" GLONASS G2 C/A (Glonass M) + RINEX_GLONASS_G2_P= "2P", //!< "2P" GLONASS G2 P + RINEX_GALILEO_E1_A= "1A", //!< "1A" GALILEO E1 A (PRS) + RINEX_GALILEO_E1_B= "1B", //!< "1B" GALILEO E1 B (I/NAV OS/CS/SoL) + RINEX_GALILEO_E1_C= "1C", //!< "1C" GALILEO E1 C (no data) + RINEX_GALILEO_E1_BC= "1X", //!< "1X" GALILEO E1 B+C + RINEX_GALILEO_E1_ABC= "1Z", //!< "1Z" GALILEO E1 A+B+C + RINEX_GALILEO_E5a_I= "5I", //!< "5I" GALILEO E5a I (F/NAV OS) + RINEX_GALILEO_E5a_Q= "5Q", //!< "5Q" GALILEO E5a Q (no data) + RINEX_GALILEO_E5aIQ= "5X", //!< "5X" GALILEO E5a I+Q + RINEX_GALILEO_E5b_I= "7I", //!< "7I" GALILEO E5b I + RINEX_GALILEO_E5b_Q= "7Q", //!< "7Q" GALILEO E5b Q + RINEX_GALILEO_E5b_IQ= "7X", //!< "7X" GALILEO E5b I+Q + RINEX_GALILEO_E5_I= "8I", //!< "8I" GALILEO E5 I + RINEX_GALILEO_E5_Q= "8Q", //!< "8Q" GALILEO E5 Q + RINEX_GALILEO_E5_IQ= "8X", //!< "8X" GALILEO E5 I+Q + RINEX_GALILEO_E56_A= "6A", //!< "6A" GALILEO E6 A + RINEX_GALILEO_E56_B = "6B", //!< "6B" GALILEO E6 B + RINEX_GALILEO_E56_B = "6C", //!< "6C" GALILEO E6 C + RINEX_GALILEO_E56_BC = "6X", //!< "6X" GALILEO E6 B+C + RINEX_GALILEO_E56_ABC = "6Z", //!< "6Z" GALILEO E6 A+B+C + RINEX_SBAS_L1_CA = "1C", //!< "1C" SBAS L1 C/A + RINEX_SBAS_L5_I = "5I", //!< "5I" SBAS L5 I + RINEX_SBAS_L5_Q = "5Q", //!< "5Q" SBAS L5 Q + RINEX_SBAS_L5_IQ = "5X" //!< "5X" SBAS L5 I+Q +} ; + +enum RINEX_enumMarkerType { + GEODETIC, //!< GEODETIC Earth-fixed, high-precision monumentation + NON_GEODETIC, //!< NON_GEODETIC Earth-fixed, low-precision monumentation + SPACEBORNE, //!< SPACEBORNE Orbiting space vehicle + AIRBORNE , //!< AIRBORNE Aircraft, balloon, etc. + WATER_CRAFT, //!< WATER_CRAFT Mobile water craft + GROUND_CRAFT, //!< GROUND_CRAFT Mobile terrestrial vehicle + FIXED_BUOY, //!< FIXED_BUOY "Fixed" on water surface + FLOATING_BUOY, //!< FLOATING_BUOY Floating on water surface + FLOATING_ICE, //!< FLOATING_ICE Floating ice sheet, etc. + GLACIER, //!< GLACIER "Fixed" on a glacier + BALLISTIC, //!< BALLISTIC Rockets, shells, etc + ANIMAL, //!< ANIMAL Animal carrying a receiver + HUMAN //!< HUMAN Human being +}; + +*/ + + + +/* + + + / ** @name Rinex3ObsHeaderValues + * / + //@{ + double version; ///< RINEX 3 version/type + std::string fileType, ///< RINEX 3 file type + satSys; ///< RINEX 3 satellite system + std::string system; ///< RINEX satellite system (enum) + std::string fileProgram, ///< program used to generate file + fileAgency, ///< who ran program + date; ///< when program was run + std::vector commentList; ///< comments in header (optional) + std::string markerName, ///< MARKER NAME + markerNumber, ///< MARKER NUMBER (optional) + markerType; ///< MARKER TYPE + std::string observer, ///< who collected the data + agency; ///< observer's agency + std::string recNo, ///< receiver number + recType, ///< receiver type + recVers; ///< receiver version + std::string antNo, ///< antenna number + antType; ///< antenna type + std::vector antennaPosition, ///< APPROX POSITION XYZ (optional if moving) + antennaDeltaHEN, ///< ANTENNA: DELTA H/E/N + antennaDeltaXYZ; ///< ANTENNA: DELTA X/Y/Z (optional) + std::string antennaSatSys, ///< ANTENNA P.CTR BLOCK: SAT SYS (optional) + antennaObsCode; ///< ANTENNA P.CTR BLOCK: OBS CODE (optional) + std::vector antennaPhaseCtr; ///< ANTENNA P.CTR BLOCK: PCTR POS (optional) + std::vector antennaBsightXYZ; ///< ANTENNA B.SIGHT XYZ (optional) + double antennaZeroDirAzi; ///< ANTENNA ZERODIR AZI (optional) + std::vector antennaZeroDirXYZ; ///< ANTENNA ZERODIR XYZ (optional) + std::vector centerOfMass; ///< vehicle CENTER OF MASS: XYZ (optional) + std::vector obsTypeList; ///< number & types of observations + map > mapObsTypes; ///< map for different sat. systems + std::string sigStrengthUnit; ///< SIGNAL STRENGTH UNIT (optional) + std::vector interval; ///< INTERVAL (optional) + boost::gregorian::date firstObs, ///< TIME OF FIRST OBS + lastObs; ///< TIME OF LAST OBS (optional) + int receiverOffset; ///< RCV CLOCK OFFS APPL (optional) + std::vector infoDCBS; ///< DCBS INFO (optional) + std::vector infoPCVS; ///< PCVS INFO (optional) + int factor, factorPrev; ///< scale factor (temp holders) + int leapSeconds; ///< LEAP SECONDS (optional) + short numSVs; ///< # OF SATELLITES (optional) + std::map > numObsForSat; ///< PRN / # OF OBS (optional) + unsigned long valid; ///< bits set when header members present & valid + std::string satSysTemp, ///< used to save the Sat Sys char while reading Scale Factor lines + satSysPrev; ///< used to recall the previous sat. sys for continuation lines + int numObs, ///< used to save number of obs on # / TYPES and Sys / SCALE FACTOR continuation lines + numObsPrev; ///< used to recall the previous # obs for continuation lines + std::string lastPRN; ///< used to save current PRN while reading PRN/OBS continuation lines + //@} + + /// Converts the daytime \a dt into a Rinex Obs time string for the header + + std::string writeTime(const boost::gregorian::date& date) const; + + + + /// Enum of Time System Correction types. + enum + { + GAUT, /// GAL to UTC using A0, A1 + GPUT, /// GPS to UTC using A0, A1 + SBUT, /// SBAS to UTC using A0, A1 + GLUT, /// GLO to UTC using A0 = TauC , A1 = 0 + GPGA, /// GPS to GAL using A0 = A0G , A1 = A1G + GLGP /// GLO to GPS using A0 = TauGPS, A1 = 0 + } TimeSysCorrEnum; + std::string ionoCorrType; + double ionoParam1[4], ionoParam2[4], ionoParamGal[3]; + long leapSeconds; + std::string timeSysCorrType; + TimeSysCorrEnum timeSysCorrEnum; + double A0, A1; + long timeSysRefTime, timeSysRefWeek; + std::string timeSysCorrSBAS; + long timeSysUTCid; + struct TimeSysCorrInfo + { + std::string timeSysCorrType; + double A0, A1; + long timeSysRefTime, timeSysRefWeek; + std::string timeSysCorrSBAS; + long timeSysUTCid; + }; + //@} + + /// Map for Time System Correction info. + typedef std::map TimeSysCorrMap; + + /// Instance of the map. + TimeSysCorrMap tscMap; */ + diff --git a/src/algorithms/PVT/libs/rinex_2_1_printer.h b/src/algorithms/PVT/libs/rinex_2_1_printer.h index 9c73d425a..f4e0e7bfa 100644 --- a/src/algorithms/PVT/libs/rinex_2_1_printer.h +++ b/src/algorithms/PVT/libs/rinex_2_1_printer.h @@ -1,52 +1,168 @@ -/** - * Copyright notice +/*! + * \file rinex_2_1_printer.h (temporal name) + * \brief Interface of a RINEX 3.01 printer + * See http://igscb.jpl.nasa.gov/igscb/data/format/rinex301.pdf + * \author Carles Fernandez Prades, 2011. cfernandez(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- */ -/** - * Author: Javier Arribas, 2011. jarribas(at)cttc.es - * Luis Esteve, 2011. luis(at)epsilon-formacion.com - */ - -#ifndef RINEX_PRINTER_H_ -#define RINEX_PRINTER_H_ +#ifndef GNSS_SDR_RINEX_PRINTER_H_ +#define GNSS_SDR_RINEX_PRINTER_H_ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - +#include #include "gps_navigation_message.h" +/*! + * \brief Class that handles the generation of Receiver + * INdependent EXchange format (RINEX) files + */ class rinex_printer { private: - int temps_primera_obs; //per saber si he escrit el temps de la primera observació. - int correccio_primera_obs; //per saber si he escrit l correccio de temps de la primera observació. - int primeravegada;//per evitar problemes primera pseudodistancia - int PERMIS_RINEX; //PER DEIXAR ESCRIURE PER PRIMERA VEGADA AL RINEX + std::ofstream navFile ; + std::ofstream obsFile ; + + /*! + * \brief Creates RINEX file names according to the naming convention + * + * See http://igscb.jpl.nasa.gov/igscb/data/format/rinex301.pdf + * Section 4, page 6 + * + * \param[in] type of RINEX file. Can be: + * "RINEX_FILE_TYPE_OBS" - Observation file. + * "RINEX_FILE_TYPE_GPS_NAV" - GPS navigation message file. + * "RINEX_FILE_TYPE_MET" - Meteorological data file. + * "RINEX_FILE_TYPE_GLO_NAV" - GLONASS navigation file. + * "RINEX_FILE_TYPE_GAL_NAV" - Galileo navigation message file. + * "RINEX_FILE_TYPE_MIXED_NAV" - Mixed GNSS navigation message file. + * "RINEX_FILE_TYPE_GEO_NAV" - SBAS Payload navigation message file. + * "RINEX_FILE_TYPE_SBAS" - SBAS broadcast data file. + * "RINEX_FILE_TYPE_CLK" - Clock file. + */ + std::string createFilename(std::string type); + + /*! + * \brief Generates the data for the PGM / RUN BY / DATE line + */ + std::string getLocalTime(); + + /*! + * \brief Checks that the line is 80 characters length + */ + void lengthCheck(std::string line); + + /*! + * \brief If the string is bigger than length, truncate it from the right. + * otherwise, add pad characters to its right. + * + * Left-justifies the input in a string of the specified + * length. If the new length (\a length) is larger than the + * current length, the string is extended by the pad + * character (\a pad). The default pad character is a + * blank. + * \param[in] s string to be modified. + * \param[in] length new desired length of string. + * \param[in] pad character to pad string with (blank by default). + * \return a reference to \a s. */ + inline std::string& leftJustify(std::string& s, + const std::string::size_type length, + const char pad = ' '); + + /*! + * \brief If the string is bigger than length, truncate it from the right. + * otherwise, add pad characters to its right. + * + * Left-justifies the receiver in a string of the specified + * length (const version). If the new length (\a length) is larger + * than the current length, the string is extended by the pad + * character (\a pad). The default pad character is a + * blank. + * \param[in] s string to be modified. + * \param[in] length new desired length of string. + * \param[in] pad character to pad string with (blank by default). + * \return a reference to \a s. */ + inline std::string leftJustify(const std::string& s, + const std::string::size_type length, + const char pad = ' ') + { std::string t(s); return leftJustify(t, length, pad); } + + + + /*! + * \brief Generates the Navigation Data header + */ + void Rinex2NavHeader(std::ofstream& out); + + /*! + * \brief Generates the Observation data header + */ + void Rinex2ObsHeader(std::ofstream& out); + + /*! + * \brief Generation of RINEX signal strength indicators + */ + int signalStrength(double snr); + - FILE *fp_rin; //!< RINEX OBS FILE Output - FILE *fp_rin2; //!< RINEX NAV FILE Output - unsigned long int fp_rin_end; //!< Hold place of last RINEX OBS FILE pointer, minus the header - unsigned long int fp_rin_end2; //!< Hold place of last RINEX NAV FILE pointer, minus the header - int signalstrength( double snr); - void Rinex2ObsHeader(); - void Rinex2NavHeader(); 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(); + void LogRinex2Nav(gps_navigation_message nav_msg); + void LogRinex2Obs(gps_navigation_message nav_msg,double interframe_seconds, std::map pseudoranges); - void set_headers(std::string file_name); - void LogRinex2Nav(gps_navigation_message nav_msg); - void LogRinex2Obs(gps_navigation_message nav_msg,double interframe_seconds, std::map pseudoranges); - rinex_printer(); - ~rinex_printer(); }; + + +// Implementation of inline function + +inline std::string& rinex_printer::leftJustify(std::string& s, + const std::string::size_type length, + const char pad) +{ + + if(length < s.length()) + { + s = s.substr(0, length); + } + else + { + s.append(length-s.length(), pad); + } + return s; +} + + #endif diff --git a/src/core/system_parameters/GPS_L1_CA.h b/src/core/system_parameters/GPS_L1_CA.h index a7497c101..e961fed2a 100644 --- a/src/core/system_parameters/GPS_L1_CA.h +++ b/src/core/system_parameters/GPS_L1_CA.h @@ -29,32 +29,30 @@ */ -#ifndef GPS_DEFINES_H -#define GPS_DEFINES_H +#ifndef GNSS_SDR_GPS_L1_CA_H_ +#define GNSS_SDR_GPS_L1_CA_H_ #define NAVIGATION_SOLUTION_RATE_MS 1000 -// GPS CONSTANTS -// JAVI: ADD SYSTEM PREFIX - -// SEPARATE FILE GPS.H -const float GPS_C_m_s= 299792458.0; // The speed of light, [m/s] -const float GPS_C_m_ms= 299792.4580; // The speed of light, [m/ms] +const float GPS_C_m_s = 299792458.0; //!< The speed of light, [m/s] +const float GPS_C_m_ms = 299792.4580; //!< The speed of light, [m/ms] const float GPS_STARTOFFSET_ms= 68.802; //[ms] Initial sign. travel time -const double GPS_PI = 3.1415926535898; // Pi used in the GPS coordinate system +const double GPS_PI = 3.1415926535898; //!< Pi used in the GPS coordinate system + + // carrier and code frequencies -const float GPS_L1_FREQ_HZ = 1.57542e9; -const float GPS_L2_FREQ_HZ = 1.22760e9; -const float GPS_L1_CA_CODE_RATE_HZ = 1.023e6; -const float GPS_L1_CA_CODE_LENGTH_CHIPS = 1023.0; +const float GPS_L1_FREQ_HZ = 1.57542e9; +const float GPS_L2_FREQ_HZ = 1.22760e9; +const float GPS_L1_CA_CODE_RATE_HZ = 1.023e6; +const float GPS_L1_CA_CODE_LENGTH_CHIPS = 1023.0; //-- Constants for satellite position calculation ------------------------- -const double OMEGA_EARTH_DOT = 7.2921151467e-5; // Earth rotation rate, [rad/s] -const double GM = 3.986005e14; // Universal gravitational constant times the mass of the Earth, [m^3/s^2] -const double F = -4.442807633e-10; // Constant, [sec/(meter)^(1/2)] +const double OMEGA_EARTH_DOT = 7.2921151467e-5; //!< Earth rotation rate, [rad/s] +const double GM = 3.986005e14; //!< Universal gravitational constant times the mass of the Earth, [m^3/s^2] +const double F = -4.442807633e-10; //!< Constant, [sec/(meter)^(1/2)] // NAVIGATION MESSAGE DEMODULATION AND DECODING @@ -67,17 +65,19 @@ const double F = -4.442807633e-10; // Constant, [sec/(meter)^(1/2) #define GPS_SUBFRAME_BITS 300 #define GPS_WORD_BITS 30 /*! - * Maximum Time-Of-Arrival (TOA) difference between satellites for a receiveer operated on Earth surface is 20 ms, according to the GPS orbit model descrived in [1] Pag. 32. - * It should be taken into account to set the buffer size for the PRN start timestamp in the pseudorranges block. + * \brief Maximum Time-Of-Arrival (TOA) difference between satellites for a receiver operated on Earth surface is 20 ms * - * [1] J. Bao-Yen Tsui, Fundamentals of Global Positioning System Receivers. A Software Approach, John Wiley & Sons, Inc., Hoboken, NJ, 2n edition, 2005. + * According to the GPS orbit model described in [1] Pag. 32. + * It should be taken into account to set the buffer size for the PRN start timestamp in the pseudoranges block. + * [1] J. Bao-Yen Tsui, Fundamentals of Global Positioning System Receivers. A Software Approach, John Wiley & Sons, + * Inc., Hoboken, NJ, 2nd edition, 2005. */ -#define MAX_TOA_DELAY_MS 20 +const double MAX_TOA_DELAY_MS=20; #define num_of_slices(x) sizeof(x)/sizeof(bits_slice) -/*! @ingroup GPS_DEFINES - * @brief Navigation message bits slice structure: A portion of bits is indicated by +/*! + * \brief Navigation message bits slice structure: A portion of bits is indicated by * the start position inside the subframe and the length in number of bits */ typedef struct bits_slice{ int position; @@ -90,9 +90,10 @@ typedef struct bits_slice{ } bits_slice; -/*! @ingroup GPS_DEFINES - * @brief Demodulator gnss_synchro structure, used to feed the pseudorange block */ + +/*! + * \brief Demodulator gnss_synchro structure, used to feed the pseudorange block */ typedef struct gnss_synchro { double preamble_delay_ms; @@ -105,9 +106,11 @@ typedef struct gnss_synchro bool flag_preamble; } gnss_synchro; -/*! @ingroup GPS_DEFINES - * @brief Observables structure, used to feed the PVT block */ + + +/*! + * \brief Observables structure, used to feed the PVT block */ typedef struct gnss_pseudorange { double pseudorange_m; @@ -116,6 +119,10 @@ typedef struct gnss_pseudorange bool valid; } gnss_pseudorange; + + + + /* Constants for scaling the ephemeris found in the data message the format is the following: TWO_N5 -> 2^-5, TWO_P4 -> 2^4, PI_TWO_N43 -> Pi*2^-43, etc etc Additionally some of the PI*2^N terms are used in the tracking stuff @@ -125,56 +132,62 @@ typedef struct gnss_pseudorange PI_TWO_PX ==> Pi*2^X ONE_PI_TWO_PX = (1/Pi)*2^X */ +#define TWO_P4 (16) //!< 2^4 +#define TWO_P11 (2048) //!< 2^11 +#define TWO_P12 (4096) //!< 2^12 +#define TWO_P14 (16384) //!< 2^14 +#define TWO_P16 (65536) //!< 2^16 +#define TWO_P19 (524288) //!< 2^19 +#define TWO_P31 (2147483648.0) //!< 2^31 +#define TWO_P32 (4294967296.0) //!< 2^32 this is too big for an int so add the x.0 +#define TWO_P57 (1.441151880758559e+017) //!< 2^57 -// SEPARATE FILE: CONSTANTS.H +#define TWO_N5 (0.03125) //!< 2^-5 +#define TWO_N11 (4.882812500000000e-004) //!< 2^-11 +#define TWO_N19 (1.907348632812500e-006) //!< 2^-19 +#define TWO_N20 (9.536743164062500e-007) //!< 2^-20 +#define TWO_N21 (4.768371582031250e-007) //!< 2^-21 +#define TWO_N24 (5.960464477539063e-008) //!< 2^-24 +#define TWO_N25 (2.980232238769531e-008) //!< 2^-25 +#define TWO_N27 (7.450580596923828e-009) //!< 2^-27 +#define TWO_N29 (1.862645149230957e-009) //!< 2^-29 +#define TWO_N30 (9.313225746154785e-010) //!< 2^-30 +#define TWO_N31 (4.656612873077393e-010) //!< 2^-31 +#define TWO_N32 (2.328306436538696e-010) //!< 2^-32 +#define TWO_N33 (1.164153218269348e-010) //!< 2^-33 +#define TWO_N38 (3.637978807091713e-012) //!< 2^-38 +#define TWO_N43 (1.136868377216160e-013) //!< 2^-43 +#define TWO_N50 (8.881784197001252e-016) //!< 2^-50 +#define TWO_N55 (2.775557561562891e-017) //!< 2^-55 +#define TWO_P56 (7.205759403792794e+016) //!< 2^56 +#define TWO_P57 (1.441151880758559e+017) //!< 2^57 -#define TWO_P4 (16) //!< 2^4 -#define TWO_P11 (2048) //!< 2^11 -#define TWO_P12 (4096) //!< 2^12 -#define TWO_P14 (16384) //!< 2^14 -#define TWO_P16 (65536) //!< 2^16 -#define TWO_P19 (524288) //!< 2^19 -#define TWO_P31 (2147483648.0) //!< 2^31 -#define TWO_P32 (4294967296.0) //!< 2^32 this is too big for an int so add the x.0 -#define TWO_P57 (1.441151880758559e+017) //!< 2^57 +#define PI_TWO_N19 (5.992112452678286e-006) //!< Pi*2^-19 +#define PI_TWO_N43 (3.571577341960839e-013) //!< Pi*2^-43 +#define PI_TWO_N31 (1.462918079267160e-009) //!< Pi*2^-31 +#define PI_TWO_N38 (1.142904749427469e-011) //!< Pi*2^-38 +#define PI_TWO_N23 (3.745070282923929e-007) //!< Pi*2^-23 -#define TWO_N5 (0.03125) //!< 2^-5 -#define TWO_N11 (4.882812500000000e-004) //!< 2^-11 -#define TWO_N19 (1.907348632812500e-006) //!< 2^-19 -#define TWO_N20 (9.536743164062500e-007) //!< 2^-20 -#define TWO_N21 (4.768371582031250e-007) //!< 2^-21 -#define TWO_N24 (5.960464477539063e-008) //!< 2^-24 -#define TWO_N25 (2.980232238769531e-008) //!< 2^-25 -#define TWO_N27 (7.450580596923828e-009) //!< 2^-27 -#define TWO_N29 (1.862645149230957e-009) //!< 2^-29 -#define TWO_N30 (9.313225746154785e-010) //!< 2^-30 -#define TWO_N31 (4.656612873077393e-010) //!< 2^-31 -#define TWO_N32 (2.328306436538696e-010) //!< 2^-32 -#define TWO_N33 (1.164153218269348e-010) //!< 2^-33 -#define TWO_N38 (3.637978807091713e-012) //!< 2^-38 -#define TWO_N43 (1.136868377216160e-013) //!< 2^-43 -#define TWO_N50 (8.881784197001252e-016) //!< 2^-50 -#define TWO_N55 (2.775557561562891e-017) //!< 2^-55 -#define TWO_P56 (7.205759403792794e+016) //!< 2^56 -#define TWO_P57 (1.441151880758559e+017) //!< 2^57 -#define PI_TWO_N19 (5.992112452678286e-006) //!< Pi*2^-19 -#define PI_TWO_N43 (3.571577341960839e-013) //!< Pi*2^-43 -#define PI_TWO_N31 (1.462918079267160e-009) //!< Pi*2^-31 -#define PI_TWO_N38 (1.142904749427469e-011) //!< Pi*2^-38 -#define PI_TWO_N23 (3.745070282923929e-007) //!< Pi*2^-23 // GPS NAVIGATION MESSAGE STRUCTURE -// NAVIGATION MESSAGE FIELDS POSITIONS (from GPS SPS Signal specifications) +// NAVIGATION MESSAGE FIELDS POSITIONS (from IS-GPS-200E Appendix II) // SUBFRAME 1-5 (TLM and HOW) -const bits_slice SUBFRAME_ID[]= {{50,3}}; + const bits_slice TOW[]= {{31,17}}; +const bits_slice INTEGRITY_STATUS_FLAG[] = {{23,1}}; +const bits_slice ALERT_FLAG[] = {{48,1}}; +const bits_slice ANTI_SPOOFING_FLAG[] = {{49,1}}; +const bits_slice SUBFRAME_ID[]= {{50,3}}; + // SUBFRAME 1 const bits_slice GPS_WEEK[]= {{61,10}}; +const bits_slice CA_OR_P_ON_L2[]= {{71,2}}; //* const bits_slice SV_ACCURACY[]= {{73,4}}; const bits_slice SV_HEALTH[]= {{77,6}}; +const bits_slice L2_P_DATA_FLAG[] = {{91,1}}; const bits_slice T_GD[]= {{197,8}}; const double T_GD_LSB=TWO_N31; @@ -238,7 +251,45 @@ const bits_slice SV_PAGE[]= {{63,6}}; // SUBFRAME 4 +//! \todo read all pages of subframe 4 + +// Page 18 - Ionospheric and UTC data +const bits_slice ALPHA_0[]= {{69,8}}; +const double ALPHA_0_LSB=TWO_N30; +const bits_slice ALPHA_1[]= {{77,8}}; +const double ALPHA_1_LSB=TWO_N27; +const bits_slice ALPHA_2[]= {{91,8}}; +const double ALPHA_2_LSB=TWO_N24; +const bits_slice ALPHA_3[]= {{99,8}}; +const double ALPHA_3_LSB=TWO_N24; +const bits_slice BETA_0[]= {{107,8}}; +const double BETA_0_LSB=TWO_P11; +const bits_slice BETA_1[]= {{121,8}}; +const double BETA_1_LSB=TWO_P14; +const bits_slice BETA_2[]= {{129,8}}; +const double BETA_2_LSB=TWO_P16; +const bits_slice BETA_3[]= {{137,8}}; +const double BETA_3_LSB=TWO_P16; +const bits_slice A_1[]= {{151,24}}; +const double A_1_LSB=TWO_N50; +const bits_slice A_0[]= {{181,24},{211,8}}; +const double A_0_LSB=TWO_N30; +const bits_slice T_OT[]= {{219,8}}; +const double T_OT_LSB=TWO_P12; +const bits_slice WN_T[]= {{227,8}}; +const double WN_T_LSB = 1; +const bits_slice DELTAT_LS[]= {{241,8}}; +const double DELTAT_LS_LSB = 1; +const bits_slice WN_LSF[]= {{249,8}}; +const double WN_LSF_LSB = 1; +const bits_slice DN[]= {{257,8}}; +const double DN_LSB = 1; +const bits_slice DELTAT_LSF[]= {{271,8}}; +const double DELTAT_LSF_LSB = 1; + + + // SUBFRAME 5 +//! \todo read all pages of subframe 5 - -#endif /* GPS_DEFINES_H */ +#endif /* GNSS_SDR_GPS_L1_CA_H_ */ diff --git a/src/core/system_parameters/gps_navigation_message.cc b/src/core/system_parameters/gps_navigation_message.cc index 39761a479..339588150 100644 --- a/src/core/system_parameters/gps_navigation_message.cc +++ b/src/core/system_parameters/gps_navigation_message.cc @@ -1,6 +1,8 @@ /*! * \file gps_navigation_message.cc - * \brief Navigation message structure for GPS L1 C/A signal + * \brief Implementation of a GPS NAV Data message decoder + * + * See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II * \author Javier Arribas, 2011. jarribas(at)cttc.es * * ------------------------------------------------------------------------- @@ -32,254 +34,294 @@ void gps_navigation_message::reset() { - d_TOW=0; - //broadcast orbit 1 - d_IODE_SF2=0; - d_IODE_SF3=0; - d_Crs=0; - d_Delta_n=0; - d_M_0=0; - //broadcast orbit 2 - d_Cuc=0; - d_e_eccentricity=0; - d_Cus=0; - d_sqrt_A=0; - //broadcast orbit 3 - d_Toe=0; - d_Toc=0; - d_Cic=0; - d_OMEGA0=0; - d_Cis=0; - //broadcast orbit 4 - d_i_0=0; - d_Crc=0; - d_OMEGA=0; - d_OMEGA_DOT=0; - //broadcast orbit 5 - d_IDOT=0; - d_codes_on_L2=0; - d_GPS_week=0; - d_L2_P_data_flag=0; - //broadcast orbit 6 - d_SV_accuracy=0; - d_SV_health=0; - d_TGD=0; - d_IODC=-1; - //broadcast orbit 7 + d_TOW=0; + //broadcast orbit 1 + d_IODE_SF2=0; + d_IODE_SF3=0; + d_Crs=0; + d_Delta_n=0; + d_M_0=0; + //broadcast orbit 2 + d_Cuc=0; + d_e_eccentricity=0; + d_Cus=0; + d_sqrt_A=0; + //broadcast orbit 3 + d_Toe=0; + d_Toc=0; + d_Cic=0; + d_OMEGA0=0; + d_Cis=0; + //broadcast orbit 4 + d_i_0=0; + d_Crc=0; + d_OMEGA=0; + d_OMEGA_DOT=0; + //broadcast orbit 5 + d_IDOT=0; + d_codes_on_L2=0; + d_GPS_week=0; + b_L2_P_data_flag=false; + //broadcast orbit 6 + d_SV_accuracy=0; + d_SV_health=0; + d_TGD=0; + d_IODC=-1; + //broadcast orbit 7 - d_fit_interval=0; - d_spare1=0; - d_spare2=0; + d_fit_interval=0; + d_spare1=0; + d_spare2=0; - d_A_f0=0; - d_A_f1=0; - d_A_f2=0; + d_A_f0=0; + d_A_f1=0; + d_A_f2=0; - //clock terms - d_master_clock=0; - d_dtr=0; - d_satClkCorr=0; + //clock terms + d_master_clock=0; + d_dtr=0; + d_satClkCorr=0; - // satellite positions - d_satpos_X=0; - d_satpos_Y=0; - d_satpos_Z=0; + // satellite positions + d_satpos_X=0; + d_satpos_Y=0; + d_satpos_Z=0; - // info - d_channel_ID=0; - d_satellite_PRN=0; + // info + d_channel_ID=0; + d_satellite_PRN=0; - // time synchro - d_subframe1_timestamp_ms=0; + // time synchro + d_subframe1_timestamp_ms=0; + + // flags + b_alert_flag = false; + b_integrity_status_flag = false; + b_antispoofing_flag = false; + + + // Ionosphere and UTC + d_alpha0=0; + d_alpha1=0; + d_alpha2=0; + d_alpha3=0; + d_beta0=0; + d_beta1=0; + d_beta2=0; + d_beta3=0; + d_A1=0; + d_A0=0; + d_t_OT=0; + d_WN_T=0; + d_DeltaT_LS=0; + d_WN_LSF=0; + d_DN=0; + d_DeltaT_LSF=0; } + + gps_navigation_message::gps_navigation_message() { - reset(); - + reset(); } + + + + + +bool gps_navigation_message::read_navigation_bool(std::bitset bits, const bits_slice *slices) +{ + bool value; + + if (bits[GPS_SUBFRAME_BITS-slices[0].position]==1) + { + value=true; + } + else + { + value=false; + } + + return value; +} + + + + + unsigned long int gps_navigation_message::read_navigation_unsigned(std::bitset bits, const bits_slice *slices, int num_of_slices) { - unsigned long int value; - value=0; - for (int i=0;i bits, const bits_slice *slices, int num_of_slices) { - signed long int value=0; + signed long int value=0; - // read the MSB ad perform the sign extension - if (bits[GPS_SUBFRAME_BITS-slices[0].position]==1) - { - value^=0xFFFFFFFF; - }else{ - value&=0; - } - for (int i=0;i half_week) - { - corrTime = time - 2*half_week; - }else if (time < -half_week) - { - corrTime = time + 2*half_week; - } - return corrTime; + double corrTime; + double half_week = 302400; // seconds + corrTime = time; + if (time > half_week) + { + corrTime = time - 2*half_week; + }else if (time < -half_week) + { + corrTime = time + 2*half_week; + } + return corrTime; } + + void gps_navigation_message::master_clock(double transmitTime) { - double dt; - double satClkCorr; - // Find initial satellite clock correction -------------------------------- + double dt; + double satClkCorr; + // Find initial satellite clock correction -------------------------------- - // --- Find time difference --------------------------------------------- - dt = check_t(transmitTime - d_Toc); + // --- Find time difference --------------------------------------------- + dt = check_t(transmitTime - d_Toc); - //--- Calculate clock correction --------------------------------------- - satClkCorr = (d_A_f2 * dt + d_A_f1) * dt + d_A_f0 - d_TGD; + //--- Calculate clock correction --------------------------------------- + satClkCorr = (d_A_f2 * dt + d_A_f1) * dt + d_A_f0 - d_TGD; - d_master_clock = transmitTime - satClkCorr; + d_master_clock = transmitTime - satClkCorr; } + + void gps_navigation_message::satpos() { - double tk; - double a; - double n; - double n0; - double M; - double E; - double E_old; - double dE; - double nu; - double phi; - double u; - double r; - double i; - double Omega; + double tk; + double a; + double n; + double n0; + double M; + double E; + double E_old; + double dE; + double nu; + double phi; + double u; + double r; + double i; + double Omega; - // Find satellite's position ---------------------------------------------- + // Find satellite's position ---------------------------------------------- - // Restore semi-major axis - a = d_sqrt_A*d_sqrt_A; + // Restore semi-major axis + a = d_sqrt_A*d_sqrt_A; - // Time correction - tk = check_t(d_master_clock - d_Toe); + // Time correction + tk = check_t(d_master_clock - d_Toe); - // Initial mean motion - n0 = sqrt(GM / (a*a*a)); - // Mean motion - n = n0 + d_Delta_n; + // Initial mean motion + n0 = sqrt(GM / (a*a*a)); + // Mean motion + n = n0 + d_Delta_n; - // Mean anomaly - M = d_M_0 + n * tk; - // Reduce mean anomaly to between 0 and 360 deg + // Mean anomaly + M = d_M_0 + n * tk; + // Reduce mean anomaly to between 0 and 360 deg - M = fmod((M + 2*GPS_PI),(2*GPS_PI)); + M = fmod((M + 2*GPS_PI),(2*GPS_PI)); - // Initial guess of eccentric anomaly - E = M; + // Initial guess of eccentric anomaly + E = M; - // --- Iteratively compute eccentric anomaly ---------------------------- - //std::cout<<"d_e_eccentricity="<d_channel_ID==0){ + // debug + /* + if (this->d_channel_ID==0){ std::cout<<"tk"< subframe_bits; - std::bitset word_bits; - for (int i=0;i<10;i++) - { - memcpy(&gps_word,&subframe[i*4],sizeof(char)*4); - word_bits=std::bitset<(GPS_WORD_BITS+2)>(gps_word); - for (int j=0;j - -using namespace boost::assign; - #include "GPS_L1_CA.h" +//using namespace boost::assign; + + + +/*! + * \brief This class represents a GPS NAV Data as described in IS-GPS-200E + * + * See http://www.gps.gov/technical/icwg/IS-GPS-200E.pdf Appendix II + */ class gps_navigation_message { private: unsigned long int read_navigation_unsigned(std::bitset bits, const bits_slice *slices, int num_of_slices); signed long int read_navigation_signed(std::bitset bits, const bits_slice *slices, int num_of_slices); + bool read_navigation_bool(std::bitset bits, const bits_slice *slices); + + /*! + * Accounts for the beginning or end of week crossover + * + * See paragraph 20.3.3.3.3.1 (IS-GPS-200E) + * \param[in] - time in seconds + * \param[out] - corrected time, in seconds + */ double check_t(double time); + public: //broadcast orbit 1 double d_TOW; double d_IODE_SF2; double d_IODE_SF3; - double d_Crs; - double d_Delta_n; - double d_M_0; + double d_Crs; //!< Amplitude of the Sine Harmonic Correction Term to the Orbit Radius [m] + double d_Delta_n; //!< Mean Motion Difference From Computed Value [semi-circles/s] + double d_M_0; //!< Mean Anomaly at Reference Time [semi-circles] //broadcast orbit 2 - double d_Cuc; - double d_e_eccentricity; - double d_Cus; - double d_sqrt_A; + double d_Cuc; //!< Amplitude of the Cosine Harmonic Correction Term to the Argument of Latitude [rad] + double d_e_eccentricity; //!< Eccentricity [dimensionless] + double d_Cus; //!< Amplitude of the Sine Harmonic Correction Term to the Argument of Latitude [rad] + double d_sqrt_A; //!< Square Root of the Semi-Major Axis [sqrt(m)] //broadcast orbit 3 - double d_Toe; - double d_Toc; - double d_Cic; - double d_OMEGA0; - double d_Cis; + double d_Toe; //!< Ephemeris data reference time of week (Ref. 20.3.3.4.3 IS-GPS-200E) [s] + double d_Toc; //!< clock data reference time (Ref. 20.3.3.3.3.1 IS-GPS-200E) [s] + double d_Cic; //!< Amplitude of the Cosine Harmonic Correction Term to the Angle of Inclination [rad] + double d_OMEGA0; //!< Longitude of Ascending Node of Orbit Plane at Weekly Epoch [semi-circles] + double d_Cis; //!< Amplitude of the Sine Harmonic Correction Term to the Angle of Inclination [rad] //broadcast orbit 4 - double d_i_0; - double d_Crc; - double d_OMEGA; - double d_OMEGA_DOT; + double d_i_0; //!< Inclination Angle at Reference Time [semi-circles] + double d_Crc; //!< Amplitude of the Cosine Harmonic Correction Term to the Orbit Radius [m] + double d_OMEGA; //!< Argument of Perigee [semi-cicles] + double d_OMEGA_DOT; //!< Rate of Right Ascension [semi-circles/s] //broadcast orbit 5 - double d_IDOT; - double d_codes_on_L2; - double d_GPS_week; - double d_L2_P_data_flag; + double d_IDOT; //!< Rate of Inclination Angle [semi-circles/s] + double d_codes_on_L2; //!< + double d_GPS_week; //!< GPS week number, aka WN [week] + bool b_L2_P_data_flag; //!< When true, indicates that the NAV data stream was commanded OFF on the P-code of the L2 channel //broadcast orbit 6 - double d_SV_accuracy; + double d_SV_accuracy; //!< User Range Accuracy (URA) index of the SV (reference paragraph 6.2.1) for the standard positioning service user (Ref 20.3.3.3.1.3 IS-GPS-200E) double d_SV_health; - double d_TGD; - double d_IODC; + double d_TGD; //!< Estimated Group Delay Differential: L1-L2 correction term for the benefit of "L1 only" or "L2 only" users [s] + double d_IODC; //!< Issue of Data, Clock //broadcast orbit 7 double d_fit_interval; double d_spare1; double d_spare2; - double d_A_f0; - double d_A_f1; - double d_A_f2; + double d_A_f0; //!< Coefficient 0 of code phase offset model [s] + double d_A_f1; //!< Coefficient 1 of code phase offset model [s/s] + double d_A_f2; //!< Coefficient 2 of code phase offset model [s/s^2] + + // Flags + + /*! \brief If true, enhanced level of integrity assurance. + * + * If false, indicates that the conveying signal is provided with the legacy level of integrity assurance. + * That is, the probability that the instantaneous URE of the conveying signal exceeds 4.42 times the upper bound + * value of the current broadcast URA index, for more than 5.2 seconds, without an accompanying alert, is less + * than 1E-5 per hour. If true, indicates that the conveying signal is provided with an enhanced level of + * integrity assurance. That is, the probability that the instantaneous URE of the conveying signal exceeds 5.73 + * times the upper bound value of the current broadcast URA index, for more than 5.2 seconds, without an + * accompanying alert, is less than 1E-8 per hour. + */ + bool b_integrity_status_flag; + + bool b_alert_flag; //!< If true, indicates that the SV URA may be worse than indicated in d_SV_accuracy, use that SV at our own risk. + bool b_antispoofing_flag; //