rclrb 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/COPYING +373 -0
- data/README.md +13 -0
- data/lib/rclrb/callback_group.rb +31 -0
- data/lib/rclrb/capi.rb +369 -0
- data/lib/rclrb/client.rb +79 -0
- data/lib/rclrb/clock.rb +17 -0
- data/lib/rclrb/common.rb +43 -0
- data/lib/rclrb/executor.rb +34 -0
- data/lib/rclrb/fields.rb +224 -0
- data/lib/rclrb/future.rb +82 -0
- data/lib/rclrb/guard_condition.rb +18 -0
- data/lib/rclrb/init.rb +59 -0
- data/lib/rclrb/interfaces.rb +270 -0
- data/lib/rclrb/internal.rb +16 -0
- data/lib/rclrb/node.rb +143 -0
- data/lib/rclrb/publisher.rb +40 -0
- data/lib/rclrb/qos.rb +116 -0
- data/lib/rclrb/service.rb +46 -0
- data/lib/rclrb/subscription.rb +45 -0
- data/lib/rclrb/time.rb +32 -0
- data/lib/rclrb/timer.rb +31 -0
- data/lib/rclrb/version.rb +3 -0
- data/lib/rclrb/wait_set.rb +62 -0
- data/lib/rclrb.rb +43 -0
- metadata +98 -0
data/lib/rclrb/capi.rb
ADDED
@@ -0,0 +1,369 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Rclrb
|
4
|
+
##
|
5
|
+
# This module contains the function and data structures used to interface with the RCL C library
|
6
|
+
# The content of CApi is internal API to rclrb and should not be directly called and is subject
|
7
|
+
# to change.
|
8
|
+
module CApi
|
9
|
+
extend FFI::Library
|
10
|
+
ffi_lib 'rcl'
|
11
|
+
|
12
|
+
RCL_RET_OK = 0
|
13
|
+
RCL_RET_TIMEOUT = 2
|
14
|
+
RCL_RET_SUBSCRIPTION_TAKE_FAILED = 401
|
15
|
+
RCL_RET_CLIENT_TAKE_FAILED = 501
|
16
|
+
RCL_RET_SERVICE_TAKE_FAILED = 601
|
17
|
+
|
18
|
+
RCUTILS_ERROR_MESSAGE_MAX_LENGTH = 1024
|
19
|
+
RMW_GID_STORAGE_SIZE = 24
|
20
|
+
|
21
|
+
POINTER_SIZE = FFI::Pointer::SIZE
|
22
|
+
SIZE_T_SIZE = FFI::type_size(:size_t)
|
23
|
+
INT32_SIZE = FFI::type_size(:int32)
|
24
|
+
UINT32_SIZE = FFI::type_size(:uint32)
|
25
|
+
|
26
|
+
# Rcutils structs
|
27
|
+
class RcutilsErrorStringT < FFI::Struct
|
28
|
+
layout :str, [:uint8, RCUTILS_ERROR_MESSAGE_MAX_LENGTH]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Rmw structs
|
32
|
+
enum :RmwQosReliabilityPolicyE, [
|
33
|
+
:RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT,
|
34
|
+
:RMW_QOS_POLICY_RELIABILITY_RELIABLE,
|
35
|
+
:RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT,
|
36
|
+
:RMW_QOS_POLICY_RELIABILITY_UNKNOWN
|
37
|
+
]
|
38
|
+
enum :RmwQosDdurabilityPolicy, [
|
39
|
+
:RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT,
|
40
|
+
:RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL,
|
41
|
+
:RMW_QOS_POLICY_DURABILITY_VOLATILE,
|
42
|
+
:RMW_QOS_POLICY_DURABILITY_UNKNOWN
|
43
|
+
]
|
44
|
+
enum :RmwQosLivelinessPolicy, [
|
45
|
+
:RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT,
|
46
|
+
:RMW_QOS_POLICY_LIVELINESS_AUTOMATIC,
|
47
|
+
:RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_NODE_DEPRECATED,
|
48
|
+
:RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC,
|
49
|
+
:RMW_QOS_POLICY_LIVELINESS_UNKNOWN
|
50
|
+
]
|
51
|
+
enum :RmwQosGistoryPolicyE, [
|
52
|
+
:RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT,
|
53
|
+
:RMW_QOS_POLICY_HISTORY_KEEP_LAST,
|
54
|
+
:RMW_QOS_POLICY_HISTORY_KEEP_ALL,
|
55
|
+
:RMW_QOS_POLICY_HISTORY_UNKNOWN
|
56
|
+
]
|
57
|
+
|
58
|
+
enum :rmw_unique_network_flow_endpoints_requirement_e, []
|
59
|
+
|
60
|
+
class RmwTimeS < FFI::Struct
|
61
|
+
layout :sec, :uint64, :nsec, :uint64
|
62
|
+
end
|
63
|
+
|
64
|
+
class RmwQoSProfileT < FFI::Struct
|
65
|
+
layout :history, :RmwQosGistoryPolicyE,
|
66
|
+
:depth, :size_t,
|
67
|
+
:reliability, :RmwQosReliabilityPolicyE,
|
68
|
+
:durability, :RmwQosDdurabilityPolicy,
|
69
|
+
:deadline, RmwTimeS,
|
70
|
+
:lifespan, RmwTimeS,
|
71
|
+
:liveliness, :RmwQosLivelinessPolicy,
|
72
|
+
:liveliness_lease_duration, RmwTimeS,
|
73
|
+
:avoid_ros_namespace_conventions, :bool
|
74
|
+
end
|
75
|
+
|
76
|
+
class RmwSubscriptionOptionsT < FFI::Struct
|
77
|
+
layout :rmw_specific_subscription_payload, :pointer,
|
78
|
+
:ignore_local_publications, :bool,
|
79
|
+
:require_unique_network_flow_endpoints, :rmw_unique_network_flow_endpoints_requirement_e,
|
80
|
+
:content_filter_options, :pointer
|
81
|
+
end
|
82
|
+
|
83
|
+
class RmwPublisherOptionsT < FFI::Struct
|
84
|
+
layout :rmw_specific_publisher_payload, :pointer,
|
85
|
+
:require_unique_network_flow_endpoints, :rmw_unique_network_flow_endpoints_requirement_e
|
86
|
+
end
|
87
|
+
|
88
|
+
class RmwGidT < FFI::Struct
|
89
|
+
layout :implementation_identifier, :string,
|
90
|
+
:data, [:uint8, RMW_GID_STORAGE_SIZE]
|
91
|
+
end
|
92
|
+
|
93
|
+
RmwTimePointValueT = :int64
|
94
|
+
|
95
|
+
class RmwMessageInfoT < FFI::Struct
|
96
|
+
layout :source_timestamp, RmwTimePointValueT,
|
97
|
+
:received_timestamp, RmwTimePointValueT,
|
98
|
+
:publication_sequence_number, :uint64,
|
99
|
+
:reception_sequence_number, :uint64,
|
100
|
+
:publisher_gid, RmwGidT,
|
101
|
+
:from_intra_process, :bool
|
102
|
+
end
|
103
|
+
|
104
|
+
class RmwSubscriptionAllocationT < FFI::Struct
|
105
|
+
layout :implementation_identifier, :string,
|
106
|
+
:data, :pointer
|
107
|
+
end
|
108
|
+
|
109
|
+
class RmwPublisherAllocationT < FFI::Struct
|
110
|
+
layout :implementation_identifier, :string,
|
111
|
+
:data, :pointer
|
112
|
+
end
|
113
|
+
|
114
|
+
class RmwRequestIdT < FFI::Struct
|
115
|
+
layout :writer_guid, [:int16, 16],
|
116
|
+
:sequence_number, :int64
|
117
|
+
end
|
118
|
+
|
119
|
+
class RmwServiceInfoT < FFI::Struct
|
120
|
+
layout :source_timestamp, RmwTimePointValueT,
|
121
|
+
:received_timestamp, RmwTimePointValueT,
|
122
|
+
:request_id, RmwRequestIdT
|
123
|
+
end
|
124
|
+
|
125
|
+
# Rosidl
|
126
|
+
|
127
|
+
class RosidlMessageTypeSupportT < FFI::Struct
|
128
|
+
layout :typesuport_identifier, :string,
|
129
|
+
:data, :pointer,
|
130
|
+
:func, :pointer
|
131
|
+
end
|
132
|
+
|
133
|
+
class RosidlServiceTypeSupportT < FFI::Struct
|
134
|
+
layout :typesuport_identifier, :string,
|
135
|
+
:data, :pointer,
|
136
|
+
:func, :pointer
|
137
|
+
end
|
138
|
+
|
139
|
+
# Rcl
|
140
|
+
callback :allocate_callback, [:size_t, :pointer], :pointer
|
141
|
+
callback :deallocate_callback, [:pointer, :pointer], :void
|
142
|
+
|
143
|
+
class RclAllocatorT < FFI::Struct
|
144
|
+
layout :allocate, :allocate_callback, :deallocate, :deallocate_callback,
|
145
|
+
:reallocate, :pointer, :zero_allocate, :pointer,
|
146
|
+
:state, :pointer
|
147
|
+
end
|
148
|
+
|
149
|
+
class RclArgumentsT < FFI::Struct
|
150
|
+
layout :impl, :pointer
|
151
|
+
end
|
152
|
+
|
153
|
+
class RclContextT < FFI::Struct
|
154
|
+
layout :global_arguments, RclArgumentsT,
|
155
|
+
:impl, :pointer,
|
156
|
+
:instance_id_storage, [:uint8, 8]
|
157
|
+
end
|
158
|
+
|
159
|
+
class RclInitOptionsT < FFI::Struct
|
160
|
+
layout :impl, :pointer
|
161
|
+
end
|
162
|
+
|
163
|
+
enum :RclClockTypeT, [:RCL_CLOCK_UNINITIALIZED, :RCL_ROS_TIME, :RCL_SYSTEM_TIME, :RCL_STEADY_TIME]
|
164
|
+
|
165
|
+
class RclClockT < FFI::Struct
|
166
|
+
layout :type, :RclClockTypeT,
|
167
|
+
:jump_callbacks, :pointer,
|
168
|
+
:num_jump_callbacks, :size_t,
|
169
|
+
:now, :pointer,
|
170
|
+
:data, :pointer,
|
171
|
+
:allocator, RclAllocatorT
|
172
|
+
end
|
173
|
+
|
174
|
+
class RclNodeT < FFI::Struct
|
175
|
+
layout :context, :pointer, :impl, :pointer
|
176
|
+
end
|
177
|
+
|
178
|
+
class RclSubscriptionOptionsT < FFI::Struct
|
179
|
+
layout :qos, RmwQoSProfileT, :allocator, RclAllocatorT, :rmw_subscription_options, RmwSubscriptionOptionsT
|
180
|
+
end
|
181
|
+
|
182
|
+
class RclPublisherOptionsT < FFI::Struct
|
183
|
+
layout :qos, RmwQoSProfileT, :allocator, RclAllocatorT, :rmw_subscription_options, RmwPublisherOptionsT
|
184
|
+
end
|
185
|
+
|
186
|
+
class RclServiceOptionsT < FFI::Struct
|
187
|
+
layout :qos, RmwQoSProfileT, :allocator, RclAllocatorT
|
188
|
+
end
|
189
|
+
|
190
|
+
class RclClientOptionsT < FFI::Struct
|
191
|
+
layout :qos, RmwQoSProfileT, :allocator, RclAllocatorT
|
192
|
+
end
|
193
|
+
|
194
|
+
class RclGuardConditionOptionsT < FFI::Struct
|
195
|
+
layout :allocator, RclAllocatorT
|
196
|
+
end
|
197
|
+
|
198
|
+
class RclSubscriptionT < FFI::Struct
|
199
|
+
layout :impl, :pointer
|
200
|
+
end
|
201
|
+
|
202
|
+
class RclPublisherT < FFI::Struct
|
203
|
+
layout :impl, :pointer
|
204
|
+
end
|
205
|
+
|
206
|
+
class RclServiceT < FFI::Struct
|
207
|
+
layout :impl, :pointer
|
208
|
+
end
|
209
|
+
|
210
|
+
class RclClientT < FFI::Struct
|
211
|
+
layout :impl, :pointer
|
212
|
+
end
|
213
|
+
|
214
|
+
class RclGuardConditionT < FFI::Struct
|
215
|
+
layout :context, RclContextT.by_ref,
|
216
|
+
:impl, :pointer
|
217
|
+
end
|
218
|
+
|
219
|
+
class RclTimerT < FFI::Struct
|
220
|
+
layout :impl, :pointer
|
221
|
+
end
|
222
|
+
|
223
|
+
class RclNodeOptionsT < FFI::Struct
|
224
|
+
layout :allocator, RclAllocatorT, :use_global_arguments, :bool,
|
225
|
+
:arguments, RclArgumentsT, :enable_rosout, :bool,
|
226
|
+
:rosout_qos, RmwQoSProfileT
|
227
|
+
end
|
228
|
+
|
229
|
+
class RclWaitSetT < FFI::Struct
|
230
|
+
layout :subscriptions, :pointer,
|
231
|
+
:size_of_subscriptions, :size_t,
|
232
|
+
:guard_conditions, :pointer,
|
233
|
+
:size_of_guard_conditions, :size_t,
|
234
|
+
:timers, :pointer,
|
235
|
+
:size_of_timers, :size_t,
|
236
|
+
:clients, :pointer,
|
237
|
+
:size_of_clients, :size_t,
|
238
|
+
:services, :pointer,
|
239
|
+
:size_of_services, :size_t,
|
240
|
+
:events, :pointer,
|
241
|
+
:size_of_events, :size_t,
|
242
|
+
:impl, :pointer
|
243
|
+
end
|
244
|
+
|
245
|
+
# Misc
|
246
|
+
|
247
|
+
RclRetT = :int
|
248
|
+
class BoolPtr < FFI::Struct
|
249
|
+
layout :value, :bool
|
250
|
+
end
|
251
|
+
class Int64Ptr < FFI::Struct
|
252
|
+
layout :value, :int64
|
253
|
+
end
|
254
|
+
class SizeTPtr < FFI::Struct
|
255
|
+
layout :value, :size_t
|
256
|
+
end
|
257
|
+
|
258
|
+
# init API
|
259
|
+
attach_function :rcl_get_zero_initialized_context, [], RclContextT.by_value
|
260
|
+
attach_function :rcl_context_fini, [:pointer], :int
|
261
|
+
attach_function :rcl_get_zero_initialized_init_options, [], RclInitOptionsT.by_value
|
262
|
+
attach_function :rcl_init_options_init, [RclInitOptionsT.by_ref, RclAllocatorT.by_value], RclRetT
|
263
|
+
attach_function :rcl_init, [:int, :pointer, RclInitOptionsT.by_ref, RclContextT.by_ref], RclRetT
|
264
|
+
|
265
|
+
# Node API
|
266
|
+
attach_function :rcl_node_init, [RclNodeT.by_ref, :string, :string, RclContextT.by_ref, RclNodeOptionsT.by_ref], RclRetT
|
267
|
+
attach_function :rcl_node_fini, [RclNodeT.by_ref], RclRetT
|
268
|
+
attach_function :rcl_node_get_default_options, [], RclNodeOptionsT.by_value
|
269
|
+
attach_function :rcl_node_get_namespace, [RclNodeT.by_ref], :string
|
270
|
+
|
271
|
+
# Subscription API
|
272
|
+
attach_function :rcl_get_zero_initialized_subscription, [], RclSubscriptionT.by_value
|
273
|
+
attach_function :rcl_subscription_get_default_options, [], RclSubscriptionOptionsT.by_value
|
274
|
+
attach_function :rcl_subscription_init, [RclSubscriptionT.by_ref, RclNodeT.by_ref, RosidlMessageTypeSupportT.by_ref, :string, RclSubscriptionOptionsT.by_ref], RclRetT
|
275
|
+
attach_function :rcl_subscription_fini, [RclSubscriptionT.by_ref, RclNodeT.by_ref], RclRetT
|
276
|
+
attach_function :rcl_take, [RclSubscriptionT.by_ref, :pointer, RmwMessageInfoT.by_ref, RmwSubscriptionAllocationT.by_ref], RclRetT
|
277
|
+
|
278
|
+
# Publisher API
|
279
|
+
attach_function :rcl_get_zero_initialized_publisher, [], RclPublisherT.by_value
|
280
|
+
attach_function :rcl_publisher_get_default_options, [], RclPublisherOptionsT.by_value
|
281
|
+
attach_function :rcl_publisher_init, [RclPublisherT.by_ref, RclNodeT.by_ref, RosidlMessageTypeSupportT.by_ref, :string, RclPublisherOptionsT.by_ref], RclRetT
|
282
|
+
attach_function :rcl_publisher_fini, [RclPublisherT.by_ref, RclNodeT.by_ref], RclRetT
|
283
|
+
attach_function :rcl_publish, [RclPublisherT.by_ref, :pointer, RmwPublisherAllocationT.by_ref], RclRetT
|
284
|
+
attach_function :rcl_publisher_get_subscription_count, [RclPublisherT.by_ref, SizeTPtr.by_ref], RclRetT
|
285
|
+
|
286
|
+
# Service API
|
287
|
+
attach_function :rcl_get_zero_initialized_service, [], RclServiceT.by_value
|
288
|
+
attach_function :rcl_service_get_default_options, [], RclServiceOptionsT.by_value
|
289
|
+
attach_function :rcl_service_init, [RclServiceT.by_ref, RclNodeT.by_ref, RosidlServiceTypeSupportT.by_ref, :string, RclServiceOptionsT.by_ref], RclRetT
|
290
|
+
attach_function :rcl_service_fini, [RclServiceT.by_ref, RclNodeT.by_ref], RclRetT
|
291
|
+
attach_function :rcl_take_request, [RclServiceT.by_ref, RmwRequestIdT.by_ref, :pointer], RclRetT
|
292
|
+
attach_function :rcl_send_response, [RclServiceT.by_ref, RmwRequestIdT.by_ref, :pointer], RclRetT
|
293
|
+
|
294
|
+
# Client API
|
295
|
+
attach_function :rcl_get_zero_initialized_client, [], RclClientT.by_value
|
296
|
+
attach_function :rcl_client_get_default_options, [], RclClientOptionsT.by_value
|
297
|
+
attach_function :rcl_client_init, [RclClientT.by_ref, RclNodeT.by_ref, RosidlServiceTypeSupportT.by_ref, :string, RclClientOptionsT.by_ref], RclRetT
|
298
|
+
attach_function :rcl_client_fini, [RclClientT.by_ref, RclNodeT.by_ref], RclRetT
|
299
|
+
attach_function :rcl_send_request, [RclClientT.by_ref, :pointer, Int64Ptr.by_ref], RclRetT
|
300
|
+
attach_function :rcl_take_response_with_info, [RclClientT.by_ref, RmwServiceInfoT.by_ref, :pointer], RclRetT
|
301
|
+
|
302
|
+
# GuardCondition API
|
303
|
+
attach_function :rcl_get_zero_initialized_guard_condition, [], RclGuardConditionT.by_value
|
304
|
+
attach_function :rcl_guard_condition_init, [RclGuardConditionT.by_ref, RclContextT.by_ref, RclGuardConditionOptionsT.by_value], RclRetT
|
305
|
+
attach_function :rcl_guard_condition_get_default_options, [], RclGuardConditionOptionsT.by_value
|
306
|
+
attach_function :rcl_trigger_guard_condition, [RclGuardConditionT.by_ref], RclRetT
|
307
|
+
|
308
|
+
# Clock API
|
309
|
+
attach_function :rcl_clock_init, [:RclClockTypeT, RclClockT.by_ref, RclAllocatorT.by_ref], RclRetT
|
310
|
+
|
311
|
+
# Timer API
|
312
|
+
attach_function :rcl_get_zero_initialized_timer, [], RclTimerT.by_value
|
313
|
+
callback :timer_callback, [RclTimerT.by_ref, :int64], :void
|
314
|
+
attach_function :rcl_timer_init, [RclTimerT.by_ref, RclClockT.by_ref, RclContextT.by_ref, :int64, :timer_callback, RclAllocatorT.by_value], RclRetT
|
315
|
+
attach_function :rcl_timer_fini, [RclTimerT.by_ref, RclNodeT.by_ref], RclRetT
|
316
|
+
attach_function :rcl_timer_call, [RclTimerT.by_ref], RclRetT
|
317
|
+
attach_function :rcl_timer_is_ready, [RclTimerT.by_ref, BoolPtr.by_ref], RclRetT
|
318
|
+
|
319
|
+
# WaitSet API
|
320
|
+
attach_function :rcl_get_zero_initialized_wait_set, [], RclWaitSetT.by_value
|
321
|
+
attach_function :rcl_wait_set_init, [RclWaitSetT.by_ref, :size_t, :size_t, :size_t, :size_t, :size_t, :size_t, RclContextT.by_ref, RclAllocatorT.by_value], RclRetT
|
322
|
+
attach_function :rcl_wait_set_fini, [RclWaitSetT.by_ref], RclRetT
|
323
|
+
attach_function :rcl_wait, [RclWaitSetT.by_ref, :int64], RclRetT, blocking: true
|
324
|
+
attach_function :rcl_wait_set_add_subscription, [RclWaitSetT.by_ref, RclSubscriptionT.by_ref, SizeTPtr.by_ref], RclRetT
|
325
|
+
attach_function :rcl_wait_set_add_guard_condition, [RclWaitSetT.by_ref, RclGuardConditionT.by_ref, SizeTPtr.by_ref], RclRetT
|
326
|
+
attach_function :rcl_wait_set_add_timer, [RclWaitSetT.by_ref, RclTimerT.by_ref, SizeTPtr.by_ref], RclRetT
|
327
|
+
attach_function :rcl_wait_set_add_client, [RclWaitSetT.by_ref, RclClientT.by_ref, SizeTPtr.by_ref], RclRetT
|
328
|
+
attach_function :rcl_wait_set_add_service, [RclWaitSetT.by_ref, RclServiceT.by_ref, SizeTPtr.by_ref], RclRetT
|
329
|
+
|
330
|
+
# Graph API
|
331
|
+
attach_function :rcl_service_server_is_available, [RclNodeT.by_ref, RclClientT.by_ref, BoolPtr.by_ref], RclRetT
|
332
|
+
|
333
|
+
# rcutils API
|
334
|
+
attach_function :rcutils_get_default_allocator, [], RclAllocatorT.by_value
|
335
|
+
attach_function :rcutils_get_error_string, [], RcutilsErrorStringT.by_value
|
336
|
+
attach_function :rcutils_reset_error, [], :void
|
337
|
+
|
338
|
+
def CApi.create_type_support_library(module_name, package_name, longtype, shorttype, idltype, messages)
|
339
|
+
template = ERB.new <<-EOF
|
340
|
+
module <%= module_name %>
|
341
|
+
module TypeSupportCApi
|
342
|
+
extend FFI::Library
|
343
|
+
ffi_lib '<%= package_name %>__rosidl_typesupport_c'
|
344
|
+
<% messages.each() do | m | %>
|
345
|
+
attach_function :rosidl_typesupport_c__get_#{longtype}_type_support_handle__<%= package_name %>__#{shorttype}__<%= m %>, [], CApi::#{idltype}.by_ref
|
346
|
+
TypeSupport_#{shorttype}_<%= m %> = rosidl_typesupport_c__get_#{longtype}_type_support_handle__<%= package_name %>__#{shorttype}__<%= m %>
|
347
|
+
<% end %>
|
348
|
+
end
|
349
|
+
end
|
350
|
+
EOF
|
351
|
+
Object.class_eval template.result(binding)
|
352
|
+
end
|
353
|
+
|
354
|
+
def CApi.create_node()
|
355
|
+
return CApi::RclNodeT.new()
|
356
|
+
end
|
357
|
+
def CApi.get_error_string()
|
358
|
+
msg = CApi.rcutils_get_error_string()[:str]
|
359
|
+
CApi.rcutils_reset_error();
|
360
|
+
return msg
|
361
|
+
end
|
362
|
+
def CApi.handle_result(ret, always_call = nil)
|
363
|
+
always_call.call if always_call
|
364
|
+
if ret != RCL_RET_OK
|
365
|
+
raise RclError.new "Error #{ret.to_i}: #{CApi.get_error_string()}"
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
data/lib/rclrb/client.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
module Rclrb
|
2
|
+
##
|
3
|
+
# Represent a ROS client
|
4
|
+
class Client
|
5
|
+
attr_reader :srv_type, :client_handle
|
6
|
+
# Construct a new publisher, this should not be called directly, instead use Node.create_publisher.
|
7
|
+
def initialize(client_handle, node_handle, srv_type, srv_name, qos_profile)
|
8
|
+
@client_handle = client_handle
|
9
|
+
@node_handle = node_handle
|
10
|
+
@srv_type = srv_type
|
11
|
+
@srv_name = srv_name
|
12
|
+
@qos_profile = qos_profile
|
13
|
+
@call_counter = 0
|
14
|
+
|
15
|
+
client_ops = CApi.rcl_client_get_default_options()
|
16
|
+
client_ops[:qos] = QoSProfile.get_profile(qos_profile).ros_profile
|
17
|
+
CApi.handle_result CApi.rcl_client_init(@client_handle, node_handle, srv_type.type_support(), @srv_name, client_ops)
|
18
|
+
end
|
19
|
+
|
20
|
+
rclrb_finalize_with :@client_handle, :@node_handle do |client_handle, node_handle|
|
21
|
+
CApi.handle_result CApi.rcl_client_fini client_handle, node_handle
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Call a service asynchronously with the given +request+, it will return a Future object.
|
26
|
+
def call_async(request)
|
27
|
+
raise RclError.new unless request.kind_of? @srv_type::Request
|
28
|
+
|
29
|
+
counter = CApi::Int64Ptr.new
|
30
|
+
counter[:value] = (@call_counter += 1)
|
31
|
+
future = Future.execute do
|
32
|
+
ros_req = @srv_type::Request.get_ros_message request
|
33
|
+
CApi.handle_result CApi.rcl_send_request(@client_handle, ros_req, counter), lambda { @srv_type::Request.destroy_ros_message(ros_req)}
|
34
|
+
ros_resp = @srv_type::Response::FFIType.new
|
35
|
+
info = CApi::RmwServiceInfoT.new
|
36
|
+
waiting_for_answer = true
|
37
|
+
wait_set = WaitSet.new
|
38
|
+
wait_set.add self
|
39
|
+
while waiting_for_answer
|
40
|
+
wait_set.wait
|
41
|
+
status = CApi.rcl_take_response_with_info @client_handle, info, ros_resp
|
42
|
+
if status == CApi::RCL_RET_OK
|
43
|
+
response = @srv_type::Response.parse_ros_message ros_resp
|
44
|
+
@srv_type::Response.destroy_ros_message ros_resp
|
45
|
+
waiting_for_answer = false
|
46
|
+
elsif status == CApi::RCL_RET_CLIENT_TAKE_FAILED
|
47
|
+
raise ServiceCallFailed.new
|
48
|
+
else
|
49
|
+
CApi.handle_result status
|
50
|
+
end
|
51
|
+
if Rclrb.rcl_shutdown_requested?
|
52
|
+
raise InterruptedClientCall.new "Call to #{@srv_name} was interrupted by shutdown"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
response
|
56
|
+
end
|
57
|
+
return future
|
58
|
+
end
|
59
|
+
##
|
60
|
+
# Wait for the service to be available. If +timeout_sec+ is nil, it will wait forever, otherwise it will timeout when
|
61
|
+
# the amount of time specified by +timeout_sec+ has expired.
|
62
|
+
def wait_for_service(timeout_sec=nil)
|
63
|
+
sleep_time = 0.25
|
64
|
+
timeout_sec = Float::INFINITY if timeout_sec.nil?
|
65
|
+
until Rclrb.rcl_shutdown_requested? or self.service_is_ready() or timeout_sec < 0.0
|
66
|
+
sleep(sleep_time)
|
67
|
+
timeout_sec -= sleep_time
|
68
|
+
end
|
69
|
+
return self.service_is_ready
|
70
|
+
end
|
71
|
+
# Return true if the service is available.
|
72
|
+
def service_is_ready
|
73
|
+
b = CApi::BoolPtr.new
|
74
|
+
CApi.handle_result CApi.rcl_service_server_is_available @node_handle, @client_handle, b
|
75
|
+
return b[:value]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
data/lib/rclrb/clock.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Rclrb
|
2
|
+
##
|
3
|
+
# Represent a clock, instead of creating directly, use RosClock or SystemClock
|
4
|
+
class Clock
|
5
|
+
attr_reader :handle
|
6
|
+
def initialize(type)
|
7
|
+
@handle = CApi::RclClockT.new
|
8
|
+
CApi.handle_result(CApi.rcl_clock_init(type, @handle, CApi.rcutils_get_default_allocator()))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
##
|
12
|
+
# Represent a clock with Ros time (either system or simulated time)
|
13
|
+
RosClock = Clock.new(:RCL_ROS_TIME)
|
14
|
+
##
|
15
|
+
# Represent a clock that is always set to system time
|
16
|
+
SystemClock = Clock.new(:RCL_SYSTEM_TIME)
|
17
|
+
end
|
data/lib/rclrb/common.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
def Object.rclrb_finalize_with *ivars_names, &block
|
3
|
+
old_init = instance_method :initialize
|
4
|
+
|
5
|
+
define_method :initialize do |*args|
|
6
|
+
old_init.bind(self).call *args
|
7
|
+
ivars = ivars_names.map { |ivar| instance_variable_get(ivar) }
|
8
|
+
ObjectSpace.define_finalizer self, Object.rclrb_create_finalizer(block, ivars)
|
9
|
+
end
|
10
|
+
private_class_method def Object.rclrb_create_finalizer block, ivars
|
11
|
+
return proc { block.call(*ivars) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Rclrb
|
16
|
+
##
|
17
|
+
# Base class for any exception triggered by Rclrb
|
18
|
+
class Error < StandardError
|
19
|
+
end
|
20
|
+
##
|
21
|
+
# An unhandled error occured in the Rcl library. This is generally indicative of a bug in Rclrb.
|
22
|
+
class RclError < Error
|
23
|
+
end
|
24
|
+
##
|
25
|
+
# An error occured while parsing a message, service or action definiton.
|
26
|
+
class ParseError < Error
|
27
|
+
end
|
28
|
+
##
|
29
|
+
# A call to service was interrupted
|
30
|
+
class InterruptedClientCall < Error
|
31
|
+
end
|
32
|
+
##
|
33
|
+
# Failed to get answer to a service call
|
34
|
+
class ServiceCallFailed < Error
|
35
|
+
end
|
36
|
+
##
|
37
|
+
# Publisher.call or Client.call was called with the wrong type of message.
|
38
|
+
class InvalidMessageTypeError < Error
|
39
|
+
def initialize got, expected
|
40
|
+
super "Invalid message type got '#{got}' expected '#{expected}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rclrb
|
2
|
+
##
|
3
|
+
# An executor controls the threading model used to process callbacks. Callbacks are units of work
|
4
|
+
# like subscription callbacks, timer callbacks, and service calls. An executor controls which threads
|
5
|
+
# callbacks get executed in.
|
6
|
+
class Executor
|
7
|
+
def initialize(*nodes)
|
8
|
+
@nodes = nodes
|
9
|
+
@groups = nodes.map { |x| x.default_callback_group }
|
10
|
+
end
|
11
|
+
##
|
12
|
+
# Add a node to the executor
|
13
|
+
def add_node(node)
|
14
|
+
@nodes.append node
|
15
|
+
@groups.append node.default_callback_group
|
16
|
+
end
|
17
|
+
##
|
18
|
+
# Spin continuously untill shutdown was requested
|
19
|
+
def spin()
|
20
|
+
until Rclrb.rcl_shutdown_requested?
|
21
|
+
wait_set = WaitSet.new
|
22
|
+
threads = @groups.map { |g| g.spin wait_set }
|
23
|
+
threads.each { |t| t.join }
|
24
|
+
wait_set.wait
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
##
|
29
|
+
# Spin the given nodes using Executor
|
30
|
+
def Rclrb.spin(*nodes)
|
31
|
+
e = Executor.new *nodes
|
32
|
+
return e.spin
|
33
|
+
end
|
34
|
+
end
|