troposphere.c

Go to the documentation of this file.
00001 /**
00002 \file    troposphere.c
00003 \brief   GNSS core 'c' function library: GPS tropospheric calculations
00004 \author  Glenn D. MacGougan (GDM)
00005 \date    2007-11-29
00006 \since   2005-08-22
00007 
00008 \b REFERENCES \n
00009 - RTCA, 2001. MINIMUM OPERATIONAL PERFORMANCE STANDARDS FOR GLOBAL POSITIONING SYSTEM/WIDE AREA 
00010   AUGMENTATION SYSTEM AIRBORNE EQUIPMENT. RTCA/DO-229C. Prepared by SC-159. November 28, 2001. 
00011   Supersedes DO-229B. Available at http://www.rtca.org/doclist.asp . pp. 338-340 of 586 in PDF. \n
00012 - Guo, J. and R. B. Langely 2003. A New Tropospheric Propagation Delay Mapping Function for 
00013   Elevation Angles Down to 2 degrees. ION GPS 2003, 9-12 Sept. 2003, Portland OR. \n
00014 - Parkinson, B. and J. J. Spilker (1996). Global Positioning System: Theory And
00015   Applications Volume 1. American Institute of Aeronautics and Astronautics, Inc.,
00016   Washinton D.C. \n
00017 
00018 \b "LICENSE INFORMATION" \n
00019 Copyright (c) 2007, refer to 'author' doxygen tags \n
00020 All rights reserved. \n
00021 
00022 Redistribution and use in source and binary forms, with or without
00023 modification, are permitted provided the following conditions are met: \n
00024 
00025 - Redistributions of source code must retain the above copyright
00026   notice, this list of conditions and the following disclaimer. \n
00027 - Redistributions in binary form must reproduce the above copyright
00028   notice, this list of conditions and the following disclaimer in the
00029   documentation and/or other materials provided with the distribution. \n
00030 - The name(s) of the contributor(s) may not be used to endorse or promote 
00031   products derived from this software without specific prior written 
00032   permission. \n
00033 
00034 THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 
00035 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
00036 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00037 DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00038 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00039 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00040 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00041 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00042 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00043 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00044 SUCH DAMAGE.
00045 */
00046 
00047 #include <math.h>
00048 #include "troposphere.h"
00049 #include "constants.h"
00050 
00051 /*
00052 Local Preprocessor Constants
00053 */
00054 
00055 // Constants used in Equation [A-6] and [A-7], p. 339
00056 #define TROPOSPHERE_K1      (77.604)  // K/mbar
00057 #define TROPOSPHERE_K2    (382000.0)  // K^2/mbar
00058 #define TROPOSPHERE_RD     (287.054)  // J/kg/K
00059 #define TROPOSPHERE_GM       (9.784)  // m/s^2
00060 
00061 // Constant used in Equation [A-8] and [A-9], p. 340
00062 #define TROPOSPHERE_G      (9.80665)  // m/s^2
00063 
00064 // Average Standard Meteorological parameters from Table A-2, p. 339
00065 #define TROPOSPHERE_AVERAGE_PRESSURE                {1013.25, 1017.25, 1015.75, 1011.75, 1013.00}  // mbar
00066 #define TROPOSPHERE_AVERAGE_TEMPERATURE             { 299.65,  294.15,  283.15,  272.15,  263.65}  // K
00067 #define TROPOSPHERE_AVERAGE_WATER_VAPOR_PRESSURE    {  26.31,   21.79,   11.66,    6.78,    4.11}  // mbar
00068 #define TROPOSPHERE_AVERAGE_TEMPERATURE_LAPSE_RATE  {6.30e-3, 6.05e-3, 5.58e-3, 5.39e-3, 4.53e-3}  // K/m
00069 #define TROPOSPHERE_AVERAGE_WATER_VAPOR_LAPSE_RATE  {   2.77,    3.15,    2.57,    1.81,    1.55}  // dimensionless
00070 
00071 // Seasonal Variation value from Table A-2, p. 339
00072 #define TROPOSPHERE_SEASONAL_VARIATION_PRESSURE               {0.0,   -3.75,   -2.25,   -1.75,   -0.50}  // mbar
00073 #define TROPOSPHERE_SEASONAL_VARIATION_TEMPERATURE            {0.0,    7.00,   11.00,   15.00,   14.50}  // K
00074 #define TROPOSPHERE_SEASONAL_VARIATION_WATER_VAPOR_PRESSURE   {0.0,    8.85,    7.24,    5.36,    3.39}  // mbar
00075 #define TROPOSPHERE_SEASONAL_VARIATION_TEMPERATURE_LAPSE_RATE {0.0, 0.25e-3, 0.32e-3, 0.81e-3, 0.62e-3}  // K/m
00076 #define TROPOSPHERE_SEASONAL_VARIATION_WATER_VAPOR_LAPSE_RATE {0.0,    0.33,    0.46,    0.74,    0.30}  // dimensionless
00077 
00078 
00079 // local constant global variables
00080 static const double  P_Table[5] = TROPOSPHERE_AVERAGE_PRESSURE;
00081 static const double dP_Table[5] = TROPOSPHERE_SEASONAL_VARIATION_PRESSURE;
00082 static const double  T_Table[5] = TROPOSPHERE_AVERAGE_TEMPERATURE;
00083 static const double dT_Table[5] = TROPOSPHERE_SEASONAL_VARIATION_TEMPERATURE;
00084 static const double  E_Table[5] = TROPOSPHERE_AVERAGE_WATER_VAPOR_PRESSURE;
00085 static const double dE_Table[5] = TROPOSPHERE_SEASONAL_VARIATION_WATER_VAPOR_PRESSURE;
00086 static const double  B_Table[5] = TROPOSPHERE_AVERAGE_TEMPERATURE_LAPSE_RATE;
00087 static const double dB_Table[5] = TROPOSPHERE_SEASONAL_VARIATION_TEMPERATURE_LAPSE_RATE;
00088 static const double  L_Table[5] = TROPOSPHERE_AVERAGE_WATER_VAPOR_LAPSE_RATE;
00089 static const double dL_Table[5] = TROPOSPHERE_SEASONAL_VARIATION_WATER_VAPOR_LAPSE_RATE;
00090 
00091 
00092 /*
00093 DESRIPTION
00094 Performs linear interpolation given (x1,y1), (x2,y2), and x, returns y
00095 */
00096 static void _TROPOSPHERE_Interpolate( 
00097  const double x1,
00098  const double y1,
00099  const double x2,
00100  const double y2,
00101  const double x,
00102  double* y );
00103 
00104 
00105 
00106 
00107 void TROPOSPHERE_GetDayAndWetMappingValues_UsingThe_UNBabc_MappingFunction( 
00108   const double elevation,  // satellite elevation angle (must be >= 2 deg)  [rad]
00109   const double latitude,   // user latitude                                 [rad]
00110   const double height,     // user height (orthometric, ie above sea level) [m]
00111   double* drymap,          // dry delay scale factor                        []
00112   double* wetmap )         // wet delay scale factor                        []
00113 {
00114   double a,    // mapping value parameter (see Eqn 2, [2])
00115          b,    // mapping value parameter (see Eqn 2, [2])
00116          c,    // mapping value parameter (see Eqn 2, [2])
00117          num,  // numerator
00118          dem,  // denominator
00119          sine; // sin(elevation)
00120 
00121   if( elevation > HALFPI )
00122     sine = 1.0; // user error, sine(HALFPI)
00123   else if( elevation < 2.0*DEG2RAD )
00124     sine = sin(2.0*DEG2RAD); // this mapping function is only good to 2 degrees
00125   else
00126     sine = sin(elevation);
00127   
00128   // dry
00129   a = (1.18972 - 0.026855*height/1000.0 + 0.10664*cos(latitude)) / 1000.0;
00130   b = 0.0035716;
00131   c = 0.082456;
00132   
00133   num = 1.0 + ( a / ( 1.0 + ( b / ( 1.0 + c ) ) ) );
00134   dem = sine + ( a / ( sine + ( b / ( sine + c ) ) ) );
00135   
00136   *drymap = num/dem;  
00137   
00138   // wet
00139   a = (0.61120 - 0.035348*height/1000.0 - 0.01526*cos(latitude)) / 1000.0;
00140   b = 0.0018576;
00141   c = 0.062741;
00142   
00143   num = 1.0 + ( a / ( 1.0 + ( b / ( 1.0 + c ) ) ) );
00144   dem = sine + ( a / ( sine + ( b / ( sine + c ) ) ) );
00145   
00146   *wetmap = num/dem;  
00147 }
00148 
00149 
00150 void TROPOSPHERE_DetermineZenithDelayValues_WAAS_Model(
00151   const double latitude,          //!< user latitude        [rad]
00152   const double height,            //!< user height          [m]
00153   const unsigned short dayofyear, //!< day of year (1-366)  [days]    
00154   double* zenith_dry_delay,       //!< dry zenith delay     [m]
00155   double* zenith_wet_delay        //!< wet zenith delay     [m]
00156   )
00157 {
00158   // interpolated meteorological values
00159   double P; // pressure,               [mbar]
00160   double T; // temperature,            [K]
00161   double E; // wator vapor pressure,   [mbar]
00162   double B; // temperature lapse rate, [K/m]
00163   double L; // water vapor lapse rate, []
00164 
00165   double Dmin;    //day of year min constant   
00166   double d;       // temporary double
00167   double abs_lat; // absolute latitude [deg]
00168   double common;  // a common factor
00169   double base;
00170   double power;
00171   int i;
00172 
00173   abs_lat = fabs(latitude)*RAD2DEG;
00174 
00175   // determine day of year min constant   
00176   if( latitude < 0 )
00177     Dmin = 211.0; // Southern hemisphere
00178   else
00179     Dmin = 28.0;  // Northern hemisphere
00180   
00181   // common part of Equation [A-3]
00182   common = cos( (TWOPI * (dayofyear - Dmin)) / 365.25 );
00183 
00184   if( abs_lat <= 15.0 )
00185   {
00186     P = P_Table[0] - dP_Table[0] * common;
00187     T = T_Table[0] - dT_Table[0] * common;
00188     E = E_Table[0] - dE_Table[0] * common;
00189     B = B_Table[0] - dB_Table[0] * common;
00190     L = L_Table[0] - dL_Table[0] * common;
00191   }
00192   else if( abs_lat > 15.0 && abs_lat < 75.0 )
00193   {
00194     i = ((int)abs_lat) / 15;
00195 
00196     _TROPOSPHERE_Interpolate( i*15.0,  P_Table[i-1], (i+1)*15.0,  P_Table[i], abs_lat, &P );
00197     _TROPOSPHERE_Interpolate( i*15.0, dP_Table[i-1], (i+1)*15.0, dP_Table[i], abs_lat, &d );    
00198     P = P - d * common;
00199 
00200     _TROPOSPHERE_Interpolate( i*15.0,  T_Table[i-1], (i+1)*15.0,  T_Table[i], abs_lat, &T );
00201     _TROPOSPHERE_Interpolate( i*15.0, dT_Table[i-1], (i+1)*15.0, dT_Table[i], abs_lat, &d );    
00202     T = T - d * common;
00203 
00204     _TROPOSPHERE_Interpolate( i*15.0,  E_Table[i-1], (i+1)*15.0,  E_Table[i], abs_lat, &E );
00205     _TROPOSPHERE_Interpolate( i*15.0, dE_Table[i-1], (i+1)*15.0, dE_Table[i], abs_lat, &d );    
00206     E = E - d * common;
00207 
00208     _TROPOSPHERE_Interpolate( i*15.0,  B_Table[i-1], (i+1)*15.0,  B_Table[i], abs_lat, &B );
00209     _TROPOSPHERE_Interpolate( i*15.0, dB_Table[i-1], (i+1)*15.0, dB_Table[i], abs_lat, &d );    
00210     B = B - d * common;
00211 
00212     _TROPOSPHERE_Interpolate( i*15.0,  L_Table[i-1], (i+1)*15.0,  L_Table[i], abs_lat, &L );
00213     _TROPOSPHERE_Interpolate( i*15.0, dL_Table[i-1], (i+1)*15.0, dL_Table[i], abs_lat, &d );    
00214     L = L - d * common;    
00215   }
00216   else // abs_lat >= 75.0
00217   {
00218     P = P_Table[4] - dP_Table[4] * common;
00219     T = T_Table[4] - dT_Table[4] * common;
00220     E = E_Table[4] - dE_Table[4] * common;
00221     B = B_Table[4] - dB_Table[4] * common;
00222     L = L_Table[4] - dL_Table[4] * common;
00223   }
00224 
00225   // zero altitude zenith dry delay, Equation [A-6]
00226   *zenith_dry_delay = (1.0e-6 * TROPOSPHERE_K1 * TROPOSPHERE_RD * P) / TROPOSPHERE_GM;
00227 
00228   // zero altitude zenith wet delay, Equation [A-7]
00229   *zenith_wet_delay = (((1.0e-6 * TROPOSPHERE_K2 * TROPOSPHERE_RD) / (TROPOSPHERE_GM * (L + 1.0) - B * TROPOSPHERE_RD)) * (E / T));
00230 
00231   // for Equations [A-8] and [A-9]
00232   base  = 1.0 - ((B * height) / T);
00233 
00234   // zenith dry delay with height compensation, Equation [A-8]  
00235   power = (TROPOSPHERE_G / (TROPOSPHERE_RD * B));
00236   *zenith_dry_delay = pow(base, power) * (*zenith_dry_delay);
00237 
00238   // zenith wet delay with height compensation, Equation [A-9]
00239   power = (((L + 1.0) * TROPOSPHERE_G) / (TROPOSPHERE_RD * B)) - 1.0;
00240   *zenith_wet_delay = pow(base, power) * (*zenith_wet_delay);
00241 }
00242 
00243 
00244 
00245 void TROPOSPHERE_GetDryAndWetDelay_UsingThe_UNBabc_MappingFunction(  
00246   const double zenith_dry_delay,  //!< dry zenith delay                              [m]
00247   const double zenith_wet_delay,  //!< wet zenith delay                              [m]
00248   const double elevation,         //!< satellite elevation angle (must be >= 2 deg)  [rad]
00249   const double latitude,          //!< user latitude                                 [rad]
00250   const double height,            //!< user height (orthometric, ie above sea level) [m]  
00251   double*      drydelay,          //!< dry delay mapped to this elevation angle      [m]
00252   double*      wetdelay           //!< wet delay mapped to this elevation angle      [m]
00253   )
00254 {
00255   double drymap;
00256   double wetmap;
00257 
00258   TROPOSPHERE_GetDayAndWetMappingValues_UsingThe_UNBabc_MappingFunction(
00259     elevation,
00260     latitude,
00261     height,
00262     &drymap,
00263     &wetmap );
00264 
00265   *drydelay = zenith_dry_delay*drymap;
00266   *wetdelay = zenith_wet_delay*wetmap;
00267 } 
00268 
00269 
00270 
00271 
00272 /*
00273 DESRIPTION
00274 Performs linear interpolation given (x1,y1), (x2,y2), and x, returns y
00275 */
00276 static void _TROPOSPHERE_Interpolate( 
00277  const double x1,
00278  const double y1,
00279  const double x2,
00280  const double y2,
00281  const double x,
00282  double* y )
00283 {
00284   double dx;
00285   dx = x2 - x1;
00286 
00287   // check divide by zero
00288   if( dx < 1e-25 && dx > -1e-25 )
00289     *y = y1;
00290     
00291   *y = y1 + (x - x1)/dx * (y2 - y1);
00292 }
00293 
00294 
00295 
00296