7 #include <shape_detect.h>
9 #include "map_handling.h"
11 /*******************************************************************************
12 * Parameters of Obstacle detection
13 *******************************************************************************/
15 const double OBS_SIZE_M = 0.2; /**< Expected size of detected obstacle */
16 const double IGNORE_CLOSER_THAN_M = 0.2; /**< Do not mark any obstacle closer than this to center of the robot (avoid path planning deadlock) */
17 const double IGNORE_FURTHER_THAN_M = 0.5; /**< Ignore data from sharp if further than this */
18 const int OBS_FORGET_PERIOD = 100; /**< The period of thread_obstacle_forgeting [ms] */
19 const int OBS_FORGET_SEC = 1; /**< Time to completely forget detected obstacle. */
20 const double OBS_OFFSET = 0.6;
22 void obstacle_detected_at(double x, double y, bool real_obstacle)
24 int i,j, xcell, ycell;
25 struct robot_pos_type est_pos;
26 struct map *map = robot.map;
33 ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
34 /* Ignore obstacles outside playground */
38 /* Ignore obstacles at marked places */
39 if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
43 /* The obstacle was detected here */
44 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
47 /** Then all the cells arround obstacle cell are set as
48 * #MAP_NEW_OBSTACLE. Cells of current robot position are not
49 * set to avoid path planning deadlock. If there are a path
50 * cell between them, the path will be recalculated. @see
53 /* Mark "protected" area around the obstacle */
54 robot.get_est_pos(est_pos.x, est_pos.y, est_pos.phi);
56 int obst_size_cell = (int)ceil(OBS_SIZE_M/MAP_CELL_SIZE_M);
57 for (i=(xcell-obst_size_cell); i <= xcell+obst_size_cell; i++) {
58 for (j=(ycell- obst_size_cell); j <=ycell + obst_size_cell; j++) {
59 if (!ShmapIsCellInMap(i, j)) continue;
60 ShmapCell2Point(i, j, &xx, &yy);
61 if ((distance(xx, yy, est_pos.x, est_pos.y) > IGNORE_CLOSER_THAN_M) &&
62 (distance(xx, yy, x, y) < OBS_SIZE_M)) { // We expect cirtular area around obstacle
63 map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
70 void figure_detected_at(double x, double y, const bool state)
72 int i,j, xcell, ycell;
73 struct robot_pos_type est_pos;
74 struct map *map = robot.map;
81 ShmapPoint2Cell(x, y, &xcell, &ycell, &valid);
82 /* Ignore obstacles outside playground */
86 /* Ignore obstacles at marked places */
87 if (map->cells[ycell][xcell].flags & MAP_FLAG_IGNORE_OBST)
91 map->cells[ycell][xcell].flags |= MAP_FLAG_DET_OBST;
93 /* Mark "protected" area around the obstacle */
94 robot.get_est_pos(est_pos.x, est_pos.y, est_pos.phi);
96 int obst_size_cell = (int)ceil(0.2/MAP_CELL_SIZE_M);
97 for (i=(xcell-obst_size_cell); i <= xcell+obst_size_cell; i++) {
98 for (j=(ycell- obst_size_cell); j <=ycell + obst_size_cell; j++) {
99 if (!ShmapIsCellInMap(i, j)) continue;
100 ShmapCell2Point(i, j, &xx, &yy);
101 if ((distance(xx, yy, est_pos.x, est_pos.y) > IGNORE_CLOSER_THAN_M) &&
102 (distance(xx, yy, x, y) < OBS_SIZE_M)) { // We expect cirtular area around obstacle
103 map->cells[j][i].detected_obstacle = MAP_NEW_OBSTACLE;
112 * A thread running the trajectory recalc
114 * This (low-medium priority) thread updates the map with sensors information.
115 * If it is necesary, it recalculate the path.
121 void obst_coord(struct robot_pos_type *e, const struct sharp_pos *s, double v, double &x, double &y)
124 sx = e->x + s->x*cos(e->phi) - s->y*sin(e->phi);
125 sy = e->y + s->x*sin(e->phi) + s->y*cos(e->phi);
126 sa = e->phi + s->ang;
132 void get_checkerboard(std::vector<Shape_detect::Point> &team)
134 Shape_detect::Point tmp, newPoint, start;
137 if (robot.team_color) {
148 for (i = 1; i < 4; i++) {
149 for (int j = 0; j < 3; j++) {
150 newPoint.y = tmp.y + 0.7 * j;
152 team.push_back(newPoint);
157 if (robot.team_color) {
158 tmp.x = start.x + 0.35;
159 tmp.y = start.y + 0.35;
161 tmp.x = start.x - 0.35;
162 tmp.y = start.y + 0.35;
166 for (i = 1; i < 4; i++) {
167 for (int j = 0; j < 2; j++) {
168 newPoint.y = tmp.y + 0.7 * j;
170 team.push_back(newPoint);
175 if (robot.team_color) {
187 inline float point_distance(Shape_detect::Point a, Shape_detect::Point b)
189 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
192 void update_map_hokuyo(struct hokuyo_scan_type *s)
195 struct robot_pos_type e;
197 struct sharp_pos beam;
200 static std::vector<Shape_detect::Point> reds;
201 static std::vector<Shape_detect::Point> blues;
203 if (reds.size() < 16) {
204 get_checkerboard(blues);
205 get_checkerboard(reds);
208 robot.get_est_pos(e.x, e.y, e.phi);
210 beam.x = HOKUYO_CENTER_OFFSET_M;
215 Shape_detect shapeDet;
216 std::vector<Shape_detect::Arc> arcs;
217 std::vector<Shape_detect::Point> center_arcs;
219 shapeDet.prepare(data);
220 shapeDet.arc_detect(arcs);
222 Shape_detect::Point tmpPoint;
226 if (arcs.size() > 0) {
227 for (i = 0; i < arcs.size(); i++) {
228 x = arcs[i].center.x / 1000;
229 y = arcs[i].center.y / 1000;
231 tmpPoint.x = e.x + x * cos(e.phi) - y * sin(e.phi);
232 tmpPoint.y = e.y + x * sin(e.phi) + y * cos(e.phi);
234 center_arcs.push_back(tmpPoint);
237 for (i = 0; i < center_arcs.size(); i++) {
238 if (robot.team_color) {
239 for (unsigned int j = 0; j < blues.size(); j++) {
240 distance = point_distance(blues[j], center_arcs[i]);
241 if (distance < 0.05) {
242 figure_detected_at(center_arcs[i].x, center_arcs[i].y, true);
247 for (unsigned int j = 0; j < reds.size(); j++) {
248 distance = point_distance(reds[j], center_arcs[i]);
249 if (distance < 0.05) {
250 figure_detected_at(center_arcs[i].x, center_arcs[i].y, true);
258 bool obstacle = true;
260 for (i = 0; i < HOKUYO_ARRAY_SIZE; i++) {
261 beam.ang = HOKUYO_INDEX_TO_RAD(i);
262 if((beam.ang<(-HOKUYO_RANGE_ANGLE_LEFT/180.0*M_PI))||((beam.ang>(HOKUYO_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);