ruby-player 0.3.0 → 0.4.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.
@@ -1,3 +1,17 @@
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
+ #
1
15
  module Player
2
16
  PLAYERXDR_DEVADDR_SIZE = 16
3
17
  PLAYERXDR_MSGHDR_SIZE = PLAYERXDR_DEVADDR_SIZE + 24
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -14,6 +14,7 @@
14
14
  require "socket"
15
15
 
16
16
  module Player
17
+ # Basic class for all intrefaces
17
18
  class Device
18
19
  include Common
19
20
 
@@ -33,7 +34,6 @@ module Player
33
34
  raise_error "Method `handle_response` isn't implemented for `#{self.class}`"
34
35
  end
35
36
 
36
- private
37
37
  def send_message(type, subtype, msg="")
38
38
  @client.write( Header.new(
39
39
  dev_addr: @addr,
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -149,19 +149,19 @@ module Player
149
149
  private
150
150
  def read_state(msg)
151
151
  fill_hash!(@state, msg.unpack("NNN"))
152
- debug("Get gripper state state=%d, beams=%d, stored=%d" % @state.values)
152
+ debug "Get state: " + hash_to_sft(@state)
153
153
  end
154
154
 
155
155
  def read_geom(msg)
156
156
  data = msg.unpack("G12NN")
157
157
  fill_hash!(@geom[:pose], data)
158
- debug "Get gripper pose: " + pose_to_s(@geom[:pose])
158
+ debug "Get pose: " + hash_to_sft(@geom[:pose])
159
159
 
160
160
  fill_hash!(@geom[:outer_size], data)
161
- debug "Get gripper outer size: " + size_to_s(@geom[:outer_size])
161
+ debug "Get outer size: " + hash_to_sft(@geom[:outer_size])
162
162
 
163
163
  fill_hash!(@geom[:inner_size], data)
164
- debug "Get gripper inner size: " + size_to_s(@geom[:inner_size])
164
+ debug "Get inner size: " + hash_to_sft(@geom[:inner_size])
165
165
 
166
166
  @geom[:number_beams] = data.shift
167
167
  @geom[:capacity] = data.shift
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -13,6 +13,7 @@
13
13
  # GNU General Public License for more details.
14
14
 
15
15
  module Player
16
+ # Header of message
16
17
  class Header
17
18
  include Common
18
19
 
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -43,7 +43,7 @@ module Player
43
43
  @geom = {px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0, sw: 0.0, sl: 0.0, sh: 0.0}
44
44
  end
45
45
 
46
- # Depricated alias for data
46
+ # @deprecated Use {#state}
47
47
  def position
48
48
  warn "Method `position` is deprecated. Pleas use `data` for access to position"
49
49
  state
@@ -58,17 +58,29 @@ module Player
58
58
 
59
59
  # Turn on motor
60
60
  # @return self
61
- def turn_on!
61
+ def power_on!
62
62
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_MOTOR_POWER, [1].pack("N"))
63
63
  self
64
64
  end
65
65
 
66
+ # @deprecated Use {#power_on!}
67
+ def turn_on!
68
+ warn "Method `turn_on!` is deprecated. Pleas use `power_on!`"
69
+ power_on!
70
+ end
71
+
66
72
  # Turn off motor
67
- def turn_off!
73
+ def power_off!
68
74
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_MOTOR_POWER, [0].pack("N"))
69
75
  self
70
76
  end
71
77
 
78
+ # @deprecated Use {#power_off!}
79
+ def turn_off!
80
+ warn "Method `turn_off!` is deprecated. Pleas use `power_off!`"
81
+ power_off!
82
+ end
83
+
72
84
  def direct_speed_control!
73
85
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_POSITION2D_REQ_VELOCITY_MODE, [0].pack("N"))
74
86
  self
@@ -90,10 +102,10 @@ module Player
90
102
  end
91
103
 
92
104
  # Set odometry of robot.
93
- # @param [Hash] odometry
94
- # @option odometry :px x position (m)
95
- # @option odometry :py y position (m)
96
- # @option odometry :pa angle (rad).
105
+ # @param [Hash] odom odometry
106
+ # @option odom :px x position (m)
107
+ # @option odom :py y position (m)
108
+ # @option odom :pa angle (rad).
97
109
  # @return self
