$search
00001 00002 /****************************************************************************** 00003 * 00004 * Copyright (c) 2012 00005 * 00006 * SCHUNK GmbH & Co. KG 00007 * 00008 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00009 * 00010 * Project name: Drivers for "Amtec M5 Protocol" Electronics V4 00011 * 00012 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00013 * 00014 * Email:robotics@schunk.com 00015 * 00016 * ToDo: 00017 * 00018 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00019 * 00020 * Redistribution and use in source and binary forms, with or without 00021 * modification, are permitted provided that the following conditions are met: 00022 * 00023 * * Redistributions of source code must retain the above copyright 00024 * notice, this list of conditions and the following disclaimer. 00025 * * Redistributions in binary form must reproduce the above copyright 00026 * notice, this list of conditions and the following disclaimer in the 00027 * documentation and/or other materials provided with the distribution. 00028 * * Neither the name of SCHUNK GmbH & Co. KG nor the names of its 00029 * contributors may be used to endorse or promote products derived from 00030 * this software without specific prior written permission. 00031 * 00032 * This program is free software: you can redistribute it and/or modify 00033 * it under the terms of the GNU Lesser General Public License LGPL as 00034 * published by the Free Software Foundation, either version 3 of the 00035 * License, or (at your option) any later version. 00036 * 00037 * This program is distributed in the hope that it will be useful, 00038 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00039 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00040 * GNU Lesser General Public License LGPL for more details. 00041 * 00042 * You should have received a copy of the GNU Lesser General Public 00043 * License LGPL along with this program. 00044 * If not, see <http://www.gnu.org/licenses/>. 00045 * 00046 ******************************************************************************/ 00047 00048 00049 #include "StopWatch.h" 00050 00051 // ========================================================================== ; 00052 // ; 00053 // private auxiliary functions 00054 // ; 00055 // ========================================================================== ; 00056 00057 // ========================================================================== ; 00058 // ; 00059 // protected auxiliary functions 00060 // ; 00061 // ========================================================================== ; 00062 00063 // ========================================================================= ; 00064 // ; 00065 // constructors / destructor ; 00066 // ; 00067 // ========================================================================= ; 00068 00069 CStopWatch::CStopWatch() 00070 : CMessage("CStopWatch", g_iDebugLevel, g_bDebug, g_bDebugFile), 00071 m_bStartFlag(false), 00072 m_bStopFlag(false), 00073 m_iTimeType(util_REAL_TIME) 00074 { 00075 m_iFirst = 0; 00076 m_iLast = 0; 00077 m_fOverflowTime = 0.0; 00078 00079 #if defined(_WIN32) 00080 QueryPerformanceFrequency(&m_TempTime); // pointer to current frequency 00081 frequencyE = m_TempTime.LowPart; 00082 m_FirstTime.HighPart = 0; 00083 m_FirstTime.LowPart = 0; 00084 m_LastTime.HighPart = 0; 00085 m_LastTime.LowPart = 0; 00086 m_TempTime.HighPart = 0; 00087 m_TempTime.LowPart = 0; 00088 m_ActualTime.HighPart = 0; 00089 m_ActualTime.LowPart = 0; 00090 #elif defined(__QNX__) 00091 m_FirstTime.tv_sec = 0; 00092 m_FirstTime.tv_nsec = 0; 00093 m_LastTime.tv_sec = 0; 00094 m_LastTime.tv_nsec = 0; 00095 m_TempTime.tv_sec = 0; 00096 m_TempTime.tv_nsec = 500000; 00097 clock_setres(CLOCK_REALTIME, &m_TempTime); 00098 m_ActualTime.tv_sec = 0; 00099 m_ActualTime.tv_nsec = 0; 00100 #else 00101 m_FirstTime.tv_sec = 0; 00102 m_FirstTime.tv_usec = 0; 00103 m_LastTime.tv_sec = 0; 00104 m_LastTime.tv_usec = 0; 00105 m_TempTime.tv_sec = 0; 00106 m_TempTime.tv_usec = 0; 00107 m_ActualTime.tv_sec = 0; 00108 m_ActualTime.tv_usec = 0; 00109 #endif 00110 } 00111 00112 CStopWatch::CStopWatch(util_TimeMeasurementType iTimeType) 00113 : CMessage("CStopWatch", g_iDebugLevel, g_bDebug, g_bDebugFile), 00114 m_bStartFlag(false), 00115 m_bStopFlag(false), 00116 m_iTimeType(iTimeType) 00117 { 00118 m_iFirst = 0; 00119 m_iLast = 0; 00120 m_fOverflowTime = 0.0; 00121 00122 #if defined(_WIN32) 00123 QueryPerformanceFrequency(&m_TempTime); // pointer to current frequency 00124 frequencyE = m_TempTime.LowPart; 00125 m_FirstTime.HighPart = 0; 00126 m_FirstTime.LowPart = 0; 00127 m_LastTime.HighPart = 0; 00128 m_LastTime.LowPart = 0; 00129 m_TempTime.HighPart = 0; 00130 m_TempTime.LowPart = 0; 00131 m_ActualTime.HighPart = 0; 00132 m_ActualTime.LowPart = 0; 00133 #elif defined(__QNX__) 00134 m_FirstTime.tv_sec = 0; 00135 m_FirstTime.tv_nsec = 0; 00136 m_LastTime.tv_sec = 0; 00137 m_LastTime.tv_nsec = 0; 00138 m_TempTime.tv_sec = 0; 00139 m_TempTime.tv_nsec = 500000; 00140 clock_setres(CLOCK_REALTIME, &m_TempTime); 00141 m_ActualTime.tv_sec = 0; 00142 m_ActualTime.tv_nsec = 0; 00143 #else 00144 m_FirstTime.tv_sec = 0; 00145 m_FirstTime.tv_usec = 0; 00146 m_LastTime.tv_sec = 0; 00147 m_LastTime.tv_usec = 0; 00148 m_TempTime.tv_sec = 0; 00149 m_TempTime.tv_usec = 0; 00150 m_ActualTime.tv_sec = 0; 00151 m_ActualTime.tv_usec = 0; 00152 #endif 00153 } 00154 00155 CStopWatch::CStopWatch(const CStopWatch& ) 00156 { 00157 error(-1, "copy constructor : method should not be called!"); 00158 } 00159 00160 // ========================================================================= ; 00161 // ; 00162 // operators 00163 // ; 00164 // ========================================================================= ; 00165 00166 CStopWatch& CStopWatch::operator=(const CStopWatch&) 00167 { 00168 error(-1, "assignment operator : method should not be called!"); 00169 return *this; 00170 } 00171 00172 // ========================================================================= ; 00173 // ; 00174 // query functions 00175 // ; 00176 // ========================================================================= ; 00177 00178 // ========================================================================= ; 00179 // ; 00180 // modifiy functions 00181 // ; 00182 // ========================================================================= ; 00183 00184 // ========================================================================= ; 00185 // ; 00186 // I/O 00187 // ; 00188 // ========================================================================= ; 00189 00190 /* 00191 This member function computes the difference between the taken start and stop times, if both are valid. 00192 Attention: cpu-time is calculated in a wrong way, if process lasts longer than 35 min or 2 processes 00193 are stoped with the second beginning more than half an hour after the first one was started. 00194 Look for function testOverflow in any of these cases. 00195 difference or $0.0$ if call was invalid 00196 */ 00197 double CStopWatch::executionTime() 00198 { 00199 // --- check 00200 if ( !(m_bStartFlag && m_bStopFlag) ) 00201 { 00202 warning("executionTime() : return 0.0, for you must call 'start()' and 'stop()' first"); 00203 return 0.0; 00204 }; 00205 00206 if(m_iTimeType == util_CPU_TIME) 00207 { 00208 if ((m_iLast < m_iFirst) && (m_fOverflowTime == 0)) 00209 { 00210 warning("executionTime() : return 0.0, for start time is bigger than stop time and no overflow was detected"); 00211 return 0.0; 00212 } 00213 else 00214 { 00215 double fTempTime; 00216 testOverflow(); 00217 fTempTime = m_fOverflowTime; 00218 m_fOverflowTime = 0.0; 00219 return fTempTime + (double(m_iLast - m_iFirst)) / CLOCKS_PER_SEC; 00220 }; 00221 } 00222 else 00223 { 00224 #if defined(__QNX__) 00225 return (m_LastTime.tv_sec-m_FirstTime.tv_sec 00226 +(double(m_LastTime.tv_nsec-m_FirstTime.tv_nsec)/1e+9)); 00227 #elif defined(_WIN32) 00228 return double(m_LastTime.LowPart-m_FirstTime.LowPart)/frequencyE; 00229 #else 00230 return (m_LastTime.tv_sec-m_FirstTime.tv_sec 00231 +(double(m_LastTime.tv_usec-m_FirstTime.tv_usec)/1e+6)); 00232 #endif 00233 }; 00234 }; 00235 00236 // ========================================================================= ; 00237 // ; 00238 // exec functions 00239 // ; 00240 // ========================================================================= ; 00241 00242 void CStopWatch::start() 00243 { 00244 if(m_iTimeType == util_CPU_TIME) 00245 { 00246 m_iFirst=clock(); 00247 m_bStartFlag = true; 00248 m_bStopFlag = false; 00249 } 00250 else 00251 { 00252 #if defined(__QNX__) 00253 clock_gettime(CLOCK_REALTIME,&m_FirstTime); 00254 #elif defined(_WIN32) 00255 QueryPerformanceCounter(&m_FirstTime); 00256 #else 00257 gettimeofday(&m_FirstTime,0); 00258 #endif 00259 m_bStartFlag = true; 00260 m_bStopFlag = false; 00261 }; 00262 }; 00263 00264 /* 00265 This member function sets the stop time of the watch to the current clock value, if a valid start time exists. 00266 */ 00267 void CStopWatch::stop() 00268 { 00269 if (m_bStartFlag) 00270 { 00271 if(m_iTimeType == util_CPU_TIME) 00272 { 00273 m_iLast = clock(); 00274 } 00275 else 00276 { 00277 #if defined(__QNX__) 00278 clock_gettime(CLOCK_REALTIME,&m_LastTime); 00279 #elif defined(_WIN32) 00280 QueryPerformanceCounter(&m_LastTime); 00281 #else 00282 gettimeofday(&m_LastTime,0); 00283 #endif 00284 }; 00285 m_bStopFlag = true; 00286 } 00287 else 00288 { 00289 m_bStopFlag = false; 00290 warning("stop() : you must call 'start()' first"); 00291 }; 00292 }; 00293 00294 // -------------------------------------------------------------------------- ; 00295 00296 /* 00297 This member function continues the run of the clock after is has been stopped. 00298 */ 00299 void CStopWatch::cont() 00300 { 00301 if (m_bStartFlag && m_bStopFlag) 00302 { 00303 if(m_iTimeType == util_CPU_TIME) 00304 { 00305 m_iFirst = m_iFirst + (clock() - m_iLast); 00306 m_bStopFlag = false; 00307 } 00308 else 00309 { 00310 #if defined(__QNX__) 00311 clock_gettime(CLOCK_REALTIME,&m_TempTime); 00312 m_FirstTime.tv_sec += m_TempTime.tv_sec-m_LastTime.tv_sec; 00313 m_FirstTime.tv_nsec += m_TempTime.tv_nsec-m_LastTime.tv_nsec; 00314 #elif defined(_WIN32) 00315 QueryPerformanceCounter(&m_TempTime); 00316 m_FirstTime.HighPart += m_TempTime.HighPart-m_LastTime.HighPart; 00317 m_FirstTime.LowPart += m_TempTime.LowPart-m_LastTime.LowPart; 00318 #else 00319 gettimeofday(&m_TempTime,0); 00320 m_FirstTime.tv_sec += m_TempTime.tv_sec-m_LastTime.tv_sec; 00321 m_FirstTime.tv_usec += m_TempTime.tv_usec-m_LastTime.tv_usec; 00322 #endif 00323 }; 00324 } 00325 else 00326 warning("cont() : you must call 'start()' and 'stop()' first"); 00327 }; 00328 00329 // This member function returns the current real time in [s]. 00330 double CStopWatch::realTime() 00331 { 00332 #if defined(__QNX__) 00333 clock_gettime(CLOCK_REALTIME,&m_ActualTime); 00334 return (m_ActualTime.tv_sec+(double(m_ActualTime.tv_nsec)/1e+9)); 00335 #elif defined(_WIN32) 00336 QueryPerformanceCounter(&m_ActualTime); 00337 return (double(m_ActualTime.LowPart)/frequencyE); 00338 #else 00339 gettimeofday(&m_ActualTime,0); 00340 return (m_ActualTime.tv_sec 00341 +(double(m_ActualTime.tv_usec)/1e+6)); 00342 #endif 00343 }; 00344 00345 // This member function returns the real time resolution in [s]. 00346 double CStopWatch::realTimeResolution() 00347 { 00348 #if defined(__QNX__) 00349 clock_getres(CLOCK_REALTIME,&m_TempTime); 00350 return (m_TempTime.tv_sec+(double(m_TempTime.tv_nsec)/1e+9)); 00351 #elif defined(_WIN32) 00352 warning("unkown real time resolution\n"); 00353 return 0.001; 00354 #else 00355 warning("unkown real time resolution\n"); 00356 return 0.001; 00357 #endif 00358 }; 00359 00360 /* 00361 This member function waits the given realtime in [ms]. 00362 uiTime: realtime in [ms] 00363 */ 00364 void CStopWatch::wait(unsigned int uiTime) 00365 { 00366 bool bTimeOutFlag = false; 00367 #if defined(__QNX__) 00368 unsigned int uiSec, uiNSec; 00369 uiSec = uiTime / 1000; 00370 uiNSec = (uiTime % 1000) * 1000000; 00371 clock_gettime(CLOCK_REALTIME, &m_TempTime); 00372 m_TempTime.tv_sec = m_TempTime.tv_sec + uiSec + (m_TempTime.tv_nsec + uiNSec) / 1000000000; 00373 m_TempTime.tv_nsec = (m_FirstTime.tv_nsec + uiNSec) % 1000000000; 00374 do 00375 { 00376 clock_gettime(CLOCK_REALTIME, &m_ActualTime); 00377 if(m_ActualTime.tv_sec > m_TempTime.tv_sec) 00378 bTimeOutFlag = true; 00379 else if((m_ActualTime.tv_sec == m_TempTime.tv_sec) && (m_ActualTime.tv_nsec > m_TempTime.tv_nsec)) 00380 bTimeOutFlag = true; 00381 } 00382 while(!bTimeOutFlag); 00383 #elif defined(_WIN32) 00384 Sleep(uiTime); 00385 #else 00386 unsigned int uiSec, uiUSec; 00387 uiSec = uiTime / 1000; 00388 uiUSec = (uiTime % 1000) * 1000; 00389 gettimeofday(&m_TempTime, 0); 00390 m_TempTime.tv_sec = m_TempTime.tv_sec + uiSec + (m_TempTime.tv_usec + uiUSec) / 1000000; 00391 m_TempTime.tv_usec = (m_TempTime.tv_usec + uiUSec) % 1000000; 00392 do 00393 { 00394 gettimeofday(&m_ActualTime, 0); 00395 if(m_ActualTime.tv_sec > m_TempTime.tv_sec) 00396 bTimeOutFlag = true; 00397 else if((m_ActualTime.tv_sec == m_TempTime.tv_sec) && (m_ActualTime.tv_usec > m_TempTime.tv_usec)) 00398 bTimeOutFlag = true; 00399 } 00400 while(!bTimeOutFlag); 00401 #endif 00402 }; 00403 00404 // -------------------------------------------------------------------------- ; 00405 00406 /* 00407 This member function returns the current date and time in local representation 00408 char* to hold the local date and time 00409 */ 00410 void CStopWatch::date(char* acDate) const 00411 { 00412 time_t currentTime; 00413 struct tm *localTime; 00414 00415 // get the current time 00416 currentTime = time (NULL); 00417 00418 // convert it to local time representation 00419 localTime = localtime (¤tTime); 00420 00421 // print it out in a buffer 00422 strftime (acDate, 256, "%a %b %d %I:%M:%S %p %Z %Y", localTime); 00423 }; 00424 00425 // -------------------------------------------------------------------------- ; 00426 00427 /* 00428 This member function returns the current weekday in local representation 00429 string to hold the local weekday 00430 */ 00431 void CStopWatch::weekday(char* acWeekDay) const 00432 { 00433 time_t currentTime; 00434 struct tm *localTime; 00435 00436 // get the current time 00437 currentTime = time (NULL); 00438 00439 // convert it to local time representation 00440 localTime = localtime (¤tTime); 00441 00442 // print it out in a buffer 00443 strftime (acWeekDay, 256, "%A", localTime); 00444 }; 00445 00446 // ========================================================================= ; 00447 00448 /* 00449 This function tests, if there is an overflow at the clock counter 00450 Function should be called at least every 30 min., if the cpu_time is stoped 00451 Otherwise there might be more than one overflow and results are wrong! 00452 */ 00453 void CStopWatch::testOverflow() 00454 { 00455 if(m_iTimeType == util_CPU_TIME) 00456 { 00457 stop(); 00458 if (m_iLast < m_iFirst) 00459 { 00460 m_fOverflowTime += (double(m_iLast - m_iFirst + ULONG_MAX)) / CLOCKS_PER_SEC; 00461 start(); 00462 } 00463 else 00464 cont(); 00465 } 00466 else 00467 warning("testOverflow() : overflow has to be tested only when measuring cpu-time"); 00468 }; 00469 00470 // ========================================================================= ;