Go to the documentation of this file.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 #ifdef _MSC_VER
00035 #ifndef NOMINMAX
00036 #define NOMINMAX
00037 #endif
00038 #endif
00039
00040 #include "ros/time.h"
00041 #include "ros/impl/time.h"
00042 #include <cmath>
00043 #include <ctime>
00044 #include <iomanip>
00045 #include <stdexcept>
00046 #include <limits>
00047
00048 #include <boost/thread/mutex.hpp>
00049 #include <boost/io/ios_state.hpp>
00050 #include <boost/date_time/posix_time/ptime.hpp>
00051
00052
00053
00054
00055
00056
00057
00058 #define HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L)
00059
00060
00061
00062
00063
00064 namespace ros
00065 {
00066
00067
00068
00069
00070
00071 const Duration DURATION_MAX(std::numeric_limits<int32_t>::max(), 999999999);
00072 const Duration DURATION_MIN(std::numeric_limits<int32_t>::min(), 0);
00073
00074 const Time TIME_MAX(std::numeric_limits<uint32_t>::max(), 999999999);
00075 const Time TIME_MIN(0, 1);
00076
00077
00078
00079 static bool g_stopped(false);
00080
00081
00082
00083 static boost::mutex g_sim_time_mutex;
00084
00085 static bool g_initialized(false);
00086 static bool g_use_sim_time(true);
00087 static Time g_sim_time(0, 0);
00088
00089
00090
00091
00092
00093
00094
00095
00096 void ros_walltime(uint32_t& sec, uint32_t& nsec)
00097 #ifndef WIN32
00098 throw(NoHighPerformanceTimersException)
00099 #endif
00100 {
00101 #ifndef WIN32
00102 #if HAS_CLOCK_GETTIME
00103 timespec start;
00104 clock_gettime(CLOCK_REALTIME, &start);
00105 sec = start.tv_sec;
00106 nsec = start.tv_nsec;
00107 #else
00108 struct timeval timeofday;
00109 gettimeofday(&timeofday,NULL);
00110 sec = timeofday.tv_sec;
00111 nsec = timeofday.tv_usec * 1000;
00112 #endif
00113 #else
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 static LARGE_INTEGER cpu_freq, init_cpu_time;
00125 static uint32_t start_sec = 0;
00126 static uint32_t start_nsec = 0;
00127 if ( ( start_sec == 0 ) && ( start_nsec == 0 ) )
00128 {
00129 QueryPerformanceFrequency(&cpu_freq);
00130 if (cpu_freq.QuadPart == 0) {
00131 throw NoHighPerformanceTimersException();
00132 }
00133 QueryPerformanceCounter(&init_cpu_time);
00134
00135 FILETIME ft;
00136 GetSystemTimeAsFileTime(&ft);
00137 LARGE_INTEGER start_li;
00138 start_li.LowPart = ft.dwLowDateTime;
00139 start_li.HighPart = ft.dwHighDateTime;
00140
00141
00142 #ifdef _MSC_VER
00143 start_li.QuadPart -= 116444736000000000Ui64;
00144 #else
00145 start_li.QuadPart -= 116444736000000000ULL;
00146 #endif
00147 start_sec = (uint32_t)(start_li.QuadPart / 10000000);
00148 start_nsec = (start_li.LowPart % 10000000) * 100;
00149 }
00150 LARGE_INTEGER cur_time;
00151 QueryPerformanceCounter(&cur_time);
00152 LARGE_INTEGER delta_cpu_time;
00153 delta_cpu_time.QuadPart = cur_time.QuadPart - init_cpu_time.QuadPart;
00154
00155
00156 double d_delta_cpu_time = delta_cpu_time.QuadPart / (double) cpu_freq.QuadPart;
00157 uint32_t delta_sec = (uint32_t) floor(d_delta_cpu_time);
00158 uint32_t delta_nsec = (uint32_t) boost::math::round((d_delta_cpu_time-delta_sec) * 1e9);
00159
00160 int64_t sec_sum = (int64_t)start_sec + (int64_t)delta_sec;
00161 int64_t nsec_sum = (int64_t)start_nsec + (int64_t)delta_nsec;
00162
00163
00164 normalizeSecNSecUnsigned(sec_sum, nsec_sum);
00165
00166 sec = sec_sum;
00167 nsec = nsec_sum;
00168 #endif
00169 }
00173 int ros_nanosleep(const uint32_t &sec, const uint32_t &nsec)
00174 {
00175 #if defined(WIN32)
00176 HANDLE timer = NULL;
00177 LARGE_INTEGER sleepTime;
00178 sleepTime.QuadPart = -
00179 static_cast<int64_t>(sec)*10000000LL -
00180 static_cast<int64_t>(nsec) / 100LL;
00181
00182 timer = CreateWaitableTimer(NULL, TRUE, NULL);
00183 if (timer == NULL)
00184 {
00185 return -1;
00186 }
00187
00188 if (!SetWaitableTimer (timer, &sleepTime, 0, NULL, NULL, 0))
00189 {
00190 return -1;
00191 }
00192
00193 if (WaitForSingleObject (timer, INFINITE) != WAIT_OBJECT_0)
00194 {
00195 return -1;
00196 }
00197 return 0;
00198 #else
00199 timespec req = { sec, nsec };
00200 return nanosleep(&req, NULL);
00201 #endif
00202 }
00203
00209 bool ros_wallsleep(uint32_t sec, uint32_t nsec)
00210 {
00211 #if defined(WIN32)
00212 ros_nanosleep(sec,nsec);
00213 #else
00214 timespec req = { sec, nsec };
00215 timespec rem = {0, 0};
00216 while (nanosleep(&req, &rem) && !g_stopped)
00217 {
00218 req = rem;
00219 }
00220 #endif
00221 return !g_stopped;
00222 }
00223
00224
00225
00226
00227
00228 bool Time::useSystemTime()
00229 {
00230 return !g_use_sim_time;
00231 }
00232
00233 bool Time::isSimTime()
00234 {
00235 return g_use_sim_time;
00236 }
00237
00238 bool Time::isSystemTime()
00239 {
00240 return !isSimTime();
00241 }
00242
00243 Time Time::now()
00244 {
00245 if (!g_initialized)
00246 {
00247 throw TimeNotInitializedException();
00248 }
00249
00250 if (g_use_sim_time)
00251 {
00252 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00253 Time t = g_sim_time;
00254 return t;
00255 }
00256
00257 Time t;
00258 ros_walltime(t.sec, t.nsec);
00259
00260 return t;
00261 }
00262
00263 void Time::setNow(const Time& new_now)
00264 {
00265 boost::mutex::scoped_lock lock(g_sim_time_mutex);
00266
00267 g_sim_time = new_now;
00268 g_use_sim_time = true;
00269 }
00270
00271 void Time::init()
00272 {
00273 g_stopped = false;
00274 g_use_sim_time = false;
00275 g_initialized = true;
00276 }
00277
00278 void Time::shutdown()
00279 {
00280 g_stopped = true;
00281 }
00282
00283 bool Time::isValid()
00284 {
00285 return (!g_use_sim_time) || !g_sim_time.isZero();
00286 }
00287
00288 bool Time::waitForValid()
00289 {
00290 return waitForValid(ros::WallDuration());
00291 }
00292
00293 bool Time::waitForValid(const ros::WallDuration& timeout)
00294 {
00295 ros::WallTime start = ros::WallTime::now();
00296 while (!isValid() && !g_stopped)
00297 {
00298 ros::WallDuration(0.01).sleep();
00299
00300 if (timeout > ros::WallDuration(0, 0) && (ros::WallTime::now() - start > timeout))
00301 {
00302 return false;
00303 }
00304 }
00305
00306 if (g_stopped)
00307 {
00308 return false;
00309 }
00310
00311 return true;
00312 }
00313
00314 Time Time::fromBoost(const boost::posix_time::ptime& t)
00315 {
00316 boost::posix_time::time_duration diff = t - boost::posix_time::from_time_t(0);
00317 return Time::fromBoost(diff);
00318 }
00319
00320 Time Time::fromBoost(const boost::posix_time::time_duration& d)
00321 {
00322 Time t;
00323 t.sec = d.total_seconds();
00324 #if defined(BOOST_DATE_TIME_HAS_NANOSECONDS)
00325 t.nsec = d.fractional_seconds();
00326 #else
00327 t.nsec = d.fractional_seconds()*1000;
00328 #endif
00329 return t;
00330 }
00331
00332 std::ostream& operator<<(std::ostream& os, const Time &rhs)
00333 {
00334 boost::io::ios_all_saver s(os);
00335 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00336 return os;
00337 }
00338
00339 std::ostream& operator<<(std::ostream& os, const Duration& rhs)
00340 {
00341 boost::io::ios_all_saver s(os);
00342 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00343 return os;
00344 }
00345
00346 bool Time::sleepUntil(const Time& end)
00347 {
00348 if (Time::useSystemTime())
00349 {
00350 Duration d(end - Time::now());
00351 if (d > Duration(0))
00352 {
00353 return d.sleep();
00354 }
00355
00356 return true;
00357 }
00358 else
00359 {
00360 Time start = Time::now();
00361 while (!g_stopped && (Time::now() < end))
00362 {
00363 ros_nanosleep(0,1000000);
00364 if (Time::now() < start)
00365 {
00366 return false;
00367 }
00368 }
00369
00370 return true;
00371 }
00372 }
00373
00374 bool WallTime::sleepUntil(const WallTime& end)
00375 {
00376 WallDuration d(end - WallTime::now());
00377 if (d > WallDuration(0))
00378 {
00379 return d.sleep();
00380 }
00381
00382 return true;
00383 }
00384
00385 bool Duration::sleep() const
00386 {
00387 if (Time::useSystemTime())
00388 {
00389 return ros_wallsleep(sec, nsec);
00390 }
00391 else
00392 {
00393 Time start = Time::now();
00394 Time end = start + *this;
00395 if (start.isZero())
00396 {
00397 end = TIME_MAX;
00398 }
00399
00400 while (!g_stopped && (Time::now() < end))
00401 {
00402 ros_wallsleep(0, 1000000);
00403
00404
00405
00406 if (start.isZero())
00407 {
00408 start = Time::now();
00409 end = start + *this;
00410 }
00411
00412
00413 if (Time::now() < start)
00414 {
00415 return false;
00416 }
00417 }
00418
00419 return true;
00420 }
00421 }
00422
00423 std::ostream &operator<<(std::ostream& os, const WallTime &rhs)
00424 {
00425 boost::io::ios_all_saver s(os);
00426 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00427 return os;
00428 }
00429
00430 WallTime WallTime::now()
00431 {
00432 WallTime t;
00433 ros_walltime(t.sec, t.nsec);
00434
00435 return t;
00436 }
00437
00438 std::ostream &operator<<(std::ostream& os, const WallDuration& rhs)
00439 {
00440 boost::io::ios_all_saver s(os);
00441 os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
00442 return os;
00443 }
00444
00445 bool WallDuration::sleep() const
00446 {
00447 return ros_wallsleep(sec, nsec);
00448 }
00449
00450 void normalizeSecNSec(uint64_t& sec, uint64_t& nsec)
00451 {
00452 uint64_t nsec_part = nsec % 1000000000UL;
00453 uint64_t sec_part = nsec / 1000000000UL;
00454
00455 if (sec + sec_part > UINT_MAX)
00456 throw std::runtime_error("Time is out of dual 32-bit range");
00457
00458 sec += sec_part;
00459 nsec = nsec_part;
00460 }
00461
00462 void normalizeSecNSec(uint32_t& sec, uint32_t& nsec)
00463 {
00464 uint64_t sec64 = sec;
00465 uint64_t nsec64 = nsec;
00466
00467 normalizeSecNSec(sec64, nsec64);
00468
00469 sec = (uint32_t)sec64;
00470 nsec = (uint32_t)nsec64;
00471 }
00472
00473 void normalizeSecNSecUnsigned(int64_t& sec, int64_t& nsec)
00474 {
00475 int64_t nsec_part = nsec % 1000000000L;
00476 int64_t sec_part = sec + nsec / 1000000000L;
00477 if (nsec_part < 0)
00478 {
00479 nsec_part += 1000000000L;
00480 --sec_part;
00481 }
00482
00483 if (sec_part < 0 || sec_part > UINT_MAX)
00484 throw std::runtime_error("Time is out of dual 32-bit range");
00485
00486 sec = sec_part;
00487 nsec = nsec_part;
00488 }
00489
00490 template class TimeBase<Time, Duration>;
00491 template class TimeBase<WallTime, WallDuration>;
00492 }
00493
00494