4 * @author Michal Sojka, Jose Maria Martin Laguna, Petr Beneš
17 #include <path_planner.h>
19 #include <movehelper.h>
23 #include "robot_config.h"
25 #include "motion-control.h"
28 #define DBG(format, ...) printf(format, ##__VA_ARGS__)
30 #define DBG(format, ...)
33 #define MAX_WAIT_FOR_CLOSE_MS 2000
35 // time to calculate new trajectory [seconds]
36 #define TRGEN_DELAY 0.3
39 // Target position of the current movement
40 static struct move_target current_target;
43 TARGET_OK, // We can go the the target
44 TARGET_INACC, // Target is inaccessible because of an obstacle
45 TARGET_ERROR // Fatal errror during planning
48 void invalidateAcropole(Point point)
50 Point center(PLAYGROUND_WIDTH_M/2.0, PLAYGROUND_HEIGHT_M/2.0);
52 double a = center.angleTo(point);
53 for (int i=0; i<5; i++) {
57 x = point.x + d*cos(a);
58 y = point.y + d*sin(a);
59 ShmapSetRectangleFlag(x-s, y-s, x+s, y+s, MAP_FLAG_INVALIDATE_WALL, 0);
63 void invalidateDown(Point point)
65 printf("XXXXXXXXXXXXXXXinvalidateDown %g, %g\n", point.x, point.y);
69 ShmapSetRectangleFlag(x, 0.1, x, 0.4, MAP_FLAG_INVALIDATE_WALL, 0);
73 * @brief FIXME Calculates and simplifies a path to goal position avoiding obstacles.
74 * @param start_in_future is delay utilised to calculate the trajectory while robot
75 * is moving (zero means to start movement from the current position)
76 * @return True on succes, false on error.
78 static enum target_status new_goal(struct move_target *move_target, double start_in_future)
80 enum target_status ret;
82 PathPoint * path = NULL;
83 PathPoint * tmp_point = NULL;
84 Pos future_traj_point;
85 Point target(move_target->x, move_target->y);
86 Point center(PLAYGROUND_WIDTH_M/2.0, PLAYGROUND_HEIGHT_M/2.0);
88 bool backward = false;
90 // Where to start trajectory planning?
91 get_future_pos(start_in_future, future_traj_point, time_ts);
92 Point start(future_traj_point.x, future_traj_point.y);
94 Trajectory *t = new Trajectory(move_target->tc, backward);
96 // Clear all invalidate flags;
97 ShmapSetRectangleFlag(0, 0, PLAYGROUND_WIDTH_M, PLAYGROUND_HEIGHT_M, 0, MAP_FLAG_INVALIDATE_WALL);
98 // Set invalidate flags if we are going to walled area
99 if (target.distanceTo(center) < 0.40)
100 invalidateAcropole(target);
101 if (start.distanceTo(center) < 0.40)
102 invalidateAcropole(start);
104 invalidateDown(target);
106 invalidateDown(start);
108 if (move_target->heading.operation == TOP_ARRIVE_FROM) {
109 get_arrive_from_point(move_target->x, move_target->y, move_target->heading,
110 &target.x, &target.y);
113 if (move_target->use_planning) {
114 /// Calculates the path between actual position to goal position. If the goal is not reachable returns -1.
115 switch (path_planner(start.x, start.y, target.x, target.y, &path, &angle)) {
116 case PP_ERROR_MAP_NOT_INIT:
117 ret = TARGET_ERROR; break;
118 case PP_ERROR_GOAL_IS_OBSTACLE:
119 case PP_ERROR_GOAL_NOT_REACHABLE:
120 ret = TARGET_INACC; break;
122 ret = TARGET_OK; break;
125 if (ret != TARGET_OK)
127 // Add this path to the trajectory.
128 for (tmp_point = path; tmp_point!=NULL; tmp_point=tmp_point->next) {
129 DBG("ADDING POINT (%f, %f)\n", tmp_point->x, tmp_point->y);
130 t->addPoint(tmp_point->x, tmp_point->y);
132 freePathMemory(path);
134 t->addPoint(target.x, target.y);
137 if (move_target->heading.operation == TOP_ARRIVE_FROM) {
138 t->addPoint(move_target->x, move_target->y);
140 t->finalHeading = target2final_heading(move_target->heading);
142 if (t->prepare(future_traj_point)) {
143 if (start_in_future) {
144 /* not to switch immediately
145 switch_trajectory_at(t, time_ts); */
146 // new test - appending trajectories
162 * Starts moving on trajectory prepared by functions in
163 * movehelper.cc. In case of error it sends the proper event to MAIN
166 * @return TARGET_OK on succes, TARGET_ERROR on error.
168 static enum target_status new_trajectory(Trajectory *t)
173 printf("ERROR: No trajectory\n");
176 // FIXME: This is duplicite code with new_goal. Remove this
177 // function and use always new_goal.
178 robot_get_est_pos(&pos.x, &pos.y, &pos.phi);
182 if (t->prepare(pos)) {
192 * Handles new target signal from main FSM
198 static enum target_status new_target(struct move_target *target)
200 enum target_status ret;
201 if (target->trajectory) {
202 Trajectory *t = (Trajectory*)target->trajectory;
203 target->tc = t->constr;
204 ret = new_trajectory(t);
205 target->trajectory = NULL;
206 // Trajectory is deleted by somebody else
208 ret = new_goal(target, 0);
210 if (ret != TARGET_ERROR) {
211 current_target = *target;
217 * Recalculates trajectory to previous move target specified by
223 recalculate_trajectory(void)
225 /* TODO: Different start for planning than esitmated position */
226 enum target_status ret;
227 current_target.use_planning = true;
228 ret = new_goal(¤t_target, TRGEN_DELAY);
233 printf("Target error on recalculation_in_progress\n");
240 sem_getvalue(&recalculation_not_running, &val);
242 sem_post(&recalculation_not_running);
246 /*******************************************************************************
248 *******************************************************************************/
250 FSM_STATE_DECL(movement);
251 FSM_STATE_DECL(close_to_target);
252 FSM_STATE_DECL(wait_for_command);
253 FSM_STATE_DECL(lost);
254 FSM_STATE_DECL(wait_and_try_again);
259 if (FSM_EVENT == EV_ENTRY) {
260 FSM_TRANSITION(wait_for_command);
264 FSM_STATE(wait_for_command)
266 enum target_status ret;
272 ret = new_target((struct move_target*)FSM_EVENT_PTR);
274 case TARGET_OK: FSM_TRANSITION(movement); break;
275 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
276 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
289 if (robot.localization_works) {
291 ROBOT_LOCK(est_pos_uzv);
292 p = robot.est_pos_uzv;
293 ROBOT_UNLOCK(est_pos_uzv);
295 robot_set_est_pos_notrans(p.x, p.y, p.phi);
298 case EV_TRAJECTORY_DONE:
299 // Skip close to target because sometimes it turn the robot to much
300 // FSM_TRANSITION(close_to_target);
302 case EV_TRAJECTORY_DONE_AND_CLOSE:
303 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
304 FSM_TRANSITION(wait_for_command);
307 switch (recalculate_trajectory()) {
308 case TARGET_OK: break;
309 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
310 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
313 case EV_OBSTACLE_BEHIND:
314 FSM_TRANSITION(wait_and_try_again);
316 case EV_TRAJECTORY_LOST:
317 FSM_TRANSITION(lost);
320 FSM_TRANSITION(wait_for_command);
327 DBG_PRINT_EVENT("unhandled event");
332 FSM_STATE(close_to_target)
336 FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
338 case EV_TRAJECTORY_DONE_AND_CLOSE:
339 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
340 FSM_TRANSITION(wait_for_command);
342 case EV_OBSTACLE_BEHIND:
343 FSM_TRANSITION(wait_and_try_again);
345 case EV_TRAJECTORY_LOST:
347 FSM_TRANSITION(lost);
350 FSM_TRANSITION(wait_for_command);
357 case EV_TRAJECTORY_DONE:
359 DBG_PRINT_EVENT("unhandled event");
372 switch (recalculate_trajectory()) {
373 case TARGET_OK: FSM_TRANSITION(movement); break;
374 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
375 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
379 FSM_TRANSITION(wait_for_command);
383 case EV_OBSTACLE_BEHIND:
384 case EV_TRAJECTORY_DONE:
386 case EV_TRAJECTORY_DONE_AND_CLOSE:
387 case EV_TRAJECTORY_LOST:
390 DBG_PRINT_EVENT("unhandled event");
394 FSM_STATE(wait_and_try_again)
398 stop(); //FIXME: Not hard stop
402 switch (recalculate_trajectory()) {
403 case TARGET_OK: FSM_TRANSITION(movement); break;
404 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); printf("Inaccessible\n"); break;
405 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
408 case EV_TRAJECTORY_DONE:
409 case EV_TRAJECTORY_DONE_AND_CLOSE:
410 FSM_TRANSITION(wait_for_command);
411 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
414 FSM_TRANSITION(wait_for_command);
416 case EV_OBSTACLE_BEHIND:
417 FSM_TRANSITION(wait_and_try_again);
420 case EV_TRAJECTORY_LOST:
423 DBG_PRINT_EVENT("unhandled event");