rclrb 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rclrb/node.rb ADDED
@@ -0,0 +1,143 @@
1
+ module Rclrb
2
+ ##
3
+ # The node class is the center piece of RCL, it allows to create subscriptions, publishers timers,
4
+ # and services server and clients.
5
+ class Node
6
+ attr_reader :subscriptions, :timers, :services, :default_callback_group
7
+ ##
8
+ # Create a node with the given +name+,
9
+ def initialize(name)
10
+ @node_handle = CApi::RclNodeT.new()
11
+ @services = []
12
+ @subscriptions = []
13
+ @timers = []
14
+ options = CApi.rcl_node_get_default_options()
15
+ @default_callback_group = MutuallyExclusiveCallbackGroup.new
16
+ CApi.handle_result(CApi.rcl_node_init(@node_handle, name, "", Rclrb.rcl_context(), options))
17
+ end
18
+
19
+ rclrb_finalize_with :@node_handle do |node_handle|
20
+ CApi.handle_result CApi.rcl_node_fini node_handle
21
+ end
22
+
23
+ ##
24
+ # Get the namespace for this node
25
+ def get_namespace
26
+ return CApi.rcl_node_get_namespace @node_handle
27
+ end
28
+
29
+ ##
30
+ # Create a new Publisher and return it.
31
+ #
32
+ # Parameters:
33
+ # * +msg_type+ The type of ROS messages the publisher will publish.
34
+ # * +topic+ (string) The name of the topic the publisher will publish to.
35
+ # * +qos_profile+ (QoSProfile or int) A QoSProfile or a history depth to apply to the publisher. In the case that a history depth is provided, the QoS history is set to RMW_QOS_POLICY_HISTORY_KEEP_LAST, the QoS history depth is set to the value of the parameter, and all other QoS settings are set to their default values.
36
+ # * +callback_group+ (optional CallbackGroup) The callback group for the publisher’s event handlers. If None, then the node’s default callback group is used.
37
+ def create_publisher(msg_type, topic, qos_profile, callback_group=nil, event_callbacks=nil)
38
+ callback_group = @default_callback_group if callback_group.nil?
39
+ ## * +event_callbacks+ (Optional) – User-defined callbacks for middleware events.
40
+ if event_callbacks != nil
41
+ raise RclError.new("event_callbacks are not supported yet")
42
+ end
43
+ handle = CApi::rcl_get_zero_initialized_publisher()
44
+ publisher = Publisher.new(handle, @node_handle, msg_type, topic, qos_profile, callback_group, event_callbacks)
45
+ return publisher
46
+ end
47
+
48
+ ##
49
+ # Create a new Subscription and return it. This function will also add the Subscription object to @subscriptions.
50
+ # To unsubscribe it is necesserary to call tje unsubscribe function with the handle to the subscriber.
51
+ #
52
+ # Parameters:
53
+ # * +msg_type+ The type of ROS messages the subscription will subscribe to.
54
+ # * +topic+ (string) – The name of the topic the subscription will subscribe to.
55
+ # * +callback+ (block) – A user-defined callback function that is called when a message is received by the subscription.
56
+ # * +qos_profile+ (QoSProfile or int) – A QoSProfile or a history depth to apply to the subscription. In the case that a history depth is provided, the QoS history is set to RMW_QOS_POLICY_HISTORY_KEEP_LAST, the QoS history depth is set to the value of the parameter, and all other QoS settings are set to their default values.
57
+ # * +callback_group (optional CallbackGroup) – The callback group for the subscription. If None, then the nodes default callback group is used.
58
+ def create_subscription(msg_type, topic, qos_profile, callback_group = nil, event_callbacks = nil, raw = false, &callback)
59
+ callback_group = @default_callback_group if callback_group.nil?
60
+ # * +event_callbacks (Optional[SubscriptionEventCallbacks]) – User-defined callbacks for middleware events.
61
+ if event_callbacks != nil
62
+ raise RclError.new("event_callbacks are not supported yet")
63
+ end
64
+ # * +raw (bool) – If True, then received messages will be stored in raw binary representation.
65
+ if raw != false
66
+ raise RclError.new("raw is not supported yet")
67
+ end
68
+
69
+ handle = CApi::rcl_get_zero_initialized_subscription()
70
+ subscription = Subscription.new(handle, @node_handle, msg_type, topic, callback, qos_profile, callback_group, event_callbacks, raw)
71
+ @subscriptions.append subscription
72
+ return subscription
73
+ end
74
+
75
+ ##
76
+ # Unsubscribe
77
+ # * +subscription+ a subscription created by create_subscription
78
+ def remove_subscription(subscription)
79
+ @subscriptions.remove subscription
80
+ end
81
+
82
+ ##
83
+ # Create a new service server.
84
+ #
85
+ # Parameters:
86
+ # * +srv_type+: The service type.
87
+ # * +srv_name+ (str): The name of the service.
88
+ # * +callback+ (block): A user-defined callback function that is called when a service request received by the server, it expects a request and response argument.
89
+ # * +qos_profile+ (QoSProfile): The quality of service profile to apply the service server.
90
+ # * +callback_group+ (optional CallbackGroup): The callback group for the service server. If None, then the nodes default callback group is used.
91
+ def create_service(srv_type, srv_name, qos_profile=QoSProfileServicesDefault, callback_group=nil, &callback)
92
+ callback_group = @default_callback_group if callback_group.nil?
93
+ handle = CApi::rcl_get_zero_initialized_service()
94
+ service = Service.new(handle, @node_handle, srv_type, srv_name, callback, qos_profile, callback_group)
95
+ @services.append(service)
96
+ return service
97
+ end
98
+
99
+ ##
100
+ # Unsubscribe
101
+ # * +service+ a service created by create_service
102
+ def remove_service(service)
103
+ @services.remove service
104
+ end
105
+
106
+ ##
107
+ # Create a new service client.
108
+ # Parameters:
109
+ # * +srv_type+: The service type.
110
+ # * +srv_name+ (str): The name of the service.
111
+ # * +qos_profile+ (optional QoSProfile): The quality of service profile to apply the service client.
112
+ # * +callback_group+ (optional CallbackGroup): The callback group for the service client. If None, then the nodes default callback group is used
113
+ def create_client(srv_type, srv_name, qos_profile=QoSProfileServicesDefault)
114
+ handle = CApi::rcl_get_zero_initialized_client()
115
+ client = Client.new(handle, @node_handle, srv_type, srv_name, qos_profile)
116
+ return client
117
+ end
118
+
119
+ ##
120
+ # Create a new timer.
121
+ # The timer will be started and every timer_period_sec number of seconds the provided callback function will be called.
122
+ #
123
+ # Parameters:
124
+ # * +timer_period_sec+ (float): The period (s) of the timer.
125
+ # * +callback+ (block): A user-defined callback function that is called when the timer expires.
126
+ # * +callback_group+ (optional CallbackGroup): The callback group for the timer. If None, then the nodes default callback group is used.
127
+ # * +clock+ (optional Clock): The clock which the timer gets time from.
128
+ def create_timer(timer_period_sec, callback_group=nil, clock=Rclrb::RosClock, &callback)
129
+ callback_group = @default_callback_group if callback_group.nil?
130
+ handle = CApi::rcl_get_zero_initialized_timer()
131
+ timer = Timer.new(handle, @node_handle, timer_period_sec, callback, callback_group, clock)
132
+ @timers.append(timer)
133
+ return timer
134
+ end
135
+
136
+ ##
137
+ # Stop a timer
138
+ # * +timer+ a timer created by create_timer
139
+ def remove_timer(timer)
140
+ @timers.remove timer
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,40 @@
1
+ module Rclrb
2
+ ##
3
+ # Represent a ROS publisher
4
+ class Publisher
5
+ attr_reader :msg_type
6
+ # Construct a new publisher, this should not be called directly, instead use Node.create_publisher.
7
+ def initialize(publisher_handle, node_handle, msg_type, topic, qos_profile, callback_group, event_callbacks)
8
+ @publisher_handle = publisher_handle
9
+ @node_handle = node_handle
10
+ @msg_type = msg_type
11
+ @topic = topic
12
+ @qos_profile = qos_profile
13
+
14
+ publisher_ops = CApi.rcl_publisher_get_default_options()
15
+ publisher_ops[:qos] = QoSProfile.get_profile(qos_profile).ros_profile
16
+ CApi.handle_result(CApi.rcl_publisher_init(@publisher_handle, node_handle, msg_type.type_support(), @topic, publisher_ops))
17
+ end
18
+
19
+ rclrb_finalize_with :@publisher_handle, :@node_handle do |publisher_handle, node_handle|
20
+ CApi.handle_result CApi.rcl_publisher_fini publisher_handle, node_handle
21
+ end
22
+
23
+ ##
24
+ # Publish a message. If +msg+ has the wrong type, an exception is triggered.
25
+ def pub(msg)
26
+ raise InvalidMessageTypeError.new msg.class, @msg_type unless msg.kind_of? @msg_type
27
+ ros_msg = @msg_type.get_ros_message msg
28
+ CApi.handle_result(CApi.rcl_publish(@publisher_handle, ros_msg, nil), lambda { @msg_type.destroy_ros_message ros_msg})
29
+ end
30
+
31
+ ##
32
+ # Return the number of subscription to that topic.
33
+ def subscription_count()
34
+ count = CApi::SizeTPtr.new
35
+ CApi.handle_result CApi.rcl_publisher_get_subscription_count(@publisher_handle, count)
36
+ return count[:value]
37
+ end
38
+ end
39
+ end
40
+
data/lib/rclrb/qos.rb ADDED
@@ -0,0 +1,116 @@
1
+ module Rclrb
2
+ module QosReliabilityPolicy
3
+ ## Implementation specific default
4
+ SystemDefault = :RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT
5
+ ## Guarantee that samples are delivered, may retry multiple times
6
+ Reliable = :RMW_QOS_POLICY_RELIABILITY_RELIABLE
7
+ ## Attempt to deliver samples, but some may be lost if the network is not robust
8
+ BestEffort = :RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT
9
+ ## Reliability policy has not yet been set
10
+ Unknown = :RMW_QOS_POLICY_RELIABILITY_UNKNOWN
11
+ end
12
+ module QosDurabilityPolicy
13
+ ## Implementation specific default
14
+ SystemDefault = :RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT
15
+ ## The rmw publisher is responsible for persisting samples for “late-joining” subscribers
16
+ TransientLocal = :RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL
17
+ ## Samples are not persistent
18
+ Volatile = :RMW_QOS_POLICY_DURABILITY_VOLATILE
19
+ ## History policy has not yet been set
20
+ Unknown = :RMW_QOS_POLICY_DURABILITY_UNKNOWN
21
+ end
22
+ module QosLivelinessPolicy
23
+ ## Implementation specific default
24
+ SystemDefault = :RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT
25
+ ## The signal that establishes a Topic is alive comes from the ROS rmw layer
26
+ Automatic = :RMW_QOS_POLICY_LIVELINESS_AUTOMATIC
27
+ ## The signal that establishes a Topic is alive is at the Topic level. Only publishing a message
28
+ # on the Topic or an explicit signal from the application to assert liveliness on the Topic
29
+ # will mark the Topic as being alive.
30
+ ManualByTopic = :RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC
31
+ ## History policy has not yet been set
32
+ Unknown = :RMW_QOS_POLICY_LIVELINESS_UNKNOWN
33
+ end
34
+ module QosHistoryPolicy
35
+ ## Implementation default for history policy
36
+ SystemDefault = :RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT
37
+ ## Only store up to a maximum number of samples, dropping oldest once max is exceeded
38
+ KeepLast = :RMW_QOS_POLICY_HISTORY_KEEP_LAST
39
+ ## Store all samples, subject to resource limits
40
+ KeepAll = :RMW_QOS_POLICY_HISTORY_KEEP_ALL
41
+ # History policy has not yet been set
42
+ Unknown = :RMW_QOS_POLICY_HISTORY_UNKNOWN
43
+ end
44
+ ##
45
+ # Represent the QoS profile of a topic, service or action. Look at QoSProfileSensorData,
46
+ # QoSProfileParameters, QoSProfileDefault, QoSProfileServicesDefault, QoSProfileParameterEvents,
47
+ # or QoSProfileSystemDefault.
48
+ class QoSProfile
49
+ attr_reader :ros_profile
50
+ #
51
+ #
52
+ # Parameters:
53
+ # * +depth+ Size of the message queue.
54
+ # * +history+ History QoS policy setting
55
+ # * +reliability+ Reliabiilty QoS policy setting
56
+ # * +durability+ Durability QoS policy setting
57
+ # * +deadline+ The period at which messages are expected to be sent/received
58
+ # * +lifespan+ The age at which messages are considered expired and no longer valid
59
+ # * +liveliness+ Liveliness QoS policy setting
60
+ # * +liveliness_lease_duration+ The time within which the RMW node or publisher must show that it is alive
61
+ # * +avoid_ros_namespace_conventions+ If true, any ROS specific namespacing conventions will be circumvented
62
+ def initialize(depth:, history: QosHistoryPolicy::KeepLast, reliability: QosReliabilityPolicy::Reliable,
63
+ durability: QosDurabilityPolicy::Volatile, deadline: nil, lifespan: nil,
64
+ liveliness: QosLivelinessPolicy::SystemDefault, liveliness_lease_duration: nil,
65
+ avoid_ros_namespace_conventions: false)
66
+ @ros_profile = CApi::RmwQoSProfileT.new
67
+ @ros_profile[:depth] = depth
68
+ @ros_profile[:history] = history
69
+ @ros_profile[:reliability] = reliability
70
+ @ros_profile[:durability] = durability
71
+ unless deadline.nil?
72
+ s, n = deadline.to_sec_nsec
73
+ @ros_profile[:deadline][:sec] = s
74
+ @ros_profile[:deadline][:nsec] = n
75
+ end
76
+ unless lifespan.nil?
77
+ s, n = lifespan.to_sec_nsec
78
+ @ros_profile[:lifespan][:sec] = s
79
+ @ros_profile[:lifespan][:nsec] = n
80
+ end
81
+ @ros_profile[:lifespan]
82
+ @ros_profile[:liveliness] = liveliness
83
+ unless liveliness_lease_duration.nil?
84
+ s, n = liveliness_lease_duration.to_sec_nsec
85
+ @ros_profile[:liveliness_lease_duration][:sec] = s
86
+ @ros_profile[:liveliness_lease_duration][:nsec] = n
87
+ end
88
+ end
89
+ def QoSProfile.get_profile p
90
+ return p if p.kind_of? QoSProfile
91
+ return QoSProfile.new depth: p
92
+ end
93
+ end
94
+
95
+ ## Qos profile to be used for sensor data,
96
+ QoSProfileSensorData = QoSProfile.new depth: 5, reliability: QosReliabilityPolicy::BestEffort
97
+
98
+ ## Qos profile to be used for parameters.
99
+ QoSProfileParameters = QoSProfile.new depth: 1000
100
+
101
+ ## Default Qos profile for topics.
102
+ QoSProfileDefault = QoSProfile.new depth: 10
103
+
104
+ ## Default Qos profile for services.
105
+ QoSProfileServicesDefault = QoSProfile.new depth: 10
106
+
107
+ ## Default Qos profile for events.
108
+ QoSProfileParameterEvents = QoSProfile.new depth: 1000
109
+
110
+ ## Default Qos profile using system default (RMW implementation specific).
111
+ QoSProfileSystemDefault = QoSProfile.new depth: 5, history: QosHistoryPolicy::SystemDefault,
112
+ reliability: QosReliabilityPolicy::SystemDefault,
113
+ durability: QosDurabilityPolicy::SystemDefault,
114
+ liveliness: QosLivelinessPolicy::SystemDefault
115
+
116
+ end
@@ -0,0 +1,46 @@
1
+ module Rclrb
2
+ ##
3
+ # Represent a ROS service
4
+ class Service
5
+ attr_reader :srv_type, :service_handle
6
+ # Construct a new service, this should not be called directly, instead use Node.create_service.
7
+ def initialize(service_handle, node_handle, srv_type, srv_name, callback, qos_profile, callback_group)
8
+ @service_handle = service_handle
9
+ @srv_type = srv_type
10
+ @srv_name = srv_name
11
+ @callback = callback
12
+ @callback_group = callback_group
13
+ @qos_profile = qos_profile
14
+ callback_group.add self
15
+
16
+ service_ops = CApi.rcl_service_get_default_options()
17
+ service_ops[:qos] = QoSProfile.get_profile(qos_profile).ros_profile
18
+ CApi.handle_result CApi.rcl_service_init(@service_handle, node_handle, srv_type.type_support(), @srv_name, service_ops)
19
+ end
20
+
21
+ rclrb_finalize_with :@service_handle, :@node_handle do |service_handle, node_handle|
22
+ CApi.handle_result CApi.rcl_service_fini service_handle, node_handle
23
+ end
24
+
25
+ def spin(wait_set = nil)
26
+ wait_set.add self if wait_set
27
+ request_id = CApi::RmwRequestIdT.new
28
+ ros_req = @srv_type::Request::FFIType.new
29
+ status = CApi.rcl_take_request @service_handle, request_id, ros_req
30
+
31
+ if status == CApi::RCL_RET_OK
32
+ request = @srv_type::Request.parse_ros_message ros_req
33
+ @srv_type::Request.destroy_ros_message ros_req
34
+ response = @srv_type::Response.new
35
+ @callback.call request, response
36
+ ros_resp = @srv_type::Response.get_ros_message response
37
+ CApi.handle_result CApi.rcl_send_response(@service_handle, request_id, ros_resp), lambda { @srv_type::Response.destroy_ros_message ros_resp}
38
+
39
+ elsif status == CApi::RCL_RET_SERVICE_TAKE_FAILED
40
+ # no service received
41
+ else
42
+ CApi.handle_result(status)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ module Rclrb
2
+ ##
3
+ # Represent a ROS subscription to a topic
4
+ class Subscription
5
+ attr_reader :msg_type, :subscription_handle
6
+ # Construct a new subscription, this should not be called directly, instead use Node.create_subscription.
7
+ def initialize(subscription_handle, node_handle, msg_type, topic, callback, qos_profile, callback_group, event_callbacks, raw)
8
+ @subscription_handle = subscription_handle
9
+ @node_handle = node_handle
10
+ @msg_type = msg_type
11
+ @topic = topic
12
+ @callback = callback
13
+ @qos_profile = qos_profile
14
+ @raw = raw
15
+ callback_group.add self
16
+
17
+ subscription_ops = CApi.rcl_subscription_get_default_options()
18
+ subscription_ops[:qos] = QoSProfile.get_profile(qos_profile).ros_profile
19
+ CApi.handle_result CApi.rcl_subscription_init(@subscription_handle, node_handle, msg_type.type_support(), @topic, subscription_ops)
20
+ end
21
+ rclrb_finalize_with :@subscription_handle, :@node_handle do |subscription_handle, node_handle|
22
+ CApi.handle_result CApi.rcl_subscription_fini(subscription_handle, node_handle)
23
+ end
24
+ def raw?
25
+ return @raw
26
+ end
27
+
28
+ def spin(wait_set = nil)
29
+ wait_set.add self if wait_set
30
+ message_info = CApi::RmwMessageInfoT.new
31
+ data = @msg_type::FFIType.new
32
+ status = CApi.rcl_take @subscription_handle, data, message_info, nil
33
+
34
+ if status == CApi::RCL_RET_OK
35
+ msg = @msg_type.parse_ros_message data
36
+ @msg_type.destroy_ros_message data
37
+ @callback.call(msg)
38
+ elsif status == CApi::RCL_RET_SUBSCRIPTION_TAKE_FAILED
39
+ # no message received
40
+ else
41
+ CApi.handle_result status
42
+ end
43
+ end
44
+ end
45
+ end
data/lib/rclrb/time.rb ADDED
@@ -0,0 +1,32 @@
1
+ module Rclrb
2
+ ##
3
+ # Represent time.
4
+ class Time
5
+ ##
6
+ # Initialise time, +time+ is given in seconds
7
+ def initialize time = 0
8
+ @time_sec = time
9
+ end
10
+ ##
11
+ # Create a time objects from seconds
12
+ def Time.from_sec sec
13
+ return Time.new sec
14
+ end
15
+ ##
16
+ # Create a time objects from seconds and nanoseconds
17
+ def Time.from_sec_nsec sec, nsec
18
+ return Time.new sec + nsec * 1e-9
19
+ end
20
+ ##
21
+ # Return the time in seconds
22
+ def to_sec
23
+ return @time_sec
24
+ end
25
+ ##
26
+ # Return the time in second and nanoseconds (as integers)
27
+ def to_sec_nsec
28
+ si = @time_sec.to_i
29
+ return si, ((@time_sec - si) * 1e9).to_i
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Rclrb
2
+ ##
3
+ # Represent a ROS Timer
4
+ class Timer
5
+ attr_reader :timer_handle
6
+ # Construct a new timer, this should not be called directly, instead use Node.create_subscription.
7
+ def initialize(handle, node_handle, timer_period_sec, callback, callback_group, clock)
8
+ @callback_proc = Proc.new do |timer, time|
9
+ callback.call time
10
+ end
11
+ @timer_handle = handle
12
+ @node_handle = node_handle
13
+ callback_group.add self
14
+
15
+ CApi.handle_result(CApi.rcl_timer_init(handle, clock.handle, Rclrb.rcl_context, timer_period_sec*1e9, @callback_proc, Rclrb.rcl_allocator))
16
+ end
17
+
18
+ rclrb_finalize_with :@timer_handle, :@node_handle do |timer_handle, node_handle|
19
+ CApi.handle_result CApi.rcl_timer_fini timer_handle, node_handle
20
+ end
21
+
22
+ def spin(wait_set = nil)
23
+ wait_set.add self if wait_set
24
+ is_ready = CApi::BoolPtr.new
25
+ CApi.handle_result(CApi.rcl_timer_is_ready @timer_handle, is_ready)
26
+ if is_ready[:value]
27
+ CApi.handle_result(CApi.rcl_timer_call @timer_handle)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Rclrb
2
+ VERSION="1.1.0"
3
+ end
@@ -0,0 +1,62 @@
1
+ module Rclrb
2
+ ##
3
+ # This class is use to Wait for events.
4
+ class WaitSet
5
+ def initialize
6
+ @subscriptions = []
7
+ @services = []
8
+ @clients = []
9
+ @timers = []
10
+ end
11
+ ##
12
+ # Wait for an event on +ẃhat+, every +timeout+ evaluate +block+ and if the value
13
+ # returned is true, then exit the function otherwise continue waiting.
14
+ def WaitSet.wait_for what, timeout = -1, &block
15
+ ws = WaitSet.new
16
+ ws.add what
17
+ until block.call
18
+ ws.wait timeout
19
+ end
20
+ end
21
+ ##
22
+ # Add an item (Subscription, Service...) to the wait set
23
+ def add(what)
24
+ if what.kind_of? Subscription
25
+ @subscriptions.append what
26
+ elsif what.kind_of? Service
27
+ @services.append what
28
+ elsif what.kind_of? Client
29
+ @clients.append what
30
+ elsif what.kind_of? Timer
31
+ @timers.append what
32
+ end
33
+ end
34
+ ##
35
+ # Wait until +timeout+ or an event occured in one of the item added with add.
36
+ # If +timeout+ is equalt to -1, this function will block until an event occured or indefinitely.
37
+ def wait(timeout = -1)
38
+ ws = CApi.rcl_get_zero_initialized_wait_set
39
+ CApi.handle_result CApi.rcl_wait_set_init(ws, @subscriptions.size, 1, @timers.size, @clients.size, @services.size, 0, Rclrb.rcl_context, Rclrb.rcl_allocator)
40
+ begin
41
+ @subscriptions.each() { |x| CApi.handle_result CApi.rcl_wait_set_add_subscription(ws, x.subscription_handle, nil)}
42
+ CApi.handle_result CApi.rcl_wait_set_add_guard_condition(ws, Rclrb.rcl_signal_guard_condition.guard_condition_handle, nil)
43
+ @services.each() { |x| CApi.handle_result CApi.rcl_wait_set_add_service(ws, x.service_handle, nil)}
44
+ @clients.each() { |x| CApi.handle_result CApi.rcl_wait_set_add_client(ws, x.client_handle, nil)}
45
+ @timers.each() { |x| CApi.handle_result CApi.rcl_wait_set_add_timer(ws, x.timer_handle, nil)}
46
+ # Wait has to run in a seperate thread to allow for signals to work
47
+ status = nil
48
+ t = Thread.new do
49
+ status = CApi.rcl_wait(ws, timeout)
50
+ end
51
+ t.join
52
+ if status != CApi::RCL_RET_OK and status != CApi::RCL_RET_TIMEOUT
53
+ CApi.handle_result status
54
+ end
55
+ rescue RclError
56
+ CApi.handle_result CApi.rcl_wait_set_fini(ws)
57
+ raise
58
+ end
59
+ CApi.handle_result CApi.rcl_wait_set_fini(ws)
60
+ end
61
+ end
62
+ end
data/lib/rclrb.rb ADDED
@@ -0,0 +1,43 @@
1
+ require 'erb'
2
+
3
+ require_relative 'rclrb/common'
4
+ require_relative 'rclrb/internal'
5
+ require_relative 'rclrb/version'
6
+
7
+ require_relative 'rclrb/capi'
8
+
9
+ require_relative 'rclrb/callback_group'
10
+ require_relative 'rclrb/clock'
11
+ require_relative 'rclrb/client'
12
+ require_relative 'rclrb/init'
13
+ require_relative 'rclrb/executor'
14
+ require_relative 'rclrb/fields'
15
+ require_relative 'rclrb/future'
16
+ require_relative 'rclrb/guard_condition'
17
+ require_relative 'rclrb/interfaces'
18
+ require_relative 'rclrb/node'
19
+ require_relative 'rclrb/publisher'
20
+ require_relative 'rclrb/qos'
21
+ require_relative 'rclrb/subscription'
22
+ require_relative 'rclrb/time'
23
+ require_relative 'rclrb/timer'
24
+ require_relative 'rclrb/service'
25
+ require_relative 'rclrb/wait_set'
26
+
27
+ module Kernel
28
+ # make an alias of the original require
29
+ alias_method :rclrb_original_require, :require
30
+
31
+ # rewrite require
32
+ LoadedRosInterfacePackages = []
33
+ def require name
34
+ begin
35
+ rclrb_original_require name
36
+ rescue LoadError
37
+ unless LoadedRosInterfacePackages.include? name
38
+ raise unless Rclrb::Interfaces.load_definitions name
39
+ LoadedRosInterfacePackages.append(name)
40
+ end
41
+ end
42
+ end
43
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rclrb
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cyrille Berger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-09-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ffi
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ description: 'Allows to communicate with ROS program.
42
+
43
+ '
44
+ email:
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files:
48
+ - README.md
49
+ - COPYING
50
+ files:
51
+ - COPYING
52
+ - README.md
53
+ - lib/rclrb.rb
54
+ - lib/rclrb/callback_group.rb
55
+ - lib/rclrb/capi.rb
56
+ - lib/rclrb/client.rb
57
+ - lib/rclrb/clock.rb
58
+ - lib/rclrb/common.rb
59
+ - lib/rclrb/executor.rb
60
+ - lib/rclrb/fields.rb
61
+ - lib/rclrb/future.rb
62
+ - lib/rclrb/guard_condition.rb
63
+ - lib/rclrb/init.rb
64
+ - lib/rclrb/interfaces.rb
65
+ - lib/rclrb/internal.rb
66
+ - lib/rclrb/node.rb
67
+ - lib/rclrb/publisher.rb
68
+ - lib/rclrb/qos.rb
69
+ - lib/rclrb/service.rb
70
+ - lib/rclrb/subscription.rb
71
+ - lib/rclrb/time.rb
72
+ - lib/rclrb/timer.rb
73
+ - lib/rclrb/version.rb
74
+ - lib/rclrb/wait_set.rb
75
+ homepage: https://gitlab.com/cyloncore/rclrb
76
+ licenses:
77
+ - MPL-2.0
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubygems_version: 3.3.5
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Ruby bindings for Ros Communication Library (ROS2)
98
+ test_files: []