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 Calculates and simplify 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, target->x, target->y, &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)) {
153 static enum target_status new_target(struct move_target *target)
155 enum target_status ret;
156 if (target->trajectory) {
157 Trajectory *t = (Trajectory*)target->trajectory;
158 target->tc = t->constr;
159 ret = new_trajectory(t);
160 target->trajectory = NULL;
161 // Trajectory is deleted by somebody else
163 ret = new_goal(target, 0);
165 if (ret != TARGET_ERROR) {
166 current_target = *target;
167 // On recaclulation we always use path planner
168 current_target.use_planning = true;
174 recalculate_trajectory(void)
176 /* TODO: Different start for planning than esitmated position */
177 enum target_status ret = new_goal(¤t_target, TRGEN_DELAY);
182 printf("Target error on recalculation_in_progress\n");
189 sem_getvalue(&recalculation_not_running, &val);
191 sem_post(&recalculation_not_running);
195 /*******************************************************************************
197 *******************************************************************************/
199 FSM_STATE_DECL(movement);
200 FSM_STATE_DECL(close_to_target);
201 FSM_STATE_DECL(wait_for_command);
202 FSM_STATE_DECL(lost);
203 FSM_STATE_DECL(wait_and_try_again);
208 if (FSM_EVENT == EV_ENTRY) {
209 FSM_TRANSITION(wait_for_command);
213 FSM_STATE(wait_for_command)
215 enum target_status ret;
221 ret = new_target((struct move_target*)FSM_EVENT_PTR);
223 case TARGET_OK: FSM_TRANSITION(movement); break;
224 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
225 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
237 case EV_TRAJECTORY_DONE:
238 // Skip close to target because sometimes it turn the robot to much
239 // FSM_TRANSITION(close_to_target);
241 case EV_TRAJECTORY_DONE_AND_CLOSE:
242 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
243 FSM_TRANSITION(wait_for_command);
246 switch (recalculate_trajectory()) {
247 case TARGET_OK: break;
248 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
249 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
252 case EV_TRAJECTORY_LOST:
253 FSM_TRANSITION(lost);
256 FSM_TRANSITION(wait_for_command);
264 DBG_PRINT_EVENT("unhandled event");
269 FSM_STATE(close_to_target)
273 FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
275 case EV_TRAJECTORY_DONE_AND_CLOSE:
276 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
277 FSM_TRANSITION(wait_for_command);
279 case EV_TRAJECTORY_LOST:
281 FSM_TRANSITION(lost);
284 FSM_TRANSITION(wait_for_command);
291 case EV_TRAJECTORY_DONE:
293 DBG_PRINT_EVENT("unhandled event");
306 switch (recalculate_trajectory()) {
307 case TARGET_OK: FSM_TRANSITION(movement); break;
308 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
309 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
313 FSM_TRANSITION(wait_for_command);
317 case EV_TRAJECTORY_DONE:
319 case EV_TRAJECTORY_DONE_AND_CLOSE:
320 case EV_TRAJECTORY_LOST:
323 DBG_PRINT_EVENT("unhandled event");
327 FSM_STATE(wait_and_try_again)
331 stop(); //FIXME: Not hard stop
335 switch (recalculate_trajectory()) {
336 case TARGET_OK: FSM_TRANSITION(movement); break;
337 case TARGET_INACC: FSM_TRANSITION(wait_and_try_again); break;
338 case TARGET_ERROR: FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); printf("Target error\n"); break;
341 case EV_TRAJECTORY_DONE:
342 case EV_TRAJECTORY_DONE_AND_CLOSE:
343 FSM_TRANSITION(wait_for_command);
344 FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
347 FSM_TRANSITION(wait_for_command);
350 case EV_TRAJECTORY_LOST:
353 DBG_PRINT_EVENT("unhandled event");