ruby-nxt 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,82 @@
1
+ # ruby-nxt Control Mindstorms NXT via Bluetooth Serial Port Connection
2
+ # Copyright (C) 2006 Tony Buser <tbuser@gmail.com> - http://juju.org
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software Foundation,
15
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
+
17
+ require "commands/mixins/sensor"
18
+ require "nxt_comm"
19
+
20
+ # Implements (and extens) the "Light Sensor" block in NXT-G
21
+ class Commands::LightSensor
22
+
23
+ include Commands::Mixins::Sensor
24
+
25
+ attr_reader :port, :generate_light
26
+ attr_accessor :trigger_point, :comparison
27
+
28
+ def initialize(nxt)
29
+ @nxt = nxt
30
+
31
+ # defaults the same as NXT-G
32
+ @port = 3
33
+ @trigger_point = 50
34
+ @comparison = ">"
35
+ @generate_light = true
36
+ set_mode
37
+ end
38
+
39
+ # Turns off the sensor's LED light.
40
+ def ambient_mode
41
+ self.generate_light = false
42
+ end
43
+
44
+ # Turns on the sensor's LED light.
45
+ def illuminated_mode
46
+ self.generate_light = true
47
+ end
48
+
49
+ # Turns the sensor's LED on or off.
50
+ # Takes true or false as the argument; if true, light will be turned on,
51
+ # if false, light will be turned off.
52
+ def generate_light=(on)
53
+ @generate_light = on
54
+ set_mode
55
+ end
56
+
57
+ # intensity of light detected 0-100 in %
58
+ def intensity
59
+ value_scaled
60
+ end
61
+ alias light_level intensity
62
+
63
+ # returns the raw value of the sensor
64
+ def raw_value
65
+ value_raw
66
+ end
67
+
68
+ # sets up the sensor port
69
+ def set_mode
70
+ @generate_light ? mode = NXTComm::LIGHT_ACTIVE : mode = NXTComm::LIGHT_INACTIVE
71
+ @nxt.set_input_mode(
72
+ NXTComm.const_get("SENSOR_#{@port}"),
73
+ mode,
74
+ NXTComm::PCTFULLSCALEMODE
75
+ )
76
+ end
77
+
78
+ # attempt to return the input_value requested
79
+ def method_missing(cmd)
80
+ @nxt.get_input_values(NXTComm.const_get("SENSOR_#{@port}"))[cmd]
81
+ end
82
+ end
@@ -0,0 +1,84 @@
1
+ # ruby-nxt Control Mindstorms NXT via Bluetooth Serial Port Connection
2
+ # Copyright (c) 2006 Tony Buser <tbuser@gmail.com> - http://juju.org
3
+ # Copyright (c) 2006 Matt Zukowski <matt@roughest.net> - http://blog.roughest.net
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 2 of the License
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software Foundation,
16
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
+
18
+ # Common methods used in motor commands.
19
+ module Commands
20
+ module Mixins
21
+ module Motor
22
+ # Sets the duration of the motor movement.
23
+ # The parameter should be a Hash like one of the following:
24
+ # m.duration = {:seconds => 4 }
25
+ # m.duration = {:degrees => 180 }
26
+ # m.duration = {:rotations => 2 }
27
+ # To set the duration to unlimited (i.e. rotate indefinitely) you should set
28
+ # the duration to :unlimited, although this is equivalent to simply setting it to nil;
29
+ # the following expressions are equivalent:
30
+ # m.duration = nil
31
+ # m.duration = :unlimited
32
+ # If you assign an integer, it will be assumed that you are specifying seconds;
33
+ # the following are equivalent:
34
+ # m.duration = 4
35
+ # m.duration = {:seconds => 4}
36
+ # If you assign a float, it will be assumed that youa re specifying rotations;
37
+ # the following expressions are equivalent:
38
+ # m.duration = 2.0
39
+ # m.duration = {:rotations => 2}
40
+ def duration=(duration)
41
+ if duration.kind_of? Hash
42
+ @duration = duration
43
+ elsif duration.kind_of? Integer
44
+ @duration = {:seconds => duration}
45
+ elsif duration.kind_of? Float
46
+ @duration = {:rotations => duration}
47
+ elsif duration == :unlimited
48
+ @duration = nil
49
+ else
50
+ @duration = duration
51
+ end
52
+ end
53
+
54
+ def duration
55
+ if duration.nil?
56
+ :unlimited
57
+ else
58
+ @duration
59
+ end
60
+ end
61
+
62
+ protected
63
+ def tacho_limit
64
+ if @duration.kind_of? Hash
65
+ if @duration[:rotations]
66
+ tacho_limit = @duration[:rotations] * 360
67
+ end
68
+
69
+ if @duration[:degrees]
70
+ tacho_limit = @duration[:degrees]
71
+ end
72
+
73
+ if @duration[:seconds]
74
+ tacho_limit = 0
75
+ end
76
+ else
77
+ tacho_limit = 0
78
+ end
79
+
80
+ tacho_limit
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,38 @@
1
+ # ruby-nxt Control Mindstorms NXT via Bluetooth Serial Port Connection
2
+ # Copyright (c) 2006 Tony Buser <tbuser@gmail.com> - http://juju.org
3
+ # Copyright (c) 2006 Matt Zukowski <matt@roughest.net> - http://blog.roughest.net
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 2 of the License
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program; if not, write to the Free Software Foundation,
16
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
+
18
+ # Common methods used in sensor commands.
19
+ module Commands
20
+ module Mixins
21
+ module Sensor
22
+ def port=(port)
23
+ @port = port
24
+ set_mode
25
+ end
26
+
27
+ def comparison=(op)
28
+ raise ArgumentError, "'#{op}' is not a valid comparison operator." unless op =~ /^([<>=]=?|!=)$/
29
+ @comparison = op
30
+ end
31
+
32
+ # Returns true or false based on comparison and trigger point.
33
+ def logic
34
+ eval "value_scaled #{@comparison} @trigger_point"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,136 @@
1
+ # ruby-nxt Control Mindstorms NXT via Bluetooth Serial Port Connection
2
+ # Copyright (C) 2006 Tony Buser <tbuser@gmail.com> - http://juju.org
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software Foundation,
15
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
+
17
+ require "nxt_comm"
18
+ require "commands/mixins/motor"
19
+
20
+ # Implements the "Motor" block in NXT-G
21
+ class Commands::Motor
22
+
23
+ include Commands::Mixins::Motor
24
+
25
+ attr_accessor :port
26
+ attr_accessor :direction
27
+ attr_accessor :steering
28
+ attr_accessor :action
29
+ attr_accessor :power
30
+ attr_accessor :control_power
31
+ attr_accessor :wait
32
+ attr_accessor :next_action
33
+
34
+ def initialize(nxt = NXTComm.new($DEV))
35
+ @nxt = nxt
36
+
37
+ # defaults the same as NXT-G
38
+ @port = :a
39
+ @direction = :forward
40
+ @action = :constant
41
+ @power = 75
42
+ @control_power = false
43
+ @duration = nil # Same as :unlimited
44
+ @wait = false
45
+ @next_action = :brake
46
+ end
47
+
48
+ # execute the Motor command based on the properties specified
49
+ def start
50
+ @nxt.reset_motor_position(NXTComm.const_get("MOTOR_#{@port.to_s.upcase}"))
51
+
52
+ if @direction == :stop
53
+ motor_power = 0
54
+ mode = NXTComm::COAST
55
+ run_state = NXTComm::MOTOR_RUN_STATE_IDLE
56
+ else
57
+ @direction == :forward ? motor_power = @power : motor_power = -@power
58
+ mode = NXTComm::MOTORON | NXTComm::BRAKE
59
+ run_state = NXTComm::MOTOR_RUN_STATE_RUNNING
60
+ end
61
+
62
+ turn_ratio = 0
63
+
64
+ if @control_power
65
+ mode |= NXTComm::REGULATED
66
+ reg_mode = NXTComm::REGULATION_MODE_MOTOR_SPEED
67
+ else
68
+ reg_mode = NXTComm::REGULATION_MODE_IDLE
69
+ end
70
+
71
+ if @duration
72
+ if @duration[:degrees] or @duration[:seconds]
73
+ case @action
74
+ when :constant
75
+ run_state = NXTComm::MOTOR_RUN_STATE_RUNNING
76
+ when :ramp_up
77
+ run_state = NXTComm::MOTOR_RUN_STATE_RAMPUP
78
+ when :ramp_down
79
+ run_state = NXTComm::MOTOR_RUN_STATE_RAMPDOWN
80
+ end
81
+ end
82
+ end
83
+
84
+ @nxt.set_output_state(
85
+ NXTComm.const_get("MOTOR_#{@port.to_s.upcase}"),
86
+ motor_power,
87
+ mode,
88
+ reg_mode,
89
+ turn_ratio,
90
+ run_state,
91
+ tacho_limit
92
+ )
93
+
94
+ if (@duration and @duration[:seconds]) or @wait
95
+ if @duration and @duration[:seconds]
96
+ sleep(@duration[:seconds])
97
+ else
98
+ until self.run_state == NXTComm::MOTOR_RUN_STATE_IDLE
99
+ sleep(0.25)
100
+ end
101
+ end
102
+ self.stop
103
+ end
104
+ end
105
+
106
+ # stop the Motor command based on the next_action property
107
+ def stop
108
+ if @next_action == :brake
109
+ @nxt.set_output_state(
110
+ NXTComm.const_get("MOTOR_#{@port.to_s.upcase}"),
111
+ 0,
112
+ NXTComm::MOTORON | NXTComm::BRAKE | NXTComm::REGULATED,
113
+ NXTComm::REGULATION_MODE_MOTOR_SPEED,
114
+ 0,
115
+ NXTComm::MOTOR_RUN_STATE_RUNNING,
116
+ 0
117
+ )
118
+ else
119
+ @nxt.set_output_state(
120
+ NXTComm.const_get("MOTOR_#{@port.to_s.upcase}"),
121
+ 0,
122
+ NXTComm::COAST,
123
+ NXTComm::REGULATION_MODE_IDLE,
124
+ 0,
125
+ NXTComm::MOTOR_RUN_STATE_IDLE,
126
+ 0
127
+ )
128
+ end
129
+ end
130
+
131
+ # attempt to return the output_state requested
132
+ def method_missing(cmd)
133
+ @nxt.get_output_state(NXTComm.const_get("MOTOR_#{@port.to_s.upcase}"))[cmd]
134
+ end
135
+
136
+ end
@@ -0,0 +1,210 @@
1
+ # ruby-nxt Control Mindstorms NXT via Bluetooth Serial Port Connection
2
+ # Copyright (C) 2006 Tony Buser <tbuser@gmail.com> - http://juju.org
3
+ #
4
+ # This program is free software; you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation; either version 2 of the License
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program; if not, write to the Free Software Foundation,
15
+ # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
+
17
+ require "nxt_comm"
18
+ require "commands/mixins/motor"
19
+
20
+ # Implements the "Move" block in NXT-G
21
+ class Commands::Move
22
+
23
+ include Commands::Mixins::Motor
24
+
25
+ attr_reader :ports
26
+ attr_accessor :direction
27
+ attr_accessor :left_motor, :right_motor
28
+ attr_accessor :power
29
+ attr_accessor :next_action
30
+
31
+ def initialize(nxt = NXTComm.new($DEV))
32
+ @nxt = nxt
33
+
34
+ # defaults the same as NXT-G
35
+ @ports = [:b, :c]
36
+ @direction = :forward
37
+ @power = 75
38
+ @duration = {:rotations => 1}
39
+ @next_action = :brake
40
+ self.turn_ratio = :straight
41
+ end
42
+
43
+ def ports=(value)
44
+ # make it flexible, let them specify just :a, or "A", or :a,:b to do two etc.
45
+ case value.class.to_s
46
+ when "Symbol" then @ports = [value]
47
+ when "String" then @ports = [value.intern]
48
+ when "Array" then @ports = value
49
+ else raise "Invalid port type #{value.class}"
50
+ end
51
+ end
52
+ alias port= ports=
53
+
54
+ def turn_ratio=(turn_ratio)
55
+ # simplified steering... if the user wants fine control, they should just specify -100 to 100
56
+ case turn_ratio
57
+ when :straight then @turn_ratio = 0
58
+ when :spin_left then @turn_ratio = -100
59
+ when :spin_right then @turn_ratio = 100
60
+ when :left then @turn_ratio = -50
61
+ when :right then @turn_ration = 50
62
+ else @turn_ratio = turn_ratio
63
+ end
64
+
65
+ # DEPRECATED: for backwards compatibility we parse the argument as a hash... I think though that this should be deprecated
66
+ if turn_ratio.kind_of? Hash
67
+ old_steering = turn_ratio
68
+ self.left_motor = old_steering[:left_motor] if old_steering.has_key? :left_motor
69
+ self.right_motor = old_steering[:right_motor] if old_steering.has_key? :right_motor
70
+ if old_steering[:power]
71
+ self.turn_ratio = old_steering[:power] * (old_steering[:direction] == :left ? -1 : 1)
72
+ else
73
+ self.turn_ratio = old_steering[:direction]
74
+ end
75
+ end
76
+ end
77
+ alias steering= turn_ratio=
78
+
79
+ def turn_ratio
80
+ if @ports.size > 1
81
+ @turn_ratio
82
+ else
83
+ 0
84
+ end
85
+ end
86
+ alias steering turn_ratio
87
+
88
+
89
+ # execute the Move command based on the properties specified
90
+ def start
91
+ @ports.each do |p|
92
+ @nxt.reset_motor_position(NXTComm.const_get("MOTOR_#{p.to_s.upcase}"))
93
+ end
94
+
95
+ if @direction == :stop
96
+ motor_power = 0
97
+ mode = NXTComm::COAST
98
+ run_state = NXTComm::MOTOR_RUN_STATE_IDLE
99
+ else
100
+ @direction == :forward ? motor_power = @power : motor_power = -@power
101
+ mode = NXTComm::MOTORON | NXTComm::BRAKE
102
+ run_state = NXTComm::MOTOR_RUN_STATE_RUNNING
103
+ end
104
+
105
+ if @ports.size == 2
106
+ mode |= NXTComm::REGULATED
107
+ reg_mode = NXTComm::REGULATION_MODE_MOTOR_SYNC
108
+ else
109
+ reg_mode = NXTComm::REGULATION_MODE_IDLE
110
+ end
111
+
112
+ if @ports.include?(:a) and @ports.include?(:b) and @ports.include?(:c)
113
+ @nxt.set_output_state(
114
+ NXTComm::MOTOR_ALL,
115
+ motor_power,
116
+ mode,
117
+ reg_mode,
118
+ turn_ratio,
119
+ run_state,
120
+ tacho_limit
121
+ )
122
+ else
123
+ @ports.each do |p|
124
+ @nxt.set_output_state(
125
+ NXTComm.const_get("MOTOR_#{p.to_s.upcase}"),
126
+ motor_power,
127
+ mode,
128
+ reg_mode,
129
+ turn_ratio,
130
+ run_state,
131
+ tacho_limit
132
+ )
133
+ end
134
+ end
135
+
136
+ unless @duration.nil?
137
+ if @duration[:seconds]
138
+ sleep(@duration[:seconds])
139
+ else
140
+ until self.run_state[@ports[0]] == NXTComm::MOTOR_RUN_STATE_IDLE
141
+ sleep(0.25)
142
+ end
143
+ end
144
+ self.stop
145
+ end
146
+ end
147
+
148
+ # stop the Move command based on the next_action property
149
+ def stop
150
+ if @next_action == :brake
151
+ if @ports.include?(:a) and @ports.include?(:b) and @ports.include?(:c)
152
+ @nxt.set_output_state(
153
+ NXTComm::MOTOR_ALL,
154
+ 0,
155
+ NXTComm::MOTORON | NXTComm::BRAKE | NXTComm::REGULATED,
156
+ NXTComm::REGULATION_MODE_MOTOR_SPEED,
157
+ 0,
158
+ NXTComm::MOTOR_RUN_STATE_RUNNING,
159
+ 0
160
+ )
161
+ else
162
+ @ports.each do |p|
163
+ @nxt.set_output_state(
164
+ NXTComm.const_get("MOTOR_#{p.to_s.upcase}"),
165
+ 0,
166
+ NXTComm::MOTORON | NXTComm::BRAKE | NXTComm::REGULATED,
167
+ NXTComm::REGULATION_MODE_MOTOR_SPEED,
168
+ 0,
169
+ NXTComm::MOTOR_RUN_STATE_RUNNING,
170
+ 0
171
+ )
172
+ end
173
+ end
174
+ else
175
+ if @ports.include?(:a) and @ports.include?(:b) and @ports.include?(:c)
176
+ @nxt.set_output_state(
177
+ NXTComm::MOTOR_ALL,
178
+ 0,
179
+ NXTComm::COAST,
180
+ NXTComm::REGULATION_MODE_IDLE,
181
+ 0,
182
+ NXTComm::MOTOR_RUN_STATE_IDLE,
183
+ 0
184
+ )
185
+ else
186
+ @ports.each do |p|
187
+ @nxt.set_output_state(
188
+ NXTComm.const_get("MOTOR_#{p.to_s.upcase}"),
189
+ 0,
190
+ NXTComm::COAST,
191
+ NXTComm::REGULATION_MODE_IDLE,
192
+ 0,
193
+ NXTComm::MOTOR_RUN_STATE_IDLE,
194
+ 0
195
+ )
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ # attempt to return the output_state requested
202
+ def method_missing(cmd)
203
+ states = {}
204
+ @ports.each do |p|
205
+ states[p] = @nxt.get_output_state(NXTComm.const_get("MOTOR_#{p.to_s.upcase}"))[cmd]
206
+ end
207
+ states
208
+ end
209
+
210
+ end