ionosphere.c

Go to the documentation of this file.
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