ROS 2 rclcpp + rcl - humble  humble
ROS 2 C++ Client Library with ROS Client Library
timer.c
1 // Copyright 2015 Open Source Robotics Foundation, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifdef __cplusplus
16 extern "C"
17 {
18 #endif
19 
20 #include "rcl/timer.h"
21 
22 #include <inttypes.h>
23 
24 #include "rcl/error_handling.h"
25 #include "rcutils/logging_macros.h"
26 #include "rcutils/stdatomic_helper.h"
27 #include "rcutils/time.h"
28 #include "tracetools/tracetools.h"
29 
31 {
32  // The clock providing time.
33  rcl_clock_t * clock;
34  // The associated context.
35  rcl_context_t * context;
36  // A guard condition used to wake the associated wait set, either when
37  // ROSTime causes the timer to expire or when the timer is reset.
38  rcl_guard_condition_t guard_condition;
39  // The user supplied callback.
40  atomic_uintptr_t callback;
41  // This is a duration in nanoseconds.
42  atomic_uint_least64_t period;
43  // This is a time in nanoseconds since an unspecified time.
44  atomic_int_least64_t last_call_time;
45  // This is a time in nanoseconds since an unspecified time.
46  atomic_int_least64_t next_call_time;
47  // Credit for time elapsed before ROS time is activated or deactivated.
48  atomic_int_least64_t time_credit;
49  // A flag which indicates if the timer is canceled.
50  atomic_bool canceled;
51  // The user supplied allocator.
52  rcl_allocator_t allocator;
53 };
54 
57 {
58  static rcl_timer_t null_timer = {0};
59  return null_timer;
60 }
61 
62 void _rcl_timer_time_jump(
63  const rcl_time_jump_t * time_jump,
64  bool before_jump,
65  void * user_data)
66 {
67  rcl_timer_t * timer = (rcl_timer_t *)user_data;
68 
69  if (before_jump) {
70  if (RCL_ROS_TIME_ACTIVATED == time_jump->clock_change ||
72  {
74  if (RCL_RET_OK != rcl_clock_get_now(timer->impl->clock, &now)) {
75  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to get current time in jump callback");
76  return;
77  }
78  // Source of time is changing, but the timer has ellapsed some portion of its period
79  // Save ellapsed duration pre jump so the timer only waits the remainder in the new epoch
80  if (0 == now) {
81  // No time credit if clock is uninitialized
82  return;
83  }
84  const int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
85  rcutils_atomic_store(&timer->impl->time_credit, next_call_time - now);
86  }
87  } else {
89  if (RCL_RET_OK != rcl_clock_get_now(timer->impl->clock, &now)) {
90  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to get current time in jump callback");
91  return;
92  }
93  const int64_t last_call_time = rcutils_atomic_load_int64_t(&timer->impl->last_call_time);
94  const int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
95  const int64_t period = rcutils_atomic_load_uint64_t(&timer->impl->period);
96  if (RCL_ROS_TIME_ACTIVATED == time_jump->clock_change ||
98  {
99  // ROS time activated or deactivated
100  if (0 == now) {
101  // Can't apply time credit if clock is uninitialized
102  return;
103  }
104  int64_t time_credit = rcutils_atomic_exchange_int64_t(&timer->impl->time_credit, 0);
105  if (time_credit) {
106  // set times in new epoch so timer only waits the remainder of the period
107  rcutils_atomic_store(&timer->impl->next_call_time, now - time_credit + period);
108  rcutils_atomic_store(&timer->impl->last_call_time, now - time_credit);
109  }
110  } else if (next_call_time <= now) {
111  // Post Forward jump and timer is ready
112  if (RCL_RET_OK != rcl_trigger_guard_condition(&timer->impl->guard_condition)) {
113  RCUTILS_LOG_ERROR_NAMED(
114  ROS_PACKAGE_NAME, "Failed to get trigger guard condition in jump callback");
115  }
116  } else if (now < last_call_time) {
117  // Post backwards time jump that went further back than 1 period
118  // next callback should happen after 1 period
119  rcutils_atomic_store(&timer->impl->next_call_time, now + period);
120  rcutils_atomic_store(&timer->impl->last_call_time, now);
121  return;
122  }
123  }
124 }
125 
126 rcl_ret_t
128  rcl_timer_t * timer,
129  rcl_clock_t * clock,
130  rcl_context_t * context,
131  int64_t period,
132  const rcl_timer_callback_t callback,
133  rcl_allocator_t allocator)
134 {
135  RCL_CHECK_ALLOCATOR_WITH_MSG(&allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
136  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
137  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
138  if (period < 0) {
139  RCL_SET_ERROR_MSG("timer period must be non-negative");
141  }
142  RCUTILS_LOG_DEBUG_NAMED(
143  ROS_PACKAGE_NAME, "Initializing timer with period: %" PRIu64 "ns", period);
144  if (timer->impl) {
145  RCL_SET_ERROR_MSG("timer already initialized, or memory was uninitialized");
146  return RCL_RET_ALREADY_INIT;
147  }
149  rcl_ret_t now_ret = rcl_clock_get_now(clock, &now);
150  if (now_ret != RCL_RET_OK) {
151  return now_ret; // rcl error state should already be set.
152  }
153  rcl_timer_impl_t impl;
154  impl.clock = clock;
155  impl.context = context;
156  impl.guard_condition = rcl_get_zero_initialized_guard_condition();
158  rcl_ret_t ret = rcl_guard_condition_init(&(impl.guard_condition), context, options);
159  if (RCL_RET_OK != ret) {
160  return ret;
161  }
162  if (RCL_ROS_TIME == impl.clock->type) {
163  rcl_jump_threshold_t threshold;
164  threshold.on_clock_change = true;
165  threshold.min_forward.nanoseconds = 1;
166  threshold.min_backward.nanoseconds = -1;
167  ret = rcl_clock_add_jump_callback(clock, threshold, _rcl_timer_time_jump, timer);
168  if (RCL_RET_OK != ret) {
169  if (RCL_RET_OK != rcl_guard_condition_fini(&(impl.guard_condition))) {
170  // Should be impossible
171  RCUTILS_LOG_ERROR_NAMED(
172  ROS_PACKAGE_NAME, "Failed to fini guard condition after failing to add jump callback");
173  }
174  return ret;
175  }
176  }
177  atomic_init(&impl.callback, (uintptr_t)callback);
178  atomic_init(&impl.period, period);
179  atomic_init(&impl.time_credit, 0);
180  atomic_init(&impl.last_call_time, now);
181  atomic_init(&impl.next_call_time, now + period);
182  atomic_init(&impl.canceled, false);
183  impl.allocator = allocator;
184  timer->impl = (rcl_timer_impl_t *)allocator.allocate(sizeof(rcl_timer_impl_t), allocator.state);
185  if (NULL == timer->impl) {
186  if (RCL_RET_OK != rcl_guard_condition_fini(&(impl.guard_condition))) {
187  // Should be impossible
188  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to fini guard condition after bad alloc");
189  }
190  if (RCL_RET_OK != rcl_clock_remove_jump_callback(clock, _rcl_timer_time_jump, timer)) {
191  // Should be impossible
192  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to remove callback after bad alloc");
193  }
194 
195  RCL_SET_ERROR_MSG("allocating memory failed");
196  return RCL_RET_BAD_ALLOC;
197  }
198  *timer->impl = impl;
199  TRACEPOINT(rcl_timer_init, (const void *)timer, period);
200  return RCL_RET_OK;
201 }
202 
203 rcl_ret_t
205 {
206  if (!timer || !timer->impl) {
207  return RCL_RET_OK;
208  }
209  // Will return either RCL_RET_OK or RCL_RET_ERROR since the timer is valid.
210  rcl_ret_t result = rcl_timer_cancel(timer);
211  rcl_allocator_t allocator = timer->impl->allocator;
212  rcl_ret_t fail_ret;
213  if (RCL_ROS_TIME == timer->impl->clock->type) {
214  // The jump callbacks use the guard condition, so we have to remove it
215  // before freeing the guard condition below.
216  fail_ret = rcl_clock_remove_jump_callback(timer->impl->clock, _rcl_timer_time_jump, timer);
217  if (RCL_RET_OK != fail_ret) {
218  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to remove timer jump callback");
219  }
220  }
221  fail_ret = rcl_guard_condition_fini(&(timer->impl->guard_condition));
222  if (RCL_RET_OK != fail_ret) {
223  RCL_SET_ERROR_MSG("Failure to fini guard condition");
224  }
225  allocator.deallocate(timer->impl, allocator.state);
226  timer->impl = NULL;
227  return result;
228 }
229 
230 RCL_PUBLIC
231 RCL_WARN_UNUSED
232 rcl_ret_t
234 {
235  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
236  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
237  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
238  *clock = timer->impl->clock;
239  return RCL_RET_OK;
240 }
241 
242 rcl_ret_t
244 {
245  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Calling timer");
246  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
247  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
248  if (rcutils_atomic_load_bool(&timer->impl->canceled)) {
249  RCL_SET_ERROR_MSG("timer is canceled");
250  return RCL_RET_TIMER_CANCELED;
251  }
253  rcl_ret_t now_ret = rcl_clock_get_now(timer->impl->clock, &now);
254  if (now_ret != RCL_RET_OK) {
255  return now_ret; // rcl error state should already be set.
256  }
257  if (now < 0) {
258  RCL_SET_ERROR_MSG("clock now returned negative time point value");
259  return RCL_RET_ERROR;
260  }
261  rcl_time_point_value_t previous_ns =
262  rcutils_atomic_exchange_int64_t(&timer->impl->last_call_time, now);
263  rcl_timer_callback_t typed_callback =
264  (rcl_timer_callback_t)rcutils_atomic_load_uintptr_t(&timer->impl->callback);
265 
266  int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
267  int64_t period = rcutils_atomic_load_uint64_t(&timer->impl->period);
268  // always move the next call time by exactly period forward
269  // don't use now as the base to avoid extending each cycle by the time
270  // between the timer being ready and the callback being triggered
271  next_call_time += period;
272  // in case the timer has missed at least once cycle
273  if (next_call_time < now) {
274  if (0 == period) {
275  // a timer with a period of zero is considered always ready
276  next_call_time = now;
277  } else {
278  // move the next call time forward by as many periods as necessary
279  int64_t now_ahead = now - next_call_time;
280  // rounding up without overflow
281  int64_t periods_ahead = 1 + (now_ahead - 1) / period;
282  next_call_time += periods_ahead * period;
283  }
284  }
285  rcutils_atomic_store(&timer->impl->next_call_time, next_call_time);
286 
287  if (typed_callback != NULL) {
288  int64_t since_last_call = now - previous_ns;
289  typed_callback(timer, since_last_call);
290  }
291  return RCL_RET_OK;
292 }
293 
294 rcl_ret_t
295 rcl_timer_is_ready(const rcl_timer_t * timer, bool * is_ready)
296 {
297  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
298  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
299  RCL_CHECK_ARGUMENT_FOR_NULL(is_ready, RCL_RET_INVALID_ARGUMENT);
300  int64_t time_until_next_call;
301  rcl_ret_t ret = rcl_timer_get_time_until_next_call(timer, &time_until_next_call);
302  if (ret == RCL_RET_TIMER_CANCELED) {
303  *is_ready = false;
304  return RCL_RET_OK;
305  } else if (ret != RCL_RET_OK) {
306  return ret; // rcl error state should already be set.
307  }
308  *is_ready = (time_until_next_call <= 0);
309  return RCL_RET_OK;
310 }
311 
312 rcl_ret_t
313 rcl_timer_get_time_until_next_call(const rcl_timer_t * timer, int64_t * time_until_next_call)
314 {
315  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
316  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
317  RCL_CHECK_ARGUMENT_FOR_NULL(time_until_next_call, RCL_RET_INVALID_ARGUMENT);
318  if (rcutils_atomic_load_bool(&timer->impl->canceled)) {
319  return RCL_RET_TIMER_CANCELED;
320  }
322  rcl_ret_t ret = rcl_clock_get_now(timer->impl->clock, &now);
323  if (ret != RCL_RET_OK) {
324  return ret; // rcl error state should already be set.
325  }
326  *time_until_next_call =
327  rcutils_atomic_load_int64_t(&timer->impl->next_call_time) - now;
328  return RCL_RET_OK;
329 }
330 
331 rcl_ret_t
333  const rcl_timer_t * timer,
334  rcl_time_point_value_t * time_since_last_call)
335 {
336  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
337  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
338  RCL_CHECK_ARGUMENT_FOR_NULL(time_since_last_call, RCL_RET_INVALID_ARGUMENT);
340  rcl_ret_t ret = rcl_clock_get_now(timer->impl->clock, &now);
341  if (ret != RCL_RET_OK) {
342  return ret; // rcl error state should already be set.
343  }
344  *time_since_last_call =
345  now - rcutils_atomic_load_int64_t(&timer->impl->last_call_time);
346  return RCL_RET_OK;
347 }
348 
349 rcl_ret_t
350 rcl_timer_get_period(const rcl_timer_t * timer, int64_t * period)
351 {
352  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
353  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
354  RCL_CHECK_ARGUMENT_FOR_NULL(period, RCL_RET_INVALID_ARGUMENT);
355  *period = rcutils_atomic_load_uint64_t(&timer->impl->period);
356  return RCL_RET_OK;
357 }
358 
359 rcl_ret_t
360 rcl_timer_exchange_period(const rcl_timer_t * timer, int64_t new_period, int64_t * old_period)
361 {
362  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
363 
364  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
365  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
366  RCL_CHECK_ARGUMENT_FOR_NULL(old_period, RCL_RET_INVALID_ARGUMENT);
367  *old_period = rcutils_atomic_exchange_uint64_t(&timer->impl->period, new_period);
368  RCUTILS_LOG_DEBUG_NAMED(
369  ROS_PACKAGE_NAME, "Updated timer period from '%" PRIu64 "ns' to '%" PRIu64 "ns'",
370  *old_period, new_period);
371  return RCL_RET_OK;
372 }
373 
376 {
377  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
378  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
379  return (rcl_timer_callback_t)rcutils_atomic_load_uintptr_t(&timer->impl->callback);
380 }
381 
384 {
385  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Updating timer callback");
386  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
387  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
388  return (rcl_timer_callback_t)rcutils_atomic_exchange_uintptr_t(
389  &timer->impl->callback, (uintptr_t)new_callback);
390 }
391 
392 rcl_ret_t
394 {
395  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
396  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_TIMER_INVALID);
397 
398  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
399  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
400  rcutils_atomic_store(&timer->impl->canceled, true);
401  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Timer canceled");
402  return RCL_RET_OK;
403 }
404 
405 rcl_ret_t
406 rcl_timer_is_canceled(const rcl_timer_t * timer, bool * is_canceled)
407 {
408  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
409  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
410  RCL_CHECK_ARGUMENT_FOR_NULL(is_canceled, RCL_RET_INVALID_ARGUMENT);
411  *is_canceled = rcutils_atomic_load_bool(&timer->impl->canceled);
412  return RCL_RET_OK;
413 }
414 
415 rcl_ret_t
417 {
418  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
419 
420  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
421  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
423  rcl_ret_t now_ret = rcl_clock_get_now(timer->impl->clock, &now);
424  if (now_ret != RCL_RET_OK) {
425  return now_ret; // rcl error state should already be set.
426  }
427  int64_t period = rcutils_atomic_load_uint64_t(&timer->impl->period);
428  rcutils_atomic_store(&timer->impl->next_call_time, now + period);
429  rcutils_atomic_store(&timer->impl->canceled, false);
430  rcl_ret_t ret = rcl_trigger_guard_condition(&timer->impl->guard_condition);
431  if (ret != RCL_RET_OK) {
432  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to trigger timer guard condition");
433  }
434  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Timer successfully reset");
435  return RCL_RET_OK;
436 }
437 
438 const rcl_allocator_t *
440 {
441  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
442  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
443  return &timer->impl->allocator;
444 }
445 
448 {
449  if (NULL == timer || NULL == timer->impl || NULL == timer->impl->guard_condition.impl) {
450  return NULL;
451  }
452  return &timer->impl->guard_condition;
453 }
454 
455 #ifdef __cplusplus
456 }
457 #endif
#define RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, msg, fail_statement)
Check that the given allocator is initialized, or fail with a message.
Definition: allocator.h:56
rcutils_allocator_t rcl_allocator_t
Encapsulation of an allocator.
Definition: allocator.h:31
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_t rcl_get_zero_initialized_guard_condition(void)
Return a rcl_guard_condition_t struct with members set to NULL.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_trigger_guard_condition(rcl_guard_condition_t *guard_condition)
Trigger a rcl guard condition.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_guard_condition_init(rcl_guard_condition_t *guard_condition, rcl_context_t *context, const rcl_guard_condition_options_t options)
Initialize a rcl guard_condition.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_guard_condition_fini(rcl_guard_condition_t *guard_condition)
Finalize a rcl_guard_condition_t.
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_options_t rcl_guard_condition_get_default_options(void)
Return the default options in a rcl_guard_condition_options_t struct.
Encapsulation of a time source.
Definition: time.h:138
rcl_clock_type_t type
Clock type.
Definition: time.h:140
Encapsulates the non-global state of an init/shutdown cycle.
Definition: context.h:114
rcl_duration_value_t nanoseconds
Duration in nanoseconds and its source.
Definition: time.h:77
Options available for a rcl guard condition.
Handle for a rcl guard condition.
rcl_guard_condition_impl_t * impl
Pointer to the guard condition implementation.
Describe the prerequisites for calling a time jump callback.
Definition: time.h:114
rcl_duration_t min_forward
Definition: time.h:119
bool on_clock_change
True to call callback when the clock type changes.
Definition: time.h:116
rcl_duration_t min_backward
Definition: time.h:122
Struct to describe a jump in time.
Definition: time.h:95
rcl_clock_change_t clock_change
Indicate whether or not the source of time changed.
Definition: time.h:97
Structure which encapsulates a ROS Timer.
Definition: timer.h:39
rcl_timer_impl_t * impl
Private implementation pointer.
Definition: timer.h:41
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_clock_get_now(rcl_clock_t *clock, rcl_time_point_value_t *time_point_value)
Fill the time point value with the current value of the associated clock.
Definition: time.c:263
@ RCL_ROS_TIME_DEACTIVATED
The source switched to SYSTEM_TIME from ROS_TIME.
Definition: time.h:88
@ RCL_ROS_TIME_ACTIVATED
The source switched to ROS_TIME from SYSTEM_TIME.
Definition: time.h:86
rcutils_time_point_value_t rcl_time_point_value_t
A single point in time, measured in nanoseconds since the Unix epoch.
Definition: time.h:46
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_clock_add_jump_callback(rcl_clock_t *clock, rcl_jump_threshold_t threshold, rcl_jump_callback_t callback, void *user_data)
Add a callback to be called when a time jump exceeds a threshold.
Definition: time.c:392
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_clock_remove_jump_callback(rcl_clock_t *clock, rcl_jump_callback_t callback, void *user_data)
Remove a previously added time jump callback.
Definition: time.c:436
@ RCL_ROS_TIME
Use ROS time.
Definition: time.h:66
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_get_time_since_last_call(const rcl_timer_t *timer, int64_t *time_since_last_call)
Retrieve the time since the previous call to rcl_timer_call() occurred.
void(* rcl_timer_callback_t)(rcl_timer_t *, int64_t)
User callback signature for timers.
Definition: timer.h:57
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_get_time_until_next_call(const rcl_timer_t *timer, int64_t *time_until_next_call)
Calculate and retrieve the time until the next call in nanoseconds.
Definition: timer.c:313
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_call(rcl_timer_t *timer)
Call the timer's callback and set the last call time.
Definition: timer.c:243
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_init(rcl_timer_t *timer, rcl_clock_t *clock, rcl_context_t *context, int64_t period, const rcl_timer_callback_t callback, rcl_allocator_t allocator)
Initialize a timer.
Definition: timer.c:127
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_reset(rcl_timer_t *timer)
Reset a timer.
Definition: timer.c:416
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_get_period(const rcl_timer_t *timer, int64_t *period)
Retrieve the period of the timer.
Definition: timer.c:350
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_exchange_period(const rcl_timer_t *timer, int64_t new_period, int64_t *old_period)
Exchange the period of the timer and return the previous period.
Definition: timer.c:360
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_clock(rcl_timer_t *timer, rcl_clock_t **clock)
Retrieve the clock of the timer.
Definition: timer.c:233
RCL_PUBLIC RCL_WARN_UNUSED rcl_timer_callback_t rcl_timer_get_callback(const rcl_timer_t *timer)
Return the current timer callback.
Definition: timer.c:375
RCL_PUBLIC RCL_WARN_UNUSED rcl_timer_callback_t rcl_timer_exchange_callback(rcl_timer_t *timer, const rcl_timer_callback_t new_callback)
Exchange the current timer callback and return the current callback.
Definition: timer.c:383
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_cancel(rcl_timer_t *timer)
Cancel a timer.
Definition: timer.c:393
RCL_PUBLIC RCL_WARN_UNUSED rcl_guard_condition_t * rcl_timer_get_guard_condition(const rcl_timer_t *timer)
Retrieve a guard condition used by the timer to wake the waitset when using ROSTime.
Definition: timer.c:447
RCL_PUBLIC RCL_WARN_UNUSED rcl_timer_t rcl_get_zero_initialized_timer(void)
Return a zero initialized timer.
Definition: timer.c:56
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_fini(rcl_timer_t *timer)
Finalize a timer.
Definition: timer.c:204
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_is_canceled(const rcl_timer_t *timer, bool *is_canceled)
Retrieve the canceled state of a timer.
Definition: timer.c:406
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_is_ready(const rcl_timer_t *timer, bool *is_ready)
Calculates whether or not the timer should be called.
Definition: timer.c:295
RCL_PUBLIC RCL_WARN_UNUSED const rcl_allocator_t * rcl_timer_get_allocator(const rcl_timer_t *timer)
Return the allocator for the timer.
Definition: timer.c:439
#define RCL_RET_TIMER_INVALID
Invalid rcl_timer_t given return code.
Definition: types.h:90
#define RCL_RET_ALREADY_INIT
rcl_init() already called return code.
Definition: types.h:40
#define RCL_RET_OK
Success return code.
Definition: types.h:26
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:32
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:34
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:28
#define RCL_RET_TIMER_CANCELED
Given timer was canceled return code.
Definition: types.h:92
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:23