timer_manager.h
Go to the documentation of this file.
1 #include "sick_scan/sick_scan_base.h" /* Base definitions included in all header files, added by add_sick_scan_base_header.py. Do not edit this line. */
2 /*
3  * Copyright (C) 2009, Willow Garage, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its
13  * contributors may be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #ifndef ROSCPP_TIMER_MANAGER_H
30 #define ROSCPP_TIMER_MANAGER_H
31 
32 #include "ros/forwards.h"
33 #include "ros/time.h"
34 #include "ros/file_log.h"
35 
36 //#include <boost/thread/thread.hpp>
37 #include <mutex>
38 //#include <boost/thread/recursive_mutex.hpp>
39 //#include <boost/thread/condition_variable.hpp>
40 
41 #include "ros/assert.h"
42 #include "ros/callback_queue_interface.h"
43 
44 #include <vector>
45 #include <list>
46 
47 namespace roswrap
48 {
49 
50 template<class T, class D, class E>
51 class TimerManager
52 {
53 private:
54  struct TimerInfo
55  {
56  int32_t handle;
57  D period;
58 
59  std::function<void(const E&)> callback;
61 
63 
66 
68 
69  bool removed;
70 
73 
74  // TODO: atomicize
75  std::mutex waiting_mutex;
77 
78  bool oneshot;
79 
80  // debugging info
81  uint32_t total_calls;
82  };
83  typedef std::shared_ptr<TimerInfo> TimerInfoPtr;
84  typedef std::weak_ptr<TimerInfo> TimerInfoWPtr;
85  typedef std::vector<TimerInfoPtr> V_TimerInfo;
86 
87  typedef std::list<int32_t> L_int32;
88 
89 public:
90  TimerManager();
91  ~TimerManager();
92 
93  int32_t add(const D& period, const std::function<void(const E&)>& callback, CallbackQueueInterface* callback_queue, const VoidConstPtr& tracked_object, bool oneshot);
94  void remove(int32_t handle);
95 
96  bool hasPending(int32_t handle);
97  void setPeriod(int32_t handle, const D& period, bool reset=true);
98 
99  static TimerManager& global()
100  {
102  return global;
103  }
104 
105 private:
106  void threadFunc();
107 
108  bool waitingCompare(int32_t lhs, int32_t rhs);
109  TimerInfoPtr findTimer(int32_t handle);
110  void schedule(const TimerInfoPtr& info);
111  void updateNext(const TimerInfoPtr& info, const T& current_time);
112 
114  std::mutex timers_mutex_;
115  std::condition_variable timers_cond_;
116  volatile bool new_timer_;
117 
118  std::mutex waiting_mutex_;
120 
121  uint32_t id_counter_;
122  std::mutex id_mutex_;
123 
125 
126  std::thread thread_;
127 
128  bool quit_;
129 
131  {
132  public:
133  TimerQueueCallback(TimerManager<T, D, E>* parent, const TimerInfoPtr& info, T last_expected, T last_real, T current_expected)
134  : parent_(parent)
135  , info_(info)
136  , last_expected_(last_expected)
137  , last_real_(last_real)
138  , current_expected_(current_expected)
139  , called_(false)
140  {
141  std::lock_guard<std::mutex> lock(info->waiting_mutex);
142  ++info->waiting_callbacks;
143  }
144 
146  {
147  TimerInfoPtr info = info_.lock();
148  if (info)
149  {
150  std::lock_guard<std::mutex> lock(info->waiting_mutex);
151  --info->waiting_callbacks;
152  }
153  }
154 
156  {
157  TimerInfoPtr info = info_.lock();
158  if (!info)
159  {
160  return Invalid;
161  }
162 
163  {
164  ++info->total_calls;
165  called_ = true;
166 
167  VoidConstPtr tracked;
168  if (info->has_tracked_object)
169  {
170  tracked = info->tracked_object.lock();
171  if (!tracked)
172  {
173  return Invalid;
174  }
175  }
176 
177  E event;
178  event.last_expected = last_expected_;
179  event.last_real = last_real_;
180  event.current_expected = current_expected_;
181  event.current_real = T::now();
182  event.profile.last_duration = info->last_cb_duration;
183 
184  WallTime cb_start = WallTime::now();
185  info->callback(event);
186  WallTime cb_end = WallTime::now();
187  info->last_cb_duration = cb_end - cb_start;
188 
189  info->last_real = event.current_real;
190 
191  parent_->schedule(info);
192  }
193 
194  return Success;
195  }
196 
197  private:
203 
204  bool called_;
205  };
206 };
207 
208 template<class T, class D, class E>
210  new_timer_(false), id_counter_(0), thread_started_(false), quit_(false)
211 {
212 
213 }
214 
215 template<class T, class D, class E>
217 {
218  quit_ = true;
219  {
220  std::lock_guard<std::mutex> lock(timers_mutex_);
221  timers_cond_.notify_all();
222  }
223  if (thread_started_)
224  {
225  thread_.join();
226  }
227 }
228 
229 template<class T, class D, class E>
230 bool TimerManager<T, D, E>::waitingCompare(int32_t lhs, int32_t rhs)
231 {
232  TimerInfoPtr infol = findTimer(lhs);
233  TimerInfoPtr infor = findTimer(rhs);
234  if (!infol || !infor)
235  {
236  return infol < infor;
237  }
238 
239  return infol->next_expected < infor->next_expected;
240 }
241 
242 template<class T, class D, class E>
244 {
245  typename V_TimerInfo::iterator it = timers_.begin();
246  typename V_TimerInfo::iterator end = timers_.end();
247  for (; it != end; ++it)
248  {
249  if ((*it)->handle == handle)
250  {
251  return *it;
252  }
253  }
254 
255  return TimerInfoPtr();
256 }
257 
258 template<class T, class D, class E>
260 {
261  std::lock_guard<std::mutex> lock(timers_mutex_);
262  TimerInfoPtr info = findTimer(handle);
263 
264  if (!info)
265  {
266  return false;
267  }
268 
269  if (info->has_tracked_object)
270  {
271  VoidConstPtr tracked = info->tracked_object.lock();
272  if (!tracked)
273  {
274  return false;
275  }
276  }
277 
278  std::lock_guard<std::mutex> lock2(info->waiting_mutex);
279  return info->next_expected <= T::now() || info->waiting_callbacks != 0;
280 }
281 
282 template<class T, class D, class E>
283 int32_t TimerManager<T, D, E>::add(const D& period, const std::function<void(const E&)>& callback, CallbackQueueInterface* callback_queue,
284  const VoidConstPtr& tracked_object, bool oneshot)
285 {
286  TimerInfoPtr info(std::make_shared<TimerInfo>());
287  info->period = period;
288  info->callback = callback;
289  info->callback_queue = callback_queue;
290  info->last_expected = T::now();
291  info->next_expected = info->last_expected + period;
292  info->removed = false;
293  info->has_tracked_object = false;
294  info->waiting_callbacks = 0;
295  info->total_calls = 0;
296  info->oneshot = oneshot;
297  if (tracked_object)
298  {
299  info->tracked_object = tracked_object;
300  info->has_tracked_object = true;
301  }
302 
303  {
304  std::lock_guard<std::mutex> lock(id_mutex_);
305  info->handle = id_counter_++;
306  }
307 
308  {
309  std::lock_guard<std::mutex> lock(timers_mutex_);
310  timers_.push_back(info);
311 
312  if (!thread_started_)
313  {
314  thread_ = std::thread(std::bind(&TimerManager::threadFunc, this));
315  thread_started_ = true;
316  }
317 
318  {
319  std::lock_guard<std::mutex> lock(waiting_mutex_);
320  waiting_.push_back(info->handle);
321  waiting_.sort(std::bind(&TimerManager::waitingCompare, this, std::placeholders::_1, std::placeholders::_2));
322  }
323 
324  new_timer_ = true;
325  timers_cond_.notify_all();
326  }
327 
328  return info->handle;
329 }
330 
331 template<class T, class D, class E>
332 void TimerManager<T, D, E>::remove(int32_t handle)
333 {
334  CallbackQueueInterface* callback_queue = 0;
335  uint64_t remove_id = 0;
336 
337  {
338  std::lock_guard<std::mutex> lock(timers_mutex_);
339 
340  typename V_TimerInfo::iterator it = timers_.begin();
341  typename V_TimerInfo::iterator end = timers_.end();
342  for (; it != end; ++it)
343  {
344  const TimerInfoPtr& info = *it;
345  if (info->handle == handle)
346  {
347  info->removed = true;
348  callback_queue = info->callback_queue;
349  remove_id = (uint64_t)info.get();
350  timers_.erase(it);
351  break;
352  }
353  }
354 
355  {
356  std::lock_guard<std::mutex> lock2(waiting_mutex_);
357  // Remove from the waiting list if it's in it
358  L_int32::iterator it = std::find(waiting_.begin(), waiting_.end(), handle);
359  if (it != waiting_.end())
360  {
361  waiting_.erase(it);
362  }
363  }
364  }
365 
366  if (callback_queue)
367  {
368  callback_queue->removeByID(remove_id);
369  }
370 }
371 
372 template<class T, class D, class E>
374 {
375  std::lock_guard<std::mutex> lock(timers_mutex_);
376 
377  if (info->removed)
378  {
379  return;
380  }
381 
382  updateNext(info, T::now());
383  {
384  std::lock_guard<std::mutex> lock(waiting_mutex_);
385 
386  waiting_.push_back(info->handle);
387  // waitingCompare requires a lock on the timers_mutex_
388  waiting_.sort(std::bind(&TimerManager::waitingCompare, this, std::placeholders::_1, std::placeholders::_2));
389  }
390 
391  new_timer_ = true;
392  timers_cond_.notify_one();
393 }
394 
395 template<class T, class D, class E>
396 void TimerManager<T, D, E>::updateNext(const TimerInfoPtr& info, const T& current_time)
397 {
398  if (info->oneshot)
399  {
400  info->next_expected = T(INT_MAX, 999999999);
401  }
402  else
403  {
404  // Protect against someone having called setPeriod()
405  // If the next expected time is already past the current time
406  // don't update it
407  if (info->next_expected <= current_time)
408  {
409  info->last_expected = info->next_expected;
410  info->next_expected += info->period;
411  }
412 
413  // detect time jumping forward, as well as callbacks that are too slow
414  if (info->next_expected + info->period < current_time)
415  {
416  ROS_DEBUG("Time jumped forward by [%f] for timer of period [%f], resetting timer (current=%f, next_expected=%f)", (current_time - info->next_expected).toSec(), info->period.toSec(), current_time.toSec(), info->next_expected.toSec());
417  info->next_expected = current_time;
418  }
419  }
420 }
421 
422 template<class T, class D, class E>
423 void TimerManager<T, D, E>::setPeriod(int32_t handle, const D& period, bool reset)
424 {
425  std::lock_guard<std::mutex> lock(timers_mutex_);
426  TimerInfoPtr info = findTimer(handle);
427 
428  if (!info)
429  {
430  return;
431  }
432 
433  {
434  std::lock_guard<std::mutex> lock(waiting_mutex_);
435 
436  if(reset)
437  {
438  info->next_expected = T::now() + period;
439  }
440 
441  // else if some time has elapsed since last cb (called outside of cb)
442  else if( (T::now() - info->last_real) < info->period)
443  {
444  // if elapsed time is greater than the new period
445  // do the callback now
446  if( (T::now() - info->last_real) > period)
447  {
448  info->next_expected = T::now();
449  }
450 
451  // else, account for elapsed time by using last_real+period
452  else
453  {
454  info->next_expected = info->last_real + period;
455  }
456  }
457 
458  // Else if called in a callback, last_real has not been updated yet => (now - last_real) > period
459  // In this case, let next_expected be updated only in updateNext
460 
461  info->period = period;
462  waiting_.sort(std::bind(&TimerManager::waitingCompare, this, std::placeholders::_1, std::placeholders::_2));
463  }
464 
465  new_timer_ = true;
466  timers_cond_.notify_one();
467 }
468 
469 template<class T, class D, class E>
471 {
472  T current;
473  while (!quit_)
474  {
475  T sleep_end;
476 
477  std::lock_guard<std::mutex> lock(timers_mutex_);
478 
479  // detect time jumping backwards
480  if (T::now() < current)
481  {
482  ROSCPP_LOG_DEBUG("Time jumped backward, resetting timers");
483 
484  current = T::now();
485 
486  typename V_TimerInfo::iterator it = timers_.begin();
487  typename V_TimerInfo::iterator end = timers_.end();
488  for (; it != end; ++it)
489  {
490  const TimerInfoPtr& info = *it;
491 
492  // Timer may have been added after the time jump, so also check if time has jumped past its last call time
493  if (current < info->last_expected)
494  {
495  info->last_expected = current;
496  info->next_expected = current + info->period;
497  }
498  }
499  }
500 
501  current = T::now();
502 
503  {
504  std::lock_guard<std::mutex> waitlock(waiting_mutex_);
505 
506  if (waiting_.empty())
507  {
508  sleep_end = current + D(0.1);
509  }
510  else
511  {
512  TimerInfoPtr info = findTimer(waiting_.front());
513 
514  while (!waiting_.empty() && info && info->next_expected <= current)
515  {
516  current = T::now();
517 
518  //ROS_DEBUG("Scheduling timer callback for timer [%d] of period [%f], [%f] off expected", info->handle, info->period.toSec(), (current - info->next_expected).toSec());
519  CallbackInterfacePtr cb(std::make_shared<TimerQueueCallback>(this, info, info->last_expected, info->last_real, info->next_expected));
520  info->callback_queue->addCallback(cb, (uint64_t)info.get());
521 
522  waiting_.pop_front();
523 
524  if (waiting_.empty())
525  {
526  break;
527  }
528 
529  info = findTimer(waiting_.front());
530  }
531 
532  if (info)
533  {
534  sleep_end = info->next_expected;
535  }
536  }
537  }
538 
539  while (!new_timer_ && T::now() < sleep_end && !quit_)
540  {
541  // detect backwards jumps in time
542 
543  if (T::now() < current)
544  {
545  ROSCPP_LOG_DEBUG("Time jumped backwards, breaking out of sleep");
546  break;
547  }
548 
549  current = T::now();
550 
551  if (current >= sleep_end)
552  {
553  break;
554  }
555 
556  // If we're on simulation time we need to check now() against sleep_end more often than on system time,
557  // since simulation time may be running faster than real time.
558  if (!T::isSystemTime())
559  {
560  timers_cond_.timed_wait(lock, std::chrono::milliseconds(1)); // boost::posix_time::milliseconds(1));
561  }
562  else
563  {
564  // On system time we can simply sleep for the rest of the wait time, since anything else requiring processing will
565  // signal the condition variable
566  int32_t remaining_time = std::max((int32_t)((sleep_end - current).toSec() * 1000.0f), 1);
567  timers_cond_.timed_wait(lock, std::chrono::milliseconds(remaining_time)); // boost::posix_time::milliseconds(remaining_time));
568  }
569  }
570 
571  new_timer_ = false;
572  }
573 }
574 
575 }
576 
577 #endif
roswrap::TimerManager::timers_cond_
std::condition_variable timers_cond_
Definition: timer_manager.h:115
roswrap::TimerManager::TimerQueueCallback::parent_
TimerManager< T, D, E > * parent_
Definition: timer_manager.h:198
roswrap::TimerManager::timers_
V_TimerInfo timers_
Definition: timer_manager.h:113
roswrap::TimerManager::TimerInfo::last_expected
T last_expected
Definition: timer_manager.h:64
roswrap::WallTime
Time representation. Always wall-clock time.
Definition: time.h:233
roswrap::TimerManager
Definition: internal_timer_manager.h:39
roswrap::TimerManager::hasPending
bool hasPending(int32_t handle)
Definition: timer_manager.h:259
roswrap::TimerManager::TimerQueueCallback::last_expected_
T last_expected_
Definition: timer_manager.h:200
roswrap::TimerManager::TimerQueueCallback::last_real_
T last_real_
Definition: timer_manager.h:201
roswrap::TimerManager::global
static TimerManager & global()
Definition: timer_manager.h:99
roswrap::TimerManager::remove
void remove(int32_t handle)
Definition: timer_manager.h:332
roswrap::TimerManager::V_TimerInfo
std::vector< TimerInfoPtr > V_TimerInfo
Definition: timer_manager.h:85
roswrap::CallbackInterface::Invalid
@ Invalid
Call no longer valid.
Definition: callback_queue_interface.h:59
ros::TimerManager::schedule
void schedule(const TimerInfoPtr &info)
roswrap::TimerManager::TimerInfo::callback_queue
CallbackQueueInterface * callback_queue
Definition: timer_manager.h:60
roswrap::TimerManager::TimerQueueCallback::call
CallResult call()
Call this callback.
Definition: timer_manager.h:155
roswrap::TimerManager::TimerQueueCallback::called_
bool called_
Definition: timer_manager.h:204
roswrap::CallbackQueueInterface::removeByID
virtual void removeByID(uint64_t owner_id)=0
Remove all callbacks associated with an owner id.
roswrap::TimerManager::TimerInfo::total_calls
uint32_t total_calls
Definition: timer_manager.h:81
roswrap::TimerManager::TimerQueueCallback
Definition: timer_manager.h:130
roswrap::VoidConstWPtr
std::weak_ptr< void const > VoidConstWPtr
Definition: forwards.h:55
roswrap::TimerManager::TimerInfoWPtr
std::weak_ptr< TimerInfo > TimerInfoWPtr
Definition: timer_manager.h:84
roswrap::CallbackInterface::CallResult
CallResult
Possible results for the call() method.
Definition: callback_queue_interface.h:55
roswrap::TimerManager::TimerManager
TimerManager()
Definition: timer_manager.h:209
f
f
roswrap::TimerManager::thread_started_
bool thread_started_
Definition: timer_manager.h:124
roswrap::TimerManager::quit_
bool quit_
Definition: timer_manager.h:128
ROS::now
ROS::Time now(void)
Definition: ros_wrapper.cpp:116
roswrap::TimerManager::waitingCompare
bool waitingCompare(int32_t lhs, int32_t rhs)
Definition: timer_manager.h:230
roswrap::TimerManager::threadFunc
void threadFunc()
Definition: timer_manager.h:470
roswrap::TimerManager::TimerInfo::has_tracked_object
bool has_tracked_object
Definition: timer_manager.h:72
roswrap::TimerManager::updateNext
void updateNext(const TimerInfoPtr &info, const T &current_time)
Definition: timer_manager.h:396
roswrap::TimerManager::TimerInfo::handle
int32_t handle
Definition: timer_manager.h:56
roswrap::TimerManager::TimerInfo::callback
std::function< void(const E &)> callback
Definition: timer_manager.h:59
roswrap::TimerManager::waiting_
L_int32 waiting_
Definition: timer_manager.h:119
roswrap::TimerManager::thread_
std::thread thread_
Definition: timer_manager.h:126
roswrap::TimerManager::id_mutex_
std::mutex id_mutex_
Definition: timer_manager.h:122
roswrap::TimerManager::schedule
void schedule(const TimerInfoPtr &info)
Definition: timer_manager.h:373
roswrap::TimerManager::setPeriod
void setPeriod(int32_t handle, const D &period, bool reset=true)
Definition: timer_manager.h:423
roswrap::TimerManager::findTimer
TimerInfoPtr findTimer(int32_t handle)
Definition: timer_manager.h:243
roswrap::TimerManager::TimerInfo::waiting_mutex
std::mutex waiting_mutex
Definition: timer_manager.h:75
roswrap::TimerManager::add
int32_t add(const D &period, const std::function< void(const E &)> &callback, CallbackQueueInterface *callback_queue, const VoidConstPtr &tracked_object, bool oneshot)
Definition: timer_manager.h:283
roswrap::TimerManager::TimerInfo
Definition: timer_manager.h:54
roswrap::CallbackQueueInterface
Abstract interface for a queue used to handle all callbacks within roscpp.
Definition: callback_queue_interface.h:83
roswrap::TimerManager::TimerInfo::last_cb_duration
WallDuration last_cb_duration
Definition: timer_manager.h:62
roswrap
Definition: param_modi.cpp:41
roswrap::WallDuration
Duration representation for use with the WallTime class.
Definition: duration.h:137
roswrap::TimerManager::TimerInfo::removed
bool removed
Definition: timer_manager.h:69
roswrap::TimerManager::TimerQueueCallback::current_expected_
T current_expected_
Definition: timer_manager.h:202
roswrap::TimerManager::TimerQueueCallback::info_
TimerInfoWPtr info_
Definition: timer_manager.h:199
sick_scan_base.h
ROS_DEBUG
#define ROS_DEBUG(...)
Definition: sick_scan_logging.h:112
roswrap::CallbackInterface
Abstract interface for items which can be added to a CallbackQueueInterface.
Definition: callback_queue_interface.h:49
roswrap::TimerManager::TimerInfo::waiting_callbacks
uint32_t waiting_callbacks
Definition: timer_manager.h:76
roswrap::CallbackInterface::Success
@ Success
Call succeeded.
Definition: callback_queue_interface.h:57
roswrap::TimerManager::TimerInfo::oneshot
bool oneshot
Definition: timer_manager.h:78
roswrap::TimerManager::waiting_mutex_
std::mutex waiting_mutex_
Definition: timer_manager.h:118
roswrap::TimerManager::TimerQueueCallback::~TimerQueueCallback
~TimerQueueCallback()
Definition: timer_manager.h:145
roswrap::TimerManager::new_timer_
volatile bool new_timer_
Definition: timer_manager.h:116
roswrap::CallbackInterfacePtr
std::shared_ptr< CallbackInterface > CallbackInterfacePtr
Definition: callback_queue_interface.h:75
roswrap::TimerManager::~TimerManager
~TimerManager()
Definition: timer_manager.h:216
roswrap::TimerManager::L_int32
std::list< int32_t > L_int32
Definition: timer_manager.h:87
roswrap::TimerManager::TimerQueueCallback::TimerQueueCallback
TimerQueueCallback(TimerManager< T, D, E > *parent, const TimerInfoPtr &info, T last_expected, T last_real, T current_expected)
Definition: timer_manager.h:133
roswrap::TimerManager::TimerInfoPtr
std::shared_ptr< TimerInfo > TimerInfoPtr
Definition: timer_manager.h:83
roswrap::VoidConstPtr
std::shared_ptr< void const > VoidConstPtr
Definition: forwards.h:54
roswrap::TimerManager::TimerInfo::last_real
T last_real
Definition: timer_manager.h:67
ROSCPP_LOG_DEBUG
#define ROSCPP_LOG_DEBUG(...)
Definition: file_log.h:36
roswrap::TimerManager::TimerInfo::next_expected
T next_expected
Definition: timer_manager.h:65
roswrap::TimerManager::TimerInfo::tracked_object
VoidConstWPtr tracked_object
Definition: timer_manager.h:71
roswrap::TimerManager::timers_mutex_
std::mutex timers_mutex_
Definition: timer_manager.h:114
roswrap::TimerManager::id_counter_
uint32_t id_counter_
Definition: timer_manager.h:121
roswrap::TimerManager::TimerInfo::period
D period
Definition: timer_manager.h:57
callback
void callback(const sick_scan_xd::RadarScan::ConstPtr &oa)
Definition: radar_object_marker.cpp:157
roswrap::WallTime::now
static WallTime now()
Returns the current wall clock time.
Definition: time_modi.cpp:534


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:12