Show EOL distros: 

Package Summary

The haf_grasping package: calculates grasps for a given point cloud using Height Accumulated Features (HAF)

Package Summary

The haf_grasping package: calculates grasps for a given point cloud using Height Accumulated Features (HAF)

Package Summary

The haf_grasping package: calculates grasps for a given point cloud using Height Accumulated Features (HAF)


This package calculates graspable regions at unknown (or known) objects.

HAF_GRASPING calculates grasp points for unknown and known objects represented by object point cloud data. For scientific foundation see: '''D. Fischinger, A. Weiss, M. Vincze: "Learning Grasps with Topographic Features", The International Journal of Robotics Research. (2015)'''


This part shows how to get the code running and visualizes the grasp calculation for a point cloud in RVIZ:


>> mkdir -p ~/haf_grasping_ws/src
>> cd ~/haf_grasping_ws/src
>> catkin_init_workspace

OR navigate to an existing *src* folder of your ROS workspace:

cd location_of_workspace/src

DOWNLOAD CODE (and add the path to the environment variable ROS_PACKAGE_PATH if needed)

>> git clone

Execute "make" in the libsvm folder:

>> roscd haf_grasping/libsvm-3.12
>> make


>> roscd haf_grasping/../..
>> catkin_make -DCMAKE_BUILD_TYPE=Release
>> source devel/

Start calculation server (does the work), haf_client (small program including the class that shows how to use haf_grasping) and a visualization in rviz:

>> roslaunch haf_grasping haf_grasping_all.launch

Publish the path of a point cloud to calculate grasp points on this object with the gripper approaching direction along the z-axis:

>> rostopic pub /haf_grasping/input_pcd_rcs_path std_msgs/String "$(rospack find haf_grasping)/data/pcd2.pcd" -1

Alternatively, publish a point cloud to the ROS topic: /haf_grasping/depth_registered/single_cloud/points_in_lcs:

>> roscd haf_grasping/data
>> rosrun pcl_ros pcd_to_pointcloud pcd2.pcd cloud_pcd:=/haf_grasping/depth_registered/single_cloud/points_in_lcs


RVIZ will now visualize the point cloud with its corresponding frame (blue indicates the z-axis).

Bigger grey rectangle: indicates the area where heights can be used for grasp calculation

Inner grey rectangle: defines the area which is searched for potential grasps (grasp centers).

Long red line: indicates the closing direction (for a two finger gripper)

Red/green spots: indicate the positions where grasps are really tested for the current gripper roll (ignoring points where no calculation is needed, e.g. no data there)

Green bars: indicate identified potential grasps available. The height of the bars indicates the grasp evaluation score (the higher the better)

Black arrow: indicates the best grasp position found and the approaching direction (for a parallel two finger gripper)

Visualization of the grasp calculation process in rviz:

haf_in_rviz1.png haf_in_rviz1.png

Red line indicates currently tested gripper opening direction, red points indicate positions where no grasp was found, green bars indicate positions where grasps were found - the higher the bar, the better the quality.


Finally the top grasp (position and approaching direction of the gripper) is shown by the black arrow together with the gripper orientation (red line).



The package haf_grasping provides one SimpleActionServer:

  • /calc_grasppoints_svm_action_server: requests the calculation of a grasp for a given point cloud. A simple implementation of the client can be found here: calc_grasppoints_action_client.cpp: :

    • action definition:
      • goal: GraspInput.msg defined by a point cloud and a number of settings for the action server

      • result: std_msgs/String defining the best grasp found (see below)
      • feedback: std_msgs/String
    • the object must have been previously segmented from the background
    • the action will then:
      • calculate the best grasp for a parallel gripper approaching the tool center point along the z-axis of the coordinate frame.


There are a number of parameters that can be set in the launch file haf_grasping_all.launch or via a service call.

Approach vector: x,y,z-direction of the approach vector. The tool center point of a gripper approaches the object in the opposite direction of this vector. For the default vector (0,0,1) the gripper is going down the z-axis towards the origin. Service to set the approach vector to (1,1,1):

>> rosservice call /haf_grasping/set_approach_vector "approach_vector:  x: 1.0
  y: 1.0
  z: 1.0"

Grasp_center: the x-,y-,z-position, that is the center of the area where grasps are searched. Set grasp search center (in m) to (x=0.1,y=0,z=0) with a service call:

>> rosservice call /haf_grasping/set_grasp_center "graspsearchcenter:
   x: 0.10
   y: 0.0
   z: 0.0"

Grasp_area_size: the size of the area where grasps should be detected. Set rectangle to 16x10 centimeter:

>> rosservice call /haf_grasping/set_grasp_search_area_size "grasp_search_size_x: 16 grasp_search_size_y: 10"

