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