98
110
  def set_odometry(odom)
99
111
  data = [
@@ -248,12 +260,12 @@ module Player
248
260
  private
249
261
  def read_state(msg)
250
262
  fill_hash!(@state, msg.unpack("GGGGGGN"))
251
- debug("Get state px=%.2f py=%.2f pa=%.2f; vx=%.2f, vy=%.2f, va=%.2f, stall=%d" % @state.values)
263
+ debug "Get state: " + hash_to_sft(@state)
252
264
  end
253
265
 
254
266
  def read_geom(msg)
255
267
  fill_hash!(@geom, msg.unpack("G*"))
256
- debug "Get geom " + geom_to_s(@geom)
268
+ debug "Get geom: " + hash_to_sft(@geom)
257
269
  end
258
270
  end
259
271
  end
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -96,7 +96,7 @@ module Player
96
96
  private
97
97
  def read_state(msg)
98
98
  fill_hash!(@state, msg.unpack("NggggN"))
99
- debug("Get power state valid=%x volts=%.2f, percent=%.2f, joules=%.2f; watts=%.2f, charging=%d" % @state.values)
99
+ debug "Get state: " + hash_to_sft(@state)
100
100
  end
101
101
  end
102
102
  end
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -18,19 +18,13 @@ module Player
18
18
  #
19
19
  # @example
20
20
  # ranger = robot.subscribe(:ranger, index: 0)
21
- # ranger.rangers #=> [0.2, 0.1, 0.2]
21
+ # ranger[0].range #=> 0.2
22
22
  class Ranger < Device
23
+ include Enumerable
23
24
 
24
- # Range data [m]
25
- # @return [Array] fot each sensor
26
- attr_reader :rangers
27
-
28
- # Intensity data [m].
29
- # @return [Array] fot each sensor
30
- attr_reader :intensities
31
25
 
32
26
  # Configuration of ranger
33
- # @see set_config
27
+ # @see #set_config
34
28
  attr_reader :config
35
29
 
36
30
 
@@ -40,12 +34,23 @@ module Player
40
34
 
41
35
  def initialize(addr, client)
42
36
  super
43
- @rangers = []
44
- @intensities = []
45
- @geom = {px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0, sw: 0.0, sl: 0.0, sh: 0.0, sensors: []}
37
+ @sensors = []
38
+ @geom = {px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0, sw: 0.0, sl: 0.0, sh: 0.0 }
46
39
  @config = { min_angle: 0.0, max_angle: 0.0, angular_res: 0.0, min_range: 0.0, max_range: 0.0, range_res: 0.0, frequecy: 0.0 }
47
40
  end
41
+
42
+ # @deprecated use `ranger.collect { |r| r.range }
43
+ def rangers
44
+ warn "Method `rangers` is deprecated. Pleas use `ranger.collect { |r| r.state[:range] }`"
45
+ @sensors.collect { |s| s.range }
46
+ end
48
47
 
48
+ # @deprecated use `ranger.collect { |r| r.intensity }
49
+ def intensities
50
+ warn "Method `intensities` is deprecated. Pleas use `ranger.collect { |r| r.state[:intensity] }`"
51
+ @sensors.collect { |s| s.intensity }
52
+ end
53
+
49
54
  # Query ranger geometry
50
55
  # @return self
51
56
  def query_geom
@@ -55,17 +60,29 @@ module Player
55
60
 
56
61
  # Turn on ranger
57
62
  # @return self
58
- def turn_on!
63
+ def power_on!
59
64
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_POWER, [1].pack("N"))
60
65
  self
61
66
  end
62
67
 
68
+ # @deprecated Use {#power_on!}
69
+ def turn_on!
70
+ warn "Method `turn_on!` is deprecated. Pleas use `power_on!`"
71
+ power_on!
72
+ end
73
+
63
74
  # Turn off ranger
64
- def turn_off!
75
+ def power_off!
65
76
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_POWER, [0].pack("N"))
66
77
  self
67
78
  end
68
79
 
80
+ # @deprecated Use {#power_off!}
81
+ def turn_off!
82
+ warn "Method `turn_off!` is deprecated. Pleas use `power_off!`"
83
+ power_off!
84
+ end
85
+
69
86
  def intensity_enable!
70
87
  send_message(PLAYER_MSGTYPE_REQ, PLAYER_RANGER_REQ_INTNS, [1].pack("N"))
71
88
  self
@@ -109,12 +126,18 @@ module Player
109
126
  case hdr.subtype
110
127
  when PLAYER_RANGER_DATA_RANGE
111
128
  data = msg.unpack("NNG*")
112
- @rangers = data[2..-1]
113
- debug "Get rangers #{@rangers.inspect}"
129
+ data[2..-1].each_with_index do |r, i|
130
+ self[i].state[:range] = r
131
+ end
132
+
133
+ debug "Get rangers #{@sensors.collect { |s| s.state[:range] }}"
114
134
  when PLAYER_RANGER_DATA_INTNS
115
135
  data = msg.unpack("NNG*")
116
- @intensities = data[2..-1]
117
- debug "Get intensities #{@rangers.inspect}"
136
+ data[2..-1].each_with_index do |ints, i|
137
+ self[i].state[:intensity] = ints
138
+ end
139
+
140
+ debug "Get intensities #{@sensors.collect { |s| s.state[:intensity]}}"
118
141
  when PLAYER_RANGER_DATA_GEOM
119
142
  read_geom(msg)
120
143
  else
@@ -135,6 +158,14 @@ module Player
135
158
  end
136
159
  end
137
160
 
161
+ def [](index)
162
+ @sensors[index] ||= Sensor.new(index, self)
163
+ end
164
+
165
+ def each
166
+ @sensors.each { |s| yield s }
167
+ end
168
+
138
169
  private
139
170
  def read_config(msg)
140
171
  fill_hash!(@config, msg.unpack("G*"))
@@ -143,7 +174,7 @@ module Player
143
174
  def read_geom(msg)
144
175
  data = msg[0,72].unpack("G*")
145
176
  fill_hash!(@geom, data)
146
- debug("Get geom: " + geom_to_s(@geom))
177
+ debug "Get geom: " + hash_to_sft(@geom)
147
178
 
148
179
 
149
180
  p_count = msg[72,8].unpack("NN")
@@ -155,21 +186,18 @@ module Player
155
186
  sizes = msg[88 + 48*p_count, 24*s_count].unpack("G" +(3* s_count).to_s)
156
187
 
157
188
  p_count.times do |i|
158
- @geom[:sensors][i] ||= {}
159
- [:px, :py, :pz, :proll, :ppitch, :pyaw].each_with_index do |k,j|
160
- @geom[:sensors][i][k] = poses[6*i + j]
161
- end
162
- debug("Get poses for ##{i} sensor: px=%.2f, py=%.2f, pz=%.2f, proll=%.2f, ppitch=%.2f, pyaw=%.2f" % @geom[:sensors][i].values[0,6])
189
+ [:px, :py, :pz, :proll, :ppitch, :pyaw]
190
+ .each_with_index { |k,j| self[i].geom[k] = poses[6*i + j] }
191
+ debug("Get poses for ##{i} sensor: px=%.2f, py=%.2f, pz=%.2f, proll=%.2f, ppitch=%.2f, pyaw=%.2f" % @sensors[i].geom.values[0,6])
163
192
  end
164
193
 
165
194
  s_count.times do |i|
166
- @geom[:sensors][i] ||= {}
167
- [:sw, :sl, :sh].each_with_index do |k,j|
168
- @geom[:sensors][i][k] = sizes[3*i + j]
169
- end
170
- debug("Get sizes for ##{i} sensor: sw=%.2f, sl=%.2f, sh=%.2f" % @geom[:sensors][i].values[6,3])
195
+ [:sw, :sl, :sh]
196
+ .each_with_index { |k,j| self[i].geom[k] = sizes[3*i + j] }
197
+ debug("Get sizes for ##{i} sensor: sw=%.2f, sl=%.2f, sh=%.2f" % @sensors[i].geom.values[6,3])
171
198
  end
172
199
 
173
200
  end
201
+
174
202
  end
