-/*
- * Copyright Droids Corporation, Microb Technology (2009)
- *
+/*
+ * Copyright Droids, Microb Technology (2010)
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
- * Revision : $Id: strat_avoid.c,v 1.5 2009-11-08 17:24:33 zer0 Exp $
+ * Revision : $Id: strat.c,v 1.6 2009-11-08 17:24:33 zer0 Exp $
*
+ * Olivier MATZ <zer0@droids-corp.org>
*/
+
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <stdint.h>
#include <math.h>
+#include <aversive.h>
#include <aversive/pgmspace.h>
-#include <aversive/wait.h>
#include <aversive/error.h>
#include <ax12.h>
#include <uart.h>
#include <pwm_ng.h>
-#include <time.h>
+#include <clock_time.h>
#include <spi.h>
#include <pid.h>
#include <quadramp.h>
#include <control_system_manager.h>
#include <trajectory_manager.h>
+#include <trajectory_manager_utils.h>
+#include <trajectory_manager_core.h>
#include <vect_base.h>
#include <lines.h>
#include <polygon.h>
#include <robot_system.h>
#include <position_manager.h>
+#include <diagnostic.h>
+
#include <rdline.h>
#include <parse.h>
+#include "../common/i2c_commands.h"
+#include "i2c_protocol.h"
#include "main.h"
#include "strat.h"
+#include "strat_db.h"
#include "strat_base.h"
+#include "strat_corn.h"
+#include "strat_avoid.h"
#include "strat_utils.h"
#include "sensor.h"
-
-#define EDGE_NUMBER 5
-void set_rotated_pentagon(poly_t *pol, const point_t *robot_pt,
- int16_t radius, int16_t x, int16_t y)
+#include "actuator.h"
+
+
+const struct wp_coord circuit1[] = {
+ { .i = 11, .j = 6, .end = 0, },
+ { .i = 10, .j = 6, .end = 0, },
+ { .i = 9, .j = 5, .end = 0, },
+ { .i = 8, .j = 5, .end = 0, },
+ { .i = 7, .j = 4, .end = 0, },
+ { .i = 6, .j = 4, .end = 0, },
+ { .i = 5, .j = 4, .end = 0, },
+ { .i = 4, .j = 5, .end = 0, },
+ { .i = 3, .j = 5, .end = 0, },
+ { .i = 2, .j = 6, .end = 0, },
+ { .i = 1, .j = 6, .end = 0, },
+ { .i = 1, .j = 5, .end = 0, },
+ { .i = 1, .j = 4, .end = 0, },
+ { .i = 1, .j = 3, .end = 0, },
+ { .i = 1, .j = 2, .end = 0, },
+ { .i = 1, .j = 1, .end = 0, },
+ { .i = 2, .j = 2, .end = 0, },
+ { .i = 3, .j = 2, .end = 0, },
+ { .i = 4, .j = 3, .end = 0, },
+ { .i = 5, .j = 3, .end = 0, },
+ { .i = 6, .j = 4, .end = 0, },
+ { .i = 7, .j = 3, .end = 0, },
+ { .i = 8, .j = 3, .end = 0, },
+ { .i = 9, .j = 2, .end = 0, },
+ { .i = 10, .j = 2, .end = 0, },
+ { .i = 11, .j = 1, .end = 0, },
+ { .i = 11, .j = 2, .end = 0, },
+ { .i = 11, .j = 3, .end = 0, },
+ { .i = 11, .j = 4, .end = 0, },
+ { .i = 11, .j = 5, .end = 0, },
+ { .i = 11, .j = 6, .end = 1, },
+};
+
+const struct wp_coord circuit2[] = {
+ { .i = 11, .j = 6, .end = 0, },
+ { .i = 10, .j = 6, .end = 0, },
+ { .i = 9, .j = 5, .end = 0, },
+ { .i = 9, .j = 4, .end = 0, },
+ { .i = 9, .j = 3, .end = 0, },
+ { .i = 10, .j = 4, .end = 0, },
+ { .i = 11, .j = 4, .end = 0, },
+ { .i = 11, .j = 5, .end = 0, },
+ { .i = 11, .j = 6, .end = 1, },
+};
+
+/* list of all possible circuits */
+const struct wp_coord *circuits[] = {
+ circuit1,
+ circuit2,
+ NULL,
+};
+
+/* symetric neighbor position */
+static inline uint8_t opposite_position(uint8_t pos)
{
-
- double c_a, s_a;
- uint8_t i;
- double px1, py1, px2, py2;
- double a_rad;
-
- a_rad = atan2(y - robot_pt->y, x - robot_pt->x);
-
- /* generate pentagon */
- c_a = cos(-2*M_PI/EDGE_NUMBER);
- s_a = sin(-2*M_PI/EDGE_NUMBER);
-
- /*
- px1 = radius;
- py1 = 0;
- */
- px1 = radius * cos(a_rad + 2*M_PI/(2*EDGE_NUMBER));
- py1 = radius * sin(a_rad + 2*M_PI/(2*EDGE_NUMBER));
-
-
- for (i = 0; i < EDGE_NUMBER; i++){
- oa_poly_set_point(pol, x + px1, y + py1, i);
-
- px2 = px1*c_a + py1*s_a;
- py2 = -px1*s_a + py1*c_a;
-
- px1 = px2;
- py1 = py2;
- }
+ pos += 3;
+ if (pos > LINE_L_UP)
+ pos -= 6;
+ return pos;
}
-void set_rotated_poly(poly_t *pol, const point_t *robot_pt,
- int16_t w, int16_t l, int16_t x, int16_t y)
+#if 0
+static uint8_t cc;
+uint8_t xget_cob_count(void)
{
- double tmp_x, tmp_y;
- double a_rad;
-
- a_rad = atan2(y - robot_pt->y, x - robot_pt->x);
-
- DEBUG(E_USER_STRAT, "%s() x,y=%d,%d a_rad=%2.2f",
- __FUNCTION__, x, y, a_rad);
-
- /* point 1 */
- tmp_x = w;
- tmp_y = l;
- rotate(&tmp_x, &tmp_y, a_rad);
- tmp_x += x;
- tmp_y += y;
- oa_poly_set_point(pol, tmp_x, tmp_y, 0);
-
- /* point 2 */
- tmp_x = -w;
- tmp_y = l;
- rotate(&tmp_x, &tmp_y, a_rad);
- tmp_x += x;
- tmp_y += y;
- oa_poly_set_point(pol, tmp_x, tmp_y, 1);
-
- /* point 3 */
- tmp_x = -w;
- tmp_y = -l;
- rotate(&tmp_x, &tmp_y, a_rad);
- tmp_x += x;
- tmp_y += y;
- oa_poly_set_point(pol, tmp_x, tmp_y, 2);
-
- /* point 4 */
- tmp_x = w;
- tmp_y = -l;
- rotate(&tmp_x, &tmp_y, a_rad);
- tmp_x += x;
- tmp_y += y;
- oa_poly_set_point(pol, tmp_x, tmp_y, 3);
+ return cc;
}
-#define DISC_X CENTER_X
-#define DISC_Y CENTER_Y
-
-void set_central_disc_poly(poly_t *pol, const point_t *robot_pt)
+static uint8_t bc;
+uint8_t xget_ball_count(void)
{
- set_rotated_pentagon(pol, robot_pt, DISC_PENTA_DIAG,
- DISC_X, DISC_Y);
+ return bc;
}
-#ifdef HOMOLOGATION
-/* /!\ half size */
-#define O_WIDTH 400
-#define O_LENGTH 550
+static uint32_t ts;
+uint8_t xtime_get_s(void)
+{
+ return ts;
+}
#else
-/* /!\ half size */
-#define O_WIDTH 360
-#define O_LENGTH 500
+#define xget_cob_count() get_cob_count()
+#define xget_ball_count() get_ball_count()
+#define xtime_get_s() time_get_s()
#endif
-void set_opponent_poly(poly_t *pol, const point_t *robot_pt, int16_t w, int16_t l)
+/* get the neighbour of the point at specified dir, return -1 if
+ * there is no neighbor */
+int8_t wp_get_neigh(uint8_t i, uint8_t j, uint8_t *ni, uint8_t *nj,
+ uint8_t dir)
{
- int16_t x, y;
- get_opponent_xy(&x, &y);
- DEBUG(E_USER_STRAT, "oponent at: %d %d", x, y);
-
- /* place poly even if invalid, because it's -100 */
- set_rotated_poly(pol, robot_pt, w, l, x, y);
-}
-
-/* don't care about polygons further than this distance for escape */
-#define ESCAPE_POLY_THRES 1000
+ switch (dir) {
+ case LINE_UP:
+ j++;
+ break;
+ case LINE_R_UP:
+ if ((i & 1)) j++;
+ i++;
+ break;
+ case LINE_R_DOWN:
+ if (!(i & 1)) j--;
+ i++;
+ break;
+ case LINE_DOWN:
+ j--;
+ break;
+ case LINE_L_DOWN:
+ if (!(i & 1)) j--;
+ i--;
+ break;
+ case LINE_L_UP:
+ if ((i & 1)) j++;
+ i--;
+ break;
+ default:
+ return -1;
+ }
+ if (i >= WAYPOINTS_NBX || j >= WAYPOINTS_NBY)
+ return -1;
-/* don't reduce opp if opp is too far */
-#define REDUCE_POLY_THRES 600
+ *ni = i;
+ *nj = j;
+ return 0;
+}
-/* has to be longer than any poly */
-#define ESCAPE_VECT_LEN 3000
+static uint8_t get_line_num(int8_t i, int8_t j, uint8_t dir)
+{
+ switch (dir) {
+ case LINE_UP:
+ case LINE_DOWN:
+ return i/2;
+ case LINE_R_UP:
+ case LINE_L_DOWN:
+ i &= 0xfe;
+ j -= i/2;
+ return (5-j)/2;
+ case LINE_R_DOWN:
+ case LINE_L_UP:
+ i &= 0xfe;
+ j += i/2;
+ return (11-j)/2;
+ default:
+ return -1;
+ }
+}
-/*
- * Go in playground, loop until out of poly. The argument robot_pt is
- * the pointer to the current position of the robot.
- * Return 0 if there was nothing to do.
- * Return 1 if we had to move. In this case, update the theorical
- * position of the robot in robot_pt.
- */
-static int8_t go_in_area(point_t *robot_pt)
+static uint8_t get_dir(uint8_t prev_i, uint8_t prev_j,
+ uint8_t i, uint8_t j)
{
- point_t poly_pts_area[4];
- poly_t poly_area;
- point_t disc_pt, dst_pt;
+ int8_t diff_i, diff_j;
+
+ diff_i = i - prev_i;
+ diff_j = j - prev_j;
+
+ if (diff_i == 0 && diff_j == 1)
+ return LINE_UP;
+ if (diff_i == 0 && diff_j == -1)
+ return LINE_DOWN;
+
+ if ((prev_i & 1) == 0) {
+ if (diff_i == 1 && diff_j == 0)
+ return LINE_R_UP;
+ if (diff_i == 1 && diff_j == -1)
+ return LINE_R_DOWN;
+ if (diff_i == -1 && diff_j == 0)
+ return LINE_L_UP;
+ if (diff_i == -1 && diff_j == -1)
+ return LINE_L_DOWN;
+ }
+ else {
+ if (diff_i == 1 && diff_j == 1)
+ return LINE_R_UP;
+ if (diff_i == 1 && diff_j == 0)
+ return LINE_R_DOWN;
+ if (diff_i == -1 && diff_j == 1)
+ return LINE_L_UP;
+ if (diff_i == -1 && diff_j == 0)
+ return LINE_L_DOWN;
+ }
- disc_pt.x = DISC_X;
- disc_pt.y = DISC_Y;
+ /* invalid value */
+ return 0xFF;
+}
- /* Go in playground */
- if (!is_in_boundingbox(robot_pt)){
- NOTICE(E_USER_STRAT, "not in playground %"PRIi32", %"PRIi32"",
- robot_pt->x, robot_pt->y);
+/* return true if a waypoint belongs to a line */
+uint8_t wp_belongs_to_line(uint8_t i, uint8_t j, uint8_t linenum, uint8_t dir)
+{
+ uint8_t ln;
+ ln = get_line_num(i, j, dir);
+ if (ln == linenum)
+ return 1;
+ return 0;
+}
- poly_area.l = 4;
- poly_area.pts = poly_pts_area;
- poly_pts_area[0].x = strat_infos.area_bbox.x1;
- poly_pts_area[0].y = strat_infos.area_bbox.y1;
+/* count the number of non-black corns which are neighbors of
+ * specified cob */
+uint8_t corn_count_neigh(uint8_t i, uint8_t j)
+{
+ uint8_t dir, n = 0;
+ uint8_t ni, nj;
- poly_pts_area[1].x = strat_infos.area_bbox.x2;
- poly_pts_area[1].y = strat_infos.area_bbox.y1;
+ for (dir = LINE_UP; dir <= LINE_R_DOWN; dir++) {
+ if (wp_get_neigh(i, j, &ni, &nj, dir) < 0)
+ continue;
- poly_pts_area[2].x = strat_infos.area_bbox.x2;
- poly_pts_area[2].y = strat_infos.area_bbox.y2;
+ //printf("i,j=%d,%d dir=%d, ni,nj=%d,%d\r\n",
+ // i, j, dir, ni, nj);
- poly_pts_area[3].x = strat_infos.area_bbox.x1;
- poly_pts_area[3].y = strat_infos.area_bbox.y2;
+ /* is there a corn cob ? */
+ if (strat_db.wp_table[ni][nj].type == WP_TYPE_CORN &&
+ strat_db.wp_table[ni][nj].present &&
+ strat_db.wp_table[ni][nj].corn.color != I2C_COB_BLACK)
+ n ++;
+ }
- is_crossing_poly(*robot_pt, disc_pt, &dst_pt, &poly_area);
- NOTICE(E_USER_STRAT, "pt dst %"PRIi32", %"PRIi32"", dst_pt.x, dst_pt.y);
-
- strat_goto_xy_force(dst_pt.x, dst_pt.y);
+ return n;
+}
- robot_pt->x = dst_pt.x;
- robot_pt->y = dst_pt.y;
- NOTICE(E_USER_STRAT, "GOTO %"PRIi32",%"PRIi32"",
- dst_pt.x, dst_pt.y);
+int8_t get_path(const struct wp_coord *circuit,
+ uint8_t starti, uint8_t startj, uint8_t faceA,
+ struct wp_line *circuit_wpline)
+{
+ const struct wp_coord *curcircuit;
+ uint8_t prev_i, prev_j;
+ uint8_t dir, prev_dir = 0xFF;
+ uint8_t found = 0, i = 0, j = 0;
+ uint8_t linenum;
+ int8_t step = faceA ? 1 : -1;
+ int8_t skipfirst=0;
+ int8_t path_len = 0;
+
+ printf_P(PSTR("face: %d\r\n"), faceA);
+ if ( !faceA && circuit->i == 11 && circuit->j == 6)
+ skipfirst=1;
+
+ /* check that the point is present in the circuit */
+ for (curcircuit = circuit + skipfirst; curcircuit->end == 0; curcircuit ++) {
+ if (curcircuit->i == starti && curcircuit->j == startj) {
+ found = 1;
+ break;
+ }
+ }
- return 1;
+ if ( !faceA && curcircuit->i == 11 && curcircuit->j == 6)
+ found = 1;
+ if (found == 0)
+ return -1;
+
+ /* XXX len must be >= 1 */
+ /* XXX start = 11,6 */
+
+ prev_i = starti;
+ prev_j = startj;
+
+ curcircuit = curcircuit;
+ while (1) {
+ if (faceA && curcircuit->end)
+ break;
+ else if (!faceA && curcircuit == circuit)
+ break;
+ i = curcircuit->i;
+ j = curcircuit->j;
+
+ dir = get_dir(prev_i, prev_j, i, j);
+
+ if (prev_dir != dir) {
+ linenum = get_line_num(prev_i, prev_j, dir);
+ /* printf_P(PSTR("COIN %d, %d, dir=%d linenum=%d\r\n"), */
+ /* prev_i, prev_j, dir, linenum); */
+ circuit_wpline[path_len].line_num = linenum;
+ circuit_wpline[path_len].dir = dir;
+ path_len++;
+ }
+ prev_dir = dir;
+ prev_i = i;
+ prev_j = j;
+ curcircuit += step;
}
- return 0;
-}
+/* printf_P(PSTR("COIN %d, %d\r\n"), curcircuit->i, curcircuit->j); */
+ return path_len; /* XXX */
+}
-/*
- * Escape from polygons if needed.
- * robot_pt is the current position of the robot, it will be
- * updated.
- */
-static int8_t escape_from_poly(point_t *robot_pt,
- poly_t *pol_disc,
- int16_t opp_x, int16_t opp_y,
- int16_t opp_w, int16_t opp_l,
- poly_t *pol_opp)
+int16_t get_score(uint32_t wcorn_retrieved, uint32_t ucorn_retrieved,
+ uint16_t tomato_retrieved, uint8_t len)
{
- uint8_t in_disc = 0, in_opp = 0;
- double escape_dx = 0, escape_dy = 0;
- double disc_dx = 0, disc_dy = 0;
- double opp_dx = 0, opp_dy = 0;
- double len;
- point_t opp_pt, disc_pt, dst_pt;
- point_t intersect_disc_pt, intersect_opp_pt;
-
- opp_pt.x = opp_x;
- opp_pt.y = opp_y;
- disc_pt.x = DISC_X;
- disc_pt.y = DISC_Y;
-
- /* escape from other poly if necessary */
- if (is_in_poly(robot_pt, pol_disc) == 1)
- in_disc = 1;
- if (is_in_poly(robot_pt, pol_opp) == 1)
- in_opp = 1;
-
- if (in_disc == 0 && in_opp == 0) {
- NOTICE(E_USER_STRAT, "no need to escape");
- return 0;
- }
-
- NOTICE(E_USER_STRAT, "in_disc=%d, in_opp=%d", in_disc, in_opp);
-
- /* process escape vector */
-
- if (distance_between(robot_pt->x, robot_pt->y, DISC_X, DISC_Y) < ESCAPE_POLY_THRES) {
- disc_dx = robot_pt->x - DISC_X;
- disc_dy = robot_pt->y - DISC_Y;
- NOTICE(E_USER_STRAT, " robot is near disc: vect=%2.2f,%2.2f",
- disc_dx, disc_dy);
- len = norm(disc_dx, disc_dy);
- if (len != 0) {
- disc_dx /= len;
- disc_dy /= len;
+ int16_t score = 0;
+ uint8_t i;
+ uint32_t mask = 1;
+ uint8_t n;
+
+ /* score with corn */
+ n = xget_cob_count() * 2;
+ for (i = 0; i<CORN_NB; i++) {
+ if (n >= 10)
+ break;
+ if (wcorn_retrieved & mask) {
+ score += 250;
+ n += 2;
}
- else {
- disc_dx = 1.0;
- disc_dy = 0.0;
+ if (n >= 10)
+ break;
+ if (ucorn_retrieved & mask) {
+ score += 125;
+ n += 1;
}
- escape_dx += disc_dx;
- escape_dy += disc_dy;
+ mask <<= 1UL;
}
- if (distance_between(robot_pt->x, robot_pt->y, opp_x, opp_y) < ESCAPE_POLY_THRES) {
- opp_dx = robot_pt->x - opp_x;
- opp_dy = robot_pt->y - opp_y;
- NOTICE(E_USER_STRAT, " robot is near opp: vect=%2.2f,%2.2f",
- opp_dx, opp_dy);
- len = norm(opp_dx, opp_dy);
- if (len != 0) {
- opp_dx /= len;
- opp_dy /= len;
+ printf_P(PSTR("get score: cob %d \r\n"), n);
+ /* score with tomato */
+ n = xget_ball_count();
+ mask = 1;
+ for (i = 0; i<TOMATO_NB; i++) {
+ if (n >= 4)
+ break;
+ if (tomato_retrieved & mask) {
+ score += 150;
+ n += 1;
}
- else {
- opp_dx = 1.0;
- opp_dy = 0.0;
- }
- escape_dx += opp_dx;
- escape_dy += opp_dy;
+ mask <<= 1UL;
}
- /* normalize escape vector */
- len = norm(escape_dx, escape_dy);
- if (len != 0) {
- escape_dx /= len;
- escape_dy /= len;
- }
- else {
- if (pol_disc != NULL) {
- /* rotate 90° */
- escape_dx = disc_dy;
- escape_dy = disc_dx;
- }
- else if (pol_opp != NULL) {
- /* rotate 90° */
- escape_dx = opp_dy;
- escape_dy = opp_dx;
- }
- else { /* should not happen */
- opp_dx = 1.0;
- opp_dy = 0.0;
- }
+ printf_P(PSTR("get score: ball %d \r\n"), n);
+ /* malus for long circuits */
+ score -= (len * 20);
+
+ /* double malus for long circuits if we don't have much
+ * time */
+#define WP_SPEED 1
+ if (len * WP_SPEED > (MATCH_TIME - xtime_get_s())) {
+ uint16_t extra;
+ extra = (len * WP_SPEED) - (MATCH_TIME - xtime_get_s());
+ score -= (200 * extra);
}
- NOTICE(E_USER_STRAT, " escape vect = %2.2f,%2.2f",
- escape_dx, escape_dy);
+ /* XXX use direction of robot */
- /* process the correct len of escape vector */
+ return score;
+}
- dst_pt.x = robot_pt->x + escape_dx * ESCAPE_VECT_LEN;
- dst_pt.y = robot_pt->y + escape_dy * ESCAPE_VECT_LEN;
+/* i,j: starting position */
+int8_t browse_one_circuit(const struct wp_coord *circuit,
+ uint8_t starti, uint8_t startj,
+ int16_t *scoreA, int16_t *scoreB)
+{
+ const struct wp_coord *curcircuit;
+ uint32_t wcorn_retrieved = 0; /* bit mask */
+ uint32_t ucorn_retrieved = 0; /* bit mask */
+ uint16_t tomato_retrieved = 0; /* bit mask */
+ uint8_t len = 0, found = 0, i, j;
+ uint8_t ni = 0, nj = 0, pos, color;
+
+ /* check that the point is present in the circuit */
+ for (curcircuit = circuit; curcircuit->end == 0; curcircuit ++) {
+ if (curcircuit->i == starti && curcircuit->j == startj) {
+ found = 1;
+ break;
+ }
+ }
- NOTICE(E_USER_STRAT, "robot pt %"PRIi32" %"PRIi32,
- robot_pt->x, robot_pt->y);
- NOTICE(E_USER_STRAT, "dst point %"PRIi32",%"PRIi32,
- dst_pt.x, dst_pt.y);
+ if (found == 0)
+ return -1;
- if (in_disc) {
- if (is_crossing_poly(*robot_pt, dst_pt, &intersect_disc_pt,
- pol_disc) == 1) {
- /* we add 2 mm to be sure we are out of th polygon */
- dst_pt.x = intersect_disc_pt.x + escape_dx * 2;
- dst_pt.y = intersect_disc_pt.y + escape_dy * 2;
- if (is_point_in_poly(pol_opp, dst_pt.x, dst_pt.y) != 1) {
+ for (curcircuit = circuit; curcircuit->end == 0; curcircuit ++, len ++) {
+ i = curcircuit->i;
+ j = curcircuit->j;
- if (!is_in_boundingbox(&dst_pt))
- return -1;
-
- NOTICE(E_USER_STRAT, "GOTO %"PRIi32",%"PRIi32"",
- dst_pt.x, dst_pt.y);
+/* printf("cur:%d,%d %x %x %x %d\n", i, j, */
+/* wcorn_retrieved, ucorn_retrieved, tomato_retrieved, len); */
- strat_goto_xy_force(dst_pt.x, dst_pt.y);
+ /* face A completed */
+ if (i == starti && j == startj) {
+ *scoreA = get_score(wcorn_retrieved, ucorn_retrieved,
+ tomato_retrieved, len);
+ wcorn_retrieved = 0; /* bit mask */
+ ucorn_retrieved = 0; /* bit mask */
+ tomato_retrieved = 0; /* bit mask */
+ len = 0;
+ }
- robot_pt->x = dst_pt.x;
- robot_pt->y = dst_pt.y;
+ /* is there a tomato ? */
+ if (strat_db.wp_table[i][j].type == WP_TYPE_TOMATO &&
+ strat_db.wp_table[i][j].present) {
+ tomato_retrieved |= (1UL << strat_db.wp_table[i][j].tomato.idx);
+ }
- return 0;
+ /* browse all neighbours to see if there is cobs */
+ for (pos = LINE_UP; pos <= LINE_R_DOWN; pos++) {
+ if (wp_get_neigh(i, j, &ni, &nj, pos) < 0)
+ continue;
+
+ /* is there a corn cob ? */
+ if (strat_db.wp_table[ni][nj].type == WP_TYPE_CORN &&
+ strat_db.wp_table[ni][nj].present) {
+ color = strat_db.wp_table[ni][nj].corn.color;
+ if (color == I2C_COB_WHITE)
+ wcorn_retrieved |= (1UL << strat_db.wp_table[ni][nj].corn.idx);
+ else if (color == I2C_COB_UNKNOWN)
+ ucorn_retrieved |= (1UL << strat_db.wp_table[ni][nj].corn.idx);
}
}
- }
+ };
- if (in_opp) {
- if (is_crossing_poly(*robot_pt, dst_pt, &intersect_opp_pt,
- pol_opp) == 1) {
- /* we add 2 cm to be sure we are out of th polygon */
- dst_pt.x = intersect_opp_pt.x + escape_dx * 2;
- dst_pt.y = intersect_opp_pt.y + escape_dy * 2;
+ *scoreB = get_score(wcorn_retrieved, ucorn_retrieved,
+ tomato_retrieved, len);
+ if (circuit->i == starti && circuit->j == startj)
+ *scoreA = *scoreB;
- if (is_point_in_poly(pol_disc, dst_pt.x, dst_pt.y) != 1) {
-
- if (!is_in_boundingbox(&dst_pt))
- return -1;
-
- NOTICE(E_USER_STRAT, "GOTO %"PRIi32",%"PRIi32"",
- dst_pt.x, dst_pt.y);
-
- strat_goto_xy_force(dst_pt.x, dst_pt.y);
-
- robot_pt->x = dst_pt.x;
- robot_pt->y = dst_pt.y;
+ return 0;
+}
- return 0;
- }
+/* i,j starting position */
+int8_t browse_circuits(uint8_t i, uint8_t j,
+ const struct wp_coord **selected_circuit,
+ int8_t *selected_face)
+{
+ const struct wp_coord **circuit;
+ int16_t scoreA, scoreB;
+ int16_t selected_score = 0x8000; /* ~-int_max */
+ int8_t found = -1;
+
+ *selected_face = 0;
+ *selected_circuit = circuits[0] ;
+ for (circuit = &circuits[0]; *circuit; circuit++) {
+ if (browse_one_circuit(*circuit, i, j, &scoreA, &scoreB) < 0)
+ continue;
+ found = 0;
+ printf_P(PSTR("Circuit: %d %d\r\n"), scoreA, scoreB);
+ if (scoreA > selected_score) {
+ *selected_circuit = *circuit;
+ selected_score = scoreA;
+ *selected_face = 0;
+ }
+ if (scoreB > selected_score) {
+ *selected_circuit = *circuit;
+ selected_score = scoreB;
+ *selected_face = 1;
}
}
-
- /* should not happen */
- return -1;
+ return found;
}
-
-static int8_t __goto_and_avoid(int16_t x, int16_t y,
- uint8_t flags_intermediate,
- uint8_t flags_final,
- uint8_t forward)
+static void dump_circuit_wp(struct wp_line *circuit_wpline, int8_t len)
{
- int8_t len = -1, i;
- point_t *p;
- poly_t *pol_disc, *pol_opp;
- int8_t ret;
- int16_t opp_w, opp_l, opp_x, opp_y;
- point_t p_dst, robot_pt;
-
- DEBUG(E_USER_STRAT, "%s(%d,%d) flags_i=%x flags_f=%x forw=%d",
- __FUNCTION__, x, y, flags_intermediate, flags_final, forward);
-
- retry:
- get_opponent_xy(&opp_x, &opp_y);
- opp_w = O_WIDTH;
- opp_l = O_LENGTH;
-
- robot_pt.x = position_get_x_s16(&mainboard.pos);
- robot_pt.y = position_get_y_s16(&mainboard.pos);
-
- oa_init();
- pol_disc = oa_new_poly(5);
- set_central_disc_poly(pol_disc, &robot_pt);
- pol_opp = oa_new_poly(4);
- set_opponent_poly(pol_opp, &robot_pt, O_WIDTH, O_LENGTH);
-
- /* If we are not in the limited area, try to go in it. */
- ret = go_in_area(&robot_pt);
-
- /* check that destination is valid */
- p_dst.x = x;
- p_dst.y = y;
- if (!is_in_boundingbox(&p_dst)) {
- NOTICE(E_USER_STRAT, " dst is not in playground");
- return END_ERROR;
+ int8_t i;
+ if (len <= 0)
+ return;
+ for (i = 0; i < len; i ++) {
+ printf_P(PSTR("linenum %d dir %d\r\n"), circuit_wpline[i].line_num,
+ circuit_wpline[i].dir);
}
- if (is_point_in_poly(pol_disc, x, y)) {
- NOTICE(E_USER_STRAT, " dst is in disc");
+
+}
+
+uint8_t strat_harvest_circuit(void)
+{
+ const struct wp_coord *selected_circuit;
+ int8_t selected_face;
+ struct wp_line circuit_wpline[MAX_CIRCUIT_WPLINE];
+ int8_t len;
+ uint8_t i, j, idx;
+ int16_t x, y;
+ uint8_t linenum, prev_linenum;
+ uint8_t dir, prev_dir;
+ uint8_t err;
+
+ x = position_get_x_s16(&mainboard.pos);
+ y = position_get_y_s16(&mainboard.pos);
+
+ if (xycoord_to_ijcoord(&x, &y, &i, &j) < 0) {
+ DEBUG(E_USER_STRAT, "%s(): cannot find waypoint at %d,%d",
+ __FUNCTION__, x, y);
return END_ERROR;
}
- if (is_point_in_poly(pol_opp, x, y)) {
- NOTICE(E_USER_STRAT, " dst is in opp");
+
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ len = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ if (len < 0) {
+ DEBUG(E_USER_STRAT, "%s(): cannot find a path",
+ __FUNCTION__);
return END_ERROR;
}
- /* now start to avoid */
- while (opp_w && opp_l) {
-
- /* robot_pt is not updated if it fails */
- ret = escape_from_poly(&robot_pt,
- pol_disc, opp_x, opp_y,
- opp_w, opp_l, pol_opp);
- if (ret == 0) {
- oa_reset();
- oa_start_end_points(robot_pt.x, robot_pt.y, x, y);
- /* oa_dump(); */
-
- len = oa_process();
- if (len >= 0)
- break;
- }
- if (distance_between(robot_pt.x, robot_pt.y, opp_x, opp_y) < REDUCE_POLY_THRES ) {
- if (opp_w == 0)
- opp_l /= 2;
- opp_w /= 2;
- }
- else {
- NOTICE(E_USER_STRAT, "oa_process() returned %d", len);
- return END_ERROR;
- }
-
- NOTICE(E_USER_STRAT, "reducing opponent %d %d", opp_w, opp_l);
- set_opponent_poly(pol_opp, &robot_pt, opp_w, opp_l);
- }
-
- p = oa_get_path();
- for (i=0 ; i<len ; i++) {
- DEBUG(E_USER_STRAT, "With avoidance %d: x=%"PRIi32" y=%"PRIi32"", i, p->x, p->y);
-
- if (forward)
- trajectory_goto_forward_xy_abs(&mainboard.traj, p->x, p->y);
- else
- trajectory_goto_backward_xy_abs(&mainboard.traj, p->x, p->y);
-
- /* no END_NEAR for the last point */
- if (i == len - 1)
- ret = wait_traj_end(flags_final);
- else
- ret = wait_traj_end(flags_intermediate);
-
- if (ret == END_BLOCKING) {
- DEBUG(E_USER_STRAT, "Retry avoidance %s(%d,%d)",
- __FUNCTION__, x, y);
+ dump_circuit_wp(circuit_wpline, len);
+
+ prev_linenum = circuit_wpline[0].line_num;
+ prev_dir = circuit_wpline[0].dir;
+ for (idx = 1; idx < len; idx ++) {
+ retry:
+ linenum = circuit_wpline[idx].line_num;
+ dir = circuit_wpline[idx].dir;
+
+ /* XXX basic opponent management */
+ DEBUG(E_USER_STRAT, "%s(): line %d dir %d -> line %d dir %d",
+ __FUNCTION__, prev_linenum, prev_dir, linenum, dir);
+ err = line2line(prev_linenum, prev_dir, linenum, dir,
+ TRAJ_FLAGS_NO_NEAR);
+ if (!TRAJ_SUCCESS(err)) {
+ strat_hardstop();
+ time_wait_ms(2000);
goto retry;
}
- else if (ret == END_OBSTACLE) {
- /* brake and wait the speed to be slow */
- DEBUG(E_USER_STRAT, "Retry avoidance %s(%d,%d)",
- __FUNCTION__, x, y);
- goto retry;
- }
- /* else if it is not END_TRAJ or END_NEAR, return */
- else if (!TRAJ_SUCCESS(ret)) {
- return ret;
- }
- p++;
+
+ prev_linenum = linenum;
+ prev_dir = dir;
}
-
- return END_TRAJ;
-}
-/* go forward to a x,y point. use current speed for that */
-uint8_t goto_and_avoid_forward(int16_t x, int16_t y, uint8_t flags_intermediate,
- uint8_t flags_final)
-{
- return __goto_and_avoid(x, y, flags_intermediate, flags_final, 1);
+ return END_TRAJ; // XXX
}
-/* go backward to a x,y point. use current speed for that */
-uint8_t goto_and_avoid_backward(int16_t x, int16_t y, uint8_t flags_intermediate,
- uint8_t flags_final)
+void test_strat_avoid(void)
{
- return __goto_and_avoid(x, y, flags_intermediate, flags_final, 0);
-}
-/* go to a x,y point. prefer backward but go forward if the point is
- * near and in front of us */
-uint8_t goto_and_avoid(int16_t x, int16_t y, uint8_t flags_intermediate,
- uint8_t flags_final)
-{
- double d,a;
- abs_xy_to_rel_da(x, y, &d, &a);
-
- if (d < 300 && a < RAD(90) && a > RAD(-90))
- return __goto_and_avoid(x, y, flags_intermediate,
- flags_final, 1);
- else
- return __goto_and_avoid(x, y, flags_intermediate,
- flags_final, 0);
+ //corn_count_neigh(1, 3);
+
+
+#if 0
+ uint8_t i, j;
+ const struct wp_coord *selected_circuit;
+ int8_t selected_face;
+ struct wp_line circuit_wpline[MAX_CIRCUIT_WPLINE];
+ int8_t ret;
+
+ i = 1; j = 1;
+ printf_P(PSTR("========= i=%d, j=%d\r\n"), i, j);
+
+ ts = 0; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 3; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 4; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 3; cc = 5;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 4; cc = 5;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 80; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ i = 4; j = 3;
+ printf_P(PSTR("========= i=%d, j=%d\r\n"), i, j);
+
+ ts = 0; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 3; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 80; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ i = 11; j = 6;
+ printf_P(PSTR("========= i=%d, j=%d\r\n"), i, j);
+
+ ts = 0; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 0; bc = 3; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+
+ ts = 80; bc = 0; cc = 0;
+ printf_P(PSTR("=== time=%"PRIu32", ball=%d, corn=%d\r\n"), ts, bc, cc);
+ browse_circuits(i, j, &selected_circuit, &selected_face);
+ ret = get_path(selected_circuit, i, j, selected_face, circuit_wpline);
+ dump_circuit_wp(circuit_wpline, ret);
+#endif
}