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