Bancroft.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: Bancroft.cpp 1161 2008-03-27 17:16:22Z ckiesch $"
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 ). 2006/2007
00027 //
00028 //============================================================================
00029  
00030 #include <cstdlib>              // for std::abs()
00031 #include "Bancroft.hpp"
00032 #include "MiscMath.hpp"
00033 #include "Matrix.hpp"
00034 #include "Vector.hpp"
00035 
00036 using namespace std;
00037 using namespace gpstk;
00038 
00039 namespace gpstk
00040 {
00041 
00042       /* 'Data'   Matrix of data containing observation data in rows, one
00043        *          row per observation and complying with this format:
00044        *                    x y z P
00045        *          Where x,y,z are satellite coordinates in an ECEF system
00046        *          and P is pseudorange (corrected as much as possible,
00047        *          specially from satellite clock errors), all expresed
00048        *          in meters.
00049        *
00050        * 'X'      Vector of position solution, in meters. There may be
00051        *          another solution, that may be accessed with vector
00052        *          "SecondSolution" if "ChooseOne" is set to "false".
00053        *
00054        * Return values:
00055        *  0  Ok
00056        * -1  Not enough good data
00057        * -2  Singular problem
00058        */
00059    int Bancroft::Compute( Matrix<double>& Data,
00060                           Vector<double>& X )
00061       throw(Exception)
00062    {
00063 
00064       try
00065       {
00066 
00067          int N = Data.rows();
00068          Matrix<double> B(0,4);     // Working matrix
00069 
00070             // Let's test the input data
00071          if( testInput )
00072          {
00073 
00074             double satRadius = 0.0;
00075 
00076                // Check each row of B Matrix
00077             for( int i=0; i < N; i++ )
00078             {
00079                   // If Data(i,3) -> Pseudorange is NOT between the allowed
00080                   // range, then drop line immediately
00081                if( !( (Data(i,3) >= minPRange) && (Data(i,3) <= maxPRange) ) )
00082                {
00083                   continue;
00084                }
00085 
00086                   // Let's compute distance between Earth center and
00087                   // satellite position
00088                satRadius = RSS(Data(i,0), Data(i,1) , Data(i,2));
00089 
00090                   // If satRadius is NOT between the allowed range, then drop
00091                   // line immediately
00092                if( !( (satRadius >= minRadius) && (satRadius <= maxRadius) ) )
00093                {
00094                   continue;
00095                }
00096 
00097                   // If everything is ok so far, then extract the good
00098                   // data row and add it to working matrix
00099                MatrixRowSlice<double> goodRow(Data,i);
00100                B = B && goodRow;              
00101 
00102             }
00103 
00104                // Let's redefine "N" and check if we have enough data rows
00105                // left in a single step
00106             if( (N = B.rows()) < 4 )
00107             {
00108                return -1;  // We need at least 4 data rows
00109             }
00110 
00111          }  // End of 'if( testInput )...'
00112          else
00113          {
00114                // No input filtering. Working matrix (B) and
00115                // input matrix (Data) are equal
00116             B = Data;
00117          }
00118 
00119 
00120          Matrix<double> BT=transpose(B);
00121          Matrix<double> BTBI(4,4), M(4,4,0.0);
00122          Vector<double> aux(4), alpha(N), solution1(4), solution2(4);
00123 
00124             // Temporary storage for BT*B. It will be inverted later
00125          BTBI = BT * B;
00126 
00127             // Let's try to invert BTB matrix
00128          try
00129          {
00130             BTBI = inverseChol( BTBI ); 
00131          }
00132          catch(...)
00133          {
00134             return -2;
00135          }
00136 
00137             // Now, let's compute alpha vector
00138          for( int i=0; i < N; i++ )
00139          {
00140                // First, fill auxiliar vector with corresponding satellite
00141                // position and pseudorange
00142             aux(0) = B(i,0);
00143             aux(1) = B(i,1);
00144             aux(2) = B(i,2);
00145             aux(3) = B(i,3);
00146             alpha(i) = 0.5 * Minkowski(aux, aux);
00147          }
00148 
00149          Vector<double> tau(N,1.0), BTBIBTtau(4), BTBIBTalpha(4);
00150 
00151          BTBIBTtau = BTBI * BT * tau;
00152          BTBIBTalpha = BTBI * BT * alpha;
00153 
00154             // Now, let's find the coeficients of the second order-equation
00155          double a(Minkowski(BTBIBTtau, BTBIBTtau));
00156          double b(2.0 * (Minkowski(BTBIBTtau, BTBIBTalpha) - 1.0));
00157          double c(Minkowski(BTBIBTalpha, BTBIBTalpha));
00158 
00159             // Calculate discriminant and exit if negative
00160          double discriminant = b*b - 4.0 * a * c;
00161          if (discriminant < 0.0)
00162          {
00163             return -2;
00164          }
00165 
00166             // Find possible DELTA values
00167          double DELTA1 = ( -b + SQRT(discriminant) ) / ( 2.0 * a );
00168          double DELTA2 = ( -b - SQRT(discriminant) ) / ( 2.0 * a );
00169 
00170             // We need to define M matrix
00171          M(0,0) = 1.0;
00172          M(1,1) = 1.0;
00173          M(2,2) = 1.0;
00174          M(3,3) = - 1.0;
00175 
00176             // Find possible position solutions with their implicit radii
00177          solution1 = M *  BTBI * ( BT * DELTA1 * tau + BT * alpha );
00178          double radius1(RSS(solution1(0), solution1(1), solution1(2)));
00179 
00180          solution2 = M *  BTBI * ( BT * DELTA2 * tau + BT * alpha );
00181          double radius2(RSS(solution2(0), solution2(1), solution2(2)));
00182 
00183             // Let's choose the right solution
00184          if ( ChooseOne )
00185          {
00186             if ( ABS(CloseTo-radius1) < ABS(CloseTo-radius2) )
00187             {
00188                X = solution1;
00189             }
00190             else
00191             {
00192                X = solution2;
00193             }
00194          }
00195          else
00196          {
00197                // Both solutions will be reported
00198             X = solution1;
00199             SecondSolution = solution2;
00200          }
00201      
00202          return 0;
00203 
00204       }  // end of first "try"
00205       catch(Exception& e)
00206       {
00207          GPSTK_RETHROW(e);
00208       }
00209    }  // end Bancroft::Compute()
00210 
00211 
00212       // Another version of Compute method to allow calling it with
00213       // const Matrix B.
00214    int Bancroft::Compute( const Matrix<double>& Data,
00215                           Vector<double>& X )
00216       throw(Exception) 
00217    {
00218       Matrix<double> Datanoconst(Data);
00219 
00220       return Bancroft::Compute(Datanoconst, X);
00221 
00222    }
00223  
00224 
00225 } // namespace gpstk

Generated on Wed Feb 8 03:30:57 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1