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