PRSolution_example_1.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation; either version 3.0 of the License, or
8 // any later version.
9 //
10 // The GNSSTk is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with GNSSTk; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 // This software was developed by Applied Research Laboratories at the
20 // University of Texas at Austin.
21 // Copyright 2004-2022, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 // This software was developed by Applied Research Laboratories at the
28 // University of Texas at Austin, under contract to an agency or agencies
29 // within the U.S. Department of Defense. The U.S. Government retains all
30 // rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 // Pursuant to DoD Directive 523024
33 //
34 // DISTRIBUTION STATEMENT A: This software has been approved for public
35 // release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 // GNSSTk example program #4
40 
41 
42  // First, let's include Standard Template Library classes
43 #include <string>
44 #include <vector>
45 
46  // Classes for handling observations RINEX files (data)
47 #include "Rinex3ObsHeader.hpp"
48 #include "Rinex3ObsData.hpp"
49 #include "Rinex3ObsStream.hpp"
50 
51  // Classes for handling satellite navigation parameters RINEX
52  // files (ephemerides)
53 #include "Rinex3NavHeader.hpp"
54 #include "Rinex3NavData.hpp"
55 #include "Rinex3NavStream.hpp"
56 
57  // Classes for handling RINEX files with meteorological parameters
58 #include "RinexMetBase.hpp"
59 #include "RinexMetData.hpp"
60 #include "RinexMetHeader.hpp"
61 #include "RinexMetStream.hpp"
62 
63  // Class for handling tropospheric model
64 #include "GGTropModel.hpp"
65 
66  // Classes for storing ephemerides
67 #include "NavLibrary.hpp"
69 
70  // Class for handling RAIM
71 #include "PRSolution.hpp"
72 
73  // Class defining GPS system constants
74 #include "GNSSconstants.hpp"
75 
76 
77 using namespace std;
78 using namespace gnsstk;
79 
80 
81 int main(int argc, char *argv[])
82 {
83 
85  NavLibrary navLib;
90 
93  ZeroTropModel noTropModel;
94 
97  GGTropModel ggTropModel;
98 
101  TropModel *tropModelPtr=&noTropModel;
102 
103  // This verifies the ammount of command-line parameters given and
104  // prints a help message, if necessary
105  if ( (argc < 3) || (argc > 4) )
106  {
107  cerr << "Usage:" << endl;
108  cerr << " " << argv[0]
109  << " <RINEX Obs file> <RINEX Nav file> [<RINEX Met file>]"
110  << endl;
111 
112  exit (-1);
113  }
114 
115  // Let's compute an useful constant (also found in "GNSSconstants.hpp")
116  const double gamma = (L1_FREQ_GPS/L2_FREQ_GPS)*(L1_FREQ_GPS/L2_FREQ_GPS);
117 
118  try
119  {
120 
121  // Create the nav file reader
122  ndfp = std::make_shared<gnsstk::MultiFormatNavDataFactory>();
123  // Add the nav file reader to the nav library interface
124  navLib.addFactory(ndfp);
125  // Read nav file and store navigation data
126  if (!ndfp->addDataSource(argv[2]))
127  {
128  cerr << "Failed to read \"" << argv[2] << "\"" << endl;
129  return 1;
130  }
131 
132  // If provided, open and store met file into a linked list.
133  list<RinexMetData> rml;
134 
135  if ( argc == 4 )
136  {
137 
138  RinexMetStream rms(argv[3]); // Open meteorological data file
139  RinexMetHeader rmh;
140 
141  // Let's read the header (may be skipped)
142  rms >> rmh;
143 
144  RinexMetData rmd;
145 
146  // If meteorological data is provided, let's change pointer to
147  // a GG-model object
148  tropModelPtr=&ggTropModel;
149 
150  // All data is read into "rml", a meteorological data
151  // linked list
152  while (rms >> rmd) rml.push_back(rmd);
153 
154  } // End of 'if ( argc == 4 )'
155 
156  // Open and read the observation file one epoch at a time.
157  // For each epoch, compute and print a position solution
158  Rinex3ObsStream roffs(argv[1]); // Open observations data file
159 
160  // In order to throw exceptions, it is necessary to set the failbit
161  roffs.exceptions(ios::failbit);
162 
163  Rinex3ObsHeader roh;
164  Rinex3ObsData rod;
165 
166  // Let's read the header
167  roffs >> roh;
168 
169  // The following lines fetch the corresponding indexes for some
170  // observation types we are interested in. Given that old-style
171  // observation types are used, GPS is assumed.
172  int indexP1;
173  try
174  {
175  indexP1 = roh.getObsIndex( "P1" );
176  }
177  catch (...)
178  {
179  cerr << "The observation file doesn't have P1 pseudoranges." << endl;
180  exit(1);
181  }
182 
183  int indexP2;
184  try
185  {
186  indexP2 = roh.getObsIndex( "P2" );
187  }
188  catch (...)
189  {
190  indexP2 = -1;
191  }
192 
193  // Defining iterator "mi" for meteorological data linked list
194  // "rml", and set it to the beginning
195  list<RinexMetData>::iterator mi=rml.begin();
196 
197  // Let's process all lines of observation data, one by one
198  while ( roffs >> rod )
199  {
200 
201  // Find a weather point. Only if a meteorological RINEX file
202  // was provided, the meteorological data linked list "rml" is
203  // neither empty or at its end, and the time of meteorological
204  // records are below observation data epoch.
205  while ( ( argc==4 ) &&
206  ( !rml.empty() ) &&
207  ( mi!=rml.end() ) &&
208  ( (*mi).time < rod.time ) )
209  {
210 
211  mi++; // Read next item in list
212 
213  // Feed GG tropospheric model object with meteorological
214  // parameters. Take into account, however, that setWeather
215  // is not accumulative, i.e., only the last fed set of
216  // data will be used for computation
217  ggTropModel.setWeather( (*mi).data[RinexMetHeader::TD],
218  (*mi).data[RinexMetHeader::PR],
219  (*mi).data[RinexMetHeader::HR] );
220 
221  } // End of 'while ( ( argc==4 ) && ...'
222 
223 
224  // Apply editing criteria
225  if ( rod.epochFlag == 0 || rod.epochFlag == 1 ) // Begin usable data
226  {
227 
228  vector<SatID> prnVec;
229  vector<double> rangeVec;
230 
231  // Define the "it" iterator to visit the observations PRN map.
232  // Rinex3ObsData::DataMap is a map from RinexSatID to
233  // vector<RinexDatum>:
234  // std::map<RinexSatID, vector<RinexDatum> >
235  Rinex3ObsData::DataMap::const_iterator it;
236 
237  // This part gets the PRN numbers and ionosphere-corrected
238  // pseudoranges for the current epoch. They are correspondly fed
239  // into "prnVec" and "rangeVec"; "obs" is a public attribute of
240  // Rinex3ObsData to get the map of observations
241  for ( it = rod.obs.begin(); it!= rod.obs.end(); it++ )
242  {
243 
244  // The RINEX file may have P1 observations, but the current
245  // satellite may not have them.
246  double P1( 0.0 );
247  try
248  {
249  P1 = rod.getObs( (*it).first, indexP1 ).data;
250  }
251  catch (...)
252  {
253  // Ignore this satellite if P1 is not found
254  continue;
255  }
256 
257  double ionocorr( 0.0 );
258 
259  // If there are P2 observations, let's try to apply the
260  // ionospheric corrections
261  if ( indexP2 >= 0 )
262  {
263 
264  // The RINEX file may have P2 observations, but the
265  // current satellite may not have them.
266  double P2( 0.0 );
267  try
268  {
269  P2 = rod.getObs( (*it).first, indexP2 ).data;
270  }
271  catch (...)
272  {
273  // Ignore this satellite if P1 is not found
274  continue;
275  }
276 
277  // Vector 'vecData' contains RinexDatum, whose public
278  // attribute "data" indeed holds the actual data point
279  ionocorr = 1.0 / (1.0 - gamma) * ( P1 - P2 );
280 
281  }
282 
283  // Now, we include the current PRN number in the first part
284  // of "it" iterator into the vector holding the satellites.
285  // All satellites in view at this epoch that have P1 or P1+P2
286  // observations will be included.
287  prnVec.push_back( (*it).first );
288 
289  // The same is done for the vector of doubles holding the
290  // corrected ranges
291  rangeVec.push_back( P1 - ionocorr );
292 
293  // WARNING: Please note that so far no further correction
294  // is done on data: Relativistic effects, tropospheric
295  // correction, instrumental delays, etc.
296 
297  } // End of 'for ( it = rod.obs.begin(); it!= rod.obs.end(); ...'
298 
299  // The default constructor for PRSolution objects (like
300  // "raimSolver") is to set a RMSLimit of 6.5. We change that
301  // here. With this value of 3e6 the solution will have a lot
302  // more dispersion.
303  raimSolver.RMSLimit = 3e6;
304 
305  // In order to compute positions we need the current time, the
306  // vector of visible satellites, the vector of corresponding
307  // ranges, the object containing satellite ephemerides, and a
308  // pointer to the tropospheric model to be applied
309  raimSolver.RAIMComputeUnweighted( rod.time,
310  prnVec,
311  rangeVec,
312  navLib,
313  tropModelPtr );
314 
315  // Note: Given that the default constructor sets public
316  // attribute "Algebraic" to FALSE, a linearized least squares
317  // algorithm will be used to get the solutions.
318  // Also, the default constructor sets ResidualCriterion to true,
319  // so the rejection criterion is based on RMS residual of fit,
320  // instead of RMS distance from an a priori position.
321 
322  // If we got a valid solution, let's print it
323 
324  if ( raimSolver.isValid() )
325  {
326  // Vector "Solution" holds the coordinates, expressed in
327  // meters in an Earth Centered, Earth Fixed (ECEF) reference
328  // frame. The order is x, y, z (as all ECEF objects)
329  cout << setprecision(12) << raimSolver.Solution[0] << " " ;
330  cout << raimSolver.Solution[1] << " " ;
331  cout << raimSolver.Solution[2];
332  cout << endl ;
333 
334  } // End of 'if ( raimSolver.isValid() )'
335 
336  } // End of 'if ( rod.epochFlag == 0 || rod.epochFlag == 1 )'
337 
338  } // End of 'while ( roffs >> rod )'
339 
340  }
341  catch (Exception& e)
342  {
343  cerr << e << endl;
344  }
345  catch (...)
346  {
347  cerr << "Caught an unexpected exception." << endl;
348  }
349 
350  return 0;
351 
352 } // End of 'main()'
Rinex3NavHeader.hpp
gnsstk::RinexMetData
Definition: RinexMetData.hpp:71
gnsstk::RinexMetStream
Definition: RinexMetStream.hpp:70
GGTropModel.hpp
PRSolution.hpp
example4.raimSolver
raimSolver
Definition: example4.py:27
gnsstk::Rinex3ObsHeader
Definition: Rinex3ObsHeader.hpp:155
gnsstk::Rinex3ObsData::obs
DataMap obs
the map of observations
Definition: Rinex3ObsData.hpp:114
gnsstk::L1_FREQ_GPS
const double L1_FREQ_GPS
GPS L1 carrier frequency in Hz.
Definition: DeprecatedConsts.hpp:51
gnsstk::PRSolution
Definition: PRSolution.hpp:216
gnsstk::GGTropModel
Definition: GGTropModel.hpp:53
gnsstk::TropModel
Definition: TropModel.hpp:105
gnsstk::RinexDatum::data
double data
The actual data point.
Definition: RinexDatum.hpp:76
GNSSconstants.hpp
gnsstk::Rinex3ObsData::getObs
virtual RinexDatum getObs(const RinexSatID &svID, size_t index) const
Definition: Rinex3ObsData.cpp:224
example4.indexP1
indexP1
Definition: example4.py:25
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
Rinex3NavStream.hpp
P1
gnsstk::Matrix< double > P1
Definition: Matrix_LUDecomp_T.cpp:49
gnsstk::Rinex3ObsData::epochFlag
short epochFlag
Definition: Rinex3ObsData.hpp:104
Rinex3NavData.hpp
gnsstk::NavDataFactoryPtr
std::shared_ptr< NavDataFactory > NavDataFactoryPtr
Managed pointer to NavDataFactory.
Definition: NavDataFactory.hpp:398
example4.indexP2
indexP2
Definition: example4.py:26
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::L2_FREQ_GPS
const double L2_FREQ_GPS
GPS L2 carrier frequency in Hz.
Definition: DeprecatedConsts.hpp:53
gnsstk::Rinex3ObsData::time
CommonTime time
Time corresponding to the observations.
Definition: Rinex3ObsData.hpp:91
NavLibrary.hpp
P2
gnsstk::Matrix< double > P2
Definition: Matrix_LUDecomp_T.cpp:49
gnsstk::NavLibrary
Definition: NavLibrary.hpp:944
RinexMetBase.hpp
MultiFormatNavDataFactory.hpp
gnsstk::Rinex3ObsData
Definition: Rinex3ObsData.hpp:75
Rinex3ObsHeader.hpp
gnsstk::GGTropModel::setWeather
virtual void setWeather(const double &T, const double &P, const double &H)
Definition: GGTropModel.cpp:160
Rinex3ObsData.hpp
RinexMetHeader.hpp
gnsstk::Rinex3ObsStream
Definition: Rinex3ObsStream.hpp:65
main
int main(int argc, char *argv[])
Definition: PRSolution_example_1.cpp:81
Rinex3ObsStream.hpp
RinexMetStream.hpp
RinexMetData.hpp
std
Definition: Angle.hpp:142
gnsstk::NavLibrary::addFactory
void addFactory(NavDataFactoryPtr &fact)
Definition: NavLibrary.cpp:470
example4.ionocorr
float ionocorr
Definition: example4.py:62
gnsstk::ZeroTropModel
The 'zero' trop model, meaning it always returns zero.
Definition: TropModel.hpp:289
gnsstk::RinexMetHeader
Definition: RinexMetHeader.hpp:70


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:40