EpochCombination LinearCombination::evaluate(const RinexObsData& rod) { EpochCombination result; RinexObsData::RinexSatMap::const_iterator it; for (it = rod.obs.begin(); it!= rod.obs.end(); it++) { RinexObsData::RinexObsTypeMap otmap = it->second; RinexObsData::RinexObsTypeMap::const_iterator itObs; std::map<RinexObsHeader::RinexObsType, double>::iterator itCoeff; double sum=0; for (itCoeff=coeffList.begin(); itCoeff!=coeffList.end(); itCoeff++) { bool valid= ((itObs=otmap.find(itCoeff->first))!=otmap.end()); sum += itObs->second.data * itCoeff->second; } result[it->first] = sum; } return (result); }
/** Pull out the selected observation type from a RinexObsData object * @param rinexData The Rinex data set holding the observations * @param typeObs The type of observation we want to get * * @return * Number of satellites with this kind of data available */ inline virtual int getData(const RinexObsData& rinexData, RinexObsHeader::RinexObsType typeObs) throw(InvalidData) { try { // Let's make sure each time we start with clean Vectors availableSV.resize(0); obsData.resize(0); // Create a CheckPRData object with the given limits CheckPRData checker(minPRange, maxPRange); // Let's define the "it" iterator to visit the observations PRN map // RinexSatMap is a map from SatID to RinexObsTypeMap: // std::map<SatID, RinexObsTypeMap> RinexObsData::RinexSatMap::const_iterator it; for (it = rinexData.obs.begin(); it!= rinexData.obs.end(); it++) { // RinexObsTypeMap is a map from RinexObsType to RinexDatum: // std::map<RinexObsHeader::RinexObsType, RinexDatum> RinexObsData::RinexObsTypeMap otmap; // Let's define a iterator to visit the observations type map RinexObsData::RinexObsTypeMap::const_iterator itObs1; // The "second" field of a RinexSatMap (it) is a RinexObsTypeMap (otmap) otmap = (*it).second; // Let's find the observation type inside the RinexObsTypeMap that is "otmap" itObs1 = otmap.find(typeObs); // Let's check if we found this type of observation and it is between the limits if ( (itObs1!=otmap.end()) && ( (checker.check((*itObs1).second.data)) || !(checkData) ) ) { // Store all relevant data of this epoch availableSV = availableSV && (*it).first; obsData = obsData && (*itObs1).second.data; } } // End of data extraction from this epoch } catch(...) { InvalidData e("Unable to get data from RinexObsData object"); GPSTK_THROW(e); } // Let's record the number of SV with this type of data available numSV = (int)obsData.size(); // If everything is fine so far, then the results should be valid valid = true; return numSV; }; // end ExtractData::getData()
int main(int argc, char *argv[]) { // Declaration of objects for storing ephemerides and handling RAIM GPSEphemerisStore bcestore; PRSolution raimSolver; // Object for void-type tropospheric model (in case no meteorological RINEX // is available) ZeroTropModel noTropModel; // Object for GG-type tropospheric model (Goad and Goodman, 1974) GGTropModel ggTropModel; // Default constructor => default values for model // Pointer to one of the two available tropospheric models. It points to // the void model by default TropModel *tropModelPtr=&noTropModel; // This verifies the ammount of command-line parameters given and prints a help // message, if necessary if ((argc < 3) || (argc>4)) { cerr << "Usage:" << endl; cerr << " " << argv[0] << " <RINEX Obs file> <RINEX Nav file> [<RINEX Met file>]" << endl; exit (-1); } // Let's compute an useful constant (also found in "icd_200_constants.hpp") const double gamma = (L1_FREQ / L2_FREQ)*(L1_FREQ / L2_FREQ); try { // Read nav file and store unique list of ephemeredes RinexNavStream rnffs(argv[2]); // Open ephemerides data file RinexNavData rne; RinexNavHeader hdr; // Let's read the header (may be skipped) rnffs >> hdr; // Storing the ephemeris in "bcstore" while (rnffs >> rne) bcestore.addEphemeris(rne); // Setting the criteria for looking up ephemeris bcestore.SearchNear(); // If provided, open and store met file into a linked list. list<RinexMetData> rml; if (argc==4) { RinexMetStream rms(argv[3]); // Open meteorological data file RinexMetHeader rmh; // Let's read the header (may be skipped) rms >> rmh; RinexMetData rmd; // If meteorological data is provided, let's change pointer to // a GG-model object tropModelPtr=&ggTropModel; // All data is read into "rml", a meteorological data linked list while (rms >> rmd) rml.push_back(rmd); } // Open and read the observation file one epoch at a time. // For each epoch, compute and print a position solution RinexObsStream roffs(argv[1]); // Open observations data file // In order to throw exceptions, it is necessary to set the failbit roffs.exceptions(ios::failbit); RinexObsHeader roh; RinexObsData rod; // Let's read the header (may be skipped) roffs >> roh; // Defining iterator "mi" for meteorological data linked list "rml", and // set it to the beginning list<RinexMetData>::iterator mi=rml.begin(); // Let's process all lines of observation data, one by one while (roffs >> rod) { // Find a weather point. Only if a meteorological RINEX file was // provided, the meteorological data linked list "rml" is neither empty // or at its end, and the time of meteorological records are below // observation data epoch. while ( (argc==4) && (!rml.empty()) && (mi!=rml.end()) && ((*mi).time < rod.time) ) { mi++; // Read next item in list // Feed GG tropospheric model object with meteorological parameters // Take into account, however, that setWeather is not accumulative, // i.e., only the last fed set of data will be used for computation ggTropModel.setWeather((*mi).data[RinexMetHeader::TD], (*mi).data[RinexMetHeader::PR], (*mi).data[RinexMetHeader::HR]); } // Apply editing criteria if (rod.epochFlag == 0 || rod.epochFlag == 1) // Begin usable data { vector<SatID> prnVec; vector<double> rangeVec; // Let's define the "it" iterator to visit the observations PRN map // RinexSatMap is a map from SatID to RinexObsTypeMap: // std::map<SatID, RinexObsTypeMap> RinexObsData::RinexSatMap::const_iterator it; // This part gets the PRN numbers and ionosphere-corrected // pseudoranges for the current epoch. They are correspondly fed // into "prnVec" and "rangeVec" // "obs" is a public attribute of RinexObsData to get the map // of observations for (it = rod.obs.begin(); it!= rod.obs.end(); it++) { // RinexObsTypeMap is a map from RinexObsType to RinexDatum: // std::map<RinexObsHeader::RinexObsType, RinexDatum> RinexObsData::RinexObsTypeMap otmap; // Let's define two iterators to visit the observations type map RinexObsData::RinexObsTypeMap::const_iterator itP1, itP2; ///////////////////////////////////////////////// // // What did we do in the former code lines?: // // For each observation data epoch (rod), if valid // (rod.epochFlag = 0 or 1): // - use "it" iterator to visit the RinexObsTypeMap of each // satellite, // - and then use "itP1" and "itP2" iterators to visit the // observation data (RinexDatum) according to their type // (RinexObsType) // ///////////////////////////////////////////////// // The "second" field of a RinexPrnMap (it) is a // RinexObsTypeMap (otmap) otmap = (*it).second; // Let's find a P1 observation inside the RinexObsTypeMap that // is "otmap" itP1 = otmap.find(RinexObsHeader::P1); // If "itP1" is not the last type of observation, there may be // a P2 observation and the double-frequency ionospheric // corrections may be applied if (itP1!=otmap.end()) { double ionocorr = 0; // Now, let's find a P2 observation inside the // RinexObsTypeMap that is "otmap" itP2 = otmap.find(RinexObsHeader::P2); // If we indeed found a P2 observation, let's apply the // ionospheric corrections if (itP2!=otmap.end()) // The "second" part of a RinexObsTypeMap is a RinexDatum, // whose public attribute "data" indeed holds the actual // data point ionocorr = 1./(1.-gamma)*((*itP1).second.data-(*itP2).second.data); // Now, we include the current PRN number in the first part // of "it" (a RinexPrnMap) into the vector holding PRN numbers. // All satellites in view at this epoch that also have P1 and // P2 observations will be included prnVec.push_back((*it).first); // The same is done for the vector of doubles holding the // corrected ranges rangeVec.push_back((*itP1).second.data-ionocorr); // WARNING: Please note that so far no further correction is // done on data: Relativistic effects, tropospheric correction, // instrumental delays, etc. } } // The default constructor for PRSolution objects (like "raimSolver") // is to set a RMSLimit of 6.5. We change that here. With this value // of 3e6 the solution will have a lot more dispersion raimSolver.RMSLimit = 3e6; // In order to compute positions we need the current time, the // vector of visible satellites, the vector of corresponding ranges, // the object containing satellite ephemerides and a pointer to the // tropospheric model to be applied raimSolver.RAIMCompute(rod.time,prnVec,rangeVec, bcestore, tropModelPtr); // Note: Given that the default constructor sets public attribute // "Algebraic" to FALSE, a linearized least squares algorithm will // be used to get the solutions. // Also, the default constructor sets ResidualCriterion to true, so // the rejection criterion is based on RMS residual of fit, instead // of RMS distance from an a priori position. // If we got a valid solution, let's print it if (raimSolver.isValid()) { // Vector "Solution" holds the coordinates, expressed in meters // in an Earth Centered, Earth Fixed (ECEF) reference frame. The // order is x, y, z (as all ECEF objects) cout << setprecision(12) << raimSolver.Solution[0] << " " ; cout << raimSolver.Solution[1] << " " ; cout << raimSolver.Solution[2]; cout << endl ; } } // End usable data } // End loop through each epoch }
//------------------------------------------------------------------------------------ void FillRawData(ObsFile& of) throw(Exception) { try { //int nsvs; //double C1; GSatID sat; RinexObsData::RinexSatMap::const_iterator it; RinexObsData::RinexObsTypeMap otmap; RinexObsData::RinexObsTypeMap::const_iterator jt; Station& st=Stations[of.label]; st.RawDataMap.clear(); // assumes one file per site at each epoch // loop over sat=it->first, ObsTypeMap=it->second // fill DataStruct // Don't include L2 when user has specified --Freq L1 -- there have been // cases where L2 is present but bad, and user had no recourse but to edit // the RINEX file to remove L2 before processing //nsvs = 0; for(it=of.Robs.obs.begin(); it != of.Robs.obs.end(); ++it) { sat = it->first; otmap = it->second; // ignore non-GPS satellites if(sat.system != SatID::systemGPS) continue; // is the satellite excluded? if(index(CI.ExSV,sat) != -1) continue; // pull out the data DataStruct D; D.P1 = D.P2 = D.L1 = D.L2 = D.D1 = D.D2 = D.S1 = D.S2 = 0; if(of.inP1 > -1 && CI.Frequency != 2 && (jt=otmap.find(of.Rhead.obsTypeList[of.inP1])) != otmap.end()) D.P1 = jt->second.data; if(of.inP2 > -1 && CI.Frequency != 1 && (jt=otmap.find(of.Rhead.obsTypeList[of.inP2])) != otmap.end()) D.P2 = jt->second.data; if(of.inL1 > -1 && CI.Frequency != 2 && (jt=otmap.find(of.Rhead.obsTypeList[of.inL1])) != otmap.end()) D.L1 = jt->second.data; if(of.inL2 > -1 && CI.Frequency != 1 && (jt=otmap.find(of.Rhead.obsTypeList[of.inL2])) != otmap.end()) D.L2 = jt->second.data; if(of.inD1 > -1 && CI.Frequency != 2 && (jt=otmap.find(of.Rhead.obsTypeList[of.inD1])) != otmap.end()) D.D1 = jt->second.data; if(of.inD2 > -1 && CI.Frequency != 1 && (jt=otmap.find(of.Rhead.obsTypeList[of.inD2])) != otmap.end()) D.D2 = jt->second.data; if(of.inS1 > -1 && CI.Frequency != 2 && (jt=otmap.find(of.Rhead.obsTypeList[of.inS1])) != otmap.end()) D.S1 = jt->second.data; if(of.inS2 > -1 && CI.Frequency != 1 && (jt=otmap.find(of.Rhead.obsTypeList[of.inS2])) != otmap.end()) D.S2 = jt->second.data; //if(of.inC1 > -1 && CI.Frequency != 2 && // (jt=otmap.find(of.Rhead.obsTypeList[of.inC1])) != otmap.end()) // C1 = jt->second.data; // if P1 is not available, but C1 is, use C1 in place of P1 if((of.inP1 == -1 || D.P1 == 0) && of.inC1 > -1 && CI.Frequency != 2 && (jt=otmap.find(of.Rhead.obsTypeList[of.inC1])) != otmap.end()) D.P1 = jt->second.data; // temp - round L1 and L2 to 1/256 cycle //{ // double dL1 = D.L1 - long(D.L1); // double cL1 = double(long(256.*dL1))/256.; // D.L1 -= dL1 - cL1; //} st.RawDataMap[sat] = D; st.time = SolutionEpoch; //nsvs++; } // end loop over sats } catch(Exception& e) { GPSTK_RETHROW(e); } catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); } catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); } } // end FillRawData()