irobotcreate 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ require 'irobotcreate'
2
+
3
+ # Hit Ctrl-C to end
4
+
5
+ irc = IRobotCreate::Robot.new
6
+ irc.start
7
+ irc.full
8
+
9
+ moving = false
10
+
11
+ while true
12
+ if irc.sensor_buttons[:play]
13
+ unless moving == :forward
14
+ moving = :forward
15
+ irc.drive_direct(100, 100)
16
+ end
17
+ elsif irc.sensor_buttons[:advance]
18
+ unless moving == :backwards
19
+ moving = :backwards
20
+ irc.drive_direct(-100, -100)
21
+ end
22
+ else
23
+ if moving
24
+ irc.drive_direct(0, 0)
25
+ moving = false
26
+ end
27
+ end
28
+ print "\rVelocity: #{irc.sensor_requested_right_velocity}, #{irc.sensor_requested_left_velocity} "
29
+ end
@@ -0,0 +1,7 @@
1
+ require 'irobotcreate/robot'
2
+ require 'irobotcreate/command'
3
+ require 'irobotcreate/command/sensor'
4
+
5
+ module IRobotCreate
6
+ DEBUG = false
7
+ end
@@ -0,0 +1,159 @@
1
+ module IRobotCreate
2
+
3
+ class Command
4
+
5
+ attr_reader :code, :argument_options
6
+
7
+ @@commands = {}
8
+
9
+ class << self
10
+
11
+ def register(name, *args)
12
+ @@commands[name] = new(*args)
13
+ end
14
+
15
+ def [](name)
16
+ @@commands[name.to_sym]
17
+ end
18
+
19
+ end
20
+
21
+ def initialize(code, argument_options = [])
22
+ @code = code
23
+
24
+ if argument_options != :inf
25
+ case argument_options
26
+ when Integer
27
+ argument_options = [{ :type => :integer }] * argument_options
28
+ when Symbol
29
+ argument_options = [{ :type => argument_options }]
30
+ when Array
31
+ argument_options.map!{|ao| ao.is_a?(Hash) ? ao : { :type => ao } }
32
+ when Hash
33
+ argument_options = [argument_options]
34
+ else
35
+ raise "Can't handle argument options: #{argument_options}"
36
+ end
37
+ end
38
+
39
+ @argument_options = argument_options
40
+ end
41
+
42
+ def run(robot, *args)
43
+ if argument_options == :inf
44
+ array = args
45
+ else
46
+ if IRobotCreate::DEBUG
47
+ puts "args: #{args.inspect}"
48
+ puts "argument_options: #{argument_options.inspect}"
49
+ end
50
+ if args.size != argument_options.size
51
+ raise ArgumentError, "Requires #{argument_options.size} arguments"
52
+ end
53
+
54
+ array = []
55
+ args.each_with_index do |arg, i|
56
+ opts = argument_options[i]
57
+
58
+ value = arg
59
+ puts "starting value: #{value.inspect}" if IRobotCreate::DEBUG
60
+
61
+ size = opts[:size] || 1
62
+
63
+ if opts[:inverse_map]
64
+ opts[:map] = opts[:inverse_map]
65
+ for k,v in opts[:inverse_map]
66
+ opts[:map]["not_#{k}".to_sym] = 256**size - v
67
+ end
68
+ puts "inverse_map: #{opts[:map.inspect]}" if IRobotCreate::DEBUG
69
+ end
70
+
71
+ if opts[:map]
72
+ value = opts[:map][value]
73
+ puts "mapped: #{value}" if IRobotCreate::DEBUG
74
+ raise "Couldn't map value" if value.nil?
75
+ end
76
+
77
+ if opts[:compound]
78
+ raise "Compound size must be 1!" unless size == 1
79
+
80
+ value_array = value.is_a?(Array) ? value : [value]
81
+ value = 0
82
+
83
+ compound_size = opts[:compound].size
84
+ compound_size.times do |j|
85
+ compound_value = opts[:compound][j]
86
+ puts "checking for #{compound_value}" if IRobotCreate::DEBUG
87
+ if compound_value && value_array.include?(compound_value)
88
+ bit = (compound_size - 1) - j
89
+ puts "Adding bit: #{bit}" if IRobotCreate::DEBUG
90
+ value += 2 ** bit
91
+ end
92
+ end
93
+ elsif opts[:type] == :boolean
94
+ value = value ? 1 : 0
95
+ end
96
+
97
+ puts "preprocessed value: #{value.inspect}" if IRobotCreate::DEBUG
98
+
99
+ if value < 0
100
+ value += 256 ** size
101
+ puts "converted negative: #{value.inspect}" if IRobotCreate::DEBUG
102
+ end
103
+
104
+ size.times do |j|
105
+ base = 256 ** ((size - 1) - j)
106
+ current = value / base
107
+ value %= base
108
+ array << current
109
+ end
110
+
111
+ puts "array: #{array.inspect}" if IRobotCreate::DEBUG
112
+ end
113
+ end
114
+
115
+ puts "final array: #{array.inspect}" if IRobotCreate::DEBUG
116
+
117
+ robot.send([code] + array)
118
+ end
119
+
120
+ end
121
+
122
+ Command.class_eval do
123
+ register :start, 128
124
+ register :baud, 129, :map => { 300 => 0, 600 => 1, 1200 => 2, 2400 => 3, 4800 => 4, 9600 => 5, 14440 => 6,
125
+ 19200 => 7, 28800 => 8, 38400 => 9, 57600 => 10, 115200 => 11 }
126
+ register :safe, 131
127
+ register :full, 132
128
+ register :demo, 136, :map => { :abort => -1, :cover => 0, :cover_and_dock => 1, :spot_cover => 2, :mouse => 3,
129
+ :figure_eight => 4, :wimp => 5, :home => 6, :tag => 7, :pachelbel => 8, :banjo => 9 }
130
+ register :cover, 135
131
+ register :cover_and_dock, 143
132
+ register :spot, 134
133
+ register :drive, 137, [{ :size => 2 }, { :size => 2 }]
134
+ register :drive_direct, 145, [{ :size => 2 }, { :size => 2 }]
135
+ register :leds, 139, [{ :compound => [:advance, nil, :play, nil ]}, :integer, :integer]
136
+ register :digital, 147, :compound => [:output2, :output1, :output0 ]
137
+ register :pwm, 144, 3
138
+ register :driver, 138, :compound => [:side_driver2, :low_side_driver1, :low_side_driver0]
139
+ register :ir, 151, 1
140
+ register :song, 140, :inf
141
+ register :play_song, 141, 1
142
+ register :sensors, 142, 1
143
+ register :query, 149, :inf
144
+ register :stream, 148, :inf
145
+ register :stream_playing, 150, :boolean
146
+ register :script, 152, :inf
147
+ register :play_script, 153
148
+ register :show_script, 154
149
+ register :wait_time, 155, 1
150
+ register :wait_distance, 156, :size => 2
151
+ register :wait_angle, 157, :size => 2
152
+ register :wait_event, 158, :inverse_map => { :wheel_drop => 1, :front_wheel_drop => 2, :left_wheel_drop => 3, :right_wheel_drop => 4,
153
+ :bump => 5, :left_bump => 6, :right_bump => 7, :virtual_wall => 8, :wall => 9,
154
+ :cliff => 10, :left_cliff => 11, :front_left_cliff => 12, :front_right_cliff => 13,
155
+ :right_cliff => 14, :home_base => 15, :advance_button => 16, :play_button => 17,
156
+ :digital0 => 18, :digital1 => 19, :digital2 => 20, :digital3 => 21, :oi_passive => 22 }
157
+ end
158
+
159
+ end
@@ -0,0 +1,108 @@
1
+ module IRobotCreate
2
+ class SensorCommand < Command
3
+
4
+ attr_reader :sensor_code, :response_size, :response_type, :response_options
5
+
6
+ @@sensor_commands = {}
7
+
8
+ class << self
9
+
10
+ def register(name, *args)
11
+ @@sensor_commands[name] = new(*args)
12
+ end
13
+
14
+ def [](name)
15
+ @@sensor_commands[name.to_sym]
16
+ end
17
+
18
+ end
19
+
20
+ def initialize(sensor_code, response_size, response_type, response_options = nil)
21
+ super(142, 1)
22
+ @sensor_code = sensor_code
23
+ @response_size = response_size
24
+ @response_type = response_type
25
+ @response_options = response_options
26
+ end
27
+
28
+ def run(robot)
29
+ super(robot, sensor_code)
30
+
31
+ response = robot.read_response(response_size)
32
+
33
+ case response_type
34
+ when :boolean
35
+ response.first == 1
36
+ when :integer, :signed_integer
37
+ integer = 0
38
+ response_size.times do |i|
39
+ integer += response[i] * (256 ** ((response_size - 1) - i))
40
+ end
41
+
42
+ if response_type == :signed_integer
43
+ max = 256 ** response_size
44
+ if integer > max / 2
45
+ integer -= max
46
+ end
47
+ end
48
+
49
+ integer
50
+ when :map
51
+ response_options[response.first]
52
+ when :compound
53
+ hash = {}
54
+ options_size = response_options.size
55
+ options_size.times do |i|
56
+ item = response_options[i]
57
+ next unless item
58
+ hash[item] = response.first & 2**((options_size - 1) - i) != 0
59
+ end
60
+ hash
61
+ else
62
+ response
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ SensorCommand.class_eval do
69
+ register :bump_drop, 7, 1, :compound, [:wheeldrop_caster, :wheeldrop_left, :wheeldrop_right, :bump_left, :bump_right]
70
+ register :wall, 8, 1, :boolean
71
+ register :cliff_left, 9, 1, :boolean
72
+ register :cliff_front_left, 10, 1, :boolean
73
+ register :cliff_front_right, 11, 1, :boolean
74
+ register :cliff_right, 12, 1, :boolean
75
+ register :virtual_wall, 13, 1, :boolean
76
+ register :low_side_and_wheels, 14, 1, :compound, [:left_wheel, :right_wheel, :ld2, :ld0, :ld1]
77
+ register :ir, 17, 1, :map, { 129 => :left, 130 => :forward, 131 => :right, 132 => :spot, 133 => :max,
78
+ 134 => :small, 135 => :medium, 136 => :large, 137 => :pause, 138 => :power,
79
+ 139 => :arc_left, 140 => :arc_right, 141 => :drive_stop }
80
+ register :buttons, 18, 1, :compound, [:advance, nil, :play]
81
+ register :distance, 19, 2, :signed_integer
82
+ register :angle, 20, 2, :signed_integer
83
+ register :charging, 21, 1, :map, { 0 => :not_charging, 1 => :reconditioning, 2 => :full, 3 => :trickle,
84
+ 4 => :waiting, 5 => :fault }
85
+ register :voltage, 22, 2, :integer
86
+ register :current, 23, 2, :signed_integer
87
+ register :battery_temperature, 24, 1, :signed_integer
88
+ register :battery_charge, 25, 2, :integer
89
+ register :battery_capacity, 26, 2, :integer
90
+ register :wall_signal, 27, 2, :integer
91
+ register :cliff_left_signal, 28, 2, :integer
92
+ register :cliff_front_left_signal, 29, 2, :integer
93
+ register :cliff_front_right_signal, 30, 2, :integer
94
+ register :cliff_right_signal, 31, 2, :integer
95
+ register :cargo_bay_digital, 32, 1, :compound, [:detect, :input3, :input2, :input1, :input0]
96
+ register :cargo_bay_analog, 33, 2, :integer
97
+ register :charging_sources, 34, 1, :compound, [:home_base, :internal]
98
+ register :oi_mode, 35, 1, :map, { 0 => :off, 1 => :passive, 2 => :safe, 3 => :full }
99
+ register :song_number, 36, 1, :integer
100
+ register :song_playing, 37, 1, :boolean
101
+ register :stream_packets_count, 38, 1, :integer
102
+ register :requested_velocity, 39, 2, :signed_integer
103
+ register :requested_radius, 40, 2, :signed_integer
104
+ register :requested_right_velocity, 41, 2, :signed_integer
105
+ register :requested_left_velocity, 42, 2, :signed_integer
106
+ end
107
+
108
+ end
@@ -0,0 +1,57 @@
1
+ require 'serialport'
2
+
3
+ module IRobotCreate
4
+
5
+ class Robot
6
+
7
+ DEFAULT_PORT = '/dev/tty.ElementSerial-ElementSe'
8
+
9
+ attr_reader :serial
10
+
11
+ def initialize(port = DEFAULT_PORT, args = {})
12
+ args = { :baudrate => 57600, :databits => 8, :stopbits => 1 }.merge(args)
13
+ @serial = SerialPort.new(port, args)
14
+ end
15
+
16
+ def format_bytes(arg)
17
+ array = case arg
18
+ when String
19
+ arg.split(/\s+/).map(&:to_i)
20
+ when Array
21
+ arg
22
+ else
23
+ [arg]
24
+ end
25
+
26
+ array.pack('C*')
27
+ end
28
+
29
+ def send(cmd)
30
+ serial.write format_bytes(cmd)
31
+ end
32
+
33
+ def read_response(size=1)
34
+ (0...size).map{|_| serial.getc }.join.unpack('C*')
35
+ end
36
+
37
+ def run_command(name, *args)
38
+ Command[name].run(self, *args)
39
+ end
40
+
41
+ def check_sensor(name)
42
+ SensorCommand[name].run(self)
43
+ end
44
+
45
+ def method_missing(sym, *args, &block)
46
+ if sym.to_s =~ /^sensor_(.*)$/ && SensorCommand[$1]
47
+ check_sensor($1)
48
+ elsif Command[sym]
49
+ run_command(sym, *args, &block)
50
+ else
51
+ super
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,3 @@
1
+ module IRobotCreate
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: irobotcreate
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Peter Wagenet
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-06 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: serialport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ version: "1.0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: Connect to the IRobotCreate with Ruby via a serial connection.
34
+ email:
35
+ - peter.wagenet@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - lib/irobotcreate/command/sensor.rb
44
+ - lib/irobotcreate/command.rb
45
+ - lib/irobotcreate/robot.rb
46
+ - lib/irobotcreate/version.rb
47
+ - lib/irobotcreate.rb
48
+ - examples/push_to_drive.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/peterwagenet/irobotcreate
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 1
71
+ - 3
72
+ - 6
73
+ version: 1.3.6
74
+ requirements: []
75
+
76
+ rubyforge_project: irobotcreate
77
+ rubygems_version: 1.3.6
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: Ruby interface for the IRobotCreate
81
+ test_files: []
82
+