asterism 0.1.0 → 0.3.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 +4 -4
- data/README.md +222 -13
- data/lib/asterism/cruby/objects.rb +224 -0
- data/lib/asterism/cruby/ros.rb +305 -0
- data/lib/asterism/cruby/runner.rb +253 -0
- data/lib/asterism/cruby/zenoh.rb +648 -0
- data/lib/asterism/cruby.rb +6 -0
- data/lib/asterism/version.rb +1 -1
- data/lib/asterism.rb +5 -0
- data/mrblib/asterism.rb +81 -9
- data/mrblib/future.rb +6 -1
- data/mrblib/ros.rb +185 -15
- metadata +7 -3
data/mrblib/asterism.rb
CHANGED
|
@@ -166,7 +166,7 @@ module Asterism
|
|
|
166
166
|
# and Error when the same <node>/<app> is already on the network.
|
|
167
167
|
def self.connect(locator, node:, app:, mode: nil, listen: nil)
|
|
168
168
|
raise Error, "already connected (Asterism.close first)" if connected?
|
|
169
|
-
|
|
169
|
+
release
|
|
170
170
|
node = check_name("node", node)
|
|
171
171
|
app = check_name("app", app)
|
|
172
172
|
begin
|
|
@@ -195,6 +195,7 @@ module Asterism
|
|
|
195
195
|
@proxies = {}
|
|
196
196
|
@depth = 0
|
|
197
197
|
@lost = nil
|
|
198
|
+
@known = [] # the other nodes told to on_join so far
|
|
198
199
|
self
|
|
199
200
|
end
|
|
200
201
|
|
|
@@ -206,8 +207,9 @@ module Asterism
|
|
|
206
207
|
found = false
|
|
207
208
|
while true
|
|
208
209
|
s.poll
|
|
210
|
+
ended = g.done? # before taking the replies (see Future#collect)
|
|
209
211
|
found = true if g.each_reply.size > 0
|
|
210
|
-
break if found ||
|
|
212
|
+
break if found || ended || now_ms - t0 > 1500
|
|
211
213
|
pause(WAIT_STEP_MS)
|
|
212
214
|
end
|
|
213
215
|
found
|
|
@@ -235,8 +237,17 @@ module Asterism
|
|
|
235
237
|
@lost
|
|
236
238
|
end
|
|
237
239
|
|
|
238
|
-
# Closes the connection (and with it every exposed object)
|
|
240
|
+
# Closes the connection (and with it every exposed object), and forgets
|
|
241
|
+
# the on_join / on_leave blocks. Idempotent.
|
|
239
242
|
def self.close
|
|
243
|
+
release
|
|
244
|
+
@known = nil
|
|
245
|
+
@on_join = nil
|
|
246
|
+
@on_leave = nil
|
|
247
|
+
nil
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def self.release
|
|
240
251
|
s = @session
|
|
241
252
|
@session = nil
|
|
242
253
|
@objects = {}
|
|
@@ -247,7 +258,6 @@ module Asterism
|
|
|
247
258
|
@node_token = nil
|
|
248
259
|
@queryable = nil
|
|
249
260
|
@watch = nil
|
|
250
|
-
nil
|
|
251
261
|
end
|
|
252
262
|
|
|
253
263
|
def self.session!
|
|
@@ -255,10 +265,11 @@ module Asterism
|
|
|
255
265
|
@session
|
|
256
266
|
end
|
|
257
267
|
|
|
268
|
+
# The connection went away: closed, but the next Asterism.poll still tells
|
|
269
|
+
# on_leave about every node known until then.
|
|
258
270
|
def self.lost(reason)
|
|
259
271
|
@lost = reason
|
|
260
|
-
|
|
261
|
-
@lost = reason
|
|
272
|
+
release
|
|
262
273
|
end
|
|
263
274
|
|
|
264
275
|
# ------------------------------------------------------------ exposing
|
|
@@ -300,10 +311,71 @@ module Asterism
|
|
|
300
311
|
# ------------------------------------------------------------ polling
|
|
301
312
|
|
|
302
313
|
# Call from the application's update loop. Answers the calls that came
|
|
303
|
-
# in
|
|
314
|
+
# in, follows who is alive and calls the on_join / on_leave blocks. false
|
|
315
|
+
# once the connection is closed.
|
|
304
316
|
def self.poll
|
|
305
|
-
|
|
306
|
-
|
|
317
|
+
ok = @session ? pump : false
|
|
318
|
+
tell_nodes
|
|
319
|
+
ok
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# ------------------------------------------------------------ nodes coming and going
|
|
323
|
+
|
|
324
|
+
# on_join { |node| }: another node appeared (its node token or one of its
|
|
325
|
+
# objects). The nodes there already join on the first polls after
|
|
326
|
+
# connecting. on_leave { |node| }: a node is gone (no token and no object
|
|
327
|
+
# left); when the connection is lost, every node known until then leaves.
|
|
328
|
+
#
|
|
329
|
+
# The blocks run from Asterism.poll only, never from the polling inside a
|
|
330
|
+
# waiting call. What a block raises comes out of Asterism.poll (on CRuby
|
|
331
|
+
# with a receiving thread: to on_error). Asterism.close forgets them.
|
|
332
|
+
def self.on_join(&blk)
|
|
333
|
+
raise ArgumentError, "on_join needs a block" unless blk
|
|
334
|
+
(@on_join ||= []) << blk
|
|
335
|
+
self
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def self.on_leave(&blk)
|
|
339
|
+
raise ArgumentError, "on_leave needs a block" unless blk
|
|
340
|
+
(@on_leave ||= []) << blk
|
|
341
|
+
self
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
# Compares the nodes alive now with those told before and calls the
|
|
345
|
+
# blocks for the difference.
|
|
346
|
+
def self.tell_nodes
|
|
347
|
+
known = @known
|
|
348
|
+
return if known.nil?
|
|
349
|
+
now = @session ? nodes : []
|
|
350
|
+
now.shift if @session # this node
|
|
351
|
+
joined = []
|
|
352
|
+
left = []
|
|
353
|
+
now.each { |n| joined << n unless known.include?(n) }
|
|
354
|
+
known.each { |n| left << n unless now.include?(n) }
|
|
355
|
+
# After a loss, everything has been told: nothing more to compare.
|
|
356
|
+
@known = @session ? now : nil
|
|
357
|
+
tell_each("on_join", @on_join, joined)
|
|
358
|
+
tell_each("on_leave", @on_leave, left)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
# While loops, not each with a block: the blocks are the application's,
|
|
362
|
+
# and nothing else stands between them and the update loop on the stack.
|
|
363
|
+
def self.tell_each(where, blocks, names)
|
|
364
|
+
return if blocks.nil? || names.empty?
|
|
365
|
+
i = 0
|
|
366
|
+
while i < names.size
|
|
367
|
+
j = 0
|
|
368
|
+
while j < blocks.size
|
|
369
|
+
tell(where, blocks[j], names[i])
|
|
370
|
+
j += 1
|
|
371
|
+
end
|
|
372
|
+
i += 1
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# One block for one node (CRuby routes what it raises to on_error).
|
|
377
|
+
def self.tell(_where, blk, node)
|
|
378
|
+
blk.call(node)
|
|
307
379
|
end
|
|
308
380
|
|
|
309
381
|
def self.pump
|
data/mrblib/future.rb
CHANGED
|
@@ -70,11 +70,16 @@ module Asterism
|
|
|
70
70
|
def collect
|
|
71
71
|
return if @finished
|
|
72
72
|
g = @get
|
|
73
|
+
# done? before taking the replies: with a binding whose replies come
|
|
74
|
+
# in on another thread (zenoh-c), a reply and the end of the get may
|
|
75
|
+
# both arrive between the two; read the other way round, the get
|
|
76
|
+
# would look finished with its reply still queued.
|
|
77
|
+
ended = g.done?
|
|
73
78
|
# The Array form, not a block: a block called from C costs another
|
|
74
79
|
# interpreter entry on the C stack, and this runs inside nested waits.
|
|
75
80
|
replies = g.each_reply
|
|
76
81
|
@reply = replies[0][1] if @reply.nil? && replies.size > 0
|
|
77
|
-
if !@reply.nil? ||
|
|
82
|
+
if !@reply.nil? || ended || ::Asterism.now_ms >= @deadline || !::Asterism.connected?
|
|
78
83
|
@finished = true
|
|
79
84
|
@took = ::Asterism.now_ms - @started
|
|
80
85
|
end
|
data/mrblib/ros.rb
CHANGED
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
# add = Asterism::ROS.require_type("example_interfaces/srv/AddTwoInts")
|
|
12
12
|
# node.service("/add_two_ints_fmrb", add) { |req| { sum: req.a + req.b } }
|
|
13
13
|
# cli = node.client("/add_two_ints", add)
|
|
14
|
+
# node.subscribe("/cmd", "std_msgs/msg/String") { |msg, info| puts msg.data }
|
|
15
|
+
# node.every(1.0) { pub << { data: "tick" } }
|
|
14
16
|
# loop do
|
|
15
|
-
# node.poll # session.poll
|
|
17
|
+
# node.poll # session.poll, services, then the
|
|
18
|
+
# # subscribe and every blocks
|
|
16
19
|
# pub << { data: "hello" } # or pub.publish(str.new(data: "hello"))
|
|
17
20
|
# sub.each_pending { |msg, info| puts msg.data } # info: Attachment or nil
|
|
18
21
|
# end
|
|
@@ -55,7 +58,7 @@ module Asterism
|
|
|
55
58
|
def self.mangle(name)
|
|
56
59
|
s = name.to_s
|
|
57
60
|
return "%" if s.empty? || s == "/"
|
|
58
|
-
out = ""
|
|
61
|
+
out = "".dup
|
|
59
62
|
i = 0
|
|
60
63
|
n = s.bytesize
|
|
61
64
|
while i < n
|
|
@@ -101,7 +104,7 @@ module Asterism
|
|
|
101
104
|
# rmw_zenoh hashes the entity's liveliness key the same way (with XXH3);
|
|
102
105
|
# receivers only use the GID to tell publishers apart.
|
|
103
106
|
def self.gid_for(key)
|
|
104
|
-
out = ""
|
|
107
|
+
out = "".dup
|
|
105
108
|
lane = 0
|
|
106
109
|
while lane < 4
|
|
107
110
|
h = 0x811c9dc5 ^ (lane * 0x9e3779b9 & 0xffffffff)
|
|
@@ -140,6 +143,11 @@ module Asterism
|
|
|
140
143
|
@gid = gid
|
|
141
144
|
end
|
|
142
145
|
|
|
146
|
+
# For pattern matching: case info in {sequence:, gid:}.
|
|
147
|
+
def deconstruct_keys(_keys)
|
|
148
|
+
{ sequence: @sequence, stamp_ns: @stamp_ns, gid: @gid }
|
|
149
|
+
end
|
|
150
|
+
|
|
143
151
|
def encode
|
|
144
152
|
g = @gid.to_s
|
|
145
153
|
::Asterism::CDR.le_bytes(@sequence, 8) + ::Asterism::CDR.le_bytes(@stamp_ns, 8) +
|
|
@@ -217,7 +225,7 @@ module Asterism
|
|
|
217
225
|
|
|
218
226
|
# Asterism::ROS::<Pkg>::<Name>, or nil.
|
|
219
227
|
def self.type_constant(pkg, name)
|
|
220
|
-
mod_name = ""
|
|
228
|
+
mod_name = "".dup # a fresh String: literals may be frozen (Ruby 4)
|
|
221
229
|
pkg.split("_").each do |w|
|
|
222
230
|
mod_name << w.byteslice(0, 1).upcase << w.byteslice(1, w.bytesize - 1) if w.bytesize > 0
|
|
223
231
|
end
|
|
@@ -290,6 +298,20 @@ module Asterism
|
|
|
290
298
|
end
|
|
291
299
|
end
|
|
292
300
|
|
|
301
|
+
# For pattern matching: case msg in {linear: {x:}, angular: {z:}}.
|
|
302
|
+
# Nested messages stay messages (they match the same way).
|
|
303
|
+
def deconstruct_keys(keys)
|
|
304
|
+
h = {}
|
|
305
|
+
fs = self.class::FIELDS
|
|
306
|
+
i = 0
|
|
307
|
+
while i < fs.size
|
|
308
|
+
f = fs[i]
|
|
309
|
+
h[f] = __send__(f) if keys.nil? || keys.include?(f)
|
|
310
|
+
i += 1
|
|
311
|
+
end
|
|
312
|
+
h
|
|
313
|
+
end
|
|
314
|
+
|
|
293
315
|
def ==(other)
|
|
294
316
|
other.class == self.class && to_h == other.to_h
|
|
295
317
|
end
|
|
@@ -318,6 +340,8 @@ module Asterism
|
|
|
318
340
|
@next_id = 1
|
|
319
341
|
@entities = []
|
|
320
342
|
@services = []
|
|
343
|
+
@handled = [] # subscriptions with a block
|
|
344
|
+
@timers = []
|
|
321
345
|
@key = "#{LIVELINESS_ROOT}/#{@domain}/#{@zid}/#{@nid}/#{@nid}/NN/" \
|
|
322
346
|
"#{::Asterism::ROS.mangle(@enclave)}/#{::Asterism::ROS.mangle(@namespace)}/#{@name}"
|
|
323
347
|
@token = session.liveliness(@key)
|
|
@@ -353,6 +377,35 @@ module Asterism
|
|
|
353
377
|
e
|
|
354
378
|
end
|
|
355
379
|
|
|
380
|
+
# Subscribes and gives each message (and its Attachment, or nil) to
|
|
381
|
+
# the block, from node.poll. Returns the Subscription (close ends it).
|
|
382
|
+
# The block runs on the update loop's stack: do not wait in it (no
|
|
383
|
+
# service call, no proxy call); start a call_async and look at it
|
|
384
|
+
# later instead.
|
|
385
|
+
def subscribe(topic, type, qos: DEFAULT_QOS, depth: 16, &handler)
|
|
386
|
+
raise ArgumentError, "subscribe needs a block (or use subscription)" unless handler
|
|
387
|
+
e = subscription(topic, type, qos: qos, depth: depth)
|
|
388
|
+
e.handler = handler
|
|
389
|
+
@handled << e
|
|
390
|
+
e
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# Calls the block every `seconds` (the first time one period from now),
|
|
394
|
+
# from node.poll. Returns a Timer (cancel). It keeps the period; after
|
|
395
|
+
# a long stall it starts again from now instead of firing the missed
|
|
396
|
+
# times at once. As for subscribe: do not wait in the block.
|
|
397
|
+
def every(seconds, &blk)
|
|
398
|
+
raise ArgumentError, "every needs a block" unless blk
|
|
399
|
+
t = ::Asterism::ROS::Timer.new(self, seconds, blk)
|
|
400
|
+
@timers << t
|
|
401
|
+
t
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
def cancel_timer(timer)
|
|
405
|
+
@timers.delete(timer)
|
|
406
|
+
nil
|
|
407
|
+
end
|
|
408
|
+
|
|
356
409
|
# node.call("/add_two_ints", AddTwoInts, a: 1, b: 2) -> response.
|
|
357
410
|
# A client per service name is made on first use and kept.
|
|
358
411
|
def call(service, type, request = nil, timeout_ms: ::Asterism::ROS::Client::DEFAULT_TIMEOUT_MS, **fields)
|
|
@@ -365,21 +418,85 @@ module Asterism
|
|
|
365
418
|
c.call(request, timeout_ms: timeout_ms, **fields)
|
|
366
419
|
end
|
|
367
420
|
|
|
368
|
-
# Polls the session (Asterism::Zenoh::Session#poll)
|
|
369
|
-
# requests that came in for this node's services
|
|
370
|
-
#
|
|
421
|
+
# Polls the session (Asterism::Zenoh::Session#poll), answers the
|
|
422
|
+
# requests that came in for this node's services, then gives the
|
|
423
|
+
# messages that came in to the subscribe blocks and fires the timers
|
|
424
|
+
# that are due. Returns what session.poll returns (false once the
|
|
425
|
+
# session is closed).
|
|
371
426
|
def poll(steps = 8)
|
|
427
|
+
ok = pump(steps)
|
|
428
|
+
deliver
|
|
429
|
+
fire_timers
|
|
430
|
+
ok
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
# What a waiting service call polls: the session and the services, not
|
|
434
|
+
# the subscribe / every blocks (those run from node.poll only).
|
|
435
|
+
def pump(steps = 8)
|
|
372
436
|
ok = @session.poll(steps)
|
|
373
|
-
|
|
437
|
+
i = 0
|
|
438
|
+
while i < @services.size
|
|
439
|
+
@services[i].handle_pending
|
|
440
|
+
i += 1
|
|
441
|
+
end
|
|
374
442
|
ok
|
|
375
443
|
end
|
|
376
444
|
|
|
445
|
+
# While loops, not each with a block: the application's blocks are
|
|
446
|
+
# called from here, and nothing else should stand between them and
|
|
447
|
+
# the update loop on the stack.
|
|
448
|
+
def deliver
|
|
449
|
+
i = 0
|
|
450
|
+
while i < @handled.size
|
|
451
|
+
sub = @handled[i]
|
|
452
|
+
if sub.closed?
|
|
453
|
+
@handled.delete_at(i)
|
|
454
|
+
next
|
|
455
|
+
end
|
|
456
|
+
got = sub.each_pending
|
|
457
|
+
j = 0
|
|
458
|
+
while j < got.size
|
|
459
|
+
handle(sub, got[j][0], got[j][1])
|
|
460
|
+
j += 1
|
|
461
|
+
end
|
|
462
|
+
i += 1
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def fire_timers
|
|
467
|
+
return if @timers.empty?
|
|
468
|
+
now = ::Asterism::ROS.now_ms
|
|
469
|
+
due = []
|
|
470
|
+
i = 0
|
|
471
|
+
while i < @timers.size
|
|
472
|
+
due << @timers[i] if @timers[i].due?(now)
|
|
473
|
+
i += 1
|
|
474
|
+
end
|
|
475
|
+
i = 0
|
|
476
|
+
while i < due.size
|
|
477
|
+
fire(due[i], now)
|
|
478
|
+
i += 1
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
# One message for one subscribe block, one timer firing (CRuby routes
|
|
483
|
+
# what they raise to on_error).
|
|
484
|
+
def handle(sub, msg, info)
|
|
485
|
+
sub.handler.call(msg, info)
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def fire(timer, now)
|
|
489
|
+
timer.fire(now)
|
|
490
|
+
end
|
|
491
|
+
|
|
377
492
|
# Withdraws the node and its publishers, subscriptions, services and
|
|
378
493
|
# clients. Idempotent.
|
|
379
494
|
def close
|
|
380
495
|
@entities.each { |e| e.close }
|
|
381
496
|
@entities = []
|
|
382
497
|
@services = []
|
|
498
|
+
@handled = []
|
|
499
|
+
@timers = []
|
|
383
500
|
@clients = {}
|
|
384
501
|
@token.close if @token
|
|
385
502
|
@token = nil
|
|
@@ -419,8 +536,10 @@ module Asterism
|
|
|
419
536
|
# take their defaults).
|
|
420
537
|
def publish(msg)
|
|
421
538
|
raise ::Asterism::Zenoh::Error, "publisher closed" if @token.nil?
|
|
422
|
-
|
|
423
|
-
|
|
539
|
+
# Read once (a second thread may publish meanwhile on CRuby).
|
|
540
|
+
seq = @sequence + 1
|
|
541
|
+
@sequence = seq
|
|
542
|
+
att = ::Asterism::ROS::Attachment.new(seq, ::Asterism::ROS.now_ns, @gid)
|
|
424
543
|
@session.put(@topic_key, @type.encode(msg), attachment: att.encode)
|
|
425
544
|
nil
|
|
426
545
|
end
|
|
@@ -440,6 +559,8 @@ module Asterism
|
|
|
440
559
|
|
|
441
560
|
class Subscription
|
|
442
561
|
attr_reader :topic_key, :token_key, :errors
|
|
562
|
+
# The block of node.subscribe (nil for node.subscription).
|
|
563
|
+
attr_accessor :handler
|
|
443
564
|
|
|
444
565
|
def initialize(node, session, topic, type, qos, depth)
|
|
445
566
|
@type = type
|
|
@@ -480,6 +601,47 @@ module Asterism
|
|
|
480
601
|
@token = nil
|
|
481
602
|
nil
|
|
482
603
|
end
|
|
604
|
+
|
|
605
|
+
def closed?
|
|
606
|
+
@token.nil?
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
# node.every: a block called every period, from node.poll.
|
|
611
|
+
class Timer
|
|
612
|
+
# period: seconds as given; fired: how many times it ran.
|
|
613
|
+
attr_reader :period, :fired
|
|
614
|
+
|
|
615
|
+
def initialize(node, seconds, blk)
|
|
616
|
+
@period_ms = (seconds * 1000).to_i
|
|
617
|
+
raise ArgumentError, "the period must be positive" unless @period_ms > 0
|
|
618
|
+
@node = node
|
|
619
|
+
@period = seconds
|
|
620
|
+
@blk = blk
|
|
621
|
+
@next = ::Asterism::ROS.now_ms + @period_ms
|
|
622
|
+
@fired = 0
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
def due?(now_ms)
|
|
626
|
+
now_ms >= @next
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
# Keeps the period without drifting; after a long stall it starts
|
|
630
|
+
# again from now instead of firing the missed times at once.
|
|
631
|
+
def fire(now_ms)
|
|
632
|
+
@next += @period_ms
|
|
633
|
+
@next = now_ms + @period_ms if @next <= now_ms
|
|
634
|
+
@fired += 1
|
|
635
|
+
@blk.call
|
|
636
|
+
end
|
|
637
|
+
|
|
638
|
+
def cancel
|
|
639
|
+
@node.cancel_timer(self)
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
def inspect
|
|
643
|
+
"#<Asterism::ROS::Timer every #{@period} s>"
|
|
644
|
+
end
|
|
483
645
|
end
|
|
484
646
|
end
|
|
485
647
|
end
|
|
@@ -600,6 +762,8 @@ module Asterism
|
|
|
600
762
|
def collect
|
|
601
763
|
return if @finished
|
|
602
764
|
g = @get
|
|
765
|
+
# done? before taking the replies, as in Asterism::Future#collect.
|
|
766
|
+
ended = g.done?
|
|
603
767
|
# The Array form, as in Asterism::Future (no block called from C).
|
|
604
768
|
g.each_reply.each do |r|
|
|
605
769
|
next unless @response.nil?
|
|
@@ -613,7 +777,7 @@ module Asterism
|
|
|
613
777
|
end
|
|
614
778
|
end
|
|
615
779
|
now = ::Asterism::ROS.now_ms
|
|
616
|
-
if !@response.nil? ||
|
|
780
|
+
if !@response.nil? || ended || now >= @deadline
|
|
617
781
|
@nobody = @response.nil? && now < @deadline
|
|
618
782
|
@finished = true
|
|
619
783
|
@took_ms = now - @started
|
|
@@ -647,11 +811,15 @@ module Asterism
|
|
|
647
811
|
raise ::Asterism::Zenoh::Error, "client closed" if @token.nil?
|
|
648
812
|
req = request.nil? ? fields : request
|
|
649
813
|
payload = @type::Request.encode(req)
|
|
650
|
-
|
|
651
|
-
|
|
814
|
+
# Read once into a local: the request and its Call carry the same
|
|
815
|
+
# number even when another thread (CRuby) calls through this client
|
|
816
|
+
# meanwhile.
|
|
817
|
+
seq = @sequence + 1
|
|
818
|
+
@sequence = seq
|
|
819
|
+
att = ::Asterism::ROS::Attachment.new(seq, ::Asterism::ROS.now_ns, @gid)
|
|
652
820
|
g = @session.get(@service_key, timeout_ms, nil, payload, attachment: att.encode,
|
|
653
821
|
target: :all_complete, consolidation: :none)
|
|
654
|
-
::Asterism::ROS::Call.new(self, g,
|
|
822
|
+
::Asterism::ROS::Call.new(self, g, seq, timeout_ms)
|
|
655
823
|
end
|
|
656
824
|
|
|
657
825
|
# Sends the request and waits for the response (polling the node, so
|
|
@@ -661,9 +829,11 @@ module Asterism
|
|
|
661
829
|
call_async(request, timeout_ms: timeout_ms, **fields).value
|
|
662
830
|
end
|
|
663
831
|
|
|
832
|
+
# Polls the node's session and services (not its subscribe / every
|
|
833
|
+
# blocks) until the call is done.
|
|
664
834
|
def wait_for(c)
|
|
665
835
|
until c.done?
|
|
666
|
-
break unless @node.
|
|
836
|
+
break unless @node.pump
|
|
667
837
|
break if c.done?
|
|
668
838
|
::Asterism::ROS.pause(WAIT_STEP_MS)
|
|
669
839
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: asterism
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Katsuhiko Kageyama
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 0.
|
|
19
|
+
version: 0.3.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 0.
|
|
26
|
+
version: 0.3.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: msgpack
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -115,6 +115,10 @@ files:
|
|
|
115
115
|
- data/msgs/std_msgs/msg/UInt8MultiArray.rb
|
|
116
116
|
- lib/asterism.rb
|
|
117
117
|
- lib/asterism/cruby.rb
|
|
118
|
+
- lib/asterism/cruby/objects.rb
|
|
119
|
+
- lib/asterism/cruby/ros.rb
|
|
120
|
+
- lib/asterism/cruby/runner.rb
|
|
121
|
+
- lib/asterism/cruby/zenoh.rb
|
|
118
122
|
- lib/asterism/version.rb
|
|
119
123
|
- mrblib/asterism.rb
|
|
120
124
|
- mrblib/cdr.rb
|