5 #include <shape_detect.h>
7 #include "map_handling.h"
9 /*******************************************************************************
10 * Parameters of Obstacle detection
11 *******************************************************************************/
13 #define OBS_SIZE_M 0.2 /**< Expected size of detected obstacle */
14 #define IGNORE_CLOSER_THAN_M 0.2 /**< Do not mark any obstacle closer than this to center of the robot (avoid path planning deadlock) */
15 #define IGNORE_FURTHER_THAN_M 0.5 /**< Ignore data from sharp if further than this */
16 #define OBS_FORGET_PERIOD 100 /**< The period of thread_obstacle_forgeting [ms] */
17 #define OBS_FORGET_SEC 1 /**< Time to completely forget detected obstacle. */
19 void obstacle_detected_at(double x, double y, bool real_obstacle)
21 int i,j, xcell, ycell;
22 struct robot_pos_type est_pos;
23 struct map *map = robot.map;
30 ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
31 /* Ignore obstacles outside playground */
35 /* Ignore obstacles at marked places */
36 if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
40 /* The obstacle was detected here */
41 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
44 /** Then all the cells arround obstacle cell are set as
45 * #MAP_NEW_OBSTACLE. Cells of current robot position are not
46 * set to avoid path planning deadlock. If there are a path
47 * cell between them, the path will be recalculated. @see
50 /* Mark "protected" area around the obstacle */
51 robot_get_est_pos(&est_pos.x, &est_pos.y, &est_pos.phi);
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;
67 void figure_detected_at(double x, double y, const bool state)
69 int i,j, xcell, ycell;
70 struct robot_pos_type est_pos;
71 struct map *map = robot.map;
78 ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
79 /* Ignore obstacles outside playground */
83 /* Ignore obstacles at marked places */
84 if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
88 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
90 /* Mark "protected" area around the obstacle */
91 robot_get_est_pos(&est_pos.x, &est_pos.y, &est_pos.phi);
93 int obst_size_cell = (int)ceil(0.2/MAP_CELL_SIZE_M);
94 for (i=(xcell-obst_size_cell); i <= xcell+obst_size_cell; i++) {
95 for (j=(ycell- obst_size_cell); j <=ycell + obst_size_cell; j++) {
96 if (!ShmapIsCellInMap(i, j)) continue;
97 ShmapCell2Point(i, j, &xx, &yy);
98 if ((distance(xx, yy, est_pos.x, est_pos.y) > IGNORE_CLOSER_THAN_M) &&
99 (distance(xx, yy, x, y) < OBS_SIZE_M)) { // We expect cirtular area around obstacle
100 map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
109 * A thread running the trajectory recalc
111 * This (low-medium priority) thread updates the map with sensors information.
112 * If it is necesary, it recalculate the path.
118 void obst_coord(struct robot_pos_type *e, const struct sharp_pos *s, double v, double *x, double *y)
121 sx = e->x + s->x*cos(e->phi) - s->y*sin(e->phi);
122 sy = e->y + s->x*sin(e->phi) + s->y*cos(e->phi);
123 sa = e->phi + s->ang;
129 void get_checkerboard(std::vector<Shape_detect::Point> &team)
131 Shape_detect::Point tmp, newPoint, start;
134 if (robot.team_color) {
145 for (i = 1; i < 4; i++) {
146 for (int j = 0; j < 3; j++) {
147 newPoint.y = tmp.y + 0.7 * j;
149 team.push_back(newPoint);
154 if (robot.team_color) {
155 tmp.x = start.x + 0.35;
156 tmp.y = start.y + 0.35;
158 tmp.x = start.x - 0.35;
159 tmp.y = start.y + 0.35;
163 for (i = 1; i < 4; i++) {
164 for (int j = 0; j < 2; j++) {
165 newPoint.y = tmp.y + 0.7 * j;
167 team.push_back(newPoint);
172 if (robot.team_color) {
184 inline float point_distance(Shape_detect::Point a, Shape_detect::Point b)
186 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
189 void update_map_lidar(const struct lidar_params *l, struct lidar_scan_type *s)
192 struct robot_pos_type e;
194 struct sharp_pos beam;
197 // static std::vector<Shape_detect::Point> reds;
198 // static std::vector<Shape_detect::Point> blues;
200 // if (reds.size() < 16) {
201 // get_checkerboard(blues);
202 // get_checkerboard(reds);
205 robot_get_est_pos(&e.x, &e.y, &e.phi);
207 beam.x = l->center_offset_m;
212 // Shape_detect shapeDet;
213 // std::vector<Shape_detect::Arc> arcs;
214 // std::vector<Shape_detect::Point> center_arcs;
216 // shapeDet.prepare(data);
217 // shapeDet.arc_detect(arcs);
219 // Shape_detect::Point tmpPoint;
223 // if (arcs.size() > 0) {
224 // for (i = 0; i < arcs.size(); i++) {
225 // x = arcs[i].center.x / 1000;
226 // y = arcs[i].center.y / 1000;
228 // tmpPoint.x = e.x + x * cos(e.phi) - y * sin(e.phi);
229 // tmpPoint.y = e.y + x * sin(e.phi) + y * cos(e.phi);
231 // center_arcs.push_back(tmpPoint);
234 // for (i = 0; i < center_arcs.size(); i++) {
235 // if (robot.team_color) {
236 // for (unsigned int j = 0; j < blues.size(); j++) {
237 // distance = point_distance(blues[j], center_arcs[i]);
238 // if (distance < 0.05) {
239 // figure_detected_at(center_arcs[i].x, center_arcs[i].y, true);
244 // for (unsigned int j = 0; j < reds.size(); j++) {
245 // distance = point_distance(reds[j], center_arcs[i]);
246 // if (distance < 0.05) {
247 // figure_detected_at(center_arcs[i].x, center_arcs[i].y, true);
255 bool obstacle = true;
257 for (i = 0; i < l->data_lenght; i++) {
258 beam.ang = index2rad(*l, i);
260 if ((beam.ang<(-l->range_angle_left/180.0*M_PI)) ||
261 ((beam.ang>(l->range_angle_right/180.0*M_PI)))) {
265 if(data[i] > 19 && data[i] < 2000) {
266 obst_coord(&e, &beam, data[i]/1000.0, &x, &y);
271 // if (center_arcs.size() > 0) {
272 // for (unsigned int j = 0; j < center_arcs.size(); j++) {
273 // if (point_distance(tmpPoint, center_arcs[j]) < 0.12) {
281 obstacle_detected_at(x, y, true);
282 //obst_coord(&e, &beam, (data[i]/1000.0)+0.3, &x, &y);
283 //obstacle_detected_at(x, y, false);
291 * Decrease map.detected_obstacle by val with saturation on zero. It
292 * also clears #MAP_FLAG_DET_OBST if value reaches zero.
294 * @param val Value to decrease obstacle life.
295 * @see map #MAP_NEW_OBSTACLE
296 * @todo Do faster this process. Use a cell's list to update.
298 static void forget_obstacles(map_cell_detobst_t val){
300 struct map *map = robot.map;
302 for (j=0;j<MAP_HEIGHT;j++){
303 for(i=0;i<MAP_WIDTH;i++){
304 struct map_cell *cell = &map->cells[j][i];
305 cell->flags &= ~MAP_FLAG_DET_OBST;
306 if (val < cell->detected_obstacle) cell->detected_obstacle -= val;
308 cell->detected_obstacle = 0;
309 cell->flags &= ~MAP_FLAG_DET_OBST;
315 static void gettimeofday_ts(struct timespec *ts)
318 gettimeofday(&tv, NULL);
319 /* Convert from timeval to timespec */
320 ts->tv_sec = tv.tv_sec;
321 ts->tv_nsec = tv.tv_usec * 1000;
325 * A thread updating the map
327 void * thread_obstacle_forgeting(void * arg)
331 int val = (long long)MAP_NEW_OBSTACLE/(OBS_FORGET_SEC*1000/OBS_FORGET_PERIOD);
332 if (val == 0) val = 1;
334 gettimeofday_ts(&ts);
336 sem_init(&timer, 0, 0);
338 __fsm_timespec_add_ms(&ts, NULL, OBS_FORGET_PERIOD);
339 sem_timedwait(&timer, &ts);
341 forget_obstacles(val);