175
203
  end
@@ -0,0 +1,43 @@
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
+ class Sensor
17
+
18
+ # State of sensor
19
+ # @return [Hash] { :range, :intensity }
20
+ attr_reader :state
21
+ attr_reader :geom
22
+
23
+ def initialize(index, ranger)
24
+ @index, @ranger = index, ranger
25
+ @state = { ranger: 0.0, intensity: 0.0 }
26
+ @geom = {px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0,
27
+ sw: 0.0, sl: 0.0, sh: 0.0
28
+ }
29
+ end
30
+
31
+ # Range data [m]
32
+ # @return [Float]
33
+ def range
34
+ @state[:range]
35
+ end
36
+
37
+ # Intensity data [m].
38
+ # @return [Float]
39
+ def intensity
40
+ @state[:intensity]
41
+ end
42
+ end
43
+ end
@@ -1,6 +1,6 @@
1
1
  # Ruby Player - Ruby client library for Player (tools for robots)
2
2
  #
3
- # Copyright (C) 2012 Timin Aleksey
3
+ # Copyright (C) 2012 Aleksey Timin
4
4
  #
5
5
  # This program is free software: you can redistribute it and/or modify
6
6
  # it under the terms of the GNU General Public License as published by
@@ -13,5 +13,5 @@
13
13
  # GNU General Public License for more details.
14
14
 
15
15
  module Player
16
- VERSION = "0.3.0"
16
+ VERSION = "0.4.0"
17
17
  end
