hybridgroup/artoo-roomba

View on GitHub
lib/artoo/drivers/roomba.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'artoo/drivers/driver'

module Artoo
  module Drivers
    # The Roomba driver behaviors
    class Roomba < Driver

      COMMANDS = [:start, :safe_mode, :full_mode, :forward, :stop, :fast_forward,
                  :backwards, :nudge_left, :nudge_right, :turn_left, :turn_right,
                  :turn_around, :drive, :play, :song, :beep].freeze

      # Sets Direction constant values
      module Direction
        STRAIGHT = 32768
        CLOCKWISE = 65535
        COUNTERCLOCKWISE = 1
      end

      # Sets speed constant values
      module Speed
        MAX = 500
        SLOW = 250
        NEG = (65536 - 250)
        ZERO = 0
      end

      # Sets notes constant values
      module Note
        B = 95
        D = 98
        G = 91
        C = 96
        A = 93
        QUARTER = 16
        HALF = 57
        WHOLE = 114
      end

      # Sets mode constant values
      module Mode
        FULL = 132
        SAFE = 131
        START = 128
      end

      # Sets song constant values
      module Song
        SONG = 140
        PLAY = 141
      end

      # Sends start mode
      def start
        send_bytes(Mode::START)
        sleep 0.2
      end

      # Sends safe mode
      def safe_mode
        start
        send_bytes(Mode::SAFE)
        sleep 0.1
      end

      # Sends full mode
      def full_mode
        start
        send_bytes(Mode::FULL)
        sleep 0.1
      end

      # Move forward
      # @param [Integer] seconds
      # @param [Constant] velocity
      # @see Speed
      def forward(seconds, velocity = Speed::SLOW)
        drive(velocity, Direction::STRAIGHT, seconds)
        stop if seconds > 0
      end

      # Stop movement
      def stop
        drive(Speed::ZERO, Direction::STRAIGHT)
      end

      # Move forward with fast speed
      # @param [Integer] seconds
      def fast_forward(seconds)
        drive(Speed::MAX, Direction::STRAIGHT, seconds)
        stop if seconds > 0
      end

      # Move backward
      # @param [Integer] seconds
      def backwards(seconds)
        drive(Speed::NEG, Direction::STRAIGHT, seconds)
        stop if seconds > 0
      end

      # Nudge left
      def nudge_left
        turn_left(0.25)
      end

      # Turn left
      # @param [Integer] seconds
      def turn_left(seconds = 1)
        drive(Speed::SLOW, Direction::COUNTERCLOCKWISE, seconds)
        stop if seconds > 0
      end

      # Turn right
      # @param [Integer] seconds
      def turn_right(seconds = 1)
        drive(Speed::SLOW, Direction::CLOCKWISE, seconds)
        stop if seconds > 0
      end

      # Nudge right
      def nudge_right
        turn_right(0.25)
      end

      # Turn around
      def turn_around
        turn_left(1.6)
      end

      # Drive
      # @param [Integer] v speed
      # @param [Integer] r direction
      # @param [Integer] s seconds (waiting time)
      # @see Speed
      # @see Direction
      def drive(v, r, s = 0)
        vH,vL = split_bytes(v)
        rH,rL = split_bytes(r)
        send_bytes([137, vH, vL, rH, rL])
        sleep(s) if s > 0
      end

      # Split bytes (hex)
      # @param [Integer] num
      def split_bytes(num)
        [num >> 8, num & 255]
      end

      # Play song
      # @param [Integer] song_number
      def play(song_number = 0)
        send_bytes([Song::PLAY, song_number])
      end

      # Save song
      # @param [Collection] notes
      # @param [Integer]    song_number
      # @see Notes
      def song(notes, song_number = 0)
        note_group = notes.flatten.compact
        l = note_group.length / 2
        send_bytes([Song::SONG, song_number, l] + note_group)
      end

      # Play song
      # @param [Collection] notes
      # @param [Integer]    song_number
      # @see Notes
      def play_song(notes, song_number = 0)
        song(notes, song_number)
        play(song_number)
      end

      # Beeps with a G note
      def beep
        play_song([Note::G, Note::WHOLE])
      end
    end
  end
end