7 #include <movehelper.h>
14 #include "corns_configs.h"
15 #include "actuators.h"
17 #include "match-timing.h"
18 #include "eb2010misc.h"
22 UL_LOG_CUST(ulogd_common_states); /* Log domain name = ulogd + name of the file */
24 #include "common-states.h"
26 /************************************************************************
27 * Functions used in and called from all the (almost identical)
28 * "wait for start" states in particular strategies.
29 ************************************************************************/
32 #define DBG_FSM_STATE(name) do { if (fsm->debug_states) ul_loginf("fsm %s %.1f: %s(%s)\n", \
33 fsm->debug_name, robot_current_time(), \
34 name, fsm_event_str(fsm->events[fsm->ev_head])); } while(0)
37 static void set_initial_position()
39 robot_set_est_pos_trans(ROBOT_AXIS_TO_FRONT_M,
40 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2),
44 static void actuators_home()
47 act_vidle(VIDLE_UP - tmp, VIDLE_FAST_SPEED);
48 tmp = 1 - tmp; // Force movement (we need to change the target position)
54 robot.check_turn_safety = false;
55 pthread_create(&thid, NULL, timing_thread, NULL);
60 // We set initial position periodically in order for it to be updated
61 // on the display if the team color is changed during waiting for
65 set_initial_position();
66 if (robot.start_state == START_PLUGGED_IN)
72 sem_post(&robot.start);
74 set_initial_position();
79 robot.corns = get_all_corns(robot.corns_conf_side, robot.corns_conf_center);
83 /************************************************************************
84 * Trajectory constraints used; They are initialized in the main() function in competition.cc
85 ************************************************************************/
87 struct TrajectoryConstraints tcJerk, tcFast, tcSlow, tcVerySlow;
89 #define VIDLE_TIMEOUT 2000
91 /************************************************************************
92 * States that form the "collect some oranges" subautomaton. Calling automaton
93 * SHOULD ALWAYS call the "approach_the_slope" state.
94 ************************************************************************/
96 bool inline is_ready_to_climb_the_slope(enum which_side which_slope, double x, double y) {
98 if (which_slope == MINE) {
99 ret = x < 0.5 && y > PLAYGROUND_HEIGHT_M - 0.5;
100 } else if (which_slope == OPPONENTS) {
101 ret = x > 0.5 && y > PLAYGROUND_HEIGHT_M - 0.5;
103 ul_logfatal("ERROR: unknown side;");
104 #warning Remove the next line
110 static struct slope_approach_style *slope_approach_style_p;
112 /* assures that the robot is near the slope rim; if outside our starting area, approach the slope first */
113 FSM_STATE(approach_the_slope)
117 slope_approach_style_p = (struct slope_approach_style *) FSM_EVENT_PTR;
118 if (slope_approach_style_p == NULL) {
119 ul_logfatal("\n\nit is not allowed to call the approach_the_slope state with NULL data!!\n\n");
120 #warning remove the next line
124 robot_get_est_pos_trans(&x, &y, &phi);
126 bool ready_to_climb_the_slope = is_ready_to_climb_the_slope(slope_approach_style_p->which_side, x, y);
127 /* if necessary, approach the slope */
128 if (ready_to_climb_the_slope) {
129 FSM_TRANSITION(climb_the_slope);
132 x_coord(0.3, slope_approach_style_p->which_side),
133 PLAYGROUND_HEIGHT_M - ROBOT_WIDTH_M/2 - 0.03,
134 ARRIVE_FROM(DEG2RAD(0), 0.02),
140 FSM_TRANSITION(climb_the_slope);
146 case EV_MOTION_ERROR:
147 case EV_SWITCH_STRATEGY:
148 DBG_PRINT_EVENT("unhandled event");
154 void inline enable_switches(bool enabled)
156 robot.use_left_switch = enabled;
157 robot.use_right_switch = enabled;
158 robot.use_back_switch = enabled;
161 FSM_STATE(climb_the_slope)
163 struct TrajectoryConstraints tc;
166 // disables using side switches on bumpers when going up
167 enable_switches(false);
168 robot.ignore_hokuyo = true;
169 /* create the trajectory and go */
172 robot_trajectory_new_backward(&tc);
173 if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_BOUNDARY) {
174 act_vidle(VIDLE_LOAD_PREPARE, 5);
175 robot_trajectory_add_point_trans(
176 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
177 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) +0.01);
178 robot_trajectory_add_final_point_trans(
179 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M + 0.07, slope_approach_style_p->which_side),
180 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) +0.01,
182 } else if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_CENTER) {
184 robot_trajectory_add_point_trans(
185 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
186 //1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) + 0.01 - 1.85));
187 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.199);
188 robot_trajectory_add_final_point_trans(
189 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M + 0.07, slope_approach_style_p->which_side),
190 //1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) + 0.01 - 1.85),
191 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.199,
197 SUBFSM_TRANSITION(load_oranges, NULL);
200 FSM_TRANSITION(sledge_down);
203 act_vidle(VIDLE_LOAD_PREPARE, 15);
207 case EV_MOTION_ERROR:
208 case EV_SWITCH_STRATEGY:
209 DBG_PRINT_EVENT("unhandled event");
215 /* subautomaton to load oranges in two stages */
216 FSM_STATE_DECL(load_oranges2);
217 FSM_STATE_DECL(load_oranges3);
218 FSM_STATE(load_oranges)
223 act_vidle(VIDLE_MIDDLE, VIDLE_MEDIUM_SPEED);
229 FSM_TRANSITION(load_oranges2);
234 case EV_MOTION_ERROR:
235 case EV_SWITCH_STRATEGY:
236 DBG_PRINT_EVENT("unhandled event");
242 FSM_STATE(load_oranges2)
246 act_vidle(VIDLE_UP, VIDLE_MEDIUM_SPEED);
250 FSM_TRANSITION(load_oranges3);
254 FSM_TRANSITION(load_oranges3);
260 case EV_MOTION_ERROR:
261 case EV_SWITCH_STRATEGY:
262 DBG_PRINT_EVENT("unhandled event");
264 act_vidle(VIDLE_UP-1, VIDLE_FAST_SPEED);
269 FSM_STATE(load_oranges3)
273 act_vidle(VIDLE_MIDDLE+50, 0);
285 case EV_MOTION_ERROR:
286 case EV_SWITCH_STRATEGY:
287 DBG_PRINT_EVENT("unhandled event");
289 act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
294 FSM_STATE(sledge_down)
296 struct TrajectoryConstraints tc;
301 robot_trajectory_new(&tc);
303 if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_BOUNDARY) {
304 robot_trajectory_add_point_trans(
305 x_coord(1.2 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
306 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01);
307 robot_trajectory_add_point_trans(
308 x_coord(1.0 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
309 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.01);
310 robot_trajectory_add_point_trans(
311 x_coord(0.8 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
312 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.05);
313 robot_trajectory_add_point_trans(
314 x_coord(0.6 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
315 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.10);
316 robot_trajectory_add_final_point_trans(
317 x_coord(0.5 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
318 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.19,
320 } else if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_CENTER) {
321 robot_trajectory_add_point_trans(
322 x_coord(1 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
323 //1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01 - 1.85));
324 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.199);
325 robot_trajectory_add_final_point_trans(
326 x_coord(SLOPE_TO_RIM_M - ROBOT_AXIS_TO_BACK_M - 0.2, slope_approach_style_p->which_side),
327 //1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01 - 1.85),
328 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.199,
333 /* just for sure, try to close it one more time */
334 act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
336 delete(slope_approach_style_p);
342 case EV_MOTION_ERROR:
343 case EV_SWITCH_STRATEGY:
344 DBG_PRINT_EVENT("unhandled event");
347 // enables using side switches on bumpers
348 enable_switches(true);
349 robot.ignore_hokuyo = false;
350 robot.check_turn_safety = true;
356 /************************************************************************
357 * The "unload our oranges" subautomaton
358 ************************************************************************/
360 FSM_STATE(to_cntainer_and_unld)
362 TrajectoryConstraints tcNotSoFast = trajectoryConstraintsDefault;
363 tcNotSoFast.maxv = 0.5; tcNotSoFast.maxacc = 0.3; tcNotSoFast.maxomega = 2;
366 robot_goto_trans(PLAYGROUND_WIDTH_M-0.35, 0.45, ARRIVE_FROM(DEG2RAD(90),0.05), &tcNotSoFast);
369 FSM_TIMER(1000); // FIXME: test this
370 act_vidle(VIDLE_DOWN, VIDLE_FAST_SPEED);
373 FSM_TRANSITION(jerk);
378 case EV_MOTION_ERROR:
379 case EV_SWITCH_STRATEGY:
380 DBG_PRINT_EVENT("unhandled event");
388 static char move_cnt;
392 robot_move_by(-0.05, NO_TURN(), &tcJerk);
396 robot_move_by(0.05, NO_TURN(), &tcJerk);
397 } else if (move_cnt > 0) {
398 FSM_TIMER(1500); // FIXME: test this
403 act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
409 case EV_MOTION_ERROR:
410 case EV_SWITCH_STRATEGY:
411 DBG_PRINT_EVENT("unhandled event");
417 /************************************************************************
418 * The "collect corns" subautomaton
419 ************************************************************************/
421 static enum where_to_go {
426 } where_to_go = CORN;
428 static struct corn *corn_to_get;
430 FSM_STATE(rush_corns_decider)
434 if (where_to_go == CORN) {
435 FSM_TRANSITION(approach_next_corn);
436 } else if (where_to_go == CONTAINER) {
437 FSM_TRANSITION(rush_the_corn);
438 } else if (where_to_go == TURN_AROUND) {
439 FSM_TRANSITION(turn_around);
440 } else /* NO_MORE_CORN */ {
448 case EV_MOTION_ERROR:
449 case EV_SWITCH_STRATEGY:
450 DBG_PRINT_EVENT("unhandled event");
457 FSM_STATE(approach_next_corn)
462 robot_get_est_pos(&x, &y, &phi);
463 ul_logdeb("approach_next_corn: puck cnt: %d, est pos %.3f, %.3f, %.3f\n",
466 corn_to_get = choose_next_corn();
468 Pos *p = get_corn_approach_position(corn_to_get);
469 corn_to_get->was_collected = true;
470 robot_goto_trans(p->x, p->y, TURN(p->phi), &tcFast);
472 where_to_go = CONTAINER;
474 where_to_go = NO_MORE_CORN;
480 FSM_TRANSITION(rush_corns_decider);
486 case EV_MOTION_ERROR:
487 case EV_SWITCH_STRATEGY:
488 DBG_PRINT_EVENT("unhandled event");
494 FSM_STATE(rush_the_corn)
499 if (robot.team_color == BLUE) {
500 x = corn_to_get->position.x;
502 x = PLAYGROUND_WIDTH_M - corn_to_get->position.x;
504 remove_wall_around_corn(x, corn_to_get->position.y);
505 robot_goto_trans(PLAYGROUND_WIDTH_M - 0.4, 0.15, ARRIVE_FROM(DEG2RAD(-90), 0.02), &tcSlow);
506 where_to_go = TURN_AROUND;
509 FSM_TRANSITION(rush_last_cms);
515 case EV_MOTION_ERROR:
516 case EV_SWITCH_STRATEGY:
517 DBG_PRINT_EVENT("unhandled event");
523 FSM_STATE(rush_last_cms)
525 static char move_cnt;
528 robot.ignore_hokuyo = true;
529 robot.check_turn_safety = false;
531 robot_move_by(0.08, NO_TURN(), &tcSlow);
535 robot_move_by(-0.08, NO_TURN(), &tcSlow);
536 } else if (move_cnt > 0) {
537 FSM_TRANSITION(rush_corns_decider);
545 case EV_MOTION_ERROR:
546 case EV_SWITCH_STRATEGY:
547 DBG_PRINT_EVENT("unhandled event");
549 robot.ignore_hokuyo = false;
550 robot.check_turn_safety = true;
555 // used to perform the maneuvre
556 FSM_STATE(turn_around)
560 robot_trajectory_new_backward(&tcFast);
561 robot_trajectory_add_final_point_trans(PLAYGROUND_WIDTH_M-0.35, 0.45, TURN_CCW(90));
565 FSM_TRANSITION(rush_corns_decider);
571 case EV_MOTION_ERROR:
572 case EV_SWITCH_STRATEGY:
573 DBG_PRINT_EVENT("unhandled event");