visual_tools.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2014, University of Colorado, Boulder
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the Univ of CO, Boulder nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 // Author: Dave Coleman
00036 // Desc:   Simple tools for showing parts of a robot in Rviz, such as the gripper or arm
00037 
00038 #include <moveit_visual_tools/visual_tools.h>
00039 #include <moveit/robot_interaction/robot_interaction.h>
00040 
00041 // MoveIt Messages
00042 #include <moveit_msgs/DisplayTrajectory.h>
00043 #include <moveit_msgs/CollisionObject.h>
00044 
00045 // MoveIt
00046 #include <moveit/robot_state/conversions.h>
00047 
00048 // Conversions
00049 #include <tf_conversions/tf_eigen.h>
00050 
00051 #include <eigen_conversions/eigen_msg.h>
00052 
00053 #include <shape_tools/solid_primitive_dims.h>
00054 
00055 namespace moveit_visual_tools
00056 {
00057 
00058 VisualTools::VisualTools(const std::string& base_frame,
00059                          const std::string& marker_topic,
00060                          planning_scene_monitor::PlanningSceneMonitorPtr planning_scene_monitor)
00061   :  nh_("~"),
00062      planning_scene_monitor_(planning_scene_monitor),
00063      marker_topic_(marker_topic),
00064      base_frame_(base_frame)
00065 {
00066   initialize();
00067 }
00068 
00069 VisualTools::VisualTools(const std::string& base_frame,
00070                          const std::string& marker_topic,
00071                          robot_model::RobotModelConstPtr robot_model)
00072   :  nh_("~"),
00073      robot_model_(robot_model),
00074      marker_topic_(marker_topic),
00075      base_frame_(base_frame)
00076 {
00077   initialize();
00078 }
00079 
00080 void VisualTools::initialize()
00081 {
00082   floor_to_base_height_ = 0;
00083   marker_lifetime_ = ros::Duration(0.0); // 0 - unlimited
00084   muted_ = false;
00085   alpha_ = 0.8;
00086   global_scale_ = 1.0;
00087   // Cache the reusable markers
00088   loadRvizMarkers();
00089 }
00090 
00091 void VisualTools::deleteAllMarkers()
00092 {
00093   loadMarkerPub(); // always check this before publishing
00094   pub_rviz_marker_.publish( reset_marker_ );
00095   ros::spinOnce();
00096 }
00097 
00098 void VisualTools::resetMarkerCounts()
00099 {
00100   arrow_marker_.id++;
00101   sphere_marker_.id++;
00102   block_marker_.id++;
00103   cylinder_marker_.id++;
00104   text_marker_.id++;
00105   rectangle_marker_.id++;
00106   line_marker_.id++;
00107   path_marker_.id++;
00108   spheres_marker_.id++;
00109 }
00110 
00111 bool VisualTools::loadRvizMarkers()
00112 {
00113   // Load reset marker -------------------------------------------------
00114   reset_marker_.header.frame_id = base_frame_;
00115   reset_marker_.header.stamp = ros::Time();
00116   reset_marker_.action = 3; // In ROS-J: visualization_msgs::Marker::DELETEALL;
00117 
00118   // Load arrow ----------------------------------------------------
00119 
00120   arrow_marker_.header.frame_id = base_frame_;
00121   // Set the namespace and id for this marker.  This serves to create a unique ID
00122   arrow_marker_.ns = "Arrow";
00123   // Set the marker type.
00124   arrow_marker_.type = visualization_msgs::Marker::ARROW;
00125   // Set the marker action.  Options are ADD and DELETE
00126   arrow_marker_.action = visualization_msgs::Marker::ADD;
00127   // Lifetime
00128   arrow_marker_.lifetime = marker_lifetime_;
00129 
00130   // Load rectangle ----------------------------------------------------
00131 
00132   rectangle_marker_.header.frame_id = base_frame_;
00133   // Set the namespace and id for this marker.  This serves to create a unique ID
00134   rectangle_marker_.ns = "Rectangle";
00135   // Set the marker type.
00136   rectangle_marker_.type = visualization_msgs::Marker::CUBE;
00137   // Set the marker action.  Options are ADD and DELETE
00138   rectangle_marker_.action = visualization_msgs::Marker::ADD;
00139   // Lifetime
00140   rectangle_marker_.lifetime = marker_lifetime_;
00141 
00142   // Load line ----------------------------------------------------
00143 
00144   line_marker_.header.frame_id = base_frame_;
00145   // Set the namespace and id for this marker.  This serves to create a unique ID
00146   line_marker_.ns = "Line";
00147   // Set the marker type.
00148   line_marker_.type = visualization_msgs::Marker::LINE_STRIP;
00149   // Set the marker action.  Options are ADD and DELETE
00150   line_marker_.action = visualization_msgs::Marker::ADD;
00151   // Lifetime
00152   line_marker_.lifetime = marker_lifetime_;
00153 
00154   // Load path ----------------------------------------------------
00155 
00156   path_marker_.header.frame_id = base_frame_;
00157   // Set the namespace and id for this marker.  This serves to create a unique ID
00158   path_marker_.ns = "Path";
00159   // Set the marker type.
00160   path_marker_.type = visualization_msgs::Marker::LINE_LIST;
00161   // Set the marker action.  Options are ADD and DELETE
00162   path_marker_.action = visualization_msgs::Marker::ADD;
00163   // Lifetime
00164   path_marker_.lifetime = marker_lifetime_;
00165   // Constants
00166   path_marker_.pose.position.x = 0.0;
00167   path_marker_.pose.position.y = 0.0;
00168   path_marker_.pose.position.z = 0.0;
00169 
00170   path_marker_.pose.orientation.x = 0.0;
00171   path_marker_.pose.orientation.y = 0.0;
00172   path_marker_.pose.orientation.z = 0.0;
00173   path_marker_.pose.orientation.w = 1.0;
00174 
00175   // Load sphers ----------------------------------------------------
00176 
00177   spheres_marker_.header.frame_id = base_frame_;
00178   // Set the namespace and id for this marker.  This serves to create a unique ID
00179   spheres_marker_.ns = "Spheres";
00180   // Set the marker type.
00181   spheres_marker_.type = visualization_msgs::Marker::SPHERE_LIST;
00182   // Set the marker action.  Options are ADD and DELETE
00183   spheres_marker_.action = visualization_msgs::Marker::ADD;
00184   // Lifetime
00185   spheres_marker_.lifetime = marker_lifetime_;
00186   // Constants
00187   spheres_marker_.pose.position.x = 0.0;
00188   spheres_marker_.pose.position.y = 0.0;
00189   spheres_marker_.pose.position.z = 0.0;
00190 
00191   spheres_marker_.pose.orientation.x = 0.0;
00192   spheres_marker_.pose.orientation.y = 0.0;
00193   spheres_marker_.pose.orientation.z = 0.0;
00194   spheres_marker_.pose.orientation.w = 1.0;
00195 
00196   // Load Block ----------------------------------------------------
00197   block_marker_.header.frame_id = base_frame_;
00198   // Set the namespace and id for this marker.  This serves to create a unique ID
00199   block_marker_.ns = "Block";
00200   // Set the marker action.  Options are ADD and DELETE
00201   block_marker_.action = visualization_msgs::Marker::ADD;
00202   // Set the marker type.
00203   block_marker_.type = visualization_msgs::Marker::CUBE;
00204   // Lifetime
00205   block_marker_.lifetime = marker_lifetime_;
00206 
00207   // Load Cylinder ----------------------------------------------------
00208   cylinder_marker_.header.frame_id = base_frame_;
00209   // Set the namespace and id for this marker.  This serves to create a unique ID
00210   cylinder_marker_.ns = "Cylinder";
00211   // Set the marker action.  Options are ADD and DELETE
00212   cylinder_marker_.action = visualization_msgs::Marker::ADD;
00213   // Set the marker type.
00214   cylinder_marker_.type = visualization_msgs::Marker::CYLINDER;
00215   // Lifetime
00216   cylinder_marker_.lifetime = marker_lifetime_;
00217 
00218   // Load Sphere -------------------------------------------------
00219   sphere_marker_.header.frame_id = base_frame_;
00220   // Set the namespace and id for this marker.  This serves to create a unique ID
00221   sphere_marker_.ns = "Sphere";
00222   // Set the marker type.
00223   sphere_marker_.type = visualization_msgs::Marker::SPHERE_LIST;
00224   // Set the marker action.  Options are ADD and DELETE
00225   sphere_marker_.action = visualization_msgs::Marker::ADD;
00226   // Marker group position and orientation
00227   sphere_marker_.pose.position.x = 0;
00228   sphere_marker_.pose.position.y = 0;
00229   sphere_marker_.pose.position.z = 0;
00230   sphere_marker_.pose.orientation.x = 0.0;
00231   sphere_marker_.pose.orientation.y = 0.0;
00232   sphere_marker_.pose.orientation.z = 0.0;
00233   sphere_marker_.pose.orientation.w = 1.0;
00234   // Create a sphere point
00235   geometry_msgs::Point point_a;
00236   // Add the point pair to the line message
00237   sphere_marker_.points.push_back( point_a );
00238   sphere_marker_.colors.push_back( getColor( BLUE ) );
00239   // Lifetime
00240   sphere_marker_.lifetime = marker_lifetime_;
00241 
00242   // Load Text ----------------------------------------------------
00243   text_marker_.header.frame_id = base_frame_;
00244   // Set the namespace and id for this marker.  This serves to create a unique ID
00245   text_marker_.ns = "Text";
00246   // Set the marker action.  Options are ADD and DELETE
00247   text_marker_.action = visualization_msgs::Marker::ADD;
00248   // Set the marker type.
00249   text_marker_.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00250   // Lifetime
00251   text_marker_.lifetime = marker_lifetime_;
00252 
00253   return true;
00254 }
00255 
00256 bool VisualTools::loadPlanningSceneMonitor()
00257 {
00258   // Check if we already have one
00259   if (planning_scene_monitor_)
00260   {
00261     ROS_WARN_STREAM_NAMED("visual_tools","Will not load a new planning scene monitor when one has already been set for Visual Tools");
00262     return false;
00263   }
00264   ROS_DEBUG_STREAM_NAMED("visual_tools","Loading planning scene monitor");
00265 
00266   // Create planning scene monitor
00267   // We create it the harder, more manual way so that we can tell MoveIt! to skip loading IK solvers, since we will
00268   // never use them within the context of moveit_visual_tools. This saves loading time
00269   /*
00270     robot_model_loader::RobotModelLoader::Options rml_options(ROBOT_DESCRIPTION);
00271     rml_options.load_kinematics_solvers_ = false;
00272     rm_loader_.reset(new robot_model_loader::RobotModelLoader(rml_options));
00273 
00274     std::string monitor_name = "visual_tools_planning_scene_monitor";
00275 
00276     planning_scene_monitor_.reset(new planning_scene_monitor::PlanningSceneMonitor(
00277     planning_scene::PlanningScenePtr(),
00278     rm_loader_,
00279     boost::shared_ptr<tf::Transformer>(),
00280     monitor_name
00281     ));
00282   */
00283 
00284   // Regular version b/c the other one causes problems with recognizing end effectors
00285   planning_scene_monitor_.reset(new planning_scene_monitor::PlanningSceneMonitor(ROBOT_DESCRIPTION));
00286 
00287   ros::spinOnce();
00288   ros::Duration(0.1).sleep();
00289   ros::spinOnce();
00290 
00291   if (planning_scene_monitor_->getPlanningScene())
00292   {
00293     // Optional monitors to start:
00294     //planning_scene_monitor_->startWorldGeometryMonitor();
00295     //planning_scene_monitor_->startSceneMonitor("/move_group/monitored_planning_scene");
00296     //planning_scene_monitor_->startStateMonitor("/joint_states", "/attached_collision_object");
00297     //planning_scene_monitor_->startPublishingPlanningScene(planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE, "test_planning_scene");
00298   }
00299   else
00300   {
00301     ROS_ERROR_STREAM_NAMED("visual_tools","Planning scene not configured");
00302     return false;
00303   }
00304 
00305   return true;
00306 }
00307 
00308 bool VisualTools::processCollisionObjectMsg(moveit_msgs::CollisionObject msg)
00309 {
00310   // Apply removal command directly to avoid a ROS msg call
00311   {
00312     planning_scene_monitor::LockedPlanningSceneRW scene(getPlanningSceneMonitor());
00313     scene->processCollisionObjectMsg(msg);
00314   }
00315 
00316   // Trigger an update
00317   getPlanningSceneMonitor()->triggerSceneUpdateEvent(planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE);
00318 
00319   return true;
00320 }
00321 
00322 bool VisualTools::loadRobotMarkers()
00323 {
00324   // Always load the robot state before using
00325   loadSharedRobotState();
00326 
00327   // Get all link names
00328   const std::vector<std::string> &link_names = shared_robot_state_->getRobotModel()->getLinkModelNames();;
00329 
00330   ROS_DEBUG_STREAM_NAMED("visual_tools","Number of links in robot: " << link_names.size());
00331   //    std::copy(link_names.begin(), link_names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
00332 
00333   // Get EE link markers for Rviz
00334   visualization_msgs::MarkerArray robot_marker_array;
00335   shared_robot_state_->getRobotMarkers(robot_marker_array, link_names, getColor( GREY ), "test", ros::Duration());
00336 
00337   ROS_DEBUG_STREAM_NAMED("visual_tools","Number of rviz markers: " << robot_marker_array.markers.size());
00338 
00339   // Publish the markers
00340   for (std::size_t i = 0 ; i < robot_marker_array.markers.size() ; ++i)
00341   {
00342     // Make sure ROS is still spinning
00343     if( !ros::ok() )
00344       break;
00345 
00346     // Header
00347     robot_marker_array.markers[i].header.frame_id = base_frame_;
00348     robot_marker_array.markers[i].header.stamp = ros::Time::now();
00349 
00350     // Options for meshes
00351     if( robot_marker_array.markers[i].type == visualization_msgs::Marker::MESH_RESOURCE )
00352       robot_marker_array.markers[i].mesh_use_embedded_materials = true;
00353 
00354     loadMarkerPub(); // always check this before publishing
00355     pub_rviz_marker_.publish( robot_marker_array.markers[i] );
00356     ros::spinOnce();
00357   }
00358 
00359   return true;
00360 }
00361 
00362 bool VisualTools::loadEEMarker(const std::string& ee_group_name, const std::string& planning_group)
00363 {
00364   // Always load the robot state before using
00365   loadSharedRobotState();
00366 
00367   // -----------------------------------------------------------------------------------------------
00368   // Get end effector group
00369 
00370   // Create color to use for EE markers
00371   std_msgs::ColorRGBA marker_color = getColor( GREY );
00372 
00373   // Get robot model
00374   robot_model::RobotModelConstPtr robot_model = shared_robot_state_->getRobotModel();
00375   // Get joint state group
00376   const robot_model::JointModelGroup* joint_model_group = robot_model->getJointModelGroup(ee_group_name);
00377   if( joint_model_group == NULL ) // make sure EE_GROUP exists
00378   {
00379     ROS_ERROR_STREAM_NAMED("visual_tools","Unable to find joint model group '" << ee_group_name << "'");
00380     return false;
00381   }
00382   // Get link names that are in end effector
00383   const std::vector<std::string> &ee_link_names = joint_model_group->getLinkModelNames();
00384   //ROS_DEBUG_STREAM_NAMED("visual_tools","Number of links in group " << ee_group_name << ": " << ee_link_names.size());
00385   //std::copy(ee_link_names.begin(), ee_link_names.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
00386 
00387   // Robot Interaction - finds the end effector associated with a planning group
00388   robot_interaction::RobotInteraction robot_interaction( robot_model );
00389 
00390   // Decide active end effectors
00391   robot_interaction.decideActiveComponents(planning_group);
00392 
00393   // Get active EE
00394   std::vector<robot_interaction::RobotInteraction::EndEffector> active_eef =
00395     robot_interaction.getActiveEndEffectors();
00396 
00397   ROS_DEBUG_STREAM_NAMED("visual_tools","Number of active end effectors: " << active_eef.size());
00398   if( !active_eef.size() )
00399   {
00400     ROS_ERROR_STREAM_NAMED("visual_tools","No active end effectors found! Make sure kinematics.yaml is loaded in this node's namespace!");
00401     return false;
00402   }
00403 
00404   // Just choose the first end effector \todo better logic?
00405   robot_interaction::RobotInteraction::EndEffector eef = active_eef[0];
00406 
00407   // -----------------------------------------------------------------------------------------------
00408   // Get EE link markers for Rviz
00409 
00410   shared_robot_state_->getRobotMarkers(ee_marker_array_, ee_link_names, marker_color, eef.eef_group, ros::Duration());
00411   ROS_DEBUG_STREAM_NAMED("visual_tools","Number of rviz markers in end effector: " << ee_marker_array_.markers.size());
00412 
00413   // Change pose from Eigen to TF
00414   try
00415   {
00416     //ee_parent_link_ = eef.parent_link; // save the name of the link for later use
00417     tf::poseEigenToTF(shared_robot_state_->getGlobalLinkTransform(eef.parent_link), tf_root_to_link_);
00418   }
00419   catch(...)
00420   {
00421     ROS_ERROR_STREAM_NAMED("visual_tools","Didn't find link state for " << eef.parent_link);
00422   }
00423 
00424   // Copy original marker poses to a vector
00425   for (std::size_t i = 0 ; i < ee_marker_array_.markers.size() ; ++i)
00426   {
00427     marker_poses_.push_back( ee_marker_array_.markers[i].pose );
00428   }
00429 
00430   return true;
00431 }
00432 
00433 void VisualTools::loadMarkerPub()
00434 {
00435   if (pub_rviz_marker_)
00436     return;
00437 
00438   // Rviz marker publisher
00439   pub_rviz_marker_ = nh_.advertise<visualization_msgs::Marker>(marker_topic_, 10);
00440   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing Rviz markers on topic " << pub_rviz_marker_.getTopic());
00441 
00442   ros::spinOnce();
00443   ros::Duration(0.2).sleep();
00444   ros::spinOnce();
00445 }
00446 
00447 void VisualTools::loadCollisionPub()
00448 {
00449   if (pub_collision_obj_)
00450     return;
00451 
00452   // Collision object creator
00453   pub_collision_obj_ = nh_.advertise<moveit_msgs::CollisionObject>(COLLISION_TOPIC, 10);
00454   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing collision objects on topic " << pub_collision_obj_.getTopic());
00455 
00456   ros::spinOnce();
00457   ros::Duration(0.2).sleep();
00458   ros::spinOnce();
00459 }
00460 
00461 void VisualTools::loadAttachedPub()
00462 {
00463   if (pub_attach_collision_obj_)
00464     return;
00465 
00466   // Collision object attacher
00467   pub_attach_collision_obj_ = nh_.advertise<moveit_msgs::AttachedCollisionObject>(ATTACHED_COLLISION_TOPIC, 10);
00468   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing attached collision objects on topic " << pub_attach_collision_obj_.getTopic());
00469 
00470   ros::spinOnce();
00471   ros::Duration(0.2).sleep();
00472   ros::spinOnce();
00473 }
00474 
00475 void VisualTools::loadPlanningPub()
00476 {
00477   if (pub_planning_scene_diff_)
00478     return;
00479 
00480   // Planning scene diff publisher
00481   pub_planning_scene_diff_ = nh_.advertise<moveit_msgs::PlanningScene>(PLANNING_SCENE_TOPIC, 1);
00482   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing planning scene on topic " << pub_planning_scene_diff_.getTopic());
00483 
00484   ros::spinOnce();
00485   ros::Duration(0.2).sleep();
00486   ros::spinOnce();
00487 }
00488 
00489 void VisualTools::loadTrajectoryPub()
00490 {
00491   if (pub_display_path_)
00492     return;
00493 
00494   // Trajectory paths
00495   pub_display_path_ = nh_.advertise<moveit_msgs::DisplayTrajectory>(DISPLAY_PLANNED_PATH_TOPIC, 10, false);
00496   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing MoveIt trajectory on topic " << pub_display_path_.getTopic());
00497 
00498   ros::spinOnce();
00499   ros::Duration(0.2).sleep();
00500   ros::spinOnce();
00501 }
00502 
00503 void VisualTools::loadRobotStatePub(const std::string &marker_topic)
00504 {
00505   if (pub_robot_state_)
00506     return;
00507 
00508   // RobotState Message
00509   pub_robot_state_ = nh_.advertise<moveit_msgs::DisplayRobotState>(marker_topic, 1 );
00510   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing MoveIt robot state on topic " << pub_robot_state_.getTopic());
00511 
00512   ros::spinOnce();
00513   ros::Duration(0.2).sleep();
00514   ros::spinOnce();
00515 }
00516 
00517 void VisualTools::setFloorToBaseHeight(double floor_to_base_height)
00518 {
00519   floor_to_base_height_ = floor_to_base_height;
00520 }
00521 
00522 void VisualTools::setGraspPoseToEEFPose(geometry_msgs::Pose grasp_pose_to_eef_pose)
00523 {
00524   grasp_pose_to_eef_pose_ = grasp_pose_to_eef_pose;
00525 }
00526 
00527 void VisualTools::setLifetime(double lifetime)
00528 {
00529   marker_lifetime_ = ros::Duration(lifetime);
00530 
00531   // Update cached markers
00532   arrow_marker_.lifetime = marker_lifetime_;
00533   rectangle_marker_.lifetime = marker_lifetime_;
00534   line_marker_.lifetime = marker_lifetime_;
00535   sphere_marker_.lifetime = marker_lifetime_;
00536   block_marker_.lifetime = marker_lifetime_;
00537   cylinder_marker_.lifetime = marker_lifetime_;
00538   text_marker_.lifetime = marker_lifetime_;
00539 }
00540 
00541 const rviz_colors VisualTools::getRandColor()
00542 {
00543   std::vector<rviz_colors> all_colors;
00544   
00545   all_colors.push_back(RED);
00546   all_colors.push_back(GREEN);
00547   all_colors.push_back(BLUE);
00548   all_colors.push_back(GREY);
00549   all_colors.push_back(WHITE);
00550   all_colors.push_back(ORANGE);
00551   all_colors.push_back(BLACK);
00552   all_colors.push_back(YELLOW);
00553   all_colors.push_back(PURPLE);
00554   
00555   return all_colors[ rand() % all_colors.size() ];
00556 }
00557 
00558 std_msgs::ColorRGBA VisualTools::getColor(const rviz_colors &color)
00559 {
00560   std_msgs::ColorRGBA result;
00561   result.a = alpha_;
00562   switch(color)
00563   {
00564     case RED:
00565       result.r = 0.8;
00566       result.g = 0.1;
00567       result.b = 0.1;
00568       break;
00569     case GREEN:
00570       result.r = 0.1;
00571       result.g = 0.8;
00572       result.b = 0.1;
00573       break;
00574     case GREY:
00575       result.r = 0.9;
00576       result.g = 0.9;
00577       result.b = 0.9;
00578       break;
00579     case WHITE:
00580       result.r = 1.0;
00581       result.g = 1.0;
00582       result.b = 1.0;
00583       break;
00584     case ORANGE:
00585       result.r = 1.0;
00586       result.g = 0.5;
00587       result.b = 0.0;
00588       break;
00589     case TRANSLUCENT:
00590       result.r = 0.1;
00591       result.g = 0.1;
00592       result.b = 0.8;
00593       result.a = 0.3;
00594       break;
00595     case TRANSLUCENT2:
00596       result.r = 0.1;
00597       result.g = 0.1;
00598       result.b = 0.1;
00599       result.a = 0.1;
00600       break;
00601     case BLACK:
00602       result.r = 0.0;
00603       result.g = 0.0;
00604       result.b = 0.0;
00605       break;
00606     case YELLOW:
00607       result.r = 1.0;
00608       result.g = 1.0;
00609       result.b = 0.0;
00610       break;
00611     case PURPLE:
00612       result.r = 0.597;
00613       result.g = 0.0;
00614       result.b = 0.597;
00615       break;
00616     case RAND:
00617       // Make sure color is not *too* light
00618       do
00619       {
00620         result.r = fRand(0.0,1.0);
00621         result.g = fRand(0.0,1.0);
00622         result.b = fRand(0.0,1.0);
00623       } while (result.r + result.g + result.b < 1.5); // 3 would be white
00624       break;
00625     case BLUE:
00626     default:
00627       result.r = 0.1;
00628       result.g = 0.1;
00629       result.b = 0.8;
00630   }
00631 
00632   return result;
00633 }
00634 
00635 geometry_msgs::Vector3 VisualTools::getScale(const rviz_scales &scale, bool arrow_scale, double marker_scale)
00636 {
00637   geometry_msgs::Vector3 result;
00638   double val(0.0);
00639   switch(scale)
00640   {
00641     case XXSMALL:
00642       val = 0.005;
00643       break;
00644     case XSMALL:
00645       val = 0.01;
00646       break;
00647     case SMALL:
00648       val = 0.03;
00649       break;
00650     case REGULAR:
00651       val = 0.05;
00652       break;
00653     case LARGE:
00654       val = 0.1;
00655       break;
00656     case xLARGE:
00657       val = 0.2;
00658       break;
00659     case xxLARGE:
00660       val = 0.3;
00661       break;
00662     case xxxLARGE:
00663       val = 0.4;
00664       break;
00665     case XLARGE:
00666       val = 0.5;
00667       break;
00668     case XXLARGE:
00669       val = 1.0;
00670       break;
00671     default:
00672       ROS_ERROR_STREAM_NAMED("visualization_tools","Not implemented yet");
00673       break;
00674   }
00675 
00676   // Allows an individual marker size factor and a size factor for all markers 
00677   result.x = val * marker_scale * global_scale_;
00678   result.y = val * marker_scale * global_scale_;
00679   result.z = val * marker_scale * global_scale_;
00680 
00681   // The y and z scaling is smaller for arrows
00682   if (arrow_scale)
00683   {
00684     result.y *= 0.1;
00685     result.z *= 0.1;
00686   }
00687 
00688   return result;
00689 }
00690 
00691 planning_scene_monitor::PlanningSceneMonitorPtr VisualTools::getPlanningSceneMonitor()
00692 {
00693   if( !planning_scene_monitor_ )
00694   {
00695     loadPlanningSceneMonitor();
00696     ros::spinOnce();
00697     ros::Duration(1).sleep();
00698   }
00699   return planning_scene_monitor_;
00700 }
00701 
00702 bool VisualTools::loadSharedRobotState()
00703 {
00704   // Get robot state
00705   if (!shared_robot_state_)
00706   {
00707     // Check if a robot model was passed in
00708     if (!robot_model_)
00709     {
00710       // Fall back on using planning scene monitor.
00711       // Deprecated?
00712       ROS_WARN_STREAM_NAMED("temp","Falling back to using planning scene monitor for loading a robot state");
00713       planning_scene_monitor::PlanningSceneMonitorPtr psm = getPlanningSceneMonitor();
00714       robot_model_ = psm->getRobotModel();
00715     }
00716     shared_robot_state_.reset(new robot_state::RobotState(robot_model_));
00717   }
00718 
00719   return true;
00720 }
00721 
00722 Eigen::Vector3d VisualTools::getCenterPoint(Eigen::Vector3d a, Eigen::Vector3d b)
00723 {
00724   Eigen::Vector3d center;
00725   center[0] = (a[0] + b[0]) / 2;
00726   center[1] = (a[1] + b[1]) / 2;
00727   center[2] = (a[2] + b[2]) / 2;
00728   return center;
00729 }
00730 
00731 Eigen::Affine3d VisualTools::getVectorBetweenPoints(Eigen::Vector3d a, Eigen::Vector3d b)
00732 {
00733   // from http://answers.ros.org/question/31006/how-can-a-vector3-axis-be-used-to-produce-a-quaternion/
00734 
00735   // Goal pose:
00736   Eigen::Quaterniond q;
00737 
00738   Eigen::Vector3d axis_vector = b - a;
00739   axis_vector.normalize();
00740 
00741   Eigen::Vector3d up_vector(0.0, 0.0, 1.0);
00742   Eigen::Vector3d right_axis_vector = axis_vector.cross(up_vector);
00743   right_axis_vector.normalized();
00744   double theta = axis_vector.dot(up_vector);
00745   double angle_rotation = -1.0*acos(theta);
00746 
00747   //-------------------------------------------
00748   // Method 1 - TF - works
00749   //Convert to TF
00750   tf::Vector3 tf_right_axis_vector;
00751   tf::vectorEigenToTF(right_axis_vector, tf_right_axis_vector);
00752 
00753   // Create quaternion
00754   tf::Quaternion tf_q(tf_right_axis_vector, angle_rotation);
00755 
00756   // Convert back to Eigen
00757   tf::quaternionTFToEigen(tf_q, q);
00758   //-------------------------------------------
00759   //std::cout << q.toRotationMatrix() << std::endl;
00760 
00761   //-------------------------------------------
00762   // Method 2 - Eigen - broken TODO
00763   //q = Eigen::AngleAxis<double>(angle_rotation, right_axis_vector);
00764   //-------------------------------------------
00765   //std::cout << q.toRotationMatrix() << std::endl;
00766 
00767   // Rotate so that vector points along line
00768   Eigen::Affine3d pose;
00769   q.normalize();
00770   pose = q * Eigen::AngleAxisd(-0.5*M_PI, Eigen::Vector3d::UnitY());
00771   pose.translation() = a;
00772 
00773   return pose;
00774 }
00775 
00776 bool VisualTools::publishEEMarkers(const geometry_msgs::Pose &pose, const rviz_colors &color, const std::string &ns)
00777 {
00778   if(muted_)
00779     return true;
00780 
00781   // Check if we have already loaded the EE markers
00782   if( ee_marker_array_.markers.empty() )
00783   {
00784     ROS_ERROR_STREAM_NAMED("visual_tools","Unable to publish EE marker because marker has not been loaded yet");
00785     return false;
00786   }
00787 
00788   // -----------------------------------------------------------------------------------------------
00789   // Change the end effector pose to frame of reference of this custom end effector
00790 
00791   // Convert to Eigen
00792   Eigen::Affine3d ee_pose_eigen;
00793   Eigen::Affine3d eef_conversion_pose;
00794   tf::poseMsgToEigen(pose, ee_pose_eigen);
00795   tf::poseMsgToEigen(grasp_pose_to_eef_pose_, eef_conversion_pose);
00796 
00797   // Transform the grasp pose
00798   ee_pose_eigen = ee_pose_eigen * eef_conversion_pose;
00799 
00800   // Convert back to message
00801   geometry_msgs::Pose ee_pose = convertPose(ee_pose_eigen);
00802 
00803   // -----------------------------------------------------------------------------------------------
00804   // Process each link of the end effector
00805   for (std::size_t i = 0 ; i < ee_marker_array_.markers.size() ; ++i)
00806   {
00807     // Make sure ROS is still spinning
00808     if( !ros::ok() )
00809       break;
00810 
00811     // Header
00812     ee_marker_array_.markers[i].header.frame_id = base_frame_;
00813     ee_marker_array_.markers[i].header.stamp = ros::Time::now();
00814 
00815     // Namespace
00816     ee_marker_array_.markers[i].ns = ns;
00817 
00818     // Lifetime
00819     ee_marker_array_.markers[i].lifetime = marker_lifetime_;
00820 
00821     // Color
00822     ee_marker_array_.markers[i].color = getColor( color );
00823 
00824     // Options for meshes
00825     if( ee_marker_array_.markers[i].type == visualization_msgs::Marker::MESH_RESOURCE )
00826     {
00827       ee_marker_array_.markers[i].mesh_use_embedded_materials = true;
00828     }
00829 
00830     // -----------------------------------------------------------------------------------------------
00831     // Do some math for the offset
00832     // pose             - our generated grasp
00833     // markers[i].pose        - an ee link's pose relative to the whole end effector
00834     // REMOVED grasp_pose_to_eef_pose_ - the offset from the grasp pose to eef_pose - probably nothing
00835     tf::Pose tf_root_to_marker;
00836     tf::Pose tf_root_to_mesh;
00837     tf::Pose tf_pose_to_eef;
00838 
00839     // Simple conversion from geometry_msgs::Pose to tf::Pose
00840     tf::poseMsgToTF(pose, tf_root_to_marker);
00841     tf::poseMsgToTF(marker_poses_[i], tf_root_to_mesh);
00842 
00843     // Conversions
00844     tf::Pose tf_eef_to_mesh = tf_root_to_link_.inverse() * tf_root_to_mesh;
00845     tf::Pose tf_root_to_mesh_new = tf_root_to_marker * tf_eef_to_mesh;
00846     tf::poseTFToMsg(tf_root_to_mesh_new, ee_marker_array_.markers[i].pose);
00847     // -----------------------------------------------------------------------------------------------
00848 
00849     //ROS_INFO_STREAM("Marker " << i << ":\n" << ee_marker_array_.markers[i]);
00850 
00851     loadMarkerPub(); // always check this before publishing
00852     pub_rviz_marker_.publish( ee_marker_array_.markers[i] );
00853     ros::spinOnce();
00854   }
00855 
00856   return true;
00857 }
00858 
00859 bool VisualTools::publishSphere(const Eigen::Affine3d &pose, const rviz_colors color, const rviz_scales scale, const std::string& ns)
00860 {
00861   return publishSphere(convertPose(pose), color, scale, ns);
00862 }
00863 
00864 bool VisualTools::publishSphere(const Eigen::Vector3d &point, const rviz_colors color, const rviz_scales scale, const std::string& ns)
00865 {
00866   geometry_msgs::Pose pose_msg;
00867   tf::pointEigenToMsg(point, pose_msg.position);
00868   return publishSphere(pose_msg, color, scale, ns);
00869 }
00870 
00871 bool VisualTools::publishSphere(const geometry_msgs::Point &point, const rviz_colors color, const rviz_scales scale, const std::string& ns)
00872 {
00873   geometry_msgs::Pose pose_msg;
00874   pose_msg.position = point;
00875   return publishSphere(pose_msg, color, scale, ns);
00876 }
00877 
00878 bool VisualTools::publishSphere(const geometry_msgs::Pose &pose, const rviz_colors color, const rviz_scales scale, const std::string& ns)
00879 {
00880   return publishSphere(pose, color, getScale(scale, false, 0.1), ns);
00881 }
00882 
00883 bool VisualTools::publishSphere(const geometry_msgs::Pose &pose, const rviz_colors color, double scale, const std::string& ns)
00884 {
00885   geometry_msgs::Vector3 scale_msg;
00886   scale_msg.x = scale;
00887   scale_msg.y = scale;
00888   scale_msg.z = scale;
00889   return publishSphere(pose, color, scale_msg, ns);
00890 }
00891 bool VisualTools::publishSphere(const geometry_msgs::Pose &pose, const rviz_colors color, const geometry_msgs::Vector3 scale, const std::string& ns)
00892 {
00893   if(muted_)
00894     return true; // this function will only work if we have loaded the publishers
00895 
00896   // Set the frame ID and timestamp
00897   sphere_marker_.header.stamp = ros::Time::now();
00898 
00899   sphere_marker_.id++;
00900   sphere_marker_.color = getColor(color);
00901   sphere_marker_.scale = scale;
00902   sphere_marker_.ns = ns;
00903 
00904   // Update the single point with new pose
00905   sphere_marker_.points[0] = pose.position;
00906   sphere_marker_.colors[0] = getColor(color);
00907 
00908   // Publish
00909   loadMarkerPub(); // always check this before publishing
00910   pub_rviz_marker_.publish( sphere_marker_ );
00911   ros::spinOnce();
00912 
00913   return true;
00914 }
00915 
00916 bool VisualTools::publishArrow(const Eigen::Affine3d &pose, const rviz_colors color, const rviz_scales scale)
00917 {
00918   return publishArrow(convertPose(pose), color, scale);
00919 }
00920 
00921 bool VisualTools::publishArrow(const geometry_msgs::Pose &pose, const rviz_colors color, const rviz_scales scale)
00922 {
00923   if(muted_)
00924     return true;
00925 
00926   // Set the frame ID and timestamp.  See the TF tutorials for information on these.
00927   arrow_marker_.header.stamp = ros::Time::now();
00928 
00929   arrow_marker_.id++;
00930   arrow_marker_.pose = pose;
00931   arrow_marker_.color = getColor(color);
00932   arrow_marker_.scale = getScale(scale, true);
00933 
00934   loadMarkerPub(); // always check this before publishing
00935   pub_rviz_marker_.publish( arrow_marker_ );
00936   ros::spinOnce();
00937 
00938   return true;
00939 }
00940 
00941 bool VisualTools::publishBlock(const geometry_msgs::Pose &pose, const rviz_colors color, const double &block_size)
00942 {
00943   if(muted_)
00944     return true;
00945 
00946   // Set the timestamp
00947   block_marker_.header.stamp = ros::Time::now();
00948 
00949   block_marker_.id++;
00950 
00951   // Set the pose
00952   block_marker_.pose = pose;
00953 
00954   // Set marker size
00955   block_marker_.scale.x = block_size;
00956   block_marker_.scale.y = block_size;
00957   block_marker_.scale.z = block_size;
00958 
00959   // Set marker color
00960   block_marker_.color = getColor( color );
00961 
00962   loadMarkerPub(); // always check this before publishing
00963   pub_rviz_marker_.publish( block_marker_ );
00964   ros::spinOnce();
00965 
00966   return true;
00967 }
00968 
00969 bool VisualTools::publishCylinder(const geometry_msgs::Pose &pose, const rviz_colors color, double height, double radius)
00970 {
00971   if(muted_)
00972     return true;
00973 
00974   // Set the timestamp
00975   cylinder_marker_.header.stamp = ros::Time::now();
00976 
00977   cylinder_marker_.id++;
00978 
00979   // Set the pose
00980   cylinder_marker_.pose = pose;
00981 
00982   // Set marker size
00983   cylinder_marker_.scale.x = radius;
00984   cylinder_marker_.scale.y = radius;
00985   cylinder_marker_.scale.z = height;
00986 
00987   // Set marker color
00988   cylinder_marker_.color = getColor( color );
00989 
00990   loadMarkerPub(); // always check this before publishing
00991   pub_rviz_marker_.publish( cylinder_marker_ );
00992   ros::spinOnce();
00993 
00994   return true;
00995 }
00996 
00997 bool VisualTools::publishGraph(const graph_msgs::GeometryGraph &graph, const rviz_colors color, double radius)
00998 {
00999   if(muted_)
01000     return true;
01001 
01002   // Track which pairs of nodes we've already connected since graph is bi-directional
01003   typedef std::pair<std::size_t, std::size_t> node_ids;
01004   std::set<node_ids> added_edges;
01005   std::pair<std::set<node_ids>::iterator,bool> return_value;
01006 
01007   Eigen::Vector3d a, b;
01008   for (std::size_t i = 0; i < graph.nodes.size(); ++i)
01009   {
01010     for (std::size_t j = 0; j < graph.edges[i].node_ids.size(); ++j)
01011     {
01012       // Check if we've already added this pair of nodes (edge)
01013       return_value = added_edges.insert( node_ids(i,j) );
01014       if (return_value.second == false)
01015       {
01016         // Element already existed in set, so don't add a new collision object
01017       }
01018       else
01019       {
01020         // Create a cylinder from two points
01021         a = convertPoint(graph.nodes[i]);
01022         b = convertPoint(graph.nodes[graph.edges[i].node_ids[j]]);
01023 
01024         // add other direction of edge
01025         added_edges.insert( node_ids(j,i) );
01026 
01027         // Distance between two points
01028         double height = (a - b).lpNorm<2>();
01029 
01030         // Find center point
01031         Eigen::Vector3d pt_center = getCenterPoint(a, b);
01032 
01033         // Create vector
01034         Eigen::Affine3d pose;
01035         pose = getVectorBetweenPoints(pt_center, b);
01036 
01037         // Convert pose to be normal to cylindar axis
01038         Eigen::Affine3d rotation;
01039         rotation = Eigen::AngleAxisd(0.5*M_PI, Eigen::Vector3d::UnitY());
01040         pose = pose * rotation;
01041 
01042         // Publish individually
01043         publishCylinder(convertPose(pose), color, height, radius);
01044       }
01045     }
01046   }
01047 
01048   return true;
01049 }
01050 
01051 bool VisualTools::publishRectangle(const geometry_msgs::Point &point1, const geometry_msgs::Point &point2, const rviz_colors color)
01052 {
01053   if(muted_)
01054     return true;
01055 
01056   // Set the timestamp
01057   rectangle_marker_.header.stamp = ros::Time::now();
01058 
01059   rectangle_marker_.id++;
01060   rectangle_marker_.color = getColor(color);
01061 
01062   // Calculate pose
01063   geometry_msgs::Pose pose;
01064   pose.position.x = (point1.x - point2.x) / 2.0 + point2.x;
01065   pose.position.y = (point1.y - point2.y) / 2.0 + point2.y;
01066   pose.position.z = (point1.z - point2.z) / 2.0 + point2.z;
01067   rectangle_marker_.pose = pose;
01068 
01069   // Calculate scale
01070   rectangle_marker_.scale.x = fabs(point1.x - point2.x);
01071   rectangle_marker_.scale.y = fabs(point1.y - point2.y);
01072   rectangle_marker_.scale.z = fabs(point1.z - point2.z);
01073 
01074   loadMarkerPub(); // always check this before publishing
01075   pub_rviz_marker_.publish( rectangle_marker_ );
01076   ros::spinOnce();
01077 
01078   return true;
01079 }
01080 
01081 bool VisualTools::publishLine(const geometry_msgs::Point &point1, const geometry_msgs::Point &point2,
01082                               const rviz_colors color, const rviz_scales scale)
01083 {
01084   if(muted_)
01085     return true;
01086 
01087   // Set the timestamp
01088   line_marker_.header.stamp = ros::Time::now();
01089 
01090   line_marker_.id++;
01091   line_marker_.color = getColor(color);
01092   line_marker_.scale = getScale( scale, false, 0.1 );
01093 
01094   line_marker_.points.clear();
01095   line_marker_.points.push_back(point1);
01096   line_marker_.points.push_back(point2);
01097 
01098   loadMarkerPub(); // always check this before publishing
01099   pub_rviz_marker_.publish( line_marker_ );
01100   ros::spinOnce();
01101 
01102   return true;
01103 }
01104 
01105 bool VisualTools::publishPath(const std::vector<geometry_msgs::Point> &path, const rviz_colors color, const rviz_scales scale, const std::string& ns)
01106 {
01107   if(muted_)
01108     return true;
01109 
01110   if (path.size() < 2)
01111   {
01112     ROS_WARN_STREAM_NAMED("publishPath","Skipping path because " << path.size() << " points passed in.");
01113     return true;
01114   }
01115 
01116   path_marker_.header.stamp = ros::Time();
01117   path_marker_.ns = ns;
01118 
01119   // Provide a new id every call to this function
01120   path_marker_.id++;
01121 
01122   std_msgs::ColorRGBA this_color = getColor( color );
01123   path_marker_.scale = getScale(scale, false, 0.25);
01124   path_marker_.color = this_color;
01125   path_marker_.points.clear();
01126   path_marker_.colors.clear();
01127 
01128   // Convert path coordinates
01129   for( std::size_t i = 1; i < path.size(); ++i )
01130   {
01131     // Add the point pair to the line message
01132     path_marker_.points.push_back( path[i-1] );
01133     path_marker_.points.push_back( path[i] );
01134     path_marker_.colors.push_back( this_color );
01135     path_marker_.colors.push_back( this_color );
01136   }
01137 
01138   // Send to Rviz
01139   loadMarkerPub(); // always check this before publishing
01140   pub_rviz_marker_.publish( path_marker_ );
01141   ros::spinOnce();
01142 
01143   return true;
01144 }
01145 
01146 bool VisualTools::publishPolygon(const geometry_msgs::Polygon &polygon, const rviz_colors color, const rviz_scales scale, const std::string& ns)
01147 {
01148   std::vector<geometry_msgs::Point> points;
01149   geometry_msgs::Point temp;
01150   geometry_msgs::Point first; // remember first point because we will connect first and last points for last line
01151   for (std::size_t i = 0; i < polygon.points.size(); ++i)
01152   {
01153     temp.x = polygon.points[i].x;
01154     temp.y = polygon.points[i].y;
01155     temp.z = polygon.points[i].z;
01156     if (i == 0)
01157       first = temp;
01158     points.push_back(temp);
01159   }
01160   points.push_back(first); // connect first and last points for last line
01161 
01162   publishPath(points, color, scale, ns);
01163 }
01164 
01165 bool VisualTools::publishSpheres(const std::vector<geometry_msgs::Point> &points, const rviz_colors color, const rviz_scales scale, const std::string& ns)
01166 {
01167   if(muted_)
01168     return true;
01169 
01170   spheres_marker_.header.stamp = ros::Time();
01171   spheres_marker_.ns = ns;
01172 
01173   // Provide a new id every call to this function
01174   spheres_marker_.id++;
01175 
01176   std_msgs::ColorRGBA this_color = getColor( color );
01177   spheres_marker_.scale = getScale(scale, false, 0.25);
01178   spheres_marker_.color = this_color;
01179   //spheres_marker_.points.clear();
01180   spheres_marker_.colors.clear();
01181 
01182   spheres_marker_.points = points; // straight copy
01183 
01184   // Convert path coordinates
01185   for( std::size_t i = 0; i < points.size(); ++i )
01186   {
01187     spheres_marker_.colors.push_back( this_color );
01188   }
01189 
01190   // Send to Rviz
01191   loadMarkerPub(); // always check this before publishing
01192   pub_rviz_marker_.publish( spheres_marker_ );
01193   ros::spinOnce();
01194 
01195   return true;
01196 }
01197 
01198 bool VisualTools::publishText(const geometry_msgs::Pose &pose, const std::string &text, const rviz_colors &color, const rviz_scales scale)
01199 {
01200   publishText(pose, text, color, getScale(scale));
01201 }
01202 
01203 bool VisualTools::publishText(const geometry_msgs::Pose &pose, const std::string &text, const rviz_colors &color, const geometry_msgs::Vector3 scale, bool static_id)
01204 {
01205   if(muted_)
01206     return true;
01207 
01208   // Save the ID if this is a static ID or keep incrementing ID if not static
01209   double temp_id = text_marker_.id;
01210   if (static_id)
01211   {
01212     text_marker_.id = 0;
01213   }
01214   else
01215   {
01216     text_marker_.id++;
01217   }
01218 
01219   text_marker_.header.stamp = ros::Time::now();
01220   text_marker_.text = text;
01221   text_marker_.pose = pose;
01222   text_marker_.color = getColor( color );
01223   text_marker_.scale = scale;
01224 
01225   loadMarkerPub(); // always check this before publishing
01226   pub_rviz_marker_.publish( text_marker_ );
01227   ros::spinOnce();
01228 
01229   // Restore the ID count if needed
01230   if (static_id)
01231     text_marker_.id = temp_id;
01232 
01233   return true;
01234 }
01235 
01236 bool VisualTools::publishMarker(const visualization_msgs::Marker &marker)
01237 {
01238   if(muted_)
01239     return true;
01240 
01241   loadMarkerPub(); // always check this before publishing
01242   pub_rviz_marker_.publish( marker );
01243   ros::spinOnce();
01244 
01245   return true;
01246 }
01247 
01248 bool VisualTools::publishGrasps(const std::vector<moveit_msgs::Grasp>& possible_grasps,
01249                                 const std::string &ee_parent_link)
01250 {
01251   if(muted_)
01252   {
01253     ROS_DEBUG_STREAM_NAMED("visual_tools","Not visualizing grasps - muted.");
01254     return false;
01255   }
01256 
01257   ROS_DEBUG_STREAM_NAMED("visual_tools","Visualizing " << possible_grasps.size() << " grasps with parent link "
01258                          << ee_parent_link);
01259 
01260   // Loop through all grasps
01261   for (std::size_t i = 0; i < possible_grasps.size(); ++i)
01262   {
01263     if( !ros::ok() )  // Check that ROS is still ok and that user isn't trying to quit
01264       break;
01265 
01266     ROS_DEBUG_STREAM_NAMED("grasp","Visualizing grasp pose " << i);
01267 
01268     publishEEMarkers(possible_grasps[i].grasp_pose.pose);
01269 
01270     ros::Duration(0.1).sleep();
01271   }
01272 
01273   return true;
01274 }
01275 
01276 bool VisualTools::publishAnimatedGrasps(const std::vector<moveit_msgs::Grasp>& possible_grasps,
01277                                         const std::string &ee_parent_link, double animate_speed)
01278 {
01279   if(muted_)
01280   {
01281     ROS_DEBUG_STREAM_NAMED("visual_tools","Not visualizing grasps - muted.");
01282     return false;
01283   }
01284 
01285   ROS_DEBUG_STREAM_NAMED("visual_tools","Visualizing " << possible_grasps.size() << " grasps with parent link "
01286                          << ee_parent_link << " at speed " << animate_speed);
01287 
01288   // Loop through all grasps
01289   for (std::size_t i = 0; i < possible_grasps.size(); ++i)
01290   {
01291     if( !ros::ok() )  // Check that ROS is still ok and that user isn't trying to quit
01292       break;
01293 
01294     publishAnimatedGrasp(possible_grasps[i], ee_parent_link, animate_speed);
01295 
01296     ros::Duration(0.1).sleep();
01297   }
01298 
01299   return true;
01300 }
01301 
01302 bool VisualTools::publishAnimatedGrasp(const moveit_msgs::Grasp &grasp, const std::string &ee_parent_link, double animate_speed)
01303 {
01304   if(muted_)
01305     return true;
01306 
01307   // Grasp Pose Variables
01308   geometry_msgs::Pose grasp_pose = grasp.grasp_pose.pose;
01309   Eigen::Affine3d grasp_pose_eigen;
01310   tf::poseMsgToEigen(grasp_pose, grasp_pose_eigen);
01311 
01312   // Pre-grasp pose variables
01313   geometry_msgs::Pose pre_grasp_pose;
01314   Eigen::Affine3d pre_grasp_pose_eigen;
01315 
01316   // Approach direction variables
01317   Eigen::Vector3d pre_grasp_approach_direction_local;
01318 
01319   // Display Grasp Score
01320   std::string text = "Grasp Quality: " + boost::lexical_cast<std::string>(int(grasp.grasp_quality*100)) + "%";
01321   publishText(grasp_pose, text);
01322 
01323   // Convert the grasp pose into the frame of reference of the approach/retreat frame_id
01324 
01325   // Animate the movement - for ee approach direction
01326   double animation_resulution = 0.1; // the lower the better the resolution
01327   for(double percent = 0; percent < 1; percent += animation_resulution)
01328   {
01329     if( !ros::ok() ) // Check that ROS is still ok and that user isn't trying to quit
01330       break;
01331 
01332     // Copy original grasp pose to pre-grasp pose
01333     pre_grasp_pose_eigen = grasp_pose_eigen;
01334 
01335     // The direction of the pre-grasp
01336     // Calculate the current animation position based on the percent
01337     Eigen::Vector3d pre_grasp_approach_direction = Eigen::Vector3d(
01338                                                                    -1 * grasp.pre_grasp_approach.direction.vector.x * grasp.pre_grasp_approach.desired_distance * (1-percent),
01339                                                                    -1 * grasp.pre_grasp_approach.direction.vector.y * grasp.pre_grasp_approach.desired_distance * (1-percent),
01340                                                                    -1 * grasp.pre_grasp_approach.direction.vector.z * grasp.pre_grasp_approach.desired_distance * (1-percent)
01341                                                                    );
01342 
01343     // Decide if we need to change the approach_direction to the local frame of the end effector orientation
01344     if( grasp.pre_grasp_approach.direction.header.frame_id == ee_parent_link )
01345     {
01346       // Apply/compute the approach_direction vector in the local frame of the grasp_pose orientation
01347       pre_grasp_approach_direction_local = grasp_pose_eigen.rotation() * pre_grasp_approach_direction;
01348     }
01349     else
01350     {
01351       pre_grasp_approach_direction_local = pre_grasp_approach_direction; //grasp_pose_eigen.rotation() * pre_grasp_approach_direction;
01352     }
01353 
01354     // Update the grasp matrix usign the new locally-framed approach_direction
01355     pre_grasp_pose_eigen.translation() += pre_grasp_approach_direction_local;
01356 
01357     // Convert eigen pre-grasp position back to regular message
01358     tf::poseEigenToMsg(pre_grasp_pose_eigen, pre_grasp_pose);
01359 
01360     //publishArrow(pre_grasp_pose, moveit_visual_tools::BLUE);
01361     publishEEMarkers(pre_grasp_pose);
01362 
01363     ros::Duration(animate_speed).sleep();
01364   }
01365   return true;
01366 }
01367 
01368 bool VisualTools::publishIKSolutions(const std::vector<trajectory_msgs::JointTrajectoryPoint> &ik_solutions,
01369                                      const std::string& planning_group, double display_time)
01370 {
01371   if(muted_)
01372   {
01373     ROS_DEBUG_STREAM_NAMED("visual_tools","Not visualizing inverse kinematic solutions - muted.");
01374     return false;
01375   }
01376 
01377   if (ik_solutions.empty())
01378   {
01379     ROS_WARN_STREAM_NAMED("visual_tools","Empty ik_solutions vector passed into publishIKSolutions()");
01380     return false;
01381   }
01382 
01383   loadSharedRobotState();
01384 
01385   ROS_DEBUG_STREAM_NAMED("visual_tools","Visualizing " << ik_solutions.size() << " inverse kinematic solutions");
01386 
01387   // Get robot model
01388   robot_model::RobotModelConstPtr robot_model = shared_robot_state_->getRobotModel();
01389   // Get joint state group
01390   const robot_model::JointModelGroup* joint_model_group = robot_model->getJointModelGroup(planning_group);
01391 
01392   if (joint_model_group == NULL) // not found
01393   {
01394     ROS_ERROR_STREAM_NAMED("publishIKSolutions","Could not find joint model group " << planning_group);
01395     return false;
01396   }
01397 
01398   // Apply the time to the trajectory
01399   trajectory_msgs::JointTrajectoryPoint trajectory_pt_timed;
01400 
01401   // Create a trajectory with one point
01402   moveit_msgs::RobotTrajectory trajectory_msg;
01403   trajectory_msg.joint_trajectory.header.frame_id = base_frame_;
01404   trajectory_msg.joint_trajectory.joint_names = joint_model_group->getJointModelNames();
01405 
01406   // Overall length of trajectory
01407   double running_time = 0;
01408 
01409   // Loop through all inverse kinematic solutions
01410   for (std::size_t i = 0; i < ik_solutions.size(); ++i)
01411   {
01412     if( !ros::ok() )  // Check that ROS is still ok and that user isn't trying to quit
01413       break;
01414 
01415     trajectory_pt_timed = ik_solutions[i];
01416     trajectory_pt_timed.time_from_start = ros::Duration(running_time);
01417     trajectory_msg.joint_trajectory.points.push_back(trajectory_pt_timed);
01418 
01419     running_time += display_time;
01420 
01421     //ROS_DEBUG_STREAM_NAMED("grasp","Visualizing ik solution " << i);
01422   }
01423 
01424   // Re-add final position so the last point is displayed fully
01425   trajectory_pt_timed = trajectory_msg.joint_trajectory.points.back();
01426   trajectory_pt_timed.time_from_start = ros::Duration(running_time);
01427   trajectory_msg.joint_trajectory.points.push_back(trajectory_pt_timed);
01428 
01429   return publishTrajectoryPath(trajectory_msg, true);
01430 }
01431 
01432 bool VisualTools::publishRemoveAllCollisionObjects()
01433 {
01434   // Publish an empty REMOVE message so as to remove all of them
01435 
01436   moveit_msgs::PlanningScene planning_scene;
01437   planning_scene.is_diff = true;
01438   planning_scene.world.collision_objects.clear();
01439 
01440   // Clean up old collision objects
01441   moveit_msgs::CollisionObject remove_object;
01442   remove_object.header.frame_id = base_frame_;
01443   remove_object.operation = moveit_msgs::CollisionObject::REMOVE;
01444 
01445   planning_scene.world.collision_objects.push_back(remove_object);
01446 
01447   // Publish
01448   loadPlanningPub(); // always call this before publishing
01449   pub_planning_scene_diff_.publish(planning_scene);
01450   ros::spinOnce();
01451 
01452   return true;
01453 }
01454 
01455 bool VisualTools::removeAllCollisionObjectsPS()
01456 {
01457   // Clean up old collision objects
01458   moveit_msgs::CollisionObject remove_object;
01459   remove_object.header.frame_id = base_frame_;
01460   remove_object.operation = moveit_msgs::CollisionObject::REMOVE;
01461 
01462   processCollisionObjectMsg(remove_object);
01463 }
01464 
01465 bool VisualTools::cleanupCO(std::string name)
01466 {
01467   // Clean up old collision objects
01468   moveit_msgs::CollisionObject co;
01469   co.header.stamp = ros::Time::now();
01470   co.header.frame_id = base_frame_;
01471   co.id = name;
01472   co.operation = moveit_msgs::CollisionObject::REMOVE;
01473 
01474   loadCollisionPub(); // always call this before publishing
01475   pub_collision_obj_.publish(co);
01476   ros::spinOnce();
01477   return true;
01478 }
01479 
01480 bool VisualTools::cleanupACO(const std::string& name)
01481 {
01482   // Clean up old attached collision object
01483   moveit_msgs::AttachedCollisionObject aco;
01484   aco.object.header.stamp = ros::Time::now();
01485   aco.object.header.frame_id = base_frame_;
01486 
01487   //aco.object.id = name;
01488   aco.object.operation = moveit_msgs::CollisionObject::REMOVE;
01489 
01490   //aco.link_name = ee_parent_link_;
01491 
01492   loadAttachedPub(); // always call this before publishing
01493   pub_attach_collision_obj_.publish(aco);
01494   ros::spinOnce();
01495   return true;
01496 }
01497 
01498 bool VisualTools::attachCO(const std::string& name, const std::string& ee_parent_link)
01499 {
01500   // Clean up old attached collision object
01501   moveit_msgs::AttachedCollisionObject aco;
01502   aco.object.header.stamp = ros::Time::now();
01503   aco.object.header.frame_id = base_frame_;
01504 
01505   aco.object.id = name;
01506   aco.object.operation = moveit_msgs::CollisionObject::ADD;
01507 
01508   // Link to attach the object to
01509   aco.link_name = ee_parent_link;
01510 
01511   loadAttachedPub(); // always call this before publishing
01512   pub_attach_collision_obj_.publish(aco);
01513   ros::spinOnce();
01514   return true;
01515 }
01516 
01517 bool VisualTools::publishCollisionFloor(double z, std::string plane_name)
01518 {
01519   moveit_msgs::CollisionObject collision_obj;
01520   collision_obj.header.stamp = ros::Time::now();
01521   collision_obj.header.frame_id = base_frame_;
01522   collision_obj.id = plane_name;
01523   collision_obj.operation = moveit_msgs::CollisionObject::ADD;  
01524   collision_obj.planes.resize(1);
01525   // Representation of a plane, using the plane equation ax + by + cz + d = 0
01526   collision_obj.planes[0].coef[0] = 0; // a
01527   collision_obj.planes[0].coef[1] = 0; // b
01528   collision_obj.planes[0].coef[2] = 0; // c
01529   collision_obj.planes[0].coef[3] = 0; // d
01530   // Pose
01531   geometry_msgs::Pose floor_pose;
01532 
01533   // Position
01534   floor_pose.position.x = 0;
01535   floor_pose.position.y = 0;
01536   floor_pose.position.z = z;
01537 
01538   // Orientation
01539   Eigen::Quaterniond quat(Eigen::AngleAxis<double>(0.0, Eigen::Vector3d::UnitZ()));
01540   floor_pose.orientation.x = quat.x();
01541   floor_pose.orientation.y = quat.y();
01542   floor_pose.orientation.z = quat.z();
01543   floor_pose.orientation.w = quat.w();
01544 
01545   collision_obj.plane_poses.resize(1);
01546   collision_obj.plane_poses[0] = floor_pose;
01547 
01548   ROS_INFO_STREAM_NAMED("pick_place","CollisionObject: \n " << collision_obj);
01549 
01550   processCollisionObjectMsg(collision_obj);
01551 
01552   ROS_DEBUG_STREAM_NAMED("visual_tools","Published collision object " << plane_name);
01553   return true;
01554 }
01555 
01556 bool VisualTools::publishCollisionBlock(geometry_msgs::Pose block_pose, std::string block_name, double block_size)
01557 {
01558   moveit_msgs::CollisionObject collision_obj;
01559   collision_obj.header.stamp = ros::Time::now();
01560   collision_obj.header.frame_id = base_frame_;
01561   collision_obj.id = block_name;
01562   collision_obj.operation = moveit_msgs::CollisionObject::ADD;
01563   collision_obj.primitives.resize(1);
01564   collision_obj.primitives[0].type = shape_msgs::SolidPrimitive::BOX;
01565   collision_obj.primitives[0].dimensions.resize(shape_tools::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::BOX>::value);
01566   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_X] = block_size;
01567   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Y] = block_size;
01568   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Z] = block_size;
01569   collision_obj.primitive_poses.resize(1);
01570   collision_obj.primitive_poses[0] = block_pose;
01571 
01572   //ROS_INFO_STREAM_NAMED("pick_place","CollisionObject: \n " << collision_obj);
01573 
01574   loadCollisionPub(); // always call this before publishing
01575   pub_collision_obj_.publish(collision_obj);
01576   ros::spinOnce();
01577 
01578   ROS_DEBUG_STREAM_NAMED("visual_tools","Published collision object " << block_name);
01579   return true;
01580 }
01581 
01582 bool VisualTools::publishCollisionCylinder(geometry_msgs::Point a, geometry_msgs::Point b, std::string object_name, double radius)
01583 {
01584   return publishCollisionCylinder(convertPoint(a), convertPoint(b), object_name, radius);
01585 }
01586 
01587 bool VisualTools::publishCollisionCylinder(Eigen::Vector3d a, Eigen::Vector3d b, std::string object_name, double radius)
01588 {
01589   // Distance between two points
01590   double height = (a - b).lpNorm<2>();
01591 
01592   // Find center point
01593   Eigen::Vector3d pt_center = getCenterPoint(a, b);
01594 
01595   // Create vector
01596   Eigen::Affine3d pose;
01597   pose = getVectorBetweenPoints(pt_center, b);
01598 
01599   // Convert pose to be normal to cylindar axis
01600   Eigen::Affine3d rotation;
01601   rotation = Eigen::AngleAxisd(0.5*M_PI, Eigen::Vector3d::UnitY());
01602   pose = pose * rotation;
01603 
01604   return publishCollisionCylinder(pose, object_name, radius, height);
01605 }
01606 
01607 bool VisualTools::publishCollisionCylinder(Eigen::Affine3d object_pose, std::string object_name, double radius, double height)
01608 {
01609   return publishCollisionCylinder(convertPose(object_pose), object_name, radius, height);
01610 }
01611 
01612 bool VisualTools::publishCollisionCylinder(geometry_msgs::Pose object_pose, std::string object_name, double radius, double height)
01613 {
01614   moveit_msgs::CollisionObject collision_obj;
01615   collision_obj.header.stamp = ros::Time::now();
01616   collision_obj.header.frame_id = base_frame_;
01617   collision_obj.id = object_name;
01618   collision_obj.operation = moveit_msgs::CollisionObject::ADD;
01619   collision_obj.primitives.resize(1);
01620   collision_obj.primitives[0].type = shape_msgs::SolidPrimitive::CYLINDER;
01621   collision_obj.primitives[0].dimensions.resize(shape_tools::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::CYLINDER>::value);
01622   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::CYLINDER_HEIGHT] = height;
01623   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::CYLINDER_RADIUS] = radius;
01624   collision_obj.primitive_poses.resize(1);
01625   collision_obj.primitive_poses[0] = object_pose;
01626 
01627   //ROS_INFO_STREAM_NAMED("pick_place","CollisionObject: \n " << collision_obj);
01628 
01629   loadCollisionPub(); // always call this before publishing
01630   pub_collision_obj_.publish(collision_obj);
01631   ros::spinOnce();
01632 
01633   //ROS_DEBUG_STREAM_NAMED("visual_tools","Published collision object " << object_name);
01634   return true;
01635 }
01636 
01637 bool VisualTools::publishCollisionGraph(const graph_msgs::GeometryGraph &graph, const std::string &object_name, double radius)
01638 {
01639   ROS_INFO_STREAM_NAMED("publishCollisionGraph","Preparing to create collision graph");
01640 
01641   // The graph is one collision object with many primitives
01642   moveit_msgs::CollisionObject collision_obj;
01643   collision_obj.header.stamp = ros::Time::now();
01644   collision_obj.header.frame_id = base_frame_;
01645   collision_obj.id = object_name;
01646   collision_obj.operation = moveit_msgs::CollisionObject::ADD;
01647 
01648   // Track which pairs of nodes we've already connected since graph is bi-directional
01649   typedef std::pair<std::size_t, std::size_t> node_ids;
01650   std::set<node_ids> added_edges;
01651   std::pair<std::set<node_ids>::iterator,bool> return_value;
01652 
01653   Eigen::Vector3d a, b;
01654   for (std::size_t i = 0; i < graph.nodes.size(); ++i)
01655   {
01656     for (std::size_t j = 0; j < graph.edges[i].node_ids.size(); ++j)
01657     {
01658       // Check if we've already added this pair of nodes (edge)
01659       return_value = added_edges.insert( node_ids(i,j) );
01660       if (return_value.second == false)
01661       {
01662         // Element already existed in set, so don't add a new collision object
01663       }
01664       else
01665       {
01666         // Create a cylinder from two points
01667         a = convertPoint(graph.nodes[i]);
01668         b = convertPoint(graph.nodes[graph.edges[i].node_ids[j]]);
01669 
01670         // add other direction of edge
01671         added_edges.insert( node_ids(j,i) );
01672 
01673         // Distance between two points
01674         double height = (a - b).lpNorm<2>();
01675 
01676         // Find center point
01677         Eigen::Vector3d pt_center = getCenterPoint(a, b);
01678 
01679         // Create vector
01680         Eigen::Affine3d pose;
01681         pose = getVectorBetweenPoints(pt_center, b);
01682 
01683         // Convert pose to be normal to cylindar axis
01684         Eigen::Affine3d rotation;
01685         rotation = Eigen::AngleAxisd(0.5*M_PI, Eigen::Vector3d::UnitY());
01686         pose = pose * rotation;
01687 
01688         // Create the solid primitive
01689         shape_msgs::SolidPrimitive cylinder;
01690         cylinder.type = shape_msgs::SolidPrimitive::CYLINDER;
01691         cylinder.dimensions.resize(shape_tools::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::CYLINDER>::value);
01692         cylinder.dimensions[shape_msgs::SolidPrimitive::CYLINDER_HEIGHT] = height;
01693         cylinder.dimensions[shape_msgs::SolidPrimitive::CYLINDER_RADIUS] = radius;
01694 
01695         // Add to the collision object
01696         collision_obj.primitives.push_back(cylinder);
01697 
01698         // Add the pose
01699         collision_obj.primitive_poses.push_back(convertPose(pose));
01700       }
01701     }
01702   }
01703 
01704   loadCollisionPub(); // always call this before publishing
01705   pub_collision_obj_.publish(collision_obj);
01706   ros::spinOnce();
01707 
01708   return true;
01709 }
01710 
01711 void VisualTools::getCollisionWallMsg(double x, double y, double angle, double width, const std::string name,
01712                                       moveit_msgs::CollisionObject &collision_obj)
01713 {
01714   collision_obj.header.stamp = ros::Time::now();
01715   collision_obj.header.frame_id = base_frame_;
01716   collision_obj.operation = moveit_msgs::CollisionObject::ADD;
01717   collision_obj.primitives.resize(1);
01718   collision_obj.primitives[0].type = shape_msgs::SolidPrimitive::BOX;
01719   collision_obj.primitives[0].dimensions.resize(shape_tools::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::BOX>::value);
01720 
01721   geometry_msgs::Pose rec_pose;
01722 
01723   // ----------------------------------------------------------------------------------
01724   // Name
01725   collision_obj.id = name;
01726 
01727   double depth = 0.1;
01728   double height = 2.5;
01729 
01730   // Position
01731   rec_pose.position.x = x;
01732   rec_pose.position.y = y;
01733   rec_pose.position.z = height / 2 + floor_to_base_height_;
01734 
01735   // Size
01736   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_X] = depth;
01737   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Y] = width;
01738   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Z] = height;
01739   // ----------------------------------------------------------------------------------
01740 
01741   Eigen::Quaterniond quat(Eigen::AngleAxis<double>(double(angle), Eigen::Vector3d::UnitZ()));
01742   rec_pose.orientation.x = quat.x();
01743   rec_pose.orientation.y = quat.y();
01744   rec_pose.orientation.z = quat.z();
01745   rec_pose.orientation.w = quat.w();
01746 
01747   collision_obj.primitive_poses.resize(1);
01748   collision_obj.primitive_poses[0] = rec_pose;
01749 }
01750 
01751 bool VisualTools::publishCollisionWall(double x, double y, double angle, double width, const std::string name)
01752 {
01753   moveit_msgs::CollisionObject collision_obj;
01754   getCollisionWallMsg(x, y, angle, width, name, collision_obj);
01755 
01756   loadCollisionPub(); // always call this before publishing
01757   pub_collision_obj_.publish(collision_obj);
01758   ros::spinOnce();
01759 
01760   return true;
01761 }
01762 
01763 bool VisualTools::publishCollisionTable(double x, double y, double angle, double width, double height,
01764                                         double depth, const std::string name)
01765 {
01766   geometry_msgs::Pose table_pose;
01767 
01768   // Position
01769   table_pose.position.x = x;
01770   table_pose.position.y = y;
01771   table_pose.position.z = height / 2 + floor_to_base_height_;
01772 
01773   // Orientation
01774   Eigen::Quaterniond quat(Eigen::AngleAxis<double>(double(angle), Eigen::Vector3d::UnitZ()));
01775   table_pose.orientation.x = quat.x();
01776   table_pose.orientation.y = quat.y();
01777   table_pose.orientation.z = quat.z();
01778   table_pose.orientation.w = quat.w();
01779 
01780   moveit_msgs::CollisionObject collision_obj;
01781   collision_obj.header.stamp = ros::Time::now();
01782   collision_obj.header.frame_id = base_frame_;
01783   collision_obj.id = name;
01784   collision_obj.operation = moveit_msgs::CollisionObject::ADD;
01785   collision_obj.primitives.resize(1);
01786   collision_obj.primitives[0].type = shape_msgs::SolidPrimitive::BOX;
01787   collision_obj.primitives[0].dimensions.resize(shape_tools::SolidPrimitiveDimCount<shape_msgs::SolidPrimitive::BOX>::value);
01788 
01789   // Size
01790   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_X] = depth;
01791   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Y] = width;
01792   collision_obj.primitives[0].dimensions[shape_msgs::SolidPrimitive::BOX_Z] = height;
01793 
01794   collision_obj.primitive_poses.resize(1);
01795   collision_obj.primitive_poses[0] = table_pose;
01796 
01797   loadCollisionPub(); // always call this before publishing
01798   pub_collision_obj_.publish(collision_obj);
01799   ros::spinOnce();
01800 
01801   return true;
01802 }
01803 
01804 bool VisualTools::loadCollisionSceneFromFile(const std::string &path)
01805 {
01806   {
01807     // Load directly to the planning scene
01808     planning_scene_monitor::LockedPlanningSceneRW scene(getPlanningSceneMonitor());
01809     if (scene)
01810     {
01811 
01812       std::ifstream fin(path.c_str());
01813       if (fin.good())
01814       {
01815         scene->loadGeometryFromStream(fin);
01816         fin.close();
01817         ROS_INFO("Loaded scene geometry from '%s'", path.c_str());
01818       }
01819       else
01820         ROS_WARN("Unable to load scene geometry from '%s'", path.c_str());
01821     }
01822     else
01823       ROS_WARN_STREAM_NAMED("temp","Unable to get locked planning scene RW");
01824   }
01825   getPlanningSceneMonitor()->triggerSceneUpdateEvent(planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE);
01826 }
01827 
01828 bool VisualTools::publishTrajectoryPoint(const trajectory_msgs::JointTrajectoryPoint& trajectory_pt,
01829                                          const std::string &group_name, double display_time)
01830 {
01831   loadSharedRobotState();
01832 
01833   // Get robot model
01834   robot_model::RobotModelConstPtr robot_model = shared_robot_state_->getRobotModel();
01835   // Get joint state group
01836   const robot_model::JointModelGroup* joint_model_group = robot_model->getJointModelGroup(group_name);
01837 
01838   if (joint_model_group == NULL) // not found
01839   {
01840     ROS_ERROR_STREAM_NAMED("publishTrajectoryPoint","Could not find joint model group " << group_name);
01841     return false;
01842   }
01843 
01844   // Apply the time to the trajectory
01845   trajectory_msgs::JointTrajectoryPoint trajectory_pt_timed = trajectory_pt;
01846   trajectory_pt_timed.time_from_start = ros::Duration(display_time);
01847 
01848   // Create a trajectory with one point
01849   moveit_msgs::RobotTrajectory trajectory_msg;
01850   trajectory_msg.joint_trajectory.header.frame_id = base_frame_;
01851   trajectory_msg.joint_trajectory.joint_names = joint_model_group->getJointModelNames();
01852   trajectory_msg.joint_trajectory.points.push_back(trajectory_pt);
01853   trajectory_msg.joint_trajectory.points.push_back(trajectory_pt_timed);
01854 
01855   return publishTrajectoryPath(trajectory_msg, true);
01856 }
01857 
01858 bool VisualTools::publishTrajectoryPath(const robot_trajectory::RobotTrajectory& trajectory, bool blocking)
01859 {
01860   moveit_msgs::RobotTrajectory trajectory_msg;
01861   trajectory.getRobotTrajectoryMsg(trajectory_msg);
01862 
01863   // Add time from start if none specified
01864   if (trajectory_msg.joint_trajectory.points.size() > 1)
01865   {
01866     if (trajectory_msg.joint_trajectory.points[1].time_from_start == ros::Duration(0)) // assume no timestamps exist
01867     {
01868       for (std::size_t i = 0; i < trajectory_msg.joint_trajectory.points.size(); ++i)
01869       {
01870         trajectory_msg.joint_trajectory.points[i].time_from_start = ros::Duration(i*2); // 1 hz
01871       }
01872     }
01873   }
01874 
01875   //std::cout << "trajectory_msg:\n " << trajectory_msg << std::endl;
01876 
01877   publishTrajectoryPath(trajectory_msg, blocking);
01878 }
01879 
01880 bool VisualTools::publishTrajectoryPath(const moveit_msgs::RobotTrajectory& trajectory_msg, bool blocking)
01881 {
01882   loadSharedRobotState();
01883 
01884   // Check if we have enough points
01885   if (!trajectory_msg.joint_trajectory.points.size())
01886   {
01887     ROS_WARN_STREAM_NAMED("temp","Unable to publish trajectory path because trajectory has zero points");
01888     return false;
01889   }
01890 
01891   // Create the message  TODO move to member function to load less often
01892   moveit_msgs::DisplayTrajectory display_trajectory_msg;
01893   display_trajectory_msg.model_id = robot_model_->getName();
01894 
01895   //    display_trajectory_msg.trajectory_start = start_state;
01896   display_trajectory_msg.trajectory.resize(1);
01897   display_trajectory_msg.trajectory[0] = trajectory_msg;
01898 
01899   // Publish message
01900   loadTrajectoryPub(); // always call this before publishing
01901   //std::cout << "visual_tools: " << display_trajectory_msg << std::endl;
01902   pub_display_path_.publish(display_trajectory_msg);
01903   ros::spinOnce();
01904 
01905   // Wait the duration of the trajectory
01906   if( blocking )
01907   {
01908     ROS_INFO_STREAM_NAMED("visual_tools","Waiting for trajectory animation "
01909                           << trajectory_msg.joint_trajectory.points.back().time_from_start << " seconds");
01910 
01911     // Check if ROS is ok in intervals
01912     double counter = 0;
01913     while (ros::ok() && counter < trajectory_msg.joint_trajectory.points.back().time_from_start.toSec())
01914     {
01915       counter += 0.25; // check every fourth second
01916       ros::Duration(0.25).sleep();
01917     }
01918   }
01919 
01920   return true;
01921 }
01922 
01923 bool VisualTools::publishRobotState(const robot_state::RobotStatePtr &robot_state)
01924 {
01925   publishRobotState(*robot_state.get());
01926 }
01927 
01928 bool VisualTools::publishRobotState(const robot_state::RobotState &robot_state)
01929 {
01930   robot_state::robotStateToRobotStateMsg(robot_state, display_robot_msg_.state);
01931 
01932   loadRobotStatePub(); // always call this before publishing
01933   pub_robot_state_.publish( display_robot_msg_ );
01934   ros::spinOnce();
01935 
01936   return true;
01937 }
01938 
01939 bool VisualTools::publishRobotState(const trajectory_msgs::JointTrajectoryPoint& trajectory_pt,
01940                                     const std::string &group_name)
01941 {
01942   // Always load the robot state before using
01943   loadSharedRobotState();
01944 
01945   // Set robot state
01946   shared_robot_state_->setToDefaultValues(); // reset the state just in case
01947   shared_robot_state_->setJointGroupPositions(group_name, trajectory_pt.positions);
01948 
01949   // Publish robot state
01950   publishRobotState(*shared_robot_state_);
01951 
01952   return true;
01953 }
01954 
01955 bool VisualTools::hideRobot()
01956 {
01957   // Always load the robot state before using
01958   loadSharedRobotState();
01959 
01960   shared_robot_state_->setVariablePosition("virtual_joint/trans_x", 10);
01961   shared_robot_state_->setVariablePosition("virtual_joint/trans_y", 10);
01962   shared_robot_state_->setVariablePosition("virtual_joint/trans_z", 10);
01963       
01964   publishRobotState(shared_robot_state_);
01965 }
01966 
01967 bool VisualTools::publishTest()
01968 {
01969   // Create pose
01970   geometry_msgs::Pose pose;
01971   generateRandomPose(pose);
01972 
01973   // Publish arrow vector of pose
01974   ROS_INFO_STREAM_NAMED("test","Publishing Arrow");
01975   publishArrow(pose, moveit_visual_tools::RED, moveit_visual_tools::LARGE);
01976 
01977   return true;
01978 }
01979 
01980 geometry_msgs::Pose VisualTools::convertPose(const Eigen::Affine3d &pose)
01981 {
01982   geometry_msgs::Pose pose_msg;
01983   tf::poseEigenToMsg(pose, pose_msg);
01984   return pose_msg;
01985 }
01986 
01987 Eigen::Affine3d VisualTools::convertPose(const geometry_msgs::Pose &pose)
01988 {
01989   Eigen::Affine3d pose_eigen;
01990   tf::poseMsgToEigen(pose, pose_eigen);
01991   return pose_eigen;
01992 }
01993 
01994 Eigen::Affine3d VisualTools::convertPoint32ToPose(const geometry_msgs::Point32 &point)
01995 {
01996   Eigen::Affine3d pose_eigen = Eigen::Affine3d::Identity();
01997   pose_eigen.translation().x() = point.x;
01998   pose_eigen.translation().y() = point.y;
01999   pose_eigen.translation().z() = point.z;
02000   return pose_eigen;
02001 }
02002 
02003 geometry_msgs::Pose VisualTools::convertPointToPose(const geometry_msgs::Point &point)
02004 {
02005   geometry_msgs::Pose pose_msg;
02006   pose_msg.position = point;
02007   return pose_msg;
02008 }
02009 
02010 geometry_msgs::Point convertPoseToPoint(const Eigen::Affine3d &pose)
02011 {
02012   geometry_msgs::Pose pose_msg;
02013   tf::poseEigenToMsg(pose, pose_msg);
02014   return pose_msg.position;
02015 }
02016 
02017 Eigen::Vector3d VisualTools::convertPoint(const geometry_msgs::Point &point)
02018 {
02019   Eigen::Vector3d point_eigen;
02020   point_eigen[0] = point.x;
02021   point_eigen[1] = point.y;
02022   point_eigen[2] = point.z;
02023   return point_eigen;
02024 }
02025 
02026 Eigen::Vector3d VisualTools::convertPoint32(const geometry_msgs::Point32 &point)
02027 {
02028   Eigen::Vector3d point_eigen;
02029   point_eigen[0] = point.x;
02030   point_eigen[1] = point.y;
02031   point_eigen[2] = point.z;
02032   return point_eigen;
02033 }
02034 
02035 geometry_msgs::Point32 VisualTools::convertPoint32(const Eigen::Vector3d &point)
02036 {
02037   geometry_msgs::Point32 point_msg;
02038   point_msg.x = point[0];
02039   point_msg.y = point[1];
02040   point_msg.z = point[2];
02041   return point_msg;
02042 }
02043 
02044 void VisualTools::generateRandomPose(geometry_msgs::Pose& pose)
02045 {
02046   // Position
02047   pose.position.x = dRand(0, 1);
02048   pose.position.y = dRand(0, 1);
02049   pose.position.z = dRand(0, 1);
02050 
02051   // Orientation on place
02052   double angle = M_PI * dRand(0.1,1.0);
02053   Eigen::Quaterniond quat(Eigen::AngleAxis<double>(double(angle), Eigen::Vector3d::UnitZ()));
02054   pose.orientation.x = quat.x();
02055   pose.orientation.y = quat.y();
02056   pose.orientation.z = quat.z();
02057   pose.orientation.w = quat.w();
02058 }
02059 
02060 double VisualTools::dRand(double dMin, double dMax)
02061 {
02062   double d = (double)rand() / RAND_MAX;
02063   return dMin + d * (dMax - dMin);
02064 }
02065 
02066 float VisualTools::fRand(float dMin, float dMax)
02067 {
02068   float d = (float)rand() / RAND_MAX;
02069   return dMin + d * (dMax - dMin);
02070 }
02071 
02072 int VisualTools::iRand(int dMin, int dMax)
02073 {
02074   int d = (int)rand() / RAND_MAX;
02075   return dMin + d * (dMax - dMin);
02076 }
02077 
02078 void VisualTools::print()
02079 {
02080   ROS_WARN_STREAM_NAMED("visual_tools","Debug Visual Tools variable values:");
02081   std::cout << "marker_topic_: " << marker_topic_ << std::endl;
02082   std::cout << "base_frame_: " << base_frame_ << std::endl;
02083   std::cout << "floor_to_base_height_: " << floor_to_base_height_ << std::endl;
02084   std::cout << "marker_lifetime_: " << marker_lifetime_.toSec() << std::endl;
02085   std::cout << "muted_: " << muted_ << std::endl;
02086   std::cout << "alpha_: " << alpha_ << std::endl;
02087 }
02088 
02089 } // namespace
02090 
02091 
02098 /*
02099   bool VisualTools::publishPlanningScene(std::vector<double> joint_values)
02100   {
02101   if(muted_)
02102   return true; // this function will only work if we have loaded the publishers
02103 
02104   ROS_DEBUG_STREAM_NAMED("visual_tools","Publishing planning scene");
02105 
02106   // Output debug
02107   //ROS_INFO_STREAM_NAMED("visual_tools","Joint values being sent to planning scene:");
02108   //std::copy(joint_values.begin(),joint_values.end(), std::ostream_iterator<double>(std::cout, "\n"));
02109 
02110   // Update planning scene
02111   robot_state::JointStateGroup* joint_state_group = getPlanningSceneMonitor()->getPlanningScene()->getCurrentStateNonConst()
02112   .getJointStateGroup(planning_group_name_);
02113   joint_state_group->setVariableValues(joint_values);
02114 
02115   //    getPlanningSceneMonitor()->updateFrameTransforms();
02116   getPlanningSceneMonitor()->triggerSceneUpdateEvent(planning_scene_monitor::PlanningSceneMonitor::UPDATE_SCENE);
02117 
02118   return true;
02119   }
02120 */
02121 


moveit_visual_tools
Author(s): Dave Coleman
autogenerated on Wed Aug 26 2015 14:54:49