@@ -0,0 +1,129 @@
1
+ require File.dirname(__FILE__) + "/spec_helper"
2
+
3
+ include Player
4
+ describe Player::ActArray do
5
+ before do
6
+ client = mock_client
7
+
8
+ @actarray = Player::ActArray.new(
9
+ Player::DevAddr.new(host: 0, robot:0, interface: PLAYER_ACTARRAY_CODE, index: 0),
10
+ client
11
+ )
12
+
13
+ mock_sending_message(@actarray)
14
+ end
15
+
16
+ it 'should have default state' do
17
+ @actarray.state.should eql(motor_state: 0)
18
+ @actarray.geom.should eql(px: 0.0, py: 0.0, pz: 0.0, proll: 0.0, ppitch: 0.0, pyaw: 0.0)
19
+ end
20
+
21
+ it 'should set power state for all actuators' do
22
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_POWER, [0].pack("N"))
23
+ @actarray.power_off!
24
+
25
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_POWER, [1].pack("N"))
26
+ @actarray.power_on!
27
+ end
28
+
29
+ it 'should set brakes state for all actuators' do
30
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_BRAKES, [0].pack("N"))
31
+ @actarray.brakes_off!
32
+
33
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_BRAKES, [1].pack("N"))
34
+ @actarray.brakes_on!
35
+ end
36
+
37
+ it 'should query geometry' do
38
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_GET_GEOM)
39
+ @actarray.query_geom
40
+ end
41
+
42
+
43
+ it 'should set position for all joints' do
44
+ data = [3, 1.0, 2.0, 3.0]
45
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_MULTI_POS, data.pack("Ng*"))
46
+ @actarray.set_positions(data[1..-1])
47
+ end
48
+
49
+ it 'should set speed for all joints' do
50
+ data = [2, 2.0, 3.0]
51
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_MULTI_SPEED, data.pack("Ng*"))
52
+ @actarray.set_speeds(data[1..-1])
53
+ end
54
+
55
+ it 'should tell all joint go to nome' do
56
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_HOME, [-1].pack("N"))
57
+ @actarray.go_home!
58
+ end
59
+
60
+
61
+ it 'should tell all joints to attempt to move with the given current.' do
62
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_CURRENT, [-1, 0.3].pack("Ng"))
63
+ @actarray.set_current_all(0.3)
64
+ end
65
+
66
+ it 'should tell a joint to attempt to move with the given current.' do
67
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_CURRENT, [0, 0.3].pack("Ng"))
68
+ @actarray[0].set_current(0.3)
69
+ end
70
+
71
+ it 'should set current for all joints' do
72
+ data = [2, 2.0, 3.0]
73
+ should_send_message(PLAYER_MSGTYPE_CMD, PLAYER_ACTARRAY_CMD_MULTI_CURRENT, data.pack("Ng*"))
74
+ @actarray.set_currents(data[1..-1])
75
+ end
76
+
77
+ it 'should implement Enumerable' do
78
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_ACCEL, [0, 0.3].pack("Ng"))
79
+ should_send_message(PLAYER_MSGTYPE_REQ, PLAYER_ACTARRAY_REQ_ACCEL, [1, 0.3].pack("Ng"))
80
+ @actarray[0].set_accel_config(0.3)
81
+ @actarray[1].set_accel_config(0.3)
82
+
83
+ @actarray.each_with_index { |a,i| a.joint.should eql(i) }
84
+ @actarray.count.should eql(2)
85
+ end
86
+
87
+ it 'should fill state data' do
88
+ state = [2, 0, 1.0, 2.0, 3.0, 4.0, PLAYER_ACTARRAY_ACTSTATE_IDLE,
89
+ 5.0, 6.0, 7.0, 8.0, PLAYER_ACTARRAY_ACTSTATE_MOVING,
90
+ 1]
91
+
92
+ msg = state.pack("NNg4Ng4NN")
93
+ @actarray.fill(
94
+ Player::Header.from_a([0,0,PLAYER_ACTARRAY_CODE,0, PLAYER_MSGTYPE_DATA, PLAYER_ACTARRAY_DATA_STATE, 0.0, 0, msg.bytesize]),
95
+ msg
96
+ )
97
+
98
+ @actarray[0].state.should eql(position: 1.0, speed: 2.0, acceleration: 3.0, current: 4.0, state: PLAYER_ACTARRAY_ACTSTATE_IDLE)
99
+ @actarray[1].state.should eql(position: 5.0, speed: 6.0, acceleration: 7.0, current: 8.0, state: PLAYER_ACTARRAY_ACTSTATE_MOVING)
100
+ @actarray.state[:motor_state].should eql(1)
101
+ end
102
+
103
+ it 'should get geom by request' do
104
+ geom = [2, 0,
105
+ PLAYER_ACTARRAY_TYPE_LINEAR, 2.0, 0.1, 0.2, 0.3, 1.0, 2.0, 3.0, 0.0, 0.5, 1.0, 0.0, 2.0, 0,
106
+ PLAYER_ACTARRAY_TYPE_ROTARY, 4.0, 1.1, 1.2, 1.3, 1.1, 2.1, 3.1, 0.0, 0.5, 1.0, 1.0, 1.0, 1,
107
+ 0.5, 0.6, 0.7, 1.5, 1.6, 1.7]
108
+
109
+ msg = geom.pack("NNNgG6g5NNgG6g5NG6")
110
+ @actarray.handle_response(
111
+ Player::Header.from_a([0,0,PLAYER_ACTARRAY_CODE,0, PLAYER_MSGTYPE_RESP_ACK, PLAYER_ACTARRAY_REQ_GET_GEOM, 0.0, 0, msg.bytesize]),
112
+ msg
113
+ )
114
+
115
+ @actarray[0].geom.should eql(type: PLAYER_ACTARRAY_TYPE_LINEAR, length: 2.0,
116
+ proll: 0.1, ppitch: 0.2, pyaw: 0.3,
117
+ px: 1.0, py: 2.0, pz: 3.0,
118
+ min: 0.0, centre: 0.5, max: 1.0, home: 0.0,
119
+ config_speed: 2.0, hasbreaks: 0)
120
+
121
+ @actarray[1].geom.should eql(type: PLAYER_ACTARRAY_TYPE_ROTARY, length: 4.0,
122
+ proll: 1.1, ppitch: 1.2, pyaw: 1.3,
123
+ px: 1.1, py: 2.1, pz: 3.1,
124
+ min: 0.0, centre: 0.5, max: 1.0, home: 1.0,
125
+ config_speed: 1.0, hasbreaks: 1)
126
+
127
+ @actarray.geom.should eql(px: 0.5, py: 0.6, pz: 0.7, proll: 1.5, ppitch: 1.6, pyaw: 1.7)
128
+ end
129
+ end