]> rtime.felk.cvut.cz Git - eurobot/public.git/commitdiff
robofsm: Cleaner and simpler design of motion control
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 1 May 2008 16:12:00 +0000 (18:12 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 1 May 2008 16:12:00 +0000 (18:12 +0200)
src/robofsm/eb2008/fsmdisplay.cc
src/robofsm/eb2008/fsmloc.c
src/robofsm/eb2008/fsmmove.cc
src/robofsm/eb2008/movehelper_eb2008.cc
src/robofsm/eb2008/movehelper_eb2008.h
src/robofsm/eb2008/roboevent_eb2008.py
src/robofsm/eb2008/robot_eb2008.h
src/robofsm/eb2008/test/rectangle.cc

index 2e1aa4e8b1b641072b5b29c6a05f59b9904ffec6..309491f160303f6630c90d5a77afd1a994cdcc93 100644 (file)
@@ -240,7 +240,8 @@ FSM_STATE(set_init_mode)
                case EV_TIMER:
                        FSM_TRANSITION(control);
                        break;
-
+               default:
+                       break;
        }
 }
 
index 3df45e0cf23ac202b563e47c83a4bdf6806600be..656a3609598b140b27ccdc5658462cb6e7fb069f 100644 (file)
@@ -41,7 +41,12 @@ FSM_STATE(run)
        struct mcl_model *mcl = robot.mcl;
        switch (FSM_EVENT) {
                case EV_RESET:
+                       printf("MCL reset\n");
                        mcl->reset(mcl);
+                       FSM_TIMER(3000);
+                       break;
+               case EV_TIMER:
+                       FSM_SIGNAL(MOTION, EV_FOUND_AFTER_RESET, NULL);
                        break;
                case EV_ODO_RECEIVED: {
                        struct mcl_robot_odo *odo = FSM_EVENT_PTR;
@@ -82,7 +87,6 @@ FSM_STATE(run)
                case EV_EXIT:
                        break;
                case EV_RETURN:
-               case EV_TIMER:
                        DBG_PRINT_EVENT("unhandled event");
                        break;
        }
index bf07f3273e8dc470cb8a78639c9523c749eb9b4f..ab535ff573a34aed125d38b6725f8c0ee5b0e5ab 100644 (file)
 #include <robomath.h>
 
 
-/*******************************************************************************
- * Parameters of Obstacle detection
- *******************************************************************************/
-
-#define OBS_PERIOD_WATCH       100000          /**< Time period for watching the sensors in us*/
-#define OBS_PERIOD_BETWEEN_DET 1000000         /**< Minimal time period between two detections in us. */
-#define OBS_AREA               (200/MAP_CELL_SIZE_MM)  /**< Configuration Space of the obstacle in cell units. In this case 200mm = 2 cells. @warning It should be an integer */
-#define OBS_AREA_M (OBS_AREA*MAP_CELL_SIZE_MM)
-#define OBS_FORGET_PERIOD      100000          /**< The period of thread_update_map() */
-
-#define OBS_FORGET_SEC 15                      /**< Time to completely forget detected obstacle. */
-
-#define OBS_OFFSET     0.6
 /*******************************************************************************
  * Controller thread and helper functions for that thread
  *******************************************************************************/
@@ -60,33 +47,23 @@ const struct balet_params k = {
 // Global varibles
 static pthread_t thr_trajctory_follower;
 static pthread_t thr_trajctory_recalc;
-static pthread_t thr_update_map;
 static struct timeval tv_start; /**< Absolute time, when trajectory started. */
 
 /** Stores the actually followed trajectory object */
 static Trajectory *actual_trajectory = NULL;
-
-//static Trajectory *switch_to_trajectory = NULL;
-//static double switch_time;
-
-// function definition
-static int new_goal(void);
-static void stop();
-
 bool actual_trajectory_reverse;
 pthread_mutex_t actual_trajectory_lock = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_t switch_to_trajectory_lock = PTHREAD_MUTEX_INITIALIZER;
 
-// static void odometry(double l, r) {
-//     static double last_l, last_r;
 
-//     robot.act_pos.x = (double)ROBOT_AXIS_TO_BACK_MM/1000;
-//     robot.act_pos.y = ((double)PLAYGROUND_HEIGHT_MM - ROBOT_WIDTH_MM/2)/1000;
-//     robot.act_pos.phi = 0;
+// Target position of the current movement
+static struct move_target current_target;
+
+
+//static Trajectory *switch_to_trajectory = NULL;
+//static double switch_time;
 
-//     ROBOT_LOCK(act_pos);
-//     ROBOT_UNLOCK(act_pos);
-// }
+static void stop();
 
 static void delete_actual_trajectory()
 {
@@ -120,6 +97,67 @@ static void notify_fsm(bool done, double error)
        }
 }
 
+static void do_control()
+{
+       double speedl, speedr;
+       pthread_mutex_lock(&actual_trajectory_lock);
+       Trajectory *w = actual_trajectory;
+       if (w) {
+               Pos ref_pos, est_pos, balet_out;
+               bool done;
+               double t;
+               struct timeval tv;
+
+               // Calculate reference position
+               gettimeofday(&tv, NULL);
+               t = (double)(tv.tv_usec - tv_start.tv_usec) / 1000000.0;
+               t += (tv.tv_sec - tv_start.tv_sec);
+
+               done = w->getRefPos(t, ref_pos);
+
+               ROBOT_LOCK(ref_pos);
+               robot.ref_pos.x = ref_pos.x;
+               robot.ref_pos.y = ref_pos.y;
+               robot.ref_pos.phi = ref_pos.phi;
+               ROBOT_UNLOCK(ref_pos);
+
+               ROBOT_LOCK(est_pos);
+               est_pos.x = robot.est_pos.x;
+               est_pos.y = robot.est_pos.y;
+               est_pos.phi = robot.est_pos.phi;
+               ROBOT_UNLOCK(est_pos);
+
+#ifdef CONFIG_OPEN_LOOP
+               // We don't use any feedback now. It is
+               // supposed that the estimated position is
+               // equal to the reference position.
+               robot_set_est_pos_notrans(ref_pos.x, ref_pos.y, ref_pos.phi);
+               est_pos.x = robot.est_pos.x;
+               est_pos.y = robot.est_pos.y;
+               est_pos.phi = robot.est_pos.phi;
+#endif
+
+               DBG("rx=%5.02f ry=%5.02f, rphi=%4.0f v=%-4.02f  omega=%-4.02f\r", ref_pos.x, ref_pos.y, ref_pos.phi/M_PI*180, ref_pos.v, ref_pos.omega);
+#ifdef DEBUG                   
+               fflush(stdout);
+#endif
+               // Call the controller
+               double error;
+               error = balet(ref_pos, est_pos, k, balet_out);
+               speedl = balet_out.v - ROBOT_ROTATION_RADIUS_M*balet_out.omega;
+               speedr = balet_out.v + ROBOT_ROTATION_RADIUS_M*balet_out.omega;
+               notify_fsm(done, error);
+       } else {
+               speedl = 0;
+               speedr = 0;
+       }
+
+
+       // Apply controller output
+       robot_send_speed(speedl, speedr);
+       pthread_mutex_unlock(&actual_trajectory_lock);
+}
+
 /**
  * A thread running the controller.
  *
@@ -165,194 +203,11 @@ static void *trajectory_follower(void *arg)
        }
 
        while (1) {
-               double speeds[2];
                int sig;
                // Wait for start of new period or new data
                sigwait(&sigset, &sig);
                //DBG("signal %d ", sig - SIGRTMIN);
-               pthread_mutex_lock(&actual_trajectory_lock);
-               Trajectory *w = actual_trajectory;
-               if (w) {
-                       Pos ref_pos, est_pos, balet_out;
-                       bool done;
-                       double t;
-                       struct timeval tv;
-
-                       // Calculate reference position
-                       gettimeofday(&tv, NULL);
-                       t = (double)(tv.tv_usec - tv_start.tv_usec) / 1000000.0;
-                       t += (tv.tv_sec - tv_start.tv_sec);
-
-                       done = w->getRefPos(t, ref_pos);
-
-                       ROBOT_LOCK(ref_pos);
-                       robot.ref_pos.x = ref_pos.x;
-                       robot.ref_pos.y = ref_pos.y;
-                       robot.ref_pos.phi = ref_pos.phi;
-                       ROBOT_UNLOCK(ref_pos);
-
-                       ROBOT_LOCK(est_pos);
-                       est_pos.x = robot.est_pos.x;
-                       est_pos.y = robot.est_pos.y;
-                       est_pos.phi = robot.est_pos.phi;
-                       ROBOT_UNLOCK(est_pos);
-
-#ifdef CONFIG_OPEN_LOOP
-                       // We don't use any feedback now. It is
-                       // supposed that the estimated position is
-                       // equal to the reference position.
-                       robot_set_est_pos_notrans(ref_pos.x, ref_pos.y, ref_pos.phi);
-                       est_pos.x = robot.est_pos.x;
-                       est_pos.y = robot.est_pos.y;
-                       est_pos.phi = robot.est_pos.phi;
-#endif
-
-                       DBG("rx=%5.02f ry=%5.02f, rphi=%4.0f v=%-4.02f  omega=%-4.02f\r", ref_pos.x, ref_pos.y, ref_pos.phi/M_PI*180, ref_pos.v, ref_pos.omega);
-#ifdef DEBUG                   
-                       fflush(stdout);
-#endif
-                       // Call the controller
-                       double error;
-                       error = balet(ref_pos, est_pos, k, balet_out);
-                       speeds[0] = balet_out.v - ROBOT_ROTATION_RADIUS_M*balet_out.omega;
-                       speeds[1] = balet_out.v + ROBOT_ROTATION_RADIUS_M*balet_out.omega;
-                       notify_fsm(done, error);
-               } else {
-                       speeds[0] = 0;
-                       speeds[1] = 0;
-               }
-
-
-               // Apply controller output
-               robot_send_speed(speeds[0], speeds[1]);
-               pthread_mutex_unlock(&actual_trajectory_lock);
-       }
-}
-
-static void obstacle_detected_at(double x, double y)
-{
-       int i,j, xcell, ycell;
-       struct est_pos_type est_pos;
-       struct map *map = robot.map;
-       double xx, yy;
-       bool obs_already_seen;
-
-       if (!map)
-               return;
-
-       ShmapPoint2Cell(x, y, &xcell, &ycell);
-       if (!ShmapIsCellInMap(xcell, ycell))
-               return;
-       obs_already_seen = (map->cells[ycell][xcell].flags & (MAP_FLAG_DET_OBST)) != 0;
-
-       DBG("New obstacle detected at cell [%f,%f] \n", x,y);
-       bool needs_replan = false;      // This flag indicates if the path should be recalculated
-       bool obstacle_at_goal = false;  // This flag indicates that the goal is an obstacle
-       //DBG("Cell %d, %d\n", xcell, ycell);
-
-       /** Then all the cells arround obstacle cell are set as
-        * #MAP_NEW_OBSTACLE. Cells of current robot position are not
-        * set to avoid path planning deadlock. If there are a path
-        * cell between them, the path will be recalculated. @see
-        * #OBS_CSPACE. */
-
-       ROBOT_LOCK(est_pos);
-       est_pos = robot.est_pos;
-       ROBOT_UNLOCK(est_pos);
-
-       for (i=(xcell-OBS_AREA); i <= xcell+OBS_AREA; i++) {
-               for (j=(ycell- OBS_AREA); j <=ycell + OBS_AREA; j++) {
-                       if (!ShmapIsCellInMap(i, j)) continue;
-                       ShmapCell2Point(i, j, &xx, &yy);
-                       if (distance(xx, yy, est_pos.x, est_pos.y) > 0.2) {
-                               if (i==xcell && j==ycell) 
-                                       map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
-                               map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
-                               if (map->cells[j][i].flags & MAP_FLAG_PATH) needs_replan = true;
-                               if (map->cells[j][i].flags & MAP_FLAG_GOAL) obstacle_at_goal = true;
-                       }
-               }
-       }
-
-       // Path recalculation if the goal is not an obstacle and the path should be recalc
-       if (obstacle_at_goal) {
-               FSM_SIGNAL(MOTION, EV_MOVE_STOP, NULL);
-               FSM_SIGNAL(MAIN, EV_GOAL_NOT_REACHABLE, NULL);
-       }
-       else if (needs_replan && !obs_already_seen) {
-               if (new_goal() == 0)
-                       DBG("Path recalc\n");
-               else {
-                       // TODO:
-               }
-       }
-}
-
-/**
- * A thread running the trajectory recalc
- *
- * This (low-medium priority) thread updates the map with sensors information.
- * If it is necesary, it recalculate the path.
- *
- * @param arg
- *
- * @return
- */
-static void * trajctory_recalc(void * arg)
-{
-#define NUM_SHARPS 3
-       double val[NUM_SHARPS], x, y;
-       //Pos p;
-       struct est_pos_type p;
-       int i;
-       
-       while (1) {
-               /** Updates Map. */
-               //ShmapUpdateTmpObstacles(OBS_UPDATE_MAP_SPEED);
-               /* FIXME: here should be data from opponent sharp sensors */
-               ROBOT_LOCK(sharps);
-               val[0] = robot.sharps.front_left;
-               val[1] = robot.sharps.front_right;
-               ROBOT_UNLOCK(sharps);
-               
-               const float ang[NUM_SHARPS] = {DEG2RAD(22), DEG2RAD(0), DEG2RAD(-22)};
-               for (i=0; i<NUM_SHARPS; i++) {
-                       if(val[i] < OBS_OFFSET) {
-                               /** Get actual position. */
-                               ROBOT_LOCK(est_pos);
-                               p = robot.est_pos;
-                               ROBOT_UNLOCK(est_pos);
-                               /**
-                               * The obstacle cell its calulated as (val*cos(p.phi)) + p.x) and  ((val*sin(p.phi)) + p.y)
-                               * where p is actual position and val is the value of the sensors in milimiters. Then ShmapPoint2Cell_X() and
-                               * ShmapPoint2Cell_Y() funcions are used to get cell coordonate.
-                               */
-                               val[i] += ROBOT_AXIS_TO_BELT_M;
-                               x = val[i]*cos(p.phi+ang[i]) + p.x;
-                               y = val[i]*sin(p.phi+ang[i]) + p.y;
-                               obstacle_detected_at(x, y);
-       
-                               //waits between detection
-                               usleep(OBS_PERIOD_BETWEEN_DET);
-                       }
-               }
-               
-               /** This process repeats with a period of #OBS_PERIOD_WATCH. */
-               usleep(OBS_PERIOD_WATCH);
-       }
-}
-
-/**
- * A thread updating the map
- */
-static void * thread_update_map(void * arg)
-{
-       int val = (long long)MAP_NEW_OBSTACLE/(OBS_FORGET_SEC*1000000/OBS_FORGET_PERIOD);
-       if (val == 0) val = 1;
-       while (1) {
-               /** Updates Map. */
-               ShmapUpdateTmpObstacles(val);
-               usleep(OBS_FORGET_PERIOD);
+               do_control();
        }
 }
 
