00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "ros/time.h"
00036 #include <cmath>
00037 #include <ctime>
00038 #include <iomanip>
00039 #include <stdexcept>
00040 #include <limits>
00041
00042 #include <boost/thread/mutex.hpp>
00043
00044
00045
00046
00047
00048
00049
00050 #define HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L)
00051
00052
00053
00054
00055
00056 namespace ros
00057 {
00058
00059
00060
00061
00062
00063 const Duration DURATION_MAX(std::numeric_limits<int32_t>::max(), 999999999);
00064 const Duration DURATION_MIN(std::numeric_limits<int32_t>::min(), 0);
00065
00066 const Time TIME_MAX(std::numeric_limits<uint32_t>::max(), 999999999);
00067 const Time TIME_MIN(0, 1);
00068
00069
00070
00071 static bool g_stopped(false);
00072
00073
00074
00075 static boost::mutex g_sim_time_mutex;
00076
00077 static bool g_initialized(false);
00078 static bool g_use_sim_time(true);
00079 static Time g_sim_time(0, 0);
00080
00081
00082
00083
00084
00085
00086
00087
00088 void ros_walltime(uint32_t& sec, uint32_t& nsec) throw(NoHighPerformanceTimersException)
00089 {
00090 #ifndef WIN32
00091 #if HAS_CLOCK_GETTIME
00092 timespec start;
00093 clock_gettime(CLOCK_REALTIME, &start);
00094 sec = start.tv_sec;
00095 nsec = start.tv_nsec;
00096 #else
00097 struct timeval timeofday;
00098 gettimeofday(&timeofday,NULL);
00099 sec = timeofday.tv_sec;
00100 nsec = timeofday.tv_usec * 1000;
00101 #endif
00102 #else
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 static LARGE_INTEGER cpu_freq, init_cpu_time;
00114 uint32_t start_sec = 0;
00115 uint32_t start_nsec = 0;
00116 if ( ( start_sec == 0 ) && ( start_nsec == 0 ) )
00117 {
00118 QueryPerformanceFrequency(&cpu_freq);
00119 if (cpu_freq.QuadPart == 0) {
00120 throw NoHighPerformanceTimersException();
00121 }
00122 QueryPerformanceCounter(&init_cpu_time);
00123
00124 FILETIME ft;
00125 GetSystemTimeAsFileTime(&ft);
00126 LARGE_INTEGER start_li;
00127 start_li.LowPart = ft.dwLowDateTime;
00128 start_li.HighPart = ft.dwHighDateTime;
00129
00130
00131 #ifdef _MSC_VER
00132 start_li.QuadPart -= 116444736000000000Ui64;
00133 #else
00134 start_li.QuadPart -= 116444736000000000ULL;
00135 #endif
00136 start_sec = (uint32_t)(start_li.QuadPart / 10000000);
00137 start_nsec = (start_li.LowPart % 10000000) * 100;
00138 }
00139 LARGE_INTEGER cur_time;
00140 QueryPerformanceCounter(&cur_time);
00141 LARGE_INTEGER delta_cpu_time;
00142 delta_cpu_time.QuadPart = cur_time.QuadPart - init_cpu_time.QuadPart;
00143
00144
00145 double d_delta_cpu_time = delta_cpu_time.QuadPart / (double) cpu_freq.QuadPart;
00146 uint32_t delta_sec = (uint32_t) floor(d_delta_cpu_time);
00147 uint32_t delta_nsec = (uint32_t) round((d_delta_cpu_time-delta_sec) * 1e9);
00148
00149 int64_t sec_sum = (int64_t)start_sec + (int64_t)delta_sec;
00150 int64_t nsec_sum = (int64_t)start_nsec + (int64_t)delta_nsec;
00151
00152
00153 normalizeSecNSecUnsigned(sec_sum, nsec_sum);
00154
00155 sec = sec_sum;
00156 nsec = nsec_sum;
00157 #endif
00158 }
00162 int ros_nanosleep(const uint32_t &sec, const uint32_t &nsec)
00163 {
00164 #if defined(WIN32)
00165 HANDLE timer = NULL;
00166 LARGE_INTEGER sleepTime;
00167 sleepTime.QuadPart = -
00168 static_cast<uint64_t>(sec)*10000000LL -
00169 static_cast<uint64_t>(nsec) / 100LL;
00170
00171 timer = CreateWaitableTimer(NULL, TRUE, NULL);
00172 if (timer == NULL)
00173 {
00174 return -1;
00175 }
00176
00177 if (!SetWaitableTimer (timer, &sleepTime, 0, NULL, NULL, 0))
00178 {
00179 return -1;
00180 }
00181
00182 if (WaitForSingleObject (timer, INFINITE) != WAIT_OBJECT_0)
00183 {
00184 return -1;
00185 }
00186 return 0;
00187 #else
00188 timespec req = { sec, nsec };
00189 return nanosleep(&req, NULL);
00190 #endif
00191 }
00192
00198 bool ros_wallsleep(uint32_t sec, uint32_t nsec)
00199 {
00200 #if defined(WIN32)
00201 ros_nanosleep(sec,nsec);
00202 #else
00203 timespec req = { sec, nsec };
00204 timespec rem = {0, 0};
00205 while (nanosleep(&req, &rem) && !g_stopped)
00206 {
00207 req = rem;
00208 }
00209 #endif
00210 return !g_stopped;
00211 }
00212
00213
00214
00215
00216
00217 bool Time::useSystemTime()
00218 {
00219 return !g_use_sim_time;
00220 }
00221
00222 bool Time::isSimTime()
00223 {
00224 return g_use_sim_time;
00225 }
00226
00227 bool Time::isSystemTime()
00228 {
00229 return !isSimTime();
00230 }
00231
00232 Time Time::now()
00233 {
00234 if (!g_initialized)
00235 {
00236 throw TimeNotInitializedException();
00237 }
00238
00239 if (g_use_sim_time)
00240 {
00241 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00242 Time t = g_sim_time;
00243 return t;
00244 }
00245
00246 Time t;
00247 ros_walltime(t.sec, t.nsec);
00248
00249 return t;
00250 }
00251
00252 void Time::setNow(const Time& new_now)
00253 {
00254 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00255
00256 g_sim_time = new_now;
00257 g_use_sim_time = true;
00258 }
00259
00260 void Time::init()
00261 {
00262 g_stopped = false;
00263 g_use_sim_time = false;
00264 g_initialized = true;
00265 }
00266
00267 void Time::shutdown()
00268 {
00269 g_stopped = true;
00270 }
00271
00272 bool Time::isValid()
00273 {
00274 return (!g_use_sim_time) || !g_sim_time.isZero();
00275 }
00276
00277 bool Time::waitForValid()
00278 {
00279 return waitForValid(ros::WallDuration());
00280 }
00281
00282 bool Time::waitForValid(const ros::WallDuration& timeout)
00283 {
00284 ros::WallTime start = ros::WallTime::now();
00285 while (!isValid() && !g_stopped)
00286 {
00287 ros::WallDuration(0.01).sleep();
00288
00289 if (timeout > ros::WallDuration(0, 0) && (ros::WallTime::now() - start > timeout))
00290 {
00291 return false;
00292 }
00293 }
00294
00295 if (g_stopped)
00296 {
00297 return false;
00298 }
00299
00300 return true;
00301 }
00302
00303 std::ostream& operator<<(std::ostream& os, const Time &rhs)
00304 {
00305 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00306 return os;
00307 }
00308
00309 std::ostream& operator<<(std::ostream& os, const Duration& rhs)
00310 {
00311 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00312 return os;
00313 }
00314
00315 bool Time::sleepUntil(const Time& end)
00316 {
00317 if (Time::useSystemTime())
00318 {
00319 Duration d(end - Time::now());
00320 if (d > Duration(0))
00321 {
00322 return d.sleep();
00323 }
00324
00325 return true;
00326 }
00327 else
00328 {
00329 Time start = Time::now();
00330 while (!g_stopped && (Time::now() < end))
00331 {
00332 ros_nanosleep(0,1000000);
00333 if (Time::now() < start)
00334 {
00335 return false;
00336 }
00337 }
00338
00339 return true;
00340 }
00341 }
00342
00343 bool WallTime::sleepUntil(const WallTime& end)
00344 {
00345 WallDuration d(end - WallTime::now());
00346 if (d > WallDuration(0))
00347 {
00348 return d.sleep();
00349 }
00350
00351 return true;
00352 }
00353
00354 bool Duration::sleep() const
00355 {
00356 if (Time::useSystemTime())
00357 {
00358 return ros_wallsleep(sec, nsec);
00359 }
00360 else
00361 {
00362 Time start = Time::now();
00363 Time end = start + *this;
00364 if (start.isZero())
00365 {
00366 end = TIME_MAX;
00367 }
00368
00369 while (!g_stopped && (Time::now() < end))
00370 {
00371 ros_wallsleep(0, 1000000);
00372
00373
00374
00375 if (start.isZero())
00376 {
00377 start = Time::now();
00378 end = start + *this;
00379 }
00380
00381
00382 if (Time::now() < start)
00383 {
00384 return false;
00385 }
00386 }
00387
00388 return true;
00389 }
00390 }
00391
00392 std::ostream &operator<<(std::ostream& os, const WallTime &rhs)
00393 {
00394 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00395 return os;
00396 }
00397
00398 WallTime WallTime::now()
00399 {
00400 WallTime t;
00401 ros_walltime(t.sec, t.nsec);
00402
00403 return t;
00404 }
00405
00406 std::ostream &operator<<(std::ostream& os, const WallDuration& rhs)
00407 {
00408 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00409 return os;
00410 }
00411
00412 bool WallDuration::sleep() const
00413 {
00414 return ros_wallsleep(sec, nsec);
00415 }
00416
00417 }