$search
00001 /**************************************************************** 00002 * 00003 * Copyright (c) 2011 00004 * 00005 * Fraunhofer Institute for Manufacturing Engineering 00006 * and Automation (IPA) 00007 * 00008 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00009 * 00010 * Project name: care-o-bot 00011 * ROS stack name: cob_environment_perception_intern 00012 * ROS package name: cob_3d_mapping_semantics 00013 * Description: 00014 * 00015 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00016 * 00017 * Author: Waqas Tanveer email:Waqas.Tanveer@ipa.fraunhofer.de 00018 * Supervised by: Georg Arbeiter, email:georg.arbeiter@ipa.fhg.de 00019 * 00020 * Date of creation: 11/2011 00021 * ToDo: 00022 * 00023 * 00024 * 00025 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00026 * 00027 * Redistribution and use in source and binary forms, with or without 00028 * modification, are permitted provided that the following conditions are met: 00029 * 00030 * * Redistributions of source code must retain the above copyright 00031 * notice, this list of conditions and the following disclaimer. 00032 * * Redistributions in binary form must reproduce the above copyright 00033 * notice, this list of conditions and the following disclaimer in the 00034 * documentation and/or other materials provided with the distribution. 00035 * * Neither the name of the Fraunhofer Institute for Manufacturing 00036 * Engineering and Automation (IPA) nor the names of its 00037 * contributors may be used to endorse or promote products derived from 00038 * this software without specific prior written permission. 00039 * 00040 * This program is free software: you can redistribute it and/or modify 00041 * it under the terms of the GNU Lesser General Public License LGPL as 00042 * published by the Free Software Foundation, either version 3 of the 00043 * License, or (at your option) any later version. 00044 * 00045 * This program is distributed in the hope that it will be useful, 00046 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00047 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00048 * GNU Lesser General Public License LGPL for more details. 00049 * 00050 * You should have received a copy of the GNU Lesser General Public 00051 * License LGPL along with this program. 00052 * If not, see <http://www.gnu.org/licenses/>. 00053 * 00054 ****************************************************************/ 00055 00056 //################## 00057 //#### includes #### 00058 #include <algorithm> 00059 00060 // ROS includes 00061 #include <ros/ros.h> 00062 #include <rosbag/bag.h> 00063 //#include <tf_conversions/tf_eigen.h> 00064 //#include <tf/transform_listener.h> 00065 #include <dynamic_reconfigure/server.h> 00066 00067 // ros message includes 00068 #include <sensor_msgs/PointCloud.h> 00069 #include <visualization_msgs/Marker.h> 00070 #include <visualization_msgs/MarkerArray.h> 00071 00072 // PCL includes 00073 #include <pcl/point_cloud.h> 00074 #include <pcl/point_types.h> 00075 #include <pcl/ros/conversions.h> 00076 #include <pcl/io/pcd_io.h> 00077 00078 //internal includes 00079 #include <cob_3d_mapping_msgs/ShapeArray.h> 00080 #include <cob_3d_mapping_msgs/GetGeometryMap.h> 00081 #include <cob_3d_mapping_msgs/GetObjectsOfClass.h> 00082 #include <cob_3d_mapping_msgs/GetTables.h> 00083 //#include <cob_3d_mapping_msgs/MoveToTable.h> 00084 #include <cob_3d_mapping_semantics/table_extraction.h> 00085 #include <cob_3d_mapping_semantics/table_extraction_nodeConfig.h> 00086 #include <cob_3d_mapping_common/ros_msg_conversions.h> 00087 //#include <tabletop_object_detector/TabletopDetection.h> 00088 00089 using namespace cob_3d_mapping; 00090 00091 class TableExtractionNode 00092 { 00093 public: 00094 00095 // Constructor 00096 TableExtractionNode () : 00097 target_frame_id_ ("/map"), 00098 /*tilt_angle_ (3.0), 00099 height_min_ (0.6), 00100 height_max_ (1.2), 00101 area_min_ (0.5), 00102 area_max_ (3),*/ 00103 table_ctr_(0), 00104 table_ctr_old_(0) 00105 { 00106 config_server_.setCallback(boost::bind(&TableExtractionNode::dynReconfCallback, this, _1, _2)); 00107 00108 sa_sub_ = n_.subscribe ("shape_array", 10, &TableExtractionNode::callbackShapeArray, this); 00109 sa_pub_ = n_.advertise<cob_3d_mapping_msgs::ShapeArray> ("shape_array_pub", 1); //10 00110 s_marker_pub_ = n_.advertise<visualization_msgs::Marker> ("marker", 10); 00111 00112 get_tables_server_ = n_.advertiseService ("get_objects_of_class", &TableExtractionNode::getTablesService, this); 00113 get_tables_server_2_ = n_.advertiseService ("get_tables", &TableExtractionNode::getTablesService2, this); 00114 00115 /*ros::NodeHandle private_nh("~"); 00116 private_nh.getParam ("target_frame", target_frame_id_); 00117 private_nh.getParam ("tilt_angle", tilt_angle_); 00118 private_nh.getParam ("height_min", height_min_); 00119 private_nh.getParam ("height_max", height_max_); 00120 private_nh.getParam ("area_min", area_min_); 00121 private_nh.getParam ("area_max", area_max_); 00122 00123 te_.setNormalBounds (tilt_angle_); 00124 te_.setHeightMin (height_min_); 00125 te_.setHeightMax (height_max_); 00126 te_.setAreaMin (area_min_); 00127 te_.setAreaMax (area_max_);*/ 00128 00129 } 00130 00131 // Destructor 00132 ~TableExtractionNode () 00133 { 00135 } 00136 00147 void 00148 dynReconfCallback(cob_3d_mapping_semantics::table_extraction_nodeConfig &config, uint32_t level) 00149 { 00150 ROS_INFO("[table_extraction]: received new parameters"); 00151 target_frame_id_ = config.target_frame_id; 00152 te_.setNormalBounds (config.tilt_angle); 00153 te_.setHeightMin (config.height_min); 00154 te_.setHeightMax (config.height_max); 00155 te_.setAreaMin (config.area_min); 00156 te_.setAreaMax (config.area_max); 00157 } 00158 00167 void 00168 callbackShapeArray (const cob_3d_mapping_msgs::ShapeArray::ConstPtr sa_ptr) 00169 { 00170 if(sa_ptr->header.frame_id != target_frame_id_) 00171 { 00172 ROS_ERROR("Frame IDs do not match, aborting..."); 00173 return; 00174 } 00175 cob_3d_mapping_msgs::ShapeArray tables; 00176 tables.header = sa_ptr->header; 00177 tables.header.frame_id = target_frame_id_ ; 00178 processMap(*sa_ptr, tables); 00179 publishShapeMarker (tables); 00180 sa_pub_.publish (tables); 00181 table_ctr_ = tables.shapes.size(); 00182 ROS_INFO("Found %u tables", (unsigned int)tables.shapes.size()); 00183 } 00184 00185 00194 bool 00195 getTablesService (cob_3d_mapping_msgs::GetObjectsOfClassRequest &req, 00196 cob_3d_mapping_msgs::GetObjectsOfClassResponse &res) 00197 { 00198 ROS_INFO("service get_tables started...."); 00199 00200 cob_3d_mapping_msgs::ShapeArray sa; 00201 if (getMapService (sa)) 00202 { 00203 processMap(sa, res.objects); 00204 publishShapeMarker (res.objects); 00205 table_ctr_ = res.objects.shapes.size(); 00206 ROS_INFO("Found %u tables", (unsigned int)res.objects.shapes.size()); 00207 return true; 00208 } 00209 else 00210 return false; 00211 } 00212 00221 bool 00222 getTablesService2 (cob_3d_mapping_msgs::GetTablesRequest &req, 00223 cob_3d_mapping_msgs::GetTablesResponse &res) 00224 { 00225 ROS_INFO("table detection started...."); 00226 00227 cob_3d_mapping_msgs::ShapeArray sa, tables; 00228 if (getMapService (sa)) 00229 { 00230 tables.header = sa.header; 00231 //test 00232 tables.header.frame_id = "/map" ; 00233 //end of test 00234 processMap(sa, tables); 00235 00236 for (unsigned int i = 0; i < tables.shapes.size (); i++) 00237 { 00238 //Polygon poly; 00239 Polygon::Ptr poly_ptr(new Polygon()); 00240 fromROSMsg(tables.shapes[i], *poly_ptr); 00241 00242 cob_3d_mapping_msgs::Table table; 00243 Eigen::Affine3f pose; 00244 Eigen::Vector4f min_pt; 00245 Eigen::Vector4f max_pt; 00246 poly_ptr->computePoseAndBoundingBox(pose,min_pt, max_pt); 00247 table.pose.pose.position.x = pose.translation()(0); //poly_ptr->centroid[0]; 00248 table.pose.pose.position.y = pose.translation()(1) ;//poly_ptr->centroid[1]; 00249 table.pose.pose.position.z = pose.translation()(2) ;//poly_ptr->centroid[2]; 00250 Eigen::Quaternionf quat(pose.rotation()); 00251 // ROS_WARN("poly_ptr->centroid[0]"); 00252 // std::cout << poly_ptr->centroid[0]<< "\n"; 00253 // ROS_WARN("pose.translation()"); 00254 // std::cout << pose.translation() << "\n" ; 00255 00256 table.pose.pose.orientation.x = quat.x(); 00257 table.pose.pose.orientation.y = quat.y(); 00258 table.pose.pose.orientation.z = quat.z(); 00259 table.pose.pose.orientation.w = quat.w(); 00260 table.x_min = min_pt(0); 00261 table.x_max = max_pt(0); 00262 table.y_min = min_pt(1); 00263 table.y_max = max_pt(1); 00264 00265 table.convex_hull.type = arm_navigation_msgs::Shape::MESH; 00266 for( unsigned int j=0; j<poly_ptr->contours[0].size(); j++) 00267 { 00268 geometry_msgs::Point p; 00269 p.x = poly_ptr->contours[0][j](0); 00270 p.y = poly_ptr->contours[0][j](1); 00271 p.z = poly_ptr->contours[0][j](2); 00272 table.convex_hull.vertices.push_back(p); 00273 } 00274 00275 cob_3d_mapping_msgs::TabletopDetectionResult det; 00276 det.table = table; 00277 00278 res.tables.push_back(det); 00279 } 00280 // sa_pub_.publish (tables); 00281 publishShapeMarker (tables); 00282 table_ctr_ = tables.shapes.size(); 00283 00284 ROS_INFO("Found %d tables", table_ctr_); 00285 return true; 00286 } 00287 else 00288 return false; 00289 } 00290 00296 bool 00297 getMapService (cob_3d_mapping_msgs::ShapeArray& sa) 00298 { 00299 ROS_INFO("Waiting for service server to start."); 00300 ros::service::waitForService ("get_geometry_map", 10); //will wait for infinite time 00301 00302 ROS_INFO("Server started, polling map."); 00303 00304 //build message 00305 cob_3d_mapping_msgs::GetGeometryMapRequest req; 00306 cob_3d_mapping_msgs::GetGeometryMapResponse res; 00307 00308 if (ros::service::call ("get_geometry_map", req, res)) 00309 { 00310 ROS_INFO("Service call finished."); 00311 } 00312 else 00313 { 00314 ROS_INFO("Service call failed."); 00315 return 0; 00316 } 00317 sa = res.map; 00318 return true; 00319 } 00320 00328 void 00329 publishShapeMarker (const cob_3d_mapping_msgs::ShapeArray& sa) 00330 { 00331 for(unsigned int i=0; i<table_ctr_old_; i++) 00332 { 00333 visualization_msgs::Marker marker; 00334 marker.action = visualization_msgs::Marker::DELETE; 00335 marker.id = i; 00336 s_marker_pub_.publish (marker); 00337 } 00338 for(unsigned int i=0; i<sa.shapes.size(); i++) 00339 { 00340 visualization_msgs::Marker marker; 00341 marker.action = visualization_msgs::Marker::ADD; 00342 marker.type = visualization_msgs::Marker::LINE_STRIP; 00343 marker.lifetime = ros::Duration (); 00344 marker.header.frame_id = target_frame_id_; 00345 marker.ns = "table_marker"; 00346 marker.header.stamp = ros::Time::now (); 00347 00348 marker.id = i; 00349 marker.scale.x = 0.05; 00350 marker.scale.y = 0.05; 00351 marker.scale.z = 0; 00352 marker.color.r = 0;//1; 00353 marker.color.g = 0; 00354 marker.color.b = 1; 00355 marker.color.a = 1.0; 00356 00357 00358 // sensor_msgs::PointCloud2 pc2; 00359 pcl::PointCloud<pcl::PointXYZ> cloud; 00360 00361 pcl::fromROSMsg (sa.shapes[i].points[0], cloud); 00362 00363 geometry_msgs::Point p; 00364 //marker.points.resize (cloud.size()+1); 00365 for (unsigned int j = 0; j < cloud.size(); j++) 00366 { 00367 p.x = cloud[j].x; 00368 p.y = cloud[j].y; 00369 p.z = cloud[j].z; 00370 marker.points.push_back(p); 00371 } 00372 p.x = cloud[0].x; 00373 p.y = cloud[0].y; 00374 p.z = cloud[0].z; 00375 marker.points.push_back(p); 00376 s_marker_pub_.publish (marker); 00377 } 00378 } 00379 00388 void 00389 processMap(const cob_3d_mapping_msgs::ShapeArray& sa, cob_3d_mapping_msgs::ShapeArray& tables) 00390 { 00391 /*Eigen::Affine3f af_target = Eigen::Affine3f::Identity(); 00392 if(sa.header.frame_id != target_frame_id_) 00393 { 00394 tf::StampedTransform trf_map; 00395 00396 try 00397 { 00398 tf_listener_.waitForTransform(target_frame_id_, sa.header.frame_id, sa.header.stamp, ros::Duration(2)); 00399 tf_listener_.lookupTransform(target_frame_id_, sa.header.frame_id, sa.header.stamp, trf_map); 00400 } 00401 catch (tf::TransformException ex) { ROS_ERROR("[geometry map node] : %s",ex.what()); return; } 00402 00403 Eigen::Affine3d ad; 00404 tf::TransformTFToEigen(trf_map, ad); 00405 af_target = ad.cast<float>(); 00406 }*/ 00407 for (unsigned int i = 0; i < sa.shapes.size (); i++) 00408 { 00409 Polygon::Ptr poly_ptr (new Polygon()); 00410 fromROSMsg(sa.shapes[i], *poly_ptr); 00411 //if(sa.header.frame_id!="/map") 00412 // poly_ptr->transform2tf(af_target); 00413 //ROS_INFO("\n\tisTableObject.... : "); 00414 te_.setInputPolygon(poly_ptr); 00415 if (te_.isTable()) 00416 { 00417 poly_ptr->color[0] = 1; 00418 poly_ptr->color[1] = 0; 00419 poly_ptr->color[2] = 0; 00420 poly_ptr->color[3] = 1; 00421 cob_3d_mapping_msgs::Shape s; 00422 s.header = sa.header; 00423 s.header.frame_id = target_frame_id_; 00424 toROSMsg(*poly_ptr,s); 00425 //ros::Duration (10).sleep (); 00426 //cob_3d_mapping_msgs::Shape s; 00427 //toROSMsg(*map[i], s); 00428 //convertPolygonToShape (*sem_exn_.PolygonMap[i], s); 00429 ROS_INFO("getTablesService: Polygon[%d] converted to shape",i); 00430 tables.shapes.push_back (s); 00431 } 00432 } 00433 } 00434 00435 ros::NodeHandle n_; 00436 00437 protected: 00438 ros::Subscriber sa_sub_; 00439 ros::Publisher sa_pub_; 00440 ros::Publisher pc2_pub_; 00441 ros::Publisher s_marker_pub_; 00442 ros::ServiceServer get_tables_server_; 00443 ros::ServiceServer get_tables_server_2_; 00444 //tf::TransformListener tf_listener_; ///< Retrieves transformations. 00445 00449 dynamic_reconfigure::Server<cob_3d_mapping_semantics::table_extraction_nodeConfig> config_server_; 00450 00451 TableExtraction te_; 00452 00453 std::string target_frame_id_; 00454 /*double tilt_angle_; 00455 double height_min_, height_max_; 00456 double area_min_, area_max_;*/ 00457 00458 unsigned int table_ctr_; 00459 unsigned int table_ctr_old_; 00460 00461 }; 00462 00463 int 00464 main (int argc, char** argv) 00465 { 00466 ros::init (argc, argv, "semantic_extraction_node"); 00467 00468 TableExtractionNode sem_exn_node; 00469 //ros::spin (); 00470 00471 ros::Rate loop_rate (10); 00472 while (ros::ok ()) 00473 { 00474 ros::spinOnce (); 00475 loop_rate.sleep (); 00476 } 00477 00478 }