collision_map_interface.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 *  Copyright (c) 2009, Willow Garage, Inc.
00004 *  All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Willow Garage nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 
00034 // Author(s): Gil Jones and Matei Ciocarlie
00035 
00036 #include "tabletop_collision_map_processing/collision_map_interface.h"
00037 
00038 #include <tf/transform_datatypes.h>
00039 
00040 #include <std_srvs/Empty.h>
00041 
00042 #include <arm_navigation_msgs/CollisionObject.h>
00043 #include <arm_navigation_msgs/AttachedCollisionObject.h>
00044 
00045 #include <object_manipulation_msgs/FindClusterBoundingBox.h>
00046 #include <object_manipulation_msgs/FindClusterBoundingBox2.h>
00047 
00048 #include <household_objects_database_msgs/DatabaseModelPose.h>
00049 #include <household_objects_database_msgs/GetModelMesh.h>
00050 
00051 #include <object_manipulator/tools/msg_helpers.h>
00052 
00053 namespace tabletop_collision_map_processing {
00054 
00055 static const std::string CLUSTER_BOUNDING_BOX_NAME = "find_cluster_bounding_box";
00056 static const std::string CLUSTER_BOUNDING_BOX2_NAME = "find_cluster_bounding_box2";
00057 static const std::string CLUSTER_BOUNDING_BOX_3D_NAME = "find_cluster_bounding_box_3d";
00058 static const std::string CLUSTER_BOUNDING_BOX2_3D_NAME = "find_cluster_bounding_box2_3d";
00059 
00060 CollisionMapInterface::CollisionMapInterface() : 
00061   root_nh_(""),
00062   priv_nh_("~"),
00063   connections_established_(false),
00064   collision_object_current_id_(0)
00065 {
00066   collision_object_pub_ = root_nh_.advertise<arm_navigation_msgs::CollisionObject>("collision_object", 10);
00067   attached_object_pub_ = root_nh_.advertise<arm_navigation_msgs::AttachedCollisionObject>("attached_collision_object", 10); 
00068 }
00069  
00070 void CollisionMapInterface::connectServices()
00071 {
00072   cluster_bounding_box_client_ = root_nh_.serviceClient<object_manipulation_msgs::FindClusterBoundingBox>
00073     (CLUSTER_BOUNDING_BOX_NAME, true);
00074   cluster_bounding_box2_client_ = root_nh_.serviceClient<object_manipulation_msgs::FindClusterBoundingBox2>
00075     (CLUSTER_BOUNDING_BOX2_NAME, true);
00076   cluster_bounding_box_3d_client_ = root_nh_.serviceClient<object_manipulation_msgs::FindClusterBoundingBox>
00077     (CLUSTER_BOUNDING_BOX_3D_NAME, true);
00078   cluster_bounding_box2_3d_client_ = root_nh_.serviceClient<object_manipulation_msgs::FindClusterBoundingBox2>
00079     (CLUSTER_BOUNDING_BOX2_3D_NAME, true);
00080   priv_nh_.param<int>("point_skip_num", point_skip_num_, 1);
00081   priv_nh_.param<int>("collision_box_size", collision_box_size_, 0.003);
00082   priv_nh_.param<double>("table_thickness", table_thickness_, 0.);
00083 }
00084 
00085 bool CollisionMapInterface::connectionsPresent()
00086 {
00087   if ( !ros::service::exists(CLUSTER_BOUNDING_BOX_NAME, true) ) return false;
00088   if ( !ros::service::exists(CLUSTER_BOUNDING_BOX2_NAME, true) ) return false;
00089   return true;
00090 }
00091 
00092 bool CollisionMapInterface::connectionsEstablished(ros::Duration timeout)
00093 {
00094   if (connections_established_) return true;
00095   ros::Time start_time = ros::Time::now();
00096   ros::Duration ping_time = ros::Duration(1.0);
00097   if (timeout >= ros::Duration(0) && ping_time > timeout) ping_time = timeout;
00098   while (!connectionsPresent())
00099   {
00100     ping_time.sleep();
00101     if (!root_nh_.ok()) return false;
00102     if (timeout >= ros::Duration(0) &&
00103         ros::Time::now() - start_time >= timeout) return false;
00104   }
00105   connectServices();
00106   connections_established_ = true;
00107   return true;
00108 }
00109 
00110 void CollisionMapInterface::removeCollisionModel(std::string collision_name)
00111 {
00112   arm_navigation_msgs::CollisionObject reset_object;
00113   reset_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::REMOVE;
00114   reset_object.header.frame_id = "base_link";
00115   reset_object.header.stamp = ros::Time::now();
00116   reset_object.id = collision_name;
00117   collision_object_pub_.publish(reset_object);
00118 }
00119 
00120 void CollisionMapInterface::resetCollisionModels()
00121 {
00122   arm_navigation_msgs::CollisionObject reset_object;
00123   reset_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::REMOVE;
00124   reset_object.header.frame_id = "base_link";
00125   reset_object.header.stamp = ros::Time::now();
00126   reset_object.id = "all";
00127   collision_object_pub_.publish(reset_object);
00128   //collision_object_current_id_ = 0;
00129 }
00130 
00131 void CollisionMapInterface::resetAttachedModels()
00132 {
00133   arm_navigation_msgs::CollisionObject reset_object;
00134   reset_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::REMOVE;
00135   reset_object.header.frame_id = "base_link";
00136   reset_object.header.stamp = ros::Time::now();
00137   reset_object.id = "all";
00138   arm_navigation_msgs::AttachedCollisionObject reset_attached_objects;
00139   reset_attached_objects.object.header.frame_id = "base_link";
00140   reset_attached_objects.object.header.stamp = ros::Time::now();
00141   reset_attached_objects.link_name = "all";
00142   reset_attached_objects.object = reset_object;
00143   attached_object_pub_.publish(reset_attached_objects);
00144 }
00145 
00146 std::string CollisionMapInterface::getNextObjectName()
00147 {
00148   std::ostringstream iss;
00149   iss << collision_object_current_id_++;
00150   if (collision_object_current_id_ > 10000) collision_object_current_id_ = 0;
00151   return "graspable_object_" + iss.str();
00152 }
00153 
00154 void CollisionMapInterface::processCollisionGeometryForTable(const tabletop_object_detector::Table &table,
00155                                                    std::string table_collision_name) 
00156 {
00157   arm_navigation_msgs::CollisionObject table_object;
00158   table_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00159   table_object.header.frame_id = table.pose.header.frame_id;
00160   table_object.header.stamp = ros::Time::now();
00161   table_object.shapes.resize(1);
00162   table_object.poses.resize(1);
00163 
00164   //if the convex hull mesh is available, use that
00165   if(table.convex_hull.triangles.size() != 0)
00166   {
00167     ROS_INFO("using convex hull mesh for table collision geometry");
00168     arm_navigation_msgs::Shape table_shape;
00169     table_shape.type = table_shape.MESH;
00170     table_shape.vertices = table.convex_hull.vertices;
00171     for (size_t i=0; i<table.convex_hull.triangles.size(); i++)
00172     {
00173       table_shape.triangles.push_back( table.convex_hull.triangles.at(i).vertex_indices.at(0) );
00174       table_shape.triangles.push_back( table.convex_hull.triangles.at(i).vertex_indices.at(1) );
00175       table_shape.triangles.push_back( table.convex_hull.triangles.at(i).vertex_indices.at(2) );
00176     }
00177     table_object.shapes[0] = table_shape;
00178     table_object.poses[0] = table.pose.pose;
00179     if(table_thickness_)
00180     {
00181       ROS_INFO("using table_thickness of %.3f", table_thickness_);
00182       tf::Transform T, P;
00183       tf::poseMsgToTF(table.pose.pose, P);
00184       geometry_msgs::Pose shifted_table_pose;
00185       geometry_msgs::Pose shifted_table_offset = object_manipulator::msg::createPoseMsg(tf::Pose(tf::Quaternion::getIdentity(), tf::Vector3(0,0,-table_thickness_)));
00186       tf::poseMsgToTF(shifted_table_offset, T);
00187       tf::poseTFToMsg( P*T, shifted_table_pose);
00188       table_object.shapes.push_back(table_shape);
00189       table_object.poses.push_back(shifted_table_pose);
00190     }
00191   }
00192 
00193   //otherwise, create a box using the old table specification (min/max values)
00194   else
00195   {
00196     ROS_INFO("using box table collision geometry");
00197     table_object.shapes[0].type = arm_navigation_msgs::Shape::BOX;
00198     table_object.shapes[0].dimensions.resize(3);
00199     table_object.shapes[0].dimensions[0] = fabs(table.x_max-table.x_min);
00200     table_object.shapes[0].dimensions[1] = fabs(table.y_max-table.y_min);
00201     if(table_thickness_) table_object.shapes[0].dimensions[2] = table_thickness_;
00202     else table_object.shapes[0].dimensions[2] = 0.01;
00203 
00204     //set the origin of the table object in the middle of the table
00205     tf::Transform table_trans;
00206     tf::poseMsgToTF(table.pose.pose, table_trans);
00207     tf::Transform table_translation;
00208     table_translation.setIdentity();
00209     table_translation.setOrigin( tf::Vector3( (table.x_min + table.x_max)/2.0, (table.y_min + table.y_max)/2.0, 0.0) );
00210     table_trans = table_trans * table_translation;
00211     tf::poseTFToMsg(table_trans, table_object.poses[0]);
00212   }
00213 
00214   table_object.id = table_collision_name;
00215   collision_object_pub_.publish(table_object);
00216 }
00217 
00218 void CollisionMapInterface::processCollisionGeometryForObject
00219   (const household_objects_database_msgs::DatabaseModelPose &model_pose,
00220    std::string &collision_name)
00221 {
00222   arm_navigation_msgs::CollisionObject collision_object;
00223   collision_object.shapes.resize(1);
00224 
00225   if (!getMeshFromDatabasePose(model_pose, collision_object.shapes[0]))
00226   {
00227     throw CollisionMapException("Loading mesh for database object failed");
00228   }
00229   collision_object.header.frame_id = model_pose.pose.header.frame_id;
00230   collision_object.header.stamp = ros::Time::now();
00231   collision_object.poses.push_back(model_pose.pose.pose);
00232   
00233   collision_object.shapes[0].type = arm_navigation_msgs::Shape::MESH;
00234   collision_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00235   collision_name = getNextObjectName();
00236   collision_object.id = collision_name;
00237   collision_object_pub_.publish(collision_object);
00238 }
00239 
00240 
00241 void CollisionMapInterface::processCollisionGeometryForObjectAsBoundingBox
00242   (const household_objects_database_msgs::DatabaseModelPose &model_pose,
00243    std::string &collision_name)
00244 {
00245   arm_navigation_msgs::Shape model_shape;
00246   if (!getMeshFromDatabasePose(model_pose, model_shape))
00247   {
00248     throw CollisionMapException("Loading mesh for database object failed");
00249   }
00250   sensor_msgs::PointCloud cluster;
00251   cluster.header = model_pose.pose.header;
00252   for (size_t i=0; i<model_shape.vertices.size(); i++)
00253   {
00254     geometry_msgs::Point32 point;
00255     point.x = model_shape.vertices[i].x;
00256     point.y = model_shape.vertices[i].y;
00257     point.z = model_shape.vertices[i].z;
00258     cluster.points.push_back(point);
00259   }
00260   object_manipulation_msgs::ClusterBoundingBox box;
00261   getClusterBoundingBox(cluster, box.pose_stamped, box.dimensions);
00262 
00263   arm_navigation_msgs::CollisionObject collision_object;
00264   collision_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00265 
00266   collision_name = getNextObjectName();
00267   collision_object.id = collision_name;
00268 
00269   collision_object.header.frame_id = model_pose.pose.header.frame_id;
00270   collision_object.header.stamp = ros::Time::now();
00271   
00272   arm_navigation_msgs::Shape shape;
00273   shape.type = arm_navigation_msgs::Shape::BOX;
00274   shape.dimensions.resize(3);
00275   shape.dimensions[0] = box.dimensions.x;
00276   shape.dimensions[1] = box.dimensions.y;
00277   shape.dimensions[2] = box.dimensions.z;
00278   collision_object.shapes.push_back(shape);
00279 
00280   //multiply bbox trans by object trans
00281   tf::Transform model_trans;
00282   tf::poseMsgToTF(model_pose.pose.pose, model_trans);
00283   tf::Transform box_trans;
00284   tf::poseMsgToTF(box.pose_stamped.pose, box_trans);
00285   tf::Transform total_trans = model_trans * box_trans;
00286 
00287   geometry_msgs::Pose total_pose;
00288   tf::poseTFToMsg(total_trans, total_pose);
00289   collision_object.poses.push_back(total_pose);
00290 
00291   collision_object_pub_.publish(collision_object);
00292 }
00293 
00294 void 
00295 CollisionMapInterface::processCollisionGeometryForBoundingBox(const object_manipulation_msgs::ClusterBoundingBox &box, 
00296                                                               std::string &collision_name)
00297 {
00298   ROS_INFO("Adding bounding box with dimensions %f %f %f to collision map", 
00299            box.dimensions.x, box.dimensions.y, box.dimensions.z);
00300 
00301   arm_navigation_msgs::CollisionObject collision_object;
00302   collision_object.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00303 
00304   collision_name = getNextObjectName();
00305   collision_object.id = collision_name;
00306 
00307   collision_object.header.frame_id = box.pose_stamped.header.frame_id;
00308   collision_object.header.stamp = ros::Time::now();
00309   
00310   arm_navigation_msgs::Shape shape;
00311   shape.type = arm_navigation_msgs::Shape::BOX;
00312   shape.dimensions.resize(3);
00313   shape.dimensions[0] = box.dimensions.x;
00314   shape.dimensions[1] = box.dimensions.y;
00315   shape.dimensions[2] = box.dimensions.z;
00316   collision_object.shapes.push_back(shape);
00317   collision_object.poses.push_back(box.pose_stamped.pose);
00318 
00319   collision_object_pub_.publish(collision_object);
00320 }
00321 
00322 void CollisionMapInterface::processCollisionGeometryForCluster(const sensor_msgs::PointCloud &cluster,
00323                                                                std::string &collision_name, float collision_size)
00324 {
00325   ROS_INFO("Adding cluster with %u points to collision map", (unsigned int)cluster.points.size()); 
00326 
00327   arm_navigation_msgs::CollisionObject many_boxes;
00328   many_boxes.operation.operation = arm_navigation_msgs::CollisionObjectOperation::ADD;
00329   many_boxes.header = cluster.header;
00330   many_boxes.header.stamp = ros::Time::now();
00331   unsigned int num_to_use = (unsigned int)(cluster.points.size()/point_skip_num_);
00332   many_boxes.shapes.resize(num_to_use);
00333   many_boxes.poses.resize(num_to_use);
00334 
00335   if(collision_size < 0)
00336     collision_size = collision_box_size_;
00337 
00338   for(unsigned int i = 0; i < num_to_use; i++) {
00339     arm_navigation_msgs::Shape shape;
00340     shape.type = arm_navigation_msgs::Shape::BOX;
00341     shape.dimensions.resize(3);
00342     shape.dimensions[0] = collision_size;
00343     shape.dimensions[1] = collision_size;
00344     shape.dimensions[2] = collision_size;
00345     many_boxes.shapes[i]=shape;
00346     geometry_msgs::Pose pose;
00347     pose.position.x = cluster.points[i*point_skip_num_].x;
00348     pose.position.y = cluster.points[i*point_skip_num_].y;
00349     pose.position.z = cluster.points[i*point_skip_num_].z;
00350     pose.orientation.x = 0;
00351     pose.orientation.y = 0;
00352     pose.orientation.z = 0;
00353     pose.orientation.w = 1;
00354     many_boxes.poses[i] = pose;
00355   }
00356 
00357   collision_name = getNextObjectName();
00358   //use this name for the collision map
00359   many_boxes.id = collision_name;
00360   collision_object_pub_.publish(many_boxes);
00361 }
00362 
00363 bool CollisionMapInterface::getMeshFromDatabasePose(const household_objects_database_msgs::DatabaseModelPose &model_pose,
00364                                                     arm_navigation_msgs::Shape& mesh) 
00365 {
00366   static bool service_initialized = false;
00367   if (!service_initialized)
00368   {    
00369     std::string get_model_mesh_srv_name;
00370     priv_nh_.param<std::string>("get_model_mesh_srv", get_model_mesh_srv_name, "get_model_mesh_srv");
00371     ros::Time start_time = ros::Time::now();
00372     while ( !ros::service::waitForService(get_model_mesh_srv_name, ros::Duration(2.0)) ) 
00373     {
00374       ROS_INFO("Waiting for %s service to come up", get_model_mesh_srv_name.c_str());
00375       if (!root_nh_.ok() || ros::Time::now() - start_time >= ros::Duration(5.0))
00376       {
00377         return false;
00378       }
00379     }
00380     get_model_mesh_srv_ = root_nh_.serviceClient<household_objects_database_msgs::GetModelMesh>
00381       (get_model_mesh_srv_name, false);
00382     service_initialized = true;
00383   }
00384   household_objects_database_msgs::GetModelMesh get_mesh;
00385   get_mesh.request.model_id = model_pose.model_id;
00386   if ( !get_model_mesh_srv_.call(get_mesh) )
00387   {
00388     ROS_ERROR("Get model mesh service service call failed altogether");
00389     return false;
00390   }
00391   else if (get_mesh.response.return_code.code != get_mesh.response.return_code.SUCCESS )
00392   {
00393     ROS_ERROR("Get model mesh service returned an error");
00394     return false;
00395   }
00396   //translate to arm_navigation_msgs::Shape 
00397   mesh.vertices = get_mesh.response.mesh.vertices;
00398   mesh.triangles.clear();
00399   for (size_t i=0; i<get_mesh.response.mesh.triangles.size(); i++)
00400   {
00401     mesh.triangles.push_back( get_mesh.response.mesh.triangles.at(i).vertex_indices.at(0) );
00402     mesh.triangles.push_back( get_mesh.response.mesh.triangles.at(i).vertex_indices.at(1) );
00403     mesh.triangles.push_back( get_mesh.response.mesh.triangles.at(i).vertex_indices.at(2) );
00404   }
00405   return true;
00406 }
00407 
00408 void CollisionMapInterface::getClusterBoundingBox(const sensor_msgs::PointCloud &cluster,
00409                                                   geometry_msgs::PoseStamped &pose_stamped, 
00410                                                   geometry_msgs::Vector3 &dimensions)
00411 {
00412   object_manipulation_msgs::FindClusterBoundingBox srv;
00413   srv.request.cluster = cluster;
00414   if (!cluster_bounding_box_client_.call(srv.request, srv.response))
00415   {
00416     ROS_ERROR("Failed to call cluster bounding box client");
00417     throw CollisionMapException("Failed to call cluster bounding box client");
00418   }
00419   pose_stamped = srv.response.pose;
00420   dimensions = srv.response.box_dims;
00421   if (dimensions.x == 0.0 && dimensions.y == 0.0 && dimensions.z == 0.0)
00422   {
00423     ROS_ERROR("Cluster bounding box client returned an error (0.0 bounding box)");
00424     throw CollisionMapException("Bounding box computation failed");  
00425   }
00426 }
00427 
00428 void CollisionMapInterface::getClusterBoundingBox(const sensor_msgs::PointCloud2 &cluster,
00429                                                   geometry_msgs::PoseStamped &pose_stamped, 
00430                                                   geometry_msgs::Vector3 &dimensions)
00431 {
00432   object_manipulation_msgs::FindClusterBoundingBox2 srv;
00433   srv.request.cluster = cluster;
00434   if (!cluster_bounding_box2_client_.call(srv.request, srv.response))
00435   {
00436     ROS_ERROR("Failed to call cluster bounding box client");
00437     throw CollisionMapException("Failed to call cluster bounding box client");
00438   }
00439   pose_stamped = srv.response.pose;
00440   dimensions = srv.response.box_dims;
00441   if (dimensions.x == 0.0 && dimensions.y == 0.0 && dimensions.z == 0.0)
00442   {
00443     ROS_ERROR("Cluster bounding box 2 client returned an error (0.0 bounding box)");
00444     throw CollisionMapException("Bounding box computation failed");  
00445   }
00446 }
00447 
00448 void CollisionMapInterface::getClusterBoundingBox3D(const sensor_msgs::PointCloud &cluster,
00449                                                   geometry_msgs::PoseStamped &pose_stamped, 
00450                                                   geometry_msgs::Vector3 &dimensions)
00451 {
00452   object_manipulation_msgs::FindClusterBoundingBox srv;
00453   srv.request.cluster = cluster;
00454   if (!cluster_bounding_box_3d_client_.call(srv.request, srv.response))
00455   {
00456     ROS_ERROR("Failed to call cluster bounding box client");
00457     throw CollisionMapException("Failed to call cluster bounding box client");
00458   }
00459   pose_stamped = srv.response.pose;
00460   dimensions = srv.response.box_dims;
00461   if (dimensions.x == 0.0 && dimensions.y == 0.0 && dimensions.z == 0.0)
00462   {
00463     ROS_ERROR("Cluster bounding box 3d client returned an error (0.0 bounding box)");
00464     throw CollisionMapException("Bounding box computation failed");  
00465   }
00466 }
00467 
00468 void CollisionMapInterface::getClusterBoundingBox3D(const sensor_msgs::PointCloud2 &cluster,
00469                                                   geometry_msgs::PoseStamped &pose_stamped, 
00470                                                   geometry_msgs::Vector3 &dimensions)
00471 {
00472   object_manipulation_msgs::FindClusterBoundingBox2 srv;
00473   srv.request.cluster = cluster;
00474   if (!cluster_bounding_box2_3d_client_.call(srv.request, srv.response))
00475   {
00476     ROS_ERROR("Failed to call cluster bounding box client");
00477     throw CollisionMapException("Failed to call cluster bounding box client");
00478   }
00479   pose_stamped = srv.response.pose;
00480   dimensions = srv.response.box_dims;
00481   if (dimensions.x == 0.0 && dimensions.y == 0.0 && dimensions.z == 0.0)
00482   {
00483     ROS_ERROR("Cluster bounding box 2 3d client returned an error (0.0 bounding box)");
00484     throw CollisionMapException("Bounding box computation failed");  
00485   }
00486 }
00487 
00488 
00490 bool CollisionMapInterface::extendBoundingBoxZToTable(const tabletop_object_detector::Table &table,
00491                                                       geometry_msgs::PoseStamped &pose_stamped, 
00492                                                       geometry_msgs::Vector3 &dimensions)
00493 {
00494   if (table.pose.header.frame_id != pose_stamped.header.frame_id)
00495   {
00496     ROS_INFO("cannot extend bbox to table, they are not in the same frame");
00497     return false;
00498   }
00499 
00500   //get the distance from the box to the table
00501   tf::Vector3 table_location(table.pose.pose.position.x,
00502                            table.pose.pose.position.y,
00503                            table.pose.pose.position.z);
00504   tf::Vector3 bbox_location(pose_stamped.pose.position.x, 
00505                           pose_stamped.pose.position.y, 
00506                           pose_stamped.pose.position.z);
00507   tf::Vector3 table_to_bbox = bbox_location - table_location;
00508   tf::Transform table_trans;
00509   tf::poseMsgToTF(table.pose.pose, table_trans);
00510   tf::Vector3 table_z = table_trans.getBasis().getColumn(2);
00511   ROS_INFO("Table z: %f %f %f in frame %s", 
00512            table_z.getX(), table_z.getY(), table_z.getZ(), table.pose.header.frame_id.c_str());
00513   double box_to_table_distance = table_to_bbox.dot(table_z);
00514   ROS_INFO("Table distance: %f", box_to_table_distance);
00515 
00516   //now we actually make the assumptions that the z axes are close to each other
00517   //as doing an actual computation was just too hard
00518   tf::Transform bbox_trans;
00519   tf::poseMsgToTF(pose_stamped.pose, bbox_trans);
00520   tf::Vector3 bbox_z = bbox_trans.getBasis().getColumn(2);
00521   if (fabs(bbox_z.dot(table_z)) < 0.9848) //10 degrees
00522   { 
00523     ROS_INFO("cannot extend bbox to table; z axes do not coincide");
00524     return false;
00525   }
00526   
00527   double z_to_table = box_to_table_distance;
00528   ROS_INFO("z_to_table: %f", z_to_table);
00529   if ( z_to_table < 0.005 || z_to_table > 0.3)
00530   {
00531     ROS_INFO("cannot extend bbox to table; getting z equal to %f", z_to_table);
00532     return false;
00533   }
00534   ROS_INFO("Old z: %f", dimensions.z);
00535   double new_z = dimensions.z/2.0 + z_to_table;
00536   ROS_INFO("New z: %f", new_z);
00537   pose_stamped.pose.position.z = pose_stamped.pose.position.z + (dimensions.z/2.0) - (new_z/2.0);
00538   dimensions.z = new_z;
00539   return true;
00540 }
00541 
00542 
00543 } //namespace tabletop_collision_map_processing


tabletop_collision_map_processing
Author(s): Matei Ciocarlie
autogenerated on Mon Oct 6 2014 11:47:36