5ae37974ec5538cb789f58a284e81d312997c5e4
[aversive.git] / projects / microb2010 / mainboard / strat.c
1 /*
2  *  Copyright Droids, Microb Technology (2009)
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, or
7  *  (at your option) any later version.
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
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  *  Revision : $Id: strat.c,v 1.6 2009-11-08 17:24:33 zer0 Exp $
19  *
20  *  Olivier MATZ <zer0@droids-corp.org>
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <math.h>
27
28 #include <aversive/pgmspace.h>
29 #include <aversive/queue.h>
30 #include <aversive/wait.h>
31 #include <aversive/error.h>
32
33 #include <ax12.h>
34 #include <uart.h>
35 #include <pwm_ng.h>
36 #include <clock_time.h>
37 #include <spi.h>
38
39 #include <pid.h>
40 #include <quadramp.h>
41 #include <control_system_manager.h>
42 #include <trajectory_manager.h>
43 #include <vect_base.h>
44 #include <lines.h>
45 #include <polygon.h>
46 #include <obstacle_avoidance.h>
47 #include <blocking_detection_manager.h>
48 #include <robot_system.h>
49 #include <position_manager.h>
50
51 #include <diagnostic.h>
52
53 #include <rdline.h>
54 #include <parse.h>
55
56 #include "../common/i2c_commands.h"
57 #include "i2c_protocol.h"
58 #include "main.h"
59 #include "strat.h"
60 #include "strat_db.h"
61 #include "strat_base.h"
62 #include "strat_corn.h"
63 #include "strat_utils.h"
64 #include "sensor.h"
65 #include "actuator.h"
66
67 #define COL_DISP_MARGIN 400 /* stop 40 cm in front of dispenser */
68 #define COL_SCAN_PRE_MARGIN 250
69
70 static volatile uint8_t strat_running = 0;
71 static volatile uint8_t want_pack = 0;
72 struct strat_conf strat_conf;
73
74 /*************************************************************/
75
76 /*                  INIT                                     */
77
78 /*************************************************************/
79
80 /* called before each strat, and before the start switch */
81 void strat_preinit(void)
82 {
83         time_reset();
84         interrupt_traj_reset();
85         mainboard.flags =  DO_ENCODERS | DO_CS | DO_RS |
86                 DO_POS | DO_BD | DO_POWER;
87
88         //i2c_cobboard_mode_init();
89         strat_conf_dump(__FUNCTION__);
90         strat_db_dump(__FUNCTION__);
91 }
92
93 void strat_conf_dump(const char *caller)
94 {
95         if (!strat_conf.dump_enabled)
96                 return;
97
98         printf_P(PSTR("-- conf --\r\n"));
99
100 }
101
102 void strat_event_enable(void)
103 {
104         strat_running = 1;
105 }
106
107 void strat_event_disable(void)
108 {
109         strat_running = 0;
110 }
111
112 /* call it just before launching the strat */
113 void strat_init(void)
114 {
115 #ifdef HOST_VERSION
116         position_set(&mainboard.pos, 298.16,
117                      COLOR_Y(308.78), COLOR_A(70.00));
118 #endif
119
120         /* we consider that the color is correctly set */
121         strat_running = 1;
122         strat_db_init();
123         strat_set_speed(SPEED_DIST_FAST, SPEED_ANGLE_FAST);
124         time_reset();
125         interrupt_traj_reset();
126
127         i2c_cobboard_set_mode(I2C_COBBOARD_MODE_HARVEST);
128         i2c_ballboard_set_mode(I2C_BALLBOARD_MODE_HARVEST);
129
130         /* used in strat_base for END_TIMER */
131         mainboard.flags = DO_ENCODERS | DO_CS | DO_RS |
132                 DO_POS | DO_BD | DO_TIMER | DO_POWER;
133 }
134
135 /* call it after each strat */
136 void strat_exit(void)
137 {
138 #ifndef HOST_VERSION
139         uint8_t flags;
140 #endif
141
142         strat_running = 0;
143         mainboard.flags &= ~(DO_TIMER);
144         strat_hardstop();
145         time_reset();
146         wait_ms(100);
147 #ifndef HOST_VERSION
148         IRQ_LOCK(flags);
149         mainboard.flags &= ~(DO_CS);
150         IRQ_UNLOCK(flags);
151         pwm_ng_set(LEFT_PWM, 0);
152         pwm_ng_set(RIGHT_PWM, 0);
153 #endif
154 }
155
156 /* called periodically (10ms) */
157 void strat_event(void *dummy)
158 {
159         uint8_t flags;
160         int8_t lcob_near, rcob_near;
161         uint8_t lcob, rcob;
162         uint8_t lidx, ridx;
163
164         /* ignore when strat is not running */
165         if (strat_running == 0)
166                 return;
167
168         IRQ_LOCK(flags);
169         lcob = ballboard.lcob;
170         ballboard.lcob = I2C_COB_NONE;
171         rcob = ballboard.rcob;
172         ballboard.rcob = I2C_COB_NONE;
173         IRQ_UNLOCK(flags);
174
175         /* XXX take opponent position into account */
176
177 #ifdef HOST_VERSION
178         if (time_get_s() == 15)
179                 cobboard.cob_count = 5;
180         if (time_get_s() == 16)
181                 cobboard.cob_count = 0;
182         if (time_get_s() == 25)
183                 cobboard.cob_count = 5;
184 #endif
185
186         /* detect cob on left side */
187         lcob_near = corn_is_near(&lidx, I2C_LEFT_SIDE);
188         if (lcob_near && lcob != I2C_COB_NONE) {
189                 if (strat_db.corn_table[lidx]->corn.color == I2C_COB_UNKNOWN)
190                         DEBUG(E_USER_STRAT, "lcob %s %d",
191                               lcob == I2C_COB_WHITE ? "white" : "black", lidx);
192                 corn_set_color(strat_db.corn_table[lidx], lcob);
193         }
194
195         /* detect cob on right side */
196         rcob_near = corn_is_near(&ridx, I2C_RIGHT_SIDE);
197         if (rcob_near && rcob != I2C_COB_NONE) {
198                 if (strat_db.corn_table[ridx]->corn.color == I2C_COB_UNKNOWN)
199                         DEBUG(E_USER_STRAT, "rcob %s %d",
200                               rcob == I2C_COB_WHITE ? "white" : "black", ridx);
201                 corn_set_color(strat_db.corn_table[ridx], rcob);
202         }
203
204         /* control the cobboard mode for left spickle */
205         if (get_cob_count() >= 5 || want_pack) {
206                 if (strat_db.corn_table[lidx]->corn.color != I2C_COB_WHITE &&
207                     strat_db.corn_table[lidx]->corn.color != I2C_COB_BLACK)
208                         i2c_cobboard_pack(I2C_LEFT_SIDE);
209         }
210         else {
211                 if (strat_db.corn_table[lidx]->corn.color == I2C_COB_WHITE)
212                         i2c_cobboard_autoharvest(I2C_LEFT_SIDE);
213                 else if (strat_db.corn_table[lidx]->corn.color == I2C_COB_BLACK)
214                         i2c_cobboard_deploy_nomove(I2C_LEFT_SIDE);
215                 else
216                         i2c_cobboard_deploy(I2C_LEFT_SIDE);
217         }
218
219         /* control the cobboard mode for right spickle */
220         if (get_cob_count() >= 5 || want_pack) {
221                 if (strat_db.corn_table[lidx]->corn.color != I2C_COB_WHITE &&
222                     strat_db.corn_table[lidx]->corn.color != I2C_COB_BLACK)
223                         i2c_cobboard_pack(I2C_RIGHT_SIDE);
224         }
225         else {
226                 if (strat_db.corn_table[lidx]->corn.color == I2C_COB_WHITE)
227                         i2c_cobboard_autoharvest(I2C_RIGHT_SIDE);
228                 else if (strat_db.corn_table[lidx]->corn.color == I2C_COB_BLACK)
229                         i2c_cobboard_deploy_nomove(I2C_RIGHT_SIDE);
230                 else
231                         i2c_cobboard_deploy(I2C_RIGHT_SIDE);
232         }
233
234         /* limit speed when opponent is near */
235         strat_limit_speed();
236 }
237
238
239 static uint8_t strat_harvest(void)
240 {
241         return 0;
242 }
243
244 static uint8_t strat_eject(void)
245 {
246         uint8_t err;
247
248         //XXX return vals
249         strat_set_speed(600, SPEED_ANGLE_SLOW);
250
251         trajectory_goto_xy_abs(&mainboard.traj, 2625, COLOR_Y(1847));
252         err = wait_traj_end(TRAJ_FLAGS_NO_NEAR);
253         trajectory_a_abs(&mainboard.traj, COLOR_A(70));
254         err = wait_traj_end(TRAJ_FLAGS_NO_NEAR);
255
256         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
257         strat_hardstop();
258
259         /* ball ejection */
260         trajectory_a_abs(&mainboard.traj, COLOR_A(90));
261         i2c_ballboard_set_mode(I2C_BALLBOARD_MODE_EJECT);
262         time_wait_ms(2000);
263
264         /* half turn */
265         i2c_cobboard_pack(I2C_LEFT_SIDE);
266         i2c_cobboard_pack(I2C_RIGHT_SIDE);
267         trajectory_a_rel(&mainboard.traj, COLOR_A(180));
268         err = wait_traj_end(END_INTR|END_TRAJ);
269
270         /* cob ejection */
271         trajectory_d_rel(&mainboard.traj, -100);
272         err = wait_traj_end(END_INTR|END_TRAJ);
273         strat_running = ;
274         i2c_cobboard_set_mode(I2C_COBBOARD_MODE_EJECT);
275         time_wait_ms(2000);
276
277         return 0;
278 }
279
280 static uint8_t strat_beginning(void)
281 {
282         uint8_t err;
283
284         strat_set_acc(ACC_DIST, ACC_ANGLE);
285 #ifdef HOST_VERSION
286         strat_set_speed(600, SPEED_ANGLE_FAST);
287 #else
288         /* 250 */
289         strat_set_speed(250, SPEED_ANGLE_FAST);
290 #endif
291
292         // strat_set_speed(600, 60); /* OK */
293         strat_set_speed(250, 28); /* OK */
294
295         trajectory_d_a_rel(&mainboard.traj, 1000, COLOR_A(20));
296         err = WAIT_COND_OR_TRAJ_END(trajectory_angle_finished(&mainboard.traj),
297                                     TRAJ_FLAGS_STD);
298
299         strat_set_acc(ACC_DIST, ACC_ANGLE);
300         strat_set_speed(250, SPEED_ANGLE_SLOW);
301
302 #if 1
303  l1:
304         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
305         if (get_cob_count() >= 5)
306                 strat_set_speed(600, SPEED_ANGLE_FAST);
307
308         err = line2line(LINE_UP, 0, LINE_R_DOWN, 2);
309         if (!TRAJ_SUCCESS(err)) {
310                 strat_hardstop();
311                 time_wait_ms(2000);
312                 goto l1;
313         }
314
315  l2:
316         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
317         if (get_cob_count() >= 5)
318                 strat_set_speed(600, SPEED_ANGLE_FAST);
319
320         err = line2line(LINE_R_DOWN, 2, LINE_R_UP, 2);
321         if (!TRAJ_SUCCESS(err)) {
322                 strat_hardstop();
323                 time_wait_ms(2000);
324                 goto l2;
325         }
326
327 #else
328         strat_set_speed(600, SPEED_ANGLE_FAST);
329         err = line2line(LINE_UP, 0, LINE_R_DOWN, 3);
330         err = line2line(LINE_R_DOWN, 3, LINE_R_UP, 2);
331         err = line2line(LINE_R_UP, 2, LINE_R_DOWN, 2);
332         err = line2line(LINE_R_DOWN, 2, LINE_R_UP, 3);
333         err = line2line(LINE_R_UP, 3, LINE_UP, 5);
334         err = line2line(LINE_UP, 5, LINE_L_DOWN, 2);
335         err = line2line(LINE_L_DOWN, 2, LINE_L_UP, 1);
336         err = line2line(LINE_L_UP, 1, LINE_L_DOWN, 1);
337         err = line2line(LINE_L_DOWN, 1, LINE_DOWN, 0);
338         wait_ms(500);
339         strat_hardstop();
340         return END_TRAJ;
341 #endif
342
343         strat_eject();
344
345         strat_set_speed(250, SPEED_ANGLE_FAST);
346
347  l4:
348         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
349         if (get_cob_count() >= 5)
350                 strat_set_speed(600, SPEED_ANGLE_FAST);
351
352         err = line2line(LINE_DOWN, 5, LINE_L_UP, 2);
353         if (!TRAJ_SUCCESS(err)) {
354                 strat_hardstop();
355                 time_wait_ms(2000);
356                 goto l4;
357         }
358
359  l5:
360         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
361         if (get_cob_count() >= 5)
362                 strat_set_speed(600, SPEED_ANGLE_FAST);
363
364         err = line2line(LINE_L_UP, 2, LINE_R_UP, 2);
365         if (!TRAJ_SUCCESS(err)) {
366                 strat_hardstop();
367                 time_wait_ms(2000);
368                 goto l5;
369         }
370
371         DEBUG(E_USER_STRAT, "%s():%d", __FUNCTION__, __LINE__);
372         if (get_cob_count() >= 5)
373                 strat_set_speed(600, SPEED_ANGLE_FAST);
374
375         WAIT_COND_OR_TRAJ_END(distance_from_robot(2625, COLOR_Y(1847)) < 100,
376                               TRAJ_FLAGS_STD);
377         strat_eject();
378
379         return END_TRAJ;
380 }
381
382 /* dump state (every 5 s max) */
383 #define DUMP_RATE_LIMIT(dump, last_print)               \
384         do {                                            \
385                 if (time_get_s() - last_print > 5) {    \
386                         dump();                         \
387                         last_print = time_get_s();      \
388                 }                                       \
389         } while (0)
390
391
392 /* return true if we need to grab some more elements */
393 static uint8_t need_more_elements(void)
394 {
395         if (time_get_s() <= 75) {
396                 /* we have enough time left */
397                 if (get_ball_count() >= 4)
398                         return 0;
399                 if (get_cob_count() >= 4)
400                         return 0;
401                 if ((get_ball_count() >= 2) &&
402                     (get_cob_count() >= 2))
403                         return 0;
404                 return 1;
405         }
406         else {
407                 /* not much time remaining */
408                 if ((get_ball_count() >= 1) &&
409                     (get_cob_count() >= 1))
410                         return 0;
411                 return 1;
412         }
413 }
414
415 uint8_t strat_main(void)
416 {
417         uint8_t err;
418
419         /* harvest the first cobs + balls */
420         err = strat_beginning();
421
422         while (1) {
423                 /* end of time exit ! */
424                 if (err == END_TIMER) {
425                         DEBUG(E_USER_STRAT, "End of time");
426                         strat_exit();
427                         break;
428                 }
429
430                 if (need_more_elements() == 0) {
431                         /* we have enough elements, go to eject */
432                         err = strat_eject();
433                         if (!TRAJ_SUCCESS(err))
434                                 continue;
435                 }
436                 else {
437                         /* harvest */
438                         err = strat_harvest();
439                         if (!TRAJ_SUCCESS(err))
440                                 continue;
441                 }
442         }
443
444         return err;
445 }