00001
00002
00004
00005 #include "GPS.h"
00006
00007 #include "Orbit.h"
00008 #include "CLHEP/Random/RandFlat.h"
00009
00010 #include <iomanip>
00011
00012
00013
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.),
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;
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
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
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 }
00136 }
00137
00138 void GPS::phase ( double p )
00139 {
00140
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());
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
00241 std::pair<double,double> GPS::rotateAngles(){
00242 return m_rotangles;
00243
00244 }
00245
00246
00247 void GPS::rotateAngles(std::pair<double,double> coords){
00248 m_rotangles=coords;
00249 }
00250
00251
00252 Rotation GPS::rockingAngleTransform(double seconds){
00253
00254
00255
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
00268 dirX().rotate(dirZ.dir() , inclination*cos(orbitPhase));
00269
00270
00271 m_RAZenith = dirZ.ra();
00272 m_DECZenith = dirZ.dec();
00273
00274 double rockNorth = m_rockDegrees*M_PI/180;
00275
00276
00277
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
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
00290 }
00291
00292 HepRotation rockRot;
00293 rockRot.rotateX(rockNorth);
00294
00295 return rockRot;
00296 }
00297
00298 Rotation GPS::CELTransform(double seconds){
00299
00300
00301 using namespace astro;
00302 double degsPerRad = 180./M_PI;
00303 Rotation gal;
00304 double time = m_earthOrbit->dateFromSeconds(seconds);
00305
00306 m_position = m_earthOrbit->position(time);
00307
00308
00309
00310 SkyDir dirZ(m_position.unit());
00311 SkyDir dirX(dirZ.ra()-90., 0.0);
00312
00313
00314
00315
00316 Rotation cel(dirX() , dirZ().cross(dirX()) , dirZ());
00317
00318
00319
00320
00321
00322 gal.rotateZ(-282.25/degsPerRad).rotateX(-62.6/degsPerRad).rotateZ(33./degsPerRad);
00323
00324 Rotation glstToGal=gal*cel;
00325 return glstToGal.inverse();
00326
00327 }
00328
00329 Rotation GPS::transformCelToGlast(double seconds){
00330
00331
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
00340
00341 SkyDir dirZ(m_position.unit());
00342 SkyDir dirX(dirZ.ra()-90., 0.0);
00343
00344
00345
00346
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
00357
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
00367 SkyDir dirZenith(m_position.unit());
00368
00369 SkyDir dirZ(m_position.unit());
00370 SkyDir dirX(dirZ.ra()-90., 0.0);
00371
00372
00373 dirX().rotate(dirZ.dir() , inclination*cos(orbitPhase));
00374
00375
00376 m_RAZenith = dirZ.ra();
00377 m_DECZenith = dirZ.dec();
00378
00379
00380
00381
00382
00383
00384
00385
00386 double rockNorth = m_rockDegrees*M_PI/180;
00387
00388
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
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
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
00411
00412
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 }