ROS 2 rclcpp + rcl - jazzy  jazzy
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, which is initialized as int64_t
42  // to be used for internal time calculation.
43  atomic_int_least64_t period;
44  // This is a time in nanoseconds since an unspecified time.
45  atomic_int_least64_t last_call_time;
46  // This is a time in nanoseconds since an unspecified time.
47  atomic_int_least64_t next_call_time;
48  // Credit for time elapsed before ROS time is activated or deactivated.
49  atomic_int_least64_t time_credit;
50  // A flag which indicates if the timer is canceled.
51  atomic_bool canceled;
52  // The user supplied allocator.
53  rcl_allocator_t allocator;
54  // The user supplied on reset callback data.
56 };
57 
60 {
61  static rcl_timer_t null_timer = {0};
62  return null_timer;
63 }
64 
65 void _rcl_timer_time_jump(
66  const rcl_time_jump_t * time_jump,
67  bool before_jump,
68  void * user_data)
69 {
70  rcl_timer_t * timer = (rcl_timer_t *)user_data;
71 
72  if (before_jump) {
73  if (RCL_ROS_TIME_ACTIVATED == time_jump->clock_change ||
75  {
77  if (RCL_RET_OK != rcl_clock_get_now(timer->impl->clock, &now)) {
78  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to get current time in jump callback");
79  return;
80  }
81  // Source of time is changing, but the timer has ellapsed some portion of its period
82  // Save ellapsed duration pre jump so the timer only waits the remainder in the new epoch
83  if (0 == now) {
84  // No time credit if clock is uninitialized
85  return;
86  }
87  const int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
88  rcutils_atomic_store(&timer->impl->time_credit, next_call_time - now);
89  }
90  } else {
92  if (RCL_RET_OK != rcl_clock_get_now(timer->impl->clock, &now)) {
93  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to get current time in jump callback");
94  return;
95  }
96  const int64_t last_call_time = rcutils_atomic_load_int64_t(&timer->impl->last_call_time);
97  const int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
98  const int64_t period = rcutils_atomic_load_int64_t(&timer->impl->period);
99  if (RCL_ROS_TIME_ACTIVATED == time_jump->clock_change ||
101  {
102  // ROS time activated or deactivated
103  if (0 == now) {
104  // Can't apply time credit if clock is uninitialized
105  return;
106  }
107  int64_t time_credit = rcutils_atomic_exchange_int64_t(&timer->impl->time_credit, 0);
108  if (time_credit) {
109  // set times in new epoch so timer only waits the remainder of the period
110  rcutils_atomic_store(&timer->impl->next_call_time, now - time_credit + period);
111  rcutils_atomic_store(&timer->impl->last_call_time, now - time_credit);
112  }
113  } else if (next_call_time <= now) {
114  // Post Forward jump and timer is ready
115  if (RCL_RET_OK != rcl_trigger_guard_condition(&timer->impl->guard_condition)) {
116  RCUTILS_LOG_ERROR_NAMED(
117  ROS_PACKAGE_NAME, "Failed to get trigger guard condition in jump callback");
118  }
119  } else if (now < last_call_time) {
120  // Post backwards time jump that went further back than 1 period
121  // next callback should happen after 1 period
122  rcutils_atomic_store(&timer->impl->next_call_time, now + period);
123  rcutils_atomic_store(&timer->impl->last_call_time, now);
124  return;
125  }
126  }
127 }
128 
129 rcl_ret_t
131  rcl_timer_t * timer,
132  rcl_clock_t * clock,
133  rcl_context_t * context,
134  int64_t period,
135  const rcl_timer_callback_t callback,
136  rcl_allocator_t allocator)
137 {
138  return rcl_timer_init2(
139  timer, clock, context, period, callback,
140  allocator, true);
141 }
142 
143 rcl_ret_t
145  rcl_timer_t * timer,
146  rcl_clock_t * clock,
147  rcl_context_t * context,
148  int64_t period,
149  const rcl_timer_callback_t callback,
150  rcl_allocator_t allocator,
151  bool autostart)
152 {
153  RCL_CHECK_ALLOCATOR_WITH_MSG(&allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
154  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
155  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
156  if (period < 0) {
157  RCL_SET_ERROR_MSG("timer period must be non-negative");
159  }
160  RCUTILS_LOG_DEBUG_NAMED(
161  ROS_PACKAGE_NAME, "Initializing timer with period: %" PRIu64 "ns", period);
162  if (timer->impl) {
163  RCL_SET_ERROR_MSG("timer already initialized, or memory was uninitialized");
164  return RCL_RET_ALREADY_INIT;
165  }
167  rcl_ret_t now_ret = rcl_clock_get_now(clock, &now);
168  if (now_ret != RCL_RET_OK) {
169  return now_ret; // rcl error state should already be set.
170  }
171  rcl_timer_impl_t impl;
172  impl.clock = clock;
173  impl.context = context;
174  impl.guard_condition = rcl_get_zero_initialized_guard_condition();
176  rcl_ret_t ret = rcl_guard_condition_init(&(impl.guard_condition), context, options);
177  if (RCL_RET_OK != ret) {
178  return ret;
179  }
180  if (RCL_ROS_TIME == impl.clock->type) {
181  rcl_jump_threshold_t threshold;
182  threshold.on_clock_change = true;
183  threshold.min_forward.nanoseconds = 1;
184  threshold.min_backward.nanoseconds = -1;
185  ret = rcl_clock_add_jump_callback(clock, threshold, _rcl_timer_time_jump, timer);
186  if (RCL_RET_OK != ret) {
187  if (RCL_RET_OK != rcl_guard_condition_fini(&(impl.guard_condition))) {
188  // Should be impossible
189  RCUTILS_LOG_ERROR_NAMED(
190  ROS_PACKAGE_NAME, "Failed to fini guard condition after failing to add jump callback");
191  }
192  return ret;
193  }
194  }
195  atomic_init(&impl.callback, (uintptr_t)callback);
196  atomic_init(&impl.period, period);
197  atomic_init(&impl.time_credit, 0);
198  atomic_init(&impl.last_call_time, now);
199  atomic_init(&impl.next_call_time, now + period);
200  atomic_init(&impl.canceled, !autostart);
201  impl.allocator = allocator;
202 
203  // Empty init on reset callback data
204  impl.callback_data.on_reset_callback = NULL;
205  impl.callback_data.user_data = NULL;
206  impl.callback_data.reset_counter = 0;
207 
208  timer->impl = (rcl_timer_impl_t *)allocator.allocate(sizeof(rcl_timer_impl_t), allocator.state);
209  if (NULL == timer->impl) {
210  if (RCL_RET_OK != rcl_guard_condition_fini(&(impl.guard_condition))) {
211  // Should be impossible
212  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to fini guard condition after bad alloc");
213  }
214  if (RCL_RET_OK != rcl_clock_remove_jump_callback(clock, _rcl_timer_time_jump, timer)) {
215  // Should be impossible
216  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to remove callback after bad alloc");
217  }
218 
219  RCL_SET_ERROR_MSG("allocating memory failed");
220  return RCL_RET_BAD_ALLOC;
221  }
222  *timer->impl = impl;
223  TRACETOOLS_TRACEPOINT(rcl_timer_init, (const void *)timer, period);
224  return RCL_RET_OK;
225 }
226 
227 rcl_ret_t
229 {
230  if (!timer || !timer->impl) {
231  return RCL_RET_OK;
232  }
233  // Will return either RCL_RET_OK or RCL_RET_ERROR since the timer is valid.
234  rcl_ret_t result = rcl_timer_cancel(timer);
235  rcl_allocator_t allocator = timer->impl->allocator;
236  rcl_ret_t fail_ret;
237  if (RCL_ROS_TIME == timer->impl->clock->type) {
238  // The jump callbacks use the guard condition, so we have to remove it
239  // before freeing the guard condition below.
240  fail_ret = rcl_clock_remove_jump_callback(timer->impl->clock, _rcl_timer_time_jump, timer);
241  if (RCL_RET_OK != fail_ret) {
242  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to remove timer jump callback");
243  }
244  }
245  fail_ret = rcl_guard_condition_fini(&(timer->impl->guard_condition));
246  if (RCL_RET_OK != fail_ret) {
247  RCL_SET_ERROR_MSG("Failure to fini guard condition");
248  }
249  allocator.deallocate(timer->impl, allocator.state);
250  timer->impl = NULL;
251  return result;
252 }
253 
254 RCL_PUBLIC
255 RCL_WARN_UNUSED
256 rcl_ret_t
257 rcl_timer_clock(const rcl_timer_t * timer, rcl_clock_t ** clock)
258 {
259  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
260  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
261  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
262  *clock = timer->impl->clock;
263  return RCL_RET_OK;
264 }
265 
266 rcl_ret_t
268 {
270  return rcl_timer_call_with_info(timer, &info);
271 }
272 
273 rcl_ret_t
275 {
276  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Calling timer");
277  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
278  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
279  RCL_CHECK_ARGUMENT_FOR_NULL(call_info, RCL_RET_INVALID_ARGUMENT);
280  if (rcutils_atomic_load_bool(&timer->impl->canceled)) {
281  RCL_SET_ERROR_MSG("timer is canceled");
282  return RCL_RET_TIMER_CANCELED;
283  }
285  rcl_ret_t now_ret = rcl_clock_get_now(timer->impl->clock, &now);
286  if (now_ret != RCL_RET_OK) {
287  return now_ret; // rcl error state should already be set.
288  }
289  if (now < 0) {
290  RCL_SET_ERROR_MSG("clock now returned negative time point value");
291  return RCL_RET_ERROR;
292  }
293  rcl_time_point_value_t previous_ns =
294  rcutils_atomic_exchange_int64_t(&timer->impl->last_call_time, now);
295  rcl_timer_callback_t typed_callback =
296  (rcl_timer_callback_t)rcutils_atomic_load_uintptr_t(&timer->impl->callback);
297 
298  int64_t next_call_time = rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
299  call_info->expected_call_time = next_call_time;
300  call_info->actual_call_time = now;
301  int64_t period = rcutils_atomic_load_int64_t(&timer->impl->period);
302  // always move the next call time by exactly period forward
303  // don't use now as the base to avoid extending each cycle by the time
304  // between the timer being ready and the callback being triggered
305  next_call_time += period;
306  // in case the timer has missed at least once cycle
307  if (next_call_time <= now) {
308  if (0 == period) {
309  // a timer with a period of zero is considered always ready
310  next_call_time = now;
311  } else {
312  // move the next call time forward by as many periods as necessary
313  int64_t now_ahead = now - next_call_time;
314  // rounding up without overflow
315  int64_t periods_ahead = 1 + now_ahead / period;
316  next_call_time += periods_ahead * period;
317  }
318  }
319  rcutils_atomic_store(&timer->impl->next_call_time, next_call_time);
320 
321  if (typed_callback != NULL) {
322  int64_t since_last_call = now - previous_ns;
323  typed_callback(timer, since_last_call);
324  }
325  return RCL_RET_OK;
326 }
327 
328 rcl_ret_t
329 rcl_timer_is_ready(const rcl_timer_t * timer, bool * is_ready)
330 {
331  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
332  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
333  RCL_CHECK_ARGUMENT_FOR_NULL(is_ready, RCL_RET_INVALID_ARGUMENT);
334  int64_t time_until_next_call;
335  rcl_ret_t ret = rcl_timer_get_time_until_next_call(timer, &time_until_next_call);
336  if (ret == RCL_RET_TIMER_CANCELED) {
337  *is_ready = false;
338  return RCL_RET_OK;
339  } else if (ret != RCL_RET_OK) {
340  return ret; // rcl error state should already be set.
341  }
342  *is_ready = (time_until_next_call <= 0);
343  return RCL_RET_OK;
344 }
345 
346 rcl_ret_t
347 rcl_timer_get_next_call_time(const rcl_timer_t * timer, int64_t * next_call_time)
348 {
349  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
350  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
351  RCL_CHECK_ARGUMENT_FOR_NULL(next_call_time, RCL_RET_INVALID_ARGUMENT);
352 
353  if (rcutils_atomic_load_bool(&timer->impl->canceled)) {
354  return RCL_RET_TIMER_CANCELED;
355  }
356 
357  *next_call_time =
358  rcutils_atomic_load_int64_t(&timer->impl->next_call_time);
359  return RCL_RET_OK;
360 }
361 
362 rcl_ret_t
363 rcl_timer_get_time_until_next_call(const rcl_timer_t * timer, int64_t * time_until_next_call)
364 {
365  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
366  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
367  RCL_CHECK_ARGUMENT_FOR_NULL(time_until_next_call, RCL_RET_INVALID_ARGUMENT);
368  if (rcutils_atomic_load_bool(&timer->impl->canceled)) {
369  return RCL_RET_TIMER_CANCELED;
370  }
372  rcl_ret_t ret = rcl_clock_get_now(timer->impl->clock, &now);
373  if (ret != RCL_RET_OK) {
374  return ret; // rcl error state should already be set.
375  }
376  *time_until_next_call =
377  rcutils_atomic_load_int64_t(&timer->impl->next_call_time) - now;
378  return RCL_RET_OK;
379 }
380 
381 rcl_ret_t
383  const rcl_timer_t * timer,
384  rcl_time_point_value_t * time_since_last_call)
385 {
386  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
387  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
388  RCL_CHECK_ARGUMENT_FOR_NULL(time_since_last_call, RCL_RET_INVALID_ARGUMENT);
390  rcl_ret_t ret = rcl_clock_get_now(timer->impl->clock, &now);
391  if (ret != RCL_RET_OK) {
392  return ret; // rcl error state should already be set.
393  }
394  *time_since_last_call =
395  now - rcutils_atomic_load_int64_t(&timer->impl->last_call_time);
396  return RCL_RET_OK;
397 }
398 
399 rcl_ret_t
400 rcl_timer_get_period(const rcl_timer_t * timer, int64_t * period)
401 {
402  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
403  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
404  RCL_CHECK_ARGUMENT_FOR_NULL(period, RCL_RET_INVALID_ARGUMENT);
405  *period = rcutils_atomic_load_int64_t(&timer->impl->period);
406  return RCL_RET_OK;
407 }
408 
409 rcl_ret_t
410 rcl_timer_exchange_period(const rcl_timer_t * timer, int64_t new_period, int64_t * old_period)
411 {
412  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
413 
414  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
415  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
416  RCL_CHECK_ARGUMENT_FOR_NULL(old_period, RCL_RET_INVALID_ARGUMENT);
417  *old_period = rcutils_atomic_exchange_int64_t(&timer->impl->period, new_period);
418  RCUTILS_LOG_DEBUG_NAMED(
419  ROS_PACKAGE_NAME, "Updated timer period from '%" PRIu64 "ns' to '%" PRIu64 "ns'",
420  *old_period, new_period);
421  return RCL_RET_OK;
422 }
423 
426 {
427  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
428  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
429  return (rcl_timer_callback_t)rcutils_atomic_load_uintptr_t(&timer->impl->callback);
430 }
431 
434 {
435  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Updating timer callback");
436  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
437  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
438  return (rcl_timer_callback_t)rcutils_atomic_exchange_uintptr_t(
439  &timer->impl->callback, (uintptr_t)new_callback);
440 }
441 
442 rcl_ret_t
444 {
445  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
446  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_TIMER_INVALID);
447 
448  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
449  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
450  rcutils_atomic_store(&timer->impl->canceled, true);
451  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Timer canceled");
452  return RCL_RET_OK;
453 }
454 
455 rcl_ret_t
456 rcl_timer_is_canceled(const rcl_timer_t * timer, bool * is_canceled)
457 {
458  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
459  RCL_CHECK_ARGUMENT_FOR_NULL(timer->impl, RCL_RET_TIMER_INVALID);
460  RCL_CHECK_ARGUMENT_FOR_NULL(is_canceled, RCL_RET_INVALID_ARGUMENT);
461  *is_canceled = rcutils_atomic_load_bool(&timer->impl->canceled);
462  return RCL_RET_OK;
463 }
464 
465 rcl_ret_t
467 {
468  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
469 
470  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
471  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return RCL_RET_TIMER_INVALID);
473  rcl_ret_t now_ret = rcl_clock_get_now(timer->impl->clock, &now);
474  if (now_ret != RCL_RET_OK) {
475  return now_ret; // rcl error state should already be set.
476  }
477  int64_t period = rcutils_atomic_load_int64_t(&timer->impl->period);
478  rcutils_atomic_store(&timer->impl->next_call_time, now + period);
479  rcutils_atomic_store(&timer->impl->canceled, false);
480  rcl_ret_t ret = rcl_trigger_guard_condition(&timer->impl->guard_condition);
481 
482  rcl_timer_on_reset_callback_data_t * cb_data = &timer->impl->callback_data;
483 
484  if (cb_data->on_reset_callback) {
485  cb_data->on_reset_callback(cb_data->user_data, 1);
486  } else {
487  cb_data->reset_counter++;
488  }
489 
490  if (ret != RCL_RET_OK) {
491  RCUTILS_LOG_ERROR_NAMED(ROS_PACKAGE_NAME, "Failed to trigger timer guard condition");
492  }
493  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Timer successfully reset");
494  return RCL_RET_OK;
495 }
496 
497 const rcl_allocator_t *
499 {
500  RCL_CHECK_ARGUMENT_FOR_NULL(timer, NULL);
501  RCL_CHECK_FOR_NULL_WITH_MSG(timer->impl, "timer is invalid", return NULL);
502  return &timer->impl->allocator;
503 }
504 
507 {
508  if (NULL == timer || NULL == timer->impl || NULL == timer->impl->guard_condition.impl) {
509  return NULL;
510  }
511  return &timer->impl->guard_condition;
512 }
513 
514 rcl_ret_t
516  const rcl_timer_t * timer,
517  rcl_event_callback_t on_reset_callback,
518  const void * user_data)
519 {
520  RCL_CHECK_ARGUMENT_FOR_NULL(timer, RCL_RET_INVALID_ARGUMENT);
521 
522  rcl_timer_on_reset_callback_data_t * cb_data = &timer->impl->callback_data;
523 
524  if (on_reset_callback) {
525  cb_data->on_reset_callback = on_reset_callback;
526  cb_data->user_data = user_data;
527  if (cb_data->reset_counter) {
528  cb_data->on_reset_callback(user_data, cb_data->reset_counter);
529  cb_data->reset_counter = 0;
530  }
531  } else {
532  cb_data->on_reset_callback = NULL;
533  cb_data->user_data = NULL;
534  }
535 
536  return RCL_RET_OK;
537 }
538 
539 #ifdef __cplusplus
540 }
541 #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 timer information when called.
Definition: timer.h:56
Structure which encapsulates the on reset callback data.
Definition: timer.h:48
Structure which encapsulates a ROS Timer.
Definition: timer.h:41
rcl_timer_impl_t * impl
Private implementation pointer.
Definition: timer.h:43
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_next_call_time(const rcl_timer_t *timer, int64_t *next_call_time)
Retrieve the time when the next call to rcl_timer_call() shall occur.
Definition: timer.c:347
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:74
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:363
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:267
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_reset(rcl_timer_t *timer)
Reset a timer.
Definition: timer.c:466
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:400
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_set_on_reset_callback(const rcl_timer_t *timer, rcl_event_callback_t on_reset_callback, const void *user_data)
Set the on reset callback function for the timer.
Definition: timer.c:515
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:410
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:425
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:433
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_init2(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, bool autostart)
Initialize a timer.
Definition: timer.c:144
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_cancel(rcl_timer_t *timer)
Cancel a timer.
Definition: timer.c:443
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:506
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_clock(const rcl_timer_t *timer, rcl_clock_t **clock)
Retrieve the clock of the timer.
Definition: timer.c:257
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_call_with_info(rcl_timer_t *timer, rcl_timer_call_info_t *call_info)
Same as rcl_timer_call() except that it also retrieves the actual and expected call time.
Definition: timer.c:274
RCL_PUBLIC RCL_WARN_UNUSED rcl_timer_t rcl_get_zero_initialized_timer(void)
Return a zero initialized timer.
Definition: timer.c:59
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_timer_fini(rcl_timer_t *timer)
Finalize a timer.
Definition: timer.c:228
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:456
RCL_PUBLIC 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)
Definition: timer.c:130
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:329
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:498
#define RCL_RET_TIMER_INVALID
Invalid rcl_timer_t given return code.
Definition: types.h:93
#define RCL_RET_ALREADY_INIT
rcl_init() already called return code.
Definition: types.h:41
#define RCL_RET_OK
Success return code.
Definition: types.h:27
#define RCL_RET_BAD_ALLOC
Failed to allocate memory return code.
Definition: types.h:33
#define RCL_RET_INVALID_ARGUMENT
Invalid argument return code.
Definition: types.h:35
#define RCL_RET_ERROR
Unspecified error return code.
Definition: types.h:29
#define RCL_RET_TIMER_CANCELED
Given timer was canceled return code.
Definition: types.h:95
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24