@@ -379,15 +234,18 @@ static void stop()
        pthread_kill(thr_trajctory_follower, SIG_NEWDATA);
 }
 
-
+enum target_status {
+       TARGET_OK,
+       TARGET_NOT_REACHABLE,
+       TARGET_ERROR
+};
 /**
- * @brief      Calculates and simplify a path to goal position avoiding obstacles. In case of error it sends the proper event to MAIN FSM.
- * @return     Zero on succes, non-zero on error.
- * @note Only call this function from this file.
+ * @brief      Calculates and simplify a path to goal position avoiding obstacles.
+ * @return     True on succes, false on error.
  */
-static int new_goal(void)
+static enum target_status new_goal(struct move_target *target)
 {
-       struct ref_pos_type goal;
+       enum target_status ret; 
        double startx, starty, angle;
        PathPoint * path = NULL;
        PathPoint * tmp_point = NULL;
@@ -406,38 +264,22 @@ static int new_goal(void)
        start.phi = robot.est_pos.phi;
        tc = robot.goal_trajectory_constraints;
        ROBOT_UNLOCK(est_pos);
-       /// Get goal position.
-       ROBOT_LOCK(goal);
-       goal = robot.goal;
-       ROBOT_UNLOCK(goal);
 
        //DBG("Going from (%.2f, %.2f) to (%.2f, %.2f)\n", startx, starty, goalx, goaly);
        /// Calculates the path between actual position to goal position. If the goal is not reachable returns -1.
-       switch (path_planner(startx, starty, goal.x, goal.y, &path, &angle)) {
-               case 1:
-                       break;
+       switch (path_planner(startx, starty, target->x, target->y, &path, &angle)) {
                case PP_ERROR_MAP_NOT_INIT:
-                       printf("ERROR: Map not initialized\n");
-                       FSM_SIGNAL(MOTION, EV_MOVE_STOP, NULL);
-                       FSM_SIGNAL(MAIN, EV_GOAL_NOT_REACHABLE, NULL);
-                       return -1;
-                       break;
+                       ret = TARGET_ERROR; break;
                case PP_ERROR_GOAL_IS_OBSTACLE:
-                       printf("ERROR: Goal is obstacle\n");
-                       FSM_SIGNAL(MOTION, EV_MOVE_STOP, NULL);
-                       FSM_SIGNAL(MAIN, EV_GOAL_NOT_REACHABLE, NULL);
-                       return -1;
-                       break;
                case PP_ERROR_GOAL_NOT_REACHABLE:
-                       FSM_SIGNAL(MOTION, EV_MOVE_STOP, NULL);
-                       FSM_SIGNAL(MAIN, EV_GOAL_NOT_REACHABLE, NULL);
-                       return -1;
-                       break;
+                       ret = TARGET_NOT_REACHABLE; break; 
                default:
-                       break;
-               // shouldn't we call freePathMemory() here? No, because no memory has been allocanted for the path, path is only a pointer to NULL
+                       ret = TARGET_OK; break;
        }
 
+       if (ret != TARGET_OK)
+               return ret;
+
        bool backward = false;
        Trajectory *t = new Trajectory(tc, backward);
 
@@ -447,21 +289,16 @@ static int new_goal(void)
                t->addPoint(tmp_point->x, tmp_point->y);
        }
 
-       // add the path to the robot trajectory
-       t->finalHeading = robot.goal_final_heading; // NAN should be OK here, if not, it is error.
-
-       // Free path allocated memory
+       t->finalHeading = target->h;
        freePathMemory(path);
 
        if (t->prepare(start)) {
                go(t);
        } else {
                delete(t);
-               FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
-               return -1;
+               ret = TARGET_ERROR;
        }
-
-       return 0;
+       return ret;
 }
 
 
