grasp_filter.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2013, 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 #include <moveit_simple_grasps/grasp_filter.h>
00036 #include <moveit/transforms/transforms.h>
00037 
00038 // Conversions
00039 #include <eigen_conversions/eigen_msg.h> // add to pkg TODO
00040 
00041 namespace moveit_simple_grasps
00042 {
00043 
00044 // Constructor
00045 GraspFilter::GraspFilter( robot_state::RobotState robot_state,
00046   moveit_visual_tools::VisualToolsPtr& visual_tools ):
00047   robot_state_(robot_state),
00048   visual_tools_(visual_tools),
00049   verbose_(false)
00050 {
00051   ROS_DEBUG_STREAM_NAMED("filter","Loaded simple grasp filter");
00052 }
00053 
00054 GraspFilter::~GraspFilter()
00055 {
00056 }
00057 
00058 bool GraspFilter::chooseBestGrasp( const std::vector<moveit_msgs::Grasp>& possible_grasps, moveit_msgs::Grasp& chosen )
00059 {
00060   // TODO: better logic here
00061   if( possible_grasps.empty() )
00062   {
00063     ROS_ERROR_NAMED("filter","There are no grasps to choose from");
00064     return false;
00065   }
00066   chosen = possible_grasps[0]; // just choose first one
00067   return true;
00068 }
00069 
00070 // Return grasps that are kinematically feasible
00071 bool GraspFilter::filterGrasps(std::vector<moveit_msgs::Grasp>& possible_grasps,
00072   std::vector<trajectory_msgs::JointTrajectoryPoint>& ik_solutions, bool filter_pregrasp,
00073   const std::string &ee_parent_link, const std::string& planning_group)
00074 {
00075   // -----------------------------------------------------------------------------------------------
00076   // Error check
00077   if( possible_grasps.empty() )
00078   {
00079     ROS_ERROR_NAMED("filter","Unable to filter grasps because vector is empty");
00080     return false;
00081   }
00082 
00083   // -----------------------------------------------------------------------------------------------
00084   // how many cores does this computer have and how many do we need?
00085   int num_threads = boost::thread::hardware_concurrency();
00086   if( num_threads > possible_grasps.size() )
00087     num_threads = possible_grasps.size();
00088 
00089   if(false)
00090   {
00091     num_threads = 1;
00092     ROS_WARN_STREAM_NAMED("grasp_filter","Using only " << num_threads << " threads");
00093   }
00094 
00095   // -----------------------------------------------------------------------------------------------
00096   // Get the solver timeout from kinematics.yaml
00097   double timeout = robot_state_.getRobotModel()->getJointModelGroup( planning_group )->getDefaultIKTimeout();
00098   timeout = 0.05;
00099   ROS_DEBUG_STREAM_NAMED("grasp_filter","Grasp filter IK timeout " << timeout);
00100 
00101   // -----------------------------------------------------------------------------------------------
00102   // Load kinematic solvers if not already loaded
00103   if( kin_solvers_[planning_group].size() != num_threads )
00104   {
00105     kin_solvers_[planning_group].clear();
00106 
00107     const robot_model::JointModelGroup* jmg = robot_state_.getRobotModel()->getJointModelGroup(planning_group);
00108 
00109     // Create an ik solver for every thread
00110     for (int i = 0; i < num_threads; ++i)
00111     {
00112       //ROS_INFO_STREAM_NAMED("filter","Creating ik solver " << i);
00113 
00114       kin_solvers_[planning_group].push_back(jmg->getSolverInstance());
00115 
00116       // Test to make sure we have a valid kinematics solver
00117       if( !kin_solvers_[planning_group][i] )
00118       {
00119         ROS_ERROR_STREAM_NAMED("grasp_filter","No kinematic solver found");
00120         return false;
00121       }
00122     }
00123   }
00124 
00125   // Transform poses -------------------------------------------------------------------------------
00126   // bring the pose to the frame of the IK solver
00127   const std::string &ik_frame = kin_solvers_[planning_group][0]->getBaseFrame();
00128   Eigen::Affine3d link_transform;
00129   if (!moveit::core::Transforms::sameFrame(ik_frame, robot_state_.getRobotModel()->getModelFrame()))
00130   {
00131     const robot_model::LinkModel *lm = robot_state_.getLinkModel((!ik_frame.empty() && ik_frame[0] == '/') ? ik_frame.substr(1) : ik_frame);
00132     if (!lm)
00133       return false;
00134     //pose = getGlobalLinkTransform(lm).inverse() * pose;
00135     link_transform = robot_state_.getGlobalLinkTransform(lm).inverse();
00136   }
00137 
00138   // Benchmark time
00139   ros::Time start_time;
00140   start_time = ros::Time::now();
00141 
00142   // -----------------------------------------------------------------------------------------------
00143   // Loop through poses and find those that are kinematically feasible
00144   std::vector<moveit_msgs::Grasp> filtered_grasps;
00145 
00146   boost::thread_group bgroup; // create a group of threads
00147   boost::mutex lock; // used for sharing the same data structures
00148 
00149   ROS_INFO_STREAM_NAMED("filter", "Filtering possible grasps with " << num_threads << " threads");
00150 
00151   // split up the work between threads
00152   double num_grasps_per_thread = double(possible_grasps.size()) / num_threads;
00153   //ROS_INFO_STREAM("total grasps " << possible_grasps.size() << " per thead: " << num_grasps_per_thread);
00154 
00155   int grasps_id_start;
00156   int grasps_id_end = 0;
00157 
00158   for(int i = 0; i < num_threads; ++i)
00159   {
00160     grasps_id_start = grasps_id_end;
00161     grasps_id_end = ceil(num_grasps_per_thread*(i+1));
00162     if( grasps_id_end >= possible_grasps.size() )
00163       grasps_id_end = possible_grasps.size();
00164     //ROS_INFO_STREAM_NAMED("filter","low " << grasps_id_start << " high " << grasps_id_end);
00165 
00166     IkThreadStruct tc(possible_grasps, filtered_grasps, ik_solutions, link_transform, grasps_id_start,
00167       grasps_id_end, kin_solvers_[planning_group][i], filter_pregrasp, ee_parent_link, timeout, &lock, i);
00168     bgroup.create_thread( boost::bind( &GraspFilter::filterGraspThread, this, tc ) );
00169   }
00170 
00171   ROS_DEBUG_STREAM_NAMED("filter","Waiting to join " << num_threads << " ik threads...");
00172   bgroup.join_all(); // wait for all threads to finish
00173 
00174   ROS_INFO_STREAM_NAMED("filter", "Grasp filter complete, found " << filtered_grasps.size() << " IK solutions out of " <<
00175     possible_grasps.size() );
00176 
00177   possible_grasps = filtered_grasps;
00178 
00179   if (verbose_)
00180   {
00181     // End Benchmark time
00182     double duration = (ros::Time::now() - start_time).toNSec() * 1e-6;
00183     ROS_INFO_STREAM_NAMED("filter","Grasp generator IK grasp filtering benchmark time:");
00184     std::cout << duration << "\t" << possible_grasps.size() << "\n";
00185 
00186     ROS_INFO_STREAM_NAMED("filter","Possible grasps filtered to " << possible_grasps.size() << " options.");
00187   }
00188 
00189   return true;
00190 }
00191 
00192 void GraspFilter::filterGraspThread(IkThreadStruct ik_thread_struct)
00193 {
00194   // Seed state - start at zero
00195   std::vector<double> ik_seed_state(7); // fill with zeros
00196   // TODO do not assume 7 dof
00197 
00198   std::vector<double> solution;
00199   moveit_msgs::MoveItErrorCodes error_code;
00200   geometry_msgs::PoseStamped ik_pose;
00201 
00202   // Process the assigned grasps
00203   for( int i = ik_thread_struct.grasps_id_start_; i < ik_thread_struct.grasps_id_end_; ++i )
00204   {
00205     //ROS_DEBUG_STREAM_NAMED("filter", "Checking grasp #" << i);
00206 
00207     // Clear out previous solution just in case - not sure if this is needed
00208     solution.clear();
00209 
00210     // Transform current pose to frame of planning group
00211     ik_pose = ik_thread_struct.possible_grasps_[i].grasp_pose;
00212     Eigen::Affine3d eigen_pose;
00213     tf::poseMsgToEigen(ik_pose.pose, eigen_pose);
00214     eigen_pose = ik_thread_struct.link_transform_ * eigen_pose;
00215     tf::poseEigenToMsg(eigen_pose, ik_pose.pose);
00216 
00217     // Test it with IK
00218     ik_thread_struct.kin_solver_->
00219       searchPositionIK(ik_pose.pose, ik_seed_state, ik_thread_struct.timeout_, solution, error_code);
00220 
00221     // Results
00222     if( error_code.val == moveit_msgs::MoveItErrorCodes::SUCCESS )
00223     {
00224       //ROS_INFO_STREAM_NAMED("filter","Found IK Solution");
00225 
00226       // Copy solution to seed state so that next solution is faster
00227       ik_seed_state = solution;
00228 
00229       // Start pre-grasp section ----------------------------------------------------------
00230       if (ik_thread_struct.filter_pregrasp_)       // optionally check the pregrasp
00231       {
00232         // Convert to a pre-grasp
00233         ik_pose = SimpleGrasps::getPreGraspPose(ik_thread_struct.possible_grasps_[i], ik_thread_struct.ee_parent_link_);
00234 
00235         // Transform current pose to frame of planning group
00236         Eigen::Affine3d eigen_pose;
00237         tf::poseMsgToEigen(ik_pose.pose, eigen_pose);
00238         eigen_pose = ik_thread_struct.link_transform_ * eigen_pose;
00239         tf::poseEigenToMsg(eigen_pose, ik_pose.pose);
00240 
00241         // Test it with IK
00242         ik_thread_struct.kin_solver_->
00243           searchPositionIK(ik_pose.pose, ik_seed_state, ik_thread_struct.timeout_, solution, error_code);
00244 
00245         // Results
00246         if( error_code.val == moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION )
00247         {
00248           ROS_WARN_STREAM_NAMED("filter","Unable to find IK solution for pre-grasp pose.");
00249           continue;
00250         }
00251         else if( error_code.val == moveit_msgs::MoveItErrorCodes::TIMED_OUT )
00252         {
00253           //ROS_DEBUG_STREAM_NAMED("filter","Unable to find IK solution for pre-grasp pose: Timed Out.");
00254           continue;
00255         }
00256         else if( error_code.val != moveit_msgs::MoveItErrorCodes::SUCCESS )
00257         {
00258           ROS_INFO_STREAM_NAMED("filter","IK solution error for pre-grasp: MoveItErrorCodes.msg = " << error_code);
00259           continue;
00260         }
00261       }
00262       // Both grasp and pre-grasp have passed
00263       // Lock the result vector so we can add to it for a second
00264       {
00265         boost::mutex::scoped_lock slock(*ik_thread_struct.lock_);
00266         ik_thread_struct.filtered_grasps_.push_back( ik_thread_struct.possible_grasps_[i] );
00267 
00268         trajectory_msgs::JointTrajectoryPoint point;
00269         //point.positions = ik_seed_state; // show the grasp solution
00270         point.positions = solution; // show the pre-grasp solution
00271 
00272         // Copy solution so that we can optionally use it later
00273         ik_thread_struct.ik_solutions_.push_back(point);
00274       }
00275 
00276       // End pre-grasp section -------------------------------------------------------
00277     }
00278     else if( error_code.val == moveit_msgs::MoveItErrorCodes::NO_IK_SOLUTION )
00279       ROS_WARN_STREAM_NAMED("filter","Unable to find IK solution for pose.");
00280     else if( error_code.val == moveit_msgs::MoveItErrorCodes::TIMED_OUT )
00281     {
00282       //ROS_DEBUG_STREAM_NAMED("filter","Unable to find IK solution for pose: Timed Out.");
00283     }
00284     else
00285       ROS_INFO_STREAM_NAMED("filter","IK solution error: MoveItErrorCodes.msg = " << error_code);
00286   }
00287 
00288   //ROS_DEBUG_STREAM_NAMED("filter","Thread " << ik_thread_struct.thread_id_ << " finished");
00289 }
00290 
00291 } // namespace


moveit_simple_grasps
Author(s): Dave Coleman
autogenerated on Fri Aug 28 2015 11:36:01