]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/robofsm/common-states.cc
robofsm: Switch on camera during initialization
[eurobot/public.git] / src / robofsm / common-states.cc
1 #define FSM_MAIN
2 #include <robodata.h>
3 #include <robot.h>
4 #include <fsm.h>
5 #include <unistd.h>
6 #include <math.h>
7 #include <movehelper.h>
8 #include <map.h>
9 #include <sharp.h>
10 #include <robomath.h>
11 #include <string.h>
12 #include <robodim.h>
13 #include <error.h>
14 #include "corns_configs.h"
15 #include "actuators.h"
16 #include <trgen.h>
17 #include "match-timing.h"
18 #include "eb2010misc.h"
19 #include <stdbool.h>
20
21 #include "common-states.h"
22
23 /************************************************************************
24  * Functions used in and called from all the (almost identical)
25  * "wait for start" states in particular strategies.
26  ************************************************************************/
27
28 #undef DBG_FSM_STATE
29 #define DBG_FSM_STATE(name)     do { if (fsm->debug_states) printf("fsm %s %.1f: %s(%s)\n", \
30                                                                    fsm->debug_name, robot_current_time(), \
31                                                                    name, fsm_event_str(fsm->events[fsm->ev_head])); } while(0)
32
33
34 static void set_initial_position()
35 {
36         robot_set_est_pos_trans(ROBOT_AXIS_TO_FRONT_M,
37                                 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2),
38                                 DEG2RAD(180));
39 }
40
41 static void actuators_home()
42 {
43         static int tmp = 0;
44         act_vidle(VIDLE_UP - tmp, VIDLE_FAST_SPEED);
45         tmp = 1 - tmp;          // Force movement (we need to change the target position)
46 }
47
48 void start_entry()
49 {
50         pthread_t thid;
51         robot.check_turn_safety = false;
52         pthread_create(&thid, NULL, timing_thread, NULL);
53         start_timer();
54         act_camera_on();
55 }
56
57 // We set initial position periodically in order for it to be updated
58 // on the display if the team color is changed during waiting for
59 // start.
60 void start_timer()
61 {
62         set_initial_position();
63         if (robot.start_state == START_PLUGGED_IN)
64                 actuators_home();
65 }
66
67 void start_go()
68 {
69         sem_post(&robot.start);
70         actuators_home();
71         set_initial_position();
72 }
73
74 void start_exit()
75 {
76         robot.corns = get_all_corns(robot.corns_conf_side, robot.corns_conf_center);
77         act_camera_off();
78 }
79
80 /************************************************************************
81  * Trajectory constraints used; They are  initialized in the main() function in competition.cc
82  ************************************************************************/
83
84 struct TrajectoryConstraints tcFast, tcSlow, tcVerySlow;
85
86 #define VIDLE_TIMEOUT 2000
87
88 /************************************************************************
89  * States that form the "collect some oranges" subautomaton. Calling automaton
90  * SHOULD ALWAYS call the "approach_the_slope" state.
91  ************************************************************************/
92
93 bool inline is_ready_to_climb_the_slope(enum which_side which_slope, double x, double y) {
94         bool ret;
95         if (which_slope == MINE) {
96                 ret = x < 0.5 && y > PLAYGROUND_HEIGHT_M - 0.5;
97         } else if (which_slope == OPPONENTS) {
98                 ret = x > 0.5 && y > PLAYGROUND_HEIGHT_M - 0.5;
99         } else {
100                 printf("ERROR: unknown side;");
101 #warning Remove the next line
102                 robot_exit();
103         }
104         return ret;
105 }
106
107 static struct slope_approach_style *slope_approach_style_p;
108
109 /* assures that the robot is near the slope rim; if outside our starting area, approach the slope first */
110 FSM_STATE(approach_the_slope)
111 {
112         switch(FSM_EVENT) {
113                 case EV_ENTRY: {
114                                 slope_approach_style_p = (struct slope_approach_style *) FSM_EVENT_PTR;
115                                 if (slope_approach_style_p == NULL) {
116                                         printf("\n\nit is not allowed to call the approach_the_slope state  with NULL data!!\n\n");
117 #warning remove the next line
118                                         robot_exit();
119                                 }
120                                 double x, y, phi;
121                                 robot_get_est_pos_trans(&x, &y, &phi);
122                                 /* decide */
123                                 bool ready_to_climb_the_slope = is_ready_to_climb_the_slope(slope_approach_style_p->which_side, x, y);
124                                 /* if necessary, approach the slope */
125                                 if (ready_to_climb_the_slope) {
126                                         FSM_TRANSITION(climb_the_slope);
127                                 } else {
128                                         robot_goto_trans(
129                                                 x_coord(0.3, slope_approach_style_p->which_side),
130                                                 PLAYGROUND_HEIGHT_M - ROBOT_WIDTH_M/2 - 0.03,
131                                                 ARRIVE_FROM(DEG2RAD(0), 0.02),
132                                                 &tcFast);
133                                 }
134                                 break;
135                         }
136                 case EV_MOTION_DONE:
137                         FSM_TRANSITION(climb_the_slope);
138                         break;
139                 case EV_START:
140                 case EV_TIMER:
141                 case EV_RETURN:
142                 case EV_VIDLE_DONE:
143                 case EV_MOTION_ERROR:
144                 case EV_SWITCH_STRATEGY:
145                         DBG_PRINT_EVENT("unhandled event");
146                 case EV_EXIT:
147                         break;
148         }
149 }
150
151 void inline enable_switches(bool enabled)
152 {
153         robot.use_left_switch = enabled;
154         robot.use_right_switch = enabled;
155         robot.use_back_switch = enabled;
156 }
157
158 FSM_STATE(climb_the_slope)
159 {
160         struct TrajectoryConstraints tc;
161         switch(FSM_EVENT) {
162                 case EV_ENTRY: {
163                                 // disables using side switches on bumpers when going up
164                                 enable_switches(false);
165                                 robot.ignore_hokuyo = true;
166                                 /* create the trajectory and go */
167                                 tc = tcSlow;
168                                 tc.maxacc = 0.4;
169                                 robot_trajectory_new_backward(&tc);
170                                 if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_BOUNDARY) {
171                                         act_vidle(VIDLE_LOAD_PREPARE, 5);
172                                         robot_trajectory_add_point_trans(
173                                                 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
174                                                 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) +0.01);
175                                         robot_trajectory_add_final_point_trans(
176                                                 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M + 0.07, slope_approach_style_p->which_side),
177                                                 PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) +0.01,
178                                                 NO_TURN());
179                                 } else if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_CENTER) {
180                                         FSM_TIMER(3500);
181                                         robot_trajectory_add_point_trans(
182                                                 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
183                                                 1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) + 0.01 - 1.85));
184                                         robot_trajectory_add_final_point_trans(
185                                                 x_coord(SLOPE_TO_RIM_M + SLOPE_LENGTH_M - ROBOT_AXIS_TO_BACK_M + 0.07, slope_approach_style_p->which_side),
186                                                 1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) + 0.01 - 1.85),
187                                                 NO_TURN());
188                                 }
189                                 break;
190                         }
191                 case EV_MOTION_DONE:
192                         SUBFSM_TRANSITION(load_oranges, NULL);
193                         break;
194                 case EV_RETURN:
195                         FSM_TRANSITION(sledge_down);
196                         break;
197                 case EV_TIMER:
198                         act_vidle(VIDLE_LOAD_PREPARE, 10);
199                         break;
200                 case EV_START:
201                 case EV_VIDLE_DONE:
202                 case EV_MOTION_ERROR:
203                 case EV_SWITCH_STRATEGY:
204                         DBG_PRINT_EVENT("unhandled event");
205                 case EV_EXIT:
206                         break;
207         }
208 }
209
210 /* subautomaton to load oranges in two stages */
211 FSM_STATE_DECL(load_oranges2);
212 FSM_STATE_DECL(load_oranges3);
213 FSM_STATE(load_oranges)
214 {
215         switch(FSM_EVENT) {
216                 case EV_ENTRY:
217                         FSM_TIMER(1000);
218                         act_vidle(VIDLE_MIDDLE, VIDLE_MEDIUM_SPEED);
219                         break;
220                 case EV_VIDLE_DONE:
221                         FSM_TIMER(1000);
222                         break;
223                 case EV_TIMER:
224                         FSM_TRANSITION(load_oranges2);
225                         break;
226                 case EV_MOTION_DONE:
227                 case EV_START:
228                 case EV_RETURN:
229                 case EV_MOTION_ERROR:
230                 case EV_SWITCH_STRATEGY:
231                         DBG_PRINT_EVENT("unhandled event");
232                 case EV_EXIT:
233                         break;
234         }
235 }
236
237 FSM_STATE(load_oranges2)
238 {
239         switch(FSM_EVENT) {
240                 case EV_ENTRY:
241                         act_vidle(VIDLE_UP, VIDLE_MEDIUM_SPEED);
242                         FSM_TIMER(1000);
243                         break;
244                 case EV_VIDLE_DONE:
245                         FSM_TRANSITION(load_oranges3);
246                         //SUBFSM_RET(NULL);
247                         break;
248                 case EV_TIMER:
249                         FSM_TRANSITION(load_oranges3);
250                         //SUBFSM_RET(NULL);
251                         break;
252                 case EV_MOTION_DONE:
253                 case EV_START:
254                 case EV_RETURN:
255                 case EV_MOTION_ERROR:
256                 case EV_SWITCH_STRATEGY:
257                         DBG_PRINT_EVENT("unhandled event");
258                 case EV_EXIT:
259                         act_vidle(VIDLE_UP-1, VIDLE_FAST_SPEED);
260                         break;
261         }
262 }
263
264 FSM_STATE(load_oranges3)
265 {
266         switch(FSM_EVENT) {
267                 case EV_ENTRY:
268                         act_vidle(VIDLE_MIDDLE+50, 0);
269                         FSM_TIMER(500);
270                         break;
271                 case EV_VIDLE_DONE:
272                         SUBFSM_RET(NULL);
273                         break;
274                 case EV_TIMER:
275                         SUBFSM_RET(NULL);
276                         break;
277                 case EV_MOTION_DONE:
278                 case EV_START:
279                 case EV_RETURN:
280                 case EV_MOTION_ERROR:
281                 case EV_SWITCH_STRATEGY:
282                         DBG_PRINT_EVENT("unhandled event");
283                 case EV_EXIT:
284                         act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
285                         break;
286         }
287 }
288
289 FSM_STATE(sledge_down)
290 {       
291         struct TrajectoryConstraints tc;
292         switch(FSM_EVENT) {
293                 case EV_ENTRY:
294                         tc = tcFast;
295                         tc.maxe = 0.5;
296                         robot_trajectory_new(&tc);
297
298                         if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_BOUNDARY) {
299                                 robot_trajectory_add_point_trans(
300                                         x_coord(1.2 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
301                                         PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01);
302                                 robot_trajectory_add_point_trans(
303                                         x_coord(1.0 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
304                                         PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.01);
305                                 robot_trajectory_add_point_trans(
306                                         x_coord(0.8 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
307                                         PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.05);
308                                 robot_trajectory_add_point_trans(
309                                         x_coord(0.6 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
310                                         PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.10);
311                                 robot_trajectory_add_final_point_trans(
312                                         x_coord(0.5 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
313                                         PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2) - 0.17,
314                                         NO_TURN());
315                         } else if (slope_approach_style_p->which_oranges == NEAR_PLAYGROUND_CENTER) {
316                                 robot_trajectory_add_point_trans(
317                                         x_coord(1 - ROBOT_AXIS_TO_BACK_M, slope_approach_style_p->which_side),
318                                         1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01 - 1.85));
319                                 robot_trajectory_add_final_point_trans(
320                                         x_coord(SLOPE_TO_RIM_M - ROBOT_AXIS_TO_BACK_M - 0.2, slope_approach_style_p->which_side),
321                                         1.85 - (PLAYGROUND_HEIGHT_M - (ROBOT_WIDTH_M/2)+0.01 - 1.85),
322                                         NO_TURN());
323                         }
324                         break;
325                 case EV_MOTION_DONE:
326                         /* just for sure, try to close it one more time */
327                         act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
328                         SUBFSM_RET(NULL);
329                         delete(slope_approach_style_p);
330                         break;
331                 case EV_START:
332                 case EV_TIMER:
333                 case EV_RETURN:
334                 case EV_VIDLE_DONE:
335                 case EV_MOTION_ERROR:
336                 case EV_SWITCH_STRATEGY:
337                         DBG_PRINT_EVENT("unhandled event");
338                         break;
339                 case EV_EXIT:
340                         // enables using side switches on bumpers
341                         enable_switches(true);
342                         robot.ignore_hokuyo = false;
343                         robot.check_turn_safety = true;
344
345                         break;
346         }
347 }
348
349 /************************************************************************
350  * The "unload our oranges" subautomaton
351  ************************************************************************/
352
353 FSM_STATE(to_cntainer_and_unld)
354 {
355         switch(FSM_EVENT) {
356                 case EV_ENTRY:
357                         robot_goto_trans(PLAYGROUND_WIDTH_M-0.35, 0.45, ARRIVE_FROM(DEG2RAD(90),0.05), &tcFast);
358                         break;
359                 case EV_MOTION_DONE:
360                         FSM_TIMER(3000); // FIXME: test this
361                         act_vidle(VIDLE_DOWN, VIDLE_FAST_SPEED);
362                         break;
363                 case EV_TIMER:
364                         act_vidle(VIDLE_UP, VIDLE_FAST_SPEED);
365                         SUBFSM_RET(NULL);
366                         break;
367                 case EV_START:
368                 case EV_RETURN:
369                 case EV_VIDLE_DONE:
370                 case EV_MOTION_ERROR:
371                 case EV_SWITCH_STRATEGY:
372                         DBG_PRINT_EVENT("unhandled event");
373                 case EV_EXIT:
374                         break;
375         }
376 }
377
378 /************************************************************************
379  * The "collect corns" subautomaton
380  ************************************************************************/
381
382 static enum where_to_go {
383         CORN,
384         TURN_AROUND,
385         CONTAINER,
386         NO_MORE_CORN
387 } where_to_go = CORN;
388
389 static struct corn *corn_to_get;
390
391 FSM_STATE(rush_corns_decider)
392 {
393         switch(FSM_EVENT) {
394                 case EV_ENTRY:
395                         if (where_to_go == CORN) {
396                                 FSM_TRANSITION(approach_next_corn);
397                         } else if (where_to_go == CONTAINER) {
398                                 FSM_TRANSITION(rush_the_corn);
399                         } else if (where_to_go == TURN_AROUND) {
400                                 FSM_TRANSITION(turn_around);
401                         } else /* NO_MORE_CORN */ { 
402                         }
403                         break;
404                 case EV_START:
405                 case EV_TIMER:
406                 case EV_RETURN:
407                 case EV_VIDLE_DONE:
408                 case EV_MOTION_DONE:
409                 case EV_MOTION_ERROR:
410                 case EV_SWITCH_STRATEGY:
411                         DBG_PRINT_EVENT("unhandled event");
412                 case EV_EXIT:
413                         break;
414         }
415 }
416
417 static int cnt = 0;
418 FSM_STATE(approach_next_corn)
419 {
420         switch(FSM_EVENT) {
421                 case EV_ENTRY: {
422                                 double x, y, phi;
423                                 robot_get_est_pos(&x, &y, &phi);
424                                 printf("approach_next_corn: puck cnt: %d, est pos %.3f, %.3f, %.3f\n",
425                                         cnt, x, y, phi);
426
427                                 corn_to_get = choose_next_corn();
428                                 if (corn_to_get) {
429                                         Pos *p = get_corn_approach_position(corn_to_get);
430                                         corn_to_get->was_collected = true;
431                                         robot_goto_trans(p->x, p->y, TURN(p->phi), &tcFast);
432                                         delete(p);
433                                         where_to_go = CONTAINER;
434                                 } else {
435                                         where_to_go = NO_MORE_CORN;
436                                 }
437                                 break;
438                         }
439                 case EV_MOTION_DONE:
440                         cnt++;
441                         FSM_TRANSITION(rush_corns_decider);
442                         break;
443                 case EV_START:
444                 case EV_TIMER:
445                 case EV_RETURN:
446                 case EV_VIDLE_DONE:
447                 case EV_MOTION_ERROR:
448                 case EV_SWITCH_STRATEGY:
449                         DBG_PRINT_EVENT("unhandled event");
450                 case EV_EXIT:
451                         break;
452         }
453 }
454
455 FSM_STATE(rush_the_corn)
456 {
457         switch(FSM_EVENT) {
458                 case EV_ENTRY:
459                         double x;
460                         if (robot.team_color == BLUE) {
461                                 x = corn_to_get->position.x;
462                         } else {
463                                 x = PLAYGROUND_WIDTH_M - corn_to_get->position.x;
464                         }
465                         remove_wall_around_corn(x, corn_to_get->position.y);
466                         robot_goto_trans(PLAYGROUND_WIDTH_M - 0.4, 0.15, ARRIVE_FROM(DEG2RAD(-90), 0.02), &tcSlow);
467                         where_to_go = TURN_AROUND;
468                         break;
469                 case EV_MOTION_DONE:
470                         FSM_TRANSITION(rush_corns_decider);
471                         break;
472                 case EV_START:
473                 case EV_TIMER:
474                 case EV_RETURN:
475                 case EV_VIDLE_DONE:
476                 case EV_MOTION_ERROR:
477                 case EV_SWITCH_STRATEGY:
478                         DBG_PRINT_EVENT("unhandled event");
479                 case EV_EXIT:
480                         break;
481         }
482 }
483
484 // used to perform the maneuvre
485 FSM_STATE(turn_around)
486 {
487         switch(FSM_EVENT) {
488                 case EV_ENTRY:
489                         robot_trajectory_new_backward(&tcFast);
490                         robot_trajectory_add_final_point_trans(PLAYGROUND_WIDTH_M-0.35, 0.45, TURN_CCW(90));
491                         break;
492                 case EV_MOTION_DONE:
493                         where_to_go = CORN;
494                         FSM_TRANSITION(rush_corns_decider);
495                         break;
496                 case EV_START:
497                 case EV_TIMER:
498                 case EV_RETURN:
499                 case EV_VIDLE_DONE:
500                 case EV_MOTION_ERROR:
501                 case EV_SWITCH_STRATEGY:
502                         DBG_PRINT_EVENT("unhandled event");
503                 case EV_EXIT:
504                         break;
505         }
506 }