ruby-player 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS.md +10 -0
- data/README.md +10 -1
- data/TODO.md +4 -2
- data/examples/simple_example.rb +1 -1
- data/lib/ruby-player/actarray.rb +10 -4
- data/lib/ruby-player/actuator.rb +28 -0
- data/lib/ruby-player/blob.rb +79 -0
- data/lib/ruby-player/blob_finder.rb +150 -0
- data/lib/ruby-player/client.rb +21 -12
- data/lib/ruby-player/common.rb +10 -6
- data/lib/ruby-player/constants.rb +1 -0
- data/lib/ruby-player/dev_addr.rb +1 -1
- data/lib/ruby-player/device.rb +1 -2
- data/lib/ruby-player/gripper.rb +26 -5
- data/lib/ruby-player/header.rb +1 -1
- data/lib/ruby-player/position2d.rb +67 -18
- data/lib/ruby-player/power.rb +31 -1
- data/lib/ruby-player/ranger.rb +20 -20
- data/lib/ruby-player/version.rb +1 -1
- data/lib/ruby-player.rb +2 -0
- data/spec/actarray_spec.rb +8 -0
- data/spec/actuator_spec.rb +20 -0
- data/spec/blob_finder_spec.rb +96 -0
- data/spec/blob_spec.rb +63 -0
- data/spec/client_spec.rb +47 -6
- data/spec/dev_addr_spec.rb +51 -0
- data/spec/device_spec.rb +27 -0
- data/spec/gripper_spec.rb +14 -4
- data/spec/header_spec.rb +61 -0
- data/spec/position2d_spec.rb +38 -0
- data/spec/power_spec.rb +20 -0
- data/spec/ranger_spec.rb +0 -2
- metadata +24 -17
data/NEWS.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## 2012-03-21 0.5.0
|
2
|
+
|
3
|
+
* Log level by default :notice is removed. Use :info.
|
4
|
+
* Added ActArray#power? method.
|
5
|
+
* Added #beams and #stored attributes for Gripper class.
|
6
|
+
* Added #position, #speed, #acceleration and #current attributes for Actor class.
|
7
|
+
* Added #px, #py, #pa, #vx, #vy, #va and #power? attributes for Position2d class. Method #power is deprecated.
|
8
|
+
* Added #volts, #percent, #joules and #watts attributes for Power class.
|
9
|
+
* Added blobfinder interface
|
10
|
+
|
1
11
|
## 2012-03-06 0.4.1
|
2
12
|
|
3
13
|
* Fixed bug in logging of warn and error messages
|
data/README.md
CHANGED
@@ -4,7 +4,15 @@ Summary
|
|
4
4
|
-------------------------------------
|
5
5
|
Ruby Player provide high level client library to access to Player server in pure Ruby.
|
6
6
|
|
7
|
-
|
7
|
+
This project is active developing now! *Please don't use it in serious projects.*
|
8
|
+
|
9
|
+
Why?
|
10
|
+
-------------------------------------
|
11
|
+
The Player project distributes bindings of client libraries for Ruby and Python but I think that this project has several reasons to be:
|
12
|
+
|
13
|
+
1. Pure implementation doesn't require C\C++ libraries of Player, SWIG and compilator. You can use it on any platform with installed Ruby.
|
14
|
+
2. In contrast to standard bindings Ruby Player is spreaded as gem and you can use it with Bundle, RVM and others tools which we all are loving.
|
15
|
+
3. Standard bindings doesn't use the expression of Ruby. Calls of function in C style without blocks, hashes and exceptions.
|
8
16
|
|
9
17
|
Install
|
10
18
|
-------------------------------------
|
@@ -32,6 +40,7 @@ The list of support objects and devices of Player.
|
|
32
40
|
|
33
41
|
* Client object
|
34
42
|
* ActArray
|
43
|
+
* BlobFinder
|
35
44
|
* Gripper
|
36
45
|
* Position2d
|
37
46
|
* Power
|
data/TODO.md
CHANGED
@@ -5,11 +5,13 @@ For supported devices
|
|
5
5
|
|
6
6
|
Implement PLAYER_RANGER_DATA_RANGESTAMPED and PLAYER_RANGER_DATA_INTNSTAMPED
|
7
7
|
|
8
|
+
**position2d** - The position2d proxy provides an interface to a mobile robot base
|
9
|
+
|
10
|
+
Implement PLAYER_POSITION2D_CMD_POS command
|
11
|
+
|
8
12
|
Candidates for support
|
9
13
|
--------------------------------------
|
10
14
|
|
11
|
-
**blobfinder** - The blobfinder proxy provides an interface to color blob detectors such as the ACTS vision system.
|
12
|
-
|
13
15
|
**graphics2d** - The graphics2d proxy provides an interface to the graphics2d.
|
14
16
|
|
15
17
|
**graphics3d** - The graphics3d proxy provides an interface to the graphics3d.
|
data/examples/simple_example.rb
CHANGED
data/lib/ruby-player/actarray.rb
CHANGED
@@ -29,6 +29,12 @@ module Player
|
|
29
29
|
@geom = { px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0 }
|
30
30
|
end
|
31
31
|
|
32
|
+
# Check common power
|
33
|
+
# @return [Boolean]
|
34
|
+
def power?
|
35
|
+
state[:motor_state] != 0
|
36
|
+
end
|
37
|
+
|
32
38
|
# Turn on power all actuators
|
33
39
|
# Be careful when turning power on that the array is not obstructed
|
34
40
|
# from its home position in case it moves to it (common behaviour)
|
@@ -151,10 +157,10 @@ module Player
|
|
151
157
|
msg[8..-5].unpack("a20" * c).each_with_index do |s,i|
|
152
158
|
@actuators[i] ||= Actuator.new(i,self)
|
153
159
|
@actuators[i].read_state(s)
|
154
|
-
debug "
|
160
|
+
debug "Got state for actuator ##{i}: " + hash_to_sft(@actuators[i].state)
|
155
161
|
end
|
156
162
|
@state[:motor_state] = msg[-4,4].unpack("N")[0]
|
157
|
-
debug "
|
163
|
+
debug "Got state: motor_state=%d" % @state[:motor_state]
|
158
164
|
end
|
159
165
|
|
160
166
|
def read_geom(msg)
|
@@ -162,10 +168,10 @@ module Player
|
|
162
168
|
msg[8..-48].unpack("a80" * c).each_with_index do |s, i|
|
163
169
|
@actuators[i] ||= Actuator.new(i,self)
|
164
170
|
@actuators[i].read_geom(s)
|
165
|
-
debug "
|
171
|
+
debug "Got geom for actuator ##{i}: " + hash_to_sft(@actuators[i].geom)
|
166
172
|
end
|
167
173
|
fill_hash!(@geom, msg[-48..-1].unpack("G6"))
|
168
|
-
debug("
|
174
|
+
debug("Got geom: " + hash_to_sft(@geom))
|
169
175
|
end
|
170
176
|
end
|
171
177
|
end
|
data/lib/ruby-player/actuator.rb
CHANGED
@@ -49,6 +49,34 @@ module Player
|
|
49
49
|
}
|
50
50
|
end
|
51
51
|
|
52
|
+
# The position of the actuator in m or rad depending on the type.
|
53
|
+
# @see #state
|
54
|
+
# @return [Float]
|
55
|
+
def position
|
56
|
+
state[:position]
|
57
|
+
end
|
58
|
+
|
59
|
+
# The speed of the actuator in m/s or rad/s depending on the type.
|
60
|
+
# @see #state
|
61
|
+
# @return [Float]
|
62
|
+
def speed
|
63
|
+
state[:speed]
|
64
|
+
end
|
65
|
+
|
66
|
+
# The acceleration of the actuator in m/s^2 or rad/s^2 depending on the type.
|
67
|
+
# @see #state
|
68
|
+
# @return [Float]
|
69
|
+
def acceleration
|
70
|
+
state[:acceleration]
|
71
|
+
end
|
72
|
+
|
73
|
+
# The current of the actuator in A.
|
74
|
+
# @see #state
|
75
|
+
# @return [Float]
|
76
|
+
def current
|
77
|
+
state[:current]
|
78
|
+
end
|
79
|
+
|
52
80
|
# Set speed for a joint for all subsequent movements
|
53
81
|
# @param speed - speed setting in rad/s or m/s
|
54
82
|
# @return [Actuator] self
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Ruby Player - Ruby client library for Player (tools for robots)
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Aleksey Timin
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
|
15
|
+
module Player
|
16
|
+
# Classs describing a single blob.
|
17
|
+
class Blob
|
18
|
+
# @return [Hash] blob description => { :id, :color, :area, :x, :y, :left, :right, :top, :bottom, :range }
|
19
|
+
attr_reader :state
|
20
|
+
|
21
|
+
def initialize(index, blobfinder)
|
22
|
+
@index, @blobfinder = index, blobfinder
|
23
|
+
@state = { id: 0, color: 0, area: 0, x: 0, y: 0, left: 0, right: 0, top: 0, bottom: 0, range: 0.0 }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Blob id
|
27
|
+
# @return [Integer]
|
28
|
+
def id
|
29
|
+
state[:id]
|
30
|
+
end
|
31
|
+
|
32
|
+
# A descriptive color for the blob (useful for gui's).
|
33
|
+
# @return [Integer]
|
34
|
+
def color
|
35
|
+
state[:color]
|
36
|
+
end
|
37
|
+
|
38
|
+
# The blob area [pixels].
|
39
|
+
# @return [Integer]
|
40
|
+
def area
|
41
|
+
state[:area]
|
42
|
+
end
|
43
|
+
|
44
|
+
# The blob centroid [pixels].
|
45
|
+
def x
|
46
|
+
state[:x]
|
47
|
+
end
|
48
|
+
|
49
|
+
# The blob centroid [pixels].
|
50
|
+
def y
|
51
|
+
state[:y]
|
52
|
+
end
|
53
|
+
|
54
|
+
# Bounding box for the blob [pixels].
|
55
|
+
def left
|
56
|
+
state[:left]
|
57
|
+
end
|
58
|
+
|
59
|
+
# Bounding box for the blob [pixels].
|
60
|
+
def right
|
61
|
+
state[:right]
|
62
|
+
end
|
63
|
+
|
64
|
+
# Bounding box for the blob [pixels].
|
65
|
+
def top
|
66
|
+
state[:top]
|
67
|
+
end
|
68
|
+
|
69
|
+
# Bounding box for the blob [pixels].
|
70
|
+
def bottom
|
71
|
+
state[:bottom]
|
72
|
+
end
|
73
|
+
|
74
|
+
# Range to the blob center [m].
|
75
|
+
def range
|
76
|
+
state[:range]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# Ruby Player - Ruby client library for Player (tools for robots)
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Aleksey Timin
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
|
15
|
+
module Player
|
16
|
+
# The blobfinder interface provides access to devices that detect blobs in images
|
17
|
+
class BlobFinder < Device
|
18
|
+
include Enumerable
|
19
|
+
|
20
|
+
# Blobfinder data
|
21
|
+
# @return [Hash] iby defult{ width: 0.0, height: 0.0, blobs: [] }
|
22
|
+
attr_reader :state
|
23
|
+
|
24
|
+
# Tracking color
|
25
|
+
# @see #set_color
|
26
|
+
# @return [Hash] by default { channel: 0, rmin: 0, rmax: 0, gmin: 0, gmax: 0, bmin: 0, bmax: 0 }
|
27
|
+
attr_reader :color
|
28
|
+
|
29
|
+
# Imager params.
|
30
|
+
# @see #set_imager_params
|
31
|
+
# @return [Hash] by default { brightness: 0, contrast: 0, colormode: 0, autogain: 0 }
|
32
|
+
attr_reader :imager_params
|
33
|
+
|
34
|
+
def initialize(dev, client)
|
35
|
+
super
|
36
|
+
@blobs = []
|
37
|
+
@state = { width: 0, height: 0, blobs: @blobs }
|
38
|
+
@color = { channel: 0, rmin: 0, rmax: 0, gmin: 0, gmax: 0, bmin: 0, bmax: 0 }
|
39
|
+
@imager_params = { brightness: 0, contrast: 0, colormode: 0, autogain: 0 }
|
40
|
+
end
|
41
|
+
|
42
|
+
# The image width.
|
43
|
+
# @return [Integer]
|
44
|
+
def width
|
45
|
+
state[:width]
|
46
|
+
end
|
47
|
+
|
48
|
+
# The image height.
|
49
|
+
# @return [Integer]
|
50
|
+
def height
|
51
|
+
state[:height]
|
52
|
+
end
|
53
|
+
|
54
|
+
# The list of blobs.
|
55
|
+
# @return [Array]
|
56
|
+
def blobs
|
57
|
+
state[:blobs]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Query color settings
|
61
|
+
# @return [BlobFinder] self
|
62
|
+
def query_color
|
63
|
+
send_message(PLAYER_MSGTYPE_REQ, PLAYER_BLOBFINDER_REQ_GET_COLOR)
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Set tracking color.
|
68
|
+
# @param [Hash] color
|
69
|
+
# @option [Integer] color :chanel For devices that can track multiple colors, indicate which color channel we are defining with this structure.
|
70
|
+
# @option [Integer] color :rmin RGB minimum and max values (0-255)
|
71
|
+
# @option [Integer] color :rmax RGB maximum and max values (0-255)
|
72
|
+
# @option [Integer] color :gmin RGB minimum and max values (0-255)
|
73
|
+
# @option [Integer] color :gmax RGB maximum and max values (0-255)
|
74
|
+
# @option [Integer] color :bmin RGB minimum and max values (0-255)
|
75
|
+
# @option [Integer] color :bmax RGB maximum and max values (0-255)
|
76
|
+
# @return [BlobFinder] self
|
77
|
+
def set_color(color={})
|
78
|
+
data = to_a_by_default(color, @color)
|
79
|
+
|
80
|
+
send_message(PLAYER_MSGTYPE_REQ, PLAYER_BLOBFINDER_REQ_SET_COLOR, data.pack("N*"))
|
81
|
+
self
|
82
|
+
end
|
83
|
+
|
84
|
+
# Set imager params
|
85
|
+
# Imaging sensors that do blob tracking generally have some sorts of image quality parameters that you can tweak.
|
86
|
+
# @param [Hash] params
|
87
|
+
# @option [Integer] params :brightness brightness (0-255)
|
88
|
+
# @option [Integer] params :contrast contrast (0-255)
|
89
|
+
# @option [Integer] params :color color mode (0=RGB/AutoWhiteBalance Off, 1=RGB/AutoWhiteBalance On, 2=YCrCB/AWB Off, 3=YCrCb/AWB On)
|
90
|
+
# @option [Integer] params :autogain auto gain (0=off, 1=on)
|
91
|
+
# @return [BlobFinder] self
|
92
|
+
def set_imager_params(params={})
|
93
|
+
data = to_a_by_default(params, @imager_params)
|
94
|
+
send_message(PLAYER_MSGTYPE_REQ, PLAYER_BLOBFINDER_REQ_SET_IMAGER_PARAMS, data.pack("N*"))
|
95
|
+
self
|
96
|
+
end
|
97
|
+
|
98
|
+
# Get blob
|
99
|
+
# @param [Integer] blob index
|
100
|
+
# @return [Blob] blob
|
101
|
+
def [](index)
|
102
|
+
@blobs[index] ||= Blob.new(index, self)
|
103
|
+
end
|
104
|
+
|
105
|
+
def each
|
106
|
+
@blobs.each { |b| yield b }
|
107
|
+
end
|
108
|
+
|
109
|
+
def fill(hdr, msg)
|
110
|
+
case hdr.subtype
|
111
|
+
when PLAYER_BLOBFINDER_DATA_BLOBS
|
112
|
+
read_data(msg)
|
113
|
+
else
|
114
|
+
unexpected_message hdr
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def handle_response(hdr, msg)
|
119
|
+
case hdr.subtype
|
120
|
+
when PLAYER_BLOBFINDER_REQ_GET_COLOR
|
121
|
+
read_color(msg)
|
122
|
+
when 1,2
|
123
|
+
nil
|
124
|
+
else
|
125
|
+
unexpected_message hdr
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
def read_data(msg)
|
131
|
+
data = msg[0..16].unpack("N*")
|
132
|
+
state[:width] = data[0]
|
133
|
+
state[:height] = data[1]
|
134
|
+
|
135
|
+
debug "Got image size #{state[:width]}x#{state[:height]}"
|
136
|
+
|
137
|
+
blob_count = data[2] + data[3]*256
|
138
|
+
blob_count.times do |i|
|
139
|
+
blob_data = msg[i*40 + 16, 40].unpack("N9g")
|
140
|
+
fill_hash!(self[i].state, blob_data)
|
141
|
+
debug "Got blob: " + hash_to_sft(self[i].state)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def read_color(msg)
|
146
|
+
fill_hash!(@color, msg.unpack("N7"))
|
147
|
+
debug "Got color: " + hash_to_sft(@color)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
data/lib/ruby-player/client.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
13
|
# GNU General Public License for more details.
|
14
14
|
|
15
|
+
require "socket"
|
16
|
+
|
15
17
|
module Player
|
16
18
|
# The client object manages the connection with the Player server
|
17
19
|
#
|
@@ -23,7 +25,7 @@ module Player
|
|
23
25
|
# pos2d.set_speed(vx: 1, vy: 0, va: 0.2)
|
24
26
|
# #main loop
|
25
27
|
# robot.loop do
|
26
|
-
# puts "Position: x=%{px}, y=%{py}, a=%{pa}" % pos2d.
|
28
|
+
# puts "Position: x=%{px}, y=%{py}, a=%{pa}" % pos2d.state
|
27
29
|
# end
|
28
30
|
# end
|
29
31
|
class Client < Device
|
@@ -35,10 +37,10 @@ module Player
|
|
35
37
|
# @param [String] host host of Player server
|
36
38
|
# @param [Hash] opts client options
|
37
39
|
# @option opts :port port of connection
|
38
|
-
# @option opts :log_level level of log messages [:debug
|
40
|
+
# @option opts :log_level level of log messages [:debug, :info, :warn, :error] default :info
|
39
41
|
def initialize(host, opts = {})
|
40
42
|
port = opts[:port] || 6665
|
41
|
-
@log_level = (opts[:log_level] || :
|
43
|
+
@log_level = (opts[:log_level] || :info).to_sym
|
42
44
|
|
43
45
|
@socket = TCPSocket.new(host, port)
|
44
46
|
@addr = DevAddr.new(host: 0, robot: 0, interface: PLAYER_PLAYER_CODE, index: 0)
|
@@ -46,7 +48,8 @@ module Player
|
|
46
48
|
@devices = []
|
47
49
|
|
48
50
|
banner = @socket.read(PLAYER_IDENT_STRLEN)
|
49
|
-
|
51
|
+
info "Connect with #{banner} in #{host}:#{port}"
|
52
|
+
warn "This software required Player version >= 3.1.0" if banner[/\d.\d/].to_f < 3.1
|
50
53
|
send_message PLAYER_MSGTYPE_REQ, PLAYER_PLAYER_REQ_DATAMODE, [PLAYER_DATAMODE_PULL].pack("N")
|
51
54
|
|
52
55
|
debug "Set delivery mode in PULL"
|
@@ -85,13 +88,13 @@ module Player
|
|
85
88
|
index = opts[:index] || 0
|
86
89
|
access = opts[:access] || PLAYER_OPEN_MODE
|
87
90
|
|
88
|
-
|
91
|
+
info "Subscribing to #{type}:#{index}"
|
89
92
|
data = DevAddr.new(interface: code, index: index).to_a + [access, 0, 0]
|
90
93
|
send_message PLAYER_MSGTYPE_REQ, PLAYER_PLAYER_REQ_DEV, data.pack("N*")
|
91
94
|
|
92
95
|
read!
|
93
96
|
|
94
|
-
@
|
97
|
+
@dev
|
95
98
|
end
|
96
99
|
|
97
100
|
# Check connection
|
@@ -120,7 +123,7 @@ module Player
|
|
120
123
|
end
|
121
124
|
end
|
122
125
|
|
123
|
-
def
|
126
|
+
def send_message_with_hdr(hdr, msg)
|
124
127
|
send_header hdr
|
125
128
|
@socket.write msg
|
126
129
|
@socket.flush
|
@@ -132,7 +135,7 @@ module Player
|
|
132
135
|
nil
|
133
136
|
when PLAYER_PLAYER_REQ_DEV
|
134
137
|
# read device identifier
|
135
|
-
|
138
|
+
dev_addr = DevAddr.decode(msg[0,PLAYERXDR_DEVADDR_SIZE])
|
136
139
|
# read the granted access and driver name
|
137
140
|
data = msg[PLAYERXDR_DEVADDR_SIZE,8].unpack("N*")
|
138
141
|
access = data[0]
|
@@ -140,12 +143,18 @@ module Player
|
|
140
143
|
drv_name = msg[-data[1]-2..-1]
|
141
144
|
|
142
145
|
if access == PLAYER_ERROR_MODE
|
143
|
-
raise_error "Error subscribing to " +
|
146
|
+
raise_error "Error subscribing to " + dev_addr.interface_name + ":" + dev_addr.index
|
144
147
|
end
|
145
148
|
|
146
|
-
debug "Got response: #{
|
147
|
-
|
148
|
-
@
|
149
|
+
debug "Got response: #{dev_addr.interface_name}:#{dev_addr.index} (driver name - #{drv_name})"
|
150
|
+
|
151
|
+
@dev = make_device(dev_addr)
|
152
|
+
if @devices.one? { |d| d.addr == dev_addr }
|
153
|
+
warn "The device #{dev_addr.interface_name}:#{dev_addr.index} has already been subscribed"
|
154
|
+
@dev = nil
|
155
|
+
else
|
156
|
+
@devices << @dev
|
157
|
+
end
|
149
158
|
when PLAYER_PLAYER_REQ_DATAMODE, PLAYER_PLAYER_REQ_DATA
|
150
159
|
nil
|
151
160
|
else
|
data/lib/ruby-player/common.rb
CHANGED
@@ -23,20 +23,20 @@ module Player
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def
|
27
|
-
if [:debug, :
|
28
|
-
puts log_msg(:
|
26
|
+
def info(msg)
|
27
|
+
if [:debug, :info].include?(@log_level)
|
28
|
+
puts log_msg(:info, msg).to_ansi.normal
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def warn(msg)
|
33
|
-
if [:debug, :
|
33
|
+
if [:debug, :info, :warn].include?(@log_level)
|
34
34
|
puts log_msg(:warn, msg).to_ansi.blue
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def error(msg)
|
39
|
-
if [:debug, :
|
39
|
+
if [:debug, :info, :warn, :debug].include?(@log_level)
|
40
40
|
puts log_msg(:error, msg).to_ansi.red
|
41
41
|
end
|
42
42
|
end
|
@@ -69,8 +69,12 @@ module Player
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
def to_a_by_default(src, default)
|
73
|
+
default.keys.map { |k| src[k] || default[k] }
|
74
|
+
end
|
75
|
+
|
72
76
|
def unexpected_message(hdr)
|
73
|
-
warn "
|
77
|
+
warn "Got unexpection message type #{hdr.type_name}::#{hdr.subtype_name} for #@addr"
|
74
78
|
end
|
75
79
|
|
76
80
|
def hash_to_sft(hash)
|
data/lib/ruby-player/dev_addr.rb
CHANGED
data/lib/ruby-player/device.rb
CHANGED
@@ -11,7 +11,6 @@
|
|
11
11
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
12
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
13
|
# GNU General Public License for more details.
|
14
|
-
require "socket"
|
15
14
|
|
16
15
|
module Player
|
17
16
|
# Basic class for all intrefaces
|
@@ -35,7 +34,7 @@ module Player
|
|
35
34
|
end
|
36
35
|
|
37
36
|
def send_message(type, subtype, msg="")
|
38
|
-
@client.
|
37
|
+
@client.send_message_with_hdr( Header.new(
|
39
38
|
dev_addr: @addr,
|
40
39
|
type: type,
|
41
40
|
subtype: subtype,
|
data/lib/ruby-player/gripper.rb
CHANGED
@@ -77,6 +77,22 @@ module Player
|
|
77
77
|
self
|
78
78
|
end
|
79
79
|
|
80
|
+
# Provides information on how far into the gripper an object is.
|
81
|
+
# For most grippers, this will be a bit mask, with each bit representing whether
|
82
|
+
# a beam has been interrupted or not.
|
83
|
+
# @see #state
|
84
|
+
# @retun [Integer]
|
85
|
+
def beams
|
86
|
+
state[:beams]
|
87
|
+
end
|
88
|
+
|
89
|
+
# Number of currently stored objects
|
90
|
+
# @see #state
|
91
|
+
# @retun [Integer]
|
92
|
+
def stored
|
93
|
+
state[:stored]
|
94
|
+
end
|
95
|
+
|
80
96
|
# Check openinig
|
81
97
|
def open?
|
82
98
|
state[:state] & PLAYER_GRIPPER_STATE_OPEN > 0
|
@@ -98,24 +114,28 @@ module Player
|
|
98
114
|
end
|
99
115
|
|
100
116
|
# Tells the gripper to open
|
117
|
+
# @return [Gripper] self
|
101
118
|
def open!
|
102
119
|
send_message(PLAYER_MSGTYPE_CMD, PLAYER_GRIPPER_CMD_OPEN)
|
103
120
|
self
|
104
121
|
end
|
105
122
|
|
106
123
|
# Tells the gripper to close
|
124
|
+
# @return [Gripper] self
|
107
125
|
def close!
|
108
126
|
send_message(PLAYER_MSGTYPE_CMD, PLAYER_GRIPPER_CMD_CLOSE)
|
109
127
|
self
|
110
128
|
end
|
111
129
|
|
112
130
|
# Tells the gripper to stop
|
131
|
+
# @return [Gripper] self
|
113
132
|
def stop!
|
114
133
|
send_message(PLAYER_MSGTYPE_CMD, PLAYER_GRIPPER_CMD_STOP)
|
115
134
|
self
|
116
135
|
end
|
117
136
|
|
118
137
|
# Tells the gripper to store whatever it is holding.
|
138
|
+
# @return [Gripper] self
|
119
139
|
def store!
|
120
140
|
send_message(PLAYER_MSGTYPE_CMD, PLAYER_GRIPPER_CMD_STORE)
|
121
141
|
self
|
@@ -123,6 +143,7 @@ module Player
|
|
123
143
|
|
124
144
|
# Tells the gripper to retrieve a stored object (so that it can be put back into the world).
|
125
145
|
# The opposite of store.
|
146
|
+
# @return [Gripper] self
|
126
147
|
def retrieve!
|
127
148
|
send_message(PLAYER_MSGTYPE_CMD, PLAYER_GRIPPER_CMD_RETRIEVE)
|
128
149
|
self
|
@@ -149,23 +170,23 @@ module Player
|
|
149
170
|
private
|
150
171
|
def read_state(msg)
|
151
172
|
fill_hash!(@state, msg.unpack("NNN"))
|
152
|
-
debug "
|
173
|
+
debug "Got state: " + hash_to_sft(@state)
|
153
174
|
end
|
154
175
|
|
155
176
|
def read_geom(msg)
|
156
177
|
data = msg.unpack("G12NN")
|
157
178
|
fill_hash!(@geom[:pose], data)
|
158
|
-
debug "
|
179
|
+
debug "Got pose: " + hash_to_sft(@geom[:pose])
|
159
180
|
|
160
181
|
fill_hash!(@geom[:outer_size], data)
|
161
|
-
debug "
|
182
|
+
debug "Got outer size: " + hash_to_sft(@geom[:outer_size])
|
162
183
|
|
163
184
|
fill_hash!(@geom[:inner_size], data)
|
164
|
-
debug "
|
185
|
+
debug "Got inner size: " + hash_to_sft(@geom[:inner_size])
|
165
186
|
|
166
187
|
@geom[:number_beams] = data.shift
|
167
188
|
@geom[:capacity] = data.shift
|
168
|
-
debug("
|
189
|
+
debug("Got number_beams=%{number_beams}, capacity=%{capacity}" % @geom)
|
169
190
|
end
|
170
191
|
end
|
171
192
|
end
|
data/lib/ruby-player/header.rb
CHANGED
@@ -20,7 +20,7 @@ module Player
|
|
20
20
|
attr_reader :dev_addr, :type, :subtype, :time, :seq, :size
|
21
21
|
|
22
22
|
def initialize(param = {})
|
23
|
-
@dev_addr = param[:dev_addr]
|
23
|
+
@dev_addr = param[:dev_addr] || DevAddr.new
|
24
24
|
@type = param[:type].to_i
|
25
25
|
@subtype = param[:subtype].to_i
|
26
26
|
@time = param[:time] || Time.now.to_f / 1000
|