00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define BOOST_THREAD
00047
00048 #include "ClusterDetector.h"
00049 #include "SegmentPrototype.h"
00050 #include "XMLTag.h"
00051 #include "SwissRangerReading.h"
00052 #include "BoostUtils.h"
00053
00054
00055
00056 #include <point_cloud_mapping/sample_consensus/sac.h>
00057 #include <point_cloud_mapping/sample_consensus/msac.h>
00058 #include <point_cloud_mapping/sample_consensus/ransac.h>
00059 #include <point_cloud_mapping/sample_consensus/sac_model_plane.h>
00060
00061 #include <angles/angles.h>
00062
00063
00064 #include <point_cloud_mapping/kdtree/kdtree_ann.h>
00065
00066
00067 #include <point_cloud_mapping/geometry/angles.h>
00068 #include <point_cloud_mapping/geometry/areas.h>
00069 #include <point_cloud_mapping/geometry/point.h>
00070 #include <point_cloud_mapping/geometry/distances.h>
00071 #include <point_cloud_mapping/geometry/nearest.h>
00072 #include <point_cloud_mapping/geometry/transforms.h>
00073 #include <point_cloud_mapping/geometry/statistics.h>
00074
00075 #include <sys/time.h>
00076
00077
00078
00079
00080
00081 #define SR_COLS 176
00082 #define SR_ROWS 144
00083 #define DEBUG 1
00084
00085 #define XML_ATTRIBUTE_SR4LO "sr_loid"
00086 #define XML_ATTRIBUTE_PTULO "ptu_loid"
00087
00088 using namespace cop;
00089
00090 using namespace std;
00091 using namespace ros;
00092
00093 using namespace sensor_msgs;
00094 using namespace geometry_msgs;
00095
00096
00097 bool
00098 compareRegions (const std::vector<int> &a, const std::vector<int> &b)
00099 {
00100 return (a.size () < b.size ());
00101 }
00102
00103 class PlaneClusterResult
00104 {
00105 public:
00106 class ObjectOnTable
00107 {
00108
00109 public:
00110 std::vector<double> cov33;
00111 geometry_msgs::Point32 center;
00112
00113 };
00114
00115 public:
00116 double a;
00117 double b;
00118 double c;
00119 double d;
00120 geometry_msgs::Point32 pcenter;
00121 std::vector<ObjectOnTable> oclusters;
00122 };
00123
00124
00125 class PlaneClustersSR
00126 {
00127 public:
00128
00129
00130 PointCloud cloud_in_trans_;
00131
00132 PointCloud cloud_down_;
00133 Point leaf_width_;
00134 PointCloud cloud_annotated_;
00135 Point32 axis_;
00136
00137
00138 string input_cloud_topic_;
00139 int k_;
00140 double max_z_;
00141 int clusters_min_pts_;
00142
00143 int object_cluster_min_pts_;
00144 double object_cluster_tolerance_;
00145
00146 bool need_cloud_data_;
00147
00148 double sac_distance_threshold_, eps_angle_;
00149
00150 double delta_z_, object_min_dist_from_table_;
00151
00152 double min_angle_, max_angle_;
00153
00154
00155 int downsample_factor_;
00156
00157 boost::mutex m_mutexUsage;
00159 PlaneClustersSR (XMLTag* tag)
00160 {
00161
00162 axis_.x = 0; axis_.y = 0; axis_.z = 1;
00163
00164 downsample_factor_ = 4;
00165 k_ = 2;
00166 max_z_ = 0.03;
00167
00168 eps_angle_ = 15.0;
00169 eps_angle_ = angles::from_degrees (eps_angle_);
00170
00171 clusters_min_pts_ = 10;
00172
00173 object_cluster_tolerance_ = 0.07;
00174 object_cluster_min_pts_ = 30;
00175
00176 delta_z_ = 0.03;
00177 object_min_dist_from_table_ = 0.1;
00178
00179 min_angle_ = 10.0;
00180 max_angle_ = 170.0;
00181
00182 sac_distance_threshold_ = 0.03;
00183 }
00184
00186 void
00187 updateParametersFromServer ()
00188 {
00189
00190
00191 }
00192
00194
00199 inline double
00200 getRGB (float r, float g, float b)
00201 {
00202 int res = (int(r * 255) << 16) | (int(g*255) << 8) | int(b*255);
00203 double rgb = *(float*)(&res);
00204 return (rgb);
00205 }
00206
00207
00208 void cloud_trans (unsigned long swissranger_jlo_id, unsigned long ptu_base_jlo_id, Point32& viewpoint_cloud, const PointCloud& cloud_in)
00209 {
00210 RelPose* pose = RelPoseFactory::GetRelPose(swissranger_jlo_id, ptu_base_jlo_id);
00211
00212 if(pose == NULL)
00213 {
00214 RelPose* pose1 = RelPoseFactory::GetRelPose("/sr4");
00215 RelPose* pose2 = RelPoseFactory::GetRelPose("/base_link");
00216 if(pose1 && pose2)
00217 {
00218 pose = RelPoseFactory::GetRelPose(pose1->m_uniqueID, pose2->m_uniqueID);
00219 RelPoseFactory::FreeRelPose(&pose1);
00220 RelPoseFactory::FreeRelPose(&pose2);
00221 }
00222 if(pose == NULL)
00223 throw "Cloud trans not possible: Location not clear";
00224 }
00225 Matrix m = pose->GetMatrix(0);
00226
00227 RelPoseFactory::FreeRelPose(&pose);
00228
00229 Matrix m_tmp = m;
00230 cloud_in_trans_.points.clear();
00231 if(cloud_in.points.size() == 0 || cloud_in.points.size() > 1000000000)
00232 throw "Error in pointcloud, failed check 0 =< num_points < 1000000000";
00233 for(size_t i = 0; i < cloud_in.points.size(); i++)
00234 {
00235 ColumnVector v(4);
00236 v << cloud_in.points[i].x << cloud_in.points[i].y << cloud_in.points[i].z << 1;
00237 ColumnVector a = m_tmp*v;
00238 Point32 pt;
00239 pt.x = a.element(0);
00240 pt.y = a.element(1);
00241 pt.z = a.element(2);
00242 cloud_in_trans_.points.push_back(pt);
00243 }
00244 cloud_in_trans_.channels.clear();
00245 for(size_t channels = 0 ; channels < cloud_in.channels.size(); channels++)
00246 {
00247
00248 cloud_in_trans_.channels.push_back(ChannelFloat32());
00249 cloud_in_trans_.channels[channels].name = cloud_in.channels[channels].name;
00250 for(size_t points = 0; points < cloud_in.channels[channels].values.size(); points++)
00251 {
00252 cloud_in_trans_.channels[channels].values.push_back(
00253 cloud_in.channels[channels].values[points]);
00254 }
00255 }
00256 ColumnVector vp(4);
00257 vp << viewpoint_cloud.x << viewpoint_cloud.y << viewpoint_cloud.z << 1;
00258 ColumnVector ap = m_tmp*vp;
00259 viewpoint_cloud.x = ap.element(0);
00260 viewpoint_cloud.y = ap.element(1);
00261 viewpoint_cloud.z = ap.element(2);
00262 }
00263
00265 bool
00266 plane_clusters_service (PlaneClusterResult &resp, int swissranger_jlo_id, int ptu_base_jlo_id, const PointCloud& cloud, bool parallel)
00267 {
00268 printf("plane_clusters_service::lock!\n");
00269 m_mutexUsage.lock();
00270 try
00271 {
00272
00273
00274 Point32 vp;
00275 vp.x = vp.y = vp.z = 0.0;
00276 cloud_trans(swissranger_jlo_id, ptu_base_jlo_id, vp, cloud);
00277 if(!detectTable (cloud_in_trans_, resp, vp, parallel))
00278 {
00279 printf("plane_clusters_service::unlock!\n");
00280
00281 m_mutexUsage.unlock();
00282 return false;
00283 }
00284 ROS_INFO ("Service request terminated.");
00285 printf("plane_clusters_service::lock!\n");
00286 m_mutexUsage.unlock();
00287 return (true);
00288 }
00289 catch(const char text)
00290 {
00291 printf("plane_clusters_service::lock!\n");
00292 m_mutexUsage.unlock();
00293 throw text;
00294 }
00295 }
00296
00297
00299 bool
00300 detectTable (const PointCloud &cloud, PlaneClusterResult &resp, Point32 viewpoint_cloud,bool parallel)
00301 {
00302 ros::Time ts = ros::Time::now ();
00303 bool assuming_ar4 = true;
00304
00305 cloud_down_.header = cloud.header;
00306
00307
00308 try
00309 {
00310
00311 if (abs((int)cloud.points.size() - SR_COLS*SR_ROWS) < 30)
00312 {
00313 cloud_geometry::nearest::computeOrganizedPointCloudNormalsWithFiltering (cloud_down_, cloud, k_, downsample_factor_, SR_COLS, SR_ROWS, max_z_, min_angle_, max_angle_, viewpoint_cloud);
00314 }
00315 else
00316 {
00317 assuming_ar4 = false;
00318 geometry_msgs::PointStamped view;
00319 view.point.x = viewpoint_cloud.x;
00320 view.point.y = viewpoint_cloud.y;
00321 view.point.z = viewpoint_cloud.z;
00322 cloud_down_.points = cloud.points;
00323 cloud_geometry::nearest::computePointCloudNormals(cloud_down_, k_, view);
00324 }
00325 }
00326 catch(std::out_of_range ex)
00327 {
00328 throw "Extraction failed";
00329 }
00330
00331
00332 vector<int> indices_z;
00333 if(parallel)
00334 {
00335 cloud_geometry::getPointIndicesAxisParallelNormals (cloud_down_, 0, 1, 2, eps_angle_, axis_, indices_z);
00336 }
00337 else
00338 {
00339 cloud_geometry::getPointIndicesAxisPerpendicularNormals( cloud_down_, 0, 1, 2, eps_angle_, axis_, indices_z);
00340 }
00341 #ifdef DEBUG
00342 ROS_INFO ("Number of points with normals parallel to Z: %d.", (int)indices_z.size ());
00343 #endif
00344 if(indices_z.size () < 10)
00345 {
00346 if(parallel)
00347 {
00348 cloud_geometry::getPointIndicesAxisParallelNormals (cloud_down_, 0, 1, 2, eps_angle_*2, axis_, indices_z);
00349 }
00350 else
00351 {
00352 cloud_geometry::getPointIndicesAxisPerpendicularNormals( cloud_down_, 0, 1, 2, eps_angle_*2, axis_, indices_z);
00353 }
00354 #ifdef DEBUG
00355 ROS_INFO ("Number of points with normals parallel to Z in second try: %d. with axis (%f %f %f )", (int)indices_z.size (), axis_.x, axis_.y, axis_.z);
00356 #endif
00357 }
00358 if(indices_z.size () < 10)
00359 return false;
00360
00361 vector<int> inliers_down;
00362 vector<double> coeff;
00363 printf("fitSACPlane \n");
00364 fitSACPlane (&cloud_down_, indices_z, inliers_down, coeff, viewpoint_cloud, sac_distance_threshold_);
00365
00366 printf("end fitSACPlane \n");
00367
00368 PointCloud cloud_filtered;
00369 if (assuming_ar4)
00370 {
00371 cloud_geometry::nearest::filterJumpEdges (cloud, cloud_filtered, 1, SR_COLS, SR_ROWS, min_angle_, max_angle_, viewpoint_cloud);
00372 }
00373 else
00374 {
00375 cloud_filtered = cloud;
00376 cloud_filtered.points = cloud.points;
00377 }
00378
00379 vector<int> inliers (cloud_filtered.points.size ());
00380 int j = 0;
00381 for (unsigned int i = 0; i < cloud_filtered.points.size (); i++)
00382 {
00383 double dist_to_plane = cloud_geometry::distances::pointToPlaneDistance (cloud_filtered.points[i], coeff);
00384 if (dist_to_plane < sac_distance_threshold_)
00385 inliers[j++] = i;
00386 }
00387 inliers.resize (j);
00388
00389
00390 Polygon table;
00391 printf("convexHull2D \n");
00392 cloud_geometry::areas::convexHull2D (cloud_down_, inliers_down, coeff, table);
00393 #ifdef DEBUG
00394
00395
00396
00397
00398
00399 #endif
00400
00401
00402 Point32 min_p, max_p;
00403 printf("getMinMax \n");
00404 cloud_geometry::statistics::getMinMax (cloud_filtered, inliers, min_p, max_p);
00405 vector<int> object_inliers;
00406 printf("findObjectClusters \n");
00407 findObjectClusters (cloud_filtered, coeff, table, axis_, min_p, max_p, object_inliers, resp);
00408
00409 #ifdef DEBUG
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 #endif
00421 ROS_INFO ("Results estimated in %g xseconds.", (ros::Time::now () - ts).toSec ());
00422
00423 resp.a = coeff[0]; resp.b = coeff[1]; resp.c = coeff[2]; resp.d = coeff[3];
00424 cloud_geometry::nearest::computeCentroid (cloud_filtered, inliers, resp.pcenter);
00425
00426 return true;
00427 }
00428
00430 void
00431 findObjectClusters (const PointCloud &cloud, const vector<double> &coeff, const Polygon &table,
00432 const Point32 &axis, const Point32 &min_p, const Point32 &max_p, vector<int> &object_indices, PlaneClusterResult &resp)
00433 {
00434 int nr_p = 0;
00435 Point32 pt;
00436 object_indices.resize (cloud.points.size ());
00437
00438
00439 for (unsigned int i = 0; i < cloud.points.size (); i++)
00440 {
00441
00442 if ( axis.x == 1 && ( cloud.points.at (i).y < min_p.y || cloud.points.at (i).y > max_p.y || cloud.points.at (i).z < min_p.z || cloud.points.at (i).z > max_p.z ) )
00443 continue;
00444
00445 else if ( axis.y == 1 && ( cloud.points.at (i).x < min_p.x || cloud.points.at (i).x > max_p.x || cloud.points.at (i).z < min_p.z || cloud.points.at (i).z > max_p.z ) )
00446 continue;
00447
00448 else if ( axis.z == 1 && ( cloud.points.at (i).x < min_p.x || cloud.points.at (i).x > max_p.x || cloud.points.at (i).y < min_p.y || cloud.points.at (i).y > max_p.y ) )
00449 continue;
00450
00451
00452 double dist_to_plane = coeff.at (0) * cloud.points.at (i).x +
00453 coeff.at (1) * cloud.points.at (i).y +
00454 coeff.at (2) * cloud.points.at (i).z +
00455 coeff.at (3) * 1;
00456
00457 pt.x = cloud.points.at (i).x - dist_to_plane * coeff.at (0);
00458 pt.y = cloud.points.at (i).y - dist_to_plane * coeff.at (1);
00459 pt.z = cloud.points.at (i).z - dist_to_plane * coeff.at (2);
00460
00461 if (dist_to_plane > delta_z_ && cloud_geometry::areas::isPointIn2DPolygon (pt, table))
00462 {
00463 object_indices[nr_p] = i;
00464 nr_p++;
00465 }
00466 }
00467 object_indices.resize (nr_p);
00468
00469
00470 nr_p = 0;
00471 vector<vector<int> > object_clusters;
00472 cloud_geometry::nearest::extractEuclideanClusters (cloud, object_indices, object_cluster_tolerance_,
00473 object_clusters, -1, -1, -1, -1, object_cluster_min_pts_);
00474
00475 #ifdef DEBUG
00476 int total_nr_pts = 0;
00477 for (unsigned int i = 0; i < object_clusters.size (); i++)
00478 total_nr_pts += object_clusters[i].size ();
00479
00480 cloud_annotated_.header = cloud.header;
00481 cloud_annotated_.points.resize (total_nr_pts);
00482 cloud_annotated_.channels.resize (1);
00483 cloud_annotated_.channels[0].name = "rgb";
00484 cloud_annotated_.channels[0].values.resize (total_nr_pts);
00485 ROS_INFO ("Number of clusters found: %d", (int)object_clusters.size ());
00486 #endif
00487
00488 Point32 min_p_cluster, max_p_cluster;
00489
00490 resp.oclusters.resize (object_clusters.size ());
00491 for (unsigned int i = 0; i < object_clusters.size (); i++)
00492 {
00493 #ifdef DEBUG
00494 float rgb = getRGB (rand () / (RAND_MAX + 1.0), rand () / (RAND_MAX + 1.0), rand () / (RAND_MAX + 1.0));
00495 #endif
00496 vector<int> object_idx = object_clusters.at (i);
00497
00498
00499 cloud_geometry::statistics::getMinMax (cloud, object_idx, min_p_cluster, max_p_cluster);
00500
00501 if ( axis.x == 1 && ( min_p_cluster.x > max_p.x + object_min_dist_from_table_ ) )
00502 continue;
00503 if ( axis.y == 1 && ( min_p_cluster.y > max_p.y + object_min_dist_from_table_ ) )
00504 continue;
00505 if ( axis.z == 1 && ( min_p_cluster.z > max_p.z + object_min_dist_from_table_ ) )
00506 continue;
00507
00508
00509 for (unsigned int j = 0; j < object_idx.size (); j++)
00510 {
00511 object_indices[nr_p] = object_idx.at (j);
00512 #ifdef DEBUG
00513 cloud_annotated_.points[nr_p] = cloud.points.at (object_idx.at (j));
00514 cloud_annotated_.channels[0].values[nr_p] = rgb;
00515 #endif
00516 nr_p++;
00517 }
00518 cloud_geometry::nearest::computeCentroid (cloud, object_idx, resp.oclusters[i].center);
00519 resp.oclusters[i].cov33.clear();
00520 for(unsigned int l = 0; l < 9; l++)
00521 {
00522 resp.oclusters[i].cov33.push_back(0.0);
00523 }
00524
00525 for(unsigned int k = 0; k < object_idx.size (); k++)
00526 {
00527 Point32 p = cloud.points.at (object_idx.at (k));
00528 p.x = p.x - resp.oclusters[i].center.x;
00529 p.y = p.y - resp.oclusters[i].center.y;
00530 p.z = p.z - resp.oclusters[i].center.z;
00531 resp.oclusters[i].cov33[0] += p.x*p.x;
00532 resp.oclusters[i].cov33[1] += p.y*p.x;
00533 resp.oclusters[i].cov33[2] += p.z*p.x;
00534 resp.oclusters[i].cov33[3] += p.x*p.y;
00535 resp.oclusters[i].cov33[4] += p.y*p.y;
00536 resp.oclusters[i].cov33[5] += p.z*p.y;
00537 resp.oclusters[i].cov33[6] += p.x*p.z;
00538 resp.oclusters[i].cov33[7] += p.y*p.z;
00539 resp.oclusters[i].cov33[8] += p.z*p.z;
00540 }
00541 for(unsigned int t = 0; t < resp.oclusters[i].cov33.size(); t++)
00542 {
00543 resp.oclusters[i].cov33[t] /= object_idx.size ();
00544 if(resp.oclusters[i].cov33[t] <= 0.0)
00545 resp.oclusters[i].cov33[t] = 0.000000001;
00546 }
00547
00548 }
00549 object_indices.resize (nr_p);
00550 #ifdef DEBUG
00551 cloud_annotated_.points.resize (nr_p);
00552 cloud_annotated_.channels[0].values.resize (nr_p);
00553 #endif
00554 }
00555
00556
00558 bool
00559 fitSACPlane (PointCloud *points, vector<int> &indices, vector<int> &inliers, vector<double> &coeff,
00560 const Point32 &viewpoint_cloud, double dist_thresh)
00561 {
00562 if ((int)indices.size () < clusters_min_pts_)
00563 {
00564 inliers.resize (0);
00565 coeff.resize (0);
00566 return (false);
00567 }
00568
00569
00570 sample_consensus::SACModelPlane *model = new sample_consensus::SACModelPlane ();
00571 sample_consensus::SAC *sac = new sample_consensus::MSAC (model, sac_distance_threshold_);
00572 sac->setMaxIterations (200);
00573 sac->setProbability (0.99);
00574 model->setDataSet (points, indices);
00575
00576
00577 if (sac->computeModel ())
00578 {
00579 if ((int)sac->getInliers ().size () < clusters_min_pts_)
00580 {
00581
00582 inliers.resize (0);
00583 coeff.resize (0);
00584 return (false);
00585 }
00586
00587 sac->computeCoefficients (coeff);
00588 sac->refineCoefficients (coeff);
00589 model->selectWithinDistance (coeff, dist_thresh, inliers);
00590
00591 cloud_geometry::angles::flipNormalTowardsViewpoint (coeff, points->points.at (inliers[0]), viewpoint_cloud);
00592
00593
00594 model->projectPointsInPlace (inliers, coeff);
00595 }
00596 delete model;
00597 delete sac;
00598 return (true);
00599 }
00600 };
00601
00602 PlaneClustersSR* s_planeCluster = NULL;
00603
00604 ClusterDetector::ClusterDetector(int srid, int ptuid) :
00605 m_swissranger_jlo_id(srid),
00606 m_ptu_jlo_id(ptuid)
00607 {
00608 if(s_planeCluster == NULL)
00609 s_planeCluster = new PlaneClustersSR(NULL);
00610 }
00611
00612 ClusterDetector::ClusterDetector()
00613 {
00614 }
00615
00616 void ClusterDetector::SetData(XMLTag* tag)
00617 {
00618 if(s_planeCluster == NULL)
00619 s_planeCluster = new PlaneClustersSR(tag);
00620
00621
00622 if(tag != NULL)
00623 {
00624 m_swissranger_jlo_id = tag->GetPropertyInt(XML_ATTRIBUTE_SR4LO, 0);
00625 if(m_swissranger_jlo_id == 0)
00626 {
00627 std::string name = tag->GetProperty(XML_ATTRIBUTE_SR4LO, "/sr4");
00628 RelPose* pose = RelPoseFactory::GetRelPose(name);
00629 if(pose == NULL)
00630 m_swissranger_jlo_id = 1;
00631 else
00632 {
00633 printf("Read Clusterdetector with %ld as camera position (%s)\n", pose->m_uniqueID, name.c_str());
00634 m_swissranger_jlo_id =pose->m_uniqueID;
00635 RelPoseFactory::FreeRelPose(&pose);
00636 }
00637 }
00638 m_ptu_jlo_id = tag->GetPropertyInt(XML_ATTRIBUTE_PTULO, 0);
00639 if(m_ptu_jlo_id == 0)
00640 {
00641 std::string name = tag->GetProperty(XML_ATTRIBUTE_PTULO, "/base_link");
00642 RelPose* pose = RelPoseFactory::GetRelPose(name);
00643 if(pose == NULL)
00644 m_ptu_jlo_id = 1;
00645 else
00646 {
00647 m_ptu_jlo_id =pose->m_uniqueID;
00648 RelPoseFactory::FreeRelPose(&pose);
00649 }
00650 }
00651 }
00652 }
00653
00654
00655 ClusterDetector::~ClusterDetector()
00656 {
00657 delete s_planeCluster;
00658 s_planeCluster = NULL;
00659 }
00660
00661 std::vector<RelPose*> ClusterDetector::Perform(std::vector<Sensor*> sensors, RelPose* pose, Signature& object, int &numOfObjects, double& qualityMeasure)
00662 {
00663 std::vector<RelPose*> results;
00664
00665 SegmentPrototype* proto = (SegmentPrototype*)object.GetElement(0, DESCRIPTOR_SEGMPROTO);
00666 printf("ClusterDetector::Perform: Got SegmentPrototype\n");
00667 for(std::vector<Sensor*>::const_iterator it = sensors.begin(); it != sensors.end(); it++)
00668 {
00669 if((*it)->GetName().compare(XML_NODE_SWISSRANGER) == 0)
00670 {
00671 try
00672 {
00673 results = Inner(*it, proto, numOfObjects, qualityMeasure);
00674 }
00675 catch (const char* text )
00676 {
00677 printf("Error in ClusterDetector: %s\n", text);
00678 }
00679 break;
00680 }
00681 }
00682
00683 return results;
00684 }
00685
00686
00687
00688 inline void normalize(double &a,double &b, double &c)
00689 {
00690 double norm = sqrt(a*a + b*b + c*c);
00691 a /= norm;
00692 b /= norm;
00693 c /= norm;
00694 }
00695
00696 inline double scalarproduct(const double &a,const double &b, const double &c, const double &d, const double &e, const double &f)
00697 {
00698 return a * d + b* e + c*f;
00699 }
00700
00701 inline void CrossProduct_l(const double b_x, const double b_y,const double b_z,const double c_x,const double c_y,const double c_z,double &a_x,double &a_y,double &a_z)
00702 {
00703 a_x = b_y*c_z - b_z*c_y;
00704 a_y = b_z*c_x - b_x*c_z;
00705 a_z = b_x*c_y - b_y*c_x;
00706 }
00707
00708 bool ClusterDetector::CallStaticPlaneClusterExtractor(Sensor* sensor, PlaneClusterResult* response, int ptu_jlo_id, bool parallel)
00709 {
00710 if(s_planeCluster == NULL)
00711 s_planeCluster = new PlaneClustersSR(NULL);
00712 SwissRangerReading* reading = (SwissRangerReading*)sensor->GetReading(-1);
00713 try
00714 {
00715 bool b = s_planeCluster->plane_clusters_service(*response, reading->m_relPose->m_uniqueID, ptu_jlo_id, reading->m_image, parallel);
00716 reading->Free();
00717 return b;
00718 }
00719 catch(const char* text)
00720 {
00721 printf("Error in ClusterDetector: %s\n", text);
00722 }
00723 return false;
00724 }
00725
00726 std::vector<RelPose*> ClusterDetector::Inner(Sensor* sens, SegmentPrototype* obj_descr, int &numOfObjects, double& qualityMeasure)
00727 {
00728 std::vector<RelPose*> results;
00729 PlaneClusterResult response;
00730 qualityMeasure = 0.0;
00731 bool parallel = true;
00732 unsigned long ref_frame = m_ptu_jlo_id;
00733
00734 if(obj_descr != NULL)
00735 {
00736 ref_frame = obj_descr->GetFrameId();
00737 parallel = obj_descr->m_parallel;
00738 }
00739
00740 if(!CallStaticPlaneClusterExtractor(sens, &response, ref_frame, parallel))
00741 {
00742 return results;
00743 }
00744
00745 double a = response.a;
00746 double b = response.b;
00747 double c = response.c;
00748 double s = response.d;
00749 std::vector<PlaneClusterResult::ObjectOnTable> &vec = response.oclusters;
00750 printf("Got plane equation %f x + %f y + %f z + %f = 0\n", a,b,c,s);
00751
00752 normalize(a,b,c);
00753
00754
00755 double d,e,f,g,h,i;
00756 if (a == b && a == c)
00757 {
00758 d = 1; e = 0; f = 0;
00759 }
00760 else
00761 {
00762 d = b; e = a; f = c;
00763 }
00764
00765 double tmp = scalarproduct(a,b,c,d,e,f);
00766 d = d - tmp * a;
00767 e = e - tmp * b;
00768 f = f - tmp * c;
00769
00770
00771 normalize(d,e,f);
00772
00773
00774
00775 CrossProduct_l(a,b,c,d,e,f, g,h,i);
00783 if(vec.size() == 0)
00784 {
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 }
00800 printf("Creating a pose for every cluster\n");
00801 double prob = 1.0;
00802 RelPose* ptu = RelPoseFactory::FRelPose(ref_frame);
00803
00804 for(size_t x = 0; x < vec.size(); x++)
00805 {
00806 prob = prob * 0.9;
00807 printf("a: %f , b: %f , c: %f\n", a, b, c);
00808 const geometry_msgs::Point32 ¢er = vec[x].center;
00809 Matrix rotmat(4,4);
00810
00811 rotmat << d << g << a << center.x
00812 << e << h << b << center.y
00813 << f << i << c << center.z
00814 << 0 << 0 << 0 << 1;
00815
00816 cout << "Matrix from plane_clusters:" << endl << rotmat << endl;
00817 Matrix cov (6,6);
00818 if(vec[x].cov33.size() < 9)
00819 {
00820 ROS_ERROR("Error detectin Clusters: size of cov33 (%ld) smaller than expected: 9\n", vec[x].cov33.size());
00821 }
00822 else
00823 {
00824
00825
00826 if(parallel)
00827 {
00828
00829
00830
00831
00832
00833
00834
00835 cov << sqrt(vec[x].cov33[0]) << sqrt(vec[x].cov33[1]) << sqrt(vec[x].cov33[2]) << 0 << 0 << 0
00836 << sqrt(vec[x].cov33[3]) << sqrt(vec[x].cov33[4]) << sqrt(vec[x].cov33[5]) << 0 << 0 << 0
00837 << sqrt(vec[x].cov33[6]) << sqrt(vec[x].cov33[7]) << sqrt(vec[x].cov33[8]) << 0 << 0 << 0
00838 <<0 << 0 << 0 << ((obj_descr == NULL) ? 0.2 : obj_descr->m_covRotX) << 0 << 0
00839 <<0 << 0 << 0 << 0 << ((obj_descr == NULL) ? 0.2 :obj_descr->m_covRotY) << 0
00840 <<0 << 0 << 0 << 0 << 0 << ((obj_descr == NULL) ? 0.8 :obj_descr->m_covRotZ);
00841 }
00842 else
00843 {
00844 cov << sqrt(vec[x].cov33[3]) << vec[x].cov33[4] << vec[x].cov33[5] << 0 << 0 << 0
00845 << vec[x].cov33[0] << vec[x].cov33[1] << vec[x].cov33[2] << 0 << 0 << 0
00846 << vec[x].cov33[6] << vec[x].cov33[7] << vec[x].cov33[8] << 0 << 0 << 0
00847 <<0 << 0 << 0 << ((obj_descr == NULL) ? 0.2 :obj_descr->m_covRotY) << 0 << 0
00848 <<0 << 0 << 0 << 0 << ((obj_descr == NULL) ? 0.2 :obj_descr->m_covRotX) << 0
00849 <<0 << 0 << 0 << 0 << 0 << ((obj_descr == NULL) ? 0.8 :obj_descr->m_covRotZ);
00850 }
00851
00852 cout << "Cov from pc: "<< endl << cov << endl;
00853 RelPose* pose_temp = RelPoseFactory::FRelPose(ptu, rotmat, cov);
00854 double temp_qual = min(1.0, max(0.0, fabs((sqrt(vec[x].cov33[4])*sqrt(vec[x].cov33[0])*sqrt(vec[x].cov33[8]))) * 500 ));
00855 if(x == 0)
00856 qualityMeasure =temp_qual;
00857
00858 if(pose_temp == NULL)
00859 continue;
00860 pose_temp->m_qualityMeasure = temp_qual;
00861 results.push_back(pose_temp);
00862 }
00863 }
00864 RelPoseFactory::FreeRelPose(&ptu);
00865 return results;
00866 }
00867
00868 double ClusterDetector::CheckSignature(const Signature& object, const std::vector<Sensor*> &sensors)
00869 {
00870 for(std::vector<Sensor*>::const_iterator it = sensors.begin(); it != sensors.end(); it++)
00871 {
00872 if((*it)->GetName().compare(XML_NODE_SWISSRANGER) == 0)
00873 {
00874 if(object.GetElement(0, DESCRIPTOR_SEGMPROTO) != NULL )
00875 return 0.1;
00876 else
00877 return 0.0;
00878 }
00879 }
00880 return 0.0;
00881 }
00882
00883
00884 bool ClusterDetector::TrackingPossible(const Reading& img, const Signature& sig, RelPose* pose)
00885 {
00886 return false;
00887 }
00888
00889 XMLTag* ClusterDetector::Save()
00890 {
00891 XMLTag* tag = new XMLTag(XML_NODE_CLUSTERDETECTOR);
00892 tag->AddProperty(XML_ATTRIBUTE_SR4LO, m_swissranger_jlo_id);
00893 tag->AddProperty(XML_ATTRIBUTE_PTULO, m_ptu_jlo_id);
00894 return tag;
00895 }
00896