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 /// @file SatPassIterator.cpp
40 /// Iterate over a vector of SatPass in time order.
41
42 #include "SatPassIterator.hpp"
43 #include "logstream.hpp"
44
45 using namespace std;
46 using namespace gpstk::StringUtils;
47 namespace gpstk {
48
49 // -------------------------------------------------------------------------------
50 // only constructor
SatPassIterator(vector<SatPass> & splist,bool rev,bool dbug)51 SatPassIterator::SatPassIterator(vector<SatPass>& splist, bool rev, bool dbug)
52 : SPList(splist), timeReverse(rev), debug(dbug)
53 {
54 if(SPList.size() == 0) {
55 Exception e("Empty list");
56 GPSTK_THROW(e);
57 }
58
59 int i,j;
60
61 // ensure time order
62 std::sort(SPList.begin(), SPList.end());
63
64 // copy the list of obs types, and check that each is registered
65 vector<string> otlist;
66 for(i=0; i<SPList[0].labelForIndex.size(); i++) {
67 otlist.push_back(SPList[0].labelForIndex[i]);
68 //if(RinexObsHeader::convertObsType(SPList[0].labelForIndex[i])
69 // == RinexObsHeader::UN)
70 //{
71 // Exception e("Unregistered observation type : "+SPList[0].labelForIndex[i]);
72 // GPSTK_THROW(e);
73 //}
74 }
75
76 // copy the data from the first SatPass in the list, for comparison with the rest
77 DT = SPList[0].dt;
78 FirstTime = SPList[0].getFirstTime();
79 LastTime = SPList[0].getLastTime();
80
81 // loop over the list
82 for(i=0; i<SPList.size(); i++) {
83 // check for consistency of dt
84 if(SPList[i].dt != DT) {
85 Exception e("Inconsistent time intervals: " + asString(SPList[i].dt)
86 + " != " + asString(DT));
87 GPSTK_THROW(e);
88 }
89
90 // find the earliest and latest time
91 if(SPList[i].getFirstTime() < FirstTime) FirstTime = SPList[i].getFirstTime();
92 if(SPList[i].getLastTime() > LastTime) LastTime = SPList[i].getLastTime();
93
94 } // end loop over the list
95
96 reset(timeReverse,debug);
97 }
98
99 // -------------------------------------------------------------------------------
100 // restart the iteration
reset(bool rev,bool dbug)101 void SatPassIterator::reset(bool rev, bool dbug) throw()
102 {
103 timeReverse = rev;
104 debug = dbug;
105 // clear out the old
106 currentN = 0;
107 listIndex.clear();
108 dataIndex.clear();
109 countOffset.clear();
110 indexStatus = vector<int>(SPList.size(),-1);
111 // loop over the list
112 int i = (timeReverse ? SPList.size()-1 : 0);
113 while((timeReverse && i >= 0) || (!timeReverse && i<SPList.size())) {
114
115 for(;;) {
116 // ignore passes with negative Status
117 if(SPList[i].Status < 0) break;
118
119 // define latest epoch when time reversed
120 if(timeReverse && currentN == 0)
121 currentN = int((SPList[i].firstTime - FirstTime)/DT + 0.5)
122 + SPList[i].spdvector[SPList[i].size()-1].ndt;
123
124 // (re)build the maps
125 if(listIndex.find(SPList[i].sat) == listIndex.end()) {
126 indexStatus[i] = 0;
127 listIndex[SPList[i].sat] = i;
128 dataIndex[SPList[i].sat] = (timeReverse ? SPList[i].size()-1 : 0);
129 countOffset[SPList[i].sat]
130 = int((SPList[i].firstTime - FirstTime)/DT + 0.5);
131 LOG(DEBUG4) << "reset - define map " << i <<" for sat " << SPList[i].sat
132 << " at time " << SPList[i].firstTime.printf("%4F %10.3g")
133 << " offset " << countOffset[SPList[i].sat];
134 }
135 else {
136 indexStatus[i] = -1;
137 LOG(DEBUG4)<< "reset - turn off pass "<< i <<" for sat " << SPList[i].sat
138 << " at time " << SPList[i].firstTime.printf("%4F %10.3g");
139 }
140
141 break; // mandatory
142 }
143
144 if(timeReverse) i--; else i++;
145 } // end loop over the list
146
147 }
148
149 // -------------------------------------------------------------------------------
150 // return 1 for success, 0 at end of data
151 // Access (all of) the data for the next epoch. As long as this function
152 // returns non-zero, there is more data to be accessed. Ignore passes with
153 // Status less than zero.
154 // @param indexMap map<unsigned int, unsigned int> defined so that all the
155 // data in the current iteration is found at
156 // SatPassList[i].data(j) where indexMap[i] = j.
157 // @return 1 for success, 0 at the end of the dataset.
158 // @throw if time tags are out of order.
next(map<unsigned int,unsigned int> & indexMap)159 int SatPassIterator::next(map<unsigned int, unsigned int>& indexMap)
160 {
161 int i,j,k,numsvs;
162 RinexSatID sat;
163
164 numsvs = 0;
165 indexMap.clear();
166 nextIndexMap.clear();
167
168 if(debug) LOG(INFO) << "SPIterator::next(map) - time "
169 << (FirstTime+currentN*DT).printf("%4F %10.3g")
170 << " size of listIndex " << listIndex.size();
171
172 while(numsvs == 0) {
173 if(listIndex.size() == 0) {
174 if(debug) LOG(INFO) << "Return 0 from next()";
175 return 0;
176 }
177
178 // loop over active SatPass's
179 map<RinexSatID,int>::iterator kt;
180
181 // debugging - dump the listIndex
182
183 if(debug) for(kt = listIndex.begin(); kt != listIndex.end(); kt++)
184 LOG(INFO) << " listIndex: " << kt->first << " " << kt->second;
185
186 kt = listIndex.begin();
187 while(kt != listIndex.end()) {
188 sat = kt->first;
189 i = kt->second;
190 j = dataIndex[sat];
191 if(debug) LOG(INFO) << "Loop over listIndex: " << sat << " " << i <<" "<< j;
192
193 if(SPList[i].Status < 0) {
194 listIndex.erase(kt++); // erasing a map - do exactly this and no more
195 if(debug) LOG(INFO) << " Erase this pass for bad status: index "
196 << i << " sat " << sat << " size is now " << listIndex.size();
197 continue;
198 }
199
200 if(countOffset[sat] + SPList[i].spdvector[j].ndt == currentN) {
201 // found active sat at this count - add to map
202 nextIndexMap[i] = j;
203 numsvs++;
204 if(debug) LOG(INFO) << "SPIterator::next(map) found sat " << sat
205 << " at index " << i;
206
207 // increment data index
208 if((timeReverse && --j < 0) ||
209 (!timeReverse && ++j == SPList[i].spdvector.size()))
210 {
211 if(debug) LOG(INFO) << " This pass for sat " << sat << " is done ...";
212 indexStatus[i] = 1;
213
214 // find the next pass for this sat
215 k = i + (timeReverse ? -1 : 1);
216 while((timeReverse && k>=0) || (!timeReverse && k<SPList.size()))
217 //for(k=i+1; k<SPList.size(); k++)
218 {
219 if(debug) LOG(INFO) << " ... consider next pass " << k
220 << " " << SPList[k].sat
221 << " " << SPList[k].firstTime.printf("%4F %10.3g");
222 bool found(false);
223 for(;;) {
224 if(SPList[k].Status < 0) // bad pass
225 break;
226 if(SPList[k].sat != sat) // wrong sat
227 break;
228 if(indexStatus[k] > 0) // already done
229 break;
230
231 // take this one
232 indexStatus[k] = 0;
233 i = listIndex[sat] = k;
234 dataIndex[sat] = (timeReverse ? SPList[i].size()-1 : 0);
235 countOffset[sat] = int((SPList[i].firstTime-FirstTime)/DT + 0.5);
236 found = true;
237 break; // mandatory
238 }
239 if(found) break;
240 if(timeReverse) k--; else k++;
241 } // end while loop over next passes
242
243 if(indexStatus[i] == 0) {
244 if(debug) LOG(INFO) << " ... new pass for sat " << SPList[i].sat
245 << " at index " << i << " and time "
246 << SPList[i].firstTime.printf("%4F %10.3g");
247 }
248 }
249 else {
250 dataIndex[sat] = j;
251 }
252
253 } // end if found active sat at this count
254
255 // increment the iterator
256 if(indexStatus[i] > 0) { // a new one was not found
257 listIndex.erase(kt++); // erasing a map - do exactly this and no more
258 if(debug) LOG(INFO) << " Erase this pass: index " << i << " sat " << sat
259 << " size is now " << listIndex.size();
260 }
261 else kt++;
262
263 } // end while loop over active SatPass's
264 if(debug) LOG(INFO) << "End while loop over active SatPasses";
265
266 //if(robs.numSvs == 0) cout << "Gap at " << currentN << endl;
267 if(timeReverse) currentN--; else currentN++;
268
269 } // end while robs.numSvs==0
270
271 indexMap = nextIndexMap;
272 if(debug) LOG(INFO) << "Return 1 from next()";
273
274 return 1;
275 }
276
277 // -------------------------------------------------------------------------------
278 // return 1 for success, 0 at end of data
279 // NB This assumes all the passes have the same obstypes in the same order, AND
280 // it knows nothing of the obstypes in the header....
281 // TD perhaps better design is to pass this (SatPassIterator) a vector of obstypes
282 // from the header and have it fill the robs parallel to that, inserting 0 as nec.
next(RinexObsData & robs)283 int SatPassIterator::next(RinexObsData& robs)
284 {
285 if(listIndex.size() == 0) return 0;
286
287 map<unsigned int, unsigned int> indexMap;
288 map<unsigned int, unsigned int>::const_iterator kt;
289 int iret = next(indexMap);
290 if(iret == 0) return iret;
291
292 robs.obs.clear();
293 robs.epochFlag = 0;
294 robs.clockOffset = 0.0;
295 robs.numSvs = 0;
296
297 // get the time tag.
298 // NB there is an assumption here, that all that SatPass'es in indexMap are
299 // consistent w.r.t. time tag - clearly ok if SPList was created in the usual ways.
300 kt = indexMap.begin();
301 robs.time = SPList[kt->first].time(kt->second);
302
303 // loop over the map
304 for(kt = indexMap.begin(); kt != indexMap.end(); kt++) {
305 int i = kt->first;
306 int j = kt->second;
307 RinexSatID sat = SPList[i].getSat();
308 //LOG(DEBUG2) << "SPIterator::next(robs) found sat " << sat
309 // << " at index " << i << " and time " << SPList[i].time(j);
310
311 bool found = false;
312 bool flag = (SPList[i].spdvector[j].flag != SatPass::BAD);
313 for(int k=0; k<SPList[i].labelForIndex.size(); k++) {
314 RinexObsType ot;
315 ot = RinexObsHeader::convertObsType(SPList[i].labelForIndex[k]);
316 if(ot == RinexObsHeader::UN) {
317 ; //LOG(DEBUG1) << " Error - this sat has UN obstype"; // TD warn?
318 }
319 else {
320 found = true;
321 // NO some obs may be zero b/c they are not collected (e.g. C2) -> bad
322 //robs.obs[sat][ot].data = flag ? SPList[i].spdvector[j].data[k] : 0.;
323 //robs.obs[sat][ot].lli = flag ? SPList[i].spdvector[j].lli[k] : 0;
324 //robs.obs[sat][ot].ssi = flag ? SPList[i].spdvector[j].ssi[k] : 0;
325 robs.obs[sat][ot].data = SPList[i].spdvector[j].data[k];
326 robs.obs[sat][ot].lli = SPList[i].spdvector[j].lli[k];
327 robs.obs[sat][ot].ssi = SPList[i].spdvector[j].ssi[k];
328 }
329 }
330 if(found) robs.numSvs++;
331 }
332
333 return 1;
334 }
335
336 } // end namespace
337
338 // -------------------------------------------------------------------------------
339 // -------------------------------------------------------------------------------
340