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.
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: []