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 * @brief FIXME Calculates and simplifies a path to goal position avoiding obstacles.
49 * @param start_in_future is delay utilised to calculate the trajectory while robot
50 * is moving (zero means to start movement from the current position)
51 * @return True on succes, false on error.
53 static enum target_status new_goal(struct move_target *target, double start_in_future)
55 enum target_status ret;
56 double angle, targetx, targety;
57 PathPoint * path = NULL;
58 PathPoint * tmp_point = NULL;
61 bool backward = false;
63 // Where to start trajectory planning?
64 get_future_pos(start_in_future, start, time_ts);
65 Trajectory *t = new Trajectory(target->tc, backward);
67 if (target->heading.operation == TOP_ARRIVE_FROM) {
68 get_arrive_from_point(target->x, target->y, target->heading,
75 if (target->use_planning) {
76 /// Calculates the path between actual position to goal position. If the goal is not reachable returns -1.
77 switch (path_planner(start.x, start.y, targetx, targety, &path, &angle)) {
78 case PP_ERROR_MAP_NOT_INIT:
79 ret = TARGET_ERROR; break;
80 case PP_ERROR_GOAL_IS_OBSTACLE:
81 case PP_ERROR_GOAL_NOT_REACHABLE:
82 ret = TARGET_INACC; break;
84 ret = TARGET_OK; break;
89 // Add this path to the trajectory.
90 for (tmp_point = path; tmp_point!=NULL; tmp_point=tmp_point->next) {
91 DBG("ADDING POINT (%f, %f)\n", tmp_point->x, tmp_point->y);
92 t->addPoint(tmp_point->x, tmp_point->y);
96 t->addPoint(targetx, targety);
99 if (target->heading.operation == TOP_ARRIVE_FROM) {
100 t->addPoint(target->x, target->y);
102 t->finalHeading = target2final_heading(target->heading);
104 if (t->prepare(start)) {
105 if (start_in_future) {
106 /* not to switch immediately
107 switch_trajectory_at(t, time_ts); */
108 // new test - appending trajectories
124 * Starts moving on trajectory prepared by functions in
125 * movehelper.cc. In case of error it sends the proper event to MAIN
128 * @return TARGET_OK on succes, TARGET_ERROR on error.
130 static enum target_status new_trajectory(Trajectory *t)
135 printf("ERROR: No trajectory\n");
139 pos.x = robot.est_pos.x;
140 pos.y = robot.est_pos.y;
141 pos.phi = robot.est_pos.phi;
142 ROBOT_UNLOCK(est_pos);
144 if (t->prepare(pos)) {
154 * Handles new target signal from main FSM
160 static enum target_status new_target(struct move_target *target)
162 enum target_status ret;
163 if (target->trajectory) {
164 Trajectory *t = (Trajectory*)target->trajectory;
165 target->tc = t->constr;
166 ret = new_trajectory(t);
167 target->trajectory = NULL;
168 // Trajectory is deleted by somebody else
170 ret = new_goal(target, 0);
172 if (ret != TARGET_ERROR) {
173 current_target = *target;
179 * Recalculates trajectory to previous move target specified by
185 recalculate_trajectory(void)
187 /* TODO: Different start for planning than esitmated position */
188 enum target_status ret;
189 current_target.use_planning = true;
190 ret = new_goal(¤t_target, TRGEN_DELAY);
195 printf("Target error on recalculation_in_progress\n");
202 sem_getvalue(&recalculation_not_running, &val);
204 sem_post(&recalculation_not_running);
208 /*******************************************************************************
210 *******************************************************************************/
212 FSM_STATE_DECL(movement);
213 FSM_STATE_DECL(close_to_target);
214 FSM_STATE_DECL(wait_for_command);
215 FSM_STATE_DECL(lost);
216 FSM_STATE_DECL(wait_and_try_again);
221 if (FSM_EVENT == EV_ENTRY) {
222 FSM_TRANSITION(wait_for_command);
226 FSM_STATE(wait_for_command)
228 enum target_status ret;
234 ret = new_target((struct move_target*)FSM_EVENT_PTR);
236 case TARGET_OK: FSM_TRANSITION(movement); break;
237 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
238 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
250 case EV_TRAJECTORY_DONE:
251 // Skip close to target because sometimes it turn the robot to much
252 // FSM_TRANSITION(close_to_target);
254 case EV_TRAJECTORY_DONE_AND_CLOSE:
255 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
256 FSM_TRANSITION(wait_for_command);
259 switch (recalculate_trajectory()) {
260 case TARGET_OK: break;
261 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
262 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
265 case EV_OBSTACLE_BEHIND:
266 FSM_TRANSITION(wait_and_try_again);
268 case EV_TRAJECTORY_LOST:
269 FSM_TRANSITION(lost);
272 FSM_TRANSITION(wait_for_command);
280 DBG_PRINT_EVENT("unhandled event");
285 FSM_STATE(close_to_target)
289 FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
291 case EV_TRAJECTORY_DONE_AND_CLOSE:
292 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
293 FSM_TRANSITION(wait_for_command);
295 case EV_OBSTACLE_BEHIND:
296 FSM_TRANSITION(wait_and_try_again);
298 case EV_TRAJECTORY_LOST:
300 FSM_TRANSITION(lost);
303 FSM_TRANSITION(wait_for_command);
310 case EV_TRAJECTORY_DONE:
312 DBG_PRINT_EVENT("unhandled event");
325 switch (recalculate_trajectory()) {
326 case TARGET_OK: FSM_TRANSITION(movement); break;
327 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
328 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
332 FSM_TRANSITION(wait_for_command);
336 case EV_OBSTACLE_BEHIND:
337 case EV_TRAJECTORY_DONE:
339 case EV_TRAJECTORY_DONE_AND_CLOSE:
340 case EV_TRAJECTORY_LOST:
343 DBG_PRINT_EVENT("unhandled event");
347 FSM_STATE(wait_and_try_again)
351 stop(); //FIXME: Not hard stop
355 switch (recalculate_trajectory()) {
356 case TARGET_OK: FSM_TRANSITION(movement); break;
357 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
358 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
361 case EV_TRAJECTORY_DONE:
362 case EV_TRAJECTORY_DONE_AND_CLOSE:
363 FSM_TRANSITION(wait_for_command);
364 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
367 FSM_TRANSITION(wait_for_command);
369 case EV_OBSTACLE_BEHIND:
372 case EV_TRAJECTORY_LOST:
375 DBG_PRINT_EVENT("unhandled event");