Robobuilder

(Difference between revisions)
Jump to: navigation, search
m (Using the RBC controller)
m (Ruby Examples)
Line 10: Line 10:
 
=Ruby Examples=
 
=Ruby Examples=
 
==Using the RBC controller==
 
==Using the RBC controller==
You need to make sure that your serial controller is capable of 115200 Baud. Some USB-serial adapters are not capable of this!!!
+
[[Image:New.gif]] You can download the Ruby-extension for controlling the Robobuilder here: [http://vision.eng.shu.ac.uk/jan/robobuilder-0.1.tar.bz2 robobuilder-0.1.tar.bz2]
 +
 
 +
Here is a small example program which makes the robot get up if it's lying on its back or its front.
 
<pre>
 
<pre>
 
#!/usr/bin/env ruby
 
#!/usr/bin/env ruby
# http://robosavvy.com/forum/viewtopic.php?p=19030
+
require 'robobuilder'
# http://robosavvy.org/forum/viewtopic.php?p=20035
+
require 'matrix'
# http://robosavvy.com/RoboSavvyPages/Robobuilder/RBC_over_Serial_Protocol_v1.13.pdf
+
class Vector
Kernel::require 'serialport'
+
   def norm
class Array
+
     Math.sqrt inner_product( self )
   def checksum
+
     inject( 0 ) { |a,b| a ^ b }
+
 
   end
 
   end
 
end
 
end
class Robot
+
robot = Robobuilder.new '/dev/ttyS1'
  RATE = 115200
+
puts "Robobuilder"
  BITS = 8
+
puts "Serial number: #{robot.serial_number}"
  STOP_BITS = 1
+
acceleration = Vector[ *robot.accelerometer ]
  PARITY = SerialPort::NONE
+
if acceleration.inner_product( Vector[ 0, 0, 1 ] ) > acceleration.norm / 2
  GETUP_A = 1
+
   robot.basic
  GETUP_B = 2
+
   robot.a
  TURN_LEFT = 3
+
elsif acceleration.inner_product( Vector[ 0, 0, 1 ] ) < -acceleration.norm / 2
  MOTION_FORWARD = 4
+
   robot.basic
  TURN_RIGHT = 5
+
   robot.b
  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
 
end
i = 0
+
acceleration = Vector[ *robot.accelerometer ]
# COM2
+
if acceleration.inner_product( Vector[ 0, 1, 0 ] ) > acceleration.norm / 2
robot = Robot.new '/dev/ttyS1'
+
   robot.run 1
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
 
end
# for i in 1 .. 1000
+
robot.close
#  puts "#{i}: #{ "%20s" % robot.accelerometer.inspect } #{ "%10d" % robot.distance}"
+
# end
+
# robot.basic
+
# robot.backward
+
# robot.direct true
+
# robot.direct false
+
 
</pre>
 
</pre>
  

Revision as of 18:36, 1 October 2009

Working.gif

Contents

Gallery

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

Ruby Examples

Using the RBC controller

New.gif You can download the Ruby-extension for controlling the Robobuilder here: robobuilder-0.1.tar.bz2

Here is a small example program which makes the robot get up if it's lying on its back or its front.

#!/usr/bin/env ruby
require 'robobuilder'
require 'matrix'
class Vector
  def norm
    Math.sqrt inner_product( self )
  end
end
robot = Robobuilder.new '/dev/ttyS1'
puts "Robobuilder"
puts "Serial number: #{robot.serial_number}"
acceleration = Vector[ *robot.accelerometer ]
if acceleration.inner_product( Vector[ 0, 0, 1 ] ) > acceleration.norm / 2
  robot.basic
  robot.a
elsif acceleration.inner_product( Vector[ 0, 0, 1 ] ) < -acceleration.norm / 2
  robot.basic
  robot.b
end
acceleration = Vector[ *robot.accelerometer ]
if acceleration.inner_product( Vector[ 0, 1, 0 ] ) > acceleration.norm / 2
  robot.run 1
end
robot.close

External Links

Bookmark and Share

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox