├── .ruby-version ├── .ruby-gemset ├── .gitignore ├── .rvmrc.example ├── lib ├── artoo-sphero │ └── version.rb ├── artoo-sphero.rb └── artoo │ ├── interfaces │ └── sphero.rb │ ├── adaptors │ └── sphero.rb │ └── drivers │ └── sphero.rb ├── Gemfile ├── .travis.yml ├── Rakefile ├── test ├── test_helper.rb ├── adaptors │ └── sphero_test.rb ├── interfaces │ └── sphero_test.rb └── drivers │ └── sphero_test.rb ├── examples ├── sphero_color.rb ├── sphero.rb ├── sphero_cycle.rb ├── sphero_messages.rb ├── sphero_interface.rb ├── sphero2.rb ├── sphero_pebble_accelerometer.rb ├── sphero_pebble.rb └── sphero_multiple.rb ├── LICENSE ├── docs ├── events.md └── commands.md ├── artoo-sphero.gemspec └── README.md /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-2.1.0 -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | artoo-sphero 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .rvmrc 2 | .rbx 3 | pkg 4 | Gemfile.lock 5 | -------------------------------------------------------------------------------- /.rvmrc.example: -------------------------------------------------------------------------------- 1 | rvm use rbx-2.0.0-rc1@artoo-sphero --create 2 | -------------------------------------------------------------------------------- /lib/artoo-sphero/version.rb: -------------------------------------------------------------------------------- 1 | module Artoo 2 | module Sphero 3 | VERSION = '1.5.1' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in artoo-sphero.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /lib/artoo-sphero.rb: -------------------------------------------------------------------------------- 1 | require 'lib/artoo/adaptors/sphero' 2 | require 'lib/artoo/drivers/sphero' 3 | require 'lib/artoo/interfaces/sphero' 4 | require 'lib/artoo-sphero/version' 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | - 2.1.0 5 | - 1.9.3 6 | - jruby 7 | - rbx-2.2.10 8 | script: 9 | - bundle install 10 | - bundle exec rake test -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rake/testtask' 5 | 6 | Rake::TestTask.new do |t| 7 | t.pattern = "test/**/*_test.rb" 8 | end 9 | 10 | task :default => :test 11 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/robot' 2 | 3 | require 'minitest' 4 | require 'minitest/autorun' 5 | require 'mocha/setup' 6 | 7 | Celluloid.logger = nil 8 | 9 | MiniTest::Spec.before do 10 | Celluloid.shutdown 11 | Celluloid.boot 12 | end 13 | -------------------------------------------------------------------------------- /examples/sphero_color.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | #connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4567' 5 | device :sphero, :driver => :sphero 6 | 7 | work do 8 | @count = 1 9 | every(3.seconds) do 10 | sphero.set_color(@count % 2 == 0 ? :green : :blue) 11 | @count += 1 12 | sphero.roll 60, rand(360) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /examples/sphero.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | device :sphero, :driver => :sphero 5 | 6 | work do 7 | @rolling = false 8 | 9 | every(3.seconds) do 10 | puts "Rolling..." 11 | unless @rolling 12 | sphero.roll 90, rand(360) 13 | @rolling = true 14 | else 15 | sphero.stop 16 | @rolling = false 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /examples/sphero_cycle.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4560' 4 | device :sphero, :driver => :sphero 5 | 6 | work do 7 | sphero.set_color(0, 0, 0) 8 | sphero.set_color(:red) 9 | sphero.set_color(:yellow) 10 | sphero.set_color(:green) 11 | sphero.set_color(0, 255, 255) 12 | sphero.set_color(:blue) 13 | sphero.set_color(255, 0, 255) 14 | sphero.set_color(:white) 15 | end 16 | -------------------------------------------------------------------------------- /examples/sphero_messages.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | #connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4567' 5 | device :sphero, :driver => :sphero 6 | 7 | def contact(*args) 8 | @contacts ||= 0 9 | @contacts += 1 10 | puts "Contact #{@contacts}" 11 | end 12 | 13 | work do 14 | on sphero, :collision => :contact 15 | 16 | every(3.seconds) do 17 | puts "Rolling..." 18 | sphero.roll 90, rand(360) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /examples/sphero_interface.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | device :sphero, :driver => :sphero 5 | 6 | work do 7 | @rolling = false 8 | 9 | every(3.seconds) do 10 | puts "Rolling..." 11 | unless @rolling 12 | # same as interfaces[:rover].forward(90) 13 | forward(90) 14 | @rolling = true 15 | else 16 | # same as interfaces[:rover].backward(90) 17 | backward(90) 18 | @rolling = false 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, 2013 The Hybrid Group 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /docs/events.md: -------------------------------------------------------------------------------- 1 | # Events 2 | 3 | ## start_driver 4 | 5 | Starts the driver. 6 | 7 | ## handle_collision_detected(data) 8 | 9 | Gets triggered when the Sphero has data to send to the user, related to "collision". 10 | 11 | ##### Data 12 | 13 | - **data**- The returned data 14 | 15 | ## handle_power_notification(data) 16 | 17 | Gets triggered when the Sphero has data to send to the user, related to "power". 18 | 19 | ##### Data 20 | 21 | - **data**- The returned data 22 | 23 | ## handle_sensor_data(data) 24 | 25 | Gets triggered when the Sphero has data to send to the user, related to "sensor". 26 | 27 | ##### Data 28 | 29 | - **data**- The returned data -------------------------------------------------------------------------------- /test/adaptors/sphero_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + "/../test_helper") 2 | require 'artoo/adaptors/sphero' 3 | require 'sphero' 4 | 5 | describe Artoo::Adaptors::Sphero do 6 | before do 7 | @port = Artoo::Port.new('/dev/awesome') 8 | @adaptor = Artoo::Adaptors::Sphero.new(:port => @port) 9 | @sphero = mock('sphero') 10 | Sphero.stubs(:new).returns(@sphero) 11 | end 12 | 13 | it 'Artoo::Adaptors::Sphero#connect' do 14 | @adaptor.connect.must_equal true 15 | end 16 | 17 | it 'Artoo::Adaptors::Sphero#disconnect' do 18 | @adaptor.connect 19 | 20 | @sphero.expects(:close) 21 | @adaptor.disconnect 22 | @adaptor.connected?.must_equal false 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/artoo/interfaces/sphero.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/interfaces/interface' 2 | 3 | module Artoo 4 | module Interfaces 5 | # The Sphero Rover interface 6 | class Sphero < Rover 7 | def forward(speed) 8 | @device.roll 0, speed 9 | end 10 | 11 | def backward(speed) 12 | @device.roll 180, speed 13 | end 14 | 15 | def left(speed) 16 | @device.roll 270, speed 17 | end 18 | 19 | def right(speed) 20 | @device.roll 90, speed 21 | end 22 | 23 | def turn_left(degrees) 24 | # TODO: implement 25 | end 26 | 27 | def turn_right(degrees) 28 | # TODO: implement 29 | end 30 | 31 | def stop 32 | @device.stop 33 | end 34 | end 35 | end 36 | end -------------------------------------------------------------------------------- /examples/sphero2.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/robot' 2 | 3 | class DoubleSpheroRobot < Artoo::Robot 4 | connection :sphero, :adaptor => :sphero 5 | device :sphero, :driver => :sphero 6 | 7 | work do 8 | @count = 1 9 | every(3.seconds) do 10 | sphero.set_color(@count % 2 == 0 ? :green : :blue) 11 | @count += 1 12 | sphero.roll 90, rand(360) 13 | end 14 | end 15 | end 16 | 17 | SPHEROS = {"127.0.0.1:4560" => "/dev/tty.Sphero-BRG-RN-SPP", 18 | "127.0.0.1:4561" => "/dev/tty.Sphero-YBW-RN-SPP"} 19 | robots = [] 20 | SPHEROS.each_key {|p| 21 | robots << DoubleSpheroRobot.new(:connections => 22 | {:sphero => 23 | {:port => p}}) 24 | } 25 | 26 | DoubleSpheroRobot.work!(robots) 27 | -------------------------------------------------------------------------------- /examples/sphero_pebble_accelerometer.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | #connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4567' 5 | device :sphero, :driver => :sphero 6 | 7 | connection :pebble, :adaptor => :pebble 8 | device :watch, :driver => :pebble, :name => 'pebble' 9 | 10 | api :host => '0.0.0.0', :port => '8080' 11 | 12 | name 'pebble' 13 | 14 | work do 15 | on pebble, :accel => :set_direction 16 | 17 | every(1.seconds) do 18 | sphero.roll 100, heading 19 | end 20 | end 21 | 22 | def set_direction(*data) 23 | x, y = data[1].split(",") 24 | 25 | @heading = direction(x.to_i, y.to_i) 26 | end 27 | 28 | def direction(x, y) 29 | (180.0 - (Math.atan2(y,x) * (180.0 / Math::PI))) 30 | end 31 | 32 | def heading 33 | @heading || 0 34 | end 35 | -------------------------------------------------------------------------------- /examples/sphero_pebble.rb: -------------------------------------------------------------------------------- 1 | require 'artoo' 2 | 3 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 4 | #connection :sphero, :adaptor => :sphero, :port => '127.0.0.1:4567' 5 | device :sphero, :driver => :sphero 6 | 7 | connection :pebble, :adaptor => :pebble 8 | device :watch, :driver => :pebble, :name => 'pebble' 9 | 10 | api :host => '0.0.0.0', :port => '8080' 11 | 12 | name 'pebble' 13 | 14 | def move_forward 15 | p 'moving forward' 16 | sphero.roll 100, 0 17 | sleep 4 18 | sphero.stop 19 | end 20 | 21 | def move_backward 22 | p 'moving backward' 23 | sphero.roll 100, 180 24 | sleep 4 25 | sphero.stop 26 | end 27 | 28 | def button_push(*data) 29 | unless data[1].nil? 30 | case data[1] 31 | when 'up' then 32 | move_forward 33 | when 'select' then 34 | sphero.set_color(rand(255),rand(255),rand(255)) 35 | when 'down' then 36 | move_backward 37 | end 38 | end 39 | end 40 | 41 | work do 42 | on pebble, :button => :button_push 43 | end 44 | -------------------------------------------------------------------------------- /test/interfaces/sphero_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + "/../test_helper") 2 | require 'artoo/interfaces/sphero' 3 | 4 | describe Artoo::Interfaces::Sphero do 5 | before do 6 | @device = mock('device') 7 | @interface = Artoo::Interfaces::Sphero.new(:device => @device) 8 | end 9 | 10 | describe "Rover interface" do 11 | it 'Rover#forward' do 12 | @device.expects(:roll).with(0, 30) 13 | @interface.forward 30 14 | end 15 | 16 | it 'Rover#backward' do 17 | @device.expects(:roll).with(180, 30) 18 | @interface.backward 30 19 | end 20 | 21 | it 'Rover#right' do 22 | @device.expects(:roll).with(90, 30) 23 | @interface.right 30 24 | end 25 | 26 | it 'Rover#left' do 27 | @device.expects(:roll).with(270, 30) 28 | @interface.left 30 29 | end 30 | 31 | it 'Rover#turn_right' 32 | it 'Rover#turn_left' 33 | it 'Rover#stop' do 34 | @device.expects(:stop) 35 | @interface.stop 36 | end 37 | 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /examples/sphero_multiple.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/robot' 2 | 3 | class SpheroRobot < Artoo::Robot 4 | connection :sphero, :adaptor => :sphero 5 | device :sphero, :driver => :sphero 6 | 7 | #api :host => '127.0.0.1', :port => '8080' 8 | 9 | work do 10 | @count = 1 11 | 12 | every(3.seconds) do 13 | sphero.set_color(@count % 2 == 0 ? :white : :blue) 14 | @count += 1 15 | sphero.roll 90, rand(360) 16 | end 17 | end 18 | end 19 | 20 | SPHEROS = {"127.0.0.1:4560" => "/dev/tty.Sphero-BRG-RN-SPP", 21 | "127.0.0.1:4561" => "/dev/tty.Sphero-YBW-RN-SPP", 22 | "127.0.0.1:4562" => "/dev/tty.Sphero-BWY-RN-SPP", 23 | "127.0.0.1:4563" => "/dev/tty.Sphero-YRR-RN-SPP", 24 | "127.0.0.1:4564" => "/dev/tty.Sphero-OBG-RN-SPP", 25 | "127.0.0.1:4565" => "/dev/tty.Sphero-GOB-RN-SPP", 26 | "127.0.0.1:4566" => "/dev/tty.Sphero-PYG-RN-SPP"} 27 | robots = [] 28 | SPHEROS.each_key {|p| 29 | robots << SpheroRobot.new(:connections => 30 | {:sphero => 31 | {:port => p}}) 32 | } 33 | 34 | SpheroRobot.work!(robots) 35 | -------------------------------------------------------------------------------- /artoo-sphero.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "artoo-sphero/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "artoo-sphero" 7 | s.version = Artoo::Sphero::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Ron Evans", "Adrian Zankich", "Mike Ford", "Tobias Pfeiffer", "Edgar Silva"] 10 | s.email = ["artoo@hybridgroup.com"] 11 | s.homepage = "https://github.com/hybridgroup/artoo-sphero" 12 | s.summary = %q{Artoo adaptor and driver for Sphero robot} 13 | s.description = %q{Artoo adaptor and driver for Sphero robot} 14 | 15 | s.rubyforge_project = "artoo-sphero" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | 22 | s.add_runtime_dependency 'artoo', '>= 1.8.0' 23 | s.add_runtime_dependency 'sphero', '>= 1.5.3' 24 | s.add_development_dependency 'minitest', '>= 5.0' 25 | s.add_development_dependency 'minitest-happy', "~>1.0.0" 26 | s.add_development_dependency 'mocha', '>= 0.14.0' 27 | end 28 | -------------------------------------------------------------------------------- /lib/artoo/adaptors/sphero.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/adaptors/adaptor' 2 | 3 | module Artoo 4 | module Adaptors 5 | # Connect to a Sphero device 6 | # @see http://gosphero.com Sphero information 7 | # @see http://rubydoc.info/gems/hybridgroup-sphero Sphero gem Documentation 8 | class Sphero < Adaptor 9 | attr_reader :sphero 10 | 11 | # Number of retries when connecting 12 | RETRY_COUNT = 5 13 | 14 | # Creates a connection with Sphero object with retries 15 | # @return [Boolean] 16 | def connect 17 | @retries_left = RETRY_COUNT 18 | require 'sphero' unless defined?(::Sphero) 19 | begin 20 | @sphero = ::Sphero.new(connect_to) 21 | super 22 | return true 23 | rescue Errno::EBUSY, Errno::ECONNREFUSED => e 24 | @retries_left -= 1 25 | if @retries_left > 0 26 | retry 27 | else 28 | Logger.error e.message 29 | Logger.error e.backtrace.inspect 30 | return false 31 | end 32 | end 33 | end 34 | 35 | # Closes connection with device 36 | # @return [Boolean] 37 | def disconnect 38 | Logger.info "Stopping and disconnecting sphero" 39 | sphero.close if connected? 40 | 41 | super 42 | end 43 | 44 | # Uses method missing to call sphero actions 45 | # @see http://rubydoc.info/gems/hybridgroup-sphero/Sphero Sphero documentation 46 | def method_missing(method_name, *arguments, &block) 47 | sphero.send(method_name, *arguments, &block) 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | # Commands 2 | 3 | ## roll(speed, direction) 4 | 5 | Starts the sphero rolling at the provided speed (value between `0` and `255`) and direction (value between `0` and `360`). 6 | 7 | ##### Params 8 | 9 | - **speed** - params 10 | - **direction** - params 11 | 12 | ##### Returns 13 | 14 | `true or nil` 15 | 16 | ## stop 17 | 18 | Stops the sphero. 19 | 20 | ##### Returns 21 | 22 | `true or nil` 23 | 24 | ## detect_collisions 25 | 26 | Sets the sphero to detect collisions and report them. 27 | 28 | ##### Returns 29 | 30 | `true or nil` 31 | 32 | ## messages → [sphero_event] 33 | 34 | Returns an array of sphero events, the messages reported by the sphero. 35 | 36 | ##### Returns 37 | 38 | `sphero_event` 39 | 40 | ## color(:color_symbol | [red, green, blue]) → [red_int, green_int, blue_int] 41 | 42 | You can pass a color as a symbol or an array containing RGB colors from 0 to 255 `([255, 0, 0] == red)`, if passed a symbol returns the array of RGB corresponding to the color, if passed an array of colors it returns the same array (used when setting colors to the sphero). 43 | 44 | ##### Params 45 | 46 | - **color_symbol** - params 47 | - **red** - params 48 | - **green** - params 49 | - **blue** - params 50 | 51 | ##### Returns 52 | 53 | `[red_int, green_int, blue_int]` 54 | 55 | ## set_color([red, green, blue]) → true | nil 56 | 57 | REVISION PENDING: You can either use it in tandem with color to set the color of the sphero or just pass an array containing RGB colors on the range `0` to `255` `([255, 0, 0] == red)`. 58 | 59 | ##### Params 60 | 61 | - **red** - params 62 | - **green** - params 63 | - **blue** - params 64 | 65 | ##### Returns 66 | 67 | `true or nil` -------------------------------------------------------------------------------- /test/drivers/sphero_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path(File.dirname(__FILE__) + "/../test_helper") 2 | require 'artoo/drivers/sphero' 3 | 4 | describe Artoo::Drivers::Sphero do 5 | before do 6 | @device = mock('device') 7 | @device.stubs(:require_interface) 8 | @driver = Artoo::Drivers::Sphero.new(:parent => @device) 9 | @connection = mock('connection') 10 | @messages = Queue.new 11 | @messages << ::Sphero::Response::CollisionDetected.new("yo", "ho") 12 | @messages << ::Sphero::Response::CollisionDetected.new("yo", "ho") 13 | @messages << ::Sphero::Response::SensorData.new("yo", "ho") 14 | @messages << ::Sphero::Response::SensorData.new("lo", "no") 15 | @messages << ::Sphero::Response::SensorData.new("jo", "jo") 16 | @messages << ::Sphero::Response::PowerNotification.new("yo", "ho") 17 | @messages << ::Sphero::Response::PowerNotification.new("yo", "ho") 18 | @connection.stubs(:messages).returns(@messages) 19 | @device.stubs(:connection).returns(@connection) 20 | end 21 | 22 | it 'Sphero#handle_message_events' do 23 | @driver.stubs(:handle_collision_detected) 24 | @driver.stubs(:handle_power_notification) 25 | @driver.stubs(:handle_sensor_data) 26 | 27 | @messages.empty?.must_equal false 28 | @messages.size.must_equal 7 29 | 30 | @driver.handle_message_events 31 | 32 | @messages.empty?.must_equal true 33 | @messages.size.must_equal 0 34 | end 35 | 36 | describe 'color' do 37 | it 'Sphero#color(:red)' do 38 | r, g, b = @driver.color(:red) 39 | r.must_equal 255 40 | g.must_equal 0 41 | b.must_equal 0 42 | end 43 | 44 | it 'Sphero#color(:green)' do 45 | r, g, b = @driver.color(:green) 46 | r.must_equal 0 47 | g.must_equal 255 48 | b.must_equal 0 49 | end 50 | 51 | it 'Sphero#color(r, g, b)' do 52 | r, g, b = @driver.color(2, 4, 6) 53 | r.must_equal 2 54 | g.must_equal 4 55 | b.must_equal 6 56 | end 57 | end 58 | 59 | describe 'get_rgb' do 60 | 61 | let(:rgb_color) { OpenStruct.new(r: 255, g: 254, b: 253) } 62 | 63 | it 'returns rgb color' do 64 | @connection.stubs(:user_led).returns(rgb_color) 65 | 66 | @driver.get_rgb.must_equal [255, 254, 253] 67 | end 68 | 69 | it 'returns nil if message lost' do 70 | @connection.stubs(:user_led).returns(nil) 71 | 72 | @driver.get_rgb.must_equal nil 73 | end 74 | 75 | end 76 | 77 | it 'should be able to start calibration process' 78 | it 'should be able to finish calibration process' 79 | 80 | end 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Artoo Adaptor For Sphero 2 | 3 | This repository contains the Artoo (http://artoo.io/) adaptor for the Sphero (http://gosphero.com) robot. 4 | 5 | Artoo is a open source micro-framework for robotics using Ruby. 6 | 7 | For more information abut Artoo, check out our repo at https://github.com/hybridgroup/artoo 8 | 9 | [![Code Climate](https://codeclimate.com/github/hybridgroup/artoo-sphero.png)](https://codeclimate.com/github/hybridgroup/artoo-sphero) [![Build Status](https://travis-ci.org/hybridgroup/artoo-sphero.png?branch=master)](https://travis-ci.org/hybridgroup/artoo-sphero) 10 | 11 | ## Installing 12 | 13 | ``` 14 | gem install artoo-sphero 15 | ``` 16 | 17 | ## Using 18 | 19 | ```ruby 20 | require 'artoo' 21 | 22 | connection :sphero, :adaptor => :sphero, :port => '/dev/rfcomm0' #linux 23 | device :sphero, :driver => :sphero 24 | 25 | work do 26 | @rolling = false 27 | 28 | every(3.seconds) do 29 | puts "Rolling..." 30 | sphero.roll 90, rand(360) 31 | end 32 | end 33 | ``` 34 | ## Connecting to Sphero 35 | 36 | ### OSX 37 | 38 | The main steps are: 39 | 40 | - Pair your computer and the Sphero 41 | - Find out the sphero bluetooth address 42 | - Connect to the device via Artoo 43 | 44 | First pair your computer and Sphero. You can do this using bluetooth preferences. (Sphero won't stay connected) 45 | 46 | Find out serial port address by running this command: 47 | 48 | `$ ls /dev/tty.Sphero*` 49 | 50 | Now you are ready to run the example code, be sure to update this line with correct port 51 | 52 | ```ruby 53 | connection :sphero, :adaptor => :sphero, :port => '/dev/tty.Sphero-WRW-RN-SPP' 54 | ``` 55 | 56 | ### Linux 57 | 58 | The main steps are: 59 | 60 | - Find out the sphero bluetooth address 61 | - Pair your computer and the Sphero 62 | - Map your device to a unix port 63 | - Connect to the device via Artoo 64 | 65 | First pair your computer and Sphero. 66 | We do this by finding the sphero bluetooth address and then running [Gort´s](http://gort.io) `gort bluetooth pair` command, you might be prompted to confirm a passcode. 67 | Just accept whatever passcode prompted. 68 | 69 | ``` 70 | $ gort bluetooth scan 71 | Scanning ... 72 | 00:06:66:4A:14:99 Sphero-WRW 73 | ``` 74 | 75 | After finding the bluetooth address, we pair the device with the computer. 76 | The easiest way to do this is to use the `gort bluetooth pair` command: 77 | 78 | `$ gort bluetooth pair 00:06:66:4A:14:99` 79 | 80 | Next, you need to bind the Sphero to the system serial port. In the above 81 | example, /dev/Sphero-WRW. Use the `gort bluetooth connect` command: 82 | 83 | `$ gort bluetooth connect 00:06:66:4A:14:99 Sphero-WRW` 84 | 85 | Now you are ready to run the example code, be sure to update this line with correct port. 86 | 87 | ```ruby 88 | connection :sphero, :adaptor => :sphero, :port => '/dev/Sphero-WRW' 89 | ``` 90 | 91 | ### Windows 92 | 93 | You should be able to simply pair your Sphero using your normal system tray applet for Bluetooth, and then connect to the COM port that is bound to the device, such as `COM3`. 94 | 95 | ## Documentation 96 | 97 | Check out our [documentation](http://artoo.io/documentation/) for lots of information about how to use Artoo. 98 | 99 | ## IRC 100 | 101 | Need more help? Just want to say "Hello"? Come visit us on IRC freenode #artoo 102 | 103 | ## Contributing 104 | * All active development is in the dev branch. New or updated features must be added to the dev branch. Hotfixes will be considered on the master branch in situations where it does not alter behaviour or features, only fixes a bug. 105 | * All patches must be provided under the Apache 2.0 License 106 | * Please use the -s option in git to "sign off" that the commit is your work and you are providing it under the Apache 2.0 License 107 | * Submit a Github Pull Request to the appropriate branch and ideally discuss the changes with us in IRC. 108 | * We will look at the patch, test it out, and give you feedback. 109 | * Avoid doing minor whitespace changes, renamings, etc. along with merged content. These will be done by the maintainers from time to time but they can complicate merges and should be done seperately. 110 | * Take care to maintain the existing coding style. 111 | * Add unit tests for any new or changed functionality. 112 | * All pull requests should be "fast forward" 113 | * If there are commits after yours use “git rebase -i ” 114 | * If you have local changes you may need to use “git stash” 115 | * For git help see [progit](http://git-scm.com/book) which is an awesome (and free) book on git 116 | 117 | 118 | (c) 2012-2014 The Hybrid Group 119 | -------------------------------------------------------------------------------- /lib/artoo/drivers/sphero.rb: -------------------------------------------------------------------------------- 1 | require 'artoo/drivers/driver' 2 | 3 | module Artoo 4 | module Drivers 5 | # The Sphero driver behaviors 6 | class Sphero < Driver 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 = [:ping, :version, :bluetooth_info, :auto_reconnect, 15 | :disable_auto_reconnect, :power_state, :sphero_sleep, :roll, 16 | :stop, :heading, :stabilization, :color, :rgb, :set_color, 17 | :back_led_output, :rotation_rate, :set_power_notification, 18 | :set_data_streaming, :detect_collisions, 19 | :handle_message_events, :get_rgb, :start_calibration, 20 | :finish_calibration].freeze 21 | 22 | def initialize(params={}) 23 | super 24 | require_interface(:sphero) 25 | end 26 | 27 | # Starts drives and required connections 28 | 29 | # Public: Starts the driver. 30 | # 31 | # Returns null. 32 | def start_driver 33 | begin 34 | detect_collisions 35 | enable_stop_on_disconnect 36 | 37 | every(interval) do 38 | handle_message_events 39 | end 40 | 41 | super 42 | rescue Exception => e 43 | Logger.error "Error starting Sphero driver!" 44 | Logger.error e.message 45 | Logger.error e.backtrace.inspect 46 | end 47 | end 48 | 49 | # Public: Handles different message events. 50 | # 51 | # Returns sphero_event. 52 | def handle_message_events 53 | while not connection.messages.empty? do 54 | evt = connection.messages.pop 55 | case 56 | when evt.is_a?(::Sphero::Response::CollisionDetected) 57 | handle_collision_detected(evt) 58 | when evt.is_a?(::Sphero::Response::PowerNotification) 59 | handle_power_notification(evt) 60 | when evt.is_a?(::Sphero::Response::SensorData) 61 | handle_sensor_data(evt) 62 | end 63 | end 64 | end 65 | 66 | # Detects collisions 67 | # @param [Hash] params 68 | 69 | # Public: Sets the sphero to detect collisions and report them. 70 | # 71 | # Returns true | nil. 72 | def detect_collisions(params={}) 73 | connection.configure_collision_detection 0x01, 0x20, 0x20, 0x20, 0x20, 0x50 74 | end 75 | 76 | # Set color 77 | # @param [Collection] colors 78 | 79 | # Public: You can either use it in tandem with color to set the color of the 80 | # sphero or just pass an array containing RGB colors on the range 0 to 255 81 | # ([255, 0, 0] == red). 82 | # 83 | # red - params 84 | # green - params 85 | # blue -params 86 | # 87 | # Returns true | nil. 88 | def set_color(*colors) 89 | connection.rgb(*color(*colors), true) 90 | end 91 | 92 | # Retrieves color 93 | # @param [Collection] colors 94 | 95 | # Public: You can pass a color as a symbol or an array containing RGB colors from 0 to 255 96 | # ([255, 0, 0] == red), if passed a symbol returns the array of RGB corresponding to the 97 | # color, if passed an array of colors it returns the same array (used when setting colors to the sphero). 98 | # 99 | # :color_symbol - color 100 | # red - params 101 | # green - params 102 | # blue -params 103 | # 104 | # Returns true | nil. 105 | def color(*colors) 106 | case colors.first 107 | when :red then RED 108 | when :green then GREEN 109 | when :yellow then YELLOW 110 | when :blue then BLUE 111 | when :white then WHITE 112 | else colors 113 | end 114 | end 115 | 116 | # Get the sphero color 117 | 118 | # Public: You can retrieve current sphero color 119 | # 120 | # Returns array of rgb values 121 | def get_rgb 122 | rgb = connection.user_led 123 | 124 | [rgb.r, rgb.g, rgb.b] if rgb 125 | end 126 | 127 | # Starts calibration process by turning on back LED and turning off 128 | # auto-stabilization 129 | def start_calibration 130 | connection.back_led_output = 127 131 | connection.stabilization = false 132 | end 133 | 134 | # Finishes calibration process by setting the new heading, turning off back LED, 135 | # and turning back on auto-stabilization 136 | def finish_calibration 137 | connection.heading = 0 138 | connection.back_led_output = 0 139 | connection.stabilization = true 140 | end 141 | 142 | private 143 | 144 | # Publish collision events 145 | 146 | # Handles collision message events. 147 | # 148 | # data - params 149 | # 150 | # Returns nil. 151 | def handle_collision_detected(data) 152 | publish(event_topic_name("collision"), data) 153 | end 154 | 155 | # Publish collision events 156 | 157 | # Public: Handles power message events. 158 | # 159 | # data - params 160 | # 161 | # Returns nil. 162 | def handle_power_notification(data) 163 | publish(event_topic_name("power"), data) 164 | end 165 | 166 | # Publish collision events 167 | 168 | # Handles sensor message events. 169 | # 170 | # data - params 171 | # 172 | # Returns nil. 173 | def handle_sensor_data(data) 174 | publish(event_topic_name("sensor"), data) 175 | end 176 | end 177 | end 178 | end 179 | --------------------------------------------------------------------------------