artoo 0.4.0 → 0.4.1
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/.travis.yml +1 -1
- data/.yardopts +10 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +10 -7
- data/README.md +2 -2
- data/api/assets/javascripts/artoo/controllers/robot.js.coffee +2 -1
- data/api/public/core.js +3 -1
- data/artoo.gemspec +0 -1
- data/lib/artoo/adaptors/adaptor.rb +27 -6
- data/lib/artoo/adaptors/ardrone.rb +10 -2
- data/lib/artoo/adaptors/ardrone_navigation.rb +9 -2
- data/lib/artoo/adaptors/ardrone_video.rb +13 -5
- data/lib/artoo/adaptors/firmata.rb +10 -2
- data/lib/artoo/adaptors/loopback.rb +2 -1
- data/lib/artoo/adaptors/roomba.rb +12 -4
- data/lib/artoo/adaptors/sphero.rb +15 -3
- data/lib/artoo/api.rb +48 -5
- data/lib/artoo/api_route_helpers.rb +22 -3
- data/lib/artoo/basic.rb +3 -7
- data/lib/artoo/connection.rb +25 -7
- data/lib/artoo/delegator.rb +6 -16
- data/lib/artoo/device.rb +39 -10
- data/lib/artoo/device_event_client.rb +6 -0
- data/lib/artoo/drivers/ardrone.rb +5 -1
- data/lib/artoo/drivers/ardrone_navigation.rb +5 -1
- data/lib/artoo/drivers/ardrone_video.rb +9 -4
- data/lib/artoo/drivers/button.rb +7 -1
- data/lib/artoo/drivers/driver.rb +44 -4
- data/lib/artoo/drivers/led.rb +12 -1
- data/lib/artoo/drivers/motor.rb +12 -1
- data/lib/artoo/drivers/pinger.rb +10 -1
- data/lib/artoo/drivers/pinger2.rb +10 -1
- data/lib/artoo/drivers/roomba.rb +65 -17
- data/lib/artoo/drivers/servo.rb +12 -2
- data/lib/artoo/drivers/sphero.rb +19 -5
- data/lib/artoo/drivers/wiichuck.rb +7 -1
- data/lib/artoo/drivers/wiiclassic.rb +14 -5
- data/lib/artoo/drivers/wiidriver.rb +4 -1
- data/lib/artoo/events.rb +11 -4
- data/lib/artoo/ext/actor.rb +1 -1
- data/lib/artoo/ext/timers.rb +1 -1
- data/lib/artoo/main.rb +2 -13
- data/lib/artoo/master.rb +20 -2
- data/lib/artoo/port.rb +8 -3
- data/lib/artoo/robot.rb +45 -17
- data/lib/artoo/utility.rb +53 -9
- data/lib/artoo/version.rb +1 -1
- data/test/drivers/driver_test.rb +15 -0
- data/test/drivers/led_test.rb +4 -0
- data/test/utility_test.rb +35 -18
- data/test/utility_test_cases.rb +56 -0
- metadata +5 -16
data/lib/artoo/drivers/servo.rb
CHANGED
@@ -4,14 +4,18 @@ module Artoo
|
|
4
4
|
module Drivers
|
5
5
|
# Servo behaviors for Firmata
|
6
6
|
class Servo < Driver
|
7
|
+
COMMANDS = [:move, :min, :center, :max].freeze
|
8
|
+
|
7
9
|
attr_reader :current_angle
|
8
10
|
|
11
|
+
# Create new Servo with angle=0
|
9
12
|
def initialize(params={})
|
10
13
|
super
|
11
14
|
|
12
15
|
@current_angle = 0
|
13
16
|
end
|
14
17
|
|
18
|
+
# Starts connection to read and process and driver
|
15
19
|
def start_driver
|
16
20
|
every(interval) do
|
17
21
|
connection.read_and_process
|
@@ -20,30 +24,36 @@ module Artoo
|
|
20
24
|
super
|
21
25
|
end
|
22
26
|
|
27
|
+
# Moves to specified angle
|
28
|
+
# @param [Integer] angle must be between 0-180
|
23
29
|
def move(angle)
|
24
30
|
raise "Servo angle must be an integer between 0-180" unless (angle.is_a?(Numeric) && angle >= 0 && angle <= 180)
|
25
|
-
|
31
|
+
|
26
32
|
@current_angle = angle
|
27
33
|
connection.set_pin_mode(pin, Firmata::Board::SERVO)
|
28
34
|
connection.analog_write(pin, angle_to_span(angle))
|
29
35
|
end
|
30
36
|
|
37
|
+
# Moves to min position
|
31
38
|
def min
|
32
39
|
move(0)
|
33
40
|
end
|
34
41
|
|
42
|
+
# Moves to center position
|
35
43
|
def center
|
36
44
|
move(90)
|
37
45
|
end
|
38
46
|
|
47
|
+
# Moves to max position
|
39
48
|
def max
|
40
49
|
move(180)
|
41
50
|
end
|
42
51
|
|
43
52
|
# converts an angle to a span between 0-255
|
53
|
+
# @param [Integer] angle
|
44
54
|
def angle_to_span(angle)
|
45
55
|
(angle * 255 / 180).to_i
|
46
56
|
end
|
47
57
|
end
|
48
58
|
end
|
49
|
-
end
|
59
|
+
end
|
data/lib/artoo/drivers/sphero.rb
CHANGED
@@ -4,36 +4,50 @@ module Artoo
|
|
4
4
|
module Drivers
|
5
5
|
# The Sphero driver behaviors
|
6
6
|
class Sphero < Driver
|
7
|
-
RED = [255, 0, 0]
|
8
|
-
GREEN = [0, 255, 0]
|
9
|
-
YELLOW = [255, 255, 0]
|
10
|
-
BLUE = [0, 0, 255]
|
11
|
-
WHITE = [255, 255, 255]
|
12
7
|
|
8
|
+
RED = [255, 0, 0]
|
9
|
+
GREEN = [0, 255, 0]
|
10
|
+
YELLOW = [255, 255, 0]
|
11
|
+
BLUE = [0, 0, 255]
|
12
|
+
WHITE = [255, 255, 255]
|
13
|
+
|
14
|
+
COMMANDS = [:detect_collisions, :clear_collisions, :collisions,
|
15
|
+
:power_notifications, :sensor_data, :set_color, :color].freeze
|
16
|
+
|
17
|
+
# Detects collisions
|
18
|
+
# @param [Hash] params
|
13
19
|
def detect_collisions(params={})
|
14
20
|
connection.configure_collision_detection 0x01, 0x20, 0x20, 0x20, 0x20, 0x50
|
15
21
|
end
|
16
22
|
|
23
|
+
# Clears collisions
|
17
24
|
def clear_collisions
|
18
25
|
messages.clear if responses = messages
|
19
26
|
end
|
20
27
|
|
28
|
+
# @return [CollisionDetected] collision
|
21
29
|
def collisions
|
22
30
|
matching_response_types messages, ::Sphero::Response::CollisionDetected
|
23
31
|
end
|
24
32
|
|
33
|
+
# @return [PowerNotification] power notification
|
25
34
|
def power_notifications
|
26
35
|
matching_response_types messages, ::Sphero::Response::PowerNotification
|
27
36
|
end
|
28
37
|
|
38
|
+
# @return [SensorData] sensor data
|
29
39
|
def sensor_data
|
30
40
|
matching_response_types messages, ::Sphero::Response::SensorData
|
31
41
|
end
|
32
42
|
|
43
|
+
# Set color
|
44
|
+
# @param [Collection] colors
|
33
45
|
def set_color(*colors)
|
34
46
|
connection.rgb(*color(*colors))
|
35
47
|
end
|
36
48
|
|
49
|
+
# Retrieves color
|
50
|
+
# @param [Collection] colors
|
37
51
|
def color(*colors)
|
38
52
|
case colors.first
|
39
53
|
when :red then RED
|
@@ -4,6 +4,9 @@ module Artoo
|
|
4
4
|
module Drivers
|
5
5
|
# Wiichuck driver behaviors for Firmata
|
6
6
|
class Wiichuck < Wiidriver
|
7
|
+
|
8
|
+
# Update button and joystick values
|
9
|
+
# @param [Object] value
|
7
10
|
def update(value)
|
8
11
|
begin
|
9
12
|
super
|
@@ -19,21 +22,24 @@ module Artoo
|
|
19
22
|
end
|
20
23
|
end
|
21
24
|
|
25
|
+
# Adjust x, y origin values
|
22
26
|
def adjust_origins
|
23
27
|
set_joystick_default_value(:sy_origin, data[:sy])
|
24
28
|
set_joystick_default_value(:sx_origin, data[:sx])
|
25
29
|
end
|
26
30
|
|
31
|
+
# Publishes events for c and z buttons
|
27
32
|
def update_buttons
|
28
33
|
publish(event_topic_name("c_button")) if data[:c] == true
|
29
34
|
publish(event_topic_name("z_button")) if data[:z] == true
|
30
35
|
end
|
31
36
|
|
37
|
+
# Publishes event for joystick
|
32
38
|
def update_joystick
|
33
39
|
publish(event_topic_name("joystick"), {:x => calculate_joystick_value(:sx, :sx_origin), :y => calculate_joystick_value(:sy, :sy_origin)})
|
34
40
|
end
|
35
41
|
|
36
|
-
private
|
42
|
+
private
|
37
43
|
|
38
44
|
def get_defaults
|
39
45
|
{
|
@@ -3,11 +3,14 @@ require 'artoo/drivers/wiidriver'
|
|
3
3
|
module Artoo
|
4
4
|
module Drivers
|
5
5
|
# Wiiclassic driver behaviors for Firmata
|
6
|
-
class Wiiclassic < Wiidriver
|
6
|
+
class Wiiclassic < Wiidriver
|
7
|
+
|
8
|
+
# Update buttons and joysticks values
|
9
|
+
# @param [Object] value
|
7
10
|
def update(value)
|
8
11
|
begin
|
9
12
|
super
|
10
|
-
|
13
|
+
|
11
14
|
adjust_origins
|
12
15
|
update_buttons
|
13
16
|
update_left_joystick
|
@@ -21,6 +24,7 @@ module Artoo
|
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
27
|
+
# Adjust all origins
|
24
28
|
def adjust_origins
|
25
29
|
set_joystick_default_value(:ly_origin, data[:ly])
|
26
30
|
set_joystick_default_value(:lx_origin, data[:lx])
|
@@ -30,6 +34,7 @@ module Artoo
|
|
30
34
|
set_joystick_default_value(:lt_origin, data[:lt])
|
31
35
|
end
|
32
36
|
|
37
|
+
# Update button values
|
33
38
|
def update_buttons
|
34
39
|
update_button("a_button", :a)
|
35
40
|
update_button("b_button", :b)
|
@@ -40,25 +45,29 @@ module Artoo
|
|
40
45
|
update_button("select_button", :-)
|
41
46
|
end
|
42
47
|
|
48
|
+
# Publish button event
|
43
49
|
def update_button(name, key)
|
44
50
|
publish(event_topic_name(name)) if data[key] == true
|
45
51
|
end
|
46
52
|
|
53
|
+
# Publish left joystick event
|
47
54
|
def update_left_joystick
|
48
55
|
publish(event_topic_name("left_joystick"), {:x => calculate_joystick_value(:lx, :lx_origin), :y => calculate_joystick_value(:ly, :ly_origin)})
|
49
56
|
end
|
50
57
|
|
58
|
+
# Publish right joystick event
|
51
59
|
def update_right_joystick
|
52
60
|
publish(event_topic_name("right_joystick"), {:x => calculate_joystick_value(:rx, :rx_origin), :y => calculate_joystick_value(:ry, :ry_origin)})
|
53
61
|
end
|
54
62
|
|
63
|
+
# Publish triggers events
|
55
64
|
def update_triggers
|
56
65
|
publish(event_topic_name("right_trigger"), calculate_joystick_value(:rt, :rt_origin))
|
57
66
|
publish(event_topic_name("left_trigger"), calculate_joystick_value(:lt, :lt_origin))
|
58
67
|
end
|
59
68
|
|
60
69
|
private
|
61
|
-
|
70
|
+
|
62
71
|
def get_defaults
|
63
72
|
{
|
64
73
|
:ry_origin => nil,
|
@@ -67,8 +76,8 @@ module Artoo
|
|
67
76
|
:lx_origin => nil,
|
68
77
|
:rt_origin => nil,
|
69
78
|
:lt_origin => nil
|
70
|
-
}
|
71
|
-
end
|
79
|
+
}
|
80
|
+
end
|
72
81
|
|
73
82
|
def parse(value)
|
74
83
|
return parse_joysticks(value).
|
@@ -8,12 +8,14 @@ module Artoo
|
|
8
8
|
|
9
9
|
def address; 0x52; end
|
10
10
|
|
11
|
+
# Create new Wiidriver
|
11
12
|
def initialize(params={})
|
12
13
|
@joystick = get_defaults
|
13
14
|
@data = {}
|
14
15
|
super
|
15
16
|
end
|
16
17
|
|
18
|
+
# Starts drives and required connections
|
17
19
|
def start_driver
|
18
20
|
begin
|
19
21
|
listener = ->(value) { update(value) }
|
@@ -38,6 +40,7 @@ module Artoo
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
43
|
+
# Get and update data
|
41
44
|
def update(value)
|
42
45
|
if encrypted?(value)
|
43
46
|
Logger.error "Encrypted bytes from wii device!"
|
@@ -47,7 +50,7 @@ module Artoo
|
|
47
50
|
@data = parse(value)
|
48
51
|
end
|
49
52
|
|
50
|
-
protected
|
53
|
+
protected
|
51
54
|
|
52
55
|
def get_defaults
|
53
56
|
{}
|
data/lib/artoo/events.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Artoo
|
2
|
+
# Class that handles events
|
2
3
|
module Events
|
4
|
+
|
3
5
|
# Subscribe to an event from a device
|
6
|
+
# @param [Device] device
|
7
|
+
# @param [Hash] events
|
4
8
|
def on(device, events={})
|
5
9
|
events.each do |k, v|
|
6
10
|
subscribe("#{safe_name}_#{device.name}_#{k}", create_proxy_method(k, v))
|
@@ -10,8 +14,10 @@ module Artoo
|
|
10
14
|
# Create an anonymous subscription method so we can wrap the
|
11
15
|
# subscription method fire into a valid method regardless
|
12
16
|
# of where it is defined
|
13
|
-
|
14
|
-
|
17
|
+
# @param [String] base_name
|
18
|
+
# @param [String] v
|
19
|
+
def create_proxy_method(base_name, v)
|
20
|
+
proxy_method_name(base_name).tap do |name|
|
15
21
|
self.class.send :define_method, name do |*args|
|
16
22
|
case v
|
17
23
|
when Symbol
|
@@ -24,9 +30,10 @@ module Artoo
|
|
24
30
|
end
|
25
31
|
|
26
32
|
# A simple loop to create a 'fake' anonymous method
|
27
|
-
|
33
|
+
# @return [Method] created method
|
34
|
+
def proxy_method_name(base_name)
|
28
35
|
begin
|
29
|
-
meth = "#{
|
36
|
+
meth = "#{base_name}_#{Random.rand(999)}"
|
30
37
|
end while respond_to?(meth)
|
31
38
|
meth
|
32
39
|
end
|
data/lib/artoo/ext/actor.rb
CHANGED
data/lib/artoo/ext/timers.rb
CHANGED
data/lib/artoo/main.rb
CHANGED
@@ -6,27 +6,16 @@ module Artoo
|
|
6
6
|
# DSL methods executed on main are delegated to this class like Sinatra
|
7
7
|
class MainRobot < Artoo::Robot
|
8
8
|
|
9
|
-
#
|
9
|
+
# We assume that the first file that requires 'artoo' is the
|
10
10
|
# app_file. all other path related options are calculated based
|
11
11
|
# on this path by default.
|
12
12
|
set :app_file, caller_files.first || $0
|
13
13
|
set :start_work, Proc.new { File.expand_path($0) == File.expand_path(app_file) }
|
14
|
-
|
15
|
-
# if run? && ARGV.any?
|
16
|
-
# require 'optparse'
|
17
|
-
# OptionParser.new { |op|
|
18
|
-
# op.on('-p port', 'set the port (default is 4567)') { |val| set :port, Integer(val) }
|
19
|
-
# op.on('-o addr', 'set the host (default is 0.0.0.0)') { |val| set :bind, val }
|
20
|
-
# op.on('-e env', 'set the environment (default is development)') { |val| set :environment, val.to_sym }
|
21
|
-
# op.on('-s server', 'specify rack server/handler (default is thin)') { |val| set :server, val }
|
22
|
-
# op.on('-x', 'turn on the mutex lock (default is off)') { set :lock, true }
|
23
|
-
# }.parse!(ARGV.dup)
|
24
|
-
# end
|
25
14
|
end
|
26
15
|
|
27
16
|
at_exit { MainRobot.work! if $!.nil? && MainRobot.start_work? }
|
28
17
|
end
|
29
18
|
|
30
|
-
# include would include the module in Object
|
19
|
+
# include would include the module in Object,
|
31
20
|
# extend only extends the `main` object
|
32
21
|
extend Artoo::Delegator
|
data/lib/artoo/master.rb
CHANGED
@@ -3,36 +3,52 @@ module Artoo
|
|
3
3
|
# of all the running robots
|
4
4
|
class Master
|
5
5
|
include Celluloid
|
6
|
-
|
6
|
+
attr_reader :robots
|
7
7
|
|
8
|
+
# Create new master
|
9
|
+
# @param [Collection] robots
|
8
10
|
def initialize(bots)
|
9
11
|
@robots = bots
|
10
12
|
end
|
11
13
|
|
14
|
+
# @param [String] name
|
15
|
+
# @return [Robot] robot
|
12
16
|
def robot(name)
|
13
17
|
robots.find {|r| r.name == name}
|
14
18
|
end
|
15
19
|
|
20
|
+
# @param [String] name
|
21
|
+
# @return [Collection] robot devices
|
16
22
|
def robot_devices(name)
|
17
23
|
robot(name).devices
|
18
24
|
end
|
19
25
|
|
26
|
+
# @param [String] name
|
27
|
+
# @param [String] device_id
|
28
|
+
# @return [Device] robot device
|
20
29
|
def robot_device(name, device_id)
|
21
30
|
robot_devices(name)[device_id.intern]
|
22
31
|
end
|
23
32
|
|
33
|
+
# @param [String] name
|
34
|
+
# @return [Collection] robot connections
|
24
35
|
def robot_connections(name)
|
25
36
|
robot(name).connections
|
26
37
|
end
|
27
38
|
|
39
|
+
# @param [String] robot_id
|
40
|
+
# @param [String] connection_id
|
41
|
+
# @return [Device] robot connection
|
28
42
|
def robot_connection(robot_id, connection_id)
|
29
43
|
robot_connections(robot_id)[connection_id.intern]
|
30
44
|
end
|
31
45
|
|
46
|
+
# Do asynchronous work for each robot
|
32
47
|
def start_work
|
33
48
|
robots.each {|r| r.async.work} unless Artoo::Robot.is_running?
|
34
49
|
end
|
35
50
|
|
51
|
+
# Pause work for each robot
|
36
52
|
def pause_work
|
37
53
|
robots.each {|r|
|
38
54
|
Logger.info "pausing #{r.name}"
|
@@ -40,12 +56,14 @@ module Artoo
|
|
40
56
|
}
|
41
57
|
end
|
42
58
|
|
59
|
+
# Continue work for each robot
|
43
60
|
def continue_work
|
44
61
|
robots.each {|r| r.async.continue_work}
|
45
62
|
end
|
46
63
|
|
64
|
+
# @deprecated
|
47
65
|
def stop_work
|
48
66
|
#robots.each {|r| r.async.stop_work} unless !Artoo::Robot.is_running?
|
49
67
|
end
|
50
68
|
end
|
51
|
-
end
|
69
|
+
end
|
data/lib/artoo/port.rb
CHANGED
@@ -1,28 +1,33 @@
|
|
1
1
|
module Artoo
|
2
|
-
# The Artoo::Port class represents port and/or host to be used to connect
|
2
|
+
# The Artoo::Port class represents port and/or host to be used to connect
|
3
3
|
# tp a specific individual hardware device.
|
4
4
|
class Port
|
5
5
|
attr_reader :port, :host
|
6
6
|
|
7
|
+
# Create new port
|
8
|
+
# @param [Object] data
|
7
9
|
def initialize(data)
|
8
10
|
@is_tcp, @is_serial = false
|
9
11
|
parse(data)
|
10
12
|
end
|
11
13
|
|
14
|
+
# @return [Boolean] True if serial port
|
12
15
|
def is_serial?
|
13
16
|
@is_serial == true
|
14
17
|
end
|
15
18
|
|
19
|
+
# @return [Boolean] True if tcp port
|
16
20
|
def is_tcp?
|
17
21
|
@is_tcp == true
|
18
22
|
end
|
19
23
|
|
24
|
+
# @return [String] port
|
20
25
|
def to_s
|
21
26
|
if is_serial?
|
22
27
|
port
|
23
28
|
else
|
24
29
|
"#{host}:#{port}"
|
25
|
-
end
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
private
|
@@ -48,4 +53,4 @@ module Artoo
|
|
48
53
|
end
|
49
54
|
end
|
50
55
|
end
|
51
|
-
end
|
56
|
+
end
|