00001 #pragma ident "$Id: MOPSWeight.cpp 2479 2010-10-26 08:02:55Z architest $"
00002
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "MOPSWeight.hpp"
00034
00035
00036 using namespace std;
00037
00038 namespace gpstk
00039 {
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 int MOPSWeight::getWeights( DayTime& time,
00064 Vector<SatID>& Satellites,
00065 GPSEphemerisStore& bcEph,
00066 Vector<double>& ionoCorrections,
00067 Vector<double>& elevationVector,
00068 Vector<double>& azimuthVector,
00069 Position rxPosition,
00070 int rxClass )
00071 throw(InvalidWeights)
00072 {
00073
00074 int N( Satellites.size() );
00075 int Ne( elevationVector.size() );
00076 int Na( azimuthVector.size() );
00077
00078
00079 if (N == 0)
00080 {
00081
00082 InvalidWeights eWeight("At least one satellite is needed to \
00083 compute weights.");
00084
00085 GPSTK_THROW(eWeight);
00086
00087 }
00088
00089
00090 if ( (N != Ne) ||
00091 (N != Na) )
00092 {
00093 InvalidWeights eWeight("Size of input vectors do not match.");
00094
00095 GPSTK_THROW(eWeight);
00096
00097 }
00098
00099
00100 SimpleIURAWeight sIura;
00101
00102
00103 int goodSV( sIura.getWeights(time, Satellites, bcEph) );
00104
00105
00106 Compute( goodSV,
00107 sIura,
00108 Satellites,
00109 ionoCorrections,
00110 elevationVector,
00111 azimuthVector,
00112 rxPosition,
00113 rxClass );
00114
00115 return goodSV;
00116
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 int MOPSWeight::getWeights( DayTime& time,
00143 Vector<SatID>& Satellites,
00144 TabularEphemerisStore& preciseEph,
00145 Vector<double>& ionoCorrections,
00146 Vector<double>& elevationVector,
00147 Vector<double>& azimuthVector,
00148 Position rxPosition,
00149 int rxClass )
00150 throw(InvalidWeights)
00151 {
00152
00153 int N( Satellites.size() );
00154 int Ne( elevationVector.size() );
00155 int Na( azimuthVector.size() );
00156
00157
00158 if (N == 0)
00159 {
00160
00161 InvalidWeights eWeight("At least one satellite is needed to \
00162 compute weights.");
00163
00164 GPSTK_THROW(eWeight);
00165
00166 }
00167
00168
00169 if ( (N != Ne) ||
00170 (N != Na) )
00171 {
00172
00173 InvalidWeights eWeight("Size of input vectors do not match.");
00174
00175 GPSTK_THROW(eWeight);
00176
00177 }
00178
00179
00180 SimpleIURAWeight sIura;
00181
00182
00183 int goodSV( sIura.getWeights(time, Satellites, preciseEph) );
00184
00185
00186 Compute( goodSV,
00187 sIura,
00188 Satellites,
00189 ionoCorrections,
00190 elevationVector,
00191 azimuthVector,
00192 rxPosition,
00193 rxClass );
00194
00195 return goodSV;
00196
00197 }
00198
00199
00200
00201
00202 void MOPSWeight::Compute( int goodSV,
00203 SimpleIURAWeight& sIura,
00204 Vector<SatID>& Satellites,
00205 Vector<double>& ionoCorrections,
00206 Vector<double>& elevationVector,
00207 Vector<double>& azimuthVector,
00208 Position rxPosition,
00209 int rxClass )
00210 throw(InvalidWeights)
00211 {
00212
00213 int N( Satellites.size() );
00214
00215 double sigma2rx;
00216
00217 if (rxClass==1)
00218 {
00219 sigma2rx = 0.25;
00220 }
00221 else
00222 {
00223 sigma2rx = 0.36;
00224 }
00225
00226 double sigma2ura, sigma2multipath, sigma2trop, sigma2uire;
00227
00228
00229 weightsVector.resize(goodSV);
00230
00231
00232
00233 MOPSTropModel mopsTrop(0.0, 0.0, 1);
00234
00235 if (N==goodSV)
00236 {
00237
00238 for (int i=0; i<goodSV; i++)
00239 {
00240
00241 sigma2ura = (1.0 / sIura.weightsVector(i));
00242 sigma2multipath = 0.13 + ( 0.53 *
00243 std::exp(-elevationVector(i)/10.0) );
00244
00245
00246 sigma2multipath *= sigma2multipath;
00247 sigma2trop = mopsTrop.MOPSsigma2(elevationVector(i));
00248 sigma2uire = sigma2iono( ionoCorrections(i),
00249 elevationVector(i),
00250 azimuthVector(i),
00251 rxPosition );
00252 weightsVector(i) = 1.0 / ( sigma2rx + sigma2ura + sigma2multipath
00253 + sigma2trop + sigma2uire );
00254
00255 }
00256
00257 }
00258 else
00259 {
00260
00261 int offset(0);
00262
00263 for (int i=0; i<goodSV; i++)
00264 {
00265
00266
00267 while ( (sIura.availableSV(i).id != Satellites(i+offset).id) &&
00268 ((i+offset)<N) )
00269 {
00270 offset++;
00271 }
00272
00273 if ( (i+offset) >= N )
00274 {
00275 break;
00276 }
00277
00278 sigma2ura = (1.0 / sIura.weightsVector(i));
00279 sigma2multipath = 0.13 + ( 0.53 *
00280 std::exp(-elevationVector(i)/10.0) );
00281
00282
00283 sigma2multipath *= sigma2multipath;
00284 sigma2trop = mopsTrop.MOPSsigma2(elevationVector(i+offset));
00285 sigma2uire = sigma2iono( ionoCorrections(i+offset),
00286 elevationVector(i+offset),
00287 azimuthVector(i+offset),
00288 rxPosition );
00289 weightsVector(i) = 1.0 / ( sigma2rx + sigma2ura + sigma2multipath
00290 + sigma2trop + sigma2uire );
00291
00292 }
00293
00294 }
00295
00296
00297 valid = sIura.isValid();
00298
00299 availableSV = sIura.availableSV;
00300 rejectedSV = sIura.rejectedSV;
00301
00302 return;
00303
00304 }
00305
00306
00307
00308
00309
00310 double MOPSWeight::sigma2iono( double& ionoCorrection,
00311 double& elevation,
00312 double& azimuth,
00313 Position rxPosition )
00314 throw(InvalidWeights)
00315 {
00316
00317
00318
00319 double azRad( azimuth * DEG_TO_RAD );
00320 double elevRad( elevation * DEG_TO_RAD );
00321 double cosElev( std::cos(elevRad) );
00322 double svE( elevation / 180.0 );
00323
00324 double phi_u( rxPosition.getGeodeticLatitude() / 180.0 );
00325 double lambda_u( rxPosition.getLongitude() / 180.0 );
00326
00327 double psi( (0.0137 / (svE + 0.11)) - 0.022 );
00328
00329 double phi_i( phi_u + psi * std::cos(azRad) );
00330
00331 if (phi_i > 0.416)
00332 {
00333 phi_i = 0.416;
00334 }
00335
00336 if (phi_i < -0.416)
00337 {
00338 phi_i = -0.416;
00339 }
00340
00341
00342 double lambda_i( lambda_u + (psi*std::sin(azRad) / std::cos(phi_i*PI)) );
00343 double phi_m( phi_i + 0.064 * std::cos((lambda_i - 1.617)*PI) );
00344
00345
00346 phi_m = std::abs(phi_m * 180.0);
00347
00348
00349 double tau_vert;
00350
00351 if ( (phi_m >= 0.0) &&
00352 (phi_m <= 20.0) )
00353 {
00354 tau_vert = 9.0;
00355 }
00356 else
00357 {
00358
00359 if ( (phi_m > 20.0) &&
00360 (phi_m <= 55.0) )
00361 {
00362 tau_vert = 4.5;
00363 }
00364 else
00365 {
00366 tau_vert = 6.0;
00367 }
00368
00369 }
00370
00371
00372
00373 double fpp( 1.0 / (std::sqrt(1.0 - 0.898665418 * cosElev * cosElev)) );
00374
00375 double sigma2uire( (ionoCorrection*ionoCorrection) / 25.0 );
00376
00377 double fact( (fpp*tau_vert) * (fpp*tau_vert) );
00378
00379 if (fact > sigma2uire)
00380 {
00381 sigma2uire = fact;
00382 }
00383
00384 return sigma2uire;
00385
00386 }
00387
00388
00389 }