6 #include <movehelper.h>
16 #include <shape_detect.h>
19 #include "actuators.h"
20 #include "match-timing.h"
21 #include "common-states.h"
22 #include "sub-states.h"
24 UL_LOG_CUST(ulogd_common_states); /* Log domain name = ulogd + name of the file */
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)
36 /************************************************************************
37 * Trajectory constraints used; They are initialized in the main() function in competition.cc
38 ************************************************************************/
40 struct TrajectoryConstraints tcFast, tcSlow, tcVerySlow;
43 * Vector where all absolute positions of all detected targets are stored.
45 std::vector<robot_pos_type> detected_target;
48 * Safe distance for target recognition
50 const double approach_radius = TARGET_RADIUS_M + 2.0*MAP_CELL_SIZE_M + ROBOT_DIAGONAL_RADIUS_M;
52 void set_initial_position()
54 robot_set_est_pos_trans(HOME_POS_X_M, HOME_POS_Y_M, DEG2RAD(HOME_POS_ANG_DEG));
59 //act_crane(CRANE_UP);
63 /* Check if the new point is within the playground scene */
64 bool goal_is_in_playground(double goalx, double goaly)
66 if ((goalx < 0) || (goalx > PLAYGROUND_WIDTH_M) || (goaly < 0) || (goaly > PLAYGROUND_HEIGHT_M))
72 /* Check if the new point is close to the robot */
73 bool close_goal(double goalx, double goaly)
75 const double close = 0.5;
77 robot_get_est_pos(&x, &y, &phi);
79 if ((abs(goalx - x) < close) && (abs(goaly - y) < close) )
86 * Take data from hokuyo and run shape detection on it.
88 * Absolute positions of all detected targets centers are stored in alobal variable (vector).
90 * @return True if at least one target detected, else false.
92 static bool detect_target()
94 struct hokuyo_scan_type hokuyo = robot.hokuyo;
97 std::vector<Shape_detect::Arc> arcs;
98 sd.prepare(hokuyo.data);
102 detected_target.clear();
104 if (arcs.size() > 0) {
105 robot_pos_type e, target, hok;
107 robot_get_est_pos(&e.x, &e.y, &e.phi);
109 double sinus = sin(e.phi);
110 double cosinus = cos(e.phi);
112 // save absolute positions of all detected targets
113 for (int i = 0; i < arcs.size(); i++) {
114 Shape_detect::Arc *a = &arcs[i];
116 hok.x = HOKUYO_CENTER_OFFSET_M + (double)a->center.x / 1000.0;
117 hok.y = (double)a->center.y / 1000.0;
119 /* transform target position which is relative to Hokuyo
120 center to absolute position in space */
121 target.x = (hok.x * cosinus) - (hok.y * sinus) + e.x;
122 target.y = (hok.x * sinus) + (hok.y * cosinus) + e.y;
124 // filter those targets not in playground range
125 if (goal_is_in_playground(target.x, target.y))
126 detected_target.push_back(target);
135 * Calculates point to approach the target.
137 * @param target Position of the center of the target.
138 * @param approach Pointer to the the intersection point of circle around
139 * the target and line between robot center and target.
141 void get_approach_point(double xtarget, double ytarget, double *xapproach, double *yapproach, double *phi_approach)
143 double xrobot, yrobot, phi;
146 robot_get_est_pos(&xrobot, &yrobot, &phi);
148 delta = distance(xrobot, yrobot, xtarget, ytarget);
150 *xapproach = xtarget - (approach_radius * (xtarget - xrobot) / delta);
151 *yapproach = ytarget - (approach_radius * (ytarget - yrobot) / delta);
153 *phi_approach = get_approach_angle(xtarget, ytarget);
157 * Calculates point to approach the target.
159 * @param target Position of the center of the target.
160 * @return Angle to approach the target form.
162 double get_approach_angle(double xtarget, double ytarget)
164 double xrobot, yrobot,phi;
166 robot_get_est_pos(&xrobot, &yrobot, &phi);
168 return atan2((ytarget - yrobot), (xtarget - xrobot));
173 * FSM state for neighborhood observation.
175 * Detect targets using shape_detect.
176 * If no target detected, turn 120deg and try again.
177 * Scan all 360deg and then go back to move_around state.
179 * If target detected, go to approach_target state.
183 static char turn_cntr = 0;
188 DBG_PRINT_EVENT("survey");
190 robot_pos_type target;
191 detected_target.clear();
192 for (double i = 1; i < 5; i++) {
195 detected_target.push_back(target);
197 // target detected, go to the target
198 FSM_TRANSITION(approach_target);
199 DBG_PRINT_EVENT("Target detected!");
201 // no target detected in this heading, turn 120°
202 robot_get_est_pos(&x, &y, &phi);
203 robot_goto_notrans(x, y, TURN(DEG2RAD(120)+phi), &tcSlow);
205 DBG_PRINT_EVENT("no target");
210 FSM_TRANSITION(move_around);
212 FSM_TRANSITION(survey);
221 case EV_SWITCH_STRATEGY:
222 DBG_PRINT_EVENT("unhandled event!");
224 case EV_MOTION_ERROR:
225 FSM_TRANSITION(move_around);
234 * FSM state for approaching all detected targets.
236 * Try to approach target.
237 * If approach OK - go to subautomaton and do target recognition, touch and load.
238 * On subautomaton return check if target loaded/valid.
240 * If target loaded, go home.
241 * If target not valid, try next target if any.
242 * If approach not succesfull - go to move_around state.
244 FSM_STATE(approach_target)
246 static int target_cntr = 0;
247 int max_target = detected_target.size();
248 double x_target, y_tatget;
249 double x_approach, y_approach, phi_approach;
253 DBG_PRINT_EVENT("approaching target");
254 x_target = detected_target[target_cntr].x;
255 y_tatget = detected_target[target_cntr].y;
258 get_approach_point(x_target, y_tatget, &x_approach, &y_approach, &phi_approach);
259 robot_goto_notrans(x_approach, y_approach, ARRIVE_FROM(phi_approach, 0.2), &tcSlow);
262 DBG_PRINT_EVENT("target approached");
263 SUBFSM_TRANSITION(recognize, NULL);
266 if (robot.target_loaded) {
267 FSM_TRANSITION(go_home);
268 } else if (robot.target_valid) {
269 //FIXME target is valid but not loaded - try another approach direction
271 } else if (!robot.target_valid && (target_cntr < max_target)) {
272 // go for next target if any
273 FSM_TRANSITION(approach_target);
275 // go to new point and survey
276 FSM_TRANSITION(move_around);
279 case EV_MOTION_ERROR:
280 DBG_PRINT_EVENT("ERROR approaching");
281 if (target_cntr < max_target) {
282 FSM_TRANSITION(approach_target);
284 FSM_TRANSITION(move_around);
290 case EV_SWITCH_STRATEGY:
291 DBG_PRINT_EVENT("unhandled event");
299 FSM_STATE(move_around)
301 double goalx, goaly, phi;
302 static int survey_cnt = 0;
308 goalx = ((rand()%PLAYGROUND_HEIGHT_MM)/1000.0);
309 goaly = ((rand()%PLAYGROUND_WIDTH_MM)/1000.0);
310 } while (!ShmapIsFreePoint(goalx, goaly) && close_goal(goalx, goaly));
312 robot_goto_notrans(goalx, goaly, NO_TURN(), &tcFast);
313 DBG_PRINT_EVENT("new survey point");
316 case EV_MOTION_ERROR:
317 DBG_PRINT_EVENT("ERROR: can not access survey point");
319 FSM_TRANSITION(survey);
340 DBG_PRINT_EVENT("homing");
341 robot_goto_notrans(HOME_POS_X_M, HOME_POS_Y_M, ARRIVE_FROM(DEG2RAD(HOME_POS_ANG_DEG), 0.2), &tcSlow);
343 case EV_MOTION_ERROR:
344 DBG_PRINT_EVENT("ERROR: home position is not reachable!");
350 FSM_TRANSITION(go_home);
358 DBG_PRINT_EVENT("Mission completed!");
375 case EV_MOTION_ERROR:
376 case EV_SWITCH_STRATEGY:
377 DBG_PRINT_EVENT("unhandled event");