artoo 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ module Artoo
2
+ module Events
3
+ # Subscribe to an event from a device
4
+ def on(device, events={})
5
+ events.each do |k, v|
6
+ subscribe("#{safe_name}_#{device.name}_#{k}", create_proxy_method(k, v))
7
+ end
8
+ end
9
+
10
+ # Create an anonymous subscription method so we can wrap the
11
+ # subscription method fire into a valid method regardless
12
+ # of where it is defined
13
+ def create_proxy_method(k, v)
14
+ proxy_method_name(k).tap do |name|
15
+ self.class.send :define_method, name do |*args|
16
+ case v
17
+ when Symbol
18
+ self.send v.to_sym, *args
19
+ when Proc
20
+ v.call(*args)
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ # A simple loop to create a 'fake' anonymous method
27
+ def proxy_method_name(k)
28
+ begin
29
+ meth = "#{k}_#{Random.rand(999)}"
30
+ end while respond_to?(meth)
31
+ meth
32
+ end
33
+ end
34
+ end
data/lib/artoo/robot.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require 'celluloid/io'
2
2
  require 'multi_json'
3
3
 
4
+ require 'artoo/basic'
4
5
  require 'artoo/connection'
5
6
  require 'artoo/device'
7
+ require 'artoo/events'
6
8
  require 'artoo/api'
7
9
  require 'artoo/master'
8
10
  require 'artoo/port'
@@ -14,7 +16,9 @@ module Artoo
14
16
  class Robot
15
17
  include Celluloid
16
18
  include Celluloid::Notifications
19
+ extend Artoo::Basic
17
20
  include Artoo::Utility
21
+ include Artoo::Events
18
22
 
19
23
  attr_reader :connections, :devices, :name
20
24
 
@@ -25,15 +29,18 @@ module Artoo
25
29
  end
26
30
 
27
31
  class << self
28
- attr_accessor :connection_types, :device_types, :working_code,
32
+ attr_accessor :device_types, :working_code,
29
33
  :use_api, :api_host, :api_port
30
34
 
35
+ def connection_types
36
+ @@connection_types ||= []
37
+ end
38
+
31
39
  # connection to some hardware that has one or more devices via some specific protocol
32
40
  # Example:
33
41
  # connection :arduino, :adaptor => :firmata, :port => '/dev/tty.usbmodemxxxxx'
34
42
  def connection(name, params = {})
35
43
  Celluloid::Logger.info "Registering connection '#{name}'..."
36
- self.connection_types ||= []
37
44
  self.connection_types << {:name => name}.merge(params)
38
45
  end
39
46
 
@@ -92,81 +99,6 @@ module Artoo
92
99
  def test?
93
100
  ENV["ARTOO_TEST"] == 'true'
94
101
  end
95
-
96
- # Taken from Sinatra codebase
97
- # Sets an option to the given value. If the value is a proc,
98
- # the proc will be called every time the option is accessed.
99
- def set(option, value = (not_set = true), ignore_setter = false, &block)
100
- raise ArgumentError if block and !not_set
101
- value, not_set = block, false if block
102
-
103
- if not_set
104
- raise ArgumentError unless option.respond_to?(:each)
105
- option.each { |k,v| set(k, v) }
106
- return self
107
- end
108
-
109
- if respond_to?("#{option}=") and not ignore_setter
110
- return __send__("#{option}=", value)
111
- end
112
-
113
- setter = proc { |val| set option, val, true }
114
- getter = proc { value }
115
-
116
- case value
117
- when Proc
118
- getter = value
119
- when Symbol, Fixnum, FalseClass, TrueClass, NilClass
120
- getter = value.inspect
121
- when Hash
122
- setter = proc do |val|
123
- val = value.merge val if Hash === val
124
- set option, val, true
125
- end
126
- end
127
-
128
- define_singleton_method("#{option}=", setter) if setter
129
- define_singleton_method(option, getter) if getter
130
- define_singleton_method("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
131
- self
132
- end
133
-
134
- # Taken from Sinatra codebase
135
- CALLERS_TO_IGNORE = [ # :nodoc:
136
- /lib\/artoo.*\.rb$/, # artoo code
137
- /^\(.*\)$/, # generated code
138
- /rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks
139
- /active_support/, # active_support require hacks
140
- /bundler(\/runtime)?\.rb/, # bundler require hacks
141
- /<internal:/, # internal in ruby >= 1.9.2
142
- /src\/kernel\/bootstrap\/[A-Z]/ # maglev kernel files
143
- ]
144
-
145
- # Taken from Sinatra codebase
146
- # Like Kernel#caller but excluding certain magic entries and without
147
- # line / method information; the resulting array contains filenames only.
148
- def caller_files
149
- cleaned_caller(1).flatten
150
- end
151
-
152
- private
153
-
154
- # Taken from Sinatra codebase
155
- def define_singleton_method(name, content = Proc.new)
156
- # replace with call to singleton_class once we're 1.9 only
157
- (class << self; self; end).class_eval do
158
- undef_method(name) if method_defined? name
159
- String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
160
- end
161
- end
162
-
163
- # Taken from Sinatra codebase
164
- # Like Kernel#caller but excluding certain magic entries
165
- def cleaned_caller(keep = 3)
166
- caller(1).
167
- map { |line| line.split(/:(?=\d|in )/, 3)[0,keep] }.
168
- reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
169
- end
170
102
  end
171
103
 
172
104
  def safe_name
@@ -184,30 +116,9 @@ module Artoo
184
116
  # start doing the work
185
117
  def work
186
118
  Logger.info "Starting work..."
187
- make_connections
188
- start_devices
189
- current_instance.instance_eval(&working_code)
190
- rescue Exception => e
191
- Logger.error e.message
192
- Logger.error e.backtrace.inspect
193
- end
194
-
195
- def make_connections
196
- result = false
197
- future_connections = []
198
- # block until all connections done
199
- connections.each {|k, c| future_connections << c.future.connect}
200
- future_connections.each {|v| result = v.value}
201
- result
202
- end
203
-
204
- def start_devices
205
- result = false
206
- future_devices = []
207
- # block until all devices done
208
- devices.each {|k, d| future_devices << d.future.start_device}
209
- future_devices.each {|v| result = v.value}
210
- result
119
+ execute_startup(connections) {|c| c.future.connect}
120
+ execute_startup(devices) {|d| d.future.start_device}
121
+ execute_working_code
211
122
  end
212
123
 
213
124
  def disconnect
@@ -219,7 +130,6 @@ module Artoo
219
130
  end
220
131
 
221
132
  def connection_types
222
- current_class.connection_types ||= []
223
133
  current_class.connection_types
224
134
  end
225
135
 
@@ -232,37 +142,6 @@ module Artoo
232
142
  current_class.working_code ||= proc {puts "No work defined."}
233
143
  end
234
144
 
235
- # Subscribe to an event from a device
236
- def on(device, events={})
237
- events.each do |k, v|
238
- subscribe("#{safe_name}_#{device.name}_#{k}", create_proxy_method(k, v))
239
- end
240
- end
241
-
242
- # Create an anonymous subscription method so we can wrap the
243
- # subscription method fire into a valid method regardless
244
- # of where it is defined
245
- def create_proxy_method(k, v)
246
- proxy_method_name(k).tap do |name|
247
- self.class.send :define_method, name do |*args|
248
- case v
249
- when Symbol
250
- self.send v.to_sym, *args
251
- when Proc
252
- v.call(*args)
253
- end
254
- end
255
- end
256
- end
257
-
258
- # A simple loop to create a 'fake' anonymous method
259
- def proxy_method_name(k)
260
- begin
261
- meth = "#{k}_#{Random.rand(999)}"
262
- end while respond_to?(meth)
263
- meth
264
- end
265
-
266
145
  def to_hash
267
146
  {:name => name,
268
147
  :connections => connections.each_value.collect {|c|c.to_hash},
@@ -295,5 +174,17 @@ module Artoo
295
174
  @devices[d.name.intern] = d
296
175
  }
297
176
  end
177
+
178
+ def execute_startup(things, &block)
179
+ future_things = things.each_value.collect {|t| yield(t)}
180
+ future_things.each {|v| result = v.value}
181
+ end
182
+
183
+ def execute_working_code
184
+ current_instance.instance_eval(&working_code)
185
+ rescue Exception => e
186
+ Logger.error e.message
187
+ Logger.error e.backtrace.inspect
188
+ end
298
189
  end
299
- end
190
+ end
data/lib/artoo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Artoo
2
2
  unless const_defined?('VERSION')
3
- VERSION = "0.1.3"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'artoo/drivers/motor'
3
+
4
+ describe Artoo::Drivers::Motor do
5
+ before do
6
+ @device = mock('device')
7
+ @device.stubs(:pin).returns([2, 3, 4])
8
+ @motor = Artoo::Drivers::Motor.new(:parent => @device)
9
+
10
+ @connection = mock('connection')
11
+ @connection.stubs(:set_pin_mode)
12
+ @connection.stubs(:analog_write)
13
+ @connection.stubs(:digital_write)
14
+ @device.stubs(:connection).returns(@connection)
15
+ end
16
+
17
+ it 'Motor#speed must be valid' do
18
+ invalid_speed = lambda { @motor2 = Artoo::Drivers::Motor.new(:parent => @device); @motor2.speed("ads") }
19
+ invalid_speed.must_raise RuntimeError
20
+ error = invalid_speed.call rescue $!
21
+ error.message.must_equal 'Motor speed must be an integer between 0-255'
22
+ end
23
+
24
+ it 'Motor#forward' do
25
+ @motor.wrapped_object.expects(:set_legs)
26
+ @motor.forward(100)
27
+ @motor.current_speed.must_equal 100
28
+ end
29
+
30
+ it 'Motor#backward' do
31
+ @motor.wrapped_object.expects(:set_legs)
32
+ @motor.backward(100)
33
+ @motor.current_speed.must_equal 100
34
+ end
35
+
36
+ it 'Motor#stop' do
37
+ @motor.stop
38
+ @motor.current_speed.must_equal 0
39
+ end
40
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../test_helper")
2
+ require 'artoo/drivers/servo'
3
+
4
+ describe Artoo::Drivers::Servo do
5
+ before do
6
+ @device = mock('device')
7
+ @device.stubs(:pin).returns(3)
8
+ @servo = Artoo::Drivers::Servo.new(:parent => @device)
9
+
10
+ @connection = mock('connection')
11
+ @connection.stubs(:set_pin_mode)
12
+ @connection.stubs(:analog_write)
13
+ # @connection.stubs(:digital_write)
14
+ @device.stubs(:connection).returns(@connection)
15
+ end
16
+
17
+ it "Servo#angle_to_span" do
18
+ @servo.angle_to_span(0).must_equal 0
19
+ @servo.angle_to_span(30).must_equal 42
20
+ @servo.angle_to_span(90).must_equal 127
21
+ @servo.angle_to_span(180).must_equal 255
22
+ end
23
+
24
+ it 'Servo#move must be valid' do
25
+ invalid_angle = lambda { @servo2 = Artoo::Drivers::Servo.new(:parent => @device); @servo2.move(360) }
26
+ invalid_angle.must_raise RuntimeError
27
+ error = invalid_angle.call rescue $!
28
+ error.message.must_equal 'Servo angle must be an integer between 0-180'
29
+ end
30
+
31
+ it 'Servo#min' do
32
+ @servo.min
33
+ @servo.current_angle.must_equal 0
34
+ end
35
+
36
+ it 'Servo#center' do
37
+ @servo.center
38
+ @servo.current_angle.must_equal 90
39
+ end
40
+
41
+ it 'Servo#max' do
42
+ @servo.max
43
+ @servo.current_angle.must_equal 180
44
+ end
45
+ end
@@ -7,5 +7,10 @@ describe Artoo::Drivers::Wiiclassic do
7
7
  @driver = Artoo::Drivers::Wiiclassic.new(:parent => @device)
8
8
  end
9
9
 
10
- it 'must do things'
10
+ it 'must Artoo::Drivers::Wiiclassic#set_joystick_default_value' do
11
+ val = "101"
12
+ @driver.joystick[:test_axis] = nil
13
+ @driver.set_joystick_default_value(:test_axis, val)
14
+ @driver.joystick[:test_axis].must_equal val
15
+ end
11
16
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: artoo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ron Evans
@@ -13,8 +12,106 @@ authors:
13
12
  autorequire:
14
13
  bindir: bin
15
14
  cert_chain: []
16
- date: 2013-02-26 00:00:00.000000000 Z
17
- dependencies: []
15
+ date: 2013-03-08 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: celluloid-io
19
+ requirement: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: '0.12'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '0.12'
31
+ - !ruby/object:Gem::Dependency
32
+ name: reel
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '0.3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '0.3'
45
+ - !ruby/object:Gem::Dependency
46
+ name: multi_json
47
+ requirement: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ~>
50
+ - !ruby/object:Gem::Version
51
+ version: '1.6'
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ version: '1.6'
59
+ - !ruby/object:Gem::Dependency
60
+ name: active_support
61
+ requirement: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '3.0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ version: '3.0'
73
+ - !ruby/object:Gem::Dependency
74
+ name: rake
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ~>
78
+ - !ruby/object:Gem::Version
79
+ version: '10.0'
80
+ type: :runtime
81
+ prerelease: false
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: '10.0'
87
+ - !ruby/object:Gem::Dependency
88
+ name: minitest
89
+ requirement: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '4.6'
94
+ type: :development
95
+ prerelease: false
96
+ version_requirements: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ~>
99
+ - !ruby/object:Gem::Version
100
+ version: '4.6'
101
+ - !ruby/object:Gem::Dependency
102
+ name: mocha
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ~>
106
+ - !ruby/object:Gem::Version
107
+ version: '0.13'
108
+ type: :development
109
+ prerelease: false
110
+ version_requirements: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ~>
113
+ - !ruby/object:Gem::Version
114
+ version: '0.13'
18
115
  description: Ruby-based microframework for robotics
19
116
  email:
20
117
  - artoo@hybridgroup.com
@@ -25,6 +122,7 @@ extensions: []
25
122
  extra_rdoc_files: []
26
123
  files:
27
124
  - .gitignore
125
+ - .travis.yml
28
126
  - Gemfile
29
127
  - Gemfile.lock
30
128
  - Guardfile
@@ -70,6 +168,7 @@ files:
70
168
  - examples/ardrone_nav_wiiclassic.rb
71
169
  - examples/ardrone_video.rb
72
170
  - examples/ardrone_wiiclassic.rb
171
+ - examples/christmas_roomba.rb
73
172
  - examples/conway_sphero.rb
74
173
  - examples/firmata.rb
75
174
  - examples/firmata_button.rb
@@ -85,6 +184,8 @@ files:
85
184
  - examples/sphero_firmata.rb
86
185
  - examples/sphero_messages.rb
87
186
  - examples/sphero_multiple.rb
187
+ - examples/sphero_wiichuck.rb
188
+ - examples/wiichuck.rb
88
189
  - lib/artoo.rb
89
190
  - lib/artoo/adaptors/adaptor.rb
90
191
  - lib/artoo/adaptors/ardrone.rb
@@ -92,9 +193,11 @@ files:
92
193
  - lib/artoo/adaptors/ardrone_video.rb
93
194
  - lib/artoo/adaptors/firmata.rb
94
195
  - lib/artoo/adaptors/loopback.rb
196
+ - lib/artoo/adaptors/roomba.rb
95
197
  - lib/artoo/adaptors/sphero.rb
96
198
  - lib/artoo/api.rb
97
199
  - lib/artoo/api_route_helpers.rb
200
+ - lib/artoo/basic.rb
98
201
  - lib/artoo/connection.rb
99
202
  - lib/artoo/delegator.rb
100
203
  - lib/artoo/device.rb
@@ -105,12 +208,16 @@ files:
105
208
  - lib/artoo/drivers/button.rb
106
209
  - lib/artoo/drivers/driver.rb
107
210
  - lib/artoo/drivers/led.rb
211
+ - lib/artoo/drivers/motor.rb
108
212
  - lib/artoo/drivers/passthru.rb
109
213
  - lib/artoo/drivers/pinger.rb
110
214
  - lib/artoo/drivers/pinger2.rb
215
+ - lib/artoo/drivers/roomba.rb
216
+ - lib/artoo/drivers/servo.rb
111
217
  - lib/artoo/drivers/sphero.rb
112
218
  - lib/artoo/drivers/wiichuck.rb
113
219
  - lib/artoo/drivers/wiiclassic.rb
220
+ - lib/artoo/events.rb
114
221
  - lib/artoo/main.rb
115
222
  - lib/artoo/master.rb
116
223
  - lib/artoo/port.rb
@@ -132,6 +239,8 @@ files:
132
239
  - test/drivers/ardrone_video_test.rb
133
240
  - test/drivers/driver_test.rb
134
241
  - test/drivers/led_test.rb
242
+ - test/drivers/motor_test.rb
243
+ - test/drivers/servo_test.rb
135
244
  - test/drivers/sphero_test.rb
136
245
  - test/drivers/wiichuck_test.rb
137
246
  - test/drivers/wiiclassic_test.rb
@@ -141,33 +250,26 @@ files:
141
250
  - test/utility_test.rb
142
251
  homepage: https://github.com/hybridgroup/artoo
143
252
  licenses: []
253
+ metadata: {}
144
254
  post_install_message:
145
255
  rdoc_options: []
146
256
  require_paths:
147
257
  - lib
148
258
  required_ruby_version: !ruby/object:Gem::Requirement
149
- none: false
150
259
  requirements:
151
- - - ! '>='
260
+ - - '>='
152
261
  - !ruby/object:Gem::Version
153
262
  version: '0'
154
- segments:
155
- - 0
156
- hash: -4461140220613461358
157
263
  required_rubygems_version: !ruby/object:Gem::Requirement
158
- none: false
159
264
  requirements:
160
- - - ! '>='
265
+ - - '>='
161
266
  - !ruby/object:Gem::Version
162
267
  version: '0'
163
- segments:
164
- - 0
165
- hash: -4461140220613461358
166
268
  requirements: []
167
269
  rubyforge_project: artoo
168
- rubygems_version: 1.8.25
270
+ rubygems_version: 2.0.0
169
271
  signing_key:
170
- specification_version: 3
272
+ specification_version: 4
171
273
  summary: Ruby-based microframework for robotics
172
274
  test_files:
173
275
  - test/adaptors/adaptor_test.rb
@@ -185,6 +287,8 @@ test_files:
185
287
  - test/drivers/ardrone_video_test.rb
186
288
  - test/drivers/driver_test.rb
187
289
  - test/drivers/led_test.rb
290
+ - test/drivers/motor_test.rb
291
+ - test/drivers/servo_test.rb
188
292
  - test/drivers/sphero_test.rb
189
293
  - test/drivers/wiichuck_test.rb
190
294
  - test/drivers/wiiclassic_test.rb