]> rtime.felk.cvut.cz Git - eurobot/public.git/blob - src/robofsm/eb2008/map_handling.c
Switched back to long sharps
[eurobot/public.git] / src / robofsm / eb2008 / map_handling.c
1 #include <robot_eb2008.h>
2 #include <robodim_eb2008.h>
3 #include <map.h>
4 #include <robomath.h>
5
6 /*******************************************************************************
7  * Parameters of Obstacle detection
8  *******************************************************************************/
9
10 #define OBS_SIZE_M 0.2          /**< Expected size of detected obstacle  */
11 #define IGNORE_CLOSER_THAN_M 0.2 /**< Do not mark any obstacle closer than this to center of the robot (avoid path planning deadlock) */
12 #define IGNORE_FURTHER_THAN_M 0.5 /**< Ignore data from sharp if further than this */
13 #define OBS_FORGET_PERIOD       500             /**< The period of thread_obstacle_forgeting [ms] */
14 #define OBS_FORGET_SEC 5                        /**< Time to completely forget detected obstacle. */
15 #define OBS_OFFSET      0.6
16
17 void obstacle_detected_at(double x, double y, bool real_obstacle)
18 {
19         int i,j, xcell, ycell;
20         struct est_pos_type est_pos;
21         struct map *map = robot.map;
22         double xx, yy;
23         bool valid;
24
25         if (!map)
26                 return;
27
28         ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
29         /* Ignore obstacles outside playground */
30         if (!valid)
31                 return;
32
33         /* Ignore obstacles at marked places */
34         if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
35                 return;
36
37         if (real_obstacle) {
38                 /* The obstacle was detected here */
39                 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
40         }
41
42         /** Then all the cells arround obstacle cell are set as
43          * #MAP_NEW_OBSTACLE. Cells of current robot position are not
44          * set to avoid path planning deadlock. If there are a path
45          * cell between them, the path will be recalculated. @see
46          * #OBS_CSPACE. */
47
48         /* Mark "protected" area around the obstacle */
49         ROBOT_LOCK(est_pos);
50         est_pos = robot.est_pos;
51         ROBOT_UNLOCK(est_pos);
52         int obst_size_cell = (int)ceil(OBS_SIZE_M/MAP_CELL_SIZE_M);
53         for (i=(xcell-obst_size_cell); i <= xcell+obst_size_cell; i++) {
54                 for (j=(ycell- obst_size_cell); j <=ycell + obst_size_cell; j++) {
55                         if (!ShmapIsCellInMap(i, j)) continue;
56                         ShmapCell2Point(i, j, &xx, &yy);
57                         if ((distance(xx, yy, est_pos.x, est_pos.y) > IGNORE_CLOSER_THAN_M) &&
58                             (distance(xx, yy, x, y) < OBS_SIZE_M)) { /* We expect cirtular area around obstacle */
59                                 map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
60                         }
61                 }
62         }
63 }
64 /**
65  * A thread running the trajectory recalc
66  *
67  * This (low-medium priority) thread updates the map with sensors information.
68  * If it is necesary, it recalculate the path.
69  *
70  * @param arg
71  *
72  * @return
73  */
74
75 void obst_coord(struct est_pos_type *e, const struct sharp_pos  *s, double v, double *x, double *y)
76 {
77         double sx, sy, sa;
78         sx = e->x + s->x*cos(e->phi) - s->y*sin(e->phi);
79         sy = e->y + s->x*sin(e->phi) + s->y*cos(e->phi);
80         sa = e->phi + s->ang;
81
82         *x = sx+v*cos(sa);
83         *y = sy+v*sin(sa);
84 }
85
86 void update_map(struct sharps_type *s)
87 {
88         double val[SHARP_COUNT] = { s->left, s->right, s->front_left, s->front_right,
89                                     s->back_left, s->back_right };
90         int sharp80[] = {0,1,2,3};
91         double x, y;
92         //Pos p;
93         struct est_pos_type e;
94         int i, j;
95
96         ROBOT_LOCK(est_pos);
97         e = robot.est_pos;
98         ROBOT_UNLOCK(est_pos);
99
100         for (i=0; i<sizeof(sharp80)/sizeof(sharp80[0]); i++) {
101                 j = sharp80[i];
102                 if (val[j] < IGNORE_FURTHER_THAN_M) {
103                         obst_coord(&e, &sharp[j], val[j], &x, &y);
104                         obstacle_detected_at(x, y, true);
105
106                         /* The second end of oponents robot */
107                         obst_coord(&e, &sharp[j], val[j]+0.3, &x, &y);
108                         obstacle_detected_at(x, y, false);
109                 }
110         }
111 }
112
113 /**
114  * Decrease map.detected_obstacle by val with saturation on zero. It
115  * also clears #MAP_FLAG_DET_OBST if value reaches zero.
116  * 
117  * @param val Value to decrease obstacle life.
118  * @see map #MAP_NEW_OBSTACLE
119  * @todo Do faster this process. Use a cell's list to update.
120  */
121 static void forget_obstacles(map_cell_detobst_t val){
122         int i,j;
123         struct map *map = robot.map;
124
125         for (j=0;j<MAP_HEIGHT;j++){
126                 for(i=0;i<MAP_WIDTH;i++){
127                         struct map_cell *cell = &map->cells[j][i];
128                         cell->flags &= ~MAP_FLAG_DET_OBST;
129                         if (val < cell->detected_obstacle) cell->detected_obstacle -= val;
130                         else {
131                                 cell->detected_obstacle = 0;
132                                 cell->flags &= ~MAP_FLAG_DET_OBST;
133                         }
134                 }
135         }
136 }
137
138 static void gettimeofday_ts(struct timespec *ts)
139 {
140         struct timeval tv;
141         gettimeofday(&tv, NULL);
142         /* Convert from timeval to timespec */
143         ts->tv_sec = tv.tv_sec;
144         ts->tv_nsec = tv.tv_usec * 1000;
145 }
146
147 /**
148  * A thread updating the map
149  */
150 void * thread_obstacle_forgeting(void * arg)
151 {
152         struct timespec ts;
153         sem_t timer;
154         int val = (long long)MAP_NEW_OBSTACLE/(OBS_FORGET_SEC*1000/OBS_FORGET_PERIOD);
155         if (val == 0) val = 1;
156
157         gettimeofday_ts(&ts);
158         
159         sem_init(&timer, 0, 0);
160         while (1) {
161                 __fsm_timespec_add_ms(&ts, NULL, OBS_FORGET_PERIOD);
162                 sem_timedwait(&timer, &ts);
163
164                 forget_obstacles(val);
165         }
166 }