irobotcreate 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+