1818#include < atomic>
1919#include < chrono>
2020#include < functional>
21+ #include < optional>
2122#include < memory>
2223#include < sstream>
2324#include < thread>
4344namespace rclcpp
4445{
4546
47+ struct TimerInfo
48+ {
49+ Time expected_call_time;
50+ Time actual_call_time;
51+ };
52+
4653class TimerBase
4754{
4855public:
@@ -96,16 +103,20 @@ class TimerBase
96103 * The multithreaded executor takes advantage of this to avoid scheduling
97104 * the callback multiple times.
98105 *
99- * \return `true` if the callback should be executed, `false` if the timer was canceled.
106+ * \return a valid shared_ptr if the callback should be executed,
107+ * an invalid shared_ptr (nullptr) if the timer was canceled.
100108 */
101109 RCLCPP_PUBLIC
102- virtual bool
110+ virtual std::shared_ptr< void >
103111 call () = 0 ;
104112
105113 // / Call the callback function when the timer signal is emitted.
114+ /* *
115+ * \param[in] data the pointer returned by the call function
116+ */
106117 RCLCPP_PUBLIC
107118 virtual void
108- execute_callback () = 0 ;
119+ execute_callback (const std::shared_ptr< void > & data ) = 0 ;
109120
110121 RCLCPP_PUBLIC
111122 std::shared_ptr<const rcl_timer_t >
@@ -193,16 +204,17 @@ class TimerBase
193204 set_on_reset_callback (rcl_event_callback_t callback, const void * user_data);
194205};
195206
196-
197207using VoidCallbackType = std::function<void ()>;
198208using TimerCallbackType = std::function<void (TimerBase &)>;
209+ using TimerInfoCallbackType = std::function<void (const TimerInfo &)>;
199210
200211// / Generic timer. Periodically executes a user-specified callback.
201212template <
202213 typename FunctorT,
203214 typename std::enable_if<
204215 rclcpp::function_traits::same_arguments<FunctorT, VoidCallbackType>::value ||
205- rclcpp::function_traits::same_arguments<FunctorT, TimerCallbackType>::value
216+ rclcpp::function_traits::same_arguments<FunctorT, TimerCallbackType>::value ||
217+ rclcpp::function_traits::same_arguments<FunctorT, TimerInfoCallbackType>::value
206218 >::type * = nullptr
207219>
208220class GenericTimer : public TimerBase
@@ -244,27 +256,28 @@ class GenericTimer : public TimerBase
244256 * \sa rclcpp::TimerBase::call
245257 * \throws std::runtime_error if it failed to notify timer that callback will occurr
246258 */
247- bool
259+ std::shared_ptr< void >
248260 call () override
249261 {
250- rcl_ret_t ret = rcl_timer_call (timer_handle_.get ());
262+ auto timer_call_info_ = std::make_shared<rcl_timer_call_info_t >();
263+ rcl_ret_t ret = rcl_timer_call_with_info (timer_handle_.get (), timer_call_info_.get ());
251264 if (ret == RCL_RET_TIMER_CANCELED) {
252- return false ;
265+ return nullptr ;
253266 }
254267 if (ret != RCL_RET_OK) {
255268 throw std::runtime_error (" Failed to notify timer that callback occurred" );
256269 }
257- return true ;
270+ return timer_call_info_ ;
258271 }
259272
260273 /* *
261274 * \sa rclcpp::TimerBase::execute_callback
262275 */
263276 void
264- execute_callback () override
277+ execute_callback (const std::shared_ptr< void > & data ) override
265278 {
266279 TRACEPOINT (callback_start, reinterpret_cast <const void *>(&callback_), false );
267- execute_callback_delegate<>();
280+ execute_callback_delegate<>(* static_cast < rcl_timer_call_info_t *>(data. get ()) );
268281 TRACEPOINT (callback_end, reinterpret_cast <const void *>(&callback_));
269282 }
270283
@@ -276,7 +289,7 @@ class GenericTimer : public TimerBase
276289 >::type * = nullptr
277290 >
278291 void
279- execute_callback_delegate ()
292+ execute_callback_delegate (const rcl_timer_call_info_t & )
280293 {
281294 callback_ ();
282295 }
@@ -288,11 +301,26 @@ class GenericTimer : public TimerBase
288301 >::type * = nullptr
289302 >
290303 void
291- execute_callback_delegate ()
304+ execute_callback_delegate (const rcl_timer_call_info_t & )
292305 {
293306 callback_ (*this );
294307 }
295308
309+
310+ template <
311+ typename CallbackT = FunctorT,
312+ typename std::enable_if<
313+ rclcpp::function_traits::same_arguments<CallbackT, TimerInfoCallbackType>::value
314+ >::type * = nullptr
315+ >
316+ void
317+ execute_callback_delegate (const rcl_timer_call_info_t & timer_call_info_)
318+ {
319+ const TimerInfo info{Time{timer_call_info_.expected_call_time , clock_->get_clock_type ()},
320+ Time{timer_call_info_.actual_call_time , clock_->get_clock_type ()}};
321+ callback_ (info);
322+ }
323+
296324 // / Is the clock steady (i.e. is the time between ticks constant?)
297325 /* * \return True if the clock used by this timer is steady. */
298326 bool
@@ -311,7 +339,8 @@ template<
311339 typename FunctorT,
312340 typename std::enable_if<
313341 rclcpp::function_traits::same_arguments<FunctorT, VoidCallbackType>::value ||
314- rclcpp::function_traits::same_arguments<FunctorT, TimerCallbackType>::value
342+ rclcpp::function_traits::same_arguments<FunctorT, TimerCallbackType>::value ||
343+ rclcpp::function_traits::same_arguments<FunctorT, TimerInfoCallbackType>::value
315344 >::type * = nullptr
316345>
317346class WallTimer : public GenericTimer <FunctorT>
0 commit comments