Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

GPS.cxx

Go to the documentation of this file.
00001 // GPS.cxx: implementation of the GPS class.
00002 // $Id: GPS.cxx,v 1.18 2002/10/07 23:42:20 srobinsn Exp $
00004 
00005 #include "GPS.h"
00006 
00007 #include "Orbit.h"
00008 #include "CLHEP/Random/RandFlat.h"
00009 
00010 #include <iomanip>
00011 
00012 
00013 // static declaration
00014 
00015 GPS*    GPS::s_instance = 0;
00016 
00017 GPS::GPS() 
00018 : m_orbit(new Orbit),
00019 m_rockDegrees(15.),
00020 m_rockType(NONE),
00021 m_earthOrbit(new astro::EarthOrbit),
00022 m_expansion(1.),    // default expansion:regular orbit for now
00023 m_time(0.), 
00024 m_orbittime(m_time),
00025 m_sampleintvl(0.001),
00026 m_rotangles(std::make_pair<double,double>(0.,0.))
00027 {}
00028 
00029 GPS::Coords::Coords( double alat, double alon, double apitch
00030                     , double ayaw, double aroll, GPStime atime, double aphase) 
00031                     : m_time(atime), m_lat(alat), m_lon(alon), 
00032                     m_pitch(apitch), m_yaw(ayaw), m_roll(aroll), m_phase(aphase)
00033 {}
00034 
00035 GPS::Coords::Coords(){}
00036 
00037 
00038 GPS::~GPS ()
00039 { delete m_orbit; }
00040 
00041 
00042 double  GPS::pitch () const
00043 { 
00044     return orbit()->pitch( orbittime() ); 
00045 }
00046 
00047 double  GPS::yaw () const
00048 { 
00049     return orbit()->yaw( orbittime() );   
00050 }
00051 
00052 double   GPS::roll () const
00053 { 
00054     return orbit()->roll( orbittime() ); 
00055 }
00056 
00057 const Orbit*   GPS::orbit () const 
00058 {
00059     return m_orbit;
00060 }
00061 
00062 Orbit*   GPS::orbit () 
00063 {
00064     return m_orbit;
00065 }
00066 
00067 void GPS::synch ()
00068 {
00069     static bool first=true;
00070     bool changed=  false;
00071     
00072     if (Scheduler::instance()->running()) {
00073         time( Scheduler::instance()->elapsed_time() );
00074         changed = true; // maybe have threshold before nofitying?
00075     }
00076     if (expansion() < 0.) {
00077         static GPStime  last_time = time();
00078         if ((time() - last_time) > m_sampleintvl) {
00079             orbittime( RandFlat::shoot(orbit()->period()) );
00080             orbit()->ascendingLon(RandFlat::shoot(360.));
00081             last_time = time();
00082             changed = true;
00083             
00084         }
00085     }
00086     else if( expansion()>0 ) {
00087         orbittime( time()*expansion() );
00088         changed=true; 
00089     }
00090     
00091     // notify observers if changed (or first time thru)
00092     if( changed || first) notifyObservers();
00093     first=false;
00094     
00095 }
00096 
00097 double   GPS::lat () const
00098 {
00099     return orbit()->latitude( orbittime() ); 
00100 }
00101 
00102 double  GPS::lon () const
00103 { 
00104     return orbit()->longitude( orbittime() ); 
00105 }
00106 
00107 GPStime GPS::time ()  const
00108 { 
00109     return m_time;
00110 }
00111 
00112 double   GPS::phase () const
00113 {
00114     // compute orbital phase based upon current time
00115     return orbit()->phase( orbittime() );
00116 }
00117 
00118 double   GPS::expansion () const
00119 {
00120     return m_expansion;
00121 }
00122 
00123 void    GPS::orbit ( Orbit* o )
00124 {
00125     if (o == 0) return;
00126     delete m_orbit;
00127     m_orbit = o;
00128 }
00129 
00130 
00131 void GPS::pass ( double t )
00132 { 
00133     if (!Scheduler::instance()->running())      {
00134         time(time() + t);
00135     }   // cannot pass when scheduler is in control!
00136 }
00137 
00138 void GPS::phase ( double p )
00139 {
00140     // jump to a particular point in the orbit
00141     double  pd = orbit()->period();
00142     if (pd != 0.) orbit()->startphase(p - 2.*M_PI*time()/pd);
00143 }
00144 
00145 void GPS::expansion ( double e )
00146 {
00147     m_expansion = e; 
00148 }
00149 
00150 void GPS::pitch ( double p )
00151 {
00152     m_orbit->setPitch(p);
00153 }
00154 
00155 void GPS::yaw ( double y )
00156 {
00157     m_orbit->setYaw(y);
00158 }
00159 
00160 void GPS::roll ( double r )
00161 {
00162     m_orbit->setRoll(r);
00163 }
00164 
00165 void GPS::lat ( double l )
00166 {
00167     m_orbit->setLatitude(l);
00168 }
00169 
00170 void GPS::lon ( double l )
00171 {
00172     m_orbit->setLongitude(l);
00173 }
00174 
00175 void GPS::time ( GPStime t )
00176 {
00177     m_time = t;
00178 }
00179 
00180 GPS*    GPS::instance() 
00181 { return (s_instance != 0) ? s_instance : (s_instance = new GPS()); }
00182 
00183 void GPS::kill()
00184 {
00185     delete s_instance;
00186     s_instance = 0;
00187 }
00188 
00189 GPS::Coords GPS::state () const
00190 {
00191     return GPS::Coords( lat(),lon(),pitch(),yaw(),roll(),time(), orbit()->phase(time()) );
00192 }
00193 
00194 void GPS::orbittime ( GPStime t ) 
00195 {
00196     m_orbittime = t;
00197 }
00198 
00199 GPStime GPS::orbittime () const
00200 {
00201     return m_orbittime;
00202 }
00203 
00204 void    GPS::sampleintvl ( GPStime s )
00205 {
00206     m_sampleintvl = s;
00207 }
00208 
00209 GPStime  GPS::sampleintvl () const
00210 {
00211     return m_sampleintvl;
00212 }
00213 
00214 void    GPS::setState ( const GPS::Coords& c )
00215 {
00216     m_orbit->setLatitude(c.lat());
00217     m_orbit->setLongitude(c.lon());
00218     m_orbit->setPitch(c.pitch());
00219     m_orbit->setYaw(c.yaw());
00220     m_orbit->setRoll(c.roll());
00221     if (c.time() > 0.) time(c.time());  // if the time is relevant, use that time
00222 }
00223 void GPS::ascendingLon(double lon)
00224 {
00225     m_orbit->ascendingLon(lon);
00226 }
00227 double GPS::ascendingLon()const
00228 {
00229     return m_orbit->ascendingLon();
00230 }
00231 void    GPS::printOn(std::ostream& out) const
00232 {
00233     out << "GPS: time=" << time() 
00234         << ", lat, lon=" 
00235         << std::setprecision(4) << lat() << ", " << lon() 
00236         << std::endl;
00237 }
00238 
00239 
00240 //access m_rotangles
00241 std::pair<double,double> GPS::rotateAngles(){
00242     return m_rotangles;
00243     
00244 }
00245 
00246 //set m_rotangles
00247 void GPS::rotateAngles(std::pair<double,double> coords){
00248     m_rotangles=coords;
00249 }
00250 
00251 
00252 Rotation GPS::rockingAngleTransform(double seconds){
00253     //Purpose:  return the rotation to correct for satellite rocking.
00254     //Input:  Current time
00255     //Output:  3x3 rocking-angle transformation matrix.
00256     using namespace astro;
00257     
00258     double time = m_earthOrbit->dateFromSeconds(seconds);
00259     
00260     double inclination = m_earthOrbit->inclination();
00261     double orbitPhase = m_earthOrbit->phase(time);
00262     m_position = m_earthOrbit->position(time);
00263     
00264     SkyDir dirZ(m_position.unit());
00265     SkyDir dirX(dirZ.ra()-90., 0.0);
00266     
00267     //rotate the x direction so that the x direction points along the orbital direction.
00268     dirX().rotate(dirZ.dir() , inclination*cos(orbitPhase));
00269     
00270     //now set the zenith direction to do the rocking properly.
00271     m_RAZenith = dirZ.ra();
00272     m_DECZenith = dirZ.dec();
00273 
00274     double rockNorth = m_rockDegrees*M_PI/180;
00275     
00276     //here's where we decide how much to rock about the x axis.  this depends on the 
00277     //rocking mode.
00278     if(m_rockType == NONE){
00279         rockNorth = 0.;
00280     }else if(m_rockType == UPDOWN){
00281         if(m_DECZenith <= 0) rockNorth *= -1.;
00282     }else if(m_rockType == SLEWING){
00283         //slewing is experimental
00284         if(m_DECZenith <= 0) rockNorth *= -1.;
00285         if(m_DECZenith >= -5.5 && m_DECZenith <= 5.5){
00286             rockNorth -= rockNorth*((5.5-fabs(m_DECZenith))/5.5);
00287         }
00288     }else if(m_rockType == ONEPERORBIT){
00289         //this needs an implementation - it only rocks one way now!
00290     }
00291     // now, we want to find the proper transformation for the rocking angles:
00292     HepRotation rockRot;
00293     rockRot./*rotateZ(inclination*cos(orbitPhase)).*/rotateX(rockNorth);
00294 
00295     return rockRot;
00296 }
00297 
00298 Rotation GPS::CELTransform(double seconds){
00299     // Purpose:  Return the 3x3 matrix which transforms a vector from a galactic 
00300     // coordinate system to a local coordinate system.
00301     using namespace astro;
00302     double degsPerRad = 180./M_PI;
00303     Rotation gal;//,cel;
00304     double time = m_earthOrbit->dateFromSeconds(seconds);
00305     
00306     m_position = m_earthOrbit->position(time);
00307     
00308     //first make the directions for the x and Z axes, as well as the zenith direction.
00309     //before rotation, the z axis points along the zenith:
00310     SkyDir dirZ(m_position.unit());
00311     SkyDir dirX(dirZ.ra()-90., 0.0);
00312 
00313     //so now we know where the x and z axes of the zenith-pointing frame point in the celestial frame.
00314     //what we want now is to make cel, where
00315     //cel is the matrix which rotates (cartesian)local coordinates into (cartesian)celestial ones
00316     Rotation cel(dirX() , dirZ().cross(dirX()) , dirZ());
00317 
00318     //std::cout << "time is " << seconds << std::endl;
00319     //m_orbit->displayRotation(cel);
00320 
00321     //gal is the matrix which rotates (cartesian)celestial coordiantes into (cartesian)galactic ones
00322     gal.rotateZ(-282.25/degsPerRad).rotateX(-62.6/degsPerRad).rotateZ(33./degsPerRad);
00323     //so gal*cel should be the matrix that makes local coordiates into galactic ones.
00324     Rotation glstToGal=gal*cel;
00325     return glstToGal.inverse();
00326 
00327 }
00328 
00329 Rotation GPS::transformCelToGlast(double seconds){
00330     // Purpose:  Return the 3x3 matrix which transforms a vector from a celestial 
00331     // coordinate system (like a SkyDir vector) to a local coordinate system (like the FluxSvc output).
00332     using namespace astro;
00333     double degsPerRad = 180./M_PI;
00334 
00335     double time = m_earthOrbit->dateFromSeconds(seconds);
00336     
00337     m_position = m_earthOrbit->position(time);
00338     
00339     //first make the directions for the x and Z axes, as well as the zenith direction.
00340     //before rotation, the z axis points along the zenith:
00341     SkyDir dirZ(m_position.unit());
00342     SkyDir dirX(dirZ.ra()-90., 0.0);
00343 
00344     //so now we know where the x and z axes of the zenith-pointing frame point in the celestial frame.
00345     //what we want now is to make cel, where
00346     //cel is the matrix which rotates (cartesian)local coordinates into (cartesian)celestial ones
00347     Rotation cel(dirX() , dirZ().cross(dirX()) , dirZ());
00348     return cel.inverse();
00349 }
00350 
00351 Rotation GPS::transformGlastToGalactic(double seconds){
00352     return (CELTransform(seconds).inverse())*(rockingAngleTransform(seconds).inverse());
00353 }
00354 
00355 void GPS::getPointingCharacteristics(double seconds){
00356     //this is being used by exposureAlg right now, and should be reworked
00357     //to use the rest of this class.
00358     using namespace astro;
00359     
00360     double time = m_earthOrbit->dateFromSeconds(seconds);
00361     
00362     double inclination = m_earthOrbit->inclination();
00363     double orbitPhase = m_earthOrbit->phase(time);
00364     m_position = m_earthOrbit->position(time);
00365     
00366     //first make the directions for the x and Z axes, as well as the zenith direction.
00367     SkyDir dirZenith(m_position.unit());
00368     //before rotation, the z axis points along the zenith:
00369     SkyDir dirZ(m_position.unit());
00370     SkyDir dirX(dirZ.ra()-90., 0.0);
00371     
00372     //rotate the x direction so that the x direction points along the orbital direction.
00373     dirX().rotate(dirZ.dir() , inclination*cos(orbitPhase));
00374     
00375     //now set the zenith direction before the rocking.
00376     m_RAZenith = dirZ.ra();
00377     m_DECZenith = dirZ.dec();
00378     
00379 
00380 
00381 
00382 
00383     // now, we want to find the proper transformation for the rocking angles:
00384     //HepRotation rockRot(Hep3Vector(0,0,1).cross(dirZ.dir()) , rockNorth);    
00385     //and apply the transformation to dirZ and dirX:
00386     double rockNorth = m_rockDegrees*M_PI/180;
00387     //here's where we decide how much to rock about the x axis.  this depends on the 
00388     //rocking mode.
00389     if(m_rockType == NONE){
00390         rockNorth = 0.;
00391     }else if(m_rockType == UPDOWN){
00392         if(m_DECZenith <= 0) rockNorth *= -1.;
00393     }else if(m_rockType == SLEWING){
00394         //slewing is experimental
00395         if(m_DECZenith <= 0) rockNorth *= -1.;
00396         if(m_DECZenith >= -5.5 && m_DECZenith <= 5.5){
00397             rockNorth -= rockNorth*((5.5-fabs(m_DECZenith))/5.5);
00398         }
00399     }else if(m_rockType == ONEPERORBIT){
00400         //this needs an implementation - it only rocks one way now!
00401     }
00402     
00403     dirZ().rotate(dirX.dir() , rockNorth);
00404     
00405     m_RAX = dirX.ra();
00406     m_RAZ = dirZ.ra();
00407     m_DECX = dirX.dec();
00408     m_DECZ = dirZ.dec();
00409     
00410     //a test - to ensure the rotation went properly
00411     //std::cout << " degrees between xhat and zhat directions: " <<
00412     //    dirZ.difference(dirX)*180./M_PI << std::endl;
00413 }
00414 
00415 void GPS::setRockType(int rockType){
00416     m_rockType = NONE;
00417     if(rockType == 1) m_rockType = UPDOWN;
00418     if(rockType == 2) m_rockType = SLEWING;
00419     if(rockType == 3) m_rockType = ONEPERORBIT;
00420 }

Generated on Wed Oct 16 14:01:30 2002 by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001