1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk 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 GPSTk 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 GPSTk; 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-2020, 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 /**
40  * @file Configure.cpp
41  * Manage configuration details, at various points, for program DDBase.
42  */
43 
44 //------------------------------------------------------------------------------------
45 // system includes
46 
47 // GPSTk
48 #include "Epoch.hpp"
49 #include "YDSTime.hpp"
50 // DDBase
51 #include "DDBase.hpp"
52 #include "RinexUtilities.hpp"
53 
54 #include "SimpleTropModel.hpp"
55 #include "SaasTropModel.hpp"
56 #include "NBTropModel.hpp"
57 #include "GGTropModel.hpp"
58 #include "GGHeightTropModel.hpp"
59 #include "NeillTropModel.hpp"
60 
61 //------------------------------------------------------------------------------------
62 using namespace std;
63 using namespace gpstk;
64 
65 //------------------------------------------------------------------------------------
66 // local data
67 SimpleTropModel TropModelSimple;          // CI.pTropModel will point to one of these
68 GGTropModel TropModelGG;
69 GGHeightTropModel TropModelGGh;
70 NBTropModel TropModelNB;
71 SaasTropModel TropModelSaas;
72 
73 //------------------------------------------------------------------------------------
74 // prototypes -- this module only
75 /**
76  * @throw Exception
77  */
78 int Initialize(void);
79 /**
80  * @throw Exception
81  */
82 int UpdateConfig(void);
83 /**
84  * @throw Exception
85  */
86 void ReadAllObsHeaders();                            // ReadObsFiles.cpp
87 /**
88  * @throw Exception
89  */
90 int ConfigureEstimation(void);      // Estimation.cpp
91 /**
92  * @throw Exception
93  */
94 int ConfigureStochasticModel(void); // StochasticModels.cpp
95 
96 //------------------------------------------------------------------------------------
Configure(int which)97 int Configure(int which)
98 {
99 try {
100    if(which == 1) return Initialize();
101    if(which == 2) return UpdateConfig();
102    if(which == 3) {
103       int iret = ConfigureEstimation();         // Estimation.cpp
104       if(iret) return iret;
105       return ConfigureStochasticModel();        // StochasticModels.cpp
106    }
107 
108    return 0;
109 }
110 catch(Exception& e) { GPSTK_RETHROW(e); }
111 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
112 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
113 }   // end Configure()
114 
115 //------------------------------------------------------------------------------------
116 // Configure(1)
117 // open and read navigation files
118 // open and read headers of all observation files
Initialize(void)119 int Initialize(void)
120 {
121 try {
122    size_t i;
123    // global pEph will point to one of these
124    static GPSEphemerisStore BCEphList;
125    static SP3EphemerisStore SP3EphList;
126 
127    if(CI.Verbose) oflog << "BEGIN Configure(1)"
128       << " at total time " << fixed << setprecision(3)
129       << double(clock()-totaltime)/double(CLOCKS_PER_SEC) << " seconds."
130       << endl;
131    if(CI.Frequency == 1) wave = wl1;
132    if(CI.Frequency == 2) wave = wl2;
133       // NB wave should never be used for L3 -- see warning in CommandInput.cpp
134    else if(CI.Frequency == 3) wave = wl1;
135 
136       // open nav files, if any, and read EphemerisStore into EphLists
137    if(CI.NavFileNames.size() > 0) {
138       if(!CI.NavPath.empty())
139          for(i=0; i<CI.NavFileNames.size(); i++)
140             CI.NavFileNames[i] = CI.NavPath + "/" + CI.NavFileNames[i];
141 
142       // fill ephemeris store -- this routine in RinexUtilities.cpp
143       FillEphemerisStore(CI.NavFileNames, SP3EphList, BCEphList);
144    }
145 
146       // read all headers and store information in Station object
147    ReadAllObsHeaders();
148 
149       // use the information gathered in ReadAllObsHeaders to determine DT
150       // if the user did not specify --DT, set it
151       // else if the --DT the user chose is too small, reset it
152       // else leave --DT alone
153    double DT=-1.0;
154    for(i=0; i<ObsFileList.size(); i++) {
155       if(ObsFileList[i].dt > DT)
156          DT = ObsFileList[i].dt;
157       if(ObsFileList[i].firstTime > CI.BegTime)
158          CI.BegTime = ObsFileList[i].firstTime;
159    }
160    if(CI.DataInterval == -1) {
161       CI.DataInterval = DT;
162       if(CI.Verbose) oflog << "DDBase has determined the data interval (--DT) to be "
163          << CI.DataInterval << " seconds." << endl;
164    }
165    else if(CI.DataInterval < DT) {
166       CI.DataInterval = DT;
167       oflog << "Warning - DDBase has changed the data interval (--DT) to "
168          << CI.DataInterval << " seconds." << endl;
169    }
170 
171       // dump SP3 store to log
172    if(SP3EphList.size()) {
173       if(CI.Verbose) SP3EphList.dump(oflog,0);
174    }
175    else if(CI.Verbose) oflog << "SP3 Ephemeris store is empty" << endl;
176 
177       // dump BCE store to log
178    if(BCEphList.size()) {
179          // this causes the CorrectedEphemerisRange routines to pick the
180          // closest TOE in either future or past of the epoch, rather
181          // than the closest in the past -- see GPSEphemerisStore.hpp
182       BCEphList.SearchNear();
183 
184       if(CI.Debug) BCEphList.dump(oflog,1);
185       else if(CI.Verbose) BCEphList.dump(oflog,0);
186    }
187    else if(CI.Verbose) oflog << "BC Ephemeris store is empty" << endl;
188 
189       // assign pointer
190       // NB SP3 takes precedence
191    if(SP3EphList.size())     pEph = &SP3EphList;
192    else if(BCEphList.size()) pEph = &BCEphList;
193    else {
194       cerr << "Initialize ERROR: no ephemeris. Abort." << endl;
195       oflog << "Initialize ERROR: no ephemeris. Abort." << endl;
196       return 1;
197    }
198 
199       // open all EOP files and fill the EOPstore
200    if(!CI.EOPPath.empty())
201       for(i=0; i<CI.EOPFileNames.size(); i++)
202          CI.EOPFileNames[i] = CI.EOPPath + "/" + CI.EOPFileNames[i];
203 
204    if(CI.EOPFileNames.size() > 0) {
205       for(i=0; i<CI.EOPFileNames.size(); i++)
206          EOPList.addFile(CI.EOPFileNames[i]);
207    }
208    else {
209       try {
210          EOPList.addIERSFile("finals.daily");
211       }
212       catch(FileMissingException& fme) {
213          string msg("DDBase was unable to find any Earth Orientation parameters:\n"
214            " either add option --EOPFile <file> or put file 'finals.daily' in the"
215            " current directory.\n  (http://maia.usno.navy.mil/ser7/finals.daily)\n");
216          cerr << msg;
217          oflog << msg;
218          GPSTK_RETHROW(fme);
219       }
220    }
221 
222    if(EOPList.size()) {
223       if(CI.Debug) EOPList.dump(1,oflog);
224       else if(CI.Verbose) EOPList.dump(0,oflog);
225    }
226    else oflog << "Warning - no Earth Orientation Parameters were input\n";
227 
228       // add path to output files
229    if(!CI.OutPath.empty()) {
230       if(!CI.OutputClkFile.empty())
231          CI.OutputClkFile = CI.OutPath + "/" + CI.OutputClkFile;
232       if(!CI.OutputDDDFile.empty())
233          CI.OutputDDDFile = CI.OutPath + "/" + CI.OutputDDDFile;
234       if(!CI.OutputTDDFile.empty())
235          CI.OutputTDDFile = CI.OutPath + "/" + CI.OutputTDDFile;
236       if(!CI.OutputRawFile.empty())
237          CI.OutputRawFile = CI.OutPath + "/" + CI.OutputRawFile;
238       if(!CI.OutputRawDDFile.empty())
239          CI.OutputRawDDFile = CI.OutPath + "/" + CI.OutputRawDDFile;
240       if(!CI.OutputPRSFile.empty())
241          CI.OutputPRSFile = CI.OutPath + "/" + CI.OutputPRSFile;
242       if(!CI.OutputDDRFile.empty())
243          CI.OutputDDRFile = CI.OutPath + "/" + CI.OutputDDRFile;
244    }
245 
246       // assign trop model for RAIM (model for DD est assigned in Configure(2))
247       // NB using another, like Saastamoinen, here, is problematic because it
248       // requires height, latitude and DOY input, [ this because RAIM calls
249       // CI.pTropModel->correction(elevation) ], and that info is different for
250       // different sites and not all available.
251    CI.pTropModel = &TropModelSimple;
252       // TD per site
253    CI.pTropModel->setWeather(CI.DefaultTemp,CI.DefaultPress,CI.DefaultRHumid);
254 
255       // Define first and last epochs
256    FirstEpoch = CommonTime::BEGINNING_OF_TIME;
257    LastEpoch = CommonTime::END_OF_TIME;
258 
259    return 0;
260 }
261 catch(Exception& e) { GPSTK_RETHROW(e); }
262 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
263 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
264 }
265 
266 //------------------------------------------------------------------------------------
267 // Configure(2)
UpdateConfig(void)268 int UpdateConfig(void)
269 {
270 try {
271    if(CI.Verbose) oflog << "BEGIN Configure(2)"
272       << " at total time " << fixed << setprecision(3)
273       << double(clock()-totaltime)/double(CLOCKS_PER_SEC) << " seconds."
274       << endl;
275 
276       // configure trop model for each station
277       // dump height, zenith delays, etc
278    map<string,Station>::iterator it;
279    oflog << "Zenith tropospheric delays and station heights" << endl;
280    for(it=Stations.begin(); it != Stations.end(); it++) {
281       Station& st=it->second;
282       oflog << "  Station " << it->first
283             << " (" << (st.fixed ? "":"not ") << "fixed)" << endl;
284       oflog << "    Position:  " << st.pos.printf("%13.3x m %13.3y m %13.3z m")
285             << endl;
286       oflog << "    Position:  " << st.pos.printf("%A deg N, %L deg E, %h m")
287             << endl;
288       oflog << "    Weather " << setprecision(1) << st.temp << " deg C, "
289                             << setprecision(2) << st.press << " mbars, "
290                             << setprecision(1) << st.rhumid << "%" << endl;
291 
292       // For any trop. model except NewB, use provided or assumed weather values.
293       // For NewB, interpolate weather data
294       if (st.TropType != string("NewB"))
295          st.pTropModel->setWeather(st.temp,st.press,st.rhumid);
296       st.pTropModel->setReceiverHeight(st.pos.getHeight());
297       st.pTropModel->setReceiverLatitude(st.pos.getGeodeticLatitude());
298       st.pTropModel->setDayOfYear(int(static_cast<YDSTime>(FirstEpoch).doy));
299 
300       oflog << "    Trop (model: " << st.TropType << fixed << ") zenith delays:"
301          << " dry " << setprecision(6) << st.pTropModel->dry_zenith_delay();
302       oflog << " m, wet " << setprecision(6) << st.pTropModel->wet_zenith_delay();
303       oflog << " m, total "
304             << setprecision(6) << st.pTropModel->correction(90.0) << " m";
305       oflog << endl;
306    }
307 
308       // check how much data there is
309 
310    return 0;
311 }
312 catch(Exception& e) { GPSTK_RETHROW(e); }
313 catch(std::exception& e) { Exception E("std except: "+string(e.what())); GPSTK_THROW(E); }
314 catch(...) { Exception e("Unknown exception"); GPSTK_THROW(e); }
315 }
316 
317 //------------------------------------------------------------------------------------
318 //------------------------------------------------------------------------------------
319