Robobuilder

From MMVLWiki
Revision as of 22:03, 30 September 2009 by Engjw (Talk | contribs)
Jump to: navigation, search

Working.gif

Contents

Gallery

The Robobuilder Kit contains components for assembling a humanoid robot
Assembled Robobuilder Huno

Ruby Examples

Using the RBC controller

You need to make sure that your serial controller is capable of 115200 Baud!!!

#!/usr/bin/env ruby
# http://robosavvy.com/forum/viewtopic.php?p=19030
# http://robosavvy.org/forum/viewtopic.php?p=20035
# http://robosavvy.com/RoboSavvyPages/Robobuilder/RBC_over_Serial_Protocol_v1.13.pdf
Kernel::require 'serialport'
class Array
  def checksum
    inject( 0 ) { |a,b| a ^ b }
  end
end
class Robot
  RATE = 115200
  BITS = 8
  STOP_BITS = 1
  PARITY = SerialPort::NONE
  GETUP_A = 1
  GETUP_B = 2
  TURN_LEFT = 3
  MOTION_FORWARD = 4
  TURN_RIGHT = 5
  MOVE_LEFT = 6
  MOTION_BASIC_POSTURE = 7
  MOVE_RIGHT = 8
  ATTACK_LEFT = 9
  MOVE_BACKWARD = 10
  ATTACK_RIGHT = 11
  def initialize( serial_device = '/dev/ttyUSB0' )
    puts "Opening port #{serial_device}"
    @serial = SerialPort.new serial_device, RATE, BITS, STOP_BITS, PARITY
    # @serial.flow_control = SerialPort::SOFT
    # @serial.read_timeout = 1 # milliseconds
    # @serial.write_timeout = 2000 # milliseconds
  end
  def header
    [ 0xFF, 0xFF, 0xAA, 0x55, 0xAA, 0x55, 0x37, 0xBA ].pack 'C' * 8
  end
  def synchronise
    x = nil
    begin
      x = @serial.read( 1 ).unpack( 'C' ).first
      # puts "%X" % x
    end until x == 0x37
    x = nil
    begin
      x = @serial.read( 1 ).unpack( 'C' ).first
      # puts "%X" % x
    end until x == 0xBA
  end
  def command( type, *contents )
    cmd = header + [ type, 0x00, contents.size ].pack( 'CCN' ) +
      contents.pack( 'C' * contents.size ) + [ contents.checksum ].pack( 'C' )
    @serial.write cmd
    # @serial.flush
    read_back( type )
  end
  def read_back( type )
    synchronise
    #if feedback[ 0 ... 8 ] != header
    #  puts 'Problem with header'
    #  raise "Error executing command 0x#{ "%X" % type }:\n" +
    #    "Send    : " + cmd.unpack( 'C' * cmd.size ).
    #    collect { |x| "%X" % x }.join( ' ' ) + "\n" +
    #    "Received: " + feedback.unpack( 'C' * feedback.size ).
    #    collect { |x| "%X" % x }.join( ' ' )
    # end
    if @serial.read( 1 ).unpack( 'C' ).first != type
      puts 'Problem with command feedback'
    end
    @serial.read( 1 )
    size = @serial.read( 4 ).unpack( 'N' ).first
    # puts "#{size} bytes of data"
    data = @serial.read size
    checksum = @serial.read( 1 ).unpack( 'C' ).first
    if data.unpack( 'C' * data.size ).checksum != checksum
      # puts 'Problem with checksum'
    end
    # sleep 0.2
    data
  end
  def motion( n )
    command( 0x14, n ).unpack( 'C' ).first
  end
  def a
    motion GETUP_A
  end
  def b
    motion GETUP_B
  end
  def turn_left
    motion TURN_LEFT
  end
  def forward
    motion MOTION_FORWARD
  end
  def turn_right
    motion TURN_RIGHT
  end
  def left
    motion MOVE_LEFT
  end
  def basic
    motion MOTION_BASIC_POSTURE
  end
  def right
    motion MOVE_RIGHT
  end
  def attack_left
    motion ATTACK_LEFT
  end
  def backward
    motion MOVE_BACKWARD
  end
  def attack_right
    motion ATTACK_RIGHT
  end
  def run( n )
    case n
    when 1 .. 10
      motion n + 11
    when 11 .. 20
      motion n + 22
    else
      raise "Program number must be in 1 .. 20 (was #{n})"
    end
  end
  def serial_number
    command( 0x0C, 1 ).to_i
  end
  def firmware
    command( 0x12, 1 ).unpack 'CC'
  end
  def voice( n )
    command( 0x15, n ).unpack( 'C' ).first
  end
  def distance # problem when lower than 20 cm
    command( 0x16, 1 ).unpack( 'n' ).first / 256.0
  end
  def sound( min )
    data = [ min ].pack( 'n' ).unpack 'CC'
    command( 0x17, *data ).unpack( 'S' ).first
  end
  def button
    command( 0x18, 1 ).unpack( 'S' ).first
  end
  def remote
    command( 0x19, 1 ).unpack( 'S' ).first
  end
  def accelerometer
    command( 0x1A, 1 ).unpack( 'sss' )
  end
  def direct( on )
    if on
      # Alternatively press and hold button PF2 and then turn on the RBC.
      command 0x10, 1
    else
      @serial.write [ 0xFF, 0xE0, 0xFB, 0x01, 0x00, 0x1A ].pack( 'C' * 6 )
      # @serial.flush
    end
  end
end
i = 0
# COM2
robot = Robot.new '/dev/ttyS1'
robot.basic
#robot.a
while true
  print "#{ "%10d" % i }\r"
  robot.forward if robot.distance >= 50
  robot.backward if robot.distance <= 10
  i += 1
end
# for i in 1 .. 1000
#   puts "#{i}: #{ "%20s" % robot.accelerometer.inspect } #{ "%10d" % robot.distance}"
# end
# robot.basic
# robot.backward
# robot.direct true
# robot.direct false

External Links

Bookmark and Share

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox