00001 /** 00002 \file ionosphere.c 00003 \brief GNSS core 'c' function library: GPS ionospheric calculations. 00004 \author Glenn D. MacGougan (GDM) 00005 \date 2007-11-29 00006 \since 2005-08-14 00007 00008 \remarks 00009 - Get better klobuchar (alpha and beta parameters from: 00010 http://www.aiub.unibe.ch/ionosphere/ \n 00011 ftp://ftp.unibe.ch/aiub/CODE/ \n 00012 http://www.aiub.unibe.ch/download/CODE/ \n 00013 e.g. Download CGIM3280.07N from ftp://ftp.unibe.ch/aiub/CODE/2007/ 00014 for 2007-11-29. 00015 00016 \b "LICENSE INFORMATION" \n 00017 Copyright (c) 2007, refer to 'author' doxygen tags \n 00018 All rights reserved. \n 00019 00020 Redistribution and use in source and binary forms, with or without 00021 modification, are permitted provided the following conditions are met: \n 00022 00023 - Redistributions of source code must retain the above copyright 00024 notice, this list of conditions and the following disclaimer. \n 00025 - Redistributions in binary form must reproduce the above copyright 00026 notice, this list of conditions and the following disclaimer in the 00027 documentation and/or other materials provided with the distribution. \n 00028 - The name(s) of the contributor(s) may not be used to endorse or promote 00029 products derived from this software without specific prior written 00030 permission. \n 00031 00032 THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 00033 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00034 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00035 DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 00036 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00037 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00038 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00039 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00040 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00041 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00042 SUCH DAMAGE. 00043 */ 00044 00045 #include <math.h> 00046 #include "ionosphere.h" 00047 #include "constants.h" 00048 00049 #define TWO_TO_THE_POWER_OF_M30 (0.000000000931322574615478515625) 00050 #define TWO_TO_THE_POWER_OF_M27 (0.000000007450580596923828125) 00051 #define TWO_TO_THE_POWER_OF_M24 (0.000000059604644775390625) 00052 #define TWO_TO_THE_POWER_OF_11 (2048) 00053 #define TWO_TO_THE_POWER_OF_14 (16384) 00054 #define TWO_TO_THE_POWER_OF_16 (65536) 00055 00056 00057 BOOL IONOSPHERE_GetL1KlobucharCorrection( 00058 const double alpha0, //!< coefficients of a cubic equation representing the amplitude of the vertical delay [s] 00059 const double alpha1, //!< coefficients of a cubic equation representing the amplitude of the vertical delay [s/semi-circle] 00060 const double alpha2, //!< coefficients of a cubic equation representing the amplitude of the vertical delay [s/semi-circle^2] 00061 const double alpha3, //!< coefficients of a cubic equation representing the amplitude of the vertical delay [s/semi-circle^3] 00062 const double beta0, //!< coefficients of a cubic equation representing the period of the model [s] 00063 const double beta1, //!< coefficients of a cubic equation representing the period of the model [s/semi-circle] 00064 const double beta2, //!< coefficients of a cubic equation representing the period of the model [s/semi-circle^2] 00065 const double beta3, //!< coefficients of a cubic equation representing the period of the model [s/semi-circle^3] 00066 const double latitude, //!< user geodetic latitude [rad] 00067 const double longitude, //!< user geodetic longitude [rad] 00068 const double elevation, //!< elevation angle between the user and the satellite [rad] 00069 const double azimuth, //!< azimuth angle between the user and the satellite, measured clockwise positive from the true North [rad] 00070 const double gpstow, //!< receiver computed gps time of week [s] 00071 double* ionospheric_delay //!< computed ionospheric correction [m] 00072 ) 00073 { 00074 double E; // elevation angle between the user and the satellite [semi-circles] 00075 double x; // phase [rad] 00076 double F; // obliquity factor [] 00077 double t; // local time [s] 00078 double AMP; // amplitude of the vertical delay [s] 00079 double PER; // period of the model [s] 00080 double lat; // user latitude [semi-circles] 00081 double lon; // user longitude [semi-circles] 00082 double phi_m; // geomagnetic latitude of the earth projection of the ionospheric intersection point (mean ionospheric height assumed 350 km)[semi-circles] 00083 double lon_i; // geodetic longitude of the earth projection of the ionospheric intersection point [semi-circles] 00084 double lat_i; // geodetic latitude of the earth projection of the ionospheric intersection point [semi-circles] 00085 double central_angle; // earth's central angle between the user position and the earth projection of the ionospheric intersection point [semi-circles] 00086 00087 // Check the input parameters. 00088 // Refer to page 116 of the GPS Interface Control Document. Tabble 20-X Ionospheric Parameters. 00089 if( fabs(alpha0) > 128 * pow(2.0, -30.0) ) return FALSE; 00090 if( fabs(alpha1) > 128 * pow(2.0, -27.0) ) return FALSE; 00091 if( fabs(alpha2) > 128 * pow(2.0, -24.0) ) return FALSE; 00092 if( fabs(alpha3) > 128 * pow(2.0, -24.0) ) return FALSE; 00093 if( fabs(beta0) > 128 * pow(2.0, 11.0) ) return FALSE; 00094 if( fabs(beta1) > 128 * pow(2.0, 14.0) ) return FALSE; 00095 if( fabs(beta2) > 128 * pow(2.0, 16.0) ) return FALSE; 00096 if( fabs(beta3) > 128 * pow(2.0, 16.0) ) return FALSE; 00097 if( latitude > PI/2 || latitude < -PI/2 ) 00098 return FALSE; 00099 if( gpstow < 0.0 ) 00100 return FALSE; 00101 00102 // convert to semi-circles 00103 lat = latitude / PI; 00104 lon = longitude / PI; 00105 E = elevation / PI; 00106 00107 // compute the central angle 00108 central_angle = 0.0137 / (E + 0.11) - 0.022; 00109 00110 // lat of the intersection point 00111 lat_i = lat + central_angle * cos( azimuth ); 00112 if( lat_i > 0.416 ) 00113 lat_i = 0.416; 00114 else if( lat_i < -0.416 ) 00115 lat_i = -0.416; 00116 00117 // lon of the intersection point 00118 lon_i = lon + central_angle * sin( azimuth ) / cos( lat_i*PI ); 00119 00120 // local time [s], bounded (0-86400) 00121 t = 4.32e4 * lon_i + gpstow; 00122 while( !(t >= 0.0 && t <= 86400.0) ) 00123 { 00124 if( t < 0.0 ) 00125 t += 86400.0; 00126 else 00127 t -= 86400.0; 00128 } 00129 00130 // geomagnetic latitude 00131 phi_m = lat_i + 0.064 * cos( (lon_i-1.617)*PI ); 00132 00133 // obliquity factor 00134 F = 1.0 + 16.0 * (0.53 - E)*(0.53 - E)*(0.53 - E); 00135 00136 // period of the model 00137 PER = beta0 + beta1*phi_m + beta2*phi_m*phi_m + beta3*phi_m*phi_m*phi_m; 00138 if( PER < 72000.0 ) 00139 PER = 72000.0; 00140 00141 // amplitude of the vertical delay 00142 AMP = alpha0 + alpha1*phi_m + alpha2*phi_m*phi_m + alpha3*phi_m*phi_m*phi_m; 00143 if( AMP < 0.0 ) 00144 AMP = 0.0; 00145 00146 // phase 00147 x = TWOPI * ( t - 50400.0 ) / PER; 00148 00149 // compute the ionospheric delay [s] 00150 if( x >= 1.57 || x <= -1.57 ) 00151 { 00152 *ionospheric_delay = F * 5.0e-09; 00153 } 00154 else 00155 { 00156 *ionospheric_delay = F * (5.0e-09 + AMP * ( 1.0 - x*x/2.0 + x*x*x*x/24.0 )); 00157 } 00158 00159 // convert to [m] 00160 *ionospheric_delay *= LIGHTSPEED; 00161 00162 return TRUE; 00163 } 00164