IonoModel.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 
44 #include <math.h>
45 #include "GNSSconstants.hpp"
46 #include "IonoModel.hpp"
47 #include "YDSTime.hpp"
48 #include "GNSSconstants.hpp"
49 
50 namespace gnsstk
51 {
52  IonoModel::IonoModel(const double a[4], const double b[4],
53  const bool semicircle_units) noexcept
54  {
55  setModel(a, b, semicircle_units);
56  }
57 
58 
59  IonoModel::IonoModel(const EngAlmanac& engalm) noexcept
60  {
61  try
62  {
63  engalm.getIon(alpha, beta);
64  valid = true;
65  }
66  catch(InvalidRequest& e)
67  {
68  valid = false;
69  }
70  }
71 
72 
73  void IonoModel::setModel(const double a[4], const double b[4],
74  const bool semicircle_units) noexcept
75  {
76  for (int n = 0; n < 4; n++)
77  {
78  alpha[n] = a[n];
79  beta[n] = b[n];
80  }
81  // Convert powers of inverse radians to inverse semi-circles, as needed by getCorrection.
82  // This is a necessary optional flag for historical GNSSTk code reasons.
83  if (!semicircle_units)
84  {
85  alpha[1] *= PI;
86  alpha[2] *= PI * PI;
87  alpha[3] *= PI * PI * PI;
88  beta[1] *= PI;
89  beta[2] *= PI * PI;
90  beta[3] *= PI * PI * PI;
91  }
92  valid = true;
93  }
94 
95 
97  const Position& rxgeo,
98  double svel,
99  double svaz,
100  CarrierBand band) const
101  {
102 
103  if (!valid)
104  {
105  InvalidIonoModel e("Alpha and beta parameters invalid.");
106  GNSSTK_THROW(e);
107  }
108 
109  // All angle units are in semi-circles (radians/PI), per IS-GPS-200.
110  // Note: Math functions (cos, sin, etc.) require arguments in radians,
111  // so all semi-circles must be multiplied by PI.
112 
113  double azRad = svaz * DEG_TO_RAD;
114  double svE = svel / 180.0;
115 
116  double phi_u = rxgeo.getGeodeticLatitude() / 180.0;
117  double lambda_u = rxgeo.getLongitude() / 180.0;
118 
119  double psi = (0.0137 / (svE + 0.11)) - 0.022;
120 
121  double phi_i = phi_u + psi * std::cos(azRad);
122  if (phi_i > 0.416)
123  phi_i = 0.416;
124  if (phi_i < -0.416)
125  phi_i = -0.416;
126 
127  double lambda_i = lambda_u + psi * ::sin(azRad) / ::cos(phi_i*PI);
128 
129  double phi_m = phi_i + 0.064 * ::cos((lambda_i - 1.617)*PI);
130 
131  double iAMP = 0.0;
132  double iPER = 0.0;
133  iAMP = alpha[0]+phi_m*(alpha[1]+phi_m*(alpha[2]+phi_m*alpha[3]));
134  iPER = beta[0]+phi_m*( beta[1]+phi_m*( beta[2]+phi_m* beta[3]));
135 
136  if (iAMP < 0.0)
137  iAMP = 0.0;
138  if (iPER < 72000.0)
139  iPER = 72000.0;
140 
141  double t = 43200.0 * lambda_i + YDSTime(time).sod;
142  if (t >= 86400.0)
143  t -= 86400.0;
144  if (t < 0)
145  t += 86400.0;
146 
147  double x = TWO_PI * (t - 50400.0) / iPER; // x is in radians
148 
149  double iF = 1.0 + 16.0 * (0.53 - svE)*(0.53 - svE)*(0.53 - svE);
150 
151  double t_iono = 0.0;
152  if (fabs(x) < 1.57)
153  t_iono = iF * (5.0e-9 + iAMP * (1 + x*x * (-0.5 + x*x/24.0)));
154  else
155  t_iono = iF * 5.0e-9;
156 
157  // Correction factor for GPS band; see ICD-GPS-200 20.3.3.3.3.2.
158  if (band == CarrierBand::L2)
159  {
160  t_iono *= GAMMA_GPS_12; // GAMMA_GPS = (fL1 / fL2)^2
161  }
162  else if (band == CarrierBand::L5)
163  {
164  t_iono *= GAMMA_GPS_15; // GAMMA_GPS = (fL1 / fL5)^2
165  }
166  else if (band != CarrierBand::L1)
167  {
168  throw InvalidIonoModel("Invalid CarrierBand, not one of L1,L2,L5.");
169  }
170 
171  double correction = t_iono * C_MPS; // return correction in [m]
172 
173  return correction;
174  }
175 
176 
177  bool IonoModel::operator==(const IonoModel& right) const noexcept
178  {
179  for (int n = 0; n < 4; n++)
180  {
181  if (alpha[n] != right.alpha[n] || beta[n] != right.beta[n])
182  return false;
183  }
184  return true;
185  }
186 
187 
188  bool IonoModel::operator!=(const IonoModel&right) const noexcept
189  {
190  return !(operator==(right));
191  }
192 
193 
194  bool IonoModel::getModel(double a[4], double b[4]) const noexcept
195  {
196  if (valid)
197  {
198  for (int n = 0; n < 4; n++)
199  {
200  a[n] = alpha[n];
201  b[n] = beta[n];
202  }
203  return true;
204  }
205  return false;
206  }
207 
208 
209  void IonoModel::dump(std::ostream& s) const
210  {
211  s << "a = { " << alpha[0] << " , " << alpha[1] << " , "
212  << alpha[2] << " , " << alpha[3] << " } ";
213  s << "b = { " << beta[0] << " , " << beta[1] << " , "
214  << beta[2] << " , " << beta[3] << " }" << std::endl;
215  }
216 
217 }
YDSTime.hpp
gnsstk::IonoModel::IonoModel
IonoModel() noexcept
Default constructor, creates an invalid model for lack of parameters.
Definition: IonoModel.hpp:80
gnsstk::operator==
bool operator==(const IonexData::IonexValType &x, const IonexData::IonexValType &y)
operator == for IonexData::IonexValType
Definition: IonexData.hpp:253
gnsstk::IonoModel::valid
bool valid
Definition: IonoModel.hpp:159
gnsstk::IonoModel::setModel
void setModel(const double a[4], const double b[4], const bool semicircle_units=true) noexcept
Definition: IonoModel.cpp:73
gnsstk::YDSTime
Definition: YDSTime.hpp:58
gnsstk::CarrierBand
CarrierBand
Definition: CarrierBand.hpp:54
gnsstk::TWO_PI
const double TWO_PI
GPS value of PI*2.
Definition: GNSSconstants.hpp:68
gnsstk::IonoModel::alpha
double alpha[4]
Definition: IonoModel.hpp:156
gnsstk::PI
const double PI
GPS value of PI; also specified by GAL.
Definition: GNSSconstants.hpp:62
gnsstk::IonoModel::beta
double beta[4]
Definition: IonoModel.hpp:157
gnsstk::IonoModel::operator==
bool operator==(const IonoModel &right) const noexcept
Equality operator.
Definition: IonoModel.cpp:177
GNSSconstants.hpp
IonoModel.hpp
gnsstk::GAMMA_GPS_15
const double GAMMA_GPS_15
Definition: GNSSconstants.hpp:103
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::CarrierBand::L2
@ L2
GPS L2, QZSS L2.
std::sin
double sin(gnsstk::Angle x)
Definition: Angle.hpp:144
gnsstk::GAMMA_GPS_12
const double GAMMA_GPS_12
GPS Gamma constants.
Definition: GNSSconstants.hpp:102
gnsstk::IonoModel::operator!=
bool operator!=(const IonoModel &right) const noexcept
Inequality operator.
Definition: IonoModel.cpp:188
gnsstk::EngAlmanac
Definition: EngAlmanac.hpp:71
gnsstk::C_MPS
const double C_MPS
m/s, speed of light; this value defined by GPS but applies to GAL and GLO.
Definition: GNSSconstants.hpp:74
gnsstk::IonoModel::getCorrection
double getCorrection(const CommonTime &time, const Position &rxgeo, double svel, double svaz, CarrierBand band=CarrierBand::L1) const
Definition: IonoModel.cpp:96
example4.time
time
Definition: example4.py:103
gnsstk::IonoModel::dump
virtual void dump(std::ostream &s=std::cout) const
Definition: IonoModel.cpp:209
gnsstk::Position::getGeodeticLatitude
double getGeodeticLatitude() const noexcept
return geodetic latitude (deg N)
Definition: Position.hpp:454
gnsstk::CommonTime
Definition: CommonTime.hpp:84
example6.valid
valid
Definition: example6.py:20
gnsstk::CarrierBand::L1
@ L1
GPS L1, Galileo E1, SBAS L1, QZSS L1, BeiDou L1.
std::cos
double cos(gnsstk::Angle x)
Definition: Angle.hpp:146
gnsstk::beta
double beta(double x, double y)
Definition: SpecialFuncs.cpp:204
gnsstk::YDSTime::sod
double sod
Definition: YDSTime.hpp:186
gnsstk::IonoModel
Definition: IonoModel.hpp:70
gnsstk::Position::getLongitude
double getLongitude() const noexcept
return longitude (deg E) (either geocentric or geodetic)
Definition: Position.hpp:464
gnsstk::Position
Definition: Position.hpp:136
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::IonoModel::getModel
bool getModel(double a[4], double b[4]) const noexcept
Definition: IonoModel.cpp:194
gnsstk::CarrierBand::L5
@ L5
GPS L5, Galileo E5a, SBAS L5, QZSS L5, BeiDou B2a, NavIC L5.
gnsstk::DEG_TO_RAD
static const double DEG_TO_RAD
Conversion Factor from degrees to radians (units: degrees^-1)
Definition: GNSSconstants.hpp:76


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