time.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2010, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 #ifdef _MSC_VER
35  #ifndef NOMINMAX
36  #define NOMINMAX
37  #endif
38 #endif
39 
40 #include "ros/time.h"
41 #include "ros/impl/time.h"
42 #include <cmath>
43 #include <ctime>
44 #include <iomanip>
45 #include <stdexcept>
46 #include <limits>
47 #include <mutex>
48 #include "math.h"
49 //#include <boost/thread/mutex.hpp>
50 #include <boost/io/ios_state.hpp>
51 //#include <boost/date_time/posix_time/ptime.hpp>
52 
53 /*********************************************************************
54  ** Preprocessor
55  *********************************************************************/
56 
57 // Could probably do some better and more elaborate checking
58 // and definition here.
59 #define HAS_CLOCK_GETTIME (_POSIX_C_SOURCE >= 199309L)
60 
61 /*********************************************************************
62  ** Namespaces
63  *********************************************************************/
64 
65 namespace rs2rosinternal
66 {
67 
68  /*********************************************************************
69  ** Variables
70  *********************************************************************/
71 
72  const Duration DURATION_MAX(std::numeric_limits<int32_t>::max(), 999999999);
74 
75  const Time TIME_MAX(std::numeric_limits<uint32_t>::max(), 999999999);
76  const Time TIME_MIN(0, 1);
77 
78  // This is declared here because it's set from the Time class but read from
79  // the Duration class, and need not be exported to users of either.
80  static bool g_stopped(false);
81 
82  // I assume that this is declared here, instead of time.h, to keep users
83  // of time.h from including boost/thread/mutex.hpp
84  static std::mutex g_sim_time_mutex;
85 
86  static bool g_initialized(false);
87  static bool g_use_sim_time(true);
88  static Time g_sim_time(0, 0);
89 
90  /*********************************************************************
91  ** Cross Platform Functions
92  *********************************************************************/
93  /*
94  * These have only internal linkage to this translation unit.
95  * (i.e. not exposed to users of the time classes)
96  */
97  void ros_walltime(uint32_t& sec, uint32_t& nsec)
98 #ifndef WIN32
100 #endif
101  {
102 #ifndef WIN32
103 #if HAS_CLOCK_GETTIME
104  timespec start;
105  clock_gettime(CLOCK_REALTIME, &start);
106  sec = static_cast<uint32_t>(start.tv_sec);
107  nsec = static_cast<uint32_t>(start.tv_nsec);
108 #else
109  struct timeval timeofday;
110  gettimeofday(&timeofday,NULL);
111  sec = timeofday.tv_sec;
112  nsec = timeofday.tv_usec * 1000;
113 #endif
114 #else
115  // Win32 implementation
116  // unless I've missed something obvious, the only way to get high-precision
117  // time on Windows is via the QueryPerformanceCounter() call. However,
118  // this is somewhat problematic in Windows XP on some processors, especially
119  // AMD, because the Windows implementation can freak out when the CPU clocks
120  // down to save power. Time can jump or even go backwards. Microsoft has
121  // fixed this bug for most systems now, but it can still show up if you have
122  // not installed the latest CPU drivers (an oxymoron). They fixed all these
123  // problems in Windows Vista, and this API is by far the most accurate that
124  // I know of in Windows, so I'll use it here despite all these caveats
125  static LARGE_INTEGER cpu_freq, init_cpu_time;
126  static uint32_t start_sec = 0;
127  static uint32_t start_nsec = 0;
128  if ( ( start_sec == 0 ) && ( start_nsec == 0 ) )
129  {
130  QueryPerformanceFrequency(&cpu_freq);
131  if (cpu_freq.QuadPart == 0) {
133  }
134  QueryPerformanceCounter(&init_cpu_time);
135  // compute an offset from the Epoch using the lower-performance timer API
136  FILETIME ft;
137  GetSystemTimeAsFileTime(&ft);
138  LARGE_INTEGER start_li;
139  start_li.LowPart = ft.dwLowDateTime;
140  start_li.HighPart = ft.dwHighDateTime;
141  // why did they choose 1601 as the time zero, instead of 1970?
142  // there were no outstanding hard rock bands in 1601.
143 #ifdef _MSC_VER
144  start_li.QuadPart -= 116444736000000000Ui64;
145 #else
146  start_li.QuadPart -= 116444736000000000ULL;
147 #endif
148  start_sec = (uint32_t)(start_li.QuadPart / 10000000); // 100-ns units. odd.
149  start_nsec = (start_li.LowPart % 10000000) * 100;
150  }
151  LARGE_INTEGER cur_time;
152  QueryPerformanceCounter(&cur_time);
153  LARGE_INTEGER delta_cpu_time;
154  delta_cpu_time.QuadPart = cur_time.QuadPart - init_cpu_time.QuadPart;
155  // todo: how to handle cpu clock drift. not sure it's a big deal for us.
156  // also, think about clock wraparound. seems extremely unlikey, but possible
157  double d_delta_cpu_time = delta_cpu_time.QuadPart / (double) cpu_freq.QuadPart;
158  uint32_t delta_sec = (uint32_t) floor(d_delta_cpu_time);
159  uint32_t delta_nsec = (uint32_t) round((d_delta_cpu_time-delta_sec) * 1e9);
160 
161  int64_t sec_sum = (int64_t)start_sec + (int64_t)delta_sec;
162  int64_t nsec_sum = (int64_t)start_nsec + (int64_t)delta_nsec;
163 
164  // Throws an exception if we go out of 32-bit range
165  normalizeSecNSecUnsigned(sec_sum, nsec_sum);
166 
167  sec = sec_sum;
168  nsec = nsec_sum;
169 #endif
170  }
174  int ros_nanosleep(const uint32_t &sec, const uint32_t &nsec)
175  {
176 #if defined(WIN32)
177  HANDLE timer = NULL;
178  LARGE_INTEGER sleepTime;
179  sleepTime.QuadPart = -
180  static_cast<int64_t>(sec)*10000000LL -
181  static_cast<int64_t>(nsec) / 100LL;
182 
183  timer = CreateWaitableTimer(NULL, TRUE, NULL);
184  if (timer == NULL)
185  {
186  return -1;
187  }
188 
189  if (!SetWaitableTimer (timer, &sleepTime, 0, NULL, NULL, 0))
190  {
191  return -1;
192  }
193 
194  if (WaitForSingleObject (timer, INFINITE) != WAIT_OBJECT_0)
195  {
196  return -1;
197  }
198  return 0;
199 #else
200  timespec req = { static_cast<time_t>(sec), static_cast<long>(nsec) };
201  return nanosleep(&req, NULL);
202 #endif
203  }
204 
211  {
212 #if defined(WIN32)
213  ros_nanosleep(sec,nsec);
214 #else
215  timespec req = { static_cast<time_t>(sec), static_cast<long>(nsec) };
216  timespec rem = {0, 0};
217  while (nanosleep(&req, &rem) && !g_stopped)
218  {
219  req = rem;
220  }
221 #endif
222  return !g_stopped;
223  }
224 
225  /*********************************************************************
226  ** Class Methods
227  *********************************************************************/
228 
230  {
231  return !g_use_sim_time;
232  }
233 
235  {
236  return g_use_sim_time;
237  }
238 
240  {
241  return !isSimTime();
242  }
243 
245  {
246  if (!g_initialized)
247  {
249  }
250 
251  if (g_use_sim_time)
252  {
253  std::lock_guard<std::mutex> lock(g_sim_time_mutex);
254  Time t = g_sim_time;
255  return t;
256  }
257 
258  Time t;
259  ros_walltime(t.sec, t.nsec);
260 
261  return t;
262  }
263 
264  void Time::setNow(const Time& new_now)
265  {
266  std::lock_guard<std::mutex> lock(g_sim_time_mutex);
267 
268  g_sim_time = new_now;
269  g_use_sim_time = true;
270  }
271 
272  void Time::init()
273  {
274  g_stopped = false;
275  g_use_sim_time = false;
276  g_initialized = true;
277  }
278 
280  {
281  g_stopped = true;
282  }
283 
285  {
286  return (!g_use_sim_time) || !g_sim_time.isZero();
287  }
288 
290  {
292  }
293 
295  {
297  while (!isValid() && !g_stopped)
298  {
300 
301  if (timeout > rs2rosinternal::WallDuration(0, 0) && (rs2rosinternal::WallTime::now() - start > timeout))
302  {
303  return false;
304  }
305  }
306 
307  if (g_stopped)
308  {
309  return false;
310  }
311 
312  return true;
313  }
314 
315  /* Time Time::fromBoost(const boost::posix_time::ptime& t)
316  {
317  boost::posix_time::time_duration diff = t - boost::posix_time::from_time_t(0);
318  return Time::fromBoost(diff);
319  }
320 
321  Time Time::fromBoost(const boost::posix_time::time_duration& d)
322  {
323  Time t;
324  t.sec = d.total_seconds();
325 #if defined(BOOST_DATE_TIME_HAS_NANOSECONDS)
326  t.nsec = d.fractional_seconds();
327 #else
328  t.nsec = static_cast<uint32_t>(d.fractional_seconds()*1000);
329 #endif
330  return t;
331  }*/
332 
333  std::ostream& operator<<(std::ostream& os, const Time &rhs)
334  {
336  os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
337  return os;
338  }
339 
340  std::ostream& operator<<(std::ostream& os, const Duration& rhs)
341  {
343  if (rhs.sec >= 0 || rhs.nsec == 0)
344  {
345  os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
346  }
347  else
348  {
349  os << (rhs.sec == -1 ? "-" : "") << (rhs.sec + 1) << "." << std::setw(9) << std::setfill('0') << (1000000000 - rhs.nsec);
350  }
351  return os;
352  }
353 
354  bool Time::sleepUntil(const Time& end)
355  {
356  if (Time::useSystemTime())
357  {
358  Duration d(end - Time::now());
359  if (d > Duration(0))
360  {
361  return d.sleep();
362  }
363 
364  return true;
365  }
366  else
367  {
368  Time start = Time::now();
369  while (!g_stopped && (Time::now() < end))
370  {
371  ros_nanosleep(0,1000000);
372  if (Time::now() < start)
373  {
374  return false;
375  }
376  }
377 
378  return true;
379  }
380  }
381 
383  {
384  WallDuration d(end - WallTime::now());
385  if (d > WallDuration(0))
386  {
387  return d.sleep();
388  }
389 
390  return true;
391  }
392 
393  bool Duration::sleep() const
394  {
395  if (Time::useSystemTime())
396  {
397  return ros_wallsleep(sec, nsec);
398  }
399  else
400  {
401  Time start = Time::now();
402  Time end = start + *this;
403  if (start.isZero())
404  {
405  end = TIME_MAX;
406  }
407 
408  bool rc = false;
409  while (!g_stopped && (Time::now() < end))
410  {
411  ros_wallsleep(0, 1000000);
412  rc = true;
413 
414  // If we started at time 0 wait for the first actual time to arrive before starting the timer on
415  // our sleep
416  if (start.isZero())
417  {
418  start = Time::now();
419  end = start + *this;
420  }
421 
422  // If time jumped backwards from when we started sleeping, return immediately
423  if (Time::now() < start)
424  {
425  return false;
426  }
427  }
428 
429  return rc && !g_stopped;
430  }
431  }
432 
433  std::ostream &operator<<(std::ostream& os, const WallTime &rhs)
434  {
436  os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
437  return os;
438  }
439 
441  {
442  WallTime t;
443  ros_walltime(t.sec, t.nsec);
444 
445  return t;
446  }
447 
448  std::ostream &operator<<(std::ostream& os, const WallDuration& rhs)
449  {
451  if (rhs.sec >= 0 || rhs.nsec == 0)
452  {
453  os << rhs.sec << "." << std::setw(9) << std::setfill('0') << rhs.nsec;
454  }
455  else
456  {
457  os << (rhs.sec == -1 ? "-" : "") << (rhs.sec + 1) << "." << std::setw(9) << std::setfill('0') << (1000000000 - rhs.nsec);
458  }
459  return os;
460  }
461 
462  bool WallDuration::sleep() const
463  {
464  return ros_wallsleep(sec, nsec);
465  }
466 
468  {
469  uint64_t nsec_part = nsec % 1000000000UL;
470  uint64_t sec_part = nsec / 1000000000UL;
471 
472  if (sec + sec_part > UINT_MAX)
473  throw std::runtime_error("Time is out of dual 32-bit range");
474 
475  sec += sec_part;
476  nsec = nsec_part;
477  }
478 
480  {
481  uint64_t sec64 = sec;
482  uint64_t nsec64 = nsec;
483 
484  normalizeSecNSec(sec64, nsec64);
485 
486  sec = (uint32_t)sec64;
487  nsec = (uint32_t)nsec64;
488  }
489 
491  {
492  int64_t nsec_part = nsec % 1000000000L;
493  int64_t sec_part = sec + nsec / 1000000000L;
494  if (nsec_part < 0)
495  {
496  nsec_part += 1000000000L;
497  --sec_part;
498  }
499 
500  if (sec_part < 0 || sec_part > UINT_MAX)
501  throw std::runtime_error("Time is out of dual 32-bit range");
502 
503  sec = sec_part;
504  nsec = nsec_part;
505  }
506 
507  template class TimeBase<Time, Duration>;
508  template class TimeBase<WallTime, WallDuration>;
509 }
510 
511 
static bool isSimTime()
Definition: time.cpp:234
static const textual_icon lock
Definition: model-views.h:218
static bool g_initialized(false)
GLuint GLuint end
ROSTIME_DECL void normalizeSecNSec(uint64_t &sec, uint64_t &nsec)
Definition: time.cpp:467
GLdouble s
bool sleep() const
sleep for the amount of time specified by this Duration. If a signal interrupts the sleep...
Definition: time.cpp:462
static bool waitForValid()
Wait for time to become valid.
Definition: time.cpp:289
static void setNow(const Time &new_now)
Definition: time.cpp:264
static bool isSystemTime()
Definition: time.cpp:239
ROSTIME_DECL const Time TIME_MAX
Thrown if the ros subsystem hasn&#39;t been initialised before use.
Definition: time.h:89
static bool g_stopped(false)
void ros_walltime(uint32_t &sec, uint32_t &nsec)
Definition: time.cpp:97
static bool useSystemTime()
Definition: time.cpp:229
d
Definition: rmse.py:171
static WallTime now()
Returns the current wall clock time.
Definition: time.cpp:440
ROSTIME_DECL const Duration DURATION_MIN
static void shutdown()
Definition: time.cpp:279
Thrown if windoze high perf. timestamping is unavailable.
Definition: time.h:103
static bool g_use_sim_time(true)
GLdouble t
::std_msgs::Duration_< std::allocator< void > > Duration
Definition: Duration.h:47
bool isZero() const
Definition: time.h:166
Duration representation for use with the Time class.
Definition: duration.h:108
Duration representation for use with the WallTime class.
Definition: duration.h:136
unsigned int uint32_t
Definition: stdint.h:80
ROSTIME_DECL void normalizeSecNSecUnsigned(int64_t &sec, int64_t &nsec)
Definition: time.cpp:490
bool sleep() const
sleep for the amount of time specified by this Duration. If a signal interrupts the sleep...
Definition: time.cpp:393
Time representation. Always wall-clock time.
Definition: time.h:233
Time representation. May either represent wall clock time or ROS clock time.
Definition: time.h:177
unsigned __int64 uint64_t
Definition: stdint.h:90
static Time g_sim_time(0, 0)
GLuint start
static bool sleepUntil(const Time &end)
Sleep until a specific time has been reached.
Definition: time.cpp:354
std::ostream & operator<<(std::ostream &os, const Duration &rhs)
Definition: time.cpp:340
ROSTIME_DECL const Duration DURATION_MAX
static std::mutex g_sim_time_mutex
Definition: time.cpp:84
ROSTIME_DECL const Time TIME_MIN
GLbitfield GLuint64 timeout
int min(int a, int b)
Definition: lz4s.c:73
static void init()
Definition: time.cpp:272
signed __int64 int64_t
Definition: stdint.h:89
bool ros_wallsleep(uint32_t sec, uint32_t nsec)
Go to the wall!
Definition: time.cpp:210
#define NULL
Definition: tinycthread.c:47
#define TRUE
Definition: tinycthread.c:50
static Time now()
Retrieve the current time. If ROS clock time is in use, this returns the time according to the ROS cl...
Definition: time.cpp:244
static bool sleepUntil(const WallTime &end)
Sleep until a specific time has been reached.
Definition: time.cpp:382
static bool isValid()
Returns whether or not the current time is valid. Time is valid if it is non-zero.
Definition: time.cpp:284
::std_msgs::Time_< std::allocator< void > > Time
Definition: Time.h:47
int ros_nanosleep(const uint32_t &sec, const uint32_t &nsec)
Simple representation of the rt library nanosleep function.
Definition: time.cpp:174


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:50:11