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 const double xcenter = (PLAYGROUND_WIDTH_M / 2.0);
53 const double ycenter = ((PLAYGROUND_HEIGHT_M / 4.0) * 3.0);
55 void set_initial_position()
57 robot_set_est_pos_trans(ROBOT_START_X_M, ROBOT_START_Y_M, DEG2RAD(ROBOT_START_ANGLE_DEG));
65 /* Check if the new point is within the playground scene */
66 bool goal_is_in_playground(double goalx, double goaly)
68 if ((goalx < 0) || (goalx > PLAYGROUND_WIDTH_M) || (goaly < 0) || (goaly > PLAYGROUND_HEIGHT_M))
74 /* Check if the new point is close to the robot */
75 bool close_goal(double goalx, double goaly)
77 const double close = 0.5;
79 robot_get_est_pos(&x, &y, &phi);
81 if ((abs(goalx - x) < close) && (abs(goaly - y) < close) )
88 * Take data from hokuyo and run shape detection on it.
90 * Absolute positions of all detected targets centers are stored in alobal variable (vector).
92 * @return True if at least one target detected, else false.
94 static bool detect_target()
96 struct hokuyo_scan_type hokuyo = robot.hokuyo;
99 std::vector<Shape_detect::Arc> arcs;
100 sd.prepare(hokuyo.data);
104 detected_target.clear();
106 if (arcs.size() > 0) {
107 robot_pos_type e, target, hok;
109 robot_get_est_pos(&e.x, &e.y, &e.phi);
111 double sinus = sin(e.phi);
112 double cosinus = cos(e.phi);
114 // save absolute positions of all detected targets
115 for (int i = 0; i < arcs.size(); i++) {
116 Shape_detect::Arc *a = &arcs[i];
118 hok.x = HOKUYO_CENTER_OFFSET_M + (double)a->center.x / 1000.0;
119 hok.y = (double)a->center.y / 1000.0;
121 /* transform target position which is relative to Hokuyo
122 center to absolute position in space */
123 target.x = (hok.x * cosinus) - (hok.y * sinus) + e.x;
124 target.y = (hok.x * sinus) + (hok.y * cosinus) + e.y;
126 // filter those targets not in playground range
127 //if (goal_is_in_playground(target.x, target.y))
128 // detected_target.push_back(target);
131 return detected_target.size();
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)
145 delta = distance(xcenter, ycenter, xtarget, ytarget);
147 *xapproach = xtarget - (approach_radius * (xtarget - xcenter) / delta);
148 *yapproach = ytarget - (approach_radius * (ytarget - ycenter) / delta);
150 *phi_approach = get_approach_angle(xtarget, ytarget);
154 * Calculates point to approach the target.
156 * @param target Position of the center of the target.
157 * @return Angle to approach the target form.
159 double get_approach_angle(double xtarget, double ytarget)
162 return atan2((ytarget - ycenter), (xtarget - xcenter));
167 * FSM state for neighborhood observation.
169 * Detect targets using shape_detect.
170 * If no target detected, turn 120deg and try again.
171 * Scan all 360deg and then go back to move_around state.
173 * If target detected, go to approach_target state.
177 static char turn_cntr = 0;
182 DBG_PRINT_EVENT("survey");
183 #if 1 // FIXME just for test
184 if (detect_target()) {
187 robot_pos_type target;
188 detected_target.clear();
189 for (double i = 1; i < 5; i++) {
192 detected_target.push_back(target);
195 // target detected, go to the target
196 FSM_TRANSITION(approach_target);
197 DBG_PRINT_EVENT("Target detected!");
199 // no target detected in this heading, turn 120°
200 robot_get_est_pos(&x, &y, &phi);
201 robot_goto_notrans(x, y, TURN(DEG2RAD(120)+phi), &tcSlow);
203 DBG_PRINT_EVENT("no target");
208 FSM_TRANSITION(move_around);
210 FSM_TRANSITION(survey);
216 case EV_MOTION_ERROR:
217 FSM_TRANSITION(move_around);
226 * FSM state for approaching all detected targets.
228 * Try to approach target.
229 * If approach OK - go to subautomaton and do target recognition, touch and load.
230 * On subautomaton return check if target loaded/valid.
232 * If target loaded, go home.
233 * If target not valid, try next target if any.
234 * If approach not succesfull - go to move_around state.
236 FSM_STATE(approach_target)
238 double x_approach, y_approach, phi_approach;
242 DBG_PRINT_EVENT("approaching target");
244 get_approach_point(robot.target_pos.x, robot.target_pos.y, &x_approach, &y_approach, &phi_approach);
245 robot_goto_notrans(x_approach, y_approach, ARRIVE_FROM(phi_approach, 0.2), &tcFast);
248 DBG_PRINT_EVENT("target approached");
249 SUBFSM_TRANSITION(get_target_turn, NULL);
252 if (robot.target_loaded) {
253 FSM_TRANSITION(go_home);
255 DBG_PRINT_EVENT("target not loaded");
256 FSM_TRANSITION(move_around);
259 case EV_MOTION_ERROR:
260 DBG_PRINT_EVENT("can not approach target");
261 FSM_TRANSITION(move_around);
268 FSM_STATE(move_around)
274 robot_trajectory_new(&tcFast);
275 robot_trajectory_add_point_notrans(1, 2);
276 robot_trajectory_add_point_notrans(0.7, 2.2);
277 robot_trajectory_add_point_notrans(0.65, 2.1);
278 robot_trajectory_add_final_point_notrans(0.7, 2, NO_TURN());
280 case EV_MOTION_ERROR:
281 DBG_PRINT_EVENT("can not access survey point");
283 FSM_TRANSITION(move_around);
285 case EV_TARGET_DETECTED:
287 robot.target_localization_enab = false;
288 FSM_TRANSITION(approach_target);
297 FSM_STATE(approach_arena)
301 DBG_PRINT_EVENT("approaching arena");
302 robot_goto_notrans(1.15, 1.35, ARRIVE_FROM(DEG2RAD(90), 0.1), &tcFast);
303 robot.target_localization_enab = true;
305 case EV_MOTION_ERROR:
306 DBG_PRINT_EVENT("ERROR: position is not reachable!");
307 FSM_TRANSITION(approach_arena);
310 FSM_TRANSITION(move_around);
312 case EV_TARGET_DETECTED:
314 robot.target_localization_enab = false;
315 FSM_TRANSITION(approach_target);
320 DBG_PRINT_EVENT("Unhandled event!");
329 DBG_PRINT_EVENT("homing");
330 robot_goto_notrans(ROBOT_START_X_M, ROBOT_START_Y_M + 0.3, ARRIVE_FROM(DEG2RAD(270), 0.1), &tcFast);
332 case EV_MOTION_ERROR:
333 DBG_PRINT_EVENT("ERROR: home position is not reachable!");
338 DBG_PRINT_EVENT("Mission completed!");
355 case EV_MOTION_ERROR:
356 case EV_SWITCH_STRATEGY:
357 DBG_PRINT_EVENT("unhandled event");