Grasp_calculation_time_max: maximal time in seconds until a grasp has to be returned. Set max time to 3 sec:

>> rosservice call /haf_grasping/set_grasp_calculation_time_max "max_calculation_time:
  secs: 3
  nsecs: 0"

Show_only_best_grasp: defines if only the best grasp should be published or each grasp with an evaluation exceeding a threshold (only top grasps per roll angle). Set this value to publish only the overall top-rated grasp:

>> rosservice call /haf_grasping/set_show_only_best_grasp "show_only_best_grasp: true"

Gripper opening width: this factor f is used to simulate a gripper that is opened 1/f-times the maximal gripper opening width (e.g.: value 3 => gripper only one third opened):

>> rosservice call /haf_grasping/set_gripper_opening_width "gripper_opening_width: 3"

These values can also be set before launching the haf_client in the launch file launch/haf_grasping_all.launch. Here are the default values:


        <!-- define center position of area which is searched for grasps -->
        <rosparam param="grasp_search_center"> [0.0,0.0,0.0] </rosparam>

        <!-- define grasp search size, i.e. the region size which is
         searched for grasps; limit x: 0-18; limit y: 0-32 -->
        <rosparam param="grasp_search_size_x"> 18 </rosparam>
        <rosparam param="grasp_search_size_y"> 30 </rosparam>

        <!-- define approach direction of gripper (without gripper roll):
         moving direction is reversed (AV = (0,0,1) <=> gripper moving along -z-axis ) -->
        <rosparam param="gripper_approach_vector"> [0,0,1] </rosparam>

        <!-- define maximal calculation time max_calculation_time for finding grasps (sec) -->
        <rosparam param="max_calculation_time"> 40 </rosparam>

        <!-- define if only best grasp should be visualized or more
             (if evaluation is higher than threshold) -->
        <rosparam param="show_only_best_grasp"> false </rosparam>

        <!-- define the topic for incoming point clouds -->
        <rosparam param="input_pc_topic">/haf_grasping/depth_registered/single_cloud

        <!-- define default point cloud frame (if generated from pcd) -->
        <rosparam param="base_frame">base_link2</rosparam>

        <!-- define default gripper_width factor: if value is n, this means
             gripper is tested with 1/n-times the max. gripper opening width -->
        <rosparam param="gripper_width">1</rosparam>

        <!-- SVM Parameters -->

        <!-- define path of feature file for SVM grasp classification -->
        <param name="feature_file_path" value="$(find haf_grasping)/data/Features.txt" />

        <!-- define path relative to haf-package of range/scaling file for features -->
        <param name="range_file_path" value="$(find haf_grasping)/data/range21062012_allfeatures" />

        <!-- define path of SVM classifier (model) -->
        <param name="svmmodel_file_path" value="$(find haf_grasping)/data/all_features.txt.scale.model" />