@@ -470,24 +307,16 @@ static int new_goal(void)
  * movehelper.cc. In case of error it sends the proper event to MAIN
  * FSM.
  *
- * @return Zero on succes, non-zero on error. 
+ * @return true on succes, false on error. 
  */
-static int new_trajectory(void)
+static enum target_status new_trajectory(Trajectory *t)
 {
-       Trajectory *t;
        Pos pos;
-       ROBOT_LOCK(new_trajectory);
-       t = (Trajectory*) robot.new_trajectory;
-       if (t) robot.new_trajectory = NULL;
-       else {
-               ROBOT_UNLOCK(new_trajectory);
-               DBG("No trajectory\n");
-               FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
-               return -1;
-       }
-       ROBOT_UNLOCK(new_trajectory);
-
 
+       if (!t) {
+               printf("ERROR: No trajectory\n");
+               return TARGET_ERROR;
+       }
        ROBOT_LOCK(est_pos);
        pos.x = robot.est_pos.x;
        pos.y = robot.est_pos.y;
@@ -496,11 +325,27 @@ static int new_trajectory(void)
 
        if (t->prepare(pos)) {
                go(t);
+               return TARGET_OK;
        } else {
-               FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL); // FIXME: Is this correct?
-               return -1;
+               delete(t);
+               return TARGET_ERROR;
        }
