flying_robot 0.0.3

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,14 @@
1
+ == 0.0.1 2009-04-03
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+
6
+ == 0.0.2 2009-07-08
7
+
8
+ * 1 major enhancement:
9
+ * Plugin support for all hardware included with Blimpduino, including L293D and Maxsonar Ultrasonic range finder
10
+
11
+ == 0.0.3 2009-11-14
12
+
13
+ * 1 major enhancement:
14
+ * Update parser for aileron command support
@@ -0,0 +1,29 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ README.txt
6
+ Rakefile
7
+ app_generators/flying_robot/USAGE
8
+ app_generators/flying_robot/flying_robot_generator.rb
9
+ app_generators/flying_robot/templates/plugins/Hmc6352_compass.rb
10
+ app_generators/flying_robot/templates/plugins/battery.rb
11
+ app_generators/flying_robot/templates/plugins/flying_robot.rb
12
+ app_generators/flying_robot/templates/plugins/pololu_ir_receiver.rb
13
+ app_generators/flying_robot/templates/plugins/pololu_micro_serial_controller.rb
14
+ app_generators/flying_robot/templates/plugins/pololu_qik_dual_serial_motor_controller.rb
15
+ app_generators/flying_robot/templates/plugins/L293d.rb
16
+ app_generators/flying_robot/templates/plugins/maxsonar.rb
17
+ app_generators/flying_robot/templates/sketch.rb.erb
18
+ bin/flying_robot
19
+ flying_robot.gemspec
20
+ lib/flying_robot.rb
21
+ script/console
22
+ script/destroy
23
+ script/generate
24
+ spec/flying_robot_spec.rb
25
+ spec/spec.opts
26
+ spec/spec_helper.rb
27
+ tasks/rspec.rake
28
+ test/test_flying_robot_generator.rb
29
+ test/test_generator_helper.rb
@@ -0,0 +1,3 @@
1
+
2
+ For more information on flying_robot, see http://flyingrobo.com
3
+
@@ -0,0 +1,58 @@
1
+ = flying_robot
2
+
3
+ http://github.com/deadprogrammer/flying_robot
4
+
5
+ == DESCRIPTION:
6
+
7
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Plugins for RAD for cool UAV-related hardware, like Pololu motor controllers and Honeywell digital compass
12
+ * Complete support for Blimpduino hardware
13
+ * More plugins coming soon to support other available Arduino-based systems like ArduPilot
14
+
15
+ == SYNOPSIS:
16
+
17
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV). It includes plugin support for the following hardware:
18
+
19
+ * LiPo Battery Voltage
20
+ * Honeywell HMC6352 Digital Compass
21
+ * L293D Motor Driver
22
+ * Maxbotix Maxsonar Ultrasonic Range Finder
23
+ * Pololu Infrared Detector Array
24
+ * Pololu Micro Serial Motor Controller
25
+ * Pololu QIK Dual Serial Motor Controller
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * sudo gem install rad
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install deadprogrammer-flying_robot
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2009 Ron Evans
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,58 @@
1
+ = flying_robot
2
+
3
+ http://github.com/deadprogrammer/flying_robot
4
+
5
+ == DESCRIPTION:
6
+
7
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Plugins for RAD for cool UAV-related hardware, like Pololu motor controllers and Honeywell digital compass
12
+ * Complete support for Blimpduino hardware
13
+ * More plugins coming soon to support other available Arduino-based systems like ArduPilot
14
+
15
+ == SYNOPSIS:
16
+
17
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV). It includes plugin support for the following hardware:
18
+
19
+ * LiPo Battery Voltage
20
+ * Honeywell HMC6352 Digital Compass
21
+ * L293D Motor Driver
22
+ * Maxbotix Maxsonar Ultrasonic Range Finder
23
+ * Pololu Infrared Detector Array
24
+ * Pololu Micro Serial Motor Controller
25
+ * Pololu QIK Dual Serial Motor Controller
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * sudo gem install rad
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install deadprogrammer-flying_robot
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2009 Ron Evans
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+
4
+ Hoe.spec 'flying_robot' do
5
+ developer('Ron Evans', 'ron dot evans at gmail dot com')
6
+
7
+ self.rubyforge_name = 'deadprogrammer'
8
+ end
9
+
10
+ task :cultivate do
11
+ system "touch Manifest.txt; rake check_manifest | grep -v \"(in \" | patch"
12
+ system "rake debug_gem | grep -v \"(in \" > `basename \\`pwd\\``.gemspec"
13
+ end
@@ -0,0 +1,7 @@
1
+ Description:
2
+
3
+ flying_robot takes a standard Ruby Arduino Development (RAD) project, and turns it into a Unmanned Aerial Vehicle (UAV)
4
+
5
+ Usage:
6
+
7
+ flying_robot [appname]
@@ -0,0 +1,75 @@
1
+ class FlyingRobotGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ extract_options
16
+ end
17
+
18
+ def manifest
19
+ record do |m|
20
+ # Ensure appropriate folder(s) exists
21
+ m.directory ''
22
+ BASEDIRS.each { |path| m.directory path }
23
+
24
+ # create stub
25
+ m.template 'sketch.rb.erb' , "#{base_name}.rb"
26
+
27
+ # copy plugins
28
+ m.file "plugins/battery.rb", "vendor/plugins/battery.rb"
29
+ m.file "plugins/flying_robot.rb", "vendor/plugins/flying_robot.rb"
30
+ m.file "plugins/Hmc6352_compass.rb", "vendor/plugins/Hmc6352_compass.rb"
31
+ m.file "plugins/pololu_ir_receiver.rb", "vendor/plugins/pololu_ir_receiver.rb"
32
+ m.file "plugins/pololu_micro_serial_controller.rb", "vendor/plugins/pololu_micro_serial_controller.rb"
33
+ m.file "plugins/pololu_qik_dual_serial_motor_controller.rb", "vendor/plugins/pololu_qik_dual_serial_motor_controller.rb"
34
+ m.file "plugins/L293d.rb", "vendor/plugins/L293d.rb"
35
+ m.file "plugins/maxsonar.rb", "vendor/plugins/maxsonar.rb"
36
+
37
+ m.dependency "install_rubigen_scripts", [destination_root, 'flying_robot'],
38
+ :shebang => options[:shebang], :collision => :force
39
+ end
40
+ end
41
+
42
+ protected
43
+ def banner
44
+ <<-EOS
45
+ Creates a ...
46
+
47
+ USAGE: #{spec.name} name
48
+ EOS
49
+ end
50
+
51
+ def add_options!(opts)
52
+ opts.separator ''
53
+ opts.separator 'Options:'
54
+ # For each option below, place the default
55
+ # at the top of the file next to "default_options"
56
+ # opts.on("-a", "--author=\"Your Name\"", String,
57
+ # "Some comment about this option",
58
+ # "Default: none") { |o| options[:author] = o }
59
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
60
+ end
61
+
62
+ def extract_options
63
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
64
+ # Templates can access these value via the attr_reader-generated methods, but not the
65
+ # raw instance variable value.
66
+ # @author = options[:author]
67
+ end
68
+
69
+ # Installation skeleton. Intermediate directories are automatically
70
+ # created so don't sweat their absence here.
71
+ BASEDIRS = %w(
72
+ vendor/plugins
73
+ examples
74
+ )
75
+ end
@@ -0,0 +1,56 @@
1
+ # Plugin for Ruby Arduino Development that allows use of the HMC6352 Compass module
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ # Based on code taken from the SparkFun forums: http://forum.sparkfun.com/viewtopic.php?t=6236
5
+ class Hmc6352Compass < ArduinoPlugin
6
+ include_wire
7
+
8
+ external_variables "int HMC6352Address = 0x42"
9
+ external_variables "byte headingData[2]"
10
+ external_variables "int headingValue = 0"
11
+
12
+ # Shift the device's documented slave address (0x42) 1 bit right
13
+ # This compensates for how the TWI library only wants the
14
+ # 7 most significant bits (with the high bit padded with 0)
15
+ # This results in 0x21 as the address to pass to TWI
16
+ external_variables "int slaveAddress = HMC6352Address >> 1"
17
+
18
+ void prepare_compass() {
19
+ // hack to reference plugin, copied this trick from twitter plugin
20
+ }
21
+
22
+ // The whole number part of the heading
23
+ int heading()
24
+ {
25
+ return int (headingValue / 10) ;
26
+ }
27
+
28
+ // The fractional part of the heading
29
+ int heading_fractional()
30
+ {
31
+ return int (headingValue % 10) ;
32
+ }
33
+
34
+ void read_compass()
35
+ {
36
+ // Send a "A" command to the HMC6352
37
+ // This requests the current heading data
38
+ Wire.beginTransmission(slaveAddress);
39
+ Wire.send("A"); // The "Get Data" command
40
+ Wire.endTransmission();
41
+ delay(10); // The HMC6352 needs at least a 70us (microsecond) delay
42
+ // after this command. Using 10ms just makes it safe
43
+ // Read the 2 heading bytes, MSB first
44
+ // The resulting 16bit word is the compass heading in 10ths of a degree
45
+ // For example: a heading of 1345 would be 134.5 degrees
46
+ Wire.requestFrom(slaveAddress, 2); // Request the 2 byte heading (MSB comes first)
47
+ int i = 0;
48
+ while(Wire.available() && i < 2)
49
+ {
50
+ headingData[i] = Wire.receive();
51
+ i++;
52
+ }
53
+ headingValue = headingData[0]*256 + headingData[1]; // Put the MSB and LSB together
54
+ }
55
+
56
+ end
@@ -0,0 +1,27 @@
1
+ # Plugin for Ruby Arduino Development that allows use of the L293D motor controller
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ #
5
+ # Adapted from code written by Jordi Muñoz for the Blimpduino project
6
+ # http://blimpduino.googlecode.com/svn/trunk/Motors.pde
7
+ #
8
+ class L293d < ArduinoPlugin
9
+ plugin_directives "#define FORWARD 1"
10
+ plugin_directives "#define REVERSE 0"
11
+
12
+ void L293_send_command(int directionPin, int speedPin, byte direction, byte speed)
13
+ {
14
+ direction = constrain(direction, 0, 1);
15
+ speed = constrain(speed, 0, 127);
16
+
17
+ if (direction == FORWARD) {
18
+ digitalWrite(directionPin, LOW);
19
+ analogWrite(speedPin, speed);
20
+ } else {
21
+ speed = 255 - speed ;
22
+ digitalWrite(directionPin, HIGH);
23
+ analogWrite(speedPin, speed);
24
+ }
25
+ }
26
+
27
+ end
@@ -0,0 +1,41 @@
1
+ # Plugin for Ruby Arduino Development that reads a battery voltage from a power source that has been connected
2
+ # to one of the Arduino's analog pins. Note that you probably need to reduce the voltage considerably with a resistor (10K value?)
3
+ # before feeding it to the analog pin. You should also add another 10K resistor as a pull-down from the pin to ground.
4
+ #
5
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
6
+ # http://github.com/deadprogrammer/flying_robot
7
+ #
8
+ # Adapted from code written by Jordi Muñoz for the Blimpduino project
9
+ # http://code.google.com/p/blimpduino/source/browse/trunk/BlimpDuino_v4.pde)
10
+ #
11
+ class Battery < ArduinoPlugin
12
+ external_variables "float average_battery = 0.0"
13
+ external_variables "bool battery_init_completed"
14
+
15
+ add_to_setup "battery_init_completed = false;"
16
+
17
+ # bogus function here to make RAD happy
18
+ void battery_test() {
19
+ }
20
+
21
+ // initialize the battery reading
22
+ void init_battery(int pin) {
23
+ average_battery = analogRead(pin);
24
+ }
25
+
26
+ // get the current voltage
27
+ // TODO: allow user to set constants for different expected battery voltages
28
+ float voltage(int pin)
29
+ {
30
+ if (! battery_init_completed) {
31
+ init_battery(pin);
32
+ }
33
+
34
+ average_battery=(((float) average_battery * 0.99) + (float)((float) analogRead(pin) * 0.01)); // Jordi called it dynamic average
35
+
36
+ float battery_voltage=(float)((float) average_battery * (float)4.887586) * (float)2; // converting values to millivolts..,
37
+
38
+ return battery_voltage ;
39
+ }
40
+
41
+ end
@@ -0,0 +1,282 @@
1
+ # Plugin for Ruby Arduino Development that parses the flying_robot command set from any source of input to the serial port
2
+ # Written by Ron Evans (http://deadprogrammersociety.com) for the flying_robot project
3
+ #
4
+ # In order to implement a sketch that uses the flying_robot parser, you need to implement the methods that make up its interface
5
+ # so that it will respond to the standard command set.
6
+ #
7
+ # The following commands are supported:
8
+ # (h)ail - See if the UAV can still respond. Should send "Roger" back.
9
+ # (s)tatus - Grab a snapshot of all instrument readings plus any other status info that the UAV can support
10
+ # (e)levators - Set the elevators. The command supports two parameters:
11
+ # direction - enter 'u' for up, 'c' for centered, or 'd' for down
12
+ # deflection - enter an angle between 0 and 90 degrees
13
+ # (r)udder - Set the rudder. This command supports two parameters:
14
+ # direction - enter 'l' for left, 'c' for centered, or 'r' for right
15
+ # deflection - enter an angle between 0 and 90 degrees
16
+ # (a)ilerons - Set the ailerons. This command supports two parameters:
17
+ # direction - enter 'l' for left, 'c' for centered, or 'r' for right
18
+ # deflection - enter an angle between 0 and 90 degrees
19
+ # (t)hrottle - Set the throttle. This command supports two parameters:
20
+ # direction - enter 'f' for forward, or 'r' for reverse
21
+ # speed - enter a percentage from 0 to 100
22
+ # (i)nstruments - Read the current data for one of the installed instruments on the UAV. This command supports one parameter:
23
+ # id - enter an integer for which instrment readings should be returned from. If there is not an instrument installed
24
+ # for that id 'Invalid instrument' will be returned
25
+ # (p)rogram - Engage whatever autopilot program is available, if any. This command supports one parameter:
26
+ # id - enter an integer for which autopilot routine should be used. Enter 0 to cancel autopilot
27
+ #
28
+ class FlyingRobot < ArduinoPlugin
29
+ # used for parsing input commands
30
+ external_variables "bool current_command_received_complete"
31
+ external_variables "int current_command_length"
32
+ external_variables "char command_buffer[120]"
33
+
34
+ # the parsed command
35
+ external_variables "char command_code[1]"
36
+ external_variables "char direction_code[1]"
37
+ external_variables "char instrument_code[1]"
38
+ external_variables "char autopilot_code[1]"
39
+ external_variables "int command_value"
40
+
41
+ # current elevator values
42
+ external_variables "char elevator_direction[1]"
43
+ external_variables "int elevator_deflection = 0"
44
+
45
+ # current rudder values
46
+ external_variables "char rudder_direction[1]"
47
+ external_variables "int rudder_deflection = 0"
48
+
49
+ # current aileron values
50
+ external_variables "char aileron_direction[1]"
51
+ external_variables "int aileron_deflection = 0"
52
+
53
+ # current throttle values
54
+ external_variables "char throttle_direction[1]"
55
+ external_variables "int throttle_speed = 0"
56
+
57
+ # autopilot
58
+ external_variables "bool autopilot_engaged"
59
+
60
+ # initialize parser vars
61
+ add_to_setup "current_command_received_complete = false; elevator_direction[0] = 'c'; rudder_direction[0] = 'c'; throttle_direction[0] = 'f'; autopilot_engaged = false;"
62
+
63
+ # this is a hack to get the plugin included, that I got from the twitter_connect example
64
+ void be_flying_robot(){}
65
+
66
+ boolean current_command_received_is_complete() {
67
+ return current_command_received_complete == true ;
68
+ }
69
+
70
+ char current_command() {
71
+ return command_code[0];
72
+ }
73
+
74
+ char current_command_direction() {
75
+ return direction_code[0];
76
+ }
77
+
78
+ char current_command_instrument() {
79
+ return instrument_code[0];
80
+ }
81
+
82
+ char current_command_autopilot() {
83
+ return autopilot_code[0];
84
+ }
85
+
86
+ int current_command_value() {
87
+ return command_value ;
88
+ }
89
+
90
+ char current_elevator_direction() {
91
+ return elevator_direction[0];
92
+ }
93
+
94
+ int current_elevator_deflection() {
95
+ return elevator_deflection ;
96
+ }
97
+
98
+ char current_aileron_direction() {
99
+ return aileron_direction[0];
100
+ }
101
+
102
+ int current_aileron_deflection() {
103
+ return aileron_deflection ;
104
+ }
105
+
106
+ char current_rudder_direction() {
107
+ return rudder_direction[0];
108
+ }
109
+
110
+ int current_rudder_deflection() {
111
+ return rudder_deflection ;
112
+ }
113
+
114
+ char current_throttle_direction() {
115
+ return throttle_direction[0];
116
+ }
117
+
118
+ int current_throttle_speed() {
119
+ return throttle_speed ;
120
+ }
121
+
122
+ boolean is_autopilot_on() {
123
+ return autopilot_engaged == true ;
124
+ }
125
+
126
+ void autopilot_on() {
127
+ autopilot_engaged = true;
128
+ }
129
+
130
+ void autopilot_off() {
131
+ autopilot_engaged = false;
132
+ }
133
+
134
+ void clear_command_buffer() {
135
+ for(int i=0; i<120; i++){
136
+ command_buffer[i] = 0 ;
137
+ }
138
+
139
+ command_code[0] = 0 ;
140
+ direction_code[0] = 0 ;
141
+ instrument_code[0] = 0 ;
142
+ current_command_length = 0 ;
143
+ current_command_received_complete = false ;
144
+ }
145
+
146
+ void parse_command_code() {
147
+ if(current_command_length == 0) {
148
+ command_code[0] = 0;
149
+ } else {
150
+ command_code[0] = command_buffer[0];
151
+ }
152
+ }
153
+
154
+ void parse_direction_code() {
155
+ if(current_command_length >= 3) {
156
+ direction_code[0] = command_buffer[2];
157
+ } else {
158
+ direction_code[0] = 0;
159
+ }
160
+ }
161
+
162
+ void parse_instrument_code() {
163
+ if(current_command_length >= 3) {
164
+ instrument_code[0] = command_buffer[2];
165
+ } else {
166
+ instrument_code[0] = 0;
167
+ }
168
+ }
169
+
170
+ void parse_autopilot_code() {
171
+ if(current_command_length >= 3) {
172
+ autopilot_code[0] = command_buffer[2];
173
+ } else {
174
+ autopilot_code[0] = 0;
175
+ }
176
+ }
177
+
178
+ void parse_command_value(int start) {
179
+ if(current_command_length >= start + 1) {
180
+ command_value = atoi(command_buffer + start);
181
+ } else {
182
+ command_value = 0 ;
183
+ }
184
+ }
185
+
186
+ void get_command() {
187
+ if(current_command_received_complete) {
188
+ clear_command_buffer();
189
+ }
190
+
191
+ while(Serial.available() > 0) {
192
+ command_buffer[current_command_length] = Serial.read();
193
+ if(command_buffer[current_command_length] == '\r') {
194
+ current_command_received_complete = true ;
195
+ parse_command_code();
196
+ return;
197
+ } else {
198
+ current_command_length++ ;
199
+ }
200
+ }
201
+ }
202
+
203
+ // used to echo the commands being received via serial
204
+ void print_current_command(const char* cmd, int val) {
205
+ Serial.print(cmd);
206
+ Serial.print(" command - direction:");
207
+ Serial.print(current_command_direction());
208
+ Serial.print(" value:");
209
+ Serial.println(val);
210
+ }
211
+
212
+ void dispatch_command() {
213
+ if(!current_command_received_is_complete()) {
214
+ return;
215
+ }
216
+
217
+ char cmd = current_command();
218
+
219
+ if (cmd == 'h') {
220
+ hail();
221
+ } else if (cmd == 's') {
222
+ status();
223
+ } else if (cmd == 'e') {
224
+ parse_direction_code();
225
+ parse_command_value(4);
226
+ elevator_direction[0] = current_command_direction();
227
+ elevator_deflection = current_command_value();
228
+ if (elevator_deflection > 90) {
229
+ elevator_deflection = 90 ;
230
+ }
231
+
232
+ elevators();
233
+ } else if (cmd == 'r') {
234
+ parse_direction_code();
235
+ parse_command_value(4);
236
+ rudder_direction[0] = current_command_direction();
237
+ rudder_deflection = current_command_value();
238
+ if (rudder_deflection > 90) {
239
+ rudder_deflection = 90 ;
240
+ }
241
+
242
+ rudder();
243
+ } else if (cmd == 'a') {
244
+ parse_direction_code();
245
+ parse_command_value(4);
246
+ aileron_direction[0] = current_command_direction();
247
+ aileron_deflection = current_command_value();
248
+ if (aileron_deflection > 90) {
249
+ aileron_deflection = 90 ;
250
+ }
251
+
252
+ ailerons();
253
+ } else if (cmd == 't') {
254
+ parse_direction_code();
255
+ parse_command_value(4);
256
+ throttle_direction[0] = current_command_direction();
257
+ throttle_speed = current_command_value();
258
+ if (throttle_speed > 100) {
259
+ throttle_speed = 100 ;
260
+ }
261
+
262
+ throttle();
263
+ } else if (cmd == 'i') {
264
+ parse_instrument_code();
265
+ instruments();
266
+ } else if (cmd == 'p') {
267
+ parse_autopilot_code();
268
+ if (autopilot_code[0] == '0') {
269
+ autopilot_off();
270
+ }
271
+
272
+ autopilot();
273
+ } else {
274
+ Serial.println("Invalid command");
275
+ }
276
+ }
277
+
278
+ void process_command() {
279
+ get_command();
280
+ dispatch_command();
281
+ }
282
+ end