00001
00007 #define FSM_MOTION
00008 #include <sys/time.h>
00009 #include <time.h>
00010 #include "fsmmove.h"
00011 #include "trgen.h"
00012 #include "balet.h"
00013 #include "robot.h"
00014 #include <pthread.h>
00015 #include <path_planner.h>
00016 #include <signal.h>
00017 #include "movehelper.h"
00018 #include <sharp.h>
00019 #include <unistd.h>
00020 #include <map.h>
00021 #include "robot_config.h"
00022
00023
00024
00025
00026
00027
00028 #define OBS_PERIOD_WATCH 100000
00029 #define OBS_PERIOD_BETWEEN_DET 1000000
00030 #define OBS_CSPACE (200/MAP_CELL_SIZE)
00031 #define OBS_FORGET_PERIOD 100000
00033 #define OBS_UPDATE_MAP_SPEED 15
00034
00035
00036
00037
00038
00039
00040 const double k[3] =
00041 {
00042 2,
00043 2,
00044 10
00045 }
00046 ;
00047 #define MAX_POS_ERROR_M 0.5
00048 #define CLOSE_TO_TARGET_M 0.1
00049 #define MAX_WAIT_FOR_CLOSE_MS 2000
00050
00051
00052 #define MOTION_PERIOD_NS (50*1000*1000)
00053 #define SIG_TIMER (SIGRTMIN+0)
00054 #define SIG_NEWDATA (SIGRTMIN+1)
00055
00056
00057 static pthread_t thr_trajctory_follower;
00058 static pthread_t thr_trajctory_recalc;
00059 static pthread_t thr_update_map;
00060 static struct timeval tv_start;
00063 static Trajectory *actual_trajectory = NULL;
00064
00065
00066
00067
00068
00069 static fsm_event new_goal(void);
00070 static void stop();
00071
00072 bool actual_trajectory_reverse;
00073 pthread_mutex_t actual_trajectory_lock = PTHREAD_MUTEX_INITIALIZER;
00074 pthread_mutex_t switch_to_trajectory_lock = PTHREAD_MUTEX_INITIALIZER;
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 void delete_actual_trajectory()
00088 {
00089 Trajectory *old;
00090 pthread_mutex_lock(&actual_trajectory_lock);
00091 old = actual_trajectory;
00092 actual_trajectory = NULL;
00093 pthread_mutex_unlock(&actual_trajectory_lock);
00094 robot_send_speed(0,0);
00095 if (old) delete(actual_trajectory);
00096 }
00097
00099 static void notify_fsm(bool done, double error)
00100 {
00101 static bool done_sent;
00102
00103 if (error > MAX_POS_ERROR_M) {
00104 FSM_SIGNAL(MOTION, EV_TRAJECTORY_LOST);
00105 } else {
00106 if (done) {
00107 if (error < CLOSE_TO_TARGET_M) {
00108 FSM_SIGNAL(MOTION, EV_TRAJECTORY_DONE_AND_CLOSE);
00109 } else if (!done_sent) {
00110 done_sent = true;
00111 FSM_SIGNAL(MOTION, EV_TRAJECTORY_DONE);
00112 }
00113 } else {
00114 done_sent = false;
00115 }
00116 }
00117 }
00118
00131 static void *trajectory_follower(void *arg)
00132 {
00133 struct itimerspec ts;
00134 sigset_t sigset;
00135 struct sigevent sigevent;
00136 timer_t timer;
00137
00138 ts.it_value.tv_sec = 0;
00139 ts.it_value.tv_nsec = MOTION_PERIOD_NS;
00140 ts.it_interval.tv_sec = 0;
00141 ts.it_interval.tv_nsec = MOTION_PERIOD_NS;
00142
00143 sigemptyset(&sigset);
00144 sigaddset(&sigset, SIG_TIMER);
00145 sigaddset(&sigset, SIG_NEWDATA);
00146
00147 pthread_sigmask(SIG_BLOCK, &sigset, (sigset_t*) NULL);
00148
00149 sigevent.sigev_notify = SIGEV_SIGNAL;
00150 sigevent.sigev_signo = SIG_TIMER;
00151 sigevent.sigev_value.sival_int = 0;
00152
00153 if (timer_create(CLOCK_REALTIME, &sigevent, &timer) < 0) {
00154 perror("move: timer_create");
00155 return NULL;
00156 }
00157
00158 if (timer_settime(timer, 0, &ts, NULL) < 0) {
00159 perror("move: timer_settimer");
00160 return NULL;
00161 }
00162
00163 while (1) {
00164 double speeds[2];
00165 int sig;
00166
00167 sigwait(&sigset, &sig);
00168
00169 pthread_mutex_lock(&actual_trajectory_lock);
00170 Trajectory *w = actual_trajectory;
00171 if (w) {
00172 Pos ref_pos;
00173 bool done;
00174 struct position_type ap;
00175 double t;
00176 struct timeval tv;
00177
00178
00179 gettimeofday(&tv, NULL);
00180 t = (double)(tv.tv_usec - tv_start.tv_usec) / 1000000.0;
00181 t += (tv.tv_sec - tv_start.tv_sec);
00182
00183
00184 done = w->getRefPos(t, ref_pos);
00185 pthread_mutex_unlock(&actual_trajectory_lock);
00186
00187 ROBOT_LOCK(act_pos);
00188 #ifdef CONFIG_OPEN_LOOP
00189
00190
00191
00192 robot.act_pos.x = ref_pos.x;
00193 robot.act_pos.y = ref_pos.y;
00194 robot.act_pos.phi = ref_pos.phi;
00195 #endif
00196 ap = robot.act_pos;
00197
00198 ROBOT_UNLOCK(act_pos);
00199 double aktPos[] = { ap.x, ap.y, ap.phi };
00200 DBG("rx=%5.02f ry=%5.02f, rphi=%4.0f v=%-4.02f\r", ref_pos.x, ref_pos.y, ref_pos.phi/M_PI*180, ref_pos.v);
00201 fflush(stdout);
00202
00203 double error;
00204 error = balet(ref_pos, aktPos, speeds, k);
00205
00206 notify_fsm(done, error);
00207 } else {
00208 pthread_mutex_unlock(&actual_trajectory_lock);
00209 speeds[0] = 0;
00210 speeds[1] = 0;
00211 }
00212
00213
00214
00215 robot_send_speed(speeds[0], speeds[1]);
00216 }
00217 }
00218
00229 static void * trajctory_recalc(void * arg)
00230 {
00231 int i,j, xcell, ycell;
00232 double val, x, y;
00233 Pos p;
00234
00235 while (1) {
00237
00238 ROBOT_LOCK(sharpsOpponent);
00239 val = (robot.sharpsOpponent.longSharpDist1 + robot.sharpsOpponent.longSharpDist2 +
00240 robot.sharpsOpponent.longSharpDist3)/3.0;
00241 ROBOT_UNLOCK(sharpsOpponent);
00242
00243 if ((val<0.8)){
00244 int flag_recalc;
00245 int flag_goal_obst;
00246
00247 flag_recalc = 0;
00248 flag_goal_obst = 0;
00249
00251 ROBOT_LOCK(act_pos);
00252 p.x = robot.act_pos.x;
00253 p.y = robot.act_pos.y;
00254 p.phi = robot.act_pos.phi;
00255 ROBOT_UNLOCK(act_pos);
00261 x = val*cos(p.phi) + p.x;
00262 y = val*sin(p.phi) + p.y;
00263 DBG("New obstacle detected at cell [%f,%f] \n", x,y);
00264 if (ShmapIsFreePoint(x,y)){
00265 xcell=ShmapPoint2Cell_X(x);ycell=ShmapPoint2Cell_Y(y);
00266 DBG("Cell %d, %d\n", xcell, ycell);
00268 for (i=(xcell-OBS_CSPACE); i <= xcell+OBS_CSPACE; i++) {
00269 for (j=(ycell- OBS_CSPACE); j <=ycell + OBS_CSPACE; j++) {
00270 switch (ShmapGetCellValue(i,j)){
00271 case MAP_PATH:
00272 case MAP_GOAL:
00273 flag_recalc =1;
00274 case MAP_FREE:
00275 ShmapSetCellValue(i , j, MAP_NEW_OBSTACLE);
00276 break;
00277 case MAP_WALL:
00278 case MAP_WALL_CSPACE:
00279 case MAP_NEW_OBSTACLE:
00280 case MAP_NEW_OBSTACLE_CSPACE:
00281 case MAP_NOT_IN_MAP:
00282 default:
00283 break;
00284 }
00285 }
00286 }
00287
00288
00289 if (flag_goal_obst) {
00290 FSM_SIGNAL(MOTION, EV_MOVE_STOP);
00291 FSM_SIGNAL(MAIN, EV_GOAL_IS_TMP_OBSTACLE);
00292 } else if (flag_recalc){
00293 if (new_goal() == 0) DBG("Path recalc\n");
00294 } else {
00295 DBG("Not necessary to recalc the path\n");
00296 }
00297 } else DBG("The detected obstacle is already in the map\n");
00298
00299
00300 usleep(OBS_PERIOD_BETWEEN_DET);
00301 }
00303 usleep(OBS_PERIOD_WATCH);
00304 }
00305 }
00306
00310 static void * thread_update_map(void * arg){
00311 while (1) {
00313 ShmapUpdateTmpObstacles(OBS_UPDATE_MAP_SPEED);
00314 usleep(OBS_FORGET_PERIOD);
00315 }
00316 }
00317
00323 static void go(Trajectory *t)
00324 {
00325 Trajectory *old;
00326 pthread_mutex_lock(&actual_trajectory_lock);
00327 old = actual_trajectory;
00328 gettimeofday(&tv_start, NULL);
00329 actual_trajectory = t;
00330 pthread_mutex_unlock(&actual_trajectory_lock);
00331 if (old)
00332 delete(old);
00333 }
00334
00335 static void stop()
00336 {
00337 delete_actual_trajectory();
00338 pthread_kill(thr_trajctory_follower, SIG_NEWDATA);
00339 }
00340
00341
00347 static int new_goal(void)
00348 {
00349 double startx, starty, goalx, goaly, angle;
00350 PathPoint * path = NULL;
00351 PathPoint * tmp_point = NULL;
00352
00353 struct TrajectoryConstraints tc = trajectoryConstraintsDefault;
00354 Pos start;
00355
00356
00357
00359 ROBOT_LOCK(act_pos);
00360 startx = robot.act_pos.x;
00361 starty = robot.act_pos.y;
00362 start.x = startx;
00363 start.y = starty;
00364 start.phi = robot.act_pos.phi;
00365 ROBOT_UNLOCK(act_pos);
00367 ROBOT_LOCK(goal);
00368 goalx = robot.goal.x;
00369 goaly = robot.goal.y;
00370 ROBOT_UNLOCK(goal);
00371
00372
00374 switch (path_planner(startx, starty, goalx, goaly, &path, &angle)) {
00375 case 1:
00376 break;
00377 case PP_ERROR_MAP_NOT_INIT:
00378 FSM_SIGNAL(MAIN, EV_MAP_NOT_INIT);
00379 return -1;
00380 break;
00381 case PP_ERROR_GOAL_IS_OBSTACLE:
00382 FSM_SIGNAL(MAIN, EV_GOAL_IS_OBSTACLE);
00383 return -1;
00384 break;
00385 case PP_ERROR_GOAL_NOT_REACHABLE:
00386 FSM_SIGNAL(MAIN, EV_GOAL_NOT_REACHABLE);
00387 return -1;
00388 break;
00389 default:
00390 break;
00391
00392 }
00393
00394 bool backward = false;
00395 Trajectory *t = new Trajectory(tc, backward);
00396
00397
00398 for (tmp_point = path; tmp_point!=NULL; tmp_point=tmp_point->next) {
00399
00400 t->addPoint(tmp_point->x, tmp_point->y);
00401 }
00402
00403
00404 t->finalHeading = angle;
00405
00406
00407 freePathMemory(path);
00408
00409 if (t->prepare(start)) {
00410 go(t);
00411 } else {
00412 DBG("ERROR preparing trajectory\n");
00413 delete(t);
00414 FSM_SIGNAL(MAIN, EV_TRAJECTORY_ERROR);
00415 return -1;
00416 }
00417
00418 return 0;
00419 }
00420
00421
00429 static int new_trajectory(void)
00430 {
00431 Trajectory *t;
00432 Pos pos;
00433 ROBOT_LOCK(new_trajectory);
00434 t = (Trajectory*) robot.new_trajectory;
00435 if (t) robot.new_trajectory = NULL;
00436 else {
00437 ROBOT_UNLOCK(new_trajectory);
00438 DBG("No trajectory\n");
00439 FSM_SIGNAL(MAIN, EV_TRAJECTORY_ERROR);
00440 return -1;
00441 }
00442 ROBOT_UNLOCK(new_trajectory);
00443
00444
00445 ROBOT_LOCK(act_pos);
00446 pos.x = robot.act_pos.x;
00447 pos.y = robot.act_pos.y;
00448 pos.phi = robot.act_pos.phi;
00449 ROBOT_UNLOCK(act_pos);
00450
00451 if (t->prepare(pos)) {
00452 go(t);
00453 } else {
00454 FSM_SIGNAL(MAIN, EV_MOTION_DONE);
00455 return -1;
00456 }
00457 return 0;
00458 }
00459
00460
00461
00462
00463
00464 FSM_STATE_DECL(movement);
00465 FSM_STATE_DECL(close_to_target);
00466 FSM_STATE_DECL(wait_for_command);
00467
00468
00469 FSM_STATE(move_init)
00470 {
00471 pthread_attr_t tattr;
00472 sched_param param;
00473 int ret;
00474
00475 if (FSM_EVENT == EV_INIT) {
00476 actual_trajectory = NULL;
00477
00478
00479 pthread_attr_init (&tattr);
00480 pthread_attr_getschedparam (&tattr, ¶m);
00481 param.sched_priority = TRAJ_FOLLOWER_PRIO;
00482 ret = pthread_attr_setschedparam (&tattr, ¶m);
00483 if(ret) {
00484 perror("pthread_attr_setschedparam");
00485 exit(1);
00486 }
00487 ret = pthread_create(&thr_trajctory_follower, &tattr, trajectory_follower, NULL);
00488 if(ret) {
00489 perror("pthread_create");
00490 exit(1);
00491 }
00492
00493 pthread_attr_init (&tattr);
00494 pthread_attr_getschedparam (&tattr, ¶m);
00495 param.sched_priority = TRAJ_RECALC_PRIO;
00496 ret = pthread_attr_setschedparam (&tattr, ¶m);
00497 if(ret) {
00498 perror("pthread_attr_setschedparam");
00499 exit(1);
00500 }
00501 pthread_create(&thr_trajctory_recalc, NULL, trajctory_recalc, NULL);
00502
00503
00504 pthread_attr_init (&tattr);
00505 pthread_attr_getschedparam (&tattr, ¶m);
00506 param.sched_priority = TRAJ_RECALC_PRIO;
00507 ret = pthread_attr_setschedparam (&tattr, ¶m);
00508 if(ret) {
00509 perror("pthread_attr_setschedparam");
00510 exit(1);
00511 }
00512 pthread_create(&thr_update_map, NULL, thread_update_map, NULL);
00513
00514 FSM_TRANSITION(wait_for_command);
00515 }
00516 }
00517
00518 FSM_STATE(wait_for_command)
00519 {
00520 switch (FSM_EVENT) {
00521 case EV_STATE_ENTERED:
00522 stop();
00523 break;
00524 case EV_NEW_GOAL:
00525 if (new_goal() != 0) {
00526
00527 DBG("Goal error\n");
00528 break;
00529 }
00530 FSM_TRANSITION(movement);
00531 break;
00532 case EV_NEW_TRAJECTORY:
00533 if (new_trajectory() != 0) {
00534 break;
00535 }
00536 FSM_TRANSITION(movement);
00537 break;
00538 default:
00539 break;
00540 }
00541 }
00542
00543
00544
00545 FSM_STATE(movement)
00546 {
00547 switch (FSM_EVENT) {
00548 case EV_TRAJECTORY_DONE:
00549 FSM_TRANSITION(close_to_target);
00550 break;
00551 case EV_TRAJECTORY_DONE_AND_CLOSE:
00552 FSM_SIGNAL(MAIN, EV_MOTION_DONE);
00553 FSM_TRANSITION(wait_for_command);
00554 break;
00555 case EV_TRAJECTORY_LOST:
00556 FSM_SIGNAL(MAIN, EV_LOST_DURING_MOTION);
00557 FSM_TRANSITION(wait_for_command);
00558 break;
00559 case EV_MOVE_STOP:
00560 FSM_TRANSITION(wait_for_command);
00561 break;
00562 default:
00563
00564 break;
00565 }
00566 }
00567
00568
00569 FSM_STATE(close_to_target)
00570 {
00571 switch (FSM_EVENT) {
00572 case EV_STATE_ENTERED:
00573 FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
00574 break;
00575 case EV_TRAJECTORY_DONE_AND_CLOSE:
00576 FSM_SIGNAL(MAIN, EV_MOTION_DONE);
00577 FSM_TRANSITION(wait_for_command);
00578 break;
00579 case EV_TRAJECTORY_LOST:
00580 case EV_TIMER:
00581 stop();
00582 FSM_SIGNAL(MAIN, EV_LOST_DURING_MOTION);
00583 FSM_TRANSITION(wait_for_command);
00584 break;
00585 case EV_MOVE_STOP:
00586 FSM_TRANSITION(wait_for_command);
00587 break;
00588 case EV_TRAJECTORY_DONE:
00589 case EV_NEW_TRAJECTORY:
00590 case EV_LOC_UPDATED:
00591 case EV_NEW_GOAL:
00592 case EV_LOC_LOST:
00593 case EV_INIT:
00594 case EV_EXIT:
00595 case EV_RETURN:
00596 case EV_TIMEOUT:
00597 DBG_PRINT_EVENT("unhandled event");
00598 break;
00599 }
00600 }