-       return 0;
+}
+
+static enum target_status new_target(struct move_target *target)
+{
+       enum target_status ret;
+       if (target->trajectory) {
+               ret = new_trajectory((Trajectory*)target->trajectory);
+               // Trajectory is deleted by somebody else
+               target->trajectory = NULL;
+       } else {
+               ret = new_goal(target);
+       }
+       if (ret != TARGET_ERROR) {
+               current_target = *target;
+       }
+       return ret;
 }
 
 /*******************************************************************************
@@ -510,6 +355,8 @@ static int new_trajectory(void)
 FSM_STATE_DECL(movement);
 FSM_STATE_DECL(close_to_target);
 FSM_STATE_DECL(wait_for_command);
+FSM_STATE_DECL(reset_mcl);
+FSM_STATE_DECL(wait_and_try_again);
 
 
 FSM_STATE(init)
@@ -561,37 +408,28 @@ FSM_STATE(init)
        }
 }
 
-FSM_STATE(delay)
-{
-       switch (FSM_EVENT) {
-               case EV_ENTRY:
-                       FSM_TIMER(FSM_EVENT_INT);
-                       break;
-               case EV_TIMER:
-                       SUBFSM_RET(NULL);
-                       break;
-       }
-}
-
 FSM_STATE(wait_for_command)
 {
+       enum target_status ret;
        switch (FSM_EVENT) {
                case EV_ENTRY:
                        stop();
                        break;
-               case EV_NEW_GOAL:
-                       if (new_goal() != 0) {
-                               // The event must be the return value of new_goal()
-                               DBG("Goal error\n");
-                               break;
-                       }
-                       FSM_TRANSITION(movement);
-                       break;
-               case EV_NEW_TRAJECTORY:
-                       if (new_trajectory() != 0) {
-                               break;
+               case EV_NEW_TARGET:
+                       ret = new_target((struct move_target*)FSM_EVENT_PTR);
+                       switch (ret) {
+                               case TARGET_OK:
+                                       FSM_TRANSITION(movement);
+                                       break;
+                               case TARGET_ERROR:
+                                       printf("Target error\n");
+                                       FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
+                                       break;
+                               case TARGET_NOT_REACHABLE:
+                                       FSM_TRANSITION(wait_and_try_again);
+                                       break;
                        }
-                       FSM_TRANSITION(movement);
+                       free(FSM_EVENT_PTR);
                        break;
                default:
                        break;
@@ -611,9 +449,7 @@ FSM_STATE(movement)
                        FSM_TRANSITION(wait_for_command);
                        break;
                case EV_TRAJECTORY_LOST:
-                       FSM_SIGNAL(LOC, EV_RESET, NULL);
-                       // FIXME: delay and try again
-                       FSM_TRANSITION(wait_for_command);
+                       FSM_TRANSITION(reset_mcl);
                        break;
                case EV_MOVE_STOP:
                        FSM_TRANSITION(wait_for_command);
@@ -621,23 +457,24 @@ FSM_STATE(movement)
                case EV_ENTRY:
                case EV_EXIT:
                        break;
-               case EV_NEW_TRAJECTORY:
-               case EV_LOC_UPDATED:
-
+               case EV_NEW_TARGET:
                case EV_TIMER:
                case EV_RETURN:
-               case EV_NEW_GOAL:
-//                     DBG_PRINT_EVENT("unhaldled event");
+               case EV_FOUND_AFTER_RESET:
+                       DBG_PRINT_EVENT("unhandled event");
                        break;
        }
 }
 
-
 FSM_STATE(close_to_target)
 {
-       FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
        switch (FSM_EVENT) {
+               case EV_RETURN:
+                       if (FSM_EVENT_INT == EV_MOVE_STOP)
+                               FSM_TRANSITION(wait_for_command);
+                       // 
                case EV_ENTRY:
+                       FSM_TIMER(MAX_WAIT_FOR_CLOSE_MS);
                        break;
                case EV_TRAJECTORY_DONE_AND_CLOSE:
                        FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
@@ -645,7 +482,7 @@ FSM_STATE(close_to_target)
                        break;
                case EV_TRAJECTORY_LOST:
                case EV_TIMER:
-                       FSM_SIGNAL(LOC, EV_RESET, NULL);
+                       FSM_TRANSITION(reset_mcl);
                        break;
                case EV_MOVE_STOP:
                        FSM_TRANSITION(wait_for_command);
@@ -654,11 +491,71 @@ FSM_STATE(close_to_target)
                        stop();
                        break;
                case EV_TRAJECTORY_DONE:
-               case EV_NEW_TRAJECTORY:
-               case EV_LOC_UPDATED:
-               case EV_NEW_GOAL:
+               case EV_NEW_TARGET:
+               case EV_FOUND_AFTER_RESET:
+                       DBG_PRINT_EVENT("unhandled event");
+                       break;
+       }
+}
+
+FSM_STATE(reset_mcl)
+{
+       switch (FSM_EVENT) {
+               case EV_ENTRY:
+                       stop();
+                       FSM_SIGNAL(LOC, EV_RESET, NULL);
+                       break;
+               case EV_FOUND_AFTER_RESET:
+                       SUBFSM_RET((void*)EV_FOUND_AFTER_RESET);
+                       printf("TODO: start motion again\n");
+                       break;
+               case EV_MOVE_STOP:
+                       SUBFSM_RET((void*)EV_MOVE_STOP);
+               case EV_EXIT:
+                       break;
+               case EV_TRAJECTORY_DONE:
+               case EV_NEW_TARGET:
+               case EV_TRAJECTORY_DONE_AND_CLOSE:
+               case EV_TRAJECTORY_LOST:
                case EV_RETURN:
+               case EV_TIMER:
                        DBG_PRINT_EVENT("unhandled event");
+       }
+}
+
+
+FSM_STATE(wait_and_try_again)
+{
+       enum target_status ret;
+       switch (FSM_EVENT) {
+               case EV_ENTRY:
+                       stop();
+                       FSM_TIMER(1000);
                        break;
+               case EV_TIMER:
+                       ret = new_goal(&current_target);
+                       switch (ret) {
+                               case TARGET_OK:
+                                       FSM_TRANSITION(movement);
+                                       break;
+                               case TARGET_ERROR:
+                                       printf("Target error\n");
+                                       FSM_SIGNAL(MAIN, EV_MOTION_DONE, NULL);
+                                       break;
+                               case TARGET_NOT_REACHABLE:
+                                       FSM_TRANSITION(wait_and_try_again);
+                                       break;
+                       }
+               case EV_MOVE_STOP:
+                       FSM_TRANSITION(wait_for_command);
+                       break;
+               case EV_TRAJECTORY_DONE:
+               case EV_NEW_TARGET:
+               case EV_TRAJECTORY_DONE_AND_CLOSE:
+               case EV_TRAJECTORY_LOST:
+               case EV_RETURN:
+               case EV_FOUND_AFTER_RESET:
+               case EV_EXIT:
+                       DBG_PRINT_EVENT("unhandled event");
        }
 }
index 253d032e73571c19f0c2bad3ce4ef41f67e7b153..529f80d75e9c6f07d1cb82818bcde2ce25887432 100644 (file)
@@ -48,17 +48,14 @@ struct TrajectoryConstraints trajectoryConstraintsDefault = {
  */
 static void robot_trajectory_new_ex(struct TrajectoryConstraints *tc, bool backward)
 {
-       Trajectory *ot, *nt;
+       Trajectory *t;
        
        if (!tc) tc = &trajectoryConstraintsDefault;
 
-       nt = new Trajectory(*tc, backward);
-       ROBOT_LOCK(new_trajectory);
-       ot = (Trajectory*)robot.new_trajectory;
-       robot.new_trajectory = nt;
-
-       ROBOT_UNLOCK(new_trajectory);
-       if (ot) delete(ot);
+       t = (Trajectory*)robot.new_trajectory;
+       if (t) delete(t);
+       t = new Trajectory(*tc, backward);
+       robot.new_trajectory = t;
 }
 
 
@@ -106,18 +103,14 @@ void robot_set_est_pos_notrans(double x, double y, double phi)
  */
 void robot_trajectory_add_point_notrans(double x_m, double y_m)
 {
-       Trajectory *w;
+       Trajectory *t;
        
-       ROBOT_LOCK(new_trajectory);
-       w = (Trajectory*)robot.new_trajectory;
-       if (w) {
-               w->addPoint(x_m, y_m);
+       t = (Trajectory*)robot.new_trajectory;
+       if (t) {
+               t->addPoint(x_m, y_m);
        }
-       ROBOT_UNLOCK(new_trajectory);
 }
 
-double target_x, target_y;
-
 /** 
  * Adds final point to trajectory objects and starts robot movement.
  * 
@@ -132,19 +125,23 @@ double target_x, target_y;
  */
 void robot_trajectory_add_final_point_notrans(double x_m, double y_m, struct final_heading *heading)
 {
-       target_x = x_m;
-       target_y = y_m;
-       robot_trajectory_add_point_notrans(target_x, target_y);
-       
-       Trajectory *w;
-       ROBOT_LOCK(new_trajectory);
-       w = (Trajectory*)robot.new_trajectory;
-       if (w) {
-               w->finalHeading = *heading;
+       struct move_target *target;
+       robot_trajectory_add_point_notrans(x_m, y_m);
+       Trajectory *t;
+
+       t = (Trajectory*)robot.new_trajectory;
+       if (t) {
+               t->finalHeading = *heading;
+               target = (struct move_target*)malloc(sizeof(*target));
+               target->x = x_m;
+               target->y = y_m;
+               target->h = *heading;
+               target->trajectory = t;
+               FSM_SIGNAL(MOTION, EV_NEW_TARGET, target);
+               robot.new_trajectory = NULL;
+       } else {
+               printf("%s: Error - No trajectory\n", __FUNCTION__);
        }
-       ROBOT_UNLOCK(new_trajectory);
-
-       FSM_SIGNAL(MOTION, EV_NEW_TRAJECTORY, NULL);
 }
 
 
@@ -184,21 +181,17 @@ void robot_send_speed(double left, double right) {
  * 
  * @param x X coordinate in meters.
  * @param y Y coordinate in meters.
- * @param heading Desired heading (in degrees) of the robot at goal
- *                point. NAN means don't care. Positive number or zero
- *                means turn counter-clockwise, negative number means
- *                turn clockwise. Example: DEG2RAD(90) means turn up
- *                counter-clockwise and DEG2RAD(-270) means turn up
- *                clockwise.
+ * @param heading Desired heading of the robot at goal point. 
  */
 void robot_goto_notrans(double x, double y, struct final_heading *heading, struct TrajectoryConstraints *tc)
 {
-       ROBOT_LOCK(goal);
-       robot.goal.x = x;
-       robot.goal.y = y;
-       robot.goal_final_heading = *heading;
-       if (tc) robot.goal_trajectory_constraints = *tc;
-       else robot.goal_trajectory_constraints = trajectoryConstraintsDefault;
-       ROBOT_UNLOCK(goal);
-       FSM_SIGNAL(MOTION, EV_NEW_GOAL, NULL);
+       struct move_target *target;
+       target = (struct move_target*)malloc(sizeof(*target));
+       target->x = x;
+       target->y = y;
+       target->h = *heading;
+       if (tc) target->tc = *tc;
+       else target->tc = trajectoryConstraintsDefault;
+       
+       FSM_SIGNAL(MOTION, EV_NEW_TARGET, target);
 }
index b85cfbe45243160c796d493475b086aaa87efa1e..0963bab7a7fd4023a9cc1e9b8214cc8ac46bd169 100644 (file)
@@ -6,6 +6,15 @@
 #include <trgenconstr.h>
 #include <math.h>
 
+/* Represents the target position of a move. If the reajectory is not
+ * specified, it is created by path planning algorithm. */
+struct move_target {
+       double x, y;
+       struct final_heading h;
+       void *trajectory;
+       struct TrajectoryConstraints tc;
+};
+
 extern struct TrajectoryConstraints trajectoryConstraintsDefault;
 
 #ifdef __cplusplus
index 851162384cc70a7f6446097caf58ca086523b4d2..622aab0e6500b3a35c21e094e3d3b3e8bb4bf490 100644 (file)
@@ -20,12 +20,11 @@ events = {
     },
     "motion" : {
        "EV_MOVE_STOP" : "Stop current motion as fast as possible",
-       "EV_NEW_TRAJECTORY" : "New trajectory submitted to robot.new_trajectory",
-       "EV_NEW_GOAL" : "A new goal is received",
+       "EV_NEW_TARGET" : "New target (point or trajectory) is sent",
         "EV_TRAJECTORY_LOST" : "Actual position of the robot is too far from reference",
         "EV_TRAJECTORY_DONE" : "Reference position is at the end of the previously submitted trajectory",
        "EV_TRAJECTORY_DONE_AND_CLOSE" : "::EV_TRAJECTORY_DONE + distance of actual position to the target is less than XXX",
-       "EV_LOC_UPDATED" : "Localization updated the estimate of the robot position",
+       "EV_FOUND_AFTER_RESET" : "MCL estimated position after reset",
     },
     "joystick" : {
     },
index a35512e3f8a4a4be3dc17917bf5edbc17c289ada..b26f30277ef819dfe1e37357170f91b89491db86 100644 (file)
@@ -113,10 +113,8 @@ extern struct lock_log robot_lock_log;
 #define __robot_lock_ref_pos           lock_ref_pos
 #define __robot_lock_est_pos           lock_est_pos
 #define __robot_lock_des_pos           lock
-#define __robot_lock_goal              lock
 #define __robot_lock_joy_data          lock_joy_data
 #define __robot_lock_meas_angles       lock_meas_angles
-#define __robot_lock_new_trajectory    lock
 #define __robot_lock_drives            lock
 #define __robot_lock_sharps            lock
 #define __robot_lock_cmu               lock
index 8a17d880a18f23386cc5565e93f75750fa69cb66..26c9f2a55484bae85066efa3f18b11d5b51b2430 100644 (file)
@@ -52,7 +52,7 @@ FSM_STATE(rectangle)
                        follow_rectangle();
                        break;
                case EV_MOTION_DONE:
-                       FSM_TRANSITION(wait);
+                       FSM_TRANSITION(turn);
                        break;
                default:
                        break;
@@ -65,7 +65,7 @@ FSM_STATE(turn)
                case EV_ENTRY:
                        robot_trajectory_new(NULL);
                        robot_trajectory_add_final_point_trans(1, 0.5, 
-                                               TURN_CW(DEG2RAD(-90)));
+                                               TURN_CW(DEG2RAD(0)));
                        break;
                case EV_MOTION_DONE:
                        FSM_TRANSITION(wait);