world.cpp
Go to the documentation of this file.
00001 #include "fetch_pbd_interaction/world.h"
00002 
00003 namespace fetch_pbd_interaction {
00004 
00005 World::World(ros::NodeHandle n, ros::NodeHandle pn, 
00006               const std::string grasp_suggestion_service,
00007               const std::string& segmentation_service_name, const std::string& segmented_objects_topic_name,
00008               const std::string& segmented_table_topic_name, const std::string& planning_scene_topic, 
00009               const float&  obj_similar_distance_threshold, const float&  obj_add_distance_threshold,
00010               const float&  obj_nearest_distance_threshold, 
00011               const float& obj_distance_zero_clamp, const float& text_h, 
00012               const float&  surface_h, const float&  text_off, 
00013               const std::string& base_frame_name)
00014               : im_server("/fetch_pbd/world_objects"){
00015   // Two objects must be closer than this to be considered 'the same'.
00016   obj_similar_dist_threshold = obj_similar_distance_threshold;
00017 
00018   // When adding objects, if they are closer than this they'll replace one
00019   // another.
00020   obj_add_dist_threshold = obj_add_distance_threshold;
00021 
00022   // How close to 'nearest' object something must be to be counted as
00023   // 'near' it.
00024   obj_nearest_dist_threshold = obj_nearest_distance_threshold;
00025 
00026   // Landmark distances below this will be clamped to zero.
00027   obj_dist_zero_clamp = obj_distance_zero_clamp;
00028 
00029   // Scales
00030   text_height = text_h;
00031   surface_height = surface_h;  // 0.01 == 1cm (i think)
00032   text_offset = text_off;  // how high objects' labels are above them.
00033 
00034   // colors
00035   color_obj = std_msgs::ColorRGBA();
00036   color_obj.r = 0.2;
00037   color_obj.g = 0.8;
00038   color_obj.b = 0.0;
00039   color_obj.a = 0.6; // not yet a param
00040   std_msgs::ColorRGBA color_surface = std_msgs::ColorRGBA(); // not yet a param
00041   color_surface.r = 0.8;
00042   color_surface.g = 0.0;
00043   color_surface.b = 0.4;
00044   color_surface.a = 0.4; // not yet a param
00045   std_msgs::ColorRGBA color_text = std_msgs::ColorRGBA(); // not yet a param
00046   color_text.r = 0.0;
00047   color_text.g = 0.0;
00048   color_text.b = 0.0;
00049   color_text.a = 0.5; // not yet a param
00050 
00051   base_frame = base_frame_name;
00052   marker_duration = ros::Duration(0.0);
00053   segmented_objects_topic = segmented_objects_topic_name;
00054   
00055   scale_text = geometry_msgs::Vector3();
00056   scale_text.z = text_height;
00057 
00058   add_grasp_pub = n.advertise<fetch_pbd_interaction::Landmark>("/fetch_pbd/add_grasp", 100);
00059   world_update_pub = n.advertise<fetch_pbd_interaction::WorldState>("/fetch_pbd/world_updates", 100);
00060   segmentation_service_client =  n.serviceClient<std_srvs::Empty>(segmentation_service_name);
00061   nearest_object_service = n.advertiseService("/fetch_pbd/get_nearest_object", &World::getNearestObjectCallback, this);
00062   object_list_service = n.advertiseService("/fetch_pbd/get_object_list", &World::getObjectListCallback, this);
00063   similar_object_service = n.advertiseService("/fetch_pbd/get_most_similar_object", &World::getMostSimilarObjectCallback, this);
00064   object_from_name_service = n.advertiseService("/fetch_pbd/get_object_from_name", &World::getObjectFromNameCallback, this);
00065   clear_world_objects_service = n.advertiseService("/fetch_pbd/clear_world_objects", &World::clearObjectsCallback, this);
00066   update_world_service = n.advertiseService("/fetch_pbd/update_world", &World::updateWorldCallback, this);
00067   // segmented_objects_topic = segmented_objects_topic_name;
00068   table_subscriber = n.subscribe(segmented_table_topic_name, 1, &World::tablePositionUpdateCallback, this);
00069   // object_subscriber = n.subscribe(segmented_objects_topic_name, 1, &World::objectsUpdateCallback, this);
00070   has_surface = false;
00071   planning_scene_diff_publisher = n.advertise<moveit_msgs::PlanningScene>(planning_scene_topic, 1);
00072   menu_handler = interactive_markers::MenuHandler();
00073   menu_handler.insert("Remove from scene", boost::bind(&World::removeObject, this, _1));
00074   if (grasp_suggestion_service != ""){
00075     menu_handler.insert("Add grasp", boost::bind(&World::addGrasp, this, _1));
00076   }
00077 
00078 }
00079 
00080 World::~World() {}
00081 
00082 // Public instance methods
00083 void World::update() {
00084   mutex.lock();
00085   if (hasObjects()) {
00086     for (int i = 0; i < objects.size(); i++){
00087       publishTfPose(objects[i].object.pose,
00088                     objects[i].getName(),
00089                     base_frame);
00090     }
00091   }
00092   mutex.unlock();
00093 }
00094 
00095 // Private static methods
00096 void World::pc2ToMarker(sensor_msgs::PointCloud2 pc2, int index, 
00097                                   ros::Duration duration, std::string output_frame,
00098                                   visualization_msgs::Marker* pc2_marker_points, visualization_msgs::Marker* pc2_marker_sphere_list){
00099   pc2_marker_points->type = visualization_msgs::Marker::POINTS;
00100   pc2_marker_points->id = index;
00101   pc2_marker_points->lifetime=duration;
00102   pc2_marker_points->scale.x = 0.005;
00103   pc2_marker_points->scale.y = 0.005;
00104   pc2_marker_points->scale.z = 0.005;
00105   pc2_marker_points->header.frame_id = pc2.header.frame_id;
00106   pc2_marker_points->pose.orientation.w = 1.0;
00107 
00108   pc2_marker_sphere_list->type = visualization_msgs::Marker::SPHERE_LIST;
00109   pc2_marker_sphere_list->id = index + 500;
00110   pc2_marker_sphere_list->lifetime=duration;
00111   pc2_marker_sphere_list->scale.x = 0.007;
00112   pc2_marker_sphere_list->scale.y = 0.007;
00113   pc2_marker_sphere_list->scale.z = 0.007;
00114   pc2_marker_sphere_list->header.frame_id = pc2.header.frame_id;
00115   pc2_marker_sphere_list->pose.orientation.w = 1.0;
00116 
00117   pcl::PointCloud<pcl::PointXYZRGB> pc;
00118   // sensor_msgs::PointCloud2 transformed_cloud_msg;
00119   // tf::TransformListener tf_listener;
00120   // tf::StampedTransform transform;
00121   // tf_listener.waitForTransform(output_frame, pc2.header.frame_id, ros::Time(0), ros::Duration(3.0));
00122   // ROS_INFO("Got transform for point cloud.");
00123   // tf_listener.lookupTransform(output_frame, pc2.header.frame_id, ros::Time(0), transform);
00124   // pcl_ros::transformPointCloud(output_frame, transform, pc2, transformed_cloud_msg);
00125  
00126   pcl::fromROSMsg(pc2, pc);
00127   std::vector<geometry_msgs::Point> points_msgs;
00128   std::vector<std_msgs::ColorRGBA> colors_msgs;
00129   std::vector<std_msgs::ColorRGBA> no_colors_msgs;
00130 
00131   for (int i=0; i < pc.points.size(); i++){
00132     pcl::PointXYZRGB point = pc.points[i];
00133     geometry_msgs::Point point_msg;
00134     std_msgs::ColorRGBA color_msg;
00135 
00136     point_msg.x = point.x;
00137     point_msg.y = point.y;
00138     point_msg.z = point.z;
00139 
00140     color_msg.r = point.r/255.0;
00141     color_msg.g = point.g/255.0;
00142     color_msg.b = point.b/255.0;
00143     color_msg.a = 1.0;
00144 
00145     points_msgs.push_back(point_msg);
00146     colors_msgs.push_back(color_msg);
00147 
00148     color_msg.a = 0.0;
00149     no_colors_msgs.push_back(color_msg);
00150   }
00151 
00152   pc2_marker_points->colors = colors_msgs;
00153   pc2_marker_points->points = points_msgs;
00154   pc2_marker_sphere_list->points = points_msgs;
00155   pc2_marker_sphere_list->colors = no_colors_msgs;
00156 
00157   return;
00158 }
00159 
00160 float World::objectDissimilarity(fetch_pbd_interaction::Landmark obj1, fetch_pbd_interaction::Landmark obj2){
00161   float dis;
00162 
00163   geometry_msgs::Vector3 d1 = obj1.dimensions;
00164   geometry_msgs::Vector3 d2 = obj2.dimensions;
00165   dis = sqrt(pow(d1.x - d2.x,2) + pow(d1.y - d2.y,2) + pow(d1.z - d2.z,2));
00166 
00167   return dis;
00168 }
00169 
00170 float World::poseDistance(geometry_msgs::Pose pose1, geometry_msgs::Pose pose2, bool is_on_table /*=true*/){
00171   float dist;
00172   geometry_msgs::Point p1 = pose1.position;
00173   geometry_msgs::Point p2 = pose2.position;
00174   if (is_on_table){
00175     dist = sqrt(pow(p1.x - p2.x,2) + pow(p1.y - p2.y,2));
00176   }
00177   else {
00178     dist = sqrt(pow(p1.x - p2.x,2) + pow(p1.y - p2.y,2) + pow(p1.z - p2.z,2));
00179   }
00180   return dist;
00181 }
00182 
00183 visualization_msgs::InteractiveMarker World::getSurfaceMarker(geometry_msgs::Pose pose, geometry_msgs::Vector3 dimensions){
00184   visualization_msgs::InteractiveMarker int_marker;
00185   int_marker.name = "surface";
00186   int_marker.header.frame_id = base_frame;
00187   int_marker.pose = pose;
00188   int_marker.scale = 1.0;
00189   visualization_msgs::Marker marker;
00190   marker.type = visualization_msgs::Marker::CUBE;
00191   marker.id = 2000;
00192   marker.lifetime = marker_duration;
00193   marker.scale = dimensions;
00194   marker.color = color_surface;
00195 
00196 
00197   visualization_msgs::InteractiveMarkerControl button_control;
00198   button_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::NONE;         
00199   button_control.always_visible = true;
00200   button_control.markers.push_back(marker);
00201   int_marker.controls.push_back(button_control);
00202   return int_marker;
00203 }
00204 
00205 // Private instance methods
00206 void World::worldChanged(){
00207   fetch_pbd_interaction::WorldState new_state;
00208   new_state.object_list = getObjectList();
00209   update();
00210   world_update_pub.publish(new_state);
00211 }
00212 
00213 std::vector<fetch_pbd_interaction::Landmark> World::getObjectList(){
00214   std::vector<fetch_pbd_interaction::Landmark> object_list;
00215   for (int i=0; i < objects.size(); i++){
00216     object_list.push_back(objects[i].object);
00217   }
00218   if (object_list.size() == 0){
00219     ROS_WARN("No objects detected");
00220   }
00221   return object_list;
00222 }
00223 
00224 bool World::getMostSimilarObjectCallback(fetch_pbd_interaction::GetMostSimilarObject::Request& req,
00225                  fetch_pbd_interaction::GetMostSimilarObject::Response& resp){
00226   mutex.lock();
00227   float best_dist = 10000.0; //just a big number
00228   fetch_pbd_interaction::Landmark chosen_object;
00229   bool success = false;
00230   std::vector<fetch_pbd_interaction::Landmark> object_list = getObjectList();
00231   for (int i=0; i < object_list.size(); i++){
00232     float dist = World::objectDissimilarity(object_list[i], req.original_object);
00233     if (dist < best_dist){
00234       best_dist = dist;
00235       chosen_object = object_list[i];
00236       success = true;
00237     }
00238   }
00239   if (!success){
00240     ROS_INFO("Did not find a similar object.");
00241     resp.has_similar = false;
00242   }
00243   else{
00244     ROS_INFO("Landmark dissimilarity is --- %f", best_dist);
00245     if (best_dist > obj_similar_dist_threshold){
00246       ROS_INFO("Found an object but it is not similar enough.");
00247       resp.has_similar = false;
00248     }
00249     else {
00250       ROS_INFO("Most similar object is: %s", chosen_object.name.c_str());
00251       resp.has_similar = true;
00252       resp.similar_object = chosen_object;
00253     }
00254   }
00255   mutex.unlock();
00256   return true;
00257 }
00258 
00259 bool World::getObjectListCallback(fetch_pbd_interaction::GetObjectList::Request& req, 
00260                   fetch_pbd_interaction::GetObjectList::Response& resp){
00261   update();
00262   resp.object_list = getObjectList();
00263   return true;
00264 }
00265 
00266 bool World::updateWorldCallback(fetch_pbd_interaction::GetObjectList::Request& req, 
00267                   fetch_pbd_interaction::GetObjectList::Response& resp){
00268   recordObjectPose();
00269   resp.object_list = getObjectList();
00270   return true;
00271 }
00272 
00273 bool World::getObjectFromNameCallback(fetch_pbd_interaction::GetObjectFromName::Request& req, 
00274                   fetch_pbd_interaction::GetObjectFromName::Response& resp){
00275   std::vector<fetch_pbd_interaction::Landmark> object_list = getObjectList();
00276   for (int i=0; i < object_list.size(); i++){
00277     if (object_list[i].name == req.ref_name){
00278       resp.has_object = true;
00279       resp.obj = object_list[i];
00280       return true;
00281     }
00282   }
00283   resp.has_object = false;
00284   return true;
00285 }
00286 
00287 bool World::hasObjects(){
00288   if (objects.size() > 0){
00289     return true; 
00290   }
00291   else {
00292     return false;
00293   }
00294 }
00295 
00296 void World::recordObjectPose(){
00297   ROS_INFO("Waiting for segmentation service");
00298   try
00299   {
00300     std_srvs::Empty srv;
00301     segmentation_service_client.call(srv);
00302     rail_manipulation_msgs::SegmentedObjectListConstPtr msg = ros::topic::waitForMessage<rail_manipulation_msgs::SegmentedObjectList>(segmented_objects_topic);
00303     objectsUpdateCallback(msg);
00304   }
00305   catch ( ros::Exception &e )
00306   {
00307     ROS_ERROR("Error occured: %s ", e.what());
00308   }
00309 }
00310 
00311 void World::objectsUpdateCallback(const rail_manipulation_msgs::SegmentedObjectListConstPtr& msg){
00312   // resetObjects();
00313   for (int i=0; i < objects.size(); i++){
00314     im_server.erase(objects[i].int_marker.name);
00315     im_server.applyChanges();
00316   }
00317   objects.clear();
00318   mutex.lock();
00319   bool added = false;
00320   for (int i=0; i < msg->objects.size(); i++){
00321     if (msg->objects[i].point_cloud.height == 0 || msg->objects[i].point_cloud.width == 0){
00322       ROS_WARN("Empty point cloud");
00323     }
00324     sensor_msgs::PointCloud2 pc2 = msg->objects[i].point_cloud;
00325     geometry_msgs::Vector3 dimensions;
00326     geometry_msgs::Pose pose;
00327     getBoundingBox(pc2, &dimensions, &pose);
00328     added = addNewObject(pose, dimensions, pc2);
00329   }
00330   if (!added){
00331     ROS_WARN("Failed to add object");
00332   }
00333 
00334   mutex.unlock();
00335   worldChanged();
00336 }
00337 
00338 void World::getBoundingBox(sensor_msgs::PointCloud2 pc2, geometry_msgs::Vector3* dimensions, geometry_msgs::Pose* pose){
00339   pcl::PointCloud<pcl::PointXYZRGB> cloud;
00340   // sensor_msgs::PointCloud2 transformed_cloud_msg;
00341   // tf::TransformListener tf_listener;
00342   // tf::StampedTransform transform;
00343   // tf_listener.waitForTransform(base_frame, pc2.header.frame_id, ros::Time(0), ros::Duration(3.0));
00344   // ROS_INFO("Got transform for point cloud.");
00345   // tf_listener.lookupTransform(base_frame, pc2.header.frame_id, ros::Time(0), transform);
00346   // pcl_ros::transformPointCloud(base_frame, transform, pc2, transformed_cloud_msg);
00347   bool switched = false;
00348   pcl::fromROSMsg(pc2, cloud);
00349 
00350   pcl::PointCloud<pcl::PointXYZRGB>::Ptr projected(new pcl::PointCloud<pcl::PointXYZRGB>(cloud));
00351   for (size_t i = 0; i < projected->points.size(); ++i) {
00352     pcl::PointXYZRGB& point = projected->at(i);
00353     point.z = 0;
00354   }
00355   // Compute PCA.
00356   pcl::PCA<pcl::PointXYZRGB> pca(true);
00357   pca.setInputCloud(projected);
00358   // Get eigenvectors.
00359   Eigen::Matrix3f eigenvectors = pca.getEigenVectors();
00360   // Because we projected points on the XY plane, we add in the Z vector as the
00361   // 3rd eigenvector.
00362   eigenvectors.col(2) = eigenvectors.col(0).cross(eigenvectors.col(1));
00363   if(eigenvectors.col(2)(2) < 0.0){
00364     //switch axes
00365     switched = true;
00366     Eigen::Matrix3f eigenvectors_temp;
00367     eigenvectors_temp.col(0) = eigenvectors.col(1);
00368     eigenvectors_temp.col(1) = eigenvectors.col(0);
00369     eigenvectors_temp.col(2) = eigenvectors_temp.col(0).cross(eigenvectors_temp.col(1));
00370     eigenvectors = eigenvectors_temp;
00371   }
00372 
00373   Eigen::Quaternionf q1(eigenvectors);
00374   // Find min/max x and y, based on the points in eigenspace.
00375   pcl::PointCloud<pcl::PointXYZRGB>::Ptr eigen_projected(
00376       new pcl::PointCloud<pcl::PointXYZRGB>(cloud));
00377   pca.project(cloud, *eigen_projected);
00378   pcl::PointXYZRGB eigen_min;
00379   pcl::PointXYZRGB eigen_max;
00380   pcl::getMinMax3D(*eigen_projected, eigen_min, eigen_max);
00381   double x_length = eigen_max.x - eigen_min.x;
00382   double y_length = eigen_max.y - eigen_min.y;
00383   // The points in eigenspace all have z values of 0. Get min/max z from the
00384   // original point cloud data.
00385   pcl::PointXYZRGB cloud_min;
00386   pcl::PointXYZRGB cloud_max;
00387   pcl::getMinMax3D(cloud, cloud_min, cloud_max);
00388   double z_length = cloud_max.z - cloud_min.z;
00389   // Compute midpoint, defined as the midpoint between the minimum and maximum
00390   // points, in x, y, and z directions. The centroid is an average that depends
00391   // on the density of points, which doesn't give you the geometric center of
00392   // the point cloud.
00393   pcl::PointXYZRGB eigen_center;
00394   eigen_center.x = eigen_min.x + x_length / 2;
00395   eigen_center.y = eigen_min.y + y_length / 2;
00396   eigen_center.z = 0;
00397   pcl::PointXYZRGB center;
00398   pca.reconstruct(eigen_center, center);
00399   center.z = z_length / 2 + cloud_min.z;
00400   // Output midpoint.
00401   pose->position.x = center.x;
00402   pose->position.y = center.y;
00403   pose->position.z = center.z;
00404   pose->orientation.w = q1.w();
00405   pose->orientation.x = q1.x();
00406   pose->orientation.y = q1.y();
00407   pose->orientation.z = q1.z();
00408   // Output dimensions.
00409   if (!switched){
00410     dimensions->x = x_length;
00411     dimensions->y = y_length;
00412     dimensions->z = z_length;
00413   }
00414   else {
00415     dimensions->x = y_length;
00416     dimensions->y = x_length;
00417     dimensions->z = z_length;
00418   }
00419 }
00420 
00421 void World::tablePositionUpdateCallback(const rail_manipulation_msgs::SegmentedObjectPtr& msg){
00422   // resetObjects();
00423   removeSurfaceMarker();
00424   // objects.clear();
00425   if (msg->point_cloud.height == 0 || msg->point_cloud.width == 0){
00426     ROS_WARN("No table detected");
00427     has_surface = false;
00428     return;
00429   }
00430   ROS_INFO("Table detected");
00431   has_surface = true;
00432   sensor_msgs::PointCloud2 pc2 = msg->point_cloud;
00433   geometry_msgs::Vector3 dimensions;
00434   geometry_msgs::Pose pose;
00435   pose.position.x = msg->center.x;
00436   pose.position.y = msg->center.y;
00437   pose.position.z = msg->center.z;
00438   pose.orientation.w = 1.0;
00439   dimensions.x = msg->depth;
00440   dimensions.y = msg->width;
00441   dimensions.z = msg->height;
00442   // getBoundingBox(pc2, &dimensions, &pose);
00443   ROS_INFO("Adding table marker");
00444   visualization_msgs::InteractiveMarker surface = getSurfaceMarker(pose, dimensions);
00445   im_server.insert(surface);
00446   im_server.setCallback(surface.name, boost::bind(&World::markerFeedbackCallback, this, _1));
00447   im_server.applyChanges();
00448   ROS_INFO("Adding surface to planning scene");
00449   addSurfaceToPlanningScene(pose, dimensions);
00450   ROS_INFO("Added surface to planning scene");
00451 }
00452 
00453 bool World::clearObjectsCallback(std_srvs::Empty::Request& req, 
00454                   std_srvs::Empty::Response& resp){
00455   clearObjects();
00456   return true;
00457 }
00458 
00459 void World::clearObjects(){
00460   ROS_INFO("Clearing objects");
00461   resetObjects();
00462   removeSurfaceMarker();
00463   worldChanged();
00464   removeSurfaceFromPlanningScene();
00465 }
00466 
00467 bool World::getNearestObjectCallback(fetch_pbd_interaction::GetNearestObject::Request& req, 
00468                   fetch_pbd_interaction::GetNearestObject::Response& resp){
00469   geometry_msgs::PoseStamped arm_pose;
00470   ROS_INFO("Transform from frame: %s to %s", base_frame.c_str(), req.pose.header.frame_id.c_str());
00471   tf_listener.waitForTransform(base_frame, req.pose.header.frame_id,
00472                               ros::Time::now(), ros::Duration(5.0));
00473   tf_listener.transformPose(base_frame, req.pose, arm_pose);
00474   std::vector<float> distances;
00475   for (int i=0; i < objects.size(); i++){
00476     float dist = poseDistance(objects[i].object.pose, arm_pose.pose);
00477     distances.push_back(dist);
00478   }
00479 
00480   if (distances.size() > 0){
00481     float min = *std::min_element(distances.begin(), distances.end());
00482     if (min < obj_nearest_dist_threshold){
00483       for (int i=0; i < distances.size(); i++){
00484         if (distances[i] == min) {
00485           resp.has_nearest = true;
00486           resp.nearest_object = objects[i].object;
00487           return true;
00488         }
00489       }
00490     }
00491   }
00492   else {
00493     ROS_INFO("No objects");
00494   }
00495   resp.has_nearest = false;
00496   return true;
00497 }
00498 
00499 void World::markerFeedbackCallback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback){
00500   ;
00501   //TODO(sarah): why do we need this? 
00502 }
00503 
00504 void World::resetObjects(){
00505   mutex.lock();
00506   ROS_INFO("Resetting objects");
00507   for (int i=0; i < objects.size(); i++){
00508     im_server.erase(objects[i].int_marker.name);
00509     im_server.applyChanges();
00510   }
00511   if (has_surface){
00512     removeSurfaceMarker();
00513   }
00514   im_server.clear();
00515   im_server.applyChanges();
00516   objects.clear();
00517   mutex.unlock();
00518   worldChanged();
00519 }
00520 
00521 bool World::addNewObject(geometry_msgs::Pose pose, geometry_msgs::Vector3 dimensions, 
00522                           sensor_msgs::PointCloud2 point_cloud){
00523   for (int i=0; i < objects.size(); i++){
00524     if (World::poseDistance(objects[i].object.pose, pose) < obj_add_dist_threshold){
00525       ROS_INFO("Previously detected object at the same location. Will not add this object.");
00526       return false;
00527     }
00528   }
00529   int n_objects = objects.size();
00530   objects.push_back(fetch_pbd_interaction::WorldLandmark( 
00531                     pose, n_objects, dimensions, point_cloud));//,
00532                     // this,
00533                     // &fetch_pbd_interaction::World::removeObject, 
00534                     // &fetch_pbd_interaction::World::generateGrasps));
00535 
00536   visualization_msgs::InteractiveMarker int_marker = getObjectMarker(n_objects);
00537   objects[n_objects].int_marker = int_marker;
00538   
00539   im_server.insert(int_marker);
00540   im_server.setCallback(int_marker.name, boost::bind(&World::markerFeedbackCallback, this, _1));
00541   im_server.applyChanges();
00542   menu_handler.apply(im_server, int_marker.name);
00543   im_server.applyChanges();
00544 
00545   return true;
00546 }
00547 
00548 
00549 void World::removeSurfaceMarker(){
00550   ROS_INFO("Removing surface marker");
00551   im_server.erase("surface");
00552   im_server.applyChanges();
00553   has_surface = false;
00554 }
00555 
00556 visualization_msgs::InteractiveMarker World::getObjectMarker(int index){
00557   visualization_msgs::InteractiveMarker int_marker;
00558   int_marker.name = objects[index].getName();
00559   int_marker.header.frame_id = objects[index].object.point_cloud.header.frame_id;
00560   int_marker.pose.position = objects[index].object.pose.position;
00561   int_marker.pose.orientation.w = 1.0;
00562   int_marker.scale = 1.0;
00563   sensor_msgs::PointCloud2 pc2 = objects[index].object.point_cloud;
00564   visualization_msgs::Marker marker_points;
00565   visualization_msgs::Marker marker_sphere_list;
00566   World::pc2ToMarker(pc2, index, marker_duration, base_frame, &marker_points, &marker_sphere_list);
00567 
00568   visualization_msgs::InteractiveMarkerControl button_control;
00569   button_control.interaction_mode = visualization_msgs::InteractiveMarkerControl::BUTTON;
00570   button_control.always_visible = true;
00571   button_control.markers.push_back(marker_sphere_list);
00572   button_control.markers.push_back(marker_points);
00573   visualization_msgs::Marker text_marker;
00574   text_marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00575   text_marker.id = index;
00576   text_marker.scale = scale_text;
00577   text_marker.text = int_marker.name;
00578   text_marker.color.a = 0.5; //= color_text;
00579   // text_marker.header.frame_id = base_frame;
00580   geometry_msgs::Point text_pos;
00581   // text_pos.x = objects[index].object.pose.position.x;
00582   // text_pos.y = objects[index].object.pose.position.y;
00583   text_pos.z = objects[index].object.dimensions.z / 2.0 + text_offset;
00584   //     objects[index].object.pose.position.z +
00585   //     objects[index].object.dimensions.z / 2.0 + text_offset);
00586   text_marker.pose.position = text_pos;
00587   text_marker.pose.orientation.w = 1.0;
00588   button_control.markers.push_back(text_marker);
00589   int_marker.controls.push_back(button_control);
00590 
00591   return int_marker;
00592 }
00593 
00594 void World::addSurfaceToPlanningScene(geometry_msgs::Pose pose, geometry_msgs::Vector3 dimensions){
00595   moveit_msgs::CollisionObject collision_object;
00596   /* The header must contain a valid TF frame*/
00597   collision_object.header.frame_id = base_frame;
00598   /* The id of the object */
00599   collision_object.id = "surface";
00600 
00601   /* Define a box to be attached */
00602   shape_msgs::SolidPrimitive primitive;
00603   primitive.type = primitive.BOX;
00604   primitive.dimensions.resize(3);
00605   primitive.dimensions[0] = dimensions.x;
00606   primitive.dimensions[1] = dimensions.y;
00607   primitive.dimensions[2] = dimensions.z;
00608 
00609   collision_object.primitives.push_back(primitive);
00610   collision_object.primitive_poses.push_back(pose);
00611   collision_object.operation = moveit_msgs::CollisionObject::ADD;
00612   moveit_msgs::PlanningScene planning_scene_msg;
00613   planning_scene_msg.world.collision_objects.push_back(collision_object);
00614   planning_scene_msg.is_diff = true;
00615   // for (int i=0; i < 5; i++){
00616   planning_scene_diff_publisher.publish(planning_scene_msg);
00617   // ros::Duration(0.1).sleep();
00618   // }
00619 }
00620 
00621 void World::removeSurfaceFromPlanningScene(){
00622   ROS_INFO("Removing the object from the world.");
00623   moveit_msgs::PlanningScene planning_scene_msg;
00624   moveit_msgs::CollisionObject remove_object;
00625   remove_object.id = "surface";
00626   remove_object.header.frame_id = base_frame;
00627   remove_object.operation = moveit_msgs::CollisionObject::REMOVE;
00628   planning_scene_msg.world.collision_objects.push_back(remove_object);
00629   planning_scene_msg.is_diff = true;
00630   // for (int i=0; i < 5; i++){
00631   planning_scene_diff_publisher.publish(planning_scene_msg);
00632   // ros::Duration(0.1).sleep();
00633   // }
00634 }
00635 
00636 void World::publishTfPose(geometry_msgs::Pose pose, std::string name, std::string parent){
00637   tf::Transform transform;
00638   transform.setOrigin( tf::Vector3(pose.position.x, pose.position.y, pose.position.z));
00639   tf::Quaternion q;
00640   tf::quaternionMsgToTF(pose.orientation, q); 
00641 
00642   transform.setRotation(q);
00643 
00644   if (name == ""){
00645     ROS_INFO("No name");
00646   }
00647   if (parent == ""){
00648     ROS_INFO("No parent");
00649   }
00650   tf_broadcaster.sendTransform(tf::StampedTransform(transform, ros::Time::now(), parent, name));
00651 }
00652 
00653 void World::removeObject(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback){
00654   std::string to_remove = feedback->marker_name;
00655   fetch_pbd_interaction::GetObjectFromNameRequest req;
00656   req.ref_name = to_remove;
00657   fetch_pbd_interaction::GetObjectFromNameResponse resp;
00658   getObjectFromNameCallback(req, resp);
00659   for (int i=0; i < objects.size(); i ++){
00660     if (objects[i].object.name == resp.obj.name){
00661       im_server.erase(objects[i].int_marker.name);
00662       objects.erase(objects.begin() + i );
00663       im_server.applyChanges();
00664       break;
00665     }
00666   }
00667   worldChanged();
00668 }
00669 
00670 void World::addGrasp(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback){
00671   ROS_INFO("Marker menu feedback: Grasp object");
00672   std::string to_grasp = feedback->marker_name;
00673   fetch_pbd_interaction::GetObjectFromNameRequest req;
00674   req.ref_name = to_grasp;
00675   fetch_pbd_interaction::GetObjectFromNameResponse resp;
00676   getObjectFromNameCallback(req, resp);
00677   if (resp.has_object){
00678     add_grasp_pub.publish(resp.obj);
00679   }
00680   else {
00681     ROS_WARN("Cannot generate grasp. No object matching that name.");
00682   }
00683 }
00684 
00685 }


fetch_pbd_interaction
Author(s): Sarah Elliott
autogenerated on Thu Jun 6 2019 18:27:21