AntennaStore.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 
45 #include "AntennaStore.hpp"
46 #include "Matrix.hpp"
47 #include "Position.hpp"
48 #include "SolarPosition.hpp"
49 #include "SunEarthSatGeometry.hpp"
50 
51 using namespace std;
52 
53 namespace gnsstk
54 {
55  /* Add the given name, AntexData pair. If the name already exists in the
56  store, replace the data for it with the input object. throw if the
57  AntexData is invalid.
58  */
59  void AntennaStore::addAntenna(const string& name, AntexData& antdata)
60  {
61  if (!antdata.isValid())
62  {
63  Exception e("Invalid AntexData object");
64  GNSSTK_THROW(e);
65  }
66 
67  // is the name already in the store?
68  map<string, AntexData>::iterator it;
69  it = antennaMap.find(name);
70  if (it != antennaMap.end()) // erase it
71  {
72  antennaMap.erase(it);
73  }
74 
75  // add the new data
76  antennaMap[name] = antdata;
77  }
78 
79  /* Get the antenna data for the given name from the store.
80  return true if successful, false if input name was not found in the store
81  */
82  bool AntennaStore::getAntenna(const string& name, AntexData& antdata)
83  {
84  map<string, AntexData>::iterator it;
85  it = antennaMap.find(name);
86  if (it != antennaMap.end())
87  {
88  antdata = it->second;
89  return true;
90  }
91  return false;
92  }
93 
94  /* Get the antenna data for the given satellite from the store.
95  Satellites are identified by two things:
96  system character: G or blank GPS, R GLONASS, E GALILEO, M MIXED
97  and integer PRN or SVN number.
98  NB. PRNs apply to GLONASS as well as GPS
99  NB. Typically there is more than one antenna per satellite in ANTEX files;
100  after calling include...Satellites(), when the store is loaded using
101  addANTEXfile(), a time tag should be passed as input; this will load only
102  the satellites valid at that time tag - most likely exactly one per
103  sys/PRN. param char sys System character for the satellite: G,R,E
104  or M param int n PRN (or SVN) of the satellite param string&
105  name Output antenna (ANTEX) name for the given satellite param AntexData&
106  data Output antenna data for the given satellite param bool inputPRN If
107  false, parameter n is SVN not PRN (default true). return true if
108  successful, false if satellite was not found in the store
109  */
110  bool AntennaStore::getSatelliteAntenna(const char sys, const int n,
111  string& name, AntexData& data,
112  bool inputPRN) const
113  {
114  map<string, AntexData>::const_iterator it;
115  for (it = antennaMap.begin(); it != antennaMap.end(); it++)
116  {
117  if (it->second.isRxAntenna)
118  {
119  continue;
120  }
121  if (it->second.systemChar != sys)
122  {
123  continue;
124  }
125  if (inputPRN && it->second.PRN == n)
126  {
127  name = it->first;
128  data = it->second;
129  return true;
130  }
131  if (!inputPRN && it->second.SVN == n)
132  {
133  name = it->first;
134  data = it->second;
135  return true;
136  }
137  }
138  return false;
139  }
140 
141  // Get a vector of all antenna names in the store
142  void AntennaStore::getNames(vector<string>& names)
143  {
144  names.clear();
145  map<string, AntexData>::iterator it;
146  for (it = antennaMap.begin(); it != antennaMap.end(); it++)
147  names.push_back(it->first);
148  }
149 
150  // Get a vector of all receiver antenna names in the store
151  void AntennaStore::getReceiverNames(vector<string>& names)
152  {
153  names.clear();
154  map<string, AntexData>::iterator it;
155  for (it = antennaMap.begin(); it != antennaMap.end(); it++)
156  {
157  if (it->second.isRxAntenna)
158  {
159  names.push_back(it->first);
160  }
161  }
162  }
163 
164  /* call to give the store a list of receiver antenna names so that only
165  those names will be included in the store (not applicable to satellites).
166  If there are already other names in the store, they will be removed.
167  NB. call before addAntenna() or addANTEXfile()
168  */
169  void AntennaStore::includeReceivers(vector<string>& names)
170  {
171  namesToInclude = names;
172  if (antennaMap.size() == 0)
173  {
174  return;
175  }
176 
177  int j;
178  map<string, AntexData>::iterator it;
179  vector<string> rejects;
180  for (it = antennaMap.begin(); it != antennaMap.end(); it++)
181  {
182  if (it->second.isRxAntenna)
183  {
184  bool ok = false;
185  for (j = 0; j < namesToInclude.size(); j++)
186  {
187  if (it->first == namesToInclude[j])
188  {
189  ok = true;
190  break;
191  }
192  }
193  if (!ok)
194  {
195  rejects.push_back(it->first);
196  }
197  }
198  }
199  for (j = 0; j < rejects.size(); j++)
200  antennaMap.erase(rejects[j]);
201  }
202 
203  /* Open and read an ANTEX format file with the given name, and read it.
204  Add to the store all the receivers with names in the given vector,
205  if it has been provided in a previous call to includeReceivers(),
206  otherwise include all receiver antennas found.
207  NB. call includeSats() or includeGPSsats() to include satellite antennas,
208  before calling this routine.
209  param filename the name of the ANTEX file to read.
210  param time the time (any) of interest, used to choose valid satellites
211  return the number of antennas added.
212  throw any exception caught during reading the file.
213  */
214  int AntennaStore::addANTEXfile(const string& filename, CommonTime time)
215  {
216  try
217  {
218  int i, n = 0;
219  AntexHeader anthdr;
220  AntexData antdata;
221  AntexStream antstrm, asout;
222  CommonTime time1, time2;
223 
224  // test for validity within a few days of time
225  time.setTimeSystem(TimeSystem::Any);
226  time1 = time2 = time;
228  {
229  time1 += double(2 * 86400);
230  time2 -= double(2 * 86400);
231  }
232 
233  // open the input file
234  antstrm.open(filename.c_str(), ios::in);
235  if (!antstrm.is_open())
236  {
237  Exception e("Could not open file " + filename);
238  GNSSTK_THROW(e);
239  }
240  antstrm.exceptions(fstream::failbit);
241 
242  // read the header
243  try
244  {
245  antstrm >> anthdr;
246  if (!anthdr.isValid())
247  {
248  Exception e("Header is not valid");
249  GNSSTK_THROW(e);
250  }
251  }
252  catch (Exception& e)
253  {
254  GNSSTK_RETHROW(e);
255  }
256  catch (exception& e)
257  {
258  Exception ge(string("Std exception: ") + e.what());
259  GNSSTK_THROW(ge);
260  }
261 
262  // read the data
263  while (1)
264  {
265  try
266  {
267  antstrm >> antdata;
268  }
269  catch (Exception& e)
270  {
271  GNSSTK_RETHROW(e);
272  }
273 
274  // ignore invalid data
275  if (!antdata.isValid())
276  {
277  if (!antstrm)
278  {
279  break;
280  }
281  continue;
282  }
283 
284  // name it
285  string name = antdata.name();
286 
287  // find receiver antenna name
288  if (antdata.isRxAntenna && namesToInclude.size())
289  {
290  for (i = 0; i < namesToInclude.size(); i++)
291  {
292  if (name == namesToInclude[i])
293  {
294  addAntenna(name, antdata);
295  n++;
296  break;
297  }
298  }
299  }
300  // else include it
301  else if (antdata.isRxAntenna || includeSats > 1 ||
302  (includeSats == 1 && antdata.systemChar == 'G'))
303  {
304  if (antdata.isValid(time1) || antdata.isValid(time2))
305  {
306  addAntenna(name, antdata);
307  n++;
308  }
309  }
310 
311  // break on EOF
312  if (!antstrm)
313  {
314  break;
315  }
316  }
317 
318  return n;
319  }
320  catch (Exception& e)
321  {
322  GNSSTK_RETHROW(e);
323  }
324  }
325 
326  /* Compute the vector from the SV Center of Mass (COM) to
327  the phase center of the antenna.
328  Satellites are identified by two things:
329  system character: G or blank GPS, R GLONASS, E GALILEO, C BeiDou
330  and integer PRN or SVN number.
331  NB. PRNs apply to GLONASS as well as GPS
332  NB. Typically there is more than one antenna per satellite in ANTEX files;
333  after calling include...Satellites(), when the store is loaded using
334  addANTEXfile(), a time tag should be passed as input; this will load only
335  the satellites valid at that time tag - most likely exactly one per
336  sys/PRN. param char sys System character for the satellite: G,R,E
337  or M param int n PRN (or SVN) of the satellite param Triple
338  satVector Vector from center of Earth to SV. param bool inputPRN If
339  false, parameter n is SVN not PRN (default true). return vector from COM
340  to PC throw InvalidRequest if no data available
341  */
342  Triple AntennaStore::ComToPcVector(const char sys, const int n,
343  const CommonTime& ct,
344  const Triple& satVector,
345  bool inputPRN) const
346  {
347  AntexData antenna;
348  string name;
349  bool dualFrequency = true;
350  try
351  {
352  if (getSatelliteAntenna(sys, n, name, antenna))
353  {
354 
355  // tracking, and future expansion.
356  double fact1 = 1.0;
357  double fact2 = 1.0;
358  string freq1("");
359  string freq2("");
360  switch (sys)
361  {
362  case 'G':
363  {
364  fact1 = 2.5458; // (alpha+1)/alpha
365  fact2 = -1.5458; // -1/alpha
366  freq1 = "G01";
367  freq2 = "G02";
368  break;
369  }
370  case 'R':
371  {
372  fact1 = 2.53125;
373  fact2 = -1.52125;
374  freq1 = "R01";
375  freq2 = "R02";
376  break;
377  }
378 
379  /* Design short-coming in that we are limited to ONE decision
380  per GNSS. The BeiDou ICD says the Broadcast Orbits are
381  aligned to B3I phase center. Generally, we are attempting to
382  move the broadcast orbit from the APC to the COM. Therefore,
383  we only need B3 (C06) */
384  case 'C':
385  {
386  /*
387  double alpha = ((1561.098 * 1561.098) / (1268.52 * 1268.52)) - 1.0;
388  B1 and B3 fact1 = (alpha+1.0) / alpha;
389  fact2 = -1.0 / alpha;
390  freq1 = "C02"; freq2 = "C06";
391  */
392  dualFrequency = false;
393  fact1 = 1.0;
394  freq1 = "C06";
395  break;
396  }
397 
398  case 'E':
399  {
400  double alpha =
401  ((154 * 154) / (116.5 * 116.5)) - 1.0; // E1 and E5a
402  fact1 = (alpha + 1.0) / alpha;
403  fact2 = -1.0 / alpha;
404  freq1 = "E01";
405  freq2 = "E05";
406  break;
407  }
408 
409  default:
410  {
411  stringstream ss;
412  ss << "Invalid satellite system " << sys << " PRN " << n;
413  ss << " for AntennaStore::ComToPcVector.";
414  InvalidRequest ir(ss.str());
415  GNSSTK_THROW(ir);
416  }
417  }
418 
419  /* Rotation matrix from satellite attitude.
420  // Rot * [XYZ] = [body frame] */
421  Matrix<double> SVAtt;
422 
423  // Use low accuracy Sun vector from SunEarthSatGeometry
424  double AR;
425  Position Sun = solarPosition(ct, AR);
427  SVAtt = satelliteAttitude(Rx, Sun);
428 
429  // phase center offset vector in body frame (at L1)
430  Vector<double> PCO(3);
431  if (dualFrequency)
432  {
433  Triple pco1 = antenna.getPhaseCenterOffset(freq1);
434  Triple pco2 = antenna.getPhaseCenterOffset(freq2);
435  for (int i = 0; i < 3;
436  i++) // body frame, mm -> m, iono-free combo
437  PCO(i) = (fact1 * pco1[i] + fact2 * pco2[i]) / 1000.0;
438  }
439  // Single-frequency case.
440  else
441  {
442  Triple pco1 = antenna.getPhaseCenterOffset(freq1);
443  for (int i = 0; i < 3;
444  i++) // body frame, mm -> m, iono-free combo
445  PCO(i) = (fact1 * pco1[i]) / 1000.0;
446  }
447 
448  // PCO vector (from COM to PC) in ECEF XYZ frame, m
449  Vector<double> SatPCOXYZ(3);
450  SatPCOXYZ = transpose(SVAtt) * PCO;
451  Triple pcoxyz = Triple(SatPCOXYZ(0), SatPCOXYZ(1), SatPCOXYZ(2));
452 
453  return pcoxyz;
454  }
455  else
456  {
457  stringstream ss;
458  ss << "AntennaStore::ComToPcVector. No satellite data found for "
459  << sys << " PRN " << n;
460  InvalidRequest ir(ss.str());
461  GNSSTK_THROW(ir);
462  }
463  }
464  catch (Exception exc)
465  {
466  GNSSTK_RETHROW(exc);
467  }
468  }
469 
470  // Same as above except with different calling sequence for convenience
471  Triple AntennaStore::ComToPcVector(const SatID& sidr, const CommonTime& ct,
472  const Triple& satVector) const
473  {
474  char sys = ' ';
475  Triple tp;
476  switch (sidr.system)
477  {
478  case SatelliteSystem::GPS:
479  {
480  sys = 'G';
481  break;
482  }
483  case SatelliteSystem::Galileo:
484  {
485  sys = 'E';
486  break;
487  }
488  case SatelliteSystem::Glonass:
489  {
490  sys = 'R';
491  break;
492  }
493  case SatelliteSystem::BeiDou:
494  {
495  sys = 'C';
496  break;
497  }
498  default:
499  {
500  stringstream ss;
501  ss << "Invalid satellite system " << sidr;
502  ss << " for AntennaStore::ComToPcVector.";
503  InvalidRequest ir(ss.str());
504  GNSSTK_THROW(ir);
505  }
506  }
507 
508  try
509  {
510  tp = ComToPcVector(sys, sidr.id, ct, satVector);
511  }
512  catch (Exception exc)
513  {
514  GNSSTK_RETHROW(exc);
515  }
516  return tp;
517  }
518 
519  // dump the store
520  void AntennaStore::dump(ostream& s, short detail)
521  {
522  s << "Dump (" << (detail == 0 ? "low" : (detail == 1 ? "medium" : "high"))
523  << " detail) of AntennaStore (" << antennaMap.size() << ") antennas\n";
524  map<string, AntexData>::iterator it;
525  for (it = antennaMap.begin(); it != antennaMap.end(); it++)
526  {
527  if (detail > 0)
528  {
529  s << endl;
530  }
531  it->second.dump(s, detail);
532  }
533  s << "End of dump of AntennaStore\n";
534  }
535 
536 } // namespace gnsstk
gnsstk::dump
void dump(vector< SatPass > &SatPassList, ostream &os, bool rev, bool dbug)
Definition: SatPassUtilities.cpp:59
gnsstk::SatID::id
int id
Satellite identifier, e.g. PRN.
Definition: SatID.hpp:154
gnsstk::BEGINNING_OF_TIME
const Epoch BEGINNING_OF_TIME(CommonTime::BEGINNING_OF_TIME)
Earliest representable Epoch.
SunEarthSatGeometry.hpp
SolarPosition.hpp
gnsstk::AntexStream
This class reads an Antex files.
Definition: AntexStream.hpp:57
gnsstk::SatID
Definition: SatID.hpp:89
Position.hpp
gnsstk::Triple
Definition: Triple.hpp:68
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
AntennaStore.hpp
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::transpose
SparseMatrix< T > transpose(const SparseMatrix< T > &M)
transpose
Definition: SparseMatrix.hpp:829
gnsstk::satelliteAttitude
Matrix< double > satelliteAttitude(const Position &sat, const Position &sun)
Definition: SunEarthSatGeometry.cpp:266
gnsstk::Matrix< double >
gnsstk::AntexData
Definition: AntexData.hpp:120
gnsstk::AntexData::isValid
bool isValid() const
Convenience function returns true only if a valid object.
Definition: AntexData.hpp:311
example4.satVector
satVector
Definition: example4.py:109
example4.time
time
Definition: example4.py:103
gnsstk::CommonTime
Definition: CommonTime.hpp:84
gnsstk::solarPosition
Position solarPosition(const CommonTime &t, double &AR)
Definition: SolarPosition.cpp:96
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::Vector< double >
gnsstk::SatID::system
SatelliteSystem system
System for this satellite.
Definition: SatID.hpp:156
example3.data
data
Definition: example3.py:22
gnsstk::AntexData::name
std::string name() const
Generate a name from type and serial number.
Definition: AntexData.cpp:150
gnsstk::AntexHeader
Definition: AntexHeader.hpp:60
gnsstk::AntexData::systemChar
char systemChar
Definition: AntexData.hpp:252
std
Definition: Angle.hpp:142
gnsstk::AntexData::getPhaseCenterOffset
Triple getPhaseCenterOffset(const std::string &freq) const
Definition: AntexData.cpp:205
gnsstk::Position
Definition: Position.hpp:136
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
Matrix.hpp
gnsstk::AntexStream::open
virtual void open(const char *fn, std::ios::openmode mode)
overrides open to reset the header
Definition: AntexStream.hpp:77
gnsstk::AntexData::isRxAntenna
bool isRxAntenna
Definition: AntexData.hpp:242


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