#pragma ident "$Id: $"

/**
 * @file Bancroft.hpp 
 * Use Bancroft method to get an initial guess of GPS receiver's position
 */
 
#ifndef BANCROFT_HPP
#define BANCROFT_HPP

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2006/2007
//
//============================================================================

#include <vector>
#include "Matrix.hpp"

using namespace std;
using namespace gpstk;

namespace gpstk
{
      /** @defgroup GPSsolutions GPS solution algorithms and Tropospheric
       *  models
       */

      //@{
       	
      /** This class defines an algebraic algorithm to get an initial guess of
       *  GPS receiver's position given satellites' positions and pseudoranges.
       *
       * The algorithm is based on Bancroft's Method as presented in: Yang,
       * Ming & Kuo-Hwa Chen. ''Performance Assessment of a Noniterative
       * Algorithm for Global Positioning System (GPS) Absolute
       * Positioning''. Proc. Natl. Sci. Counc. ROC(A). Vol. 25, No. 2,
       * 2001. pp. 102-106.
       */
   class Bancroft
   {
   public:

         /// Constructor
      Bancroft()
         throw(Exception) : SecondSolution(4,0.0)
      { 
         testInput= true;
         ChooseOne = true;
         CloseTo = 6378137.0;
         minPRange = 15000000.0;
         maxPRange = 30000000.0;
         minRadius = 23000000.0;
         maxRadius = 29000000.0;
      };


         /** Compute an initial guess of GPS receiver's position , given
          *  satellites' positions and pseudoranges.
          *
          * @param Data    Matrix of data containing observation data in rows,
          *                one row per observation and complying with the
          *                following format:
          *
          *                        x y z P
          *
          *                Where x,y,z are satellite coordinates in an ECEF
          *                system and P is pseudorange (corrected as much as
          *                possible, specially from satellite clock errors),
          *                all expresed in meters.
          *
          * @param X      Vector of position solution, in meters. There may be
          *               another solution that may be accessed with vector
          *               "SecondSolution" if "ChooseOne" is set to "false".
          *
          * @return
          *    0  Ok, 
          *   -1  Not enough good data
          *   -2  Singular problem
          */
      int Compute( Matrix<double>& Data,
                   Vector<double>& X )
         throw(Exception);


         /** Another version of Compute method allowing calls with Matrix B
          *  being const.
          */
      int Compute( const Matrix<double>& Data,
                   Vector<double>& X )
         throw(Exception);


         /** If true, the solution closest to CloseTo criterion will be chosen.
          *  If false, the two posible solutions will be provided.
          */
      bool ChooseOne;


         /** Criterion to decide which solution to choose. The algorithm will
          *  choose the solution closer to this value. By default, it is set
          *  to earth radius, in meters.
          */
      double CloseTo;


         /** If true (the default), the B input Matrix will be screened to get
          *  out suspicious data.
          *
          * It works with minPRange, maxPRange, minRadius and maxRadius to
          * pick up a set of "clean data". However, don't be too picky with
          * these parameters in order to leave room for different GNSS systems
          * and configurations. Anyway, Bancroft will give you just an
          * approximate position.
          */
      bool testInput;


         /// Minimum pseudorange value allowed for input data (in meters).
      double minPRange;


         /// Maximum pseudorange value allowed for input data (in meters).
      double maxPRange;


         /// Minimum allowed distance between Earth center and satellite
         /// position for input data (in meters).
      double minRadius;


         /// Maximum allowed distance between Earth center and satellite
         /// position for input data (in meters).
      double maxRadius;


         /** Vector<double> containing the estimated second position solution
          * (ECEF, meters), if ChooseOne is set to "false".
          */
      Vector<double> SecondSolution;


         /// Destructor.
      virtual ~Bancroft() throw() {};


   }; // end class Bancroft

      //@}

} // namespace gpstk

#endif   // BANCROFT_HPP