In calc_grasppoints_action_client.cpp we subscribe to a point_cloud topic and start the following callback when a point cloud comes in:

   1 //get goal (input point cloud) for grasp calculation,
   2 //send it to grasp action server and receive result
   3 void CCalcGrasppointsClient::get_grasp_cb(const sensor_msgs::PointCloud2ConstPtr& pc_in)
   4 {
   5         ROS_INFO("\nFrom calc_grasppoints_action_client: point cloud received");
   7         // create the action client
   8         // true causes the client to spin its own thread
   9         actionlib::SimpleActionClient<haf_grasping::CalcGraspPointsServerAction>
  10                    ac("calc_grasppoints_svm_action_server", true);
  12         ROS_INFO("Waiting for action server to start.");
  13         // wait for the action server to start
  14         ac.waitForServer(); //will wait for infinite time
  16         ROS_INFO("Action server started, sending goal.");
  17         // send a goal to the action
  18         haf_grasping::CalcGraspPointsServerGoal goal;
  19         goal.graspinput.input_pc = *pc_in;
  21         goal.graspinput.grasp_area_center = this->graspsearchcenter;
  23         // set size of grasp search area
  24         goal.graspinput.grasp_area_length_x = this->grasp_search_size_x;
  25         goal.graspinput.grasp_area_length_y = this->grasp_search_size_y;
  27         // set max grasp calculation time
  28         goal.graspinput.max_calculation_time = this->grasp_calculation_time_max;
  30         //send goal
  31         ac.sendGoal(goal);
  33         //wait for the action to return
  34         bool finished_before_timeout = ac.waitForResult(ros::Duration(50.0));
  36         if (finished_before_timeout)
  37         {
  38             actionlib::SimpleClientGoalState state = ac.getState();
  39             boost::shared_ptr<const
  40           haf_grasping::CalcGraspPointsServerResult_<std::allocator<void> > > result =
  41           ac.getResult();
  42             ROS_INFO("Result: %s", (*(result));
  43             ROS_INFO("Action finished: %s",state.toString().c_str());
  44         }
  45         else
  46             ROS_INFO("Action did not finish before the time-out.");
  47 }


Detected grasps are visualized in rviz and returned as result to the service client. Furthermore, they are published to the topic /haf_grasping/grasp_hypothesis_with_eval as string value and have the following format:

>> rostopic echo /haf_grasping/grasp_hypothesis_with_eval
data: 55     0.07 0.08 0.158921   0.07 0.02 0.158921     0 0 1     0.07 0.05 0.158921 90
       |      |     |    |          |    |      |        | | |      |     |     |      |
      val gp1(x,    y,   z)     gp2(x,   y,     z )   av(x,y,z) gcp(x,    y,    z)    roll

val: scaled evaluation of the grasp: 99 is the top value, -20 is the worst possible value, meaning that no grasp was found at all (normally indicating a data or software issue, e.g. an issue with the tf system or no make executed in the libsvm folder)

gp1(x,y,z): x-,y-,z-coordinates of the first grasp point

gp2(x,y,z): x-,y-,z-coordinates of the second grasp point

av(x,y,z) : x-,y-,z-coordinates of the approach vector

gcp(x,y,z): x-,y-,z-coordinates of the grasp center point, i.e. the middle point between gp1 and gp2

roll: gripper orientation in degrees

The returned grasps indicate (in a redundant way) how a gripper with two opposite fingers should approach an object: the gripper-specific approach vector that goes through the tool center point should approach the object along the object specific (returned) approach vector (av), which goes to the grasp center point (gcp) whereby the roll is defined by roll respectively by the heuristically estimated grasp points (gp1,gp2).


A crucial part for successful grasping is path planning and grasp (fine) planning. We achieved the best results by using a simulation software (OpenRAVE) to calculate a collision free straight approach trajectory for a gripper with fixed orientation in the following way.

The OpenRAVE simulator is used for path planning including determination of an appropriate distance between the manipulator and the object before closing the manipulator. OpenRAVE tries to approach the object mesh (i.e. an unsegmented mesh of all objects in the scene [rosnode with conversion from point cloud to mesh can be provided]) using the calculated approach vector and manipulator roll angle until a collision occurs. Then it sets the manipulator position back by a standoff value which is dependent on the object position: in recent work, we do not use a fixed standoff of 1 cm, but start with a standoff value of 1 mm. If this standoff leads to a collision of the gripper fingers with the table top or the ground (used in simulation), the standoff is increased until the closing fingers do not collide with the table or the ground any more. Then the actual grasp points, i.e. contact points of the fingers with the object mesh in the simulation, are calculated. From the resulting gripper position, OpenRAVE calculates the manipulator position about 7 cm away and searches for a collision free path to place the manipulator there. For the last 7 cm to the object OpenRAVE calculates a straight path to the object if one exists. We chose 7 cm as a practical trade-off between a higher grasping robustness (regarding calibration inaccuracy or incomplete data) achieved by a straight approach trajectory with fixed manipulator orientation and the challenge to find inverse kinematics solutions for such trajectories.

An OpenRAVE implementation for the PR2 can be found here: ('''code''', '''Readme'''). OpenRAVE implementations for an 7-DOF Schunk/AMTEC arm, a Kuka LWR and the service robot '''Hobbit''' can be provided on request.


Grasp points and approach vectors are detected using Support Vector Machines. We have included LIBSVM to work as our classifier (go to folder libsvm-3.12 and type "make" after checking out):

Chih-Chung Chang and Chih-Jen Lin, LIBSVM : a library for support vector machines. ACM Transactions on Intelligent Systems and Technology, 2:27:1--27:27, 2011. Software available at


If you like this package and use it in your own work, please cite our '''IJRR paper''':

  author    = {David Fischinger and Astrid Weiss and Markus Vincze},
  title     = {Learning Grasps with Topographic Features},
  journal   = {I. J. Robotic Res.},
  volume    = {34},
  number    = {9},
  pages     = {1167--1194},
  year      = {2015},
  url       = {},
  doi       = {10.1177/0278364915577105},
  timestamp = {Fri, 31 Jul 2015 01:00:00 +0200},
  biburl    = {},
  bibsource = {dblp computer science bibliography,}


Use GitHub to report bugs or submit feature requests. [View active issues]
or contact the package maintainer directly.

Wiki: haf_grasping (last edited 2017-01-03 16:23:07 by DavidFischinger)