ROS 2 rclcpp + rcl - jazzy  jazzy
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  default:
116  }
117 }
118 
119 static void
120 rcl_clock_generic_fini(
121  rcl_clock_t * clock)
122 {
123  // Internal function; assume caller has already checked that clock is valid.
124  if (clock->num_jump_callbacks > 0) {
125  clock->num_jump_callbacks = 0;
126  clock->allocator.deallocate(clock->jump_callbacks, clock->allocator.state);
127  clock->jump_callbacks = NULL;
128  }
129 }
130 
131 rcl_ret_t
133  rcl_clock_t * clock)
134 {
135  RCL_CHECK_ARGUMENT_FOR_NULL(clock, RCL_RET_INVALID_ARGUMENT);
137  &clock->allocator, "clock has invalid allocator", return RCL_RET_ERROR);
138  switch (clock->type) {
139  case RCL_ROS_TIME:
140  return rcl_ros_clock_fini(clock);
141  case RCL_SYSTEM_TIME:
142  return rcl_system_clock_fini(clock);
143  case RCL_STEADY_TIME:
144  return rcl_steady_clock_fini(clock);
146  // fall through
147  default:
149  }
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: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: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:132
@ 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:217
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: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: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: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: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: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: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