7 /*******************************************************************************
8 * Parameters of Obstacle detection
9 *******************************************************************************/
11 #define OBS_SIZE_M 0.2 /**< Expected size of detected obstacle */
12 #define IGNORE_CLOSER_THAN_M 0.2 /**< Do not mark any obstacle closer than this to center of the robot (avoid path planning deadlock) */
13 #define IGNORE_FURTHER_THAN_M 0.5 /**< Ignore data from sharp if further than this */
14 #define OBS_FORGET_PERIOD 100 /**< The period of thread_obstacle_forgeting [ms] */
15 #define OBS_FORGET_SEC 1 /**< Time to completely forget detected obstacle. */
16 #define OBS_OFFSET 0.6
18 void obstacle_detected_at(double x, double y, bool real_obstacle)
20 int i,j, xcell, ycell;
21 struct robot_pos_type est_pos;
22 struct map *map = robot.map;
29 ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
30 /* Ignore obstacles outside playground */
34 /* Ignore obstacles at marked places */
35 if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
39 /* The obstacle was detected here */
40 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
43 /** Then all the cells arround obstacle cell are set as
44 * #MAP_NEW_OBSTACLE. Cells of current robot position are not
45 * set to avoid path planning deadlock. If there are a path
46 * cell between them, the path will be recalculated. @see
49 /* Mark "protected" area around the obstacle */
50 ROBOT_LOCK(est_pos_uzv);
51 est_pos = robot.est_pos_uzv;
52 ROBOT_UNLOCK(est_pos_uzv);
53 int obst_size_cell = (int)ceil(OBS_SIZE_M/MAP_CELL_SIZE_M);
54 for (i=(xcell-obst_size_cell); i <= xcell+obst_size_cell; i++) {
55 for (j=(ycell- obst_size_cell); j <=ycell + obst_size_cell; j++) {
56 if (!ShmapIsCellInMap(i, j)) continue;
57 ShmapCell2Point(i, j, &xx, &yy);
58 if ((distance(xx, yy, est_pos.x, est_pos.y) > IGNORE_CLOSER_THAN_M) &&
59 (distance(xx, yy, x, y) < OBS_SIZE_M)) { /* We expect cirtular area around obstacle */
60 map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
66 * A thread running the trajectory recalc
68 * This (low-medium priority) thread updates the map with sensors information.
69 * If it is necesary, it recalculate the path.
76 void obst_coord(struct robot_pos_type *e, const struct sharp_pos *s, double v, double *x, double *y)
79 sx = e->x + s->x*cos(e->phi) - s->y*sin(e->phi);
80 sy = e->y + s->x*sin(e->phi) + s->y*cos(e->phi);
88 void update_map(struct sharps_type *s)
90 double val[SHARP_COUNT] = { s->left, s->right, s->front_left, s->front_right,
91 s->back_left, s->back_right };
92 int sharp80[] = {0,1,2,3};
95 struct robot_pos_type e;
98 ROBOT_LOCK(est_pos_uzv);
99 e = robot.est_pos_uzv;
100 ROBOT_UNLOCK(est_pos_uzv);
102 for (i=0; i<sizeof(sharp80)/sizeof(sharp80[0]); i++) {
104 if (val[j] < IGNORE_FURTHER_THAN_M) {
105 obst_coord(&e, &sharp[j], val[j], &x, &y);
106 obstacle_detected_at(x, y, true);
108 /* The second end of oponents robot */
109 obst_coord(&e, &sharp[j], val[j]+0.3, &x, &y);
110 obstacle_detected_at(x, y, false);
116 void update_map_hokuyo(struct hokuyo_scan_type *s)
120 struct robot_pos_type e;
122 struct sharp_pos beam;
125 ROBOT_LOCK(est_pos_uzv);
126 e = robot.est_pos_uzv;
127 ROBOT_UNLOCK(est_pos_uzv);
129 beam.x = HOKUYO_CENTER_OFFSET_M;
134 for (i = 0; i < HOKUYO_CLUSTER_CNT; i++) {
138 beam.ang = HOKUYO_CLUSTER_TO_RAD(i);
139 obst_coord(&e, &beam, data[i]/1000.0, &x, &y);
140 obstacle_detected_at(x, y, true);
141 obst_coord(&e, &beam, (data[i]/1000.0)+0.3, &x, &y);
142 obstacle_detected_at(x, y, false);
149 * Decrease map.detected_obstacle by val with saturation on zero. It
150 * also clears #MAP_FLAG_DET_OBST if value reaches zero.
152 * @param val Value to decrease obstacle life.
153 * @see map #MAP_NEW_OBSTACLE
154 * @todo Do faster this process. Use a cell's list to update.
156 static void forget_obstacles(map_cell_detobst_t val){
158 struct map *map = robot.map;
160 for (j=0;j<MAP_HEIGHT;j++){
161 for(i=0;i<MAP_WIDTH;i++){
162 struct map_cell *cell = &map->cells[j][i];
163 cell->flags &= ~MAP_FLAG_DET_OBST;
164 if (val < cell->detected_obstacle) cell->detected_obstacle -= val;
166 cell->detected_obstacle = 0;
167 cell->flags &= ~MAP_FLAG_DET_OBST;
173 static void gettimeofday_ts(struct timespec *ts)
176 gettimeofday(&tv, NULL);
177 /* Convert from timeval to timespec */
178 ts->tv_sec = tv.tv_sec;
179 ts->tv_nsec = tv.tv_usec * 1000;
183 * A thread updating the map
185 void * thread_obstacle_forgeting(void * arg)
189 int val = (long long)MAP_NEW_OBSTACLE/(OBS_FORGET_SEC*1000/OBS_FORGET_PERIOD);
190 if (val == 0) val = 1;
192 gettimeofday_ts(&ts);
194 sem_init(&timer, 0, 0);
196 __fsm_timespec_add_ms(&ts, NULL, OBS_FORGET_PERIOD);
197 sem_timedwait(&timer, &ts);
199 forget_obstacles(val);