Antenna.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: Antenna.cpp 1769 2009-03-04 08:03:19Z architest $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025 //
00026 //  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2009
00027 //
00028 //============================================================================
00029 
00030 
00031 #include "Antenna.hpp"
00032 
00033 
00034 
00035 namespace gpstk
00036 {
00037 
00038 
00039       /* Common constructor.
00040        *
00041        * @param[in] eccL1     Eccentricity Triple (meters) for GPS L1 freq.
00042        * @param[in] eccL2     Eccentricity Triple (meters) for GPS L2 freq.
00043        */
00044    Antenna::Antenna( const Triple& eccL1,
00045                      const Triple& eccL2 )
00046    {
00047          // Add eccentricities
00048       addAntennaEcc(G01, eccL1);
00049       addAntennaEcc(G02, eccL2);
00050 
00051    }  // End of constructor 'Antenna::Antenna()'
00052 
00053 
00054 
00055       /* Common constructor.
00056        *
00057        * @param[in] NorthEccL1   North eccentricity (meters) for GPS L1 freq
00058        * @param[in] EastEccL1    East eccentricity (meters) for GPS L1 freq
00059        * @param[in] UpEccL1      Up eccentricity (meters) for GPS L1 freq
00060        * @param[in] NorthEccL2   North eccentricity (meters) for GPS L2 freq
00061        * @param[in] EastEccL2    East eccentricity (meters) for GPS L2 freq
00062        * @param[in] UpEccL2      Up eccentricity (meters) for GPS L2 freq
00063        */
00064    Antenna::Antenna( double NorthEccL1,
00065                      double EastEccL1,
00066                      double UpEccL1,
00067                      double NorthEccL2,
00068                      double EastEccL2,
00069                      double UpEccL2 )
00070    {
00071          // Add eccentricities
00072       addAntennaEcc(G01, NorthEccL1, EastEccL1, UpEccL1);
00073       addAntennaEcc(G02, NorthEccL2, EastEccL2, UpEccL2);
00074 
00075    }  // End of constructor 'Antenna::Antenna()'
00076 
00077 
00078 
00079       /* Get antenna data.
00080        *
00081        * @param[in] dataType     Antenna data type to be fetched
00082        */
00083    std::string Antenna::getAntennaData( AntennaDataType dataType ) const
00084       throw(InvalidRequest)
00085    {
00086 
00087          // Look for this frequency in the antenna data map
00088          // Define iterator
00089       AntennaDataMap::const_iterator it( antennaData.find(dataType) );
00090       if( it != antennaData.end() )
00091       {
00092             // If we found data for this data type, let's return it
00093          return (*it).second;
00094       }
00095       else
00096       {
00097          InvalidRequest e("No data was found for provided data type.");
00098          GPSTK_THROW(e);
00099       }
00100    }  // End of method 'Antenna::getAntennaData()'
00101 
00102 
00103 
00104       /* Get antenna eccentricity (or 'phase center offset' in Antex
00105        * parlance) as a Triple in UEN system.
00106        *
00107        * @param[in] freq      Frequency
00108        *
00109        * @warning The phase center offset Triple is in UEN system.
00110        */
00111    Triple Antenna::getAntennaEccentricity( frequencyType freq ) const
00112       throw(InvalidRequest)
00113    {
00114 
00115          // Look for this frequency in the antenna eccentricity map
00116          // Define iterator
00117       AntennaEccDataMap::const_iterator it( antennaEccMap.find(freq) );
00118       if( it != antennaEccMap.end() )
00119       {
00120             // If we found a Triple for this frequency, let's
00121             // return it in UEN system
00122          Triple toReturn( (*it).second[2], (*it).second[1], (*it).second[0] );
00123          return toReturn;
00124       }
00125       else
00126       {
00127          InvalidRequest e("No eccentricities were found for this frequency.");
00128          GPSTK_THROW(e);
00129       }
00130 
00131    }  // End of method 'Antenna::getAntennaEccentricity()'
00132 
00133 
00134 
00135       /* Get antenna phase center variation. Use this method when you
00136        * don't have azimuth dependent phase center patterns.
00137        *
00138        * This method returns a Triple, in UEN system, with the
00139        * elevation-dependent phase center variation.
00140        *
00141        * @param[in] freq      Frequency
00142        * @param[in] elevation Elevation (degrees)
00143        *
00144        * @warning The phase center variation Triple is in UEN system.
00145        */
00146    Triple Antenna::getAntennaPCVariation( frequencyType freq,
00147                                           double elevation ) const
00148       throw(InvalidRequest)
00149    {
00150 
00151          // The angle should be measured respect to zenith
00152       double angle( 90.0 - elevation );
00153 
00154          // Check that angle is within limits
00155       if( ( angle < zen1 ) ||
00156           ( angle > zen2 ) )
00157       {
00158          InvalidRequest e("Elevation is out of allowed range.");
00159          GPSTK_THROW(e);
00160       }
00161 
00162          // Look for this frequency in noAziMap
00163          // Define iterator
00164       NoAziDataMap::const_iterator it( noAziMap.find(freq) );
00165       if( it != noAziMap.end() )
00166       {
00167             // Get the normalized angle
00168          double normalizedAngle( (angle-zen1)/dzen );
00169 
00170             // Return result. Only the "Up" component is important.
00171          Triple result( linearInterpol( (*it).second, normalizedAngle ),
00172                         0.0,
00173                         0.0 );
00174 
00175          return result;
00176       }
00177       else
00178       {
00179          InvalidRequest e("No data was found for this frequency.");
00180          GPSTK_THROW(e);
00181       }
00182 
00183    }  // End of method 'Antenna::getAntennaPCVariation()'
00184 
00185 
00186 
00187       /* Get antenna phase center variation.
00188        *
00189        * This method returns a Triple, in UEN system, with the
00190        * elevation and azimuth-dependent phase center variation.
00191        *
00192        * @param[in] freq      Frequency
00193        * @param[in] elevation Elevation (degrees)
00194        * @param[in] azimuth   Azimuth (degrees)
00195        *
00196        * @warning The phase center variation Triple is in UEN system.
00197        */
00198    Triple Antenna::getAntennaPCVariation( frequencyType freq,
00199                                           double elevation,
00200                                           double azimuth ) const
00201       throw(InvalidRequest)
00202    {
00203 
00204          // The angle should be measured respect to zenith
00205       double angle( 90.0 - elevation );
00206 
00207          // Check that angle is within limits
00208       if( ( angle < zen1 ) ||
00209           ( angle > zen2 ) )
00210       {
00211          InvalidRequest e("Elevation is out of allowed range.");
00212          GPSTK_THROW(e);
00213       }
00214 
00215          // Reduce azimuth to 0 <= azimuth < 360 interval
00216       while( azimuth < 0.0 )
00217       {
00218          azimuth += 360.0;
00219       }
00220       while( azimuth >= 360.0 )
00221       {
00222          azimuth -= 360.0;
00223       }
00224 
00225          // Look for this frequency in pcMap
00226          // Define iterator
00227       PCDataMap::const_iterator it( pcMap.find(freq) );
00228       if( it != pcMap.end() )
00229       {
00230 
00231             // Get the right azimuth interval
00232          const double lowerAzimuth( std::floor(azimuth/dazi) * dazi );
00233          const double upperAzimuth( lowerAzimuth + dazi );
00234 
00235                // Look for data vectors
00236          AzimuthDataMap::const_iterator it2( (*it).second.find(lowerAzimuth) );
00237          AzimuthDataMap::const_iterator it3( (*it).second.find(upperAzimuth) );
00238 
00239             // Find the fraction from 'lowerAzimuth'
00240          const double fractionalAzimuth( ( azimuth - lowerAzimuth ) /
00241                                          ( upperAzimuth - lowerAzimuth ) );
00242 
00243             // Check if 'azimuth' exactly corresponds to a value in the map
00244          if( fractionalAzimuth == 0.0 )
00245          {
00246                // Check if there is data for 'lowerAzimuth'
00247             if( it2 != (*it).second.end() )
00248             {
00249                   // Get the normalized angle
00250                const double normalizedAngle( (angle-zen1)/dzen );
00251 
00252                   // Return result. Only the "Up" component is important.
00253                Triple result( linearInterpol( (*it2).second, normalizedAngle ),
00254                               0.0,
00255                               0.0 );
00256 
00257                return result;
00258 
00259             }
00260             else
00261             {
00262                InvalidRequest e("No data was found for this azimuth.");
00263                GPSTK_THROW(e);
00264             }
00265          }
00266          else
00267          {
00268                // We have to interpolate
00269                // Check if there is data for 'lowerAzimuth' and 'upperAzimuth'
00270             if( it2 != (*it).second.end() &&
00271                 it3 != (*it).second.end() )
00272             {
00273                   // Get the normalized angle
00274                const double normalizedAngle( (angle-zen1)/dzen );
00275 
00276                   // Find values corresponding to both azimuths
00277                double val1( linearInterpol( (*it2).second, normalizedAngle ) );
00278                double val2( linearInterpol( (*it3).second, normalizedAngle ) );
00279 
00280                   // Return result. Only the "Up" component is important.
00281                Triple result( ( val1 + (val2-val1) * fractionalAzimuth ),
00282                               0.0,
00283                               0.0 );
00284 
00285                return result;
00286 
00287             }
00288             else
00289             {
00290                InvalidRequest e("Not enough data was found for this azimuth.");
00291                GPSTK_THROW(e);
00292             }
00293          }
00294 
00295       }
00296       else
00297       {
00298 
00299          InvalidRequest e("No data was found for this frequency.");
00300          GPSTK_THROW(e);
00301 
00302       }  // End of 'if( it != pcMap.end() )...'
00303 
00304    }  // End of method 'Antenna::getAntennaPCVariation()'
00305 
00306 
00307 
00308       /* Add antenna phase center eccentricities, in METERS.
00309        *
00310        * @param[in] freq        Frequency.
00311        * @param[in] northEcc    North eccentricity component, in METERS.
00312        * @param[in] eastEcc     East eccentricity component, in METERS.
00313        * @param[in] upEcc       Up eccentricity component, in METERS.
00314        */
00315    Antenna Antenna::addAntennaEcc( frequencyType freq,
00316                                    double northEcc,
00317                                    double eastEcc,
00318                                    double upEcc )
00319    {
00320 
00321          // Build a Triple with the eccentricities
00322       Triple ecc(northEcc, eastEcc, upEcc);
00323 
00324          // Get Triple into eccentricities map
00325       antennaEccMap[freq] = ecc;
00326 
00327          // Return this object
00328       return (*this);
00329 
00330    }  // End of method 'Antenna::addAntennaEcc()'
00331 
00332 
00333 
00334       /* Add antenna phase center RMS eccentricities, in METERS.
00335        *
00336        * @param[in] freq        Frequency.
00337        * @param[in] northRMS    North eccentricity RMS component, in METERS.
00338        * @param[in] eastRMS     East eccentricity RMS component, in METERS.
00339        * @param[in] upRMS       Up eccentricity RMS component, in METERS.
00340        */
00341    Antenna Antenna::addAntennaRMSEcc( frequencyType freq,
00342                                       double northRMS,
00343                                       double eastRMS,
00344                                       double upRMS )
00345    {
00346 
00347          // Build a Triple with eccentricities RMS
00348       Triple ecc(northRMS, eastRMS, upRMS);
00349 
00350          // Get Triple into eccentricities map
00351       antennaRMSEccMap[freq] = ecc;
00352 
00353          // Return this object
00354       return (*this);
00355 
00356    }  // End of method 'Antenna::addAntennaRMSEcc()'
00357 
00358 
00359 
00360       // Returns if this object is valid. The validity criteria is to
00361       // have a non-empty 'antennaData' map AND a non-empty 'antennaEccMap'.
00362    bool Antenna::isValid() const
00363    {
00364 
00365       if( getAntennaDataSize()   > 0 &&
00366           getAntennaEccMapSize() > 0 )
00367       {
00368          return true;
00369       }
00370       else
00371       {
00372          return false;
00373       }
00374 
00375    }  // End of method 'Antenna::isValid()'
00376 
00377 
00378 
00379       /* Linear interpolation as function of normalized angle
00380        *
00381        * @param[in] dataVector         std::vector holding data.
00382        * @param[in] normalizedAngle    Normalized angle.
00383        *
00384        * 'normalizedAngle' is a value corresponding to the original angle
00385        * divided by the angle interval.
00386        */
00387    double Antenna::linearInterpol( const std::vector<double>& dataVector,
00388                                    double normalizedAngle ) const
00389    {
00390 
00391          // Get the index value 'normalizedAngle' is equivalent to
00392       int index( static_cast<int>( std::floor(normalizedAngle) ) );
00393 
00394          // Find the fraction from 'index'
00395       double fraction( normalizedAngle - std::floor(normalizedAngle) );
00396 
00397          // Check if 'normalizedAngle' is exactly a value in the map
00398       if( fraction == 0.0 )
00399       {
00400                // Return result
00401             return dataVector[index];
00402       }
00403       else
00404       {
00405             // In this case, we have to interpolate
00406          double val1( dataVector[index] );
00407          double val2( dataVector[index+1] );
00408 
00409              // Return result
00410          return ( val1 + (val2-val1) * fraction );
00411       }
00412 
00413    }  // End of method 'Antenna::elevationInterpol()'
00414 
00415 
00416 
00417 }  // End of namespace gpstk

Generated on Thu Jul 29 03:30:50 2010 for GPS ToolKit Software Library by  doxygen 1.3.9.1