2 * Copyright Droids, Microb Technology (2009)
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.
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.
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
18 * Revision : $Id: strat.c,v 1.6 2009-11-08 17:24:33 zer0 Exp $
20 * Olivier MATZ <zer0@droids-corp.org>
28 #include <aversive/pgmspace.h>
29 #include <aversive/queue.h>
30 #include <aversive/wait.h>
31 #include <aversive/error.h>
34 #include <clock_time.h>
38 #include <control_system_manager.h>
39 #include <trajectory_manager.h>
40 #include <vect_base.h>
43 #include <obstacle_avoidance.h>
44 #include <blocking_detection_manager.h>
45 #include <robot_system.h>
46 #include <position_manager.h>
53 #include "strat_base.h"
54 #include "strat_utils.h"
55 #include "i2c_commands.h"
58 #define COL_DISP_MARGIN 400 /* stop 40 cm in front of dispenser */
59 #define COL_SCAN_PRE_MARGIN 250
64 #define BEACON_MAX_SAMPLES 100
65 struct beacon_sample {
74 static struct beacon_sample beacon_sample[BEACON_MAX_SAMPLES];
75 static uint8_t beacon_prev_time = 0;
76 static uint8_t beacon_cur_idx = 0;
78 static void beacon_update_samples(void)
80 int16_t opp_a, opp_d, opp_x, opp_y;
86 /* one sample per second max */
87 if (time <= beacon_prev_time)
89 /* limit max number of samples */
90 if (beacon_cur_idx >= BEACON_MAX_SAMPLES)
93 memset(&beacon_sample[beacon_cur_idx], 0, sizeof(beacon_sample[beacon_cur_idx]));
94 beacon_prev_time = time;
95 beacon_sample[beacon_cur_idx].time = time;
97 /* get opponent pos; if not found, just set struct to 0 */
98 err = get_opponent_xyda(&opp_x, &opp_y, &opp_d, &opp_a);
102 beacon_sample[beacon_cur_idx].posx = position_get_x_s16(&mainboard.pos);
103 beacon_sample[beacon_cur_idx].posy = position_get_y_s16(&mainboard.pos);
104 beacon_sample[beacon_cur_idx].posa = position_get_a_deg_s16(&mainboard.pos);
105 beacon_sample[beacon_cur_idx].oppx = opp_x;
106 beacon_sample[beacon_cur_idx].oppy = opp_y;
110 void beacon_dump_samples(void)
114 for (i=0; i<BEACON_MAX_SAMPLES; i++) {
115 printf_P(PSTR("%d: pos=(%d,%d,%d) opp=(%d,%d) time=%d\r\n"),
117 beacon_sample[i].posx,
118 beacon_sample[i].posy,
119 beacon_sample[i].posa,
120 beacon_sample[i].oppx,
121 beacon_sample[i].oppy,
122 beacon_sample[i].time);
127 struct strat_infos strat_infos = {
131 /* scanner disabled by default */
132 .scan_opp_min_time = 90,
133 .delay_between_opp_scan = 90,
134 .scan_our_min_time = 90,
135 .delay_between_our_scan = 90,
137 .lintel_min_time = 0,
138 .scan_opp_angle = -1,
147 /* column dispensers ; be carreful, positions are
148 * color-dependent, so COLOR_Y() and COLOR_A() should be
149 * used. All angles here are _absolute_ */
151 .checkpoint_x = 2711 - COL_SCAN_PRE_MARGIN,
152 .checkpoint_y = AREA_Y - COL_DISP_MARGIN,
157 .recalib_y = AREA_Y - (ROBOT_LENGTH/2 + DIST_BACK_DISPENSER),
162 .checkpoint_x = AREA_X - COL_DISP_MARGIN,
163 .checkpoint_y = 800 - COL_SCAN_PRE_MARGIN,
167 .recalib_x = AREA_X - (ROBOT_LENGTH/2 + DIST_BACK_DISPENSER),
173 .checkpoint_x = AREA_X-COL_DISP_MARGIN,
174 .checkpoint_y = 1300 + COL_SCAN_PRE_MARGIN,
178 .recalib_x = AREA_X - (ROBOT_LENGTH/2 + DIST_BACK_DISPENSER),
184 /* lintel dispensers */
186 .x = 912, /* XXX for red only */
190 .x = 1312, /* XXX for red only */
196 #define ZONE_DISC_NUM 0
198 .flags = ZONE_F_VALID | ZONE_F_DISC,
204 #define ZONE_1A_NUM 1
206 .flags = ZONE_F_VALID,
208 .checkpoint_x = 1385,
209 .checkpoint_y = 1700,
212 #define ZONE_1B_NUM 2
214 .flags = ZONE_F_VALID,
216 .checkpoint_x = 1615,
217 .checkpoint_y = 1700,
220 #define ZONE_0B_NUM 3
222 .flags = ZONE_F_VALID,
224 .checkpoint_x = 2100,
225 .checkpoint_y = 1700,
228 #define ZONE_0A_NUM 4
230 .flags = ZONE_F_VALID,
233 .checkpoint_y = 1700,
239 /*************************************************************/
243 /*************************************************************/
245 void strat_set_bounding_box(void)
247 if (get_color() == I2C_COLOR_RED) {
248 strat_infos.area_bbox.x1 = 300;
249 strat_infos.area_bbox.y1 = 200;
250 strat_infos.area_bbox.x2 = 2720; /* needed for c1 */
251 strat_infos.area_bbox.y2 = 1800;
254 strat_infos.area_bbox.x1 = 200;
255 strat_infos.area_bbox.y1 = 300;
256 strat_infos.area_bbox.x2 = 2720; /* needed for c1 */
257 strat_infos.area_bbox.y2 = 1900;
260 polygon_set_boundingbox(strat_infos.area_bbox.x1,
261 strat_infos.area_bbox.y1,
262 strat_infos.area_bbox.x2,
263 strat_infos.area_bbox.y2);
266 /* called before each strat, and before the start switch */
267 void strat_preinit(void)
270 interrupt_traj_reset();
271 mainboard.flags = DO_ENCODERS | DO_CS | DO_RS |
272 DO_POS | DO_BD | DO_POWER;
275 i2c_mechboard_mode_init();
276 if (get_color() == I2C_COLOR_RED)
277 i2c_mechboard_mode_prepare_pickup(I2C_LEFT_SIDE);
279 i2c_mechboard_mode_prepare_pickup(I2C_RIGHT_SIDE);
282 strat_dump_infos(__FUNCTION__);
285 void strat_dump_conf(void)
287 if (!strat_infos.dump_enabled)
290 printf_P(PSTR("-- conf --\r\n"));
292 printf_P(PSTR(" one build on disc: "));
293 if (strat_infos.conf.flags & STRAT_CONF_ONLY_ONE_ON_DISC)
294 printf_P(PSTR("on\r\n"));
296 printf_P(PSTR("off\r\n"));
298 printf_P(PSTR(" bypass static2: "));
299 if (strat_infos.conf.flags & STRAT_CONF_BYPASS_STATIC2)
300 printf_P(PSTR("on\r\n"));
302 printf_P(PSTR("off\r\n"));
304 printf_P(PSTR(" take one lintel: "));
305 if (strat_infos.conf.flags & STRAT_CONF_TAKE_ONE_LINTEL)
306 printf_P(PSTR("on\r\n"));
308 printf_P(PSTR("off\r\n"));
310 printf_P(PSTR(" skip this temple when temple check fails: "));
311 if (strat_infos.conf.flags & STRAT_CONF_SKIP_WHEN_CHECK_FAILS)
312 printf_P(PSTR("on\r\n"));
314 printf_P(PSTR("off\r\n"));
316 printf_P(PSTR(" store static2: "));
317 if (strat_infos.conf.flags & STRAT_CONF_STORE_STATIC2)
318 printf_P(PSTR("on\r\n"));
320 printf_P(PSTR("off\r\n"));
322 printf_P(PSTR(" (big3) try to build a temple with 3 lintels: "));
323 if (strat_infos.conf.flags & STRAT_CONF_BIG_3_TEMPLE)
324 printf_P(PSTR("on\r\n"));
326 printf_P(PSTR("off\r\n"));
328 printf_P(PSTR(" early opponent scan: "));
329 if (strat_infos.conf.flags & STRAT_CONF_EARLY_SCAN)
330 printf_P(PSTR("on\r\n"));
332 printf_P(PSTR("off\r\n"));
334 printf_P(PSTR(" push opponent columns: "));
335 if (strat_infos.conf.flags & STRAT_CONF_PUSH_OPP_COLS)
336 printf_P(PSTR("on\r\n"));
338 printf_P(PSTR("off\r\n"));
340 printf_P(PSTR(" scan opponent min time: %d\r\n"),
341 strat_infos.conf.scan_opp_min_time);
342 printf_P(PSTR(" delay between oppnent scan: %d\r\n"),
343 strat_infos.conf.delay_between_opp_scan);
344 printf_P(PSTR(" scan our min time: %d\r\n"),
345 strat_infos.conf.scan_our_min_time);
346 printf_P(PSTR(" delay between our scan: %d\r\n"),
347 strat_infos.conf.delay_between_our_scan);
348 printf_P(PSTR(" wait opponent gone before scan: %d\r\n"),
349 strat_infos.conf.wait_opponent);
350 printf_P(PSTR(" lintel min time: %d\r\n"),
351 strat_infos.conf.lintel_min_time);
352 printf_P(PSTR(" scan_opp_angle: %d\r\n"),
353 strat_infos.conf.scan_opp_angle);
356 void strat_dump_temple(struct temple *temple)
358 if (!strat_infos.dump_enabled)
361 printf_P(PSTR(" temple %p (%s): "), temple, temple->zone->name);
363 if (temple->flags & TEMPLE_F_MONOCOL)
364 printf_P(PSTR("MONOCOL "));
366 printf_P(PSTR("BICOL "));
368 if (temple->flags & TEMPLE_F_ON_DISC)
369 printf_P(PSTR("ON_DISC "));
371 printf_P(PSTR("ON_ZONE_0_1 "));
373 if (temple->flags & TEMPLE_F_OPPONENT)
374 printf_P(PSTR("OPPONENT "));
376 printf_P(PSTR("OURS "));
378 if (temple->flags & TEMPLE_F_LINTEL)
379 printf_P(PSTR("LIN_ON_TOP "));
381 printf_P(PSTR("COL_ON_TOP "));
383 printf_P(PSTR("\r\n"));
385 printf_P(PSTR(" pos=(%d,%d,%d) ckpt=(%d,%d) ltime=%d\r\n"),
386 temple->x, temple->y, temple->a,
387 temple->checkpoint_x, temple->checkpoint_y,
388 temple->last_try_time);
389 printf_P(PSTR(" L: lev=%d da=%d,%d\r\n"),
390 temple->level_l, temple->dist_l, temple->angle_l);
391 printf_P(PSTR(" R: lev=%d da=%d,%d\r\n"),
392 temple->level_l, temple->dist_l, temple->angle_l);
395 void strat_dump_zone(struct build_zone *zone)
397 if (!strat_infos.dump_enabled)
400 printf_P(PSTR(" zone %s: "), zone->name);
402 if (zone->flags & ZONE_F_DISC)
403 printf_P(PSTR("DISC "));
404 else if (zone->flags & ZONE_F_ZONE1)
405 printf_P(PSTR("ZONE1 "));
406 else if (zone->flags & ZONE_F_ZONE0)
407 printf_P(PSTR("ZONE0 "));
409 if (zone->flags & ZONE_F_BUSY)
410 printf_P(PSTR("BUSY "));
412 printf_P(PSTR("FREE "));
414 printf_P(PSTR("\r\n"));
416 printf_P(PSTR(" lev=%d ckpt=(%d,%d) ltime=%d\r\n"),
418 zone->checkpoint_x, zone->checkpoint_y,
419 zone->last_try_time);
422 void strat_dump_static_cols(void)
424 if (!strat_infos.dump_enabled)
427 printf_P(PSTR(" static cols: l0=%d l1=%d l2=%d\r\n"),
428 strat_infos.s_cols.flags & STATIC_COL_LINE0_DONE,
429 strat_infos.s_cols.flags & STATIC_COL_LINE1_DONE,
430 strat_infos.s_cols.flags & STATIC_COL_LINE2_DONE);
433 void strat_dump_col_disp(void)
435 if (!strat_infos.dump_enabled)
438 printf_P(PSTR(" c1 cnt=%d ltt=%d\r\n"),
439 strat_infos.c1.count, strat_infos.c1.last_try_time);
440 printf_P(PSTR(" c2 cnt=%d ltt=%d\r\n"),
441 strat_infos.c2.count, strat_infos.c2.last_try_time);
442 printf_P(PSTR(" c3 cnt=%d ltt=%d\r\n"),
443 strat_infos.c3.count, strat_infos.c3.last_try_time);
446 void strat_dump_lin_disp(void)
448 if (!strat_infos.dump_enabled)
450 printf_P(PSTR(" l1 cnt=%d ltt=%d\r\n"),
451 strat_infos.l1.count, strat_infos.l1.last_try_time);
452 printf_P(PSTR(" l2 cnt=%d ltt=%d\r\n"),
453 strat_infos.l2.count, strat_infos.l2.last_try_time);
457 void strat_dump_all_temples(void)
459 struct temple *temple;
462 if (!strat_infos.dump_enabled)
465 for (i=0; i<MAX_TEMPLE; i++) {
466 temple = &strat_infos.temple_list[i];
467 if (!(temple->flags & TEMPLE_F_VALID))
469 strat_dump_temple(temple);
473 void strat_dump_all_zones(void)
475 struct build_zone *zone;
478 if (!strat_infos.dump_enabled)
481 for (i=0; i<MAX_ZONE; i++) {
482 zone = &strat_infos.zone_list[i];
483 if (!(zone->flags & ZONE_F_VALID))
485 strat_dump_zone(zone);
489 /* display current information about the state of the game */
490 void strat_dump_infos(const char *caller)
492 if (!strat_infos.dump_enabled)
495 printf_P(PSTR("%s() dump strat infos:\r\n"), caller);
496 strat_dump_static_cols();
497 strat_dump_col_disp();
498 strat_dump_lin_disp();
499 strat_dump_all_temples();
500 strat_dump_all_zones();
503 /* init current area state before a match. Dump update user conf
505 void strat_reset_infos(void)
509 /* /!\ don't do a big memset() as there is static data */
510 strat_infos.s_cols.flags = 0;
511 strat_infos.c1.count = 5;
512 strat_infos.c1.last_try_time = 0;
513 strat_infos.c2.count = 5;
514 strat_infos.c2.last_try_time = 0;
515 strat_infos.c3.count = 5;
516 strat_infos.c3.last_try_time = 0;
517 strat_infos.l1.count = 1;
518 strat_infos.l1.last_try_time = 0;
519 strat_infos.l2.count = 1;
520 strat_infos.l2.last_try_time = 0;
522 strat_infos.taken_lintel = 0;
523 strat_infos.col_in_boobs = 0;
524 strat_infos.lazy_pickup_done = 0;
525 strat_infos.i2c_loaded_skipped = 0;
527 memset(strat_infos.temple_list, 0, sizeof(strat_infos.temple_list));
529 for (i=0; i<MAX_ZONE; i++)
530 strat_infos.zone_list[i].flags = ZONE_F_VALID;
531 strat_infos.zone_list[ZONE_DISC_NUM].flags |= ZONE_F_DISC;
532 strat_infos.zone_list[ZONE_1A_NUM].flags |= ZONE_F_ZONE1;
533 strat_infos.zone_list[ZONE_1B_NUM].flags |= ZONE_F_ZONE1;
534 strat_infos.zone_list[ZONE_0A_NUM].flags |= ZONE_F_ZONE0;
535 strat_infos.zone_list[ZONE_0B_NUM].flags |= ZONE_F_ZONE0;
537 strat_set_bounding_box();
539 /* set lintel position, depending on color */
540 if (mainboard.our_color == I2C_COLOR_RED) {
541 strat_infos.l1.x = 912;
542 strat_infos.l2.x = 1312;
545 strat_infos.l1.x = 888;
546 strat_infos.l2.x = 1288;
550 /* call it just before launching the strat */
551 void strat_init(void)
554 printf("not implemented\n");
559 /* we consider that the color is correctly set */
561 strat_set_speed(SPEED_DIST_FAST, SPEED_ANGLE_FAST);
563 interrupt_traj_reset();
565 /* used in strat_base for END_TIMER */
566 mainboard.flags = DO_ENCODERS | DO_CS | DO_RS |
567 DO_POS | DO_BD | DO_TIMER | DO_POWER;
570 beacon_prev_time = 0;
577 /* call it after each strat */
578 void strat_exit(void)
581 printf("not implemented\n");
586 mainboard.flags &= ~(DO_TIMER);
591 mainboard.flags &= ~(DO_CS);
592 pwm_ng_set(LEFT_PWM, 0);
593 pwm_ng_set(RIGHT_PWM, 0);
598 /* called periodically */
599 void strat_event(void *dummy)
601 /* limit speed when opponent is close */
605 beacon_update_samples();
610 /* do static cols + first temples */
611 static uint8_t strat_beginning(void)
615 /* don't limit the speed when opponent is near: it can change
616 * the radius of the curves */
617 strat_limit_speed_disable();
619 err = strat_static_columns(0);
621 strat_limit_speed_enable();
623 if (!TRAJ_SUCCESS(err))
626 /* go to disc to build the first temple */
628 /* XXX if opponent is near disc, go to zone1 */
629 err = strat_goto_disc(2);
630 if (!TRAJ_SUCCESS(err))
632 DEBUG(E_USER_STRAT, "disc reached");
634 /* can return END_ERROR or END_TIMER, should not happen
636 err = strat_build_new_temple(&strat_infos.zone_list[0]);
637 if (!TRAJ_SUCCESS(err))
640 /* bypass static2 if specified */
641 if (strat_infos.conf.flags & STRAT_CONF_BYPASS_STATIC2) {
642 err = strat_escape(&strat_infos.zone_list[0], TRAJ_FLAGS_STD);
646 /* get the last 2 columns, and build them on previous temple */
647 err = strat_static_columns_pass2();
648 if (!TRAJ_SUCCESS(err))
651 /* early opponent scan, for offensive strategy */
652 if (strat_infos.conf.flags & STRAT_CONF_EARLY_SCAN) {
653 err = strat_pickup_lintels();
656 /* try to build on opponent (scan must be enabled) */
657 err = strat_build_on_opponent_temple();
665 /* return true if we need to grab some more elements (lintel/cols) */
666 uint8_t need_more_elements(void)
669 printf("not implemented\n");
671 if (time_get_s() <= 75) {
672 /* we have at least one col on each arm, build now */
673 if ((get_column_count_left() >= 1) &&
674 (get_column_count_right() >= 1))
678 if (get_column_count())
685 /* dump state (every 5 s max) */
686 #define DUMP_RATE_LIMIT(dump, last_print) \
688 if (time_get_s() - last_print > 5) { \
690 last_print = time_get_s(); \
695 uint8_t strat_main(void)
698 printf("not implemented\n");
702 struct temple *temple = NULL;
703 struct build_zone *zone = NULL;
705 uint8_t last_print_cols = 0;
706 uint8_t last_print_lin = 0;
707 uint8_t last_print_temple = 0;
708 uint8_t last_print_zone = 0;
710 /* do static cols + first temple */
711 err = strat_beginning();
713 /* skip error code */
717 if (err == END_TIMER) {
718 DEBUG(E_USER_STRAT, "End of time");
723 /* we have at least one col on each arm, build now */
724 if (need_more_elements() == 0) {
726 /* try to build on opponent, will return
727 * END_TRAJ without doing anything if
729 err = strat_build_on_opponent_temple();
730 if (!TRAJ_SUCCESS(err))
732 if (need_more_elements())
735 /* try to scan and build on our temple, will
736 * return END_TRAJ without doing anything if
738 err = strat_check_temple_and_build();
739 if (!TRAJ_SUCCESS(err))
741 if (need_more_elements())
744 /* Else, do a simple build, as before */
746 temple = strat_get_best_temple();
748 /* one valid temple found */
750 DUMP_RATE_LIMIT(strat_dump_all_temples, last_print_temple);
752 err = strat_goto_temple(temple);
753 if (!TRAJ_SUCCESS(err))
756 /* can return END_ERROR or END_TIMER,
757 * should not happen here */
758 err = strat_grow_temple(temple);
759 if (!TRAJ_SUCCESS(err))
762 err = strat_escape(temple->zone, TRAJ_FLAGS_STD);
763 if (!TRAJ_SUCCESS(err))
769 zone = strat_get_best_zone();
771 DUMP_RATE_LIMIT(strat_dump_all_zones, last_print_zone);
773 DEBUG(E_USER_STRAT, "goto zone %s", zone->name);
774 err = strat_goto_build_zone(zone, zone->level);
775 if (!TRAJ_SUCCESS(err))
777 DEBUG(E_USER_STRAT, "zone reached");
779 /* no error code except END_ERROR, should not happen */
780 err = strat_build_new_temple(zone);
782 err = strat_escape(zone, TRAJ_FLAGS_STD);
783 if (!TRAJ_SUCCESS(err))
789 /* XXX hey what can we do here... :'( */
790 DEBUG(E_USER_STRAT, "panic :)");
795 /* else we need some elements (lintels, then columns) */
797 if (strat_infos.l1.count != 0 && strat_infos.l2.count != 0)
798 DUMP_RATE_LIMIT(strat_dump_lin_disp, last_print_lin);
800 err = strat_pickup_lintels();
801 /* can return an error code, but we have
802 * nothing to do because pickup_column()
803 * starts with a goto_and_avoid() */
804 if (!TRAJ_SUCCESS(err))
807 DUMP_RATE_LIMIT(strat_dump_col_disp, last_print_cols);
809 err = strat_pickup_columns();
810 if (!TRAJ_SUCCESS(err))
811 nop(); /* nothing to do */
813 /* XXX check here that we have elements, or do
815 /* if we cannot take elements, try to build */