ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
time.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 #include "rcl/time.h"
16 
17 #include <stdbool.h>
18 #include <stdlib.h>
19 
20 #include "./common.h"
21 #include "rcl/allocator.h"
22 #include "rcl/error_handling.h"
23 #include "rcutils/macros.h"
24 #include "rcutils/stdatomic_helper.h"
25 #include "rcutils/time.h"
26 
27 // Internal storage for RCL_ROS_TIME implementation
29 {
30  atomic_uint_least64_t current_time;
31  bool active;
33 
34 // Implementation only
35 static rcl_ret_t
36 rcl_get_steady_time(void * data, rcl_time_point_value_t * current_time)
37 {
38  (void)data; // unused
39  return rcutils_steady_time_now(current_time);
40 }
41 
42 // Implementation only
43 static rcl_ret_t
44 rcl_get_system_time(void * data, rcl_time_point_value_t * current_time)
45 {
46  (void)data; // unused
47  return rcutils_system_time_now(current_time);
48 }
49 
50 // Internal method for zeroing values on init, assumes clock is valid
51 static void
52 rcl_init_generic_clock(rcl_clock_t * clock, rcl_allocator_t * allocator)
53 {
55  clock->jump_callbacks = NULL;
56  clock->num_jump_callbacks = 0u;
57  clock->get_now = NULL;
58  clock->data = NULL;
59  clock->allocator = *allocator;
60 }
61 
62 // The function used to get the current ros time.
63 // This is in the implementation only
64 static rcl_ret_t
65 rcl_get_ros_time(void * data, rcl_time_point_value_t * current_time)
66 {
68  if (!t->active) {
69  return rcl_get_system_time(data, current_time);
70  }
71  *current_time = rcutils_atomic_load_uint64_t(&(t->current_time));
72  return RCL_RET_OK;
73 }
74 
75 bool
77 {
78  rcl_time_point_value_t query_now;
79  if (rcl_clock_get_now(clock, &query_now) == RCL_RET_OK) {
80  return query_now > 0;
81  }
82  return false;
83 }
84 
85 bool
87 {
88  if (clock == NULL ||
89  clock->type == RCL_CLOCK_UNINITIALIZED ||
90  clock->get_now == NULL)
91  {
92  return false;
93  }
94  return true;
95 }
96 
99  rcl_clock_type_t clock_type, rcl_clock_t * clock,
100  rcl_allocator_t * allocator)
101 {
102  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
103  switch (clock_type) {
105  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
106  rcl_init_generic_clock(clock, allocator);
107  return RCL_RET_OK;
108  case RCL_ROS_TIME:
109  return rcl_ros_clock_init(clock, allocator);
110  case RCL_SYSTEM_TIME:
111  return rcl_system_clock_init(clock, allocator);
112  case RCL_STEADY_TIME:
113  return rcl_steady_clock_init(clock, allocator);
114  }
116 }
117 
118 static void
119 rcl_clock_generic_fini(
120  rcl_clock_t * clock)
121 {
122  // Internal function; assume caller has already checked that clock is valid.
123  if (clock->num_jump_callbacks > 0) {
124  clock->num_jump_callbacks = 0;
125  clock->allocator.deallocate(clock->jump_callbacks, clock->allocator.state);
126  clock->jump_callbacks = NULL;
127  }
128 }
129 
130 rcl_ret_t
132  rcl_clock_t * clock)
133 {
134  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
136  &clock->allocator, "clock has invalid allocator", return RCL_RET_ERROR);
137  switch (clock->type) {
138  case RCL_ROS_TIME:
139  return rcl_ros_clock_fini(clock);
140  case RCL_SYSTEM_TIME:
141  return rcl_system_clock_fini(clock);
142  case RCL_STEADY_TIME:
143  return rcl_steady_clock_fini(clock);
146  }
148 }
149 
150 rcl_ret_t
152  rcl_clock_t * clock,
153  rcl_allocator_t * allocator)
154 {
155  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
156  RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT);
157  rcl_init_generic_clock(clock, allocator);
158  clock->data = allocator->allocate(sizeof(rcl_ros_clock_storage_t), allocator->state);
159  if (NULL == clock->data) {
160  RCL_SET_ERROR_MSG("allocating memory failed");
161  return RCL_RET_BAD_ALLOC;
162  }
163 
165  // 0 is a special value meaning time has not been set
166  atomic_init(&(storage->current_time), 0);
167  storage->active = false;
168  clock->get_now = rcl_get_ros_time;
169  clock->type = RCL_ROS_TIME;
170  return RCL_RET_OK;
171 }
172 
173 rcl_ret_t
175  rcl_clock_t * clock)
176 {
177  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
178  if (clock->type != RCL_ROS_TIME) {
179  RCL_SET_ERROR_MSG("clock not of type RCL_ROS_TIME");
180  return RCL_RET_ERROR;
181  }
182  rcl_clock_generic_fini(clock);
183  clock->allocator.deallocate(clock->data, clock->allocator.state);
184  clock->data = NULL;
185  return RCL_RET_OK;
186 }
187 
188 rcl_ret_t
190  rcl_clock_t * clock,
191  rcl_allocator_t * allocator)
192 {
193  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
194  RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT);
195  rcl_init_generic_clock(clock, allocator);
196  clock->get_now = rcl_get_steady_time;
197  clock->type = RCL_STEADY_TIME;
198  return RCL_RET_OK;
199 }
200 
201 rcl_ret_t
203  rcl_clock_t * clock)
204 {
205  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
206  if (clock->type != RCL_STEADY_TIME) {
207  RCL_SET_ERROR_MSG("clock not of type RCL_STEADY_TIME");
208  return RCL_RET_ERROR;
209  }
210  rcl_clock_generic_fini(clock);
211  return RCL_RET_OK;
212 }
213 
214 rcl_ret_t
216  rcl_clock_t * clock,
217  rcl_allocator_t * allocator)
218 {
219  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
220  RCL_CHECK_ARGUMENT_FOR_NULL(allocator, RCL_RET_INVALID_ARGUMENT);
221  rcl_init_generic_clock(clock, allocator);
222  clock->get_now = rcl_get_system_time;
223  clock->type = RCL_SYSTEM_TIME;
224  return RCL_RET_OK;
225 }
226 
227 rcl_ret_t
229  rcl_clock_t * clock)
230 {
231  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
232  if (clock->type != RCL_SYSTEM_TIME) {
233  RCL_SET_ERROR_MSG("clock not of type RCL_SYSTEM_TIME");
234  return RCL_RET_ERROR;
235  }
236  rcl_clock_generic_fini(clock);
237  return RCL_RET_OK;
238 }
239 
240 rcl_ret_t
242  const rcl_time_point_t * start, const rcl_time_point_t * finish, rcl_duration_t * delta)
243 {
244  RCL_CHECK_ARGUMENT_FOR_NULL(start, RCL_RET_INVALID_ARGUMENT);
245  RCL_CHECK_ARGUMENT_FOR_NULL(finish, RCL_RET_INVALID_ARGUMENT);
246  RCL_CHECK_ARGUMENT_FOR_NULL(delta, RCL_RET_INVALID_ARGUMENT);
247  if (start->clock_type != finish->clock_type) {
248  RCL_SET_ERROR_MSG("Cannot difference between time points with clocks types.");
249  return RCL_RET_ERROR;
250  }
251  if (finish->nanoseconds < start->nanoseconds) {
252  rcl_time_point_value_t intermediate = start->nanoseconds - finish->nanoseconds;
253  delta->nanoseconds = -1 * (int64_t) intermediate;
254  } else {
255  delta->nanoseconds = (int64_t)(finish->nanoseconds - start->nanoseconds);
256  }
257  return RCL_RET_OK;
258 }
259 
260 rcl_ret_t
262 {
263  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_INVALID_ARGUMENT);
264  RCUTILS_CAN_RETURN_WITH_ERROR_OF(RCL_RET_ERROR);
265 
266  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
267  RCL_CHECK_ARGUMENT_FOR_NULL(time_point_value, RCL_RET_INVALID_ARGUMENT);
268  if (clock->type && clock->get_now) {
269  return clock->get_now(clock->data, time_point_value);
270  }
271  RCL_SET_ERROR_MSG("Clock is not initialized or does not have get_now registered.");
272  return RCL_RET_ERROR;
273 }
274 
275 static void
276 rcl_clock_call_callbacks(
277  rcl_clock_t * clock, const rcl_time_jump_t * time_jump, bool before_jump)
278 {
279  // Internal function; assume parameters are valid.
280  bool is_clock_change = time_jump->clock_change == RCL_ROS_TIME_ACTIVATED ||
282  for (size_t cb_idx = 0; cb_idx < clock->num_jump_callbacks; ++cb_idx) {
283  rcl_jump_callback_info_t * info = &(clock->jump_callbacks[cb_idx]);
284  if (
285  (is_clock_change && info->threshold.on_clock_change) ||
286  (info->threshold.min_backward.nanoseconds < 0 &&
287  time_jump->delta.nanoseconds <= info->threshold.min_backward.nanoseconds) ||
288  (info->threshold.min_forward.nanoseconds > 0 &&
289  time_jump->delta.nanoseconds >= info->threshold.min_forward.nanoseconds))
290  {
291  info->callback(time_jump, before_jump, info->user_data);
292  }
293  }
294 }
295 
296 rcl_ret_t
298 {
299  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
300  if (clock->type != RCL_ROS_TIME) {
301  RCL_SET_ERROR_MSG("Clock is not of type RCL_ROS_TIME, cannot enable override.");
302  return RCL_RET_ERROR;
303  }
305  RCL_CHECK_FOR_NULL_WITH_MSG(
306  storage, "Clock storage is not initialized, cannot enable override.", return RCL_RET_ERROR);
307  if (!storage->active) {
308  rcl_time_jump_t time_jump;
309  time_jump.delta.nanoseconds = 0;
311  rcl_clock_call_callbacks(clock, &time_jump, true);
312  storage->active = true;
313  rcl_clock_call_callbacks(clock, &time_jump, false);
314  }
315  return RCL_RET_OK;
316 }
317 
318 rcl_ret_t
320 {
321  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
322  if (clock->type != RCL_ROS_TIME) {
323  RCL_SET_ERROR_MSG("Clock is not of type RCL_ROS_TIME, cannot disable override.");
324  return RCL_RET_ERROR;
325  }
327  RCL_CHECK_FOR_NULL_WITH_MSG(
328  storage, "Clock storage is not initialized, cannot enable override.", return RCL_RET_ERROR);
329  if (storage->active) {
330  rcl_time_jump_t time_jump;
331  time_jump.delta.nanoseconds = 0;
333  rcl_clock_call_callbacks(clock, &time_jump, true);
334  storage->active = false;
335  rcl_clock_call_callbacks(clock, &time_jump, false);
336  }
337  return RCL_RET_OK;
338 }
339 
340 rcl_ret_t
342  rcl_clock_t * clock,
343  bool * is_enabled)
344 {
345  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
346  RCL_CHECK_ARGUMENT_FOR_NULL(is_enabled, RCL_RET_INVALID_ARGUMENT);
347  if (clock->type != RCL_ROS_TIME) {
348  RCL_SET_ERROR_MSG("Clock is not of type RCL_ROS_TIME, cannot query override state.");
349  return RCL_RET_ERROR;
350  }
352  RCL_CHECK_FOR_NULL_WITH_MSG(
353  storage, "Clock storage is not initialized, cannot enable override.", return RCL_RET_ERROR);
354  *is_enabled = storage->active;
355  return RCL_RET_OK;
356 }
357 
358 rcl_ret_t
360  rcl_clock_t * clock,
361  rcl_time_point_value_t time_value)
362 {
363  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
364  if (clock->type != RCL_ROS_TIME) {
365  RCL_SET_ERROR_MSG("Clock is not of type RCL_ROS_TIME, cannot set time override.");
366  return RCL_RET_ERROR;
367  }
369  RCL_CHECK_FOR_NULL_WITH_MSG(
370  storage, "Clock storage is not initialized, cannot enable override.", return RCL_RET_ERROR);
371  rcl_time_jump_t time_jump;
372  if (storage->active) {
374  rcl_time_point_value_t current_time;
375  rcl_ret_t ret = rcl_get_ros_time(storage, &current_time);
376  if (RCL_RET_OK != ret) {
377  return ret;
378  }
379  time_jump.delta.nanoseconds = time_value - current_time;
380  rcl_clock_call_callbacks(clock, &time_jump, true);
381  rcutils_atomic_store(&(storage->current_time), time_value);
382  rcl_clock_call_callbacks(clock, &time_jump, false);
383  } else {
384  rcutils_atomic_store(&(storage->current_time), time_value);
385  }
386  return RCL_RET_OK;
387 }
388 
389 rcl_ret_t
391  rcl_clock_t * clock, rcl_jump_threshold_t threshold, rcl_jump_callback_t callback,
392  void * user_data)
393 {
394  // Make sure parameters are valid
395  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
397  &(clock->allocator), "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
398  RCL_CHECK_ARGUMENT_FOR_NULL(callback, RCL_RET_INVALID_ARGUMENT);
399  if (threshold.min_forward.nanoseconds < 0) {
400  RCL_SET_ERROR_MSG("forward jump threshold must be positive or zero");
402  }
403  if (threshold.min_backward.nanoseconds > 0) {
404  RCL_SET_ERROR_MSG("backward jump threshold must be negative or zero");
406  }
407 
408  // Callback/user_data pair must be unique
409  for (size_t cb_idx = 0; cb_idx < clock->num_jump_callbacks; ++cb_idx) {
410  const rcl_jump_callback_info_t * info = &(clock->jump_callbacks[cb_idx]);
411  if (info->callback == callback && info->user_data == user_data) {
412  RCL_SET_ERROR_MSG("callback/user_data are already added to this clock");
413  return RCL_RET_ERROR;
414  }
415  }
416 
417  // Add the new callback, increasing the size of the callback list
418  rcl_jump_callback_info_t * callbacks = clock->allocator.reallocate(
419  clock->jump_callbacks, sizeof(rcl_jump_callback_info_t) * (clock->num_jump_callbacks + 1),
420  clock->allocator.state);
421  if (NULL == callbacks) {
422  RCL_SET_ERROR_MSG("Failed to realloc jump callbacks");
423  return RCL_RET_BAD_ALLOC;
424  }
425  clock->jump_callbacks = callbacks;
426  clock->jump_callbacks[clock->num_jump_callbacks].callback = callback;
427  clock->jump_callbacks[clock->num_jump_callbacks].threshold = threshold;
428  clock->jump_callbacks[clock->num_jump_callbacks].user_data = user_data;
429  ++(clock->num_jump_callbacks);
430  return RCL_RET_OK;
431 }
432 
433 rcl_ret_t
435  rcl_clock_t * clock, rcl_jump_callback_t callback, void * user_data)
436 {
437  // Make sure parameters are valid
438  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
440  &(clock->allocator), "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
441  RCL_CHECK_ARGUMENT_FOR_NULL(callback, RCL_RET_INVALID_ARGUMENT);
442 
443  // Delete callback if found, moving all callbacks after back one
444  bool found_callback = false;
445  for (size_t cb_idx = 0; cb_idx < clock->num_jump_callbacks; ++cb_idx) {
446  const rcl_jump_callback_info_t * info = &(clock->jump_callbacks[cb_idx]);
447  if (found_callback) {
448  clock->jump_callbacks[cb_idx - 1] = *info;
449  } else if (info->callback == callback && info->user_data == user_data) {
450  found_callback = true;
451  }
452  }
453  if (!found_callback) {
454  RCL_SET_ERROR_MSG("jump callback was not found");
455  return RCL_RET_ERROR;
456  }
457 
458  // Shrink size of the callback array
459  if (--(clock->num_jump_callbacks) == 0) {
460  clock->allocator.deallocate(clock->jump_callbacks, clock->allocator.state);
461  clock->jump_callbacks = NULL;
462  } else {
463  rcl_jump_callback_info_t * callbacks = clock->allocator.reallocate(
465  clock->allocator.state);
466  if (NULL == callbacks) {
467  RCL_SET_ERROR_MSG("Failed to shrink jump callbacks");
468  return RCL_RET_BAD_ALLOC;
469  }
470  clock->jump_callbacks = callbacks;
471  }
472  return RCL_RET_OK;
473 }
#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
Encapsulation of a time source.
Definition: time.h:138
rcl_jump_callback_info_t * jump_callbacks
An array of added jump callbacks.
Definition: time.h:142
void * data
Clock storage.
Definition: time.h:149
rcl_allocator_t allocator
Custom allocator used for internal allocations.
Definition: time.h:151
rcl_ret_t(* get_now)(void *data, rcl_time_point_value_t *now)
Pointer to get_now function.
Definition: time.h:146
rcl_clock_type_t type
Clock type.
Definition: time.h:140
size_t num_jump_callbacks
Number of callbacks in jump_callbacks.
Definition: time.h:144
A duration of time, measured in nanoseconds and its source.
Definition: time.h:75
rcl_duration_value_t nanoseconds
Duration in nanoseconds and its source.
Definition: time.h:77
Struct to describe an added callback.
Definition: time.h:127
void * user_data
Pointer passed to the callback.
Definition: time.h:133
rcl_jump_threshold_t threshold
Threshold to decide when to call the callback.
Definition: time.h:131
rcl_jump_callback_t callback
Callback to fucntion.
Definition: time.h:129
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
rcl_duration_t delta
The new time minus the last time before the jump.
Definition: time.h:99
A single point in time, measured in nanoseconds, the reference point is based on the source.
Definition: time.h:156
rcl_clock_type_t clock_type
Clock type of the point in time.
Definition: time.h:160
rcl_time_point_value_t nanoseconds
Nanoseconds of the point in time.
Definition: time.h:158
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_ros_clock_init(rcl_clock_t *clock, rcl_allocator_t *allocator)
Initialize a clock as a RCL_ROS_TIME time source.
Definition: time.c:151
enum rcl_clock_type_e rcl_clock_type_t
Time source type, used to indicate the source of a time measurement.
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_steady_clock_init(rcl_clock_t *clock, rcl_allocator_t *allocator)
Initialize a clock as a RCL_STEADY_TIME time source.
Definition: time.c:189
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_enable_ros_time_override(rcl_clock_t *clock)
Enable the ROS time abstraction override.
Definition: time.c:297
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_difference_times(const rcl_time_point_t *start, const rcl_time_point_t *finish, rcl_duration_t *delta)
Compute the difference between two time points.
Definition: time.c:241
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_steady_clock_fini(rcl_clock_t *clock)
Finalize a clock as a RCL_STEADY_TIME time source.
Definition: time.c:202
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_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_clock_fini(rcl_clock_t *clock)
Finalize a clock.
Definition: time.c:131
@ RCL_ROS_TIME_DEACTIVATED
The source switched to SYSTEM_TIME from ROS_TIME.
Definition: time.h:88
@ RCL_ROS_TIME_NO_CHANGE
The source before and after the jump is ROS_TIME.
Definition: time.h:84
@ 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_system_clock_init(rcl_clock_t *clock, rcl_allocator_t *allocator)
Initialize a clock as a RCL_SYSTEM_TIME time source.
Definition: time.c:215
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_clock_time_started(rcl_clock_t *clock)
Check if the clock has started.
Definition: time.c:76
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_ros_clock_fini(rcl_clock_t *clock)
Finalize a clock as a RCL_ROS_TIME time source.
Definition: time.c:174
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_disable_ros_time_override(rcl_clock_t *clock)
Disable the ROS time abstraction override.
Definition: time.c:319
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
void(* rcl_jump_callback_t)(const rcl_time_jump_t *time_jump, bool before_jump, void *user_data)
Definition: time.h:107
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_is_enabled_ros_time_override(rcl_clock_t *clock, bool *is_enabled)
Check if the RCL_ROS_TIME time source has the override enabled.
Definition: time.c:341
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_SYSTEM_TIME
Use system time.
Definition: time.h:68
@ RCL_CLOCK_UNINITIALIZED
Clock uninitialized.
Definition: time.h:64
@ RCL_STEADY_TIME
Use a steady clock time.
Definition: time.h:70
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_system_clock_fini(rcl_clock_t *clock)
Finalize a clock as a RCL_SYSTEM_TIME time source.
Definition: time.c:228
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_set_ros_time_override(rcl_clock_t *clock, rcl_time_point_value_t time_value)
Set the current time for this RCL_ROS_TIME time source.
Definition: time.c:359
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_clock_init(rcl_clock_type_t clock_type, rcl_clock_t *clock, rcl_allocator_t *allocator)
Initialize a clock based on the passed type.
Definition: time.c:98
RCL_PUBLIC RCL_WARN_UNUSED bool rcl_clock_valid(rcl_clock_t *clock)
Check if the clock has valid values.
Definition: time.c:86
#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
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24