00001 #include "ellipses_representation.h"
00002
00003 using namespace cv;
00004 using namespace std;
00005
00006
00007 EllipsesRepresentation::EllipsesRepresentation(void)
00008 {
00009
00010 currentArmPosition.x = 0;
00011 currentArmPosition.y = 0;
00012 }
00013
00014 EllipsesRepresentation::~EllipsesRepresentation(void)
00015 {
00016 }
00017
00018 void EllipsesRepresentation::config_update(Config& new_cfg, uint32_t level)
00019 {
00020 this->lock();
00021
00022 this->minFillThreshold = new_cfg.minFillThreshold;
00023 this->minAreaThreshold = new_cfg.minAreaThreshold;
00024 this->board_plan = new_cfg.board_plan;
00025 this->max_number_ellipses = new_cfg.max_number_ellipses;
00026 this->small_objects_join_distance = new_cfg.small_objects_join_distance;
00027 this->initial_state_idx = new_cfg.initial_state_idx;
00028
00029
00030
00031 this->min_width_threshold = new_cfg.min_width_threshold;
00032 this->max_width_threshold = new_cfg.max_width_threshold;
00033
00034
00035 this->small_area_threshold = new_cfg.small_area_threshold;
00036 this->medium_area_threshold = new_cfg.medium_area_threshold;
00037 this->near_distance_threshold = new_cfg.near_distance_threshold;
00038
00039 this->is_planning = ((!new_cfg.no_perceptions) && (!new_cfg.no_planning));
00040
00041 this->is_learning = new_cfg.is_learning;
00042
00043
00044 this->config_=new_cfg;
00045
00046 this->unlock();
00047 }
00048
00049
00050 void EllipsesRepresentation::createNewState(cv::Mat image)
00051 {
00052 std::vector<estirabot_msgs::DirtyArea> previousDirtyAreas = this->dirtyAreas_;
00053 clearLastEllipses();
00054 setSourceImage(image);
00055 computeBoundingEllipses(image);
00056 this->dirtyAreas_ = orderDirtyAreas(calculateRosDirtyAreas(imageEllipses), previousDirtyAreas);
00057 }
00058
00059 void EllipsesRepresentation::setSourceImage(cv::Mat image)
00060 {
00061
00062 cv::cvtColor(image, this->show_image, CV_GRAY2BGR);
00063
00064
00065 threshold(image, this->state_image, 10, 255, cv::THRESH_BINARY );
00066 }
00067
00068
00069
00070
00071
00072 bool EllipsesRepresentation::divideBigEllipse(cv::Mat image, cv::Mat ellipseMask, RotatedRect currentEllipse)
00073 {
00074 Mat rectangleMask, finalMask;
00075 Mat firstEllipsePart, secondEllipsePart;
00076 Point2i rectanglePoint;
00077
00078 ROS_DEBUG("Recursive ellipse");
00079
00080 float angle = currentEllipse.angle;
00081
00082 if (angle > 180)
00083 angle -=180;
00084 if (angle > 90)
00085 angle = 180 - angle;
00086
00087
00088
00089 if (currentEllipse.size.width > currentEllipse.size.height) {
00090 if (angle < 45)
00091 rectanglePoint = Point2i(currentEllipse.center.x, image.size().height);
00092 else
00093 rectanglePoint = Point2i(image.size().width, currentEllipse.center.y);
00094 }
00095 else {
00096 if (angle < 45)
00097 rectanglePoint = Point2i(image.size().width, currentEllipse.center.y);
00098 else
00099 rectanglePoint = Point2i(currentEllipse.center.x, image.size().height);
00100 }
00101
00102 rectangleMask = Mat::zeros(image.size(),CV_8UC1);
00103 rectangle(rectangleMask, Point2i(0,0), rectanglePoint, 255, CV_FILLED);
00104
00105
00106 bitwise_and(ellipseMask, rectangleMask, finalMask);
00107 bitwise_and(finalMask, image, firstEllipsePart);
00108
00109
00110 bitwise_not(rectangleMask, rectangleMask);
00111 bitwise_and(ellipseMask, rectangleMask, finalMask);
00112 bitwise_and(finalMask, image, secondEllipsePart);
00113
00114
00115 int sumFirstHalf, sumSecondHalf;
00116 sumFirstHalf = countNonZero(firstEllipsePart);
00117 sumSecondHalf = countNonZero(secondEllipsePart);
00118
00119
00120 if ((sumFirstHalf < 150) || (sumSecondHalf < 150)) {
00121 ROS_INFO("EllipsesRepresentation: Couldn't divide ellipses");
00122
00123 return false;
00124 }
00125 else{
00126 computeBoundingEllipses(firstEllipsePart);
00127 computeBoundingEllipses(secondEllipsePart);
00128
00129 return true;
00130 }
00131 }
00132
00133
00134
00135 void EllipsesRepresentation::computeBoundingEllipses(cv::Mat image)
00136 {
00137 double filledArea, totalArea;
00138 bool sparse;
00139 std::vector<std::vector<cv::Point> > contours;
00140 std::vector<Vec4i> hierarchy;
00141
00142 ROS_DEBUG("Compute ellipses");
00143
00144
00145 if (this->board_plan)
00146 findContours( image, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
00147 else {
00148 cv::Mat image_closed;
00149 cv::Mat element = cv::getStructuringElement(MORPH_ELLIPSE, cv::Size(small_objects_join_distance, small_objects_join_distance));
00150 cv::morphologyEx(image, image_closed, cv::MORPH_CLOSE, element);
00151 findContours( image_closed, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
00152 }
00153
00154 ROS_DEBUG("Extracted contours");
00155
00156 RotatedRect currentEllipse;
00157 for( size_t i = 0; i < contours.size(); i++ ) {
00158 if( contours[i].size() > 5 ) {
00159 ROS_DEBUG("A ellipse");
00160 currentEllipse = fitEllipse( Mat(contours[i]) );
00161
00162
00163 if ((currentEllipse.size.width > 500) || (currentEllipse.size.height > 500)) {
00164 ROS_ERROR("Detected ellipse with a dimension bigger than 500. Ignoring it...");
00165 return;
00166 }
00167
00168
00169 Mat region = Mat::zeros(image.rows, image.cols, CV_8UC1);
00170 drawContours(region, contours, i, Scalar(255), CV_FILLED );
00171 bitwise_and(region, image, region);
00172 filledArea = countNonZero(region);
00173
00174 totalArea = currentEllipse.size.width * currentEllipse.size.height;
00175 sparse = (filledArea/totalArea) < minFillThreshold;
00176 ROS_DEBUG_STREAM("filledArea: "<<filledArea);
00177 ROS_DEBUG_STREAM("totalArea: "<< totalArea);
00178
00179
00180
00181 bool divide_ellipse = (totalArea > minAreaThreshold) and (sparse);
00182
00183 if (divide_ellipse) {
00184 Mat ellipseMask = Mat::zeros(image.size(),CV_8UC1);
00185 drawContours(ellipseMask, contours, i, 255, CV_FILLED);
00186
00187
00188 divide_ellipse = divideBigEllipse(image, ellipseMask, currentEllipse);
00189 }
00190
00191
00192 if (not divide_ellipse) {
00193 this->imageEllipses.push_back(currentEllipse);
00194 this->ellipsesMaxWidths.push_back(currentEllipse.size.height);
00195 this->ellipsesMinWidths.push_back(currentEllipse.size.width);
00196 this->ellipsesArea.push_back(totalArea);
00197 this->ellipsesSparse.push_back(sparse);
00198
00199
00200 ellipse(show_image, currentEllipse, Scalar(0,0,255), 2, CV_AA);
00201 }
00202 }
00203 }
00204
00205
00206 if (this->is_planning)
00207 truncateEllipsesNumber();
00208 }
00209
00210
00211 void EllipsesRepresentation::clearLastEllipses()
00212 {
00213 this->imageEllipses.clear();
00214 this->ellipsesMinWidths.clear();
00215 this->ellipsesMaxWidths.clear();
00216 this->ellipsesArea.clear();
00217 this->ellipsesSparse.clear();
00218 }
00219
00220
00221 void EllipsesRepresentation::truncateEllipsesNumber()
00222 {
00223 if (imageEllipses.size() <= this->max_number_ellipses)
00224 return;
00225
00226 Point origPoint = Point(0,0);
00227 std::set<size_t> availableEllipses;
00228 std::vector<size_t> selectedEllipses;
00229
00230 for (size_t i = 0; i < this->imageEllipses.size(); i++)
00231 availableEllipses.insert(i);
00232
00233 size_t nearestEllipse;
00234 double distance, minDist;
00235
00236 for (size_t i = 0; i < this->max_number_ellipses; i++) {
00237 minDist = 2000;
00238 for (size_t j = 0; j < this->imageEllipses.size(); j++) {
00239 if (availableEllipses.find(j) != availableEllipses.end()) {
00240 distance = getDistance(origPoint, imageEllipses[j].center);
00241 if (distance < minDist) {
00242 minDist = distance;
00243 nearestEllipse = j;
00244 }
00245 }
00246 }
00247 selectedEllipses.push_back(nearestEllipse);
00248 availableEllipses.erase(nearestEllipse);
00249 }
00250
00251 std::vector<cv::RotatedRect> newImageEllipses;
00252 std::vector<double> newEllipsesMinWidths;
00253 std::vector<double> newEllipsesMaxWidths;
00254 std::vector<double> newEllipsesArea;
00255 std::vector<uint8_t> newEllipsesSparse;
00256
00257 for (size_t i = 0; i < selectedEllipses.size(); i++) {
00258 newImageEllipses.push_back(this->imageEllipses[ selectedEllipses[i] ]);
00259 newEllipsesMinWidths.push_back(this->ellipsesMinWidths[ selectedEllipses[i] ]);
00260 newEllipsesMaxWidths.push_back(this->ellipsesMaxWidths[ selectedEllipses[i] ]);
00261 newEllipsesArea.push_back(this->ellipsesArea[ selectedEllipses[i] ]);
00262 newEllipsesSparse.push_back(this->ellipsesSparse[ selectedEllipses[i] ]);
00263 }
00264
00265 this->imageEllipses = newImageEllipses;
00266 this->ellipsesMinWidths = newEllipsesMinWidths;
00267 this->ellipsesMaxWidths = newEllipsesMaxWidths;
00268 this->ellipsesArea = newEllipsesArea;
00269 this->ellipsesSparse = newEllipsesSparse;
00270 }
00271
00272
00273 std::vector< estirabot_msgs::PointsDistanceMsg > EllipsesRepresentation::distancesBetweenEllipses(std::vector<estirabot_msgs::DirtyArea> dirty_areas)
00274 {
00275 std::vector< estirabot_msgs::PointsDistanceMsg > result;
00276
00277 for(size_t i=0; i < dirty_areas.size(); i++) {
00278 for(size_t j=i+1; j < dirty_areas.size(); j++) {
00279 estirabot_msgs::PointsDistanceMsg distanceMsg;
00280 distanceMsg.origIdx = dirty_areas[i].id;
00281 distanceMsg.dstIdx = dirty_areas[j].id;
00282 distanceMsg.distance = getDistance(dirty_areas[i].ellipse.center, dirty_areas[j].ellipse.center);
00283
00284 result.push_back(distanceMsg);
00285 }
00286 }
00287
00288 return result;
00289 }
00290
00291
00292 bool EllipsesRepresentation::pointIsBetween(iri_perception_msgs::ImagePoint new_p1, iri_perception_msgs::ImagePoint new_p2, iri_perception_msgs::ImagePoint new_point)
00293 {
00294 cv::Point2f p2;
00295 p2.x = new_p2.x;
00296 p2.y = new_p2.y;
00297 return pointIsBetween(new_p1, p2, new_point);
00298 }
00299
00300 bool EllipsesRepresentation::pointIsBetween(iri_perception_msgs::ImagePoint new_p1, cv::Point2f p2, iri_perception_msgs::ImagePoint new_point)
00301 {
00302 cv::Point2f p1, point;
00303 p1.x = new_p1.x;
00304 p1.y = new_p1.y;
00305 point.x = new_point.x;
00306 point.y = new_point.y;
00307 return pointIsBetween(p1, p2, point);
00308 }
00309
00310 bool EllipsesRepresentation::pointIsBetween(cv::Point2f p1, cv::Point2f p2, cv::Point2f point)
00311 {
00312 float distance, crossproduct, dotproduct, squaredlengthba;
00313 float epsilon = 12;
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 distance = sqrt( pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2) );
00327
00328 crossproduct = (point.y - p1.y) * (p2.x - p1.x) - (point.x - p1.x) * (p2.y - p1.y);
00329
00330 if (abs(crossproduct) > (epsilon * distance))
00331 return false;
00332
00333 dotproduct = (point.x - p1.x) * (p2.x - p1.x) + (point.y - p1.y)*(p2.y - p1.y);
00334 if (dotproduct < 0)
00335 return false;
00336
00337 squaredlengthba = (p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y);
00338 if (dotproduct > squaredlengthba)
00339 return false;
00340
00341 return true;
00342 }
00343
00344 std::vector< estirabot_msgs::TraversedEllipses > EllipsesRepresentation::getTraversedEllipses(std::vector<estirabot_msgs::DirtyArea> dirty_areas)
00345 {
00346 std::vector< estirabot_msgs::TraversedEllipses > result;
00347
00348 for(size_t i=0; i < dirty_areas.size(); i++) {
00349
00350 if (!this->is_learning) {
00351 for(size_t j=i+1; j < dirty_areas.size(); j++) {
00352 estirabot_msgs::TraversedEllipses traversedEllipsesMsg;
00353 traversedEllipsesMsg.idx1 = dirty_areas[i].id;
00354 traversedEllipsesMsg.idx2 = dirty_areas[j].id;
00355
00356 for (size_t k=0; k < dirty_areas.size(); k++) {
00357 if ((k != i) && (k != j) && (pointIsBetween(dirty_areas[i].ellipse.center, dirty_areas[j].ellipse.center, dirty_areas[k].ellipse.center)))
00358 traversedEllipsesMsg.traversedIdxs.push_back(dirty_areas[k].id);
00359 }
00360 result.push_back(traversedEllipsesMsg);
00361 }
00362 }
00363
00364
00365 cv::Point2f edge_point;
00366 int edge_idx;
00367 edge_idx = -1;
00368 edge_point.y = dirty_areas[i].ellipse.center.y;
00369 edge_point.x = IMAGE_WIDTH;
00370 for (size_t k=0; k < dirty_areas.size(); k++) {
00371 estirabot_msgs::TraversedEllipses traversedEllipsesMsg;
00372 traversedEllipsesMsg.idx1 = dirty_areas[i].id;
00373 traversedEllipsesMsg.idx2 = edge_idx;
00374
00375 if ( (k != i) && pointIsBetween(dirty_areas[i].ellipse.center, edge_point, dirty_areas[k].ellipse.center) ) {
00376 traversedEllipsesMsg.traversedIdxs.push_back(dirty_areas[k].id);
00377 }
00378 result.push_back(traversedEllipsesMsg);
00379 }
00380 }
00381
00382 return result;
00383 }
00384
00385
00386 int32_t EllipsesRepresentation::getNearestEllipse()
00387 {
00388 double min = 10000;
00389 int32_t min_idx = -1;
00390
00391 for(size_t i=0; i < imageEllipses.size(); i++) {
00392 double dist = getDistance(currentArmPosition, imageEllipses[i].center);
00393 if (dist < min) {
00394 min = dist;
00395 min_idx = i;
00396 }
00397 }
00398
00399 ROS_DEBUG_STREAM("Minimun distance is: " << min);
00400
00401 return min_idx;
00402 }
00403
00404
00405 void EllipsesRepresentation::drawPoints(std::vector< Point2f > img_coords_orig)
00406 {
00408 std::vector< Point2f > img_coords = img_coords_orig;
00409 img_coords.pop_back();
00410
00411
00412 if (img_coords.size() > 0) {
00413 circle(show_image, img_coords[0], 5, Scalar(255, 0, 0), -1);
00414 }
00415 if (img_coords.size() > 1) {
00416 circle(show_image, img_coords[1], 5, Scalar(0, 255, 0), -1);
00417 line(show_image, img_coords[0], img_coords[1], Scalar(0, 255, 0));
00418 }
00419 if (img_coords.size() > 2) {
00420 circle(show_image, img_coords[2], 5, Scalar(255, 0, 255), -1);
00421 line(show_image, img_coords[1], img_coords[2], Scalar(255, 0, 255));
00422 }
00423 if (img_coords.size() > 3) {
00424 circle(show_image, img_coords[3], 5, Scalar(0, 255, 255), -1);
00425 line(show_image, img_coords[2], img_coords[3], Scalar(0, 255, 255));
00426 }
00427 if (img_coords.size() > 4) {
00428 circle(show_image, img_coords[4], 5, Scalar(125, 125, 0), -1);
00429 line(show_image, img_coords[3], img_coords[4], Scalar(125, 125, 0));
00430 }
00431 if (img_coords.size() > 5) {
00432 circle(show_image, img_coords[5], 5, Scalar(0, 125, 125), -1);
00433 line(show_image, img_coords[4], img_coords[5], Scalar(0, 125, 125));
00434 }
00435 if (img_coords.size() > 6) {
00436 circle(show_image, img_coords[6], 5, Scalar(125, 0, 125), -1);
00437 line(show_image, img_coords[5], img_coords[6], Scalar(125, 0, 125));
00438 }
00439 if (img_coords.size() > 7) {
00440 circle(show_image, img_coords[7], 5, Scalar(100, 255, 100), -1);
00441 line(show_image, img_coords[6], img_coords[7], Scalar(100, 255, 100));
00442 }
00443 }
00444
00445
00446 std::vector< size_t > EllipsesRepresentation::getGoodPathThroughAllEllipses(size_t init_ellipse)
00447 {
00448 std::vector< size_t > result;
00449
00450 std::set<size_t> visited;
00451
00452 int min_dist, distance;
00453 size_t min_idx, last_idx;
00454
00455 result.push_back(init_ellipse);
00456 visited.insert(init_ellipse);
00457 last_idx = init_ellipse;
00458
00459 for(size_t i=1; i < imageEllipses.size(); i++) {
00460 ROS_DEBUG_STREAM("Nearest ellipse for " << last_idx);
00461 min_dist = 10000;
00462 for(size_t j=0; j < imageEllipses.size(); j++) {
00463 ROS_DEBUG_STREAM("New j is " << j);
00464 if (visited.find(j) == visited.end()) {
00465 distance = getDistance(imageEllipses[last_idx].center, imageEllipses[j].center);
00466 ROS_DEBUG_STREAM("Distance " << distance);
00467 if (distance < min_dist) {
00468 min_dist = distance;
00469 min_idx = j;
00470 }
00471 }
00472 }
00473
00474 result.push_back(min_idx);
00475 visited.insert(min_idx);
00476 last_idx = min_idx;
00477 ROS_DEBUG_STREAM("Nearest ellipse was " << last_idx);
00478 }
00479
00480 return result;
00481 }
00482
00483
00484 std::vector< size_t > EllipsesRepresentation::getGoodPathThroughAllDirtyAreas(std::vector< estirabot_msgs::DirtyArea > dirty_areas)
00485 {
00486 std::vector< size_t > result;
00487
00488 std::set<size_t> visited;
00489
00490 int min_dist, distance;
00491 size_t min_idx, last_idx;
00492
00493 result.push_back(dirty_areas[0].id);
00494 visited.insert(0);
00495 last_idx = 0;
00496
00497 for(size_t i=1; i < dirty_areas.size(); i++) {
00498 ROS_DEBUG_STREAM("Nearest ellipse for " << last_idx);
00499 min_dist = 10000;
00500 for(size_t j=0; j < dirty_areas.size(); j++) {
00501 ROS_DEBUG_STREAM("New j is " << j);
00502 if (visited.find(j) == visited.end()) {
00503 distance = getDistance( rosEllipseToRotatedRect(dirty_areas[last_idx].ellipse).center, rosEllipseToRotatedRect(dirty_areas[j].ellipse).center);
00504 ROS_DEBUG_STREAM("Distance " << distance);
00505 if (distance < min_dist) {
00506 min_dist = distance;
00507 min_idx = j;
00508 }
00509 }
00510 }
00511
00512 result.push_back(dirty_areas[min_idx].id);
00513 visited.insert(min_idx);
00514 last_idx = min_idx;
00515 ROS_DEBUG_STREAM("Nearest ellipse was " << last_idx);
00516 }
00517
00518 return result;
00519 }
00520
00521
00522 std::vector< cv::RotatedRect> EllipsesRepresentation::loadEllipsesFromRosMsg(vector< estirabot_msgs::Ellipse > ellipses_msg)
00523 {
00524 vector< RotatedRect > ellipses;
00525
00526 for(vector<estirabot_msgs::Ellipse>::iterator j=ellipses_msg.begin(); j!=ellipses_msg.end(); ++j) {
00527 ellipses.push_back(rosEllipseToRotatedRect(*j));
00528 }
00529
00530 return ellipses;
00531 }
00532
00533 std::vector< cv::RotatedRect > EllipsesRepresentation::loadEllipsesFromRosMsg(std::vector< estirabot_msgs::DirtyArea > dirty_areas_msg)
00534 {
00535 vector< RotatedRect > ellipses;
00536
00537 for(vector<estirabot_msgs::DirtyArea>::iterator j=dirty_areas_msg.begin(); j!=dirty_areas_msg.end(); ++j) {
00538 ellipses.push_back(rosEllipseToRotatedRect(j->ellipse));
00539 }
00540
00541 return ellipses;
00542 }
00543
00544
00545 cv::RotatedRect EllipsesRepresentation::getEllipseFromRosDirtyAreas(std::vector< estirabot_msgs::DirtyArea > dirty_areas, int idx)
00546 {
00547 cv::RotatedRect result;
00548 ROS_DEBUG_STREAM("Looking for " << idx);
00549 for(std::vector<estirabot_msgs::DirtyArea>::iterator dirty_area=dirty_areas.begin(); dirty_area!=dirty_areas.end(); ++dirty_area) {
00550 ROS_DEBUG_STREAM("Dirty area is " << *dirty_area);
00551 if (dirty_area->id == idx) {
00552 result = rosEllipseToRotatedRect(dirty_area->ellipse);
00553 ROS_DEBUG_STREAM("Found!");
00554 }
00555 }
00556 return result;
00557 }
00558
00559
00560 std::vector<estirabot_msgs::DirtyArea> EllipsesRepresentation::getRosDirtyAreas()
00561 {
00562 return this->dirtyAreas_;
00563 }
00564
00565 std::vector<estirabot_msgs::DirtyArea> EllipsesRepresentation::calculateRosDirtyAreas(std::vector< cv::RotatedRect > ellipses)
00566 {
00567 std::vector<estirabot_msgs::DirtyArea> dirty_areas;
00568 estirabot_msgs::DirtyArea dirty_area;
00569 double area, min_width, max_width;
00570
00571 for (size_t i = 0; i < ellipses.size(); i++) {
00572 dirty_area.id = i;
00573 dirty_area.ellipse = rotatedRectToRosEllipse(ellipses[i]);
00574 dirty_area.sparse = ellipsesSparse[i];
00575
00576 area = ellipsesArea[i];
00577 if (area < small_area_threshold)
00578 dirty_area.area = 0;
00579 else if (area < medium_area_threshold)
00580 dirty_area.area = 1;
00581 else
00582 dirty_area.area = 2;
00583
00584 min_width = ellipsesMinWidths[i];
00585 max_width = ellipsesMaxWidths[i];
00586 if (max_width < this->max_width_threshold)
00587 dirty_area.shape = 0;
00588 else if (min_width < this->min_width_threshold)
00589 dirty_area.shape = 1;
00590 else
00591 dirty_area.shape = 2;
00592
00593 dirty_areas.push_back(dirty_area);
00594 }
00595
00596 return dirty_areas;
00597 }
00598
00599
00600 void EllipsesRepresentation::writeStateToFile(std::string path,
00601 std::vector<estirabot_msgs::DirtyArea> dirty_areas)
00602 {
00603 std::ofstream state_file(path.c_str());
00604 if (state_file.is_open())
00605 {
00606 state_file << getStateString(dirty_areas);
00607 }
00608 state_file.close();
00609 }
00610
00611
00612 std::string EllipsesRepresentation::dirtyAreaToString(estirabot_msgs::DirtyArea dirty_area, int idx)
00613 {
00614 std::stringstream ss;
00615
00616 ss << "-clean(" << idx << "),";
00617
00618 if (dirty_area.sparse)
00619 ss << "sparse(" << idx << "),";
00620 else
00621 ss << "-sparse(" << idx << "),";
00622
00623 if (dirty_area.area == 0)
00624 ss << "smallArea(" << idx << ")";
00625 else if (dirty_area.area == 1)
00626 ss << "mediumArea(" << idx << ")";
00627 else if (dirty_area.area == 2)
00628 ss << "bigArea(" << idx << ")";
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 return ss.str();
00640 }
00641
00642
00643 std::string EllipsesRepresentation::traversedEllipsesToString(std::vector<estirabot_msgs::TraversedEllipses> traversed_ellipses)
00644 {
00645 std::stringstream ss;
00646 for (size_t i = 0; i < traversed_ellipses.size(); i++) {
00647 for (size_t j = 0; j < traversed_ellipses[i].traversedIdxs.size(); j++) {
00648 if (traversed_ellipses[i].idx1 >= 0) {
00649 if (this->is_learning) {
00650 ss << ", traversed2(" << traversed_ellipses[i].idx1 + this->initial_state_idx << "," << traversed_ellipses[i].traversedIdxs[j] + this->initial_state_idx << ")";
00651 }
00652 else {
00653 ss << ", traversed(" << traversed_ellipses[i].idx1 + this->initial_state_idx << "," << traversed_ellipses[i].idx2 + this->initial_state_idx << "," << traversed_ellipses[i].traversedIdxs[j] + this->initial_state_idx << ")";
00654
00655 ss << ", traversed(" << traversed_ellipses[i].idx2 + this->initial_state_idx << "," << traversed_ellipses[i].idx1 + this->initial_state_idx << "," << traversed_ellipses[i].traversedIdxs[j] + this->initial_state_idx << ")";
00656 }
00657 }
00658 }
00659 }
00660
00661 return ss.str();
00662 }
00663
00664
00665 std::string EllipsesRepresentation::dirtyAreasDistancesToString(std::vector< estirabot_msgs::PointsDistanceMsg> distances)
00666 {
00667 std::stringstream ss;
00668 for (size_t i = 0; i < distances.size(); i++) {
00669 ROS_DEBUG_STREAM("Distance is " << distances[i].distance);
00670 if (distances[i].distance < near_distance_threshold) {
00671 ss << ",near(" << distances[i].origIdx + this->initial_state_idx << "," << distances[i].dstIdx + this->initial_state_idx << ")";
00672 ss << ",near(" << distances[i].dstIdx + this->initial_state_idx << "," << distances[i].origIdx + this->initial_state_idx << ")";
00673 }
00674 }
00675 return ss.str();
00676 }
00677
00678
00679 std::string EllipsesRepresentation::getStateStringOrdered(const std::vector<estirabot_msgs::DirtyArea> dirty_areas)
00680 {
00681 std::stringstream ss;
00682
00683 std::vector<estirabot_msgs::TraversedEllipses> traversed_ellipses = getTraversedEllipses(dirty_areas);
00684 std::vector< estirabot_msgs::PointsDistanceMsg> distances = distancesBetweenEllipses(dirty_areas);
00685
00686 if (!this->is_learning) {
00687 ss << "edge(" << this->initial_state_idx - 1 << "),";
00688 }
00689 for (size_t i = 0; i < dirty_areas.size(); i++) {
00690 ss << dirtyAreaToString(dirty_areas[i], dirty_areas[i].id + this->initial_state_idx);
00691 if (i + 1 < dirty_areas.size())
00692 ss << ",";
00693 }
00694
00695 ss << dirtyAreasDistancesToString(distances);
00696
00697 ss << traversedEllipsesToString(traversed_ellipses);
00698
00699 return ss.str();
00700 }
00701
00702 std::string EllipsesRepresentation::getStateString(const std::vector<estirabot_msgs::DirtyArea> dirty_areas)
00703 {
00704 return getStateStringOrdered(dirty_areas);
00705 }
00706
00707
00708 std::vector<estirabot_msgs::DirtyArea> EllipsesRepresentation::orderDirtyAreas(const std::vector<estirabot_msgs::DirtyArea> current, const std::vector<estirabot_msgs::DirtyArea> previous)
00709 {
00710 std::vector<estirabot_msgs::DirtyArea> prev_copy(previous), current_copy(current);
00711 std::vector< estirabot_msgs::DirtyArea > current_with_ids, current_ordered;
00712 int max_id = -1;
00713
00714
00715
00716
00717
00718
00719 while ((prev_copy.size() > 0) && (current_copy.size() > 0)) {
00720 double min_distance = 10000;
00721 std::vector<estirabot_msgs::DirtyArea>::iterator it_previous, it_current, it_previous_max, it_current_max;
00722 for ( it_previous=prev_copy.begin() ; it_previous < prev_copy.end(); it_previous++ ) {
00723 for ( it_current=current_copy.begin() ; it_current < current_copy.end(); it_current++ ) {
00724
00725 int x_inc = it_previous->ellipse.center.x - it_current->ellipse.center.x;
00726 int y_inc = it_previous->ellipse.center.y - it_current->ellipse.center.y;
00727 double distance = sqrt( (x_inc*x_inc) + (y_inc*y_inc) );
00728 ROS_DEBUG_STREAM("New distance is " << distance << "\nx " << x_inc << "\ny " << y_inc);
00729 if (distance < min_distance) {
00730 min_distance = distance;
00731 it_previous_max = it_previous;
00732 it_current_max = it_current;
00733 }
00734 }
00735 }
00736
00737 if (it_previous_max->id > max_id) {
00738 max_id = it_previous_max->id;
00739 }
00740 it_current_max->id = it_previous_max->id;
00741
00742
00743 current_with_ids.push_back(estirabot_msgs::DirtyArea(*it_current_max));
00744 prev_copy.erase(it_previous_max);
00745 current_copy.erase(it_current_max);
00746 }
00747
00748
00749
00750
00751 if (current_copy.size() > 0) {
00752 for (std::vector<estirabot_msgs::DirtyArea>::iterator it=current_copy.begin() ; it < current_copy.end(); it++ ) {
00753 max_id++;
00754 it->id = max_id;
00755 current_with_ids.push_back(estirabot_msgs::DirtyArea(*it));
00756 }
00757 }
00758
00759
00760
00761
00762 while (current_with_ids.size() > 0) {
00763 int min_id = 1000;
00764 std::vector<estirabot_msgs::DirtyArea>::iterator min_it;
00765 for (std::vector<estirabot_msgs::DirtyArea>::iterator it=current_with_ids.begin() ; it < current_with_ids.end(); it++ ) {
00766 if (it->id < min_id) {
00767 min_id = it->id;
00768 min_it = it;
00769 }
00770 }
00771 current_ordered.push_back(estirabot_msgs::DirtyArea(*min_it));
00772 current_with_ids.erase(min_it);
00773 }
00774
00775
00776
00777 return current_ordered;
00778 }
00779