artoo 0.1.3 → 0.2.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ed97e1d66baccca21165b0960b2ed18212b2a1d4
4
+ data.tar.gz: 77e070f5faa53a75532d5c73f87c2016d9e0f23a
5
+ SHA512:
6
+ metadata.gz: 6566a8f925b396b38e0641e64548f42787d0611852733077697efad840b972281cc0ac8d218801476593a590c52287802a6bdd8bb25758c19430eaa4c20c4e67
7
+ data.tar.gz: 4107fcfa598cc71a9d3a5e11f26b1885336e0b5c64ae264fc13150162db6fe4055d54db3984007c46886a3c74306c92fc3dadb66392d1b41b820888b34662af0
data/.gitignore CHANGED
@@ -23,3 +23,6 @@ doc/
23
23
 
24
24
  # Sass
25
25
  .sass-cache
26
+
27
+ # rubinius
28
+ .rbx
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-19mode
data/Gemfile CHANGED
@@ -3,29 +3,18 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in artoo.gemspec
4
4
  gemspec
5
5
 
6
- gem 'rake'
7
- gem 'celluloid-io'
8
- gem 'reel'
9
- gem 'active_support'
10
- gem 'multi_json'
6
+ # these are for specific hardware, they have to be here for tests
7
+ gem 'hybridgroup-firmata'
8
+ gem 'hybridgroup-sphero'
9
+ gem 'hybridgroup-argus'
11
10
 
12
- group :development, :test do
13
- gem 'minitest'
14
- gem 'mocha'
15
-
16
- # these are for specific hardware, they have to be here for tests
17
- gem 'hybridgroup-firmata'
18
- gem 'hybridgroup-sphero'
19
- gem 'hybridgroup-argus'
20
-
21
- # For Front-End
22
- gem 'sass'
23
- gem 'coffee-script'
24
- gem 'sprockets'
25
- gem 'compass'
26
- gem 'bootstrap-sass'
27
- gem 'guard'
28
- gem 'guard-livereload'
29
- gem 'guard-sprockets'
30
- gem 'guard-compass'
31
- end
11
+ # For the front end web application
12
+ gem 'sass'
13
+ gem 'coffee-script'
14
+ gem 'sprockets'
15
+ gem 'compass'
16
+ gem 'bootstrap-sass'
17
+ gem 'guard'
18
+ gem 'guard-livereload'
19
+ gem 'guard-sprockets'
20
+ gem 'guard-compass'
data/Gemfile.lock CHANGED
@@ -1,7 +1,12 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- artoo (0.1.3)
4
+ artoo (0.2.0)
5
+ active_support (~> 3.0)
6
+ celluloid-io (~> 0.12)
7
+ multi_json (~> 1.6)
8
+ rake (~> 10.0)
9
+ reel (~> 0.3)
5
10
 
6
11
  GEM
7
12
  remote: http://rubygems.org/
@@ -69,12 +74,11 @@ GEM
69
74
  lumberjack (1.0.2)
70
75
  metaclass (0.0.1)
71
76
  method_source (0.8.1)
72
- minitest (4.5.0)
77
+ minitest (4.6.2)
73
78
  mocha (0.13.2)
74
79
  metaclass (~> 0.0.1)
75
80
  multi_json (1.6.1)
76
81
  nio4r (0.4.3)
77
- nio4r (0.4.3-java)
78
82
  pry (0.9.12)
79
83
  coderay (~> 1.0.5)
80
84
  method_source (~> 0.8)
@@ -112,10 +116,8 @@ PLATFORMS
112
116
  ruby
113
117
 
114
118
  DEPENDENCIES
115
- active_support
116
119
  artoo!
117
120
  bootstrap-sass
118
- celluloid-io
119
121
  coffee-script
120
122
  compass
121
123
  guard
@@ -125,10 +127,7 @@ DEPENDENCIES
125
127
  hybridgroup-argus
126
128
  hybridgroup-firmata
127
129
  hybridgroup-sphero
128
- minitest
129
- mocha
130
- multi_json
131
- rake
132
- reel
130
+ minitest (~> 4.6)
131
+ mocha (~> 0.13)
133
132
  sass
134
133
  sprockets
data/README.md CHANGED
@@ -6,7 +6,7 @@ Artoo is a micro-framework for robotics using Ruby.
6
6
 
7
7
  Artoo provides a simple, yet powerful domain-specific language (DSL) for robotics and physical computing.
8
8
 
9
- [![Code Climate](https://codeclimate.com/github/hybridgroup/artoo.png)](https://codeclimate.com/github/hybridgroup/artoo)
9
+ [![Code Climate](https://codeclimate.com/github/hybridgroup/artoo.png)](https://codeclimate.com/github/hybridgroup/artoo) [![Build Status](https://travis-ci.org/hybridgroup/artoo.png?branch=master)](https://travis-ci.org/hybridgroup/artoo)
10
10
 
11
11
  ## Examples:
12
12
 
@@ -71,9 +71,14 @@ SPHEROS.each {|p|
71
71
  SpheroRobot.work!(robots)
72
72
  ```
73
73
 
74
+ Ruby versions supported: Ruby 2.0, 1.9.3, JRuby 1.7.2, and Rubinius 2.0
75
+
76
+
74
77
  Artoo is conceptualy influenced by Sinatra (https://github.com/sinatra/sinatra) as well as borrowing some code from it.
75
78
 
76
- Artoo provides a robust actor-based messaging architecture, that can support fully multi-threaded operation and high-concurrency, as long as it is supported by the Ruby version in which it is executing. To a large extent, this is due to being built on top of Celluloid (https://github.com/celluloid/celluloid) and Celluloid::IO (https://github.com/celluloid/celluloid-io).
79
+ Artoo provides a robust actor-based messaging architecture, that can support fully multi-threaded operation and high-concurrency, as long as it is supported by the Ruby version in which it is executing. This means you will need to use JRuby or Rubinius for maximum concurrency.
80
+
81
+ To a large extent, this is due to being built on top of Celluloid (https://github.com/celluloid/celluloid), Celluloid::IO (https://github.com/celluloid/celluloid-io), and Reel (https://github.com/celluloid/reel).
77
82
 
78
83
  ## API:
79
84
 
data/artoo.gemspec CHANGED
@@ -18,4 +18,12 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
+
22
+ s.add_runtime_dependency 'celluloid-io', '~> 0.12'
23
+ s.add_runtime_dependency 'reel', '~> 0.3'
24
+ s.add_runtime_dependency 'multi_json', '~> 1.6'
25
+ s.add_runtime_dependency 'active_support', '~> 3.0'
26
+ s.add_runtime_dependency 'rake', '~> 10.0'
27
+ s.add_development_dependency 'minitest', '~> 4.6'
28
+ s.add_development_dependency 'mocha', '~> 0.13'
21
29
  end
data/examples/ardrone.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'artoo'
2
2
 
3
- connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.43:5556'
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
4
  device :drone, :driver => :ardrone, :connection => :ardrone
5
5
 
6
6
  work do
@@ -9,4 +9,4 @@ work do
9
9
 
10
10
  after(25.seconds) { drone.hover.land }
11
11
  after(30.seconds) { drone.stop }
12
- end
12
+ end
@@ -1,9 +1,9 @@
1
1
  require 'artoo'
2
2
 
3
- connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.43:5556'
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
4
  device :drone, :driver => :ardrone, :connection => :ardrone
5
5
 
6
- connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.43:5554'
6
+ connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.1:5554'
7
7
  device :nav, :driver => :ardrone_navigation, :connection => :navigation
8
8
 
9
9
  work do
@@ -19,4 +19,4 @@ def nav_update(*data)
19
19
  data[1].drone_state.each do |name, val|
20
20
  p "#{name}: #{val}"
21
21
  end
22
- end
22
+ end
@@ -1,12 +1,12 @@
1
1
  require 'artoo'
2
2
 
3
- connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.43:5556'
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
4
  device :drone, :driver => :ardrone, :connection => :ardrone
5
5
 
6
- connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.43:5554'
6
+ connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.1:5554'
7
7
  device :nav, :driver => :ardrone_navigation, :connection => :navigation
8
8
 
9
- connection :videodrone, :adaptor => :ardrone_video, :port => '192.168.1.43:5555'
9
+ connection :videodrone, :adaptor => :ardrone_video, :port => '192.168.1.1:5555'
10
10
  device :video, :driver => :ardrone_video, :connection => :videodrone
11
11
 
12
12
  connection :arduino, :adaptor => :firmata, :port => "8023"
@@ -1,9 +1,9 @@
1
1
  require 'artoo'
2
2
 
3
- connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.43:5556'
3
+ connection :ardrone, :adaptor => :ardrone, :port => '192.168.1.1:5556'
4
4
  device :drone, :driver => :ardrone, :connection => :ardrone
5
5
 
6
- connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.43:5554'
6
+ connection :navigation, :adaptor => :ardrone_navigation, :port => '192.168.1.1:5554'
7
7
  device :nav, :driver => :ardrone_navigation, :connection => :navigation
8
8
 
9
9
  connection :arduino, :adaptor => :firmata, :port => "8023"
@@ -24,25 +24,66 @@ work do
24
24
  on classic, :home_button => proc { drone.emergency }
25
25
  on classic, :start_button => proc { drone.start }
26
26
  on classic, :select_button => proc { drone.stop }
27
- on classic, :ry_up => proc { drone.up(@altitude_pitch) }
28
- on classic, :ry_down => proc { drone.down(@altitude_pitch) }
29
- on classic, :ly_up => proc { drone.forward(@fly_pitch) }
30
- on classic, :ly_down => proc { drone.backward(@fly_pitch) }
31
- on classic, :lx_right => proc { drone.right(@fly_pitch) }
32
- on classic, :lx_left => proc { drone.left(@fly_pitch) }
33
- on classic, :reset_pitch_roll => proc {
34
- drone.left(0.0)
35
- drone.forward(0.0)
27
+
28
+ on classic, :left_joystick => proc { |*value|
29
+ pair = value[1]
30
+ if pair[:y] > 0
31
+ drone.forward(validate_pitch(pair[:y], @offsets[:ly]))
32
+ elsif pair[:y] < 0
33
+ drone.backward(validate_pitch(pair[:y], @offsets[:ly]))
34
+ else
35
+ drone.forward(0.0)
36
+ end
37
+
38
+ if pair[:x] > 0
39
+ drone.right(validate_pitch(pair[:x], @offsets[:lx]))
40
+ elsif pair[:x] < 0
41
+ drone.left(validate_pitch(pair[:x], @offsets[:lx]))
42
+ else
43
+ drone.right(0.0)
44
+ end
45
+ }
46
+
47
+ on classic, :right_joystick => proc { |*value|
48
+ pair = value[1]
49
+ if pair[:y] > 0
50
+ drone.up(validate_pitch(pair[:y], @offsets[:ry]))
51
+ elsif pair[:y] < 0
52
+ drone.down(validate_pitch(pair[:y], @offsets[:ry]))
53
+ else
54
+ drone.up(0.0)
55
+ end
56
+ }
57
+
58
+ on classic, :right_trigger => proc { |*value|
59
+ if value[1] > 0
60
+ drone.turn_right(validate_pitch(value[1], @offsets[:rt]))
61
+ else
62
+ drone.turn_right(0.0)
63
+ end
64
+ }
65
+
66
+ on classic, :left_trigger => proc { |*value|
67
+ if value[1] > 0
68
+ drone.turn_left(validate_pitch(value[1], @offsets[:lt]))
69
+ else
70
+ drone.turn_left(0.0)
71
+ end
36
72
  }
37
- on classic, :rotate_left => proc { drone.turn_left(@rotate_pitch) }
38
- on classic, :rotate_right => proc { drone.turn_right(@rotate_pitch) }
39
- on classic, :reset_rotate => proc { drone.turn_left(0.0) }
40
- on classic, :reset_altitude => proc { drone.up(0.0) }
41
73
  end
42
74
 
43
75
  def init_settings
44
- @rotate_pitch = 0.5
45
- @fly_pitch = 0.7
46
- @altitude_pitch = 1
47
76
  @toggle_camera = 0
77
+ @offsets = {
78
+ :ry => 12.0,
79
+ :ly => 27.0,
80
+ :lx => 27.0,
81
+ :rt => 27.0,
82
+ :lt => 12.0
83
+ }
84
+ end
85
+
86
+ def validate_pitch(data, offset)
87
+ value = data.abs / offset
88
+ value >= 0.1 ? (value <= 1.0 ? value.round(2) : 1.0) : 0.0
48
89
  end
@@ -0,0 +1,18 @@
1
+ begin
2
+ require 'artoo'
3
+ rescue LoadError
4
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__),'..', 'lib')))
5
+ require "artoo"
6
+ end
7
+
8
+ connection :roomba, :adaptor => :roomba, :port => '/dev/tty.usbserial-A2001yzl'
9
+ device :roomba, :driver => :roomba, :connection => :roomba
10
+
11
+ work do
12
+ roomba.safe_mode
13
+ roomba.nudge_left
14
+ roomba.nudge_right
15
+ roomba.nudge_right
16
+ roomba.nudge_left
17
+ roomba.sing_jingle_bells
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'artoo'
2
+
3
+ connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4560'
4
+ device :sphero, :driver => :sphero
5
+
6
+ connection :arduino, :adaptor => :firmata, :port => "8023"
7
+ device :wiichuck, :driver => :wiichuck, :connection => :arduino, :interval => 0.1
8
+
9
+ work do
10
+ init_settings
11
+ on wiichuck, :c_button => proc {}
12
+ on wiichuck, :z_button => proc {}
13
+ on wiichuck, :joystick => proc { |*value|
14
+ @heading = heading(value[1])
15
+ }
16
+ every(1.seconds) do
17
+ puts "Rolling..."
18
+ sphero.roll 20, @heading
19
+ end
20
+ end
21
+
22
+ def init_settings
23
+ @heading = 0
24
+ end
25
+
26
+ def heading(value)
27
+ (180.0 - (Math.atan2(value[:y],value[:x]) * (180.0 / Math::PI))).round
28
+ end
@@ -0,0 +1,12 @@
1
+ require 'artoo'
2
+
3
+ connection :arduino, :adaptor => :firmata, :port => "8023"
4
+ device :wiichuck, :driver => :wiichuck, :connection => :arduino, :interval => 0.1
5
+
6
+ work do
7
+ on wiichuck, :c_button => proc { puts "c button pressed!" }
8
+ on wiichuck, :z_button => proc { puts "z button pressed!" }
9
+ on wiichuck, :joystick => proc { |*value|
10
+ puts "joystick x: #{value[1][:x]}, y: #{value[1][:y]}"
11
+ }
12
+ end
@@ -49,6 +49,13 @@ module Artoo
49
49
  def connect_to_udp
50
50
  @udp_socket ||= UDPSocket.new
51
51
  end
52
+
53
+ def connect_to_serial(speed=57600, data_bits=8, stop_bits=1, parity=SerialPort::NONE)
54
+ require 'serialport'
55
+ @sp = SerialPort.new(port.port, speed, data_bits, stop_bits, parity)
56
+ rescue LoadError
57
+ Logger.error "Please 'gem install hybridgroup-serialport' for serial port support."
58
+ end
52
59
  end
53
60
  end
54
61
  end
@@ -0,0 +1,43 @@
1
+ require 'artoo/adaptors/adaptor'
2
+
3
+ module Artoo
4
+ module Adaptors
5
+ # Connect to a Roomba (http://www.irobot.com/en/us/robots/Educators/Create.aspx)
6
+ class Roomba < Adaptor
7
+
8
+ attr_reader :sp
9
+
10
+ def finalize
11
+ if connected?
12
+ @sp.close
13
+ end
14
+ end
15
+
16
+ def connect
17
+ if port.is_serial?
18
+ @sp = connect_to_serial
19
+ @sp.dtr = 0
20
+ @sp.rts = 0
21
+ else
22
+ @sp = connect_to_tcp
23
+ end
24
+ super
25
+ end
26
+
27
+ def send_bytes(bytes)
28
+ bytes = [bytes] unless bytes.respond_to?(:map)
29
+ bytes.map!(&:chr)
30
+ Logger.debug "sending: #{bytes.inspect}"
31
+ res = []
32
+ bytes.each{|b| res << @sp.write(b) }
33
+ Logger.debug "returned: #{res.inspect}"
34
+ end
35
+
36
+ def disconnect
37
+ @sp.close
38
+ super
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,79 @@
1
+
2
+ module Artoo
3
+ module Basic
4
+ # Taken from Sinatra codebase
5
+ # Sets an option to the given value. If the value is a proc,
6
+ # the proc will be called every time the option is accessed.
7
+ def set(option, value = (not_set = true), ignore_setter = false, &block)
8
+ raise ArgumentError if block and !not_set
9
+ value, not_set = block, false if block
10
+
11
+ if not_set
12
+ raise ArgumentError unless option.respond_to?(:each)
13
+ option.each { |k,v| set(k, v) }
14
+ return self
15
+ end
16
+
17
+ if respond_to?("#{option}=") and not ignore_setter
18
+ return __send__("#{option}=", value)
19
+ end
20
+
21
+ setter = proc { |val| set option, val, true }
22
+ getter = proc { value }
23
+
24
+ case value
25
+ when Proc
26
+ getter = value
27
+ when Symbol, Fixnum, FalseClass, TrueClass, NilClass
28
+ getter = value.inspect
29
+ when Hash
30
+ setter = proc do |val|
31
+ val = value.merge val if Hash === val
32
+ set option, val, true
33
+ end
34
+ end
35
+
36
+ define_singleton_method("#{option}=", setter) if setter
37
+ define_singleton_method(option, getter) if getter
38
+ define_singleton_method("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
39
+ self
40
+ end
41
+
42
+ # Taken from Sinatra codebase
43
+ CALLERS_TO_IGNORE = [ # :nodoc:
44
+ /lib\/artoo.*\.rb$/, # artoo code
45
+ /^\(.*\)$/, # generated code
46
+ /rubygems\/(custom|core_ext\/kernel)_require\.rb$/, # rubygems require hacks
47
+ /active_support/, # active_support require hacks
48
+ /bundler(\/runtime)?\.rb/, # bundler require hacks
49
+ /<internal:/, # internal in ruby >= 1.9.2
50
+ /src\/kernel\/bootstrap\/[A-Z]/ # maglev kernel files
51
+ ]
52
+
53
+ # Taken from Sinatra codebase
54
+ # Like Kernel#caller but excluding certain magic entries and without
55
+ # line / method information; the resulting array contains filenames only.
56
+ def caller_files
57
+ cleaned_caller(1).flatten
58
+ end
59
+
60
+ private
61
+
62
+ # Taken from Sinatra codebase
63
+ def define_singleton_method(name, content = Proc.new)
64
+ # replace with call to singleton_class once we're 1.9 only
65
+ (class << self; self; end).class_eval do
66
+ undef_method(name) if method_defined? name
67
+ String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
68
+ end
69
+ end
70
+
71
+ # Taken from Sinatra codebase
72
+ # Like Kernel#caller but excluding certain magic entries
73
+ def cleaned_caller(keep = 3)
74
+ caller(1).
75
+ map { |line| line.split(/:(?=\d|in )/, 3)[0,keep] }.
76
+ reject { |file, *_| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
77
+ end
78
+ end
79
+ end