(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Grab and Release an Object Using pr2_gripper_sensor_action

Description: This tutorial will show you how to get the gripper to delicately grab an object, then after a certain amount of time automatically look for a contact event (hopefully the contact of the object and the surface you wanted to place it on), and release the object after contact.

Tutorial Level: BEGINNER

Overview and prerequisites

This tutorial will show you to use the basic pr2_gripper_sensor_action commands of grab and release to delicately grasp and hold an object, and eventually release it based on contact between the object and environment.

This is only a toy example and does not contain any code to actually move the arm. To test this code you could integrate it with code to move the arm, or run it by itself while putting the PR2 into mannequin mode and moving the arm around manually.

Using any of the pr2_gripper_sensor_action commands requires three components:

  • a controller that directly sends commands to the joint motors;
  • an action node that translates your desired actions to low-level commands for the controller;
  • the higher level program that sends your commands to the action node.

The first two of these components are available in ROS as part of the pr2_gripper_sensor_action, pr2_gripper_sensor_controller, and pr2_gripper_sensor_msgs packages. In this tutorial, we will show you how to use them by writing the third component, the higher level program.

Building pr2_gripper_sensor_action

You'll need to build pr2_gripper_sensor_action, if you haven't already.

rosdep install pr2_gripper_sensor_action
rosmake pr2_gripper_sensor_action

After that you can bring up a robot on the hardware.

Package setup

In order to create a ROS node that sends goals to the gripper_sensor_action, the first thing we'll need to do is create a package. To do this we'll use the handy roscreate-pkg command where we want to create the package directory:

roscreate-pkg my_gripper_project roscpp actionlib pr2_gripper_sensor_action

After this is done we'll need to roscd to the package we created, since we'll be using it as our workspace.

roscd my_gripper_project

Launching the controller and action nodes

Currently the pr2_gripper_sensor_controller and pr2_gripper_sensor_action nodes are not brought up by default when you launch the robot. To write a program that uses these resources you will first need to launch the controller and action nodes for both the left and right gripper by running the following launch script:

roslaunch pr2_gripper_sensor_action pr2_gripper_sensor_actions.launch

Creating the Action Client

Now we will make an action client node that grabs and releases an object.

Put the following into src/my_gripper_project.cpp:

   1 #include <ros/ros.h>
   2 #include <pr2_gripper_sensor_msgs/PR2GripperGrabAction.h>
   3 #include <pr2_gripper_sensor_msgs/PR2GripperReleaseAction.h>
   4 #include <actionlib/client/simple_action_client.h>
   5 
   6 // Our Action interface type, provided as a typedef for convenience
   7 typedef actionlib::SimpleActionClient<pr2_gripper_sensor_msgs::PR2GripperGrabAction> GrabClient;
   8 // Our Action interface type, provided as a typedef for convenience
   9 typedef actionlib::SimpleActionClient<pr2_gripper_sensor_msgs::PR2GripperReleaseAction> ReleaseClient;
  10 
  11 
  12 class Gripper{
  13 private:
  14   GrabClient* grab_client_;
  15   ReleaseClient* release_client_;
  16 
  17 public:
  18   //Action client initialization
  19   Gripper(){
  20 
  21     //Initialize the client for the Action interface to the gripper controller
  22     //and tell the action client that we want to spin a thread by default
  23     grab_client_  = new GrabClient("r_gripper_sensor_controller/grab",true);
  24     release_client_  = new ReleaseClient("r_gripper_sensor_controller/release",true);
  25 
  26     while(!grab_client_->waitForServer(ros::Duration(5.0))){
  27       ROS_INFO("Waiting for the r_gripper_sensor_controller/grab action server to come up");
  28     }
  29 
  30     while(!release_client_->waitForServer(ros::Duration(5.0))){
  31       ROS_INFO("Waiting for the r_gripper_sensor_controller/release action server to come up");
  32     }
  33   }
  34 
  35   ~Gripper(){
  36     delete grab_client_;
  37     delete release_client_;
  38   }
  39 
  40   //Open the gripper, find contact on both fingers, and go into slip-servo control mode
  41   void grab(){
  42     pr2_gripper_sensor_msgs::PR2GripperGrabGoal grip;
  43     grip.command.hardness_gain = 0.03;
  44     
  45     ROS_INFO("Sending grab goal");
  46     grab_client_->sendGoal(grip);
  47     grab_client_->waitForResult(ros::Duration(20.0));
  48     if(grab_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
  49       ROS_INFO("Successfully completed Grab");
  50     else
  51       ROS_INFO("Grab Failed");
  52   }
  53 
  54   // Look for side impact, finerpad slip, or contact acceleration signals and release the object once these occur
  55   void release(){
  56     pr2_gripper_sensor_msgs::PR2GripperReleaseGoal place;
  57     // set the robot to release on a figner-side impact, fingerpad slip, or acceleration impact with hand/arm
  58     place.command.event.trigger_conditions = place.command.event.FINGER_SIDE_IMPACT_OR_SLIP_OR_ACC;  
  59     // set the acceleration impact to trigger on to 5 m/s^2
  60     place.command.event.acceleration_trigger_magnitude = 5.0; 
  61     // set our slip-gain to release on to .005
  62     place.command.event.slip_trigger_magnitude = .01;
  63 
  64 
  65     ROS_INFO("Waiting for object placement contact...");
  66     release_client_->sendGoal(place);
  67     release_client_->waitForResult();
  68     if(release_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
  69       ROS_INFO("Release Success");
  70     else
  71       ROS_INFO("Place Failure");
  72 
  73   }
  74 
  75 
  76 };
  77 
  78 int main(int argc, char** argv){
  79   ros::init(argc, argv, "simple_gripper");
  80 
  81   Gripper gripper;
  82 
  83   // wait a few seconds so we can put something in the robot's gripper
  84   sleep(5.0);
  85 
  86   // grab something
  87   gripper.grab();
  88 
  89   // move the robot arm all ove the place here!
  90   sleep(5.0);
  91   
  92   // now that we've decided we want to look for contact and let go
  93   gripper.release();
  94   
  95 
  96   return 0;
  97 }

Building

Add the following line to the CMakeLists.txt:

rosbuild_add_executable(my_gripper_project src/my_gripper_project.cpp)

and make the binary by typing 'make' in the my_gripper_project directory.

Running

  • Bring up a robot.
  • Make sure the pr2_gripper_sensor controller and action nodes are launched (see above)
  • Start the ROS console (rxconsole) to view any errors that occur.

  • Run your new node that you created:

rosrun my_gripper_project my_gripper_project

The robot should now wait a few seconds, grab an object, wait a few more seconds, and release upon object contact with the environment.

Wiki: pr2_gripper_sensor_action/Tutorials/Grab and Release an Object Using pr2_gripper_sensor_action (last edited 2010-09-01 01:23:34 by JoeRomano)