00001 #include "cleaning_plan_alg.h"
00002
00003 using namespace cv;
00004 using namespace std;
00005
00006
00007 CleaningPlanAlgorithm::CleaningPlanAlgorithm(void)
00008 {
00009
00010 away_from_surface_distance = -0.1;
00011 }
00012
00013 CleaningPlanAlgorithm::~CleaningPlanAlgorithm(void)
00014 {
00015 }
00016
00017 void CleaningPlanAlgorithm::config_update(Config& new_cfg, uint32_t level)
00018 {
00019 this->lock();
00020
00021 this->movements_offset = new_cfg.movements_offset;
00022 this->small_objects_min = new_cfg.small_objects_min;
00023 this->small_objects_max = new_cfg.small_objects_max;
00024 this->pose_yaw = new_cfg.pose_yaw;
00025 this->two_arms_version = new_cfg.two_arms_version;
00026 this->board_plan = new_cfg.board_plan;
00027 this->camera_frame = new_cfg.camera_frame;
00028 this->rotate_hand = new_cfg.rotate_hand;
00029
00030
00031 this->config_=new_cfg;
00032
00033 this->unlock();
00034 }
00035
00036
00037 bool CleaningPlanAlgorithm::getMovementFromAction(std::vector< estirabot_msgs::DirtyArea > dirty_areas,
00038 string action, estirabot_msgs::ArrayIndexes target_ellipses,
00039 EllipsesRepresentation& ellipses_rep,
00040 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
00041 std::vector<float> plane_coeffs,
00042 std::vector<geometry_msgs::PoseStamped> &poses,
00043 std::vector<iri_perception_msgs::ImagePoint> &poses_img_coords,
00044 std::vector<uint8_t> &secondary_arm)
00045 {
00046 std::vector< Point2f > img_coords;
00047 bool is_real_movement = true;
00048 uint8_t secondary_arm_movements = 0;
00049 double orientation_yaw = this->pose_yaw;
00050
00051 for (size_t i = 0; i < dirty_areas.size(); i++) {
00052 dirty_areas[i].ellipse.center.y -= 8;
00053 }
00054 RotatedRect ellipse1 = ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[0]);
00055
00056
00057 if (action.compare("circularClean") == 0) {
00058 img_coords = getPointsCircularClean(ellipse1);
00059 }
00060 else if (action.compare("straightClean") == 0) {
00061 img_coords = getPointsStraightClean(ellipse1);
00062 }
00063 else if (action.compare("smallClean") == 0) {
00064 if (dirty_areas.size() <= 2)
00065 img_coords = getPointsLastSmallClean(ellipse1);
00066 else
00067 img_coords = getPointsSmallClean(ellipse1);
00068
00069 }
00070 else if (action.compare("move") == 0) {
00071 is_real_movement = false;
00072 }
00073
00074
00075 else if (action.compare("group") == 0) {
00076 img_coords = getPointsGroupObjects(ellipse1);
00077 }
00078 else if ( (action.compare("join") == 0) || (action.compare("joinTrav") == 0) ) {
00079
00080
00081
00082 vector<RotatedRect> ellipses;
00083 ellipses.push_back(ellipse1);
00084 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[1]));
00085 img_coords = getPointsJoinGroups(ellipses);
00086 }
00087 else if (action.compare("join3") == 0) {
00088
00089
00090
00091 vector<RotatedRect> ellipses;
00092 ellipses.push_back(ellipse1);
00093 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[1]));
00094 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[2]));
00095 img_coords = getPointsJoinGroups(ellipses);
00096 }
00097 else if (action.compare("join4") == 0) {
00098
00099
00100
00101 vector<RotatedRect> ellipses;
00102 ellipses.push_back(ellipse1);
00103 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[1]));
00104 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[2]));
00105 ellipses.push_back(ellipses_rep.getEllipseFromRosDirtyAreas(dirty_areas, target_ellipses.indexes[3]));
00106 img_coords = getPointsJoinGroups(ellipses);
00107 }
00108 else if (action.compare("pickUp") == 0) {
00109 if (this->two_arms_version) {
00110 img_coords = getPointsPickUp(ellipse1);
00111 secondary_arm_movements = 2;
00112
00113
00114 }
00115 else {
00116
00117
00118 img_coords = getPointsMoveToContainer(ellipse1);
00119 }
00120 }
00121 else if (action.compare("moveToContainerLong") == 0) {
00122 img_coords = getPointsMoveToContainer(ellipse1, 1);
00123 }
00124 else if (action.compare("moveToContainerShort") == 0) {
00125 img_coords = getPointsMoveToContainer(ellipse1, 1);
00126 }
00127 else if ( (action.compare("moveToContainerStraight") == 0) || (action.compare("moveToContainerStraightTrav") == 0)){
00128 img_coords = getPointsMoveToContainer(ellipse1, 3);
00129 }
00130 else if (action.compare("preparePickUp") == 0) {
00131
00132 is_real_movement = false;
00133 }
00134 else if (action.compare("None") == 0) {
00135
00136 is_real_movement = false;
00137 }
00138 else if (action.compare("NoPerception") == 0) {
00139 img_coords = getNoPerceptionPoints(ellipses_rep.state_image);
00140 processedPosesFromImageCoordinates(ellipses_rep, cloud, img_coords, plane_coeffs, secondary_arm_movements, orientation_yaw, poses, poses_img_coords, secondary_arm);
00141 for (size_t i = 4; i < poses.size(); i=i+4) {
00142 this->movePoseAwayFromSurface(poses[i], plane_coeffs);
00143 this->movePoseAwayFromSurface(poses[i-1], plane_coeffs);
00144 }
00145 return true;
00146 }
00147 else {
00148 ROS_ERROR_STREAM("CleaningPlanAlgorithm::getImageCoordsFromAction - ACTION NOT FOUND: " << action);
00149 }
00150
00151 if (is_real_movement) {
00152 processedPosesFromImageCoordinates(ellipses_rep, cloud, img_coords, plane_coeffs, secondary_arm_movements, orientation_yaw, poses, poses_img_coords, secondary_arm);
00153 }
00154
00155 return is_real_movement;
00156 }
00157
00158
00159 void CleaningPlanAlgorithm::processedPosesFromImageCoordinates(EllipsesRepresentation& ellipses_rep,
00160 const pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
00161 const std::vector< Point2f > img_coords,
00162 const std::vector<float> plane_coeffs,
00163 const uint8_t secondary_arm_movements,
00164 const double orientation_yaw,
00165 std::vector<geometry_msgs::PoseStamped> &poses,
00166 std::vector<iri_perception_msgs::ImagePoint> &poses_img_coords,
00167 std::vector<uint8_t> &secondary_arm
00168 )
00169 {
00170 this->posesFromImageCoordinates(cloud, img_coords,
00171 plane_coeffs, orientation_yaw,
00172 poses, poses_img_coords,
00173 secondary_arm_movements, secondary_arm);
00174
00175 if (not this->board_plan) {
00176 ROS_DEBUG("CleaningPlan - moving away movements");
00177
00178
00179 this->movePoseAwayFromSurface(poses[poses.size() - img_coords.size() + secondary_arm_movements], plane_coeffs);
00180
00181
00182 this->movePoseAwayFromSurface(poses[poses.size() - 1], plane_coeffs);
00183
00184 if (secondary_arm_movements > 0) {
00185 this->movePoseAwayFromSurface(poses[poses.size() - img_coords.size()], plane_coeffs);
00186
00187 }
00188 }
00189
00190 ellipses_rep.drawPoints(img_coords);
00191 }
00192
00193
00194 std::vector< Point2f > CleaningPlanAlgorithm::getNoPerceptionPoints(cv::Mat image)
00195 {
00196
00197 std::vector< Point2f > img_coords;
00198 int step = 20;
00199 int left_margin = 25;
00200 int right_edge = 50;
00201
00202
00203 cv::Rect bounding_box;
00204 std::vector<std::vector<Point> > contours;
00205 std::vector<Point> contours_points;
00206 std::vector<cv::Vec4i> hierarchy;
00207
00208
00209
00210 findContours( image, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
00211 for (size_t i = 0; i < contours.size(); i++)
00212 for (size_t j = 0; j < contours[i].size(); j++)
00213 contours_points.push_back(contours[i][j]);
00214 bounding_box = boundingRect(contours_points);
00215
00216
00217 int y_offset=-10;
00218
00219 Point2f start_point = Point2f(bounding_box.x - left_margin, bounding_box.y + y_offset);
00220 Point2f end_point;
00221 while (y_offset < (bounding_box.height + step)) {
00222 img_coords.push_back(start_point);
00223
00224
00225 start_point = Point2f(bounding_box.x - left_margin, bounding_box.y + y_offset);
00226
00227
00228 Point2f end_point = Point2f(image.size().width - right_edge, bounding_box.y + y_offset);
00229
00230 img_coords.push_back(start_point);
00231 img_coords.push_back(end_point);
00232 img_coords.push_back(end_point);
00233
00234 y_offset+=step;
00235 }
00236
00237 return img_coords;
00238 }
00239
00240
00241 std::vector< Point2f > CleaningPlanAlgorithm::getPointsSmallClean(RotatedRect ellipse)
00242 {
00243 ROS_DEBUG("CleaningPlan - Generating points for small move");
00244 std::vector< Point2f > result;
00245
00246 ROS_DEBUG_STREAM("Center is " << ellipse.center);
00247
00248 result.push_back(ellipse.center);
00249
00250 return result;
00251 }
00252
00253
00254 std::vector< Point2f > CleaningPlanAlgorithm::getPointsLastSmallClean(RotatedRect ellipse)
00255 {
00256 ROS_DEBUG("CleaningPlan - Generating points for one of the last small moves");
00257 std::vector< Point2f > result;
00258 Point2f point;
00259
00260 ROS_DEBUG_STREAM("Center is " << ellipse.center);
00261
00262 point = ellipse.center;
00263 point.y = point.y + 15;
00264
00265 result.push_back(point);
00266
00267 point = ellipse.center;
00268 point.y = point.y - 15;
00269
00270 result.push_back(point);
00271
00272 return result;
00273 }
00274
00275
00276 std::vector< Point2f > CleaningPlanAlgorithm::getPointsCircularClean(RotatedRect ellipse)
00277 {
00278 ROS_DEBUG("CleaningPlan - Generating points for circular move");
00279
00280 std::vector< Point2f > result;
00281 Point2f firstPoint, secondPoint, thirdPoint, fourthPoint;
00282 float angle = ellipse.angle;
00283 if (angle > 180)
00284 angle -=180;
00285
00286 angle = (angle / 180) * M_PI;
00287 float x_inc1, y_inc1, x_inc2, y_inc2;
00288
00289
00290
00291 x_inc1 = sin(angle) * ellipse.size.height / 2;
00292 y_inc1 = -cos(angle) * ellipse.size.height / 2;
00293 x_inc2 = cos(angle) * ellipse.size.width / 2;
00294 y_inc2 = sin(angle) * ellipse.size.width / 2;
00295
00296 firstPoint.x = ellipse.center.x + x_inc1;
00297 firstPoint.y = ellipse.center.y + y_inc1;
00298
00299 secondPoint.x = ellipse.center.x - x_inc1;
00300 secondPoint.y = ellipse.center.y - y_inc1;
00301
00302 thirdPoint.x = ellipse.center.x + x_inc2;
00303 thirdPoint.y = ellipse.center.y + y_inc2;
00304
00305 fourthPoint.x = ellipse.center.x - x_inc2;
00306 fourthPoint.y = ellipse.center.y - y_inc2;
00307
00308 ROS_DEBUG_STREAM("Center is " << ellipse.center);
00309 ROS_DEBUG_STREAM("Angle is " << angle);
00310 ROS_DEBUG_STREAM("Width is " << ellipse.size.width);
00311 ROS_DEBUG_STREAM("Height is " << ellipse.size.height);
00312 ROS_DEBUG_STREAM("First point " << firstPoint);
00313 ROS_DEBUG_STREAM("Second point " << secondPoint);
00314 ROS_DEBUG_STREAM("Third point " << thirdPoint);
00315 ROS_DEBUG_STREAM("Fourth point " << fourthPoint);
00316
00317
00318 if (ellipse.size.width * ellipse.size.height > 5000) {
00319 Point2f point5, point6, point7, point8;
00320
00321
00322 angle -= M_PI/4;
00323
00324
00325
00326 x_inc1 = sin(angle) * (ellipse.size.height + ellipse.size.width) / 4;
00327 y_inc1 = -cos(angle) * (ellipse.size.height + ellipse.size.width) / 4;
00328 x_inc2 = cos(angle) * (ellipse.size.height + ellipse.size.width) / 4;
00329 y_inc2 = sin(angle) * (ellipse.size.height + ellipse.size.width) / 4;
00330
00331 point5.x = ellipse.center.x + x_inc1;
00332 point5.y = ellipse.center.y + y_inc1;
00333
00334 point6.x = ellipse.center.x - x_inc1;
00335 point6.y = ellipse.center.y - y_inc1;
00336
00337 point7.x = ellipse.center.x + x_inc2;
00338 point7.y = ellipse.center.y + y_inc2;
00339
00340 point8.x = ellipse.center.x - x_inc2;
00341 point8.y = ellipse.center.y - y_inc2;
00342
00343 result.push_back(firstPoint);
00344 result.push_back(point7);
00345 result.push_back(thirdPoint);
00346 result.push_back(point6);
00347 result.push_back(secondPoint);
00348 result.push_back(point8);
00349 result.push_back(fourthPoint);
00350 result.push_back(point5);
00351 }
00352 else {
00353 result.push_back(firstPoint);
00354 result.push_back(thirdPoint);
00355 result.push_back(secondPoint);
00356 result.push_back(fourthPoint);
00357 }
00358
00359
00360
00361
00362
00363
00364 return result;
00365 }
00366
00367
00368 std::vector< Point2f > CleaningPlanAlgorithm::getPointsStraightClean(RotatedRect ellipse)
00369 {
00370 ROS_DEBUG("CleaningPlan - Generating points for straight move");
00371 std::vector< Point2f > result;
00372 Point2f firstPoint, secondPoint;
00373 float angle = (ellipse.angle / 180) * M_PI;
00374 float x_inc, y_inc;
00375
00376
00377
00378 x_inc = sin(angle) * (ellipse.size.height / 2 + this->movements_offset);
00379 y_inc = -cos(angle) * (ellipse.size.height / 2 + this->movements_offset);
00380
00381 firstPoint.x = ellipse.center.x + x_inc;
00382 firstPoint.y = ellipse.center.y + y_inc;
00383 secondPoint.x = ellipse.center.x - x_inc;
00384 secondPoint.y = ellipse.center.y - y_inc;
00385
00386 ROS_DEBUG_STREAM("Center is " << ellipse.center);
00387 ROS_DEBUG_STREAM("Angle is " << angle);
00388 ROS_DEBUG_STREAM("Width is " << ellipse.size.width);
00389 ROS_DEBUG_STREAM("Height is " << ellipse.size.height);
00390 ROS_DEBUG_STREAM("First point " << firstPoint.x << "," << firstPoint.y);
00391 ROS_DEBUG_STREAM("Second point " << secondPoint.x << "," << secondPoint.y);
00392
00393 result.push_back(firstPoint);
00394 result.push_back(secondPoint);
00395
00396
00397
00398
00399
00400
00401 return result;
00402 }
00403
00409 std::vector< Point2f > CleaningPlanAlgorithm::getPointsGroupObjects(RotatedRect ellipse)
00410 {
00411 ROS_DEBUG("CleaningPlan - Generating points for group move");
00412
00413 std::vector< Point2f > result;
00414 Point2f firstPoint, secondPoint;
00415 float angle = ellipse.angle;
00416 float x_inc, y_inc;
00417
00418 if (angle > 180)
00419 angle -=180;
00420 angle = (angle / 180) * M_PI;
00421
00422
00423
00424
00425 if ((ellipse.center.y < (IMAGE_HEIGHT*small_objects_min)) && (angle > 3*M_PI/4))
00426 angle = angle + M_PI;
00427
00428
00429 if ((ellipse.center.y > (IMAGE_HEIGHT*small_objects_max)) && (angle < M_PI/4))
00430 angle = angle + M_PI;
00431
00432
00433
00434 x_inc = sin(angle) * ellipse.size.height / 2;
00435 y_inc = -cos(angle) * ellipse.size.height / 2;
00436
00437 firstPoint.x = ellipse.center.x + x_inc;
00438 firstPoint.y = ellipse.center.y + y_inc;
00439 secondPoint.x = ellipse.center.x - x_inc;
00440 secondPoint.y = ellipse.center.y - y_inc;
00441
00442
00443 firstPoint.x = firstPoint.x + ( this->movements_offset * sin(angle) );
00444 secondPoint.x = secondPoint.x + ( this->movements_offset * sin(angle) );
00445 firstPoint.y = firstPoint.y + ( this->movements_offset * -cos(angle) );
00446 secondPoint.y = secondPoint.y + ( this->movements_offset * -cos(angle) );
00447
00448 ROS_DEBUG_STREAM("Center is " << ellipse.center);
00449 ROS_DEBUG_STREAM("Angle is " << angle);
00450 ROS_DEBUG_STREAM("Width is " << ellipse.size.width);
00451 ROS_DEBUG_STREAM("Height is " << ellipse.size.height);
00452 ROS_DEBUG_STREAM("First point " << firstPoint.x << "," << firstPoint.y);
00453 ROS_DEBUG_STREAM("Second point " << secondPoint.x << "," << secondPoint.y);
00454
00455 result.push_back(firstPoint);
00456 result.push_back(firstPoint);
00457 result.push_back(secondPoint);
00458
00459
00460 if (this->two_arms_version) {
00461
00462
00463 result.push_back(secondPoint);
00464 }
00465 else {
00466
00467 Point2f thirdPoint;
00468 thirdPoint = secondPoint;
00469 thirdPoint.x = thirdPoint.x - this->movements_offset;
00470 result.push_back(thirdPoint);
00471 result.push_back(thirdPoint);
00472 }
00473
00474
00475
00476
00477 return result;
00478 }
00479
00480
00481 std::vector< Point2f > CleaningPlanAlgorithm::getPointsJoinGroups(vector<RotatedRect> ellipses)
00482 {
00483 std::vector< Point2f > result;
00484 std::vector< Point2f > firstEllipsePoints, secondEllipsePoints;
00485 Point2f firstPoint, secondPoint, awayDirection;
00486 size_t first_ellipse_nearest, last_ellipse_nearest, first_ellipse_farthest;
00487
00488
00489
00490 ROS_DEBUG("CleaningPlan - Generating points for join move");
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517 for (size_t i = 0; i < (ellipses.size() - 1); i++){
00518 firstEllipsePoints = getPointsCircularClean(ellipses.at(i));
00519 secondEllipsePoints = getPointsCircularClean(ellipses.at(i+1));
00520
00521 first_ellipse_nearest = getNearestPoint(firstEllipsePoints, secondEllipsePoints);
00522 last_ellipse_nearest = getNearestPoint(secondEllipsePoints, firstEllipsePoints);
00523
00524 if (firstEllipsePoints.size() == 8)
00525 first_ellipse_farthest = (first_ellipse_nearest + 4) % 8;
00526 else
00527 first_ellipse_farthest = (first_ellipse_nearest + 2) % 4;
00528
00529 firstPoint = firstEllipsePoints[first_ellipse_farthest];
00530 secondPoint = firstEllipsePoints[first_ellipse_nearest];
00531
00532 ROS_DEBUG_STREAM("Nearest " << first_ellipse_nearest);
00533 ROS_DEBUG_STREAM("Farthest " << first_ellipse_farthest);
00534
00535 awayDirection.x = firstPoint.x - secondPoint.x;
00536 awayDirection.y = firstPoint.y - secondPoint.y;
00537 ROS_DEBUG_STREAM("Away direction is " << awayDirection);
00538 awayDirection.x = awayDirection.x / sqrt(awayDirection.x*awayDirection.x + awayDirection.y*awayDirection.y);
00539 awayDirection.y = awayDirection.y / sqrt(awayDirection.x*awayDirection.x + awayDirection.y*awayDirection.y);
00540 ROS_DEBUG_STREAM("Away direction is " << awayDirection);
00541
00542 if (i == 0) {
00543 firstPoint.x = firstPoint.x + awayDirection.x * this->movements_offset;
00544 firstPoint.y = firstPoint.y + awayDirection.y * this->movements_offset;
00545
00546 result.push_back(firstPoint);
00547 result.push_back(firstPoint);
00548 }
00549
00550 result.push_back(secondPoint);
00551 result.push_back(secondEllipsePoints[last_ellipse_nearest]);
00552
00553 }
00554
00555
00556
00557 result.push_back(result.back());
00558
00559 return result;
00560 }
00561
00562
00563 std::vector< Point2f > CleaningPlanAlgorithm::getPointsPickUp(RotatedRect ellipse)
00564 {
00565 ROS_DEBUG("CleaningPlan - Generating points for pick up");
00566 std::vector< Point2f > result;
00567 Point2f firstPoint, secondPoint;
00568 float angle = ellipse.angle;
00569 float x_inc1, x_inc2, x_biggest;
00570
00571 if (angle > 180)
00572 angle -=180;
00573 angle = (angle / 180) * M_PI;
00574
00575
00576
00577 x_inc1 = abs(sin(angle) * ellipse.size.height / 2);
00578 x_inc2 = abs(cos(angle) * ellipse.size.width / 2);
00579 x_biggest = max(x_inc1, x_inc2);
00580
00581
00582
00583
00584 firstPoint.x = ellipse.center.x + x_biggest + this->movements_offset;
00585 firstPoint.y = ellipse.center.y;
00586
00587 result.push_back(firstPoint);
00588 result.push_back(firstPoint);
00589
00590
00591
00592
00593 firstPoint.x = ellipse.center.x - x_biggest - this->movements_offset;
00594 firstPoint.y = ellipse.center.y;
00595 secondPoint.x = ellipse.center.x + x_biggest;
00596 secondPoint.y = ellipse.center.y;
00597
00598 result.push_back(firstPoint);
00599 result.push_back(firstPoint);
00600 result.push_back(secondPoint);
00601 result.push_back(secondPoint);
00602
00603 ROS_DEBUG("CleaningPlan - Pick up generated");
00604
00605 return result;
00606 }
00607
00608
00609 std::vector< Point2f > CleaningPlanAlgorithm::getPointsMoveToContainer(RotatedRect& ellipse, int max_steps)
00610 {
00611 ROS_DEBUG("CleaningPlan - Generating points for move right");
00612 std::vector< Point2f > result;
00613 Point2f firstPoint, secondPoint;
00614 float angle = ellipse.angle;
00615 float x_inc1, x_inc2, x_biggest;
00616 float y_inc1, y_inc2, y_biggest;
00617 if (angle > 180)
00618 angle -=180;
00619 angle = (angle / 180) * M_PI;
00620
00621
00622
00623 x_inc1 = abs(sin(angle) * ellipse.size.height / 2);
00624 x_inc2 = abs(cos(angle) * ellipse.size.width / 2);
00625 x_biggest = max(x_inc1, x_inc2);
00626
00627 y_inc1 = abs(cos(angle) * ellipse.size.height / 2);
00628 y_inc2 = abs(sin(angle) * ellipse.size.width / 2);
00629 y_biggest = max(y_inc1, y_inc2);
00630
00631
00632 if (ellipse.center.y < (IMAGE_HEIGHT*small_objects_min) ) {
00633 firstPoint.x = ellipse.center.x;
00634 firstPoint.y = ellipse.center.y - (y_biggest + this->movements_offset);
00635 secondPoint.x = ellipse.center.x;
00636 secondPoint.y = ellipse.center.y + (y_biggest + this->movements_offset);
00637
00638 result.push_back(firstPoint);
00639 result.push_back(firstPoint);
00640 result.push_back(secondPoint);
00641 result.push_back(secondPoint);
00642 }
00643
00644
00645 else if (ellipse.center.y > (IMAGE_HEIGHT*small_objects_max) ) {
00646 firstPoint.x = ellipse.center.x;
00647 firstPoint.y = ellipse.center.y + (y_biggest + this->movements_offset);
00648 secondPoint.x = ellipse.center.x;
00649 secondPoint.y = ellipse.center.y - (y_biggest + this->movements_offset);
00650
00651 result.push_back(firstPoint);
00652 result.push_back(firstPoint);
00653 result.push_back(secondPoint);
00654 result.push_back(secondPoint);
00655 }
00656
00657 else {
00658 int steps, step_size, max_x, current_x, max_steps_by_distance;
00659 firstPoint.y = ellipse.center.y;
00660 firstPoint.x = ellipse.center.x - (x_biggest + this->movements_offset);
00661
00662 max_x = IMAGE_WIDTH - 40;
00663 current_x = firstPoint.x;
00664 max_steps_by_distance = std::floor((max_x - current_x) / this->movements_offset);
00665 steps = std::min(max_steps, max_steps_by_distance);
00666 step_size = std::floor((max_x - current_x) / steps);
00667
00668
00669
00670
00671
00672
00673
00674 result.push_back(firstPoint);
00675 result.push_back(firstPoint);
00676
00677 for (int i = 1; i <= steps; i++) {
00678 current_x += step_size;
00679 secondPoint.x = current_x;
00680 secondPoint.y = ellipse.center.y;
00681
00682 result.push_back(secondPoint);
00683 }
00684 result.push_back(secondPoint);
00685
00686
00687
00688
00689
00690
00691
00692
00693 }
00694
00695
00696 ellipse.center.x = secondPoint.x;
00697 ellipse.center.y = secondPoint.y;
00698
00699 ROS_DEBUG("CleaningPlan - Move right generated");
00700
00701 return result;
00702 }
00703
00704
00705 int32_t CleaningPlanAlgorithm::getNearestPoint(std::vector< Point2f > points1, std::vector< Point2f > points2)
00706 {
00707 double min = 10000;
00708 int32_t min_idx = -1;
00709
00710 for (size_t i=0; i < points1.size(); i++) {
00711 for (size_t j=0; j < points2.size(); j++) {
00712 double dist = getDistance(points1[i], points2[j]);
00713 if (dist < min) {
00714 min = dist;
00715 min_idx = i;
00716 }
00717 }
00718 }
00719
00720 ROS_DEBUG_STREAM("Minimun distance is: " << min);
00721
00722 return min_idx;
00723 }
00724
00725
00726 void CleaningPlanAlgorithm::posesFromImageCoordinates(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
00727 std::vector< cv::Point2f > img_coords,
00728 std::vector<float> plane_coeffs,
00729 double orientation_yaw,
00730 std::vector<geometry_msgs::PoseStamped> &poses,
00731 std::vector<iri_perception_msgs::ImagePoint> &poses_coords,
00732 uint8_t secondary_arm_movements,
00733 std::vector<uint8_t> &secondary_arm)
00734 {
00735 geometry_msgs::PoseStamped a_pose;
00736 iri_perception_msgs::ImagePoint a_pose_coords;
00737 pcl::PointXYZ point;
00738 geometry_msgs::Quaternion orientation;
00739
00740 double prev_yaw_increment = orientation_yaw, yaw_increment = orientation_yaw, diff_yaw;
00741
00742 ROS_DEBUG("CleaningPlan - Transforming coords to poses");
00743
00744 for (size_t i = 0; i < img_coords.size(); i++) {
00745 if (img_coords[i].x < 0)
00746 img_coords[i].x = 0;
00747 if (img_coords[i].y < 0)
00748 img_coords[i].y = 0;
00749 if (img_coords[i].x > cloud->width)
00750 img_coords[i].x = cloud->width - 1;
00751 if (img_coords[i].y > cloud->height)
00752 img_coords[i].y = cloud->height - 1;
00753
00754
00755 a_pose.header.stamp = ros::Time::now();
00756 a_pose.header.frame_id = this->camera_frame;
00757
00758 point = cloud->at(img_coords[i].x,img_coords[i].y);
00759
00760
00761 if ((not this->board_plan) && (not this->two_arms_version)) {
00762
00763
00764
00765
00766 while (((point.x != point.x) || (pointToPlaneDistance(point, plane_coeffs) > 0.02 )) && (img_coords[i].x > (IMAGE_WIDTH/2)) ) {
00767 img_coords[i].x -= 1;
00768 ROS_DEBUG("NaN point! Trying to fix...");
00769 ROS_DEBUG_STREAM("Coords are now " << img_coords[i].x);
00770 ROS_DEBUG_STREAM("Point to plane distance is " << pointToPlaneDistance(point, plane_coeffs));
00771 point = cloud->at(img_coords[i].x,img_coords[i].y);
00772 }
00773 }
00774
00775
00776 if (point.x != point.x) {
00777 point.x = 0;
00778 point.y = 0;
00779 point.z = 0;
00780 }
00781
00782
00783
00784
00785 yaw_increment = prev_yaw_increment;
00786
00787 if (not this->board_plan && this->rotate_hand) {
00788 if ( ((i+1) < img_coords.size()) && (img_coords[i].x != img_coords[i+1].x) ) {
00789 yaw_increment = orientation_yaw;
00790 yaw_increment += getAngle2DwithAxisX(img_coords[i], img_coords[i+1]);
00791 }
00792 }
00793
00794
00795
00796
00797
00798
00799 diff_yaw = yaw_increment - prev_yaw_increment;
00800 if (diff_yaw > M_PI/2)
00801 yaw_increment -= M_PI;
00802 else if (diff_yaw < - M_PI/2)
00803 yaw_increment += M_PI;
00804
00805 if (yaw_increment > 2*M_PI)
00806 yaw_increment -= 2*M_PI;
00807 if (yaw_increment < 0)
00808 yaw_increment += 2*M_PI;
00809
00810 prev_yaw_increment = yaw_increment;
00811 ROS_DEBUG_STREAM("Yaw movement orientation increments " << yaw_increment);
00812
00813 orientation = quaternionFrom3dVector(plane_coeffs, yaw_increment);
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 if (i < secondary_arm_movements)
00824 secondary_arm.push_back(true);
00825 else
00826 secondary_arm.push_back(false);
00827
00828 a_pose.pose.position.x = point.x;
00829 a_pose.pose.position.y = point.y;
00830 a_pose.pose.position.z = point.z;
00831 a_pose.pose.orientation = orientation;
00832 a_pose_coords.x = img_coords[i].x;
00833 a_pose_coords.y = img_coords[i].y;
00834
00835 poses.push_back(a_pose);
00836 poses_coords.push_back(a_pose_coords);
00837 }
00838
00839 ROS_DEBUG("CleaningPlan - Poses generated");
00840 }
00841
00842
00843 void CleaningPlanAlgorithm::movePoseAwayFromSurface(geometry_msgs::PoseStamped &pose, std::vector<float> plane_coeffs)
00844 {
00845 pose.pose.position.x += (this->away_from_surface_distance * plane_coeffs[0]);
00846 pose.pose.position.y += (this->away_from_surface_distance * plane_coeffs[1]);
00847 pose.pose.position.z += (this->away_from_surface_distance * plane_coeffs[2]);
00848 }
00849
00850
00851 geometry_msgs::Quaternion CleaningPlanAlgorithm::quaternionFrom3dVector(std::vector<float> plane_coefs, double new_yaw)
00852 {
00853 using namespace Eigen;
00854 geometry_msgs::Quaternion q_msg;
00855
00856 Vector2f vbase(1,0);
00857 Vector2f vbase2(0,1);
00858 Vector2f vroll(plane_coefs[1], plane_coefs[2]);
00859 Vector2f vpitch(plane_coefs[2], plane_coefs[0]);
00860 Vector2f vyaw(plane_coefs[0], plane_coefs[1]);
00861
00862 double roll = getAngle2D(vroll,vbase2);
00863 double pitch = getAngle2D(vpitch,vbase);
00864 double yaw = 0;
00865
00866
00867
00868
00869 if (plane_coefs[2] * plane_coefs[0] < 0)
00870 pitch = - pitch;
00871
00872 if (plane_coefs[2] * plane_coefs[1] > 0)
00873 roll = - roll;
00874
00875 q_msg = tf::createQuaternionMsgFromRollPitchYaw(roll, pitch, yaw);
00876
00877 Quaternion<float> qe1(q_msg.w, q_msg.x, q_msg.y, q_msg.z);
00878 Quaternion<float> q_rot(AngleAxis<float>(M_PI + new_yaw, Vector3f(0,0,1)));
00879 Quaternion<float> q_dest;
00880 q_dest = qe1 * q_rot;
00881 q_msg.x = q_dest.x();
00882 q_msg.y = q_dest.y();
00883 q_msg.z = q_dest.z();
00884 q_msg.w = q_dest.w();
00885
00886 return q_msg;
00887 }