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 // we may need something similar in future
49 void invalidate(Point point)
51 //ShmapSetRectangleFlag(x-s, y-s, x+s, y+s, MAP_FLAG_INVALIDATE_WALL, 0)
55 * @brief FIXME Calculates and simplifies a path to goal position avoiding obstacles.
56 * @param start_in_future is delay utilised to calculate the trajectory while robot
57 * is moving (zero means to start movement from the current position)
58 * @return True on succes, false on error.
60 static enum target_status new_goal(struct move_target *move_target, double start_in_future)
62 enum target_status ret;
64 PathPoint * path = NULL;
65 PathPoint * tmp_point = NULL;
66 Pos future_traj_point;
67 Point target(move_target->x, move_target->y);
68 Point center(PLAYGROUND_WIDTH_M/2.0, PLAYGROUND_HEIGHT_M/2.0);
70 bool backward = false;
72 // Where to start trajectory planning?
73 get_future_pos(start_in_future, future_traj_point, time_ts);
74 Point start(future_traj_point.x, future_traj_point.y);
76 Trajectory *t = new Trajectory(move_target->tc, backward);
79 // Clear all invalidate flags;
80 ShmapSetRectangleFlag(0, 0, PLAYGROUND_WIDTH_M, PLAYGROUND_HEIGHT_M, 0, MAP_FLAG_INVALIDATE_WALL);
81 // Set invalidate flags if we are going to walled area
82 if (false) // we may need this in future
86 if (move_target->heading.operation == TOP_ARRIVE_FROM) {
87 get_arrive_from_point(move_target->x, move_target->y, move_target->heading,
88 &target.x, &target.y);
91 if (move_target->use_planning) {
92 /// Calculates the path between actual position to goal position. If the goal is not reachable returns -1.
93 switch (path_planner(start.x, start.y, target.x, target.y, &path, &angle)) {
94 case PP_ERROR_MAP_NOT_INIT:
95 ret = TARGET_ERROR; break;
96 case PP_ERROR_GOAL_IS_OBSTACLE:
97 case PP_ERROR_GOAL_NOT_REACHABLE:
98 ret = TARGET_INACC; break;
100 ret = TARGET_OK; break;
103 if (ret != TARGET_OK)
105 // Add this path to the trajectory.
106 for (tmp_point = path; tmp_point!=NULL; tmp_point=tmp_point->next) {
107 DBG("ADDING POINT (%f, %f)\n", tmp_point->x, tmp_point->y);
108 t->addPoint(tmp_point->x, tmp_point->y);
110 freePathMemory(path);
112 t->addPoint(target.x, target.y);
115 if (move_target->heading.operation == TOP_ARRIVE_FROM) {
116 t->addPoint(move_target->x, move_target->y);
118 t->finalHeading = target2final_heading(move_target->heading);
120 if (t->prepare(future_traj_point)) {
121 if (start_in_future) {
122 /* not to switch immediately
123 switch_trajectory_at(t, time_ts); */
124 // new test - appending trajectories
140 * Starts moving on trajectory prepared by functions in
141 * movehelper.cc. In case of error it sends the proper event to MAIN
144 * @return TARGET_OK on succes, TARGET_ERROR on error.
146 static enum target_status new_trajectory(Trajectory *t)
151 printf("ERROR: No trajectory\n");
154 // FIXME: This is duplicite code with new_goal. Remove this
155 // function and use always new_goal.
156 robot_get_est_pos(&pos.x, &pos.y, &pos.phi);
160 if (t->prepare(pos)) {
170 * Handles new target signal from main FSM
176 static enum target_status new_target(struct move_target *target)
178 enum target_status ret;
179 if (target->trajectory) {
180 Trajectory *t = (Trajectory*)target->trajectory;
181 target->tc = t->constr;
182 ret = new_trajectory(t);
183 target->trajectory = NULL;
184 // Trajectory is deleted by somebody else
186 ret = new_goal(target, 0);
188 if (ret != TARGET_ERROR) {
189 current_target = *target;
195 * Recalculates trajectory to previous move target specified by
201 recalculate_trajectory(void)
203 /* TODO: Different start for planning than esitmated position */
204 enum target_status ret;
205 current_target.use_planning = true;
206 ret = new_goal(¤t_target, TRGEN_DELAY);
211 printf("Target error on recalculation_in_progress\n");
218 sem_getvalue(&recalculation_not_running, &val);
220 sem_post(&recalculation_not_running);
224 /*******************************************************************************
226 *******************************************************************************/
228 FSM_STATE_DECL(movement);
229 FSM_STATE_DECL(close_to_target);
230 FSM_STATE_DECL(wait_for_command);
231 FSM_STATE_DECL(lost);
232 FSM_STATE_DECL(wait_and_try_again);
237 if (FSM_EVENT == EV_ENTRY) {
238 FSM_TRANSITION(wait_for_command);
242 FSM_STATE(wait_for_command)
244 enum target_status ret;
250 ret = new_target((struct move_target*)FSM_EVENT_PTR);
252 case TARGET_OK: FSM_TRANSITION(movement); break;
253 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
254 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
259 case EV_TRAJECTORY_DONE:
260 case EV_TRAJECTORY_DONE_AND_CLOSE:
261 case EV_TRAJECTORY_LOST:
264 case EV_OBSTACLE_BEHIND:
266 DBG_PRINT_EVENT("unhandled event");
276 if (robot.localization_works) {
278 ROBOT_LOCK(est_pos_uzv);
279 p = robot.est_pos_uzv;
280 ROBOT_UNLOCK(est_pos_uzv);
282 robot_set_est_pos_notrans(p.x, p.y, p.phi);
285 case EV_TRAJECTORY_DONE:
286 // Skip close to target because sometimes it turn the robot to much
287 // FSM_TRANSITION(close_to_target);
289 case EV_TRAJECTORY_DONE_AND_CLOSE:
290 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
291 FSM_TRANSITION(wait_for_command);
294 switch (recalculate_trajectory()) {
295 // We can go to the target:
296 case TARGET_OK: break;
297 // Target inaccessible because of an obstacle
298 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
299 // Fatal error during planning
300 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
301 printf("Target error\n");
302 /* FIXME (Filip): shouldn't transition to wait_for_command be here?
303 No, probably not, if an error occurs, robot won't move any more
304 and we can recognize the error. */
308 case EV_OBSTACLE_BEHIND:
309 if (robot.moves_backward && robot.use_back_switch)
310 FSM_TRANSITION(wait_and_try_again);
312 case EV_TRAJECTORY_LOST:
313 FSM_TRANSITION(lost);
316 FSM_TRANSITION(wait_for_command);
323 DBG_PRINT_EVENT("unhandled event");
328 FSM_STATE(close_to_target)
332 FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
334 case EV_TRAJECTORY_DONE_AND_CLOSE:
335 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
336 FSM_TRANSITION(wait_for_command);
338 case EV_OBSTACLE_BEHIND:
339 if (robot.moves_backward && robot.use_back_switch)
340 FSM_TRANSITION(wait_and_try_again);
342 case EV_TRAJECTORY_LOST:
344 FSM_TRANSITION(lost);
347 FSM_TRANSITION(wait_for_command);
354 case EV_TRAJECTORY_DONE:
356 DBG_PRINT_EVENT("unhandled event");
369 switch (recalculate_trajectory()) {
370 case TARGET_OK: FSM_TRANSITION(movement); break;
371 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
372 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
376 FSM_TRANSITION(wait_for_command);
380 case EV_OBSTACLE_BEHIND:
381 case EV_TRAJECTORY_DONE:
383 case EV_TRAJECTORY_DONE_AND_CLOSE:
384 case EV_TRAJECTORY_LOST:
387 DBG_PRINT_EVENT("unhandled event");
391 FSM_STATE(wait_and_try_again)
395 stop(); //FIXME: Not hard stop
399 switch (recalculate_trajectory()) {
400 // We can go to the target:
401 case TARGET_OK: FSM_TRANSITION(movement); break;
402 // Target inaccessible because of an obstacle
404 FSM_TRANSITION(wait_and_try_again);
405 printf("Inaccessible\n");
406 /* FIXME (Filip): this could happen forever */
408 // Fatal error during planning
409 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
412 case EV_TRAJECTORY_DONE:
413 case EV_TRAJECTORY_DONE_AND_CLOSE:
414 FSM_TRANSITION(wait_for_command);
415 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
418 FSM_TRANSITION(wait_for_command);
420 case EV_OBSTACLE_BEHIND:
423 case EV_TRAJECTORY_LOST:
426 DBG_PRINT_EVENT("unhandled event");