00001 ////////////////////////////////////////////////////////////////////////////////////////////////// 00002 /*! \file Time.h 00003 * \brief Encapsulation of the Time object, the global time instance, and time functions. 00004 * \author $Author: cakinli $ 00005 * \version $Revision: 1.1.1.1 $ 00006 * \date $Date: 2005/04/26 17:41:01 $ 00007 *////////////////////////////////////////////////////////////////////////////////////////////////// 00008 /* \todo Finish implementing the rest of the time representatins. 00009 */ 00010 ////////////////////////////////////////////////////////////////////////////////////////////////// 00011 00012 #ifndef __SSF_TIME_H__ 00013 #define __SSF_TIME_H__ 00014 #include <time.h> 00015 #include <sys/time.h> 00016 #include <math.h> 00017 #include <iostream> 00018 #include <iomanip> 00019 00020 #include "MathUtils.h" 00021 00022 // 00023 // If <time.h> didn't define timegm()... 00024 #if !defined(timegm) 00025 // 00026 // ... Then declare a function that emulates timegm(). This function doesn't 00027 // have public documentation (doxygen) because we don't want anybody to call 00028 // it explicitly. When people call timegm(), we'll redefine it as a 00029 // mktime_from_utc() call only where necessary. 00030 time_t mktime_from_utc(struct tm *t); 00031 #define timegm(T) mktime_from_utc(T) 00032 #endif 00033 00034 namespace O_SESSAME { 00035 ////////////////////////////////////////////////////////////////////////////////////////////////// 00036 /*! @defgroup Utilies Utilities 00037 * The Utilities are the collection of classes and function that can provide miscellaneous functionality 00038 * to assist with the spacecraft simulation. This includes a time object, plotting, timing of execution 00039 * speed, interface to lower-level software and operating system components and general math functions. 00040 * 00041 * \par Extension Points: 00042 * Any other operating system calls should be encapsulated in a utility class/function to 00043 * ease the use of the tool/call and help promote cross-platform compatability. This may include 00044 * file storage and retrieval functions, communications protocols, or database interoperability. 00045 */ 00046 00047 /*! @defgroup TimeUtils Time Utilities 00048 * \ingroup Utilities 00049 * @{ 00050 */ 00051 typedef double ssfSeconds; /*< Simulation representation of seconds \ingroup Utilities*/ 00052 typedef double ssfJulianDate; /*< Simulation representation of Julian Dates \ingroup Utilities */ 00053 00054 #define TIME_PRECISION 15 /*< Precision of time output when outputting seconds */ 00055 /*! @} */ 00056 00057 class ssfTime; 00058 00059 /*! \brief Simulation Time object 00060 * \ingroup TimeUtils 00061 * 00062 * ssfTime is used to encapsulate a representation of time and provide the 00063 * functionality for converting between different time representations (ie 00064 * Mean Solar, Sidereal, Julian Date, etc.) The ssfTime object includes both 00065 * a stored time, as well as an epoch that the time can be measured from. 00066 * \par Example: 00067 * \code 00068 * ssfTime simTime; 00069 * ssfSeconds integrationTime = 10; 00070 * simTime.Set(integrationTime); 00071 * 00072 * ssfTime nowTime(Now()); 00073 * \endcode 00074 */ 00075 class ssfTime 00076 { 00077 public: 00078 /*! \brief Default constructor. Initializes the time to 0 seconds. */ 00079 ssfTime() 00080 {Set(ssfSeconds(0)); SetEpoch(ssfSeconds(0));}; 00081 /*! \brief Constructor creates a time object as a copy of a time struct. 00082 * @param _Time tm struct to be copied as the time object. 00083 */ 00084 ssfTime(tm _Time) 00085 {Set(_Time);}; 00086 /*! \brief Constructor creates a time object as a copy of a timeval struct. 00087 * 00088 * 00089 *struct timeval { 00090 * long tv_sec; // seconds 00091 * long tv_usec; // and microseconds 00092 * }; 00093 * @param _Time timeval struct to be copied as the time object. 00094 */ 00095 ssfTime(timeval _Time) 00096 {Set(_Time);}; 00097 /*! \brief Constructor creates time object based on number of seconds. 00098 * @param _Time number of seconds to set the time object to. 00099 */ 00100 ssfTime(ssfSeconds _Time) 00101 {Set(_Time);}; 00102 00103 /*! \brief Constructor creates time object based on a calendar date. 00104 * @param year 4-digit year (must be between 1900-2100) 00105 * @param month numeric month (1-12) 00106 * @param day day of the month (1-31) 00107 * @param hour hour in 24-hour format (0-23) 00108 * @param minute minutes of the hour (0-59) 00109 * @param seconds seconds of the minute (0-59.9999999999) 00110 */ 00111 ssfTime(int year, int month, int day, int hour, int minute, double seconds) 00112 {Set(year, month, day, hour, minute, seconds);}; 00113 00114 /*! \brief Set the ssfTime object to a specified time struct. 00115 * @param _newTime the time to store in a tm struct 00116 */ 00117 void Set(tm _newTime) 00118 {Set(static_cast<ssfSeconds>(timegm(&_newTime)));}; 00119 00120 /*! \brief Set the time object as a copy of a timeval struct. 00121 * 00122 * 00123 * struct timeval { 00124 * long tv_sec; // seconds 00125 * long tv_usec; // and microseconds 00126 * }; 00127 * @param _Time timeval struct to set the time object. 00128 */ 00129 void Set(timeval _Time) 00130 {Set(_Time.tv_sec + _Time.tv_usec/1000000.);}; 00131 00132 /*! \brief Set the ssfTime object to a specified time in seconds. 00133 * 00134 * @param _newTime the time to store 00135 */ 00136 void Set(ssfSeconds _newTime) 00137 {m_StoredTime = _newTime;}; 00138 00139 /*! \brief Set the ssfTime object to a specified Julian Date. 00140 * @param _newJD Julian Date to set. 00141 */ 00142 void SetJulianDate(ssfJulianDate _newJD); 00143 00144 /*! \brief Set the Epoch to a specified Julian Date. 00145 * @param _newJD Julian Date to set. 00146 */ 00147 void SetEpochJulianDate(ssfJulianDate _newJD); 00148 00149 /*! \brief Set the ssfTime object based on a calendar date. 00150 * @param year 4-digit year (must be between 1900-2100) 00151 * @param month numeric month (1-12) 00152 * @param day day of the month (1-31) 00153 * @param hour hour in 24-hour format (0-23) 00154 * @param minute minutes of the hour (0-59) 00155 * @param seconds seconds of the minute (0-59.9999999999) 00156 */ 00157 void Set(int year, int month, int day, int hour, int minute, double seconds); 00158 00159 /*! \brief Set the current time after epoch. 00160 * @param _timeAfter time (in seconds) after epoch 00161 */ 00162 void SetTimeAfterEpoch(ssfSeconds _timeAfter) 00163 {Set(m_EpochTime + _timeAfter);}; 00164 00165 /*! \brief Set the epoch time 00166 * @param _newEpochTime new Epoch (seconds) 00167 */ 00168 void SetEpoch(ssfSeconds _newEpochTime) 00169 {m_EpochTime = _newEpochTime;}; 00170 00171 /*! \brief Set the epoch time 00172 * @param _newEpochTime new Epoch (tm struct) 00173 */ 00174 void SetEpoch(tm _newEpochTime) 00175 {SetEpoch(static_cast<ssfSeconds>(timegm(&_newEpochTime)));}; 00176 00177 /*! \brief Set the epoch time from a timeval struct. 00178 * 00179 * 00180 * struct timeval { 00181 * long tv_sec; // seconds 00182 * long tv_usec; // and microseconds 00183 * }; 00184 * @param _Time timeval struct used to set the Epoch time. 00185 */ 00186 void SetEpoch(const timeval &_Time) 00187 {SetEpoch(_Time.tv_sec + _Time.tv_usec/1000000.);}; 00188 00189 /*! \brief Set the epoch of the ssfTime object based on a calendar date. 00190 * @param year 4-digit year (must be between 1900-2100) 00191 * @param month numeric month (1-12) 00192 * @param day day of the month (1-31) 00193 * @param hour hour in 24-hour format (0-23) 00194 * @param minute minutes of the hour (0-59) 00195 * @param seconds seconds of the minute (0-59.9999999999) 00196 */ 00197 void SetEpoch(int year, int month, int day, int hour, int minute, double seconds); 00198 00199 /*! \brief Return the current time in seconds 00200 * @return currently stored time (seconds) 00201 */ 00202 ssfSeconds GetSeconds() const 00203 {return m_StoredTime;}; 00204 00205 /*! \brief Return a tm struct of the date, time of the stored time. 00206 * @return tm struct of the date-time 00207 * @em tm Struct Definition: 00208 \code 00209 * int tm_sec; // seconds (0 - 60) 00210 * int tm_min; // minutes (0 - 59) 00211 * int tm_hour; // hours (0 - 23) 00212 * int tm_mday; // day of month (1 - 31) 00213 * int tm_mon; // month of year (0 - 11) 00214 * int tm_year; // year - 1900 00215 * int tm_wday; // day of week (Sunday = 0) 00216 * int tm_yday; // day of year (0 - 365) 00217 * int tm_isdst; // is summer time in effect? 00218 * char *tm_zone; // abbreviation of timezone name 00219 * long tm_gmtoff; // offset from UTC in seconds 00220 \endcode 00221 * \par Example: 00222 * \code 00223 * cout << myTime.GetDateTime().tm_mon << "/" << myTime.GetEpochDateTime().tm_mday << "/" << myTime.GetEpochDateTime().tm_year; 00224 * \endcode 00225 * \warning does not return sub-seconds (rounded to lowest second) 00226 */ 00227 tm GetDateTime() const 00228 {time_t t = static_cast<time_t>(floor(m_StoredTime));return *gmtime(&t);}; 00229 00230 /*! \brief Return the epoch in a tm struct of the date-time . 00231 * @return tm struct of the date-time. 00232 * 00233 * @em tm Struct Definition: 00234 \code 00235 * int tm_sec; // seconds (0 - 60) 00236 * int tm_min; // minutes (0 - 59) 00237 * int tm_hour; // hours (0 - 23) 00238 * int tm_mday; // day of month (1 - 31) 00239 * int tm_mon; // month of year (0 - 11) 00240 * int tm_year; // year - 1900 00241 * int tm_wday; // day of week (Sunday = 0) 00242 * int tm_yday; // day of year (0 - 365) 00243 * int tm_isdst; // is summer time in effect? 00244 * char *tm_zone; // abbreviation of timezone name 00245 * long tm_gmtoff; // offset from UTC in seconds 00246 \endcode 00247 * \par Example: 00248 * \code 00249 * cout << myTime.GetEpochDateTime().tm_mon << "/" << myTime.GetEpochDateTime().tm_mday << "/" << myTime.GetEpochDateTime().tm_year; 00250 * \endcode 00251 * \warning does not return sub-seconds (rounded to lowest second) 00252 */ 00253 tm GetEpochDateTime() const 00254 {time_t t = static_cast<time_t>(floor(m_EpochTime));return *gmtime(&t);}; 00255 00256 /*! \brief Return the current Epoch 00257 * @return currently stored epoch time (tm struct) 00258 */ 00259 ssfSeconds GetEpoch() const 00260 {return m_EpochTime;}; 00261 00262 00263 /*! \brief Get the Julian Date of the time object. 00264 * @return This function returns the Julian Date (DETAIL JD OUTPUT) 00265 */ 00266 ssfJulianDate GetJulianDate() const; 00267 00268 /*! \brief Get the Julian Date of the time object's epoch. 00269 * @return This function returns the Epoch in Julian Date format (DETAIL JD OUTPUT) 00270 */ 00271 ssfJulianDate GetEpochJulianDate() const; 00272 00273 00274 /*! \brief Calculate the Greenwich sidereal time of the stored time. 00275 * @return Greenwich sidereal time, measured from epoch in 1970, [rad] 00276 */ 00277 Angle GetGreenwichMeanSiderealTime() const; 00278 00279 /*! \brief Get the Julian Date of the time object's epoch. 00280 * 00281 * ref Vallado p.61-63 00282 * \warning need to change to accept different epochs & account for rotation of central body 00283 * @return Greenwich sidereal time of the epoch, measured from epoch in 1970, [rad] 00284 */ 00285 Angle GetEpochGreenwichMeanSiderealTime() const; 00286 00287 /*! \brief Return the current Epoch 00288 * 00289 * ref Vallado p.61-63 00290 * \warning need to change to accept different epochs & account for rotation of central body 00291 * @return currently stored epoch time (tm struct) 00292 */ 00293 // tm GetEpoch() const 00294 // {return *gmtime(&m_EpochTime);}; 00295 00296 /*! \brief Return the time since epoch 00297 * @return the number of seconds that have passed since epoch 00298 */ 00299 ssfSeconds SecondsSinceEpoch() const 00300 {return static_cast<ssfSeconds>(m_StoredTime - m_EpochTime);}; 00301 00302 /*! \brief Add specified number of seconds to the current time and return a new object. 00303 * @param rhsSeconds Number of seconds to be added. 00304 * @return new Time object whose current time is equal to the original time plus rhsSeconds. 00305 */ 00306 ssfTime operator+ (const int& rhsSeconds) const 00307 {return operator+(static_cast<ssfSeconds>(rhsSeconds));}; 00308 00309 /*! \brief Add specified number of seconds to the current time. 00310 * @param rhsSeconds Number of seconds to be added. 00311 * @return the same time object with the current time plus rhsSeconds. 00312 */ 00313 ssfTime operator+= (const int& rhsSeconds) 00314 {return operator+=(static_cast<ssfSeconds>(rhsSeconds));}; 00315 00316 /*! \brief Add specified number of seconds to the current time and return a new object. 00317 * @param rhsSeconds Number of seconds to be added. 00318 * @return new Time object whose current time is equal to the original time plus rhsSeconds. 00319 */ 00320 ssfTime operator+ (const long& rhsSeconds) const 00321 {return operator+(static_cast<ssfSeconds>(rhsSeconds));}; 00322 00323 /*! \brief Add specified number of seconds to the current time. 00324 * @param rhsSeconds Number of seconds to be added. 00325 * @return the same time object with the current time plus rhsSeconds. 00326 */ 00327 ssfTime operator+= (const long& rhsSeconds) 00328 {return operator+=(static_cast<ssfSeconds>(rhsSeconds));}; 00329 00330 /*! \brief Add specified number of seconds to the current time and return a new object. 00331 * @param rhsSeconds Number of seconds to be added. 00332 * @return new Time object whose current time is equal to the original time plus rhsSeconds. 00333 */ 00334 ssfTime operator+ (const ssfSeconds& rhsSeconds) const 00335 {return ssfTime(m_StoredTime + rhsSeconds);}; 00336 00337 /*! \brief Add specified number of seconds to the current time. 00338 * @param rhsSeconds Number of seconds to be added. 00339 * @return the same time object with the current time plus rhsSeconds. 00340 */ 00341 ssfTime operator+= (const ssfSeconds& rhsSeconds) 00342 {m_StoredTime += rhsSeconds; return *this;}; 00343 00344 /*! \brief Subtract two time objects (the stored times). 00345 * @param rhs time object to be subtracted. 00346 * @return new time object that is the difference between the lhs and the rhs. 00347 */ 00348 ssfSeconds operator- (const ssfTime &rhs) const 00349 {return (m_StoredTime - rhs.GetSeconds());}; 00350 00351 /*! \brief Greater than comparison two time objects (the stored times). 00352 * @param rhs time object to be compared with. 00353 * @return TRUE if the left operand's stored time is greater than the right operand's stored time, FALSE if it is not. 00354 */ 00355 bool operator> (const ssfTime &rhs) const 00356 {return (m_StoredTime > rhs.GetSeconds());}; 00357 00358 /*! \brief Greater than or equal comparison two time objects (the stored times). 00359 * @param rhs time object to be compared with. 00360 * @return TRUE if the left operand's stored time is greater than or equal to the right operand's stored time, FALSE if it is not. 00361 */ 00362 bool operator>= (const ssfTime &rhs) const 00363 {return (m_StoredTime >= rhs.GetSeconds());}; 00364 00365 /*! \brief Less than comparison two time objects (the stored times). 00366 * @param rhs time object to be compared with. 00367 * @return TRUE if the left operand's stored time is less than the right operand's stored time, FALSE if it is not. 00368 */ 00369 bool operator< (const ssfTime &rhs) const 00370 {return (m_StoredTime < rhs.GetSeconds());}; 00371 00372 /*! \brief Less than or equal comparison two time objects (the stored times). 00373 * @param rhs time object to be compared with. 00374 * @return TRUE if the left operand's stored time is Less than or equal to the right operand's stored time, FALSE if it is not. 00375 */ 00376 bool operator<= (const ssfTime &rhs) const 00377 {return (m_StoredTime <= rhs.GetSeconds());}; 00378 00379 /*! \brief Compare the equality of two time objects (the stored times). 00380 * @param rhs time object to be compared with. 00381 * @return TRUE if the stored times are equal, FALSE if they are not. 00382 * \todo Determine if it needs to compare the Epoch times as well. 00383 */ 00384 bool operator== (const ssfTime &rhs) const 00385 {return (m_StoredTime == rhs.GetSeconds());}; 00386 00387 /*! \brief Compare the inequality of two time objects (the stored times). 00388 * @param rhs time object to be compared with. 00389 * @return TRUE if the stored times are not equal, FALSE if they are equal. 00390 * \todo Determine if it needs to compare the Epoch times as well. 00391 */ 00392 bool operator!= (const ssfTime &rhs) const 00393 {return (m_StoredTime != rhs.GetSeconds());}; 00394 00395 /*! \brief output the time in seconds format 00396 */ 00397 friend std::ostream & operator << (std::ostream& s, ssfTime& t); 00398 private: 00399 ssfSeconds m_StoredTime; /*!< Internally stored time (seconds) */ 00400 ssfSeconds m_EpochTime; /*!< Internatlly stored Epoch time (seconds) */ 00401 00402 }; 00403 00404 /*! \brief time used as epoch for measuring Greenwich sidereal time. 00405 * 00406 * 00407 */ 00408 static const ssfTime c_GreenwichSiderealEpochTime = ssfTime(1970,1,1,0,0,0); 00409 /*! actual Greenwich sidereal time at the specified epoch, m_GreenwichSiderealEpochTime. */ 00410 static const Angle c_GreenwichSiderealTimeAtEpoch = 1.74933340; 00411 00412 /*! \brief Returns the current time in seconds since Midnight GMT, January 1st, 1970. 00413 * \ingroup TimeUtils 00414 * \relates Time 00415 * @return number of seconds since Midnight UTC, January 1st, 1970 00416 */ 00417 inline ssfSeconds Now() 00418 {timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec + tv.tv_usec/1000000.);} 00419 // {return time((time_t *)0);}; 00420 00421 00422 /*! \brief Initializes the tick/tock counter 00423 * \ingroup TimeUtils 00424 * \relates Time 00425 * 00426 * Used for calculating the time during operations. First tick() is called, then 00427 * when the operation has been completed tock() is called which returns the time (in seconds) 00428 * since tick() was called. 00429 * \sa tock() 00430 \code 00431 tick(); 00432 for (int ii = 0; ii < 10; ++ii) { 00433 ii += ii*ii; 00434 } 00435 cout << tock(); 00436 \endcode 00437 * the sample code would output the time it took to calculate \f$\sum{ii^2}\f$ to the console. 00438 */ 00439 static ssfTime tickTime(-1); /*< global variable used to store the initial tick() time */ 00440 static ssfTime tockTime(-1); /*< global variable used to store the ending tock() time */ 00441 00442 inline void tick() 00443 { 00444 tickTime.Set(Now()); 00445 return; 00446 } 00447 /*! \brief Stops the tick/tock counter and returns the time (in seconds) since tick() was called. 00448 * \ingroup TimeUtils 00449 * \relates Time 00450 * \sa tick() 00451 */ 00452 inline ssfSeconds tock() 00453 { 00454 if(tickTime.GetSeconds() > -1) 00455 { 00456 tockTime.Set(Now()); 00457 return tockTime-tickTime; 00458 } 00459 else 00460 return -1; 00461 } 00462 00463 /*! \brief Converts the day of the year (1-365) (given a year) to the Month and Day of they year 00464 * \ingroup TimeUtils 00465 * \relates Time 00466 */ 00467 void DayofYear2YMD(int _dayOfYear, int _year, int &_month, int &_day); 00468 00469 } // close namespace O_SESSAME 00470 00471 #endif 00472 00473 // Do not change the comments below - they will be added automatically by CVS 00474 /***************************************************************************** 00475 * $Log: Time.h,v $ 00476 * Revision 1.1.1.1 2005/04/26 17:41:01 cakinli 00477 * Adding OpenSESSAME to DSACSS distrib to capture fixed version. 00478 * 00479 * Revision 1.15 2003/10/18 21:54:44 rsharo 00480 * Fixed CF-LF problem and added missing comment. 00481 * 00482 * Revision 1.14 2003/10/18 21:37:29 rsharo 00483 * Removed "../utils" from all qmake project paths. Prepended "utils 00484 * /" to all #include directives for utils. Removed ".h" extensions from STL header 00485 * s and referenced STL components from "std::" namespace. Overall, changed to be 00486 * more portable. 00487 * 00488 * Revision 1.13 2003/06/11 14:22:34 nilspace 00489 * Added comments to GetDateTime() and GetEpochDateTime() 00490 * 00491 * Revision 1.12 2003/06/10 01:11:46 nilspace 00492 * Fixed Time to build correctly (changed Greenwich epoch time to object instead of pointer) 00493 * 00494 * Revision 1.11 2003/06/09 19:41:30 nilspace 00495 * Added SetEpoch(year,month,day,hour,minute,second) 00496 * 00497 * Revision 1.10 2003/06/06 00:34:47 nilspace 00498 * ? 00499 * 00500 * Revision 1.9 2003/05/21 03:57:52 nilspace 00501 * Added GetEpochJulianDate and comments to JulianDate conversion function. 00502 * 00503 * Revision 1.8 2003/05/19 21:19:49 nilspace 00504 * Made calls to overloaded Set() and SetEpoch() functions recursive calls to Set(ssfSeconds) and SetEpoch(ssfSeconds) 00505 * 00506 * Revision 1.7 2003/05/19 19:21:37 nilspace 00507 * Added #include<sys/time.h> 00508 * 00509 * Revision 1.6 2003/05/16 14:01:24 nilspace 00510 * Called gettimeofday(timeval*) to have Now(), and tick/tock return seconds with subsecond decimal parts. 00511 * 00512 * Revision 1.5 2003/05/09 23:44:29 nilspace 00513 * Added operator!=() 00514 * 00515 * Revision 1.4 2003/04/30 16:32:48 nilspace 00516 * Added operator== to ssfTime 00517 * 00518 * Revision 1.3 2003/04/27 22:04:34 nilspace 00519 * Created the namespace O_SESSAME. 00520 * 00521 * Revision 1.2 2003/04/25 13:45:56 nilspace 00522 * const'd Get() functions. 00523 * 00524 * Revision 1.1 2003/04/23 14:14:45 nilspace 00525 * New simulation time. 00526 * 00527 * 00528 ******************************************************************************/