test_ionosphere.c

Go to the documentation of this file.
00001 /** 
00002 \file    test_ionosphere.c
00003 \brief   unit tests for ionosphere.c/.h
00004 \author  Glenn D. MacGougan (GDM)
00005 \date    2007-11-29
00006 \since   2007-11-29
00007 
00008 \b "LICENSE INFORMATION" \n
00009 Copyright (c) 2007, refer to 'author' doxygen tags \n
00010 All rights reserved. \n
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided the following conditions are met: \n
00014 
00015 - Redistributions of source code must retain the above copyright
00016   notice, this list of conditions and the following disclaimer. \n
00017 - Redistributions in binary form must reproduce the above copyright
00018   notice, this list of conditions and the following disclaimer in the
00019   documentation and/or other materials provided with the distribution. \n
00020 - The name(s) of the contributor(s) may not be used to endorse or promote 
00021   products derived from this software without specific prior written 
00022   permission. \n
00023 
00024 THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 
00025 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
00026 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00027 DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
00028 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00029 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
00030 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00031 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00032 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00033 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
00034 SUCH DAMAGE.
00035 */
00036 #include <stdio.h>
00037 #include "Basic.h"     // CUnit/Basic.h
00038 #include "ionosphere.h"
00039 #include "constants.h"
00040 
00041 
00042 
00043 /*
00044 The following function was extracted and modified from: IonoModel.cpp of the 
00045 The GPSTK Project, LGPL license, http://www.gpstk.org
00046 for test purposes only.
00047 
00048 Under the terms of the LGPL license, It is allowed to modify
00049 and redistribut this code. However, the code for this function is not re-released 
00050 with BSD license. It continues to be covered by th LGPL.
00051 
00052 Modified code produced by Glenn D. MacGougan, 2007-11-29.
00053 */
00054 static double test_IONOSPHERE_getCorrectionL1_gpstk_3rdParty(
00055   double gpstow,
00056   double alpha[4],
00057   double beta[4],
00058   const double  latitude,   //!< user geodetic latitude  [rad]
00059   const double  longitude,  //!< user geodetic longitude [rad]
00060   const double  svel,       //!< elevation angle between the user and the satellite [rad]
00061   const double  svaz        //!< azimuth angle between the user and the satellite, measured clockwise positive from the true North [rad]   
00062   );
00063 
00064 
00065 int init_suite_IONOSPHERE(void)
00066 {
00067   return 0;
00068 }
00069 
00070 int clean_suite_IONOSPHERE(void)
00071 {
00072   return 0;
00073 }
00074 
00075 
00076 void test_IONOSPHERE_GetL1KlobucharCorrection(void)
00077 {
00078   // We'll use CODE post-mission produced Klobuchar parameters:
00079   /*
00080      2              NAVIGATION DATA     GPS                 RINEX VERSION / TYPE
00081 INXFIT V4.3         AIUB                29-NOV-07 13:58     PGM / RUN BY / DATE 
00082 CODE'S GLOBAL IONOSPHERE MAPS FOR DAY 328, 2007             COMMENT             
00083 Contact address: stefan.schaer or igsauto @aiub.unibe.ch    COMMENT             
00084 Web site:        http://www.aiub.unibe.ch/ionosphere/       COMMENT             
00085 Data archive:    ftp://ftp.unibe.ch/aiub/CODE/              COMMENT             
00086                  http://www.aiub.unibe.ch/download/CODE/    COMMENT             
00087     1.0836D-08 -6.6222D-09 -3.4546D-07 -5.5205D-07          ION ALPHA           
00088     1.0706D+05 -1.1893D+05 -9.7785D+05 -1.3581D+06          ION BETA            
00089                                                             END OF HEADER     
00090   */
00091 
00092   double alpha[4];
00093   double beta[4];
00094 
00095   double latitude;
00096   double longitude;
00097   double azimuth;
00098   double elevation;
00099   double gpstow;
00100   double az;
00101   double el;
00102   BOOL result;
00103   double ionospheric_delay;
00104   double ionospheric_delay_test;
00105 
00106   alpha[0] = 1.0836e-08;
00107   alpha[1] = -6.6222e-09;
00108   alpha[2] = -3.4546e-07;
00109   alpha[3] = -5.5205e-07;
00110 
00111   beta[0] = 1.0706e+05;
00112   beta[1] = -1.1893e+05;
00113   beta[2] = -9.7785e+05;
00114   beta[3] = -1.3581e+06;
00115 
00116   // for Calgary
00117   latitude = 51*DEG2RAD;
00118   longitude = -114*DEG2RAD;
00119   
00120   for( az = 0; az < 360; az+= 15 )
00121   {
00122     azimuth = az*DEG2RAD;
00123     for( el = 0; el <= 90; el += 15 )
00124     {
00125       elevation = el*DEG2RAD;
00126       for( gpstow = 345600; gpstow < 5*86400.0; gpstow += 3600.0 )
00127       {
00128         result = IONOSPHERE_GetL1KlobucharCorrection(   
00129           alpha[0],
00130           alpha[1],
00131           alpha[2],
00132           alpha[3],
00133           beta[0],
00134           beta[1],
00135           beta[2],
00136           beta[3],
00137           latitude,  
00138           longitude, 
00139           elevation, 
00140           azimuth,   
00141           gpstow,    
00142           &ionospheric_delay 
00143           );
00144         CU_ASSERT_FATAL( result );
00145 
00146         ionospheric_delay_test = test_IONOSPHERE_getCorrectionL1_gpstk_3rdParty(
00147           gpstow,
00148           alpha,
00149           beta,
00150           latitude,
00151           longitude,  
00152           elevation,
00153           azimuth        
00154           );
00155         CU_ASSERT_DOUBLE_EQUAL( ionospheric_delay, ionospheric_delay_test, 1e-04 );          
00156         //printf( "%4d %4d %6d %20.10g\n", (int)az, (int)el, (int)gpstow, ionospheric_delay-ionospheric_delay_test );
00157       }
00158     }
00159   }
00160 }
00161 
00162 
00163 
00164 
00165 
00166 
00167 /*
00168 The following function was extracted and modified from: IonoModel.cpp of the 
00169 The GPSTK Project, LGPL license, http://www.gpstk.org
00170 for test purposes only.
00171 
00172 Under the terms of the LGPL license, It is allowed to modify
00173 and redistribut this code. However, the code for this function is not re-released 
00174 with BSD license. It continues to be covered by th LGPL.
00175 
00176 Modified code produced by Glenn D. MacGougan, 2007-11-29.
00177 */
00178 double test_IONOSPHERE_getCorrectionL1_gpstk_3rdParty(
00179   double gpstow,
00180   double alpha[4],
00181   double beta[4],
00182   const double  latitude,   //!< user geodetic latitude  [rad]
00183   const double  longitude,  //!< user geodetic longitude [rad]
00184   const double  svel,       //!< elevation angle between the user and the satellite [rad]
00185   const double  svaz        //!< azimuth angle between the user and the satellite, measured clockwise positive from the true North [rad]   
00186   )
00187 {
00188   // all angle units are in semi-circles (radians / TWO_PI)
00189   // Note: math functions (cos, sin, etc.) require arguments in
00190   // radians so all semi-circles must be multiplied by TWO_PI
00191 
00192   double azRad;
00193   double svE; 
00194   double phi_u;
00195   double lambda_u;
00196   double psi;
00197   double phi_i;
00198   double lambda_i;
00199   double phi_m;
00200   double iAMP;
00201   double iPER;
00202   double t;
00203   double x;
00204   double iF;
00205   double t_iono;
00206   double correction;
00207 
00208   azRad = svaz;
00209   svE = svel / PI; // semi-circles
00210 
00211   phi_u = latitude / PI; // semi-circles
00212   lambda_u = longitude / PI; // semi-circles
00213 
00214   psi = (0.0137 / (svE + 0.11)) - 0.022;
00215 
00216   phi_i = phi_u + psi * cos(azRad);
00217   if (phi_i > 0.416)
00218     phi_i = 0.416;
00219   if (phi_i < -0.416)
00220     phi_i = -0.416;
00221 
00222   lambda_i = lambda_u + psi * sin(azRad) / cos(phi_i*PI);
00223 
00224   phi_m = phi_i + 0.064 * cos((lambda_i - 1.617)*PI);
00225 
00226   iAMP = 0.0;
00227   iPER = 0.0;
00228 
00229   iPER = beta[0] + beta[1]*phi_m + beta[2]*phi_m*phi_m + beta[3]*phi_m*phi_m*phi_m;
00230   
00231   // amplitude of the vertical delay
00232   iAMP = alpha[0] + alpha[1]*phi_m + alpha[2]*phi_m*phi_m + alpha[3]*phi_m*phi_m*phi_m;
00233   
00234   iAMP = alpha[0]+phi_m*(alpha[1]+phi_m*(alpha[2]+phi_m*alpha[3]));
00235   iPER =  beta[0]+phi_m*( beta[1]+phi_m*( beta[2]+phi_m* beta[3]));
00236 
00237   if (iAMP < 0.0)
00238     iAMP = 0.0;
00239   if (iPER < 72000.0)
00240     iPER = 72000.0;
00241 
00242   t = 43200.0 * lambda_i + gpstow;  
00243   if (t >= 86400.0)
00244     t -= 86400.0;
00245   if (t < 0)
00246     t += 86400.0;
00247 
00248   x = TWOPI * (t - 50400.0) / iPER; // x is in radians
00249 
00250   iF = 1.0 + 16.0 * (0.53 - svE)*(0.53 - svE)*(0.53 - svE);
00251 
00252   t_iono = 0.0;
00253   if (fabs(x) < 1.57)
00254     t_iono = iF * (5.0e-9 + iAMP * (1 + x*x * (-0.5 + x*x/24.0)));
00255   else
00256     t_iono = iF * 5.0e-9;
00257 
00258   /*
00259   if( freq == L2 )
00260   {
00261     // see ICD-GPS-200 20.3.3.3.3.2
00262     t_iono *= GAMMA_GPS;  //  GAMMA_GPS = (fL1 / fL2)^2
00263   }
00264   */
00265 
00266   correction = t_iono * LIGHTSPEED;
00267 
00268   return correction;
00269 }
00270