ROS 2 rclcpp + rcl - lyrical  lyrical
ROS 2 C++ Client Library with ROS Client Library
event.c
1 // Copyright 2019 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/event.h"
21 
22 #include <stdio.h>
23 
24 #include "rcl/error_handling.h"
25 #include "rcl/expand_topic_name.h"
26 #include "rcl/remap.h"
27 #include "rcutils/allocator.h"
28 #include "rcutils/logging_macros.h"
29 #include "rmw/error_handling.h"
30 #include "rmw/validate_full_topic_name.h"
31 #include "rmw/event.h"
32 
33 #include "./common.h"
34 #include "./event_impl.h"
35 #include "./publisher_impl.h"
36 #include "./subscription_impl.h"
37 
40 {
41  // All members are initialized to 0 or NULL by C99 6.7.8/10.
42  static rcl_event_t null_event;
43  return null_event;
44 }
45 
48  rcl_event_t * event,
49  const rcl_publisher_t * publisher,
50  const rcl_publisher_event_type_t event_type)
51 {
52  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
53  // Check publisher and allocator first, so allocator can be used with errors.
54  RCL_CHECK_ARGUMENT_FOR_NULL(publisher, RCL_RET_INVALID_ARGUMENT);
55  rcl_allocator_t * allocator = &publisher->impl->options.allocator;
56  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
57  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
58  switch (event_type) {
59  case RCL_PUBLISHER_OFFERED_DEADLINE_MISSED:
60  rmw_event_type = RMW_EVENT_OFFERED_DEADLINE_MISSED;
61  break;
62  case RCL_PUBLISHER_LIVELINESS_LOST:
63  rmw_event_type = RMW_EVENT_LIVELINESS_LOST;
64  break;
65  case RCL_PUBLISHER_OFFERED_INCOMPATIBLE_QOS:
66  rmw_event_type = RMW_EVENT_OFFERED_QOS_INCOMPATIBLE;
67  break;
68  case RCL_PUBLISHER_INCOMPATIBLE_TYPE:
69  rmw_event_type = RMW_EVENT_PUBLISHER_INCOMPATIBLE_TYPE;
70  break;
71  case RCL_PUBLISHER_MATCHED:
72  rmw_event_type = RMW_EVENT_PUBLICATION_MATCHED;
73  break;
74  }
75  if (rmw_event_type == RMW_EVENT_INVALID) {
76  RCL_SET_ERROR_MSG("Event type for publisher not supported");
78  }
79 
80  // Allocate space for the implementation struct.
81  event->impl = (rcl_event_impl_t *) allocator->allocate(
82  sizeof(rcl_event_impl_t), allocator->state);
83  RCL_CHECK_FOR_NULL_WITH_MSG(
84  event->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
85 
86  event->impl->rmw_handle = rmw_get_zero_initialized_event();
87  event->impl->allocator = *allocator;
88 
89  rmw_ret_t ret = rmw_publisher_event_init(
90  &event->impl->rmw_handle,
91  publisher->impl->rmw_handle,
92  rmw_event_type);
93  if (ret != RMW_RET_OK) {
94  goto fail;
95  }
96 
97  return RCL_RET_OK;
98 fail:
99  allocator->deallocate(event->impl, allocator->state);
100  event->impl = NULL;
101  return rcl_convert_rmw_ret_to_rcl_ret(ret);
102 }
103 
104 rcl_ret_t
106  rcl_event_t * event,
107  const rcl_subscription_t * subscription,
108  const rcl_subscription_event_type_t event_type)
109 {
110  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
111  // Check subscription and allocator first, so allocator can be used with errors.
112  RCL_CHECK_ARGUMENT_FOR_NULL(subscription, RCL_RET_INVALID_ARGUMENT);
113  rcl_allocator_t * allocator = &subscription->impl->options.allocator;
114  RCL_CHECK_ALLOCATOR_WITH_MSG(allocator, "invalid allocator", return RCL_RET_INVALID_ARGUMENT);
115  rmw_event_type_t rmw_event_type = RMW_EVENT_INVALID;
116  switch (event_type) {
117  case RCL_SUBSCRIPTION_REQUESTED_DEADLINE_MISSED:
118  rmw_event_type = RMW_EVENT_REQUESTED_DEADLINE_MISSED;
119  break;
120  case RCL_SUBSCRIPTION_LIVELINESS_CHANGED:
121  rmw_event_type = RMW_EVENT_LIVELINESS_CHANGED;
122  break;
123  case RCL_SUBSCRIPTION_REQUESTED_INCOMPATIBLE_QOS:
124  rmw_event_type = RMW_EVENT_REQUESTED_QOS_INCOMPATIBLE;
125  break;
126  case RCL_SUBSCRIPTION_MESSAGE_LOST:
127  rmw_event_type = RMW_EVENT_MESSAGE_LOST;
128  break;
129  case RCL_SUBSCRIPTION_INCOMPATIBLE_TYPE:
130  rmw_event_type = RMW_EVENT_SUBSCRIPTION_INCOMPATIBLE_TYPE;
131  break;
132  case RCL_SUBSCRIPTION_MATCHED:
133  rmw_event_type = RMW_EVENT_SUBSCRIPTION_MATCHED;
134  break;
135  }
136  if (rmw_event_type == RMW_EVENT_INVALID) {
137  RCL_SET_ERROR_MSG("Event type for subscription not supported");
139  }
140 
141  // Allocate space for the implementation struct.
142  event->impl = (rcl_event_impl_t *) allocator->allocate(
143  sizeof(rcl_event_impl_t), allocator->state);
144  RCL_CHECK_FOR_NULL_WITH_MSG(
145  event->impl, "allocating memory failed", return RCL_RET_BAD_ALLOC);
146 
147  event->impl->rmw_handle = rmw_get_zero_initialized_event();
148  event->impl->allocator = *allocator;
149 
150  rmw_ret_t ret = rmw_subscription_event_init(
151  &event->impl->rmw_handle,
152  subscription->impl->rmw_handle,
153  rmw_event_type);
154  if (ret != RMW_RET_OK) {
155  goto fail;
156  }
157 
158  return RCL_RET_OK;
159 fail:
160  allocator->deallocate(event->impl, allocator->state);
161  event->impl = NULL;
162  return rcl_convert_rmw_ret_to_rcl_ret(ret);
163 }
164 
165 rcl_ret_t
167  const rcl_event_t * event,
168  void * event_info)
169 {
170  bool taken = false;
171  if (!rcl_event_is_valid(event)) {
172  return RCL_RET_EVENT_INVALID;
173  }
174  RCL_CHECK_ARGUMENT_FOR_NULL(event_info, RCL_RET_INVALID_ARGUMENT);
175  rmw_ret_t ret = rmw_take_event(&event->impl->rmw_handle, event_info, &taken);
176  if (RMW_RET_OK != ret) {
177  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
178  return rcl_convert_rmw_ret_to_rcl_ret(ret);
179  }
180  if (!taken) {
181  RCUTILS_LOG_DEBUG_NAMED(
182  ROS_PACKAGE_NAME, "take_event request complete, unable to take event");
184  }
185  RCUTILS_LOG_DEBUG_NAMED(
186  ROS_PACKAGE_NAME, "take_event request success");
187  return rcl_convert_rmw_ret_to_rcl_ret(ret);
188 }
189 
190 rcl_ret_t
192 {
193  rcl_ret_t result = RCL_RET_OK;
194  RCL_CHECK_ARGUMENT_FOR_NULL(event, RCL_RET_EVENT_INVALID);
195 
196  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Finalizing event");
197  if (NULL != event->impl) {
198  rcl_allocator_t allocator = event->impl->allocator;
199  rmw_ret_t ret = rmw_event_fini(&event->impl->rmw_handle);
200  if (ret != RMW_RET_OK) {
201  RCL_SET_ERROR_MSG(rmw_get_error_string().str);
202  result = rcl_convert_rmw_ret_to_rcl_ret(ret);
203  }
204  allocator.deallocate(event->impl, allocator.state);
205  event->impl = NULL;
206  }
207  RCUTILS_LOG_DEBUG_NAMED(ROS_PACKAGE_NAME, "Event finalized");
208 
209  return result;
210 }
211 
212 rmw_event_t *
214 {
215  if (!rcl_event_is_valid(event)) {
216  return NULL; // error already set
217  } else {
218  return &event->impl->rmw_handle;
219  }
220 }
221 
222 bool
224 {
225  RCL_CHECK_FOR_NULL_WITH_MSG(event, "event pointer is invalid", return false);
226  RCL_CHECK_FOR_NULL_WITH_MSG(event->impl, "event's implementation is invalid", return false);
227  if (event->impl->rmw_handle.event_type == RMW_EVENT_INVALID) {
228  RCUTILS_SET_ERROR_MSG("event's implementation not init");
229  return false;
230  }
231  RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
232  &event->impl->allocator, "not valid allocator", return false);
233  return true;
234 }
235 
236 rcl_ret_t
238  const rcl_event_t * event,
239  rcl_event_callback_t callback,
240  const void * user_data)
241 {
242  if (!rcl_event_is_valid(event)) {
243  // error state already set
245  }
246 
247  return rmw_event_set_callback(
248  &event->impl->rmw_handle,
249  callback,
250  user_data);
251 }
252 
253 #ifdef __cplusplus
254 }
255 #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_ret_t rcl_take_event(const rcl_event_t *event, void *event_info)
Definition: event.c:166
enum rcl_publisher_event_type_e rcl_publisher_event_type_t
Enumeration of all of the publisher events that may fire.
RCL_PUBLIC RCL_WARN_UNUSED rcl_event_t rcl_get_zero_initialized_event(void)
Return a rcl_event_t struct with members set to NULL.
Definition: event.c:39
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_event_set_callback(const rcl_event_t *event, rcl_event_callback_t callback, const void *user_data)
Set the callback function for the event.
Definition: event.c:237
enum rcl_subscription_event_type_e rcl_subscription_event_type_t
Enumeration of all of the subscription events that may fire.
RCL_PUBLIC RCL_WARN_UNUSED rmw_event_t * rcl_event_get_rmw_handle(const rcl_event_t *event)
Return the rmw event handle.
Definition: event.c:213
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_subscription_event_init(rcl_event_t *event, const rcl_subscription_t *subscription, const rcl_subscription_event_type_t event_type)
Initialize an rcl_event_t with a subscription.
Definition: event.c:105
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_event_fini(rcl_event_t *event)
Definition: event.c:191
RCL_PUBLIC bool rcl_event_is_valid(const rcl_event_t *event)
Check that the event is valid.
Definition: event.c:223
RCL_PUBLIC RCL_WARN_UNUSED rcl_ret_t rcl_publisher_event_init(rcl_event_t *event, const rcl_publisher_t *publisher, const rcl_publisher_event_type_t event_type)
Initialize an rcl_event_t with a publisher.
Definition: event.c:47
Structure which encapsulates a ROS QoS event handle.
Definition: event.h:61
rcl_event_impl_t * impl
Pointer to the event implementation.
Definition: event.h:63
rcl_allocator_t allocator
Custom allocator for the publisher, used for incidental allocations.
Definition: publisher.h:49
Structure which encapsulates a ROS Publisher.
Definition: publisher.h:37
rcl_publisher_impl_t * impl
Pointer to the publisher implementation.
Definition: publisher.h:39
rcl_allocator_t allocator
Custom allocator for the subscription, used for incidental allocations.
Definition: subscription.h:52
Structure which encapsulates a ROS Subscription.
Definition: subscription.h:40
rcl_subscription_impl_t * impl
Pointer to the subscription implementation.
Definition: subscription.h:42
#define RCL_RET_EVENT_TAKE_FAILED
Failed to take an event from the event handle.
Definition: types.h:121
#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_EVENT_INVALID
Invalid rcl_event_t given return code.
Definition: types.h:119
rmw_ret_t rcl_ret_t
The type that holds an rcl return code.
Definition: types.h:24