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