## For instruction on writing tutorials ## http://www.ros.org/wiki/WritingTutorials #################################### ##FILL ME IN #################################### ## for a custom note with links: ## note = ## for the canned note of "This tutorial assumes that you have completed the previous tutorials:" just add the links ## note.0= ## descriptive title for the tutorial ## title = Moving the gripper ## multi-line description to be displayed in search ## description = This tutorial shows you how to move the PR2 gripper using the pr2_gripper_action (an action that runs the gripper controller). ## the next tutorial description (optional) ## next = ## links to next tutorial (optional) ## next.0.link= ## next.1.link= ## what level user is this tutorial for ## level= BeginnerCategory ## keywords = moving, move, gripper, pr2, pr2_gripper_action, grasp, grab, open, close #################################### <> <> == Overview and prerequisites == This tutorial shows how to open and close the gripper of the PR-2. Commanding the gripper to open and close requires three components: * a controller that directly sends commands to the joint motors; * an action node that accepts as a command a desired position for the gripper, and converts that to low-level commands for the controller; * the higher level program that sends desired positions to the action node. The first two of these components are available in ROS. In this tutorial, we will show you how to use them by writing the third component, the higher level program. Before you begin, bring up a robot, either [[WgWiki:/PR2/StartRobot|on the hardware]] or [[simulator_gazebo/Tutorials/StartingGazebo|in gazebo]]. == Building pr2_gripper_action == You'll need to build pr2_gripper_action, if you haven't already. {{{ rosdep install pr2_gripper_action rosmake pr2_gripper_action }}} == Package setup == In order to create a ROS node that sends goals to the gripper 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 simple_gripper roscpp actionlib pr2_controllers_msgs }}} After this is done we'll need to roscd to the package we created, since we'll be using it as our workspace. {{{ roscd simple_gripper }}} == The gripper action and trajectory controller == The gripper controller is brought up on robot start-up. In general, a controller can be in one of three states: * not loaded * loaded, but not running (stopped) * running In general, you can use the `pr2_controller_manager` to check which controllers are available. After you bring up the robot, use the following command: {{{ rosrun pr2_controller_manager pr2_controller_manager list }}} In the list that is printed, look for a line starting with `r_gripper_controller` . If you find: * `r_gripper_controller (running)` : the controller is running; you can skip to the next section of this tutorial * `r_gripper_controller (stopped)` : the controller is loaded, but not running. To start it, use again the `pr2_controller_manager` : {{{ rosrun pr2_controller_manager pr2_controller_manager start r_gripper_controller }}} * no mention of `r_gripper_controller` : the controller has not been loaded; this probably means that something went wrong during robot start-up. Abort this tutorial and investigate the cause for that. Note that this usage of the `pr2_controller_manager` also applies to other controllers, such as the arm trajectory controller or the torso controller. == The action node == The action node is also brought up automatically on robot start-up. To check for it, you can look at the list of active nodes in the r_gripper_controller namespace: {{{ rosnode list r_gripper_controller }}} Look for the line `/r_gripper_controller/gripper_action_node` . If you don't find it, the action node was not brought up at robot start-up. Abort this tutorial and investigate the cause for that. == The action goal == The pr2_gripper_action takes in goal messages of type <>, which contains a single field, 'command,' of type <>. The command has two float64 fields, 'position' and 'max_effort'. The 'position' field specifies the desired gripper opening (the size of the space between the two fingertips) in meters: closed is 0.0, and fully open is approximately 0.09. The 'max_effort' field places a limit on the amount of effort (force in N) to apply while moving to that position. If 'max_effort' is negative, it is ignored. == Creating the action client == Now we will make an action client node that opens and then closes the gripper while limiting the force applied. Put the following into '''src/simple_gripper.cpp''': {{{ #!cplusplus block=simple_gripper #include #include #include // Our Action interface type, provided as a typedef for convenience typedef actionlib::SimpleActionClient GripperClient; class Gripper{ private: GripperClient* gripper_client_; public: //Action client initialization Gripper(){ //Initialize the client for the Action interface to the gripper controller //and tell the action client that we want to spin a thread by default gripper_client_ = new GripperClient("r_gripper_controller/gripper_action", true); //wait for the gripper action server to come up while(!gripper_client_->waitForServer(ros::Duration(5.0))){ ROS_INFO("Waiting for the r_gripper_controller/gripper_action action server to come up"); } } ~Gripper(){ delete gripper_client_; } //Open the gripper void open(){ pr2_controllers_msgs::Pr2GripperCommandGoal open; open.command.position = 0.08; open.command.max_effort = -1.0; // Do not limit effort (negative) ROS_INFO("Sending open goal"); gripper_client_->sendGoal(open); gripper_client_->waitForResult(); if(gripper_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) ROS_INFO("The gripper opened!"); else ROS_INFO("The gripper failed to open."); } //Close the gripper void close(){ pr2_controllers_msgs::Pr2GripperCommandGoal squeeze; squeeze.command.position = 0.0; squeeze.command.max_effort = 50.0; // Close gently ROS_INFO("Sending squeeze goal"); gripper_client_->sendGoal(squeeze); gripper_client_->waitForResult(); if(gripper_client_->getState() == actionlib::SimpleClientGoalState::SUCCEEDED) ROS_INFO("The gripper closed!"); else ROS_INFO("The gripper failed to close."); } }; int main(int argc, char** argv){ ros::init(argc, argv, "simple_gripper"); Gripper gripper; gripper.open(); gripper.close(); return 0; } }}} Now we'll go through a few subsets of the code in more detail. <> Here we initialize the action client and wait for the action server to come up. If the gripper controller has not been started, the action server will not be up. The message namespace for the gripper action, which we use to initialize the action client, is "r_gripper_controller/gripper_action." If you type {{{ rostopic list }}} on the command line, you should see an entire set of messages that start with "r_gripper_controller/gripper_action": cancel, feedback, goal, result, and status. We will show how to send action goals in this tutorial; if you type {{{ rostopic echo /r_gripper_controller/gripper_action/feedback }}} at the command line, you can see the feedback from the action while it executes our command. <> <> Gripper action goal messages for opening and closing. <> Here we send the goal that closes the gripper, and wait for the action to report that it has terminated. Upon termination, if it reports that it SUCCEEDED, it means that it reached the desired position; if the gripper stalls (for instance, upon hitting an object that prevents it from closing all the way), it will report ABORTED. Because the gripper controller is still running even after the action goal has terminated, the gripper will continue to try to reach the desired position, with the specified maximum effort. This continues until a new goal is sent, or until the gripper controller is stopped. Thus, if the gripper has been commanded to close around an object, it will continue to exert force on the object, holding it in the hand, until told to do otherwise. === Building === Add the following line to the CMakeLists.txt: {{{ rosbuild_add_executable(simple_gripper src/simple_gripper.cpp) }}} and make the binary by typing 'make' in the simple_gripper directory. === Running === * Bring up gazebo or a robot. * Start the ROS console ([[rxconsole]]) to view any errors that occur. * Run the controller/action launch file: {{{ roslaunch run_simple_gripper.launch }}} * Run the simple_gripper program: {{{ bin/simple_gripper }}} You should see the robot's right gripper open and close. ## AUTOGENERATED DO NOT DELETE ## TutorialCategory ## PR2GripperActionTutorial