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