pr2_gripper_grasp_controller.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 *  Copyright (c) 2009, Willow Garage, Inc.
00004 *  All rights reserved.
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *   * Redistributions of source code must retain the above copyright
00011 *     notice, this list of conditions and the following disclaimer.
00012 *   * Redistributions in binary form must reproduce the above
00013 *     copyright notice, this list of conditions and the following
00014 *     disclaimer in the documentation and/or other materials provided
00015 *     with the distribution.
00016 *   * Neither the name of the Willow Garage nor the names of its
00017 *     contributors may be used to endorse or promote products derived
00018 *     from this software without specific prior written permission.
00019 *
00020 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 *  POSSIBILITY OF SUCH DAMAGE.
00032 *********************************************************************/
00033 
00034 #include <ros/ros.h>
00035 
00036 #include <actionlib/server/simple_action_server.h>
00037 #include <actionlib/client/simple_action_client.h>
00038 
00039 #include <pr2_controllers_msgs/Pr2GripperCommandAction.h>
00040 
00041 #include <sensor_msgs/JointState.h>
00042 
00043 #include <object_manipulation_msgs/GraspHandPostureExecutionAction.h>
00044 #include <object_manipulation_msgs/GraspStatus.h>
00045 
00046 static const std::string JOINT_STATES_TOPIC = "joint_states";
00047 
00049 
00054 class PR2GripperGraspController
00055 {
00056 private:
00057 
00059   ros::NodeHandle root_nh_;
00060 
00062   ros::NodeHandle priv_nh_;
00063 
00065   actionlib::SimpleActionClient<pr2_controllers_msgs::Pr2GripperCommandAction> *gripper_action_client_;
00066 
00068   actionlib::SimpleActionServer<object_manipulation_msgs::GraspHandPostureExecutionAction> *action_server_;
00069 
00071   ros::ServiceServer query_srv_;
00072 
00074   std::string gripper_virtual_joint_name_;
00075 
00077   bool sim_;
00078 
00080   double sim_wait_;
00081 
00082   //-------------------------------- Constants ---------------------------------
00083 
00085   double gripper_open_gap_value_;
00087   static const double DEFAULT_GRIPPER_OPEN;
00088 
00090   double gripper_closed_gap_value_;
00092   static const double DEFAULT_GRIPPER_CLOSED;
00093 
00095   double gripper_object_presence_threshold_;  
00097   static const double DEFAULT_GRIPPER_OBJECT_PRESENCE_THRESHOLD;
00098 
00100   double gripper_max_effort_;
00102   static const double DEFAULT_GRIPPER_MAX_EFFORT;
00103 
00105   std::string gripper_type_;
00106 
00107   //------------------------------ Functionality -------------------------------
00108 
00110   bool getGripperValue(double &value)
00111   {
00112     //get the joint states
00113     sensor_msgs::JointState::ConstPtr joint_states = 
00114       ros::topic::waitForMessage<sensor_msgs::JointState>(JOINT_STATES_TOPIC, root_nh_);
00115     if (!joint_states)
00116     {
00117       ROS_ERROR("pr2 gripper grasp status: joint states not received");
00118       return false;
00119     }
00120     
00121     //find the gripper joint
00122     size_t i;
00123     for (i=0; i<joint_states->name.size(); i++)
00124     {
00125       if (joint_states->name[i] == gripper_virtual_joint_name_) break;
00126     }
00127     if (i==joint_states->name.size())
00128     {
00129       ROS_ERROR("pr2_gripper grasp status: gripper joint %s not found in joint state", 
00130                 gripper_virtual_joint_name_.c_str());
00131       return false;
00132     }
00133     if (joint_states->position.size() <= i)
00134     {
00135       ROS_ERROR("pr2_gripper grasp status: malformed joint state message received");
00136       return false;
00137     }
00138     value = joint_states->position[i];
00139     return true;
00140   }
00141 
00143 
00144   double jointToGap(double jointValue)
00145   {
00146     if (gripper_type_ == "pr2") return jointValue / 0.5 * 0.0857;
00147     else if (gripper_type_ == "lcg") return 2.0 * ( cos(jointValue)*60.0 + 17.5 - 6.0 ) * 1.0e-3;
00148     else {ROS_ERROR_STREAM("pr2_gripper_grasp_controller: unknown gripper type: " << gripper_type_); return 0.0;}
00149   }
00150 
00151   void executeCB(const object_manipulation_msgs::GraspHandPostureExecutionGoalConstPtr &goal)
00152   {
00153     //prepare the gripper command based on the goal
00154     pr2_controllers_msgs::Pr2GripperCommandGoal gripper_command;
00155     switch (goal->goal)
00156     {
00157     case object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP:
00158       if (goal->grasp.grasp_posture.position.empty())
00159       {
00160         ROS_ERROR("pr2 gripper grasp execution: position vector empty in requested grasp");
00161         action_server_->setAborted();
00162         return;
00163       }
00164       gripper_command.command.position = gripper_closed_gap_value_;
00165       //gripper_command.command.position = jointToGap( goal->grasp.grasp_posture.position[0] );
00166       if (goal->grasp.grasp_posture.effort.empty())
00167       {
00168         if(goal->max_contact_force > 0)
00169         {
00170           ROS_INFO("limiting max contact force to %f", goal->max_contact_force);
00171           gripper_command.command.max_effort = goal->max_contact_force;
00172         }
00173         else gripper_command.command.max_effort = gripper_max_effort_;
00174         ROS_WARN("pr2 gripper grasp execution: effort vector empty in requested grasp, using max force");
00175         //action_server_->setAborted();
00176         //return;
00177       }
00178       //we use the effort in the first joint for going to the grasp
00179       else 
00180       {
00181         if(goal->grasp.grasp_posture.effort.at(0) < goal->max_contact_force || goal->max_contact_force == 0)
00182           gripper_command.command.max_effort = goal->grasp.grasp_posture.effort.at(0);
00183         else gripper_command.command.max_effort = goal->max_contact_force;
00184       }
00185       break;
00186     case object_manipulation_msgs::GraspHandPostureExecutionGoal::PRE_GRASP:
00187       if (goal->grasp.pre_grasp_posture.position.empty())
00188       {
00189         ROS_ERROR("pr2 gripper grasp execution: position vector empty in requested pre_grasp");
00190         action_server_->setAborted();
00191         return;
00192       }
00193       //gripper_command.command.position = GRIPPER_OPEN;
00194       gripper_command.command.position = jointToGap( goal->grasp.pre_grasp_posture.position.at(0) );
00195       ROS_DEBUG("pre grasp posture opening is %.3f", gripper_command.command.position);
00196       if (goal->grasp.pre_grasp_posture.effort.empty())
00197       {
00198         gripper_command.command.max_effort = gripper_max_effort_;
00199         ROS_WARN("pr2 gripper grasp execution: effort vector empty in requested pre_grasp, using max");
00200       }
00201       else 
00202       {
00203         gripper_command.command.max_effort = goal->grasp.pre_grasp_posture.effort.at(0);
00204       }
00205       break;      
00206     case object_manipulation_msgs::GraspHandPostureExecutionGoal::RELEASE:
00207       gripper_command.command.position = gripper_open_gap_value_;
00208       gripper_command.command.max_effort = gripper_max_effort_;
00209       break;
00210     default:
00211       ROS_ERROR("pr2 gripper grasp execution: unknown goal code (%d)", goal->goal);
00212       action_server_->setAborted();
00213       return;
00214     }
00215 
00216     //check the requested effort
00217     if (gripper_command.command.max_effort > gripper_max_effort_)
00218     {
00219       ROS_WARN("pr2 gripper grasp execution: effort exceeds max value for gripper, reducing to max");
00220       gripper_command.command.max_effort = gripper_max_effort_;
00221     }
00222 
00223     //send the command to the gripper
00224     gripper_action_client_->sendGoal(gripper_command);
00225     if (!sim_) 
00226     {
00227       gripper_action_client_->waitForResult();
00228     }
00229     else 
00230     {
00231       //simulated gripper has a habit of never settling and thus never returning
00232       //so in sim we just continue after a hard-coded interval here
00233       bool withinWait = gripper_action_client_->waitForResult(ros::Duration(sim_wait_));
00234       if (!withinWait)
00235       {
00236         ROS_WARN("pr2 gripper grasp execution: controller has not returned within limit, "
00237                  "but since we are in simulation we are continuing anyway.");
00238       }
00239     }
00240 
00241     //process the result
00242     if(gripper_action_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) 
00243     {
00244       ROS_INFO("Gripper goal achieved");
00245       action_server_->setSucceeded();
00246     } 
00247     else 
00248     {
00249       if (goal->goal == object_manipulation_msgs::GraspHandPostureExecutionGoal::GRASP)
00250       {
00251         //this is probably correct behavior, since there is an object in the gripper
00252         //we can not expect to reach our goal
00253         action_server_->setSucceeded();
00254       }
00255       else
00256       {
00257         ROS_WARN("Gripper goal not achieved for pre-grasp or release");
00258         //this might become a failure later, for now we're still investigating
00259         action_server_->setSucceeded();
00260       }
00261     }
00262   }
00263 
00264   bool serviceCallback(object_manipulation_msgs::GraspStatus::Request &request,
00265                        object_manipulation_msgs::GraspStatus::Response &response)
00266   {
00267     double gripper_value;
00268     if (!getGripperValue(gripper_value)) return false;    
00269 
00270     double min_gripper_opening = gripper_object_presence_threshold_;
00271     if (gripper_value < min_gripper_opening) 
00272     {
00273       ROS_INFO("Gripper grasp query false: gripper value %f below threshold %f", 
00274                gripper_value, min_gripper_opening);
00275       response.is_hand_occupied = false;
00276     }
00277     else 
00278     {
00279       ROS_DEBUG("Gripper grasp query true: gripper value %f above threshold %f", 
00280                gripper_value, min_gripper_opening);
00281       response.is_hand_occupied = true;
00282     }
00283     return true;
00284   }
00285                        
00286 
00287 public:
00288   PR2GripperGraspController() :
00289     root_nh_(""),
00290     priv_nh_("~")
00291   {
00292     std::string gripper_action_name = root_nh_.resolveName("gripper_action_name");
00293     gripper_action_client_ = new actionlib::SimpleActionClient<pr2_controllers_msgs::Pr2GripperCommandAction>
00294       (gripper_action_name, true);
00295     while(!gripper_action_client_->waitForServer(ros::Duration(2.0)) && root_nh_.ok())
00296     {
00297       ROS_INFO_STREAM("Waiting for gripper action client on topic " << gripper_action_name);
00298     }
00299     if (!root_nh_.ok()) exit(0);
00300     ROS_INFO_STREAM("Using gripper action client on topic " << gripper_action_name);
00301 
00302     priv_nh_.param<std::string>("gripper_virtual_joint_name", gripper_virtual_joint_name_, "undefined");
00303     if ( gripper_virtual_joint_name_ == "undefined" )
00304     {
00305       ROS_ERROR("Gripper virtual joint name not defined; set the parameter "
00306                 "gripper_virtual_joint_name in the launch file");
00307       exit(0);
00308     }
00309 
00310     priv_nh_.param<double>("gripper_object_presence_threshold", gripper_object_presence_threshold_,
00311                            DEFAULT_GRIPPER_OBJECT_PRESENCE_THRESHOLD);
00312     priv_nh_.param<double>("gripper_open_gap_value", gripper_open_gap_value_, DEFAULT_GRIPPER_OPEN);
00313     priv_nh_.param<double>("gripper_closed_gap_value", gripper_closed_gap_value_, DEFAULT_GRIPPER_CLOSED);
00314     priv_nh_.param<double>("gripper_max_effort", gripper_max_effort_, DEFAULT_GRIPPER_MAX_EFFORT);
00315     priv_nh_.param<std::string>("gripper_type", gripper_type_, "pr2");
00316     priv_nh_.param<bool>("sim", sim_, false);
00317     priv_nh_.param<double>("sim_wait", sim_wait_, 8.0);
00318 
00319     std::string query_service_name = root_nh_.resolveName("grasp_query_name");   
00320     query_srv_ = root_nh_.advertiseService(query_service_name, &PR2GripperGraspController::serviceCallback, this);    
00321     ROS_INFO_STREAM("pr2_gripper grasp query service started on topic " << query_service_name);
00322 
00323     std::string posture_action_name = root_nh_.resolveName("posture_action_name");
00324     action_server_ = new actionlib::SimpleActionServer<object_manipulation_msgs::GraspHandPostureExecutionAction>
00325       (root_nh_, posture_action_name, boost::bind(&PR2GripperGraspController::executeCB, this, _1), false);
00326     action_server_->start();
00327     ROS_INFO_STREAM("pr2_gripper grasp hand posture action server started on topic " << posture_action_name);
00328   }
00329 
00330   ~PR2GripperGraspController()
00331   {
00332     delete action_server_;
00333     delete gripper_action_client_;
00334   }
00335 
00336 };
00337 
00338 //Note that all these values are set for the PR2 gripper
00339 const double PR2GripperGraspController::DEFAULT_GRIPPER_OPEN = 0.086;
00340 const double PR2GripperGraspController::DEFAULT_GRIPPER_CLOSED = 0.0;
00341 const double PR2GripperGraspController::DEFAULT_GRIPPER_OBJECT_PRESENCE_THRESHOLD = 0.0021;
00342 const double PR2GripperGraspController::DEFAULT_GRIPPER_MAX_EFFORT = 100;
00343 
00344 int main(int argc, char **argv)
00345 {
00346   ros::init(argc, argv, "pr2_gripper_grasp_controller");
00347   PR2GripperGraspController node;
00348   ros::spin();
00349   return 0;  
00350 }


pr2_gripper_grasp_controller
Author(s): Matei Ciocarlie
autogenerated on Mon Oct 6 2014 12:24:57