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