calc_grasppoints_action_server.cpp
Go to the documentation of this file.
00001 /*
00002  * calc_grasppoints_action_server.cpp
00003  *
00004  *     ActionServer for calculating grasp points with Height Accumulated Features
00005  *     (see Int. Journal of Robotics Research, 21st July 2015: http://ijr.sagepub.com/content/34/9/1167)
00006  *
00007  *     Author: David Fischinger, Vienna University of Technology
00008  *     Date:   August 2015
00009  *
00010  *     This ActionServer calculates grasp points and approach vectors, given an input-goal
00011  *     (incl. point cloud and grasp search parameters such as the area where to search for grasps (center and size),
00012  *     goal_frame_id for point cloud transformation, maximal calculation time, approach vector, ..).
00013  *     In a first step for the given approach vector and different tested gripper rotations a height grid is created from the point cloud.
00014  *     For each 14x14 square of the height grid a feature vector is created.
00015  *     Using SVM with an existing model file, it is predicted if the center of the square is a good
00016  *     grasping point. For the best grasping point the coordinates and the direction of the approach vector and the gripper orientation
00017  *     is published.
00018  *
00019  *
00020  *      == Input ==
00021  *
00022  *      An action goal including a point cloud of objects (in a local coordinates system (lcs) where z-axis is pointing upwards)
00023  *
00024  *      == Output ==
00025  *
00026  *      Grasp points and approach vector which are detected using Support Vector Machines with Height Accumulated Features
00027  *      Format: eval, gp1_x, gp1_y, gp1_z, gp2_x, gp2_y, gp2_z, appr_dir_x, appr_dir_y, appr_dir_z roll
00028  *              - eval: an evaluation value between 10 and 99. (99 is the top value)
00029  *              - gp1_x: x value for the first of the two grasp points
00030  *              - gp2_x: x value for the second grasp point (analog for y- and z-values)
00031  *              - appr_dir_x, appr_dir_y, appr_dir_z: approach direction; direction that has to be used to approach to the object with the grippers tcp
00032  *              - roll: the roll orientation of the gripper in degree
00033  *
00034  *
00035  *      == USAGE ==
00036  *
00037  *      us the calc_grasppoints_action_client for convenient usage
00038  *
00039  *      == PARAMETERS ==
00040  *
00041  *      outputpath_full = "/tmp/features.txt";
00042  *      path_svm_output = "/tmp/output_calc_gp.txt";
00043  *
00044  */
00045 
00046 
00047 //System includes
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <sstream>
00051 #include <iostream>
00052 #include <iomanip>
00053 #include <unistd.h>
00054 #include <math.h>
00055 #include <time.h>
00056 //tf
00057 #include <tf/tf.h>
00058 #include <tf/transform_broadcaster.h>
00059 #include <tf/transform_datatypes.h>
00060 #include <tf/transform_listener.h>
00061 #include "tf/LinearMath/Transform.h"
00062 //PCL includes
00063 #include <pcl_ros/point_cloud.h>
00064 #include "pcl_ros/transforms.h"
00065 #include "pcl_ros/publisher.h"
00066 #include "pcl/io/io.h"
00067 #include "pcl/point_types.h"
00068 #include "pcl/point_cloud.h"
00069 #include "pcl/registration/ia_ransac.h"
00070 #include <pcl/point_types.h>
00071 #include <pcl/io/pcd_io.h>
00072 //ROS includes
00073 #include <ros/ros.h>
00074 #include "ros/ros.h"
00075 #include "ros/package.h"
00076 #include "std_msgs/String.h"
00077 #include "sensor_msgs/PointCloud2.h"
00078 #include "geometry_msgs/Vector3.h"
00079 #include <visualization_msgs/Marker.h>
00080 #include <visualization_msgs/MarkerArray.h>
00081 //Actionlib
00082 #include <actionlib/server/simple_action_server.h>
00083 #include <haf_grasping/CalcGraspPointsServerAction.h>
00084 
00085 
00086 
00087 //#include <opencv/cv.h>
00088 
00089 #include <CIntImage_to_Featurevec.h>
00090 
00091 //new HEIGHT and WIDTH have to be next higher even number of the up-rounded square root of (HEIGHT*HEIGHT+WIDTH*WIDTH)
00092 #define HEIGHT 56
00093 #define WIDTH 56
00094 #define PI 3.141592653
00095 #define ROLL_STEPS_DEGREE 15    //define in degree how different the tested rolls should be
00096 #define TILT_STEPS_DEGREE 40    //define in degree the angle for one tilt step
00097 #define TILT_STEPS 1                    //define the number of tilt steps [not used anymore]
00098 
00099 //define maximal degree of rotation of box, should be normally 180+ROLL_STEPS_DEGREE because in OR the opposite
00100 //grasp is always tested (=> overall 360 degree). Set this value to ROLL_STEPS_DEGREE if only the first rotation should be checked!
00101 #define ROLL_MAX_DEGREE 190//190
00102 
00103 
00104 using namespace std;
00105 //using namespace cv;
00106 
00107 class CCalc_Grasppoints
00108 {
00109 protected:
00110         // define ROS node
00111         ros::NodeHandle nh_;
00112         // define simple action server for grasp calculation
00113         actionlib::SimpleActionServer<haf_grasping::CalcGraspPointsServerAction> as_;
00114         std::string action_name_;
00115         // create messages that are used to publish feedback/result
00116         haf_grasping::CalcGraspPointsServerFeedback feedback_;
00117         haf_grasping::CalcGraspPointsServerResult result_;
00118 
00119 
00120 public:
00121         ros::Subscriber box_position_sub;       //subscriber for x and y coordinates of the box center and the rotation
00122         ros::Subscriber pc_sub;                         //subscriber for the point cloud (point of objects without basket)
00123         ros::Publisher pubInputPCROS;
00124         ros::Publisher pubTransformedPCROS;     //publisher for transformed point cloud for visualization purpose
00125         ros::Publisher pubGraspPoints;          //publisher for grasp points
00126         ros::Publisher pubGraspPointsEval;      //publisher for grasp points with evaluation at the first 2 position (value: 10-99)
00127         ros::Publisher vis_pub;                         //Marker (for visualization of grasps)
00128         ros::Publisher vis_pub_ma;                      //MarkerArray (for visualization of grasps)
00129         ros::Publisher vis_pub_ma_params;       //MarkerArray (for visualization of grasp parameters: search filed size, gripper closing direction,..)
00130         geometry_msgs::Point graspsearchcenter; //substitute for box_center_x/y => origin of approach vector
00131         float boxrot_angle_init;                        //angle the box is rotated in real world w.r.t. "default" position
00132         int grasp_search_area_size_x_dir;       // defines the size (x-direction) of the rectangle where grasps are searched
00133         int grasp_search_area_size_y_dir;   // defines the size (y-direction) of the rectangle where grasps are searched
00134         geometry_msgs::Vector3 approach_vector; // defines approach direction for grasp
00135         float max_duration_for_grasp_calc;      //maximal time (in seconds) before a result is returned
00136         float heightsgridroll[ROLL_MAX_DEGREE/ROLL_STEPS_DEGREE][TILT_STEPS][HEIGHT][WIDTH];
00137         float integralimageroll[ROLL_MAX_DEGREE/ROLL_STEPS_DEGREE][TILT_STEPS][HEIGHT+1][WIDTH+1];
00138         bool point_inside_box_grid[ROLL_MAX_DEGREE/ROLL_STEPS_DEGREE][TILT_STEPS][HEIGHT][WIDTH];       //saves for which points featurevector is calculated
00139         string outputpath_full;
00140         bool return_only_best_gp;
00141         string base_frame_id;                                   //base frame for calculation of grasps
00142         int graspval_th;                                        //treshold if grasp hypothesis should be returned
00143         int graspval_top;                                       //optimal grasp evaluation possible
00144         int graspval_max_diff_for_pub;
00145         //define x,y,and roll for top grasp for overall grasping (all tilts, all rows)
00146         int id_row_top_overall;
00147         int id_col_top_overall;
00148         int nr_roll_top_overall;
00149         int nr_tilt_top_overall;
00150         int topval_gp_overall;
00151         int marker_cnt;
00152         haf_grasping::GraspOutput gp_result; //saves return values for ActionServer
00153         tf::TransformListener tf_listener;
00154         bool visualization;
00155         bool print_heights_bool; //indicates if grid heights should be printed on screen
00156         Eigen::Matrix4f av_trans_mat;   //transformation matrix for approach vector
00157         float trans_z_after_pc_transform; // additional translation in z-axis direction to guarantee that all height values are bigger zero (for haf-calculation)
00158         tf::Quaternion quat_tf_to_tf_help;      //saves quaternion for axis transformation
00159         string feature_file_path;               //path to files of Features (Features.txt)
00160         string range_file_path;
00161         string svmmodel_file_path;
00162         int nr_features_without_shaf;
00163         int gripper_opening_width;
00164 
00165 
00166         void print_heights(int nr_roll, int nr_tilt);
00167         void read_pc_cb(const haf_grasping::CalcGraspPointsServerGoalConstPtr &goal); // receive action goal incl. point cloud and grasp search parameters
00168         void loop_control(pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in);
00169         void generate_grid(int roll, int tilt, pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in);
00170         void publish_transformed_pcl_cloud(int roll, int tilt, pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in);
00171         void calc_intimage(int roll, int tilt);
00172         void calc_featurevectors(int roll, int tilt);
00173         void pnt_in_box(int nr_roll, int nr_tilt);
00174         void predict_bestgp_withsvm(bool svm_with_probability=false);
00175         void show_predicted_gps(int nr_roll, int tilt, bool svm_with_probability=false);
00176         void transform_gp_in_wcs_and_publish(int id_row_top_all, int id_col_top_all,int nr_roll_top_all, int nr_tilt_top_all, int scaled_gp_eval);
00177         void publish_grasp_grid(int nr_roll, int tilt, float graspsgrid[][WIDTH], int gripperwidth);
00178         void gp_to_marker(visualization_msgs::Marker *marker, float x, float y, float z, float green, bool pubmarker, int gripperwidth, int nr_roll, bool pub_grip_open_dir, bool pub_grid);
00179         void grasp_area_to_marker(visualization_msgs::Marker *marker, float x, float y, float z, int gripperwidth, int nr_roll, int param_id, bool top_grasp);
00180 
00181         CCalc_Grasppoints(string name) :
00182             as_(nh_, name, boost::bind(&CCalc_Grasppoints::read_pc_cb, this, _1), false),
00183             action_name_(name)
00184         {
00185                 this->pubGraspPointsEval = nh_.advertise<std_msgs::String>("/haf_grasping/grasp_hypothesis_with_eval", 1);
00186                 this->vis_pub = nh_.advertise<visualization_msgs::Marker>( "visualization_marker", 1 );                                 //Marker
00187                 this->vis_pub_ma = nh_.advertise<visualization_msgs::MarkerArray>( "visualization_marker_array", 1 );   //MarkerArray
00188                 this->vis_pub_ma_params = nh_.advertise<visualization_msgs::MarkerArray>( "visualization_marker_array_grasp_params", 1 );       //MarkerArray for grasp params
00189                 this->pubInputPCROS = nh_.advertise<sensor_msgs::PointCloud2>( "/haf_grasping/calc_gp_as_inputpcROS", 1);
00190                 this->pubTransformedPCROS = nh_.advertise<sensor_msgs::PointCloud2>( "/haf_grasping/transformed_point_cloud",1);
00191                 this->graspsearchcenter.x = 0;  //default value
00192                 this->graspsearchcenter.y = 0;  //default value
00193                 this->graspsearchcenter.z = 0;  //default value
00194                 this->grasp_search_area_size_x_dir = 32;
00195                 this->grasp_search_area_size_y_dir = 44;
00196                 this->approach_vector.x = 0;    //default value
00197                 this->approach_vector.y = 0;    //default value
00198                 this->approach_vector.z = 1;    //default value
00199                 this->max_duration_for_grasp_calc = 50;         //max calculation time before restult is returned (in sec)
00200                 outputpath_full = "/tmp/features.txt";
00201                 this->return_only_best_gp = false;
00202                 graspval_th = 70;                                       //treshold if grasp hypothesis should be returned (in function - so program internal) (for top result of one loop run)
00203                 graspval_top = 119;
00204                 graspval_max_diff_for_pub = 80;         //if the value of grasps is more than graspval_max_diff_for_pub lower than optimal value graspval_top, nothing gets published (for top result of one whole roll run)
00205                 id_row_top_overall = -1;
00206                 id_col_top_overall = -1;
00207                 nr_roll_top_overall = -1;
00208                 nr_tilt_top_overall = -1;
00209                 topval_gp_overall = -1000;
00210                 marker_cnt = 0;
00211                 this->visualization = true;
00212                 this->print_heights_bool = false;
00213                 this->av_trans_mat = Eigen::Matrix4f::Identity();;      //transformation matrix for approach vector
00214                 this->trans_z_after_pc_transform = 0.15;
00215                 this->gripper_opening_width = 1;
00216 
00217                 //parameter for svm classification
00218                 this->feature_file_path = "";
00219                 nh_.param("feature_file_path", this->feature_file_path, this->feature_file_path);
00220                 this->range_file_path = "";
00221                 nh_.param("range_file_path", this->range_file_path, this->range_file_path);
00222                 this->svmmodel_file_path = "";
00223                 nh_.param("svmmodel_file_path", this->svmmodel_file_path, this->svmmodel_file_path);
00224                 this->nr_features_without_shaf = 302;   //default value
00225                 nh_.param("nr_features_without_shaf", this->nr_features_without_shaf, this->nr_features_without_shaf);
00226 
00227             as_.start();
00228         }
00229 };
00230 
00231 
00232 
00233 // Print heights of heightsgridroll
00234 void CCalc_Grasppoints::print_heights(int nr_roll, int nr_tilt)
00235 {
00236         //print heights matrix
00237         cout << "\n CCalc_Grasppoints::print_heights: print heights matrix for roll number : " << nr_roll << "\t and tilt nr: "<< nr_tilt << endl;
00238         for (int i = 0; i < HEIGHT; i++){  //rows
00239                 for (int j = 0; j < WIDTH; j++){  //cols
00240                         cout << setw(5) << setprecision(2) << this->heightsgridroll[nr_roll][nr_tilt][HEIGHT-i-1][WIDTH-j-1];
00241                 }
00242                 cout << "\n";
00243         }
00244 }
00245 
00246 
00247 
00248 // Callback triggered by input goal: variable are set from the goal and the loop for grasp point calculation is started
00249 // Input: action goal including point clout, approach direction, center position where to grasp (x-,y-,z-coordinates), size of area where grasps are searched
00250 void CCalc_Grasppoints::read_pc_cb(const haf_grasping::CalcGraspPointsServerGoalConstPtr &goal)
00251 {
00252         ROS_INFO("\n ==> calc_grasppoints_action_server.cpp: read_pc_cb() --> GRASP GOAL RECEIVED (incl. point cloud)");
00253         //transform point cloud to PCL
00254         pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in;
00255         pcl::PointCloud<pcl::PointXYZ> pc_new_cs;
00256 
00257         // set center of area where grasps are searched
00258         this->graspsearchcenter.x = goal->graspinput.grasp_area_center.x;
00259         this->graspsearchcenter.y = goal->graspinput.grasp_area_center.y;
00260         this->graspsearchcenter.z = goal->graspinput.grasp_area_center.z;
00261 
00262         cout << "************************************************************************************************************" << endl;
00263         cout << " --> SET NEW GRASP SEARCH CENTER:  [x,y,z] = [" << this->graspsearchcenter.x << "," << this->graspsearchcenter.y << "," << this->graspsearchcenter.z << "]" << endl;
00264 
00265         // define size of area where to search for grasp points
00266         this->grasp_search_area_size_x_dir = goal->graspinput.grasp_area_length_x;
00267         this->grasp_search_area_size_y_dir = goal->graspinput.grasp_area_length_y;
00268 
00269         //define grasp approach vector (and normalize)
00270         float vector_length = sqrt(goal->graspinput.approach_vector.x*goal->graspinput.approach_vector.x+goal->graspinput.approach_vector.y*goal->graspinput.approach_vector.y+goal->graspinput.approach_vector.z*goal->graspinput.approach_vector.z);
00271         this->approach_vector.x = goal->graspinput.approach_vector.x/vector_length;
00272         this->approach_vector.y = goal->graspinput.approach_vector.y/vector_length;
00273         this->approach_vector.z = goal->graspinput.approach_vector.z/vector_length;
00274         cout << " --> SET APPROACH VECTOR TO:      " << " [x,y,z] = [" << this->approach_vector.x << "," << this->approach_vector.y << "," << this->approach_vector.z << "]" << endl;
00275 
00276         // set maximal calculation time
00277         this->max_duration_for_grasp_calc = (float) goal->graspinput.max_calculation_time.toSec();
00278         cout << " --> SET MAX. CALCULATION TIME TO: " <<  this->max_duration_for_grasp_calc << endl;
00279 
00280         // set pre-grasp gripper opening width (factor f for scaling pc to imitate gripper opening width of 1/f of maximum)
00281         this->gripper_opening_width = (float) goal->graspinput.gripper_opening_width;
00282 
00283         // set if only the best grasp should be visualized
00284         this->return_only_best_gp = (bool) goal->graspinput.show_only_best_grasp;
00285         cout << " --> SET show_only_best_grasp TO:  " << this->return_only_best_gp << endl;
00286 
00287         // set frame_id needed as base frame for calculation
00288         string orig_tf = (string) goal->graspinput.input_pc.header.frame_id;
00289         cout << " --> FRAME_ID ORIGINAL Point Cloud: " << orig_tf << endl;
00290 
00291         cout << "Fixed by now: this->trans_z_after_pc_transform: " << this->trans_z_after_pc_transform << endl;
00292 
00293         // set base_frame_id to goal_frame_id if set
00294         if (!goal->graspinput.goal_frame_id.empty())
00295         {
00296             this->base_frame_id = goal->graspinput.goal_frame_id;
00297         }
00298         else
00299         {
00300             this->base_frame_id = "/base_link";
00301         }
00302         cout << " --> BASE_FRAME_ID: " << this->base_frame_id << endl;
00303 
00304         cout << "************************************************************************************************************" << endl;
00305 
00306         //search for tf transform between camera and robot coordinate system
00307         bool foundTransform = tf_listener.waitForTransform(this->base_frame_id, orig_tf, goal->graspinput.input_pc.header.stamp, ros::Duration(1.0));
00308         if (!foundTransform)
00309         {
00310                 ROS_WARN(" ==> calc_grasppoints_action_server.cpp: read_pc_cb(): NO TRANSFORM FOR POINT CLOUD FOUND");
00311         }
00312 
00313         pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in_old_cs;
00314         pcl::fromROSMsg(goal->graspinput.input_pc, pcl_cloud_in_old_cs); // transform ROS msg into PCL-pointcloud
00315 
00316         pcl_ros::transformPointCloud(this->base_frame_id, pcl_cloud_in_old_cs, pc_new_cs, tf_listener);
00317 
00318         //publish input pc:
00319         this->pubInputPCROS.publish(goal->graspinput.input_pc);
00320 
00321         //set initial values for row,col,tilt,topval for top grasp points
00322         id_row_top_overall = -1;
00323         id_col_top_overall = -1;
00324         nr_roll_top_overall = -1;
00325         nr_tilt_top_overall = -1;
00326         topval_gp_overall = -1000;
00327 
00328         loop_control(pc_new_cs);
00329 }
00330 
00331 
00332 
00333 //Main function: controls the sequence and execution of class methods
00334 //loop goes through all rolls [tilts are currently not used] and executes necessary methods for calculation of gps
00335 void CCalc_Grasppoints::loop_control(pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in)
00336 {
00337         int time_for_calc_in_secs = this->max_duration_for_grasp_calc;
00338         time_t start,end;
00339         time (&start);
00340         double timedif;
00341         bool success = true;
00342 
00343         for (int tilt = 0; tilt < TILT_STEPS; tilt++)                   // tilt loop
00344         {
00345                 for (int roll = 0; roll < ROLL_MAX_DEGREE/ROLL_STEPS_DEGREE; roll++)    // roll loop
00346                 {
00347                     // feedback:                    (3.12.2014)
00348                     feedback_.feedback.data = "this->topval_gp_overall";        //shows best gp so far
00349 
00350                     if (as_.isPreemptRequested() || !ros::ok() || success == false)
00351                          {
00352                            ROS_INFO("%s: Preempted", action_name_.c_str());
00353                            // set the action state to preempted
00354                            as_.setPreempted();
00355                            success = false;
00356                            break;
00357                          }
00358 
00359                     as_.publishFeedback(feedback_);
00360 
00361 
00362                         if (this->return_only_best_gp and (this->topval_gp_overall >= this->graspval_top)){
00363                                 cout << "Top grasp already found\n";
00364                                 break;
00365                         }
00366 
00367                         //calculate only for defined time
00368                         time (&end);
00369                         timedif = difftime (end,start);
00370                         cout << "\n ===> TEST ROTATION: " << roll*ROLL_STEPS_DEGREE << "\nRuntime so far (in sec): " << timedif << endl;
00371                         if (timedif > time_for_calc_in_secs) {
00372                                 cout << "\n Calculation time is over, stop calculation of grasp points!!\n";
00373                                 break;
00374                         }
00375 
00376                         generate_grid(roll, tilt, pcl_cloud_in);
00377                         if (this->print_heights_bool){
00378                                 print_heights(roll,tilt);
00379                         }
00380                         calc_intimage(roll, tilt);
00381                         calc_featurevectors(roll, tilt);
00382                         //ii_to_fv->print_heights(ii_to_fv->intimagemat);
00383                         bool svm_with_probability = false;
00384                         predict_bestgp_withsvm(svm_with_probability);
00385                         show_predicted_gps(roll, tilt, svm_with_probability);
00386                 }
00387         }
00388         //publish original point cloud (to see where grasp was found)
00389         publish_transformed_pcl_cloud(0, 0, pcl_cloud_in);      //publish point cloud input (as received at beginning)
00390         transform_gp_in_wcs_and_publish(this->id_row_top_overall, this->id_col_top_overall, this->nr_roll_top_overall,this->nr_tilt_top_overall, this->topval_gp_overall-20); //last entry is "scaled" (=> -16)
00391 
00392         time (&end);
00393         timedif = difftime (end,start);
00394         cout << "\n Gesamtzeit fuer Loop: " << timedif << endl;
00395 
00396         if(success)     // ActionServer: return grasp representation (overall best grasp)
00397         {
00398                 result_.graspOutput = this->gp_result;
00399                 ROS_INFO_STREAM("Succeeded:\n" << this->gp_result);
00400                 as_.setSucceeded(result_);
00401         }
00402 }
00403 
00404 
00405 // transforms point cloud and generates height grid
00406 void CCalc_Grasppoints::generate_grid(int roll, int tilt, pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in)
00407 {
00408         pcl::PointCloud<pcl::PointXYZ> pcl_cloud_transformed;
00409         int nr_rows = HEIGHT, nr_cols = WIDTH;
00410         float r_col_m = (0.5 * (float)nr_cols)/100.0;   //"Matrix radius" in meter for cols
00411         float r_row_m = (0.5 * (float)nr_rows)/100.0;   //"Matrix radius" in meter for rows
00412         float rot_about_z;              //rotation needed about z-axis to align y-axis (old cs) with orthoganal projection of new z-axis on x-y-plane (rad)
00413         float rot_about_x = 0;  //rotation needed to align z axis old with z-axis new after rot_about_z was executed (this way old x-axis keeps direction in x-y-plane) (rad)
00414         pcl::PointXYZ pnt;              //point for loop
00415         pcl::PointXYZ *av = new pcl::PointXYZ(0,0,-1);  //approach vector (default would be (0,0,1) because we define AV in a way that it is equal to new z-axis for grasp calculation
00416 
00417 
00418         av->x = this->approach_vector.x;
00419         av->y = this->approach_vector.y;
00420         av->z = this->approach_vector.z;
00421         //cout <<  "\nApproach vector: [" << av->x << "," << av->y << "," << av->z << "]" << endl;
00422 
00423         Eigen::Matrix4f mat_sh_to_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from search center to origin
00424         Eigen::Matrix4f mat_rot_z_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about z-axis)
00425         Eigen::Matrix4f mat_rot_x_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about x-axis)
00426         Eigen::Matrix4f mat_sh_from_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from origin to basket center
00427         Eigen::Matrix4f mat_rot = Eigen::Matrix4f::Identity(); //matrix which rotates pc and then shifts pc back to box center
00428         Eigen::Matrix4f mat_scale_x_dir = Eigen::Matrix4f::Identity();//NEW grippertest: scale point cloud
00429 
00430         Eigen::Matrix4f mat_transform = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about box center)
00431 
00432 
00433         mat_scale_x_dir(0,0) = this->gripper_opening_width;     //NEW grippertest: scale point cloud in x-axis direction
00434 
00435         mat_sh_to_orig(0,3) = -this->graspsearchcenter.x;       //shift x value
00436         mat_sh_to_orig(1,3) = -this->graspsearchcenter.y;       //shift y-value
00437         mat_sh_to_orig(2,3) = -this->graspsearchcenter.z;       //shift z-value
00438 
00439         mat_sh_from_orig(0,3) = 0;// this->graspsearchcenter.x;                 //!!!! 17.8.2015
00440         mat_sh_from_orig(1,3) = 0;//this->graspsearchcenter.y;
00441         mat_sh_from_orig(2,3) = /*this->graspsearchcenter.z*/0 + this->trans_z_after_pc_transform;      //move pc up to make calculation possible
00442 
00443 
00444         if (av->y == 0 and av->x == 0){ //if av->y = av->x = 0
00445                 rot_about_z = 0;
00446                 if (av->z >= 0) {
00447                         rot_about_x = 0;        //grasp from top
00448                 } else {
00449                         rot_about_x = PI;       //grasp from upside down (in practice hardly relevant)
00450                 }
00451         } else {        //av->y <> 0 or = av->x <> 0
00452                 rot_about_z = 90*PI/180.0 - atan2(av->y, av->x);        // av->y, av->x not both 0
00453                 rot_about_x = 90*PI/180.0 - atan2( av->z, sqrt(av->y*av->y + av->x*av->x) );
00454         }
00455 
00456         //cout << "rot_about_z: " << rot_about_z << "\nav->y: " << av->y << "\nav->x: " << av->x << endl;
00457         //cout << "rot_about_x: " << rot_about_x << "\nav->z: " << av->z << "\nav->y: " << av->y << endl;
00458 
00459         //define matrices s.t. transformation matrix can be calculated for point cloud (=> roll and tilt are simulated)
00460 
00461         //define rotation about z-axis (for roll loop):
00462         float angle = roll*ROLL_STEPS_DEGREE*PI/180;//roll*ROLL_STEPS_DEGREE*PI/180 + this->boxrot_angle_init;  //angle for roll
00463         mat_rot(0,0) = cos(angle);
00464         mat_rot(0,1) = -sin(angle);
00465         mat_rot(1,0) = sin(angle);
00466         mat_rot(1,1) = cos(angle);
00467 
00468         //define rotation about z-axis:
00469         mat_rot_z_axis(0,0) = cos(rot_about_z);
00470         mat_rot_z_axis(0,1) = -sin(rot_about_z);
00471         mat_rot_z_axis(1,0) = sin(rot_about_z);
00472         mat_rot_z_axis(1,1) = cos(rot_about_z);
00473 
00474 
00475         //define rotation about x-axis
00476         mat_rot_x_axis(1,1) = cos(rot_about_x);
00477         mat_rot_x_axis(1,2) = -sin(rot_about_x);
00478         mat_rot_x_axis(2,1) = sin(rot_about_x);
00479         mat_rot_x_axis(2,2) = cos(rot_about_x);
00480 
00481         // transforms pc in a way that the old coordinate system is transformed to the new one by rotation about first: z-axis, second (new) x-axis
00482         //NEW: point cloud scaling for gripper opening
00483         mat_transform = mat_scale_x_dir * mat_rot* mat_sh_from_orig * mat_rot_x_axis * mat_rot_z_axis * mat_sh_to_orig;     //define transformation matrix mat_transform
00484         this->av_trans_mat = mat_transform;     //class variable to transform visualization stuff
00485 
00486 
00487         pcl::copyPointCloud(pcl_cloud_in, pcl_cloud_transformed);
00488         pcl::transformPointCloud(pcl_cloud_in, pcl_cloud_transformed, mat_transform);  //transform original point cloud
00489 
00490 
00491         //publish transformed point cloud:
00492         if (this->visualization)
00493         {
00494                 cout << "Publish transformed point cloud! \n";
00495                 this->pubTransformedPCROS.publish(pcl_cloud_transformed);
00496         }
00497 
00498         //set heightsgridroll to -1.0 at each position
00499         for (int i = 0; i < nr_rows; i++)
00500                 for (int j = 0; j < nr_cols; j++)
00501                         this->heightsgridroll[roll][tilt][i][j]= -1.0;  //needed because after tilting (now: general pc transform) values below 0 possible
00502 
00503         //make heightsgrid (find highest points for each 1x1cm rectangle); translate grid s.t. it starts with (0,0)
00504         for (size_t i = 0; i < pcl_cloud_transformed.points.size(); ++i)
00505         {
00506                 //In the current implementation the point cloud was centered about origin (at least x-/y-coordinates), before grasps are calculated w.r.t. graspsearchcenter
00507                 //=> no shift is needed here
00508                 int idx_x = -1, idx_y = -1;
00509                 pnt = pcl_cloud_transformed.points[i];
00510                 if ((pnt.x > /*this->graspsearchcenter.x*/-r_row_m) and (pnt.x < /*this->graspsearchcenter.x+*/ r_row_m) and
00511                         (pnt.y > /*this->graspsearchcenter.y*/-r_col_m) and (pnt.y < /*this->graspsearchcenter.y+*/r_col_m))
00512                 { //point is relevant for object grid
00513                         idx_x = (int) (floor (100*(pnt.x - (/*this->graspsearchcenter.x*/ - r_row_m))));
00514                         idx_y = (int) (floor (100*(pnt.y - (/*this->graspsearchcenter.y*/ - r_col_m))));;
00515                         if (heightsgridroll[roll][tilt][idx_x][idx_y] < pnt.z)
00516                         {
00517                                 heightsgridroll[roll][tilt][idx_x][idx_y] = pnt.z;
00518                         }
00519                 }
00520         }
00521 
00522         for (int i = 0; i < nr_rows; i++){
00523                 for (int j = 0; j < nr_cols; j++){
00524                         if (this->heightsgridroll[roll][tilt][i][j] < -0.99){
00525                                 this->heightsgridroll[roll][tilt][i][j] = 0; //set values where no points are, to zero
00526                         }
00527                 }
00528         }
00529 }
00530 
00531 
00532 //function by now only used to publish original point cloud without transformations
00533 void CCalc_Grasppoints::publish_transformed_pcl_cloud(int roll, int tilt, pcl::PointCloud<pcl::PointXYZ> pcl_cloud_in)
00534 {
00535         pcl::PointCloud<pcl::PointXYZ> pcl_cloud_transformed;
00536 
00537         Eigen::Matrix4f mat_sh_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from center to origin
00538         Eigen::Matrix4f mat_rot = Eigen::Matrix4f::Identity(); //matrix which rotates pc and then shifts pc back to box center
00539         Eigen::Matrix4f mat_tilt = Eigen::Matrix4f::Identity(); //matrix which tilts pc  NEW
00540         Eigen::Matrix4f mat_sh_from_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from origin to basket center
00541         Eigen::Matrix4f mat_transform = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about box center)
00542 
00543         mat_sh_orig(0,3) = -this->graspsearchcenter.x;  //shift x value
00544         mat_sh_orig(1,3) = -this->graspsearchcenter.y;   //shift y-value
00545         mat_sh_from_orig(0,3) = this->graspsearchcenter.x;
00546         mat_sh_from_orig(1,3) = this->graspsearchcenter.y;
00547 
00548         //define matrices s.t. transformation matrix can be calculated for point cloud (=> roll and tilt are simulated)
00549 
00550         //next 5 lines could be outside tilt-loop
00551         float angle = roll*ROLL_STEPS_DEGREE*PI/180 + this->boxrot_angle_init;  //angle for roll
00552         mat_rot(0,0) = cos(angle);
00553         mat_rot(0,1) = -sin(angle);
00554         mat_rot(1,0) = sin(angle);
00555         mat_rot(1,1) = cos(angle);
00556 
00557         float beta = -tilt*TILT_STEPS_DEGREE*PI/180; //angle for tilt in Rad
00558         mat_tilt(0,0) = cos(beta);
00559         mat_tilt(0,2) = -sin(beta);
00560         mat_tilt(2,0) = sin(beta);
00561         mat_tilt(2,2) = cos(beta);
00562 
00563         mat_transform = mat_sh_from_orig*mat_tilt*mat_rot*mat_sh_orig;  //define transformation matrix mat_transform
00564 
00565         pcl::copyPointCloud(pcl_cloud_in, pcl_cloud_transformed);       // copy notwendig??
00566         pcl::transformPointCloud(pcl_cloud_in, pcl_cloud_transformed, mat_transform);  //transform original point cloud
00567 
00568 
00569         //publish transformed point cloud:
00570         this->pubTransformedPCROS.publish(pcl_cloud_transformed);
00571 }
00572 
00573 
00574 
00575 
00576 //calculates integral image of heights grid
00577 void CCalc_Grasppoints::calc_intimage(int roll, int tilt)
00578 {
00579     cv::Mat heightsIntegral;
00580     heightsIntegral = cv::Mat(HEIGHT+1, WIDTH+1, CV_64FC1);
00581         //cout << "\n print integral height matrix on screen\n";
00582 
00583     double *TempHeights = (double *)malloc(HEIGHT * WIDTH * sizeof(double));
00584 
00585     int k = 0;
00586     for(int i = 0; i < HEIGHT; i++ )
00587         for(int j = 0; j < WIDTH; j++ )
00588         {
00589                 TempHeights[k] = this->heightsgridroll[roll][tilt][i][j];
00590                 k++;
00591         }
00592 
00593     cv::Mat const cvheightsmat = cv::Mat(HEIGHT, WIDTH, CV_64FC1, TempHeights);
00594         //Mat const cvheightsmat = Mat(HEIGHT, WIDTH, CV_64FC1, this->heightsgridroll[roll][tilt]);
00595         integral(cvheightsmat, heightsIntegral,CV_64FC1);
00596 
00597 
00598         //copy integral image from opencv format to normal matrix format (better implementation would be fine)
00599         for (int row = 0; row < 1+HEIGHT; row++)  //rows
00600                 for (int col = 0; col < 1+WIDTH; col++)  //cols
00601                         this->integralimageroll[roll][tilt][row][col] = ((double*)(heightsIntegral.ptr() + heightsIntegral.step*row))[col];
00602 
00603         //print integral matrix
00604         /*cout << "\n print integral height matrix on screen (intuitiv way)\n";
00605         for (int row = 0; row < 1+HEIGHT; row++){  //rows
00606                 cout << endl;
00607                 for (int col = 0; col < 1+WIDTH; col++){  //cols
00608                         cout << this->integralimageroll[roll][tilt][HEIGHT-row][WIDTH-col] << "\t";
00609                 }
00610         }*/
00611 
00612         free(TempHeights);
00613 }
00614 
00615 
00616 void CCalc_Grasppoints::calc_featurevectors(int roll, int tilt)
00617 {
00618         //cout << "\n calc_featurevectors \n";
00619 
00620         //create object for calculating features
00621         CIntImage_to_Featurevec * ii_to_fv = new CIntImage_to_Featurevec();
00622 
00623         string pkg_path = ros::package::getPath("haf_grasping");
00624         //read all features (saved in external file)
00625         //ii_to_fv->read_features(pkg_path); feature_file_path
00626         if (this->feature_file_path == ""){
00627                 this->feature_file_path = pkg_path + "/data/Features.txt";      //path to default Features
00628         }
00629         ii_to_fv->read_features(this->feature_file_path);
00630 
00631         //silly way to delete file
00632         ofstream output_fv_file(outputpath_full.c_str());
00633 
00634 
00635         pnt_in_box(roll, tilt); //calculate if points are inside box, saved in this->point_inside_box_grid[roll][nr_tilt][][]
00636 
00637         for (int row = 0; row < HEIGHT - 14; row++){
00638                 for (int col = 0; col < WIDTH -14; col++)
00639                 {
00640                         //check if grasping point is possible (inside box) ("inside box detection code")
00641                         if (!this->point_inside_box_grid[roll][tilt][row+7][col+7]){   //point not inside box (not relevant)
00642                                 continue;       //do not generate feature vector for this point
00643                         }
00644                         //if (row == 10 and col == 10) cout << "\n one 15x15 intimage: " << ++cnt << "\n";
00645                         //write integral image (15x15!)  => better implementation will come later
00646                         for (int i = 0; i < 15; i++){
00647                                 for (int j = 0; j < 15; j++){
00648                                         ii_to_fv->intimagemat[i][j] = this->integralimageroll[roll][tilt][row+i][col+j];
00649                                 }
00650                         }
00651 
00652                         //calculate featurevector and write it in file
00653                         ii_to_fv->write_featurevector(outputpath_full.c_str(), this->nr_features_without_shaf);
00654                 }
00655         }
00656 }
00657 
00658 
00659 
00660 
00661 // (short: calculates if for a position, the feature vector should be calculated)
00662 //calculates if for a given row and column and a specified number of roll,
00663 //the indicated point (center of 14x14 square) is inside the real box
00664 //AND (new since 6.2.2012): if the point is surrounded by 14x14 integral square!! => feature calculation is possible
00665 // !!!!!!!!!!!!!! at the moment nr_tilt is not used for more exact calculation !!!!!!!!!!
00666 void CCalc_Grasppoints::pnt_in_box(int nr_roll, int nr_tilt){
00667 
00668         bool print_pnt_in_box = false;
00669     //function:
00670     //   ( cx )               ( cos(alpha) )
00671     //g: (    ) +  lambda *   (            ) = r
00672     //   ( cy )               ( sin(alpha) )
00673 
00674     //function parallel to center line:
00675     //   ( cx )       (-sin(alpha)                           ( cos(alpha) )
00676     //g: (      ) +/- (          )*DIMBOX/2    +    lambda * (            ) = r
00677     //   ( cy )       ( cos(alpha)                           ( sin(alpha) )
00678 
00679     float alpha_deg = -nr_roll*ROLL_STEPS_DEGREE - this->boxrot_angle_init * 180/PI;//angle for rotation in degree
00680     float alpha = alpha_deg*PI/180;             //angle for rotation in rad
00681     float cx = HEIGHT/2;                        //x-coordinate for rotation center   works because  !! HEIGHT and WIDTH are equal!!
00682     float cy = HEIGHT/2;                         //y-coordinate for rotation center  works because  !! HEIGHT and WIDTH are equal!!
00683     float cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4;    //coordinates of points which are used to define points inside the box (points at box edges)
00684 
00685     //define points at the center of each of the 4 boarder edges of box
00686     float boarder = 7.0;                                                //ungraspable inside in box (because hand would touch box)
00687     float height_r = this->grasp_search_area_size_x_dir/2 - boarder;    //defines the half of the length of one side of the graspable inside of box (defines rectangle in box rectangle where grasping is possible)
00688     float width_r = this->grasp_search_area_size_y_dir/2 - boarder;             //width is equal to y direction!
00689     cx1 = cx - sin(alpha)*height_r;
00690     cy1 = cy + cos(alpha)*height_r;
00691     cx2 = cx + sin(alpha)*height_r;
00692     cy2 = cy - cos(alpha)*height_r;
00693     cx3 = cx - sin(alpha+PI/2)*width_r;
00694     cy3 = cy + cos(alpha+PI/2)*width_r;
00695     cx4 = cx + sin(alpha+PI/2)*width_r;
00696     cy4 = cy - cos(alpha+PI/2)*width_r;
00697 
00698     if (print_pnt_in_box)
00699         cout << cx1 << "\t" << cy1 << "\n" << cx2 << "\t" << cy2 << "\n" << cx3 << "\t" << cy3 << "\n" << cx4 << "\t" << cy4 << "\n\n";
00700     int cnt_all = 0;
00701     int cnt_in = 0;
00702     int cnt_out = 0;
00703     //i = row, j = col
00704     for (int i = 0; i < HEIGHT; i++){
00705         for (int j = 0; j < HEIGHT; j++){       //(2 times HEIGHT works because HEIGHT and WIDTH are equal!!)
00706                 ++cnt_all;
00707 
00708                 // parameters to check if calculation of feature vector is needed (if no object points are around a potential grasp position, no calculation necessary)
00709                 int th_empty_r = 4;                     //r..radius;if 4 => 8x8cm field is checked if integral image has at least difference of ii_th_in_r
00710                 float ii_th_in_r = 0.03;        //threshold which must be smaller as integral-difference value if featurevec should be calculated
00711 
00712                 // check if point (i,j) is "inside the box" AND not near the overall boarder (of 56x56cm grid)
00713             if ((i>6 and i < HEIGHT-7 and j>6 and j<HEIGHT-7)           and        // take only points which are not in the 7cm boarder of the 56x56 grid (otherwise no featurecalc possible)
00714                         (this->integralimageroll[nr_roll][nr_tilt][i+th_empty_r][j+th_empty_r]-         //check if there are heights (if every height about 0, no calc. of fv needed)
00715                          this->integralimageroll[nr_roll][nr_tilt][i-th_empty_r-1][j+th_empty_r]-
00716                  this->integralimageroll[nr_roll][nr_tilt][i+th_empty_r][j-th_empty_r-1]+
00717                  this->integralimageroll[nr_roll][nr_tilt][i-th_empty_r-1][j-th_empty_r-1] > ii_th_in_r) and
00718                 (-sin(alpha)*(-cx1+j) + cos(alpha)*(-cy1+i) <  0.00001) and    //0.00001 and not 0 because of rounding errors otherwise
00719                 (-sin(alpha)*(-cx2+j) + cos(alpha)*(-cy2+i) > -0.00001) and
00720                 ( cos(alpha)*(-cx3+j) + sin(alpha)*(-cy3+i) > -0.00001) and
00721                 ( cos(alpha)*(-cx4+j) + sin(alpha)*(-cy4+i) <  0.00001)){
00722                 //if (print_pnt_in_box)
00723                 //      cout << " + ";    //point inside box AND (new 6.2.2012) not in boarder of 56x56 grid
00724                 this->point_inside_box_grid[nr_roll][nr_tilt][i][j] = true;
00725                 cnt_in++;
00726             } else {
00727                 //if (print_pnt_in_box)
00728                 //      cout << " - ";    //point not inside box (or near 56x56 boarder => no 14x14 integral grid available => no calc of fv possible)
00729                 this->point_inside_box_grid[nr_roll][nr_tilt][i][j] = false;
00730                 cnt_out++;
00731             }
00732         }
00733     }
00734 
00735     //print pnt_in_box if variable print_pnt_in_box is set
00736     if (print_pnt_in_box){
00737         cout << "points_all: " << cnt_all << "  points in: " << cnt_in << "  and points out: " << cnt_out << endl;
00738         for (int i = HEIGHT-1; i >= 0; i--){
00739                 for (int j = HEIGHT-1; j >= 0; j--){    //(2 times HEIGHT works because HEIGHT and WIDTH are equal!!)
00740                         if (this->point_inside_box_grid[nr_roll][nr_tilt][i][j] == true){
00741                                 cout << " + ";    //point inside box AND (new 6.2.2012) not in boarder of 56x56 grid
00742                         } else {
00743                                 cout << " - ";    //point not inside box (or near 56x56 boarder => no 14x14 integral grid available => no calc of fv possible)
00744                         }
00745             }
00746             cout << endl;
00747         }
00748     }
00749 }
00750 
00751 
00752 
00753 //Use trained SVM-model for grasp prediction (and scale feature values beforehand)
00754 void CCalc_Grasppoints::predict_bestgp_withsvm(bool svm_with_probability){
00755         //executes:
00756         //      ./svm-scale -r ./tools/range /tmp/features.txt > /tmp/features.txt.scale
00757         //  ./svm-predict /tmp/features.txt.scale ./tools/mixedmanual_features_1000_rand.txt.model output
00758 
00759         try{
00760                 string pkg_path = ros::package::getPath("haf_grasping");
00761 
00762                 //scale: use existing scaling file to scale feature values
00763                 stringstream ss, ss2;
00764 
00765 
00766 
00767                 if (this->range_file_path == ""){
00768                         this->range_file_path = pkg_path + "/data/range21062012_allfeatures";   //path to default range file
00769                 }
00770 
00771                 if (this->svmmodel_file_path == ""){
00772                         this->svmmodel_file_path = pkg_path + "/data/all_features.txt.scale.model";     //path to default svm model file
00773                 }
00774 
00775                 ss << pkg_path << "/libsvm-3.12/svm-scale -r " << this->range_file_path << " /tmp/features.txt > /tmp/features.txt.scale";
00776                 string command = ss.str();
00777                 int i = system(command.c_str());
00778                 if (i != 0){
00779                         ROS_WARN(" CCalc_Grasppoints::predict_bestgp_withsvm() SCALING OF FEATURES WAS NOT EXECUTED AS IT SHOULD (Was SVM code compiled?) ");
00780                         cout << "===> CCalc_Grasppoints::predict_bestgp_withsvm: System return value for scaling features is: " << i << endl;
00781                 }
00782 
00783                 //predict grasping points
00784                 if (!svm_with_probability){
00785                         //      trained with all examples
00786                         ss2 << pkg_path << "/libsvm-3.12/svm-predict /tmp/features.txt.scale " << this->svmmodel_file_path << " /tmp/output_calc_gp.txt";
00787                         string command2 = ss2.str();
00788                         i = system(command2.c_str());
00789                 } else {
00790                         //      trained with all manual examples, using probability as output
00791                         i = system("/usr/lib/libsvm/libsvm-3.1/svm-predict -b 1 /tmp/features.txt.scale /usr/lib/libsvm/libsvm-3.1/tools/allmanualfeatures.txt.scale.p.model /tmp/output_calc_gp.txt");
00792                 }
00793                 if (i != 0){
00794                         ROS_WARN(" CCalc_Grasppoints::predict_bestgp_withsvm() GRASP PREDICTION FROM FEATURES WAS NOT EXECUTED AS IT SHOULD (Was SVM code compiled?) ");
00795                         cout << "===> CCalc_Grasppoints::predict_bestgp_withsvm: System return value for execution of grasp prediction with SVM: " << i << endl;
00796                 }
00797         } catch (int j) {
00798                 cerr << "ERROR in calc_grasppoints.cpp: predict_bestgp_withsvm()" << endl;
00799         }
00800 }
00801 
00802 
00803 void CCalc_Grasppoints::show_predicted_gps(int nr_roll, int tilt, bool svm_with_probability){
00804         //PARAMETERS
00805         string path_svm_output =        "/tmp/output_calc_gp.txt";
00806 
00807         //open file
00808         ifstream file_in(path_svm_output.c_str());
00809 
00810         //define x,y,and roll for top grasp
00811         int id_row_top_all = -1;
00812         int id_col_top_all = -1;
00813         int nr_roll_top_all = -1;
00814         int nr_tilt_top_all = -1;
00815         int topval_gp_all = -1000;
00816 
00817         string line;
00818         getline(file_in, line);
00819 
00820         bool printgraspsgrid = false;
00821         bool printgraspseval = false;
00822         float graspsgrid[HEIGHT][WIDTH];
00823         float graspseval[HEIGHT][WIDTH];
00824 
00825         for (int row = 0; row < HEIGHT; row++){
00826                 for (int col = 0; col < WIDTH; col++){
00827                         //check if gp is possible => if featurevector was calculated; no calculation of fv before=> take -1
00828                         if (this->point_inside_box_grid[nr_roll][tilt][row][col] == false){
00829                                 graspsgrid[row][col] = -1;
00830                         } else {
00831                                 if (svm_with_probability){
00832                                         int start=0,end=0, res;
00833                                         res = atof(line.substr(0,2).c_str());
00834                                         start = line.find(" ",0);
00835                                         end = line.find(" ",start+1);
00836                                         if (res>0){  //=> is gp => have to take second probability value in file (otherwise first)
00837                                                 start = end;
00838                                                 end = line.find(" ", start+1);
00839                                         }
00840                                         float prob = atof(line.substr(start,end).c_str());
00841                                         graspsgrid[row][col] = res*prob;
00842                                 } else {
00843                                         graspsgrid[row][col] = atoi(line.substr(0,2).c_str());
00844                                 }
00845 
00846                                 getline(file_in, line);
00847                         }
00848                 }
00849         }
00850 
00851         //print graspgrid in intuitive way (if variable printgraspsgrid is set true)
00852         if (printgraspsgrid){
00853                 cout << "\n Graspsgrid: intuitiv! \n";
00854                 for (int row = HEIGHT-1; row >= 0; row--){
00855                         cout << row << ") \t";
00856                         for (int col = WIDTH-1; col >= 0; col--){
00857                                 cout << graspsgrid[row][col] << "\t";
00858                         }
00859                         cout << "\n";
00860                 }
00861         }
00862 
00863 
00864         if (printgraspseval) cout << "graspseval[row][col]" << "\n\n";
00865         int w1=1, w2=2,w3=3,w4=4,w5=55; //weights: direct grasp neighbors have more impact
00866         int topval_gp = -1000; //top rated value of all grasping points (same rating => take first gp)
00867         int id_row_top = -1, id_col_top = -1;
00868         for (int row = 0; row < HEIGHT; row++){
00869                 for (int col = 0; col < WIDTH; col++){
00870                         if ( graspsgrid[row][col] < 0 ){
00871                                 graspseval[row][col] = 0;
00872                         } else {
00873                                 graspseval[row][col] =
00874                                                 w1*graspsgrid[row-2][col-2]+w2*graspsgrid[row-2][col-1]+w3*graspsgrid[row-2][col]+w2*graspsgrid[row-2][col+1]+w1*graspsgrid[row-2][col+2]+ //row-2
00875                                                 w2*graspsgrid[row-1][col-2]+w3*graspsgrid[row-1][col-1]+w4*graspsgrid[row-1][col]+w3*graspsgrid[row-1][col+1]+w2*graspsgrid[row-1][col+2]+ //row -1
00876                                                 w2*graspsgrid[row][col-4] + w2*graspsgrid[row][col-3] + w3*graspsgrid[row][col-2] + w4*graspsgrid[row][col-1] + w5*graspsgrid[row][col] + w4*graspsgrid[row][col+1] + w3*graspsgrid[row][col+2] + w2*graspsgrid[row][col+3] +w2*graspsgrid[row][col+4] + //row
00877                                                 w2*graspsgrid[row+1][col-2]+w3*graspsgrid[row+1][col-1]+w4*graspsgrid[row+1][col]+w3*graspsgrid[row+1][col+1]+w2*graspsgrid[row+1][col+2]+ //row +1
00878                                                 w1*graspsgrid[row+2][col-2]+w2*graspsgrid[row+2][col-1]+w3*graspsgrid[row+2][col]+w2*graspsgrid[row+2][col+1]+w1*graspsgrid[row+2][col+2]; //row +2
00879 
00880                         }
00881                         if (printgraspseval) cout << graspseval[row][col] << "\t";
00882                         if (graspseval[row][col] > topval_gp){
00883                                 topval_gp = graspseval[row][col];
00884                                 id_row_top = row;
00885                                 id_col_top = col;
00886                                 if (topval_gp > topval_gp_all){
00887                                         cout << "New overall grasp evaluation with value: " << topval_gp << "  in row,col: [" << id_row_top << ", " << id_col_top <<"] and rotation: " << nr_roll*ROLL_STEPS_DEGREE << endl;
00888                                         id_row_top_all = id_row_top;
00889                                         id_col_top_all = id_col_top;
00890                                         nr_roll_top_all = nr_roll;
00891                                         nr_tilt_top_all = tilt;
00892                                         topval_gp_all = topval_gp;
00893                                 }
00894                         }
00895                 }
00896                 if (printgraspseval) cout << "\n";
00897         }
00898 
00899 
00900         //publish grasp grid as ros marker message (visualization_msgs::ArrayMarker) for rviz
00901         marker_cnt = 1;
00902         publish_grasp_grid(nr_roll, tilt, graspseval, 1);
00903 
00904         //choose best gp out of top rated ones (the one in the middle)
00905         int best_topval_row = -1, best_topval_col = -1;
00906         int longest_topval_len = 0;             //indicates the length of longest found sequence of topvals in one row
00907         int cur_topval_len = 0;                 //indicates the length of the current run/sequence
00908         bool count_topval_len = false;
00909         for (int row = 0; row < HEIGHT; row++){
00910                 cur_topval_len = 0;
00911                 count_topval_len = false;
00912                 for (int col = 0; col < WIDTH; col++){
00913                         if (graspseval[row][col] == topval_gp){
00914                                 count_topval_len = true;
00915                                 cur_topval_len++;
00916                                 if (cur_topval_len > longest_topval_len){       //new longest run of topvals
00917                                         longest_topval_len = cur_topval_len;
00918                                         best_topval_row = row;
00919                                         best_topval_col = col - cur_topval_len/2;
00920                                         if (topval_gp == topval_gp_all){
00921                                                 cout << "Better topval gp still with topval: " << topval_gp << "  in row,col: [" << best_topval_row << ", " << best_topval_col <<"] and rotation: " << nr_roll*ROLL_STEPS_DEGREE << endl;
00922                                                 id_row_top_all = best_topval_row;
00923                                                 id_col_top_all = best_topval_col;
00924                                         }
00925                                 }
00926                         }
00927                         else {
00928                                 count_topval_len = false;
00929                                 cur_topval_len = 0;
00930                         }
00931                 }
00932         }
00933 
00934 
00935         //show grasp predicted in mirrored (more intuitive) way
00936         if (printgraspseval) {
00937                 cout << "\n Grasps predicted more intuitively: \n";
00938                 for (int row = HEIGHT-1; row >= 0; row--){
00939                         for (int col = WIDTH-1; col >= 0; col--){
00940                                 cout << setw(3) << setprecision(3) <<graspseval[row][col];
00941                                 if (col > 6 and col < WIDTH-7 )
00942                                         cout << " ";
00943                         }
00944                         if (row > 7 and row < HEIGHT - 7)
00945                                 cout << "\n";
00946                         cout << endl;
00947                 }
00948         }
00949         cout << "\n Best grasp value for currently tested roll: " << topval_gp_all << endl;
00950 
00951         file_in.close();
00952 
00953         if (topval_gp_all > this->topval_gp_overall){   //new best grasp hypothesis!
00954                 cout << "\n New overall (overall!) grasp evaluation with value: " << topval_gp_all << "  in row,col: [" << id_row_top_all << ", " << id_col_top_all <<"] and rotation: " << nr_roll*ROLL_STEPS_DEGREE << endl;
00955                 this->id_row_top_overall = id_row_top_all;
00956                 this->id_col_top_overall = id_col_top_all;
00957                 this->nr_roll_top_overall = nr_roll_top_all;
00958                 this->nr_tilt_top_overall = nr_tilt_top_all;
00959                 this->topval_gp_overall = topval_gp_all;
00960         }
00961 
00962         if (this->return_only_best_gp){
00963                 cout << "\n Grasp detection for one roll finished. Only best grasp is published after full gp calculation! \n";
00964         } else if ((topval_gp_all > this->graspval_th)  ){
00965                 //calculate coordinates for best grasp points with roll in world
00966                 //transfer validation to value between 10 and 99 (if smaler 26, then value is set to 10)
00967                 int scaled_gp_eval = topval_gp_all-20;
00968                 if (scaled_gp_eval < 10) scaled_gp_eval = 10;   //should not be neccessary since graspval_th is high enough
00969                 transform_gp_in_wcs_and_publish(id_row_top_all, id_col_top_all,nr_roll_top_all, nr_tilt_top_all, scaled_gp_eval);
00970         } else { //better grasps would be published but were not found for this loop
00971                 cout << "\n For current roll no grasp point had an evaluation above threshold for publishing! \n";
00972         }
00973 }
00974 
00975 
00976 
00977 
00978 
00979 void CCalc_Grasppoints::publish_grasp_grid(int nr_roll, int tilt, float graspsgrid[][WIDTH], int gripperwidth=1){
00980         visualization_msgs::MarkerArray ma;
00981         visualization_msgs::MarkerArray ma_params;
00982         visualization_msgs::Marker marker;
00983         visualization_msgs::Marker marker_graps_params;
00984         cout << "publish_grasp_grid: input parameter gripperwidth: " << gripperwidth << endl;
00985         float x,y,z;
00986         x = this->graspsearchcenter.x - 0.01*HEIGHT/2/gripperwidth;
00987         y = this->graspsearchcenter.y - 0.01*WIDTH/2;
00988         z = this->graspsearchcenter.z + this->trans_z_after_pc_transform;
00989 
00990 
00991         //publish tf_frame "tf_help" and grasp position (green bars where height is indicating the quality)
00992         for (int row = 0; row <= HEIGHT-1; row++){
00993                 for (int col = 0; col <= WIDTH-1; col++){
00994                         if (this->point_inside_box_grid[nr_roll][tilt][row][col] == true){
00995                                 gp_to_marker(&marker, x+0.01/gripperwidth*row,y+0.01*col,z, graspsgrid[row][col], false, gripperwidth, nr_roll, false, true); // before 0 instead of nr_roll
00996                                 ma.markers.push_back(marker);
00997                         }
00998                 }
00999         }
01000 
01001 
01002         //show grasp params (grasp search field size, gripper closing direction)
01003         for (int i = 1; i <= 3; i++){
01004                 grasp_area_to_marker(&marker_graps_params, this->graspsearchcenter.x,this->graspsearchcenter.y, z, gripperwidth, nr_roll, i /*param_id*/, false /*top_grasp*/ );   //add grasping direction to marker
01005                 ma_params.markers.push_back(marker_graps_params);
01006         }
01007 
01008 
01009         // show (add) grasping direction:
01010         gp_to_marker(&marker, this->graspsearchcenter.x,this->graspsearchcenter.y,z, graspsgrid[0][0], false, gripperwidth, nr_roll, true, true);   //add grasping direction to marker
01011         ma.markers.push_back(marker);   // add gripper opening direction to marker array
01012     //vis_pub.publish( marker );
01013     vis_pub_ma.publish(ma);
01014     vis_pub_ma_params.publish(ma_params);  //publish grasp params as marker array
01015     //ros::spinOnce();
01016 }
01017 
01018 
01019 
01020 void CCalc_Grasppoints::gp_to_marker(visualization_msgs::Marker *marker, float x, float y, float z, float green, bool pubmarker, int gripperwidth=1, int nr_roll=0,bool pub_grip_open_dir=false, bool pub_grid=true){
01021 
01022         // broadcast helper tf-frame for correct visualization of grasping points AND green/red grasping grid
01023         string tmp_tf_help = "tf_help";
01024         static tf::TransformBroadcaster br;
01025 
01026         //calculate rotation for tf-helper coordinate system for visualization
01027         float rot_z, rot_x;
01028 
01029         if (this->approach_vector.y == 0 and this->approach_vector.x == 0){     //if av->y = av->x = 0
01030                 rot_z = 0;
01031                 if (this->approach_vector.z >= 0) {
01032                         rot_x = 0;      //grasp from top
01033                 } else {
01034                         rot_x = PI;     //grasp from upside down (in practice hardly relevant)
01035                 }
01036         } else {        //av->y <> 0 or = av->x <> 0
01037                 rot_z = 90*PI/180.0 - atan2(this->approach_vector.y, this->approach_vector.x);  // av->y, av->x not both 0
01038                 rot_x = 90*PI/180.0 - atan2( this->approach_vector.z, sqrt(this->approach_vector.y*this->approach_vector.y + this->approach_vector.x*this->approach_vector.x) );
01039         }
01040         //cout << "marker: rot_z: " << rot_z << "\nthis->approach_vector.y: " << this->approach_vector.y << "\nthis->approach_vector.x: " << this->approach_vector.x << endl;
01041         //cout << "marker: rot_x: " << rot_x << "\nthis->approach_vector.z: " << this->approach_vector.z << "\nthis->approach_vector.y: " << this->approach_vector.y << endl;
01042 
01043 
01044         //compensate roll transform
01045 
01046         Eigen::Matrix4f mat_sh_to_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from center to origin
01047         Eigen::Matrix4f mat_rot = Eigen::Matrix4f::Identity(); //matrix which rotates pc
01048         Eigen::Matrix4f mat_sh_from_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from origin to center
01049         Eigen::Matrix4f mat_transform = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about box center)
01050         Eigen::Matrix3f mat_rot_for_appr_vec = Eigen::Matrix3f::Identity(); //matrix which makes the rotation for the approximation vector
01051 
01052         Eigen::Matrix4f mat_rot_z_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about z-axis)
01053         Eigen::Matrix4f mat_rot_x_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about x-axis)
01054 
01055 
01056         mat_sh_to_orig(0,3) = -this->graspsearchcenter.x;       //shift x value
01057         mat_sh_to_orig(1,3) = -this->graspsearchcenter.y;       //shift y-value
01058         mat_sh_to_orig(2,3) = -this->graspsearchcenter.z;       //shift z-value
01059         mat_sh_from_orig(0,3) = 0;//this->graspsearchcenter.x;
01060         mat_sh_from_orig(1,3) = 0;//this->graspsearchcenter.y;
01061         mat_sh_from_orig(2,3) = 0/*this->graspsearchcenter.z*/ + this->trans_z_after_pc_transform;      //move pc up to make calculation possible
01062 
01063         //define matrices s.t. transformation matrix can be calculated for point cloud (=> roll and tilt are simulated)
01064 
01065         //define rotation about z-axis (for roll):
01066         float angle = nr_roll*ROLL_STEPS_DEGREE*PI/180;//for roll
01067         mat_rot(0,0) = cos(angle);
01068         mat_rot(0,1) = -sin(angle);
01069         mat_rot(1,0) = sin(angle);
01070         mat_rot(1,1) = cos(angle);
01071 
01072         //define rotation about z-axis:
01073         mat_rot_z_axis(0,0) = cos(rot_z);
01074         mat_rot_z_axis(0,1) = -sin(rot_z);
01075         mat_rot_z_axis(1,0) = sin(rot_z);
01076         mat_rot_z_axis(1,1) = cos(rot_z);
01077 
01078 
01079         //define rotation about x-axis
01080         mat_rot_x_axis(1,1) = cos(rot_x);
01081         mat_rot_x_axis(1,2) = -sin(rot_x);
01082         mat_rot_x_axis(2,1) = sin(rot_x);
01083         mat_rot_x_axis(2,2) = cos(rot_x);
01084 
01085         // transforms in a way that the old coordinate system is transformed to the new one by rotation about first: z-axis, second (new) x-axis
01086         mat_transform = mat_rot*mat_sh_from_orig*mat_rot_x_axis*mat_rot_z_axis*mat_sh_to_orig;     //define transformation matrix mat_transform
01087 
01088 
01089         //stupid data conversion from Eigen::Matrix4f to tf::Transform
01090         Eigen::Matrix4f Tm;
01091         Tm = mat_transform.inverse();
01092         tf::Vector3 origin;
01093         origin.setValue(static_cast<double>(Tm(0,3)),static_cast<double>(Tm(1,3)),static_cast<double>(Tm(2,3)));
01094         tf::Matrix3x3 tf3d;
01095         tf3d.setValue(static_cast<double>(Tm(0,0)), static_cast<double>(Tm(0,1)), static_cast<double>(Tm(0,2)),
01096                 static_cast<double>(Tm(1,0)), static_cast<double>(Tm(1,1)), static_cast<double>(Tm(1,2)),
01097                 static_cast<double>(Tm(2,0)), static_cast<double>(Tm(2,1)), static_cast<double>(Tm(2,2)));
01098 
01099         tf::Quaternion tfqt;
01100         tf3d.getRotation(tfqt);
01101         this->quat_tf_to_tf_help = tfqt;
01102         tf::Transform transform;
01103         transform.setOrigin(origin);
01104         transform.setRotation(tfqt);
01105 
01106         br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), this->base_frame_id, tmp_tf_help));
01107 
01108         if (pub_grid){
01109                 std::stringstream ss;
01110                 ss << tmp_tf_help ;
01111                 (*marker).header.frame_id = ss.str();  //used: "tf_help"
01112                 (*marker).header.stamp = ros::Time();
01113                 (*marker).ns = "my_namespace";
01114                 (*marker).id = marker_cnt++;
01115                 (*marker).type = visualization_msgs::Marker::SPHERE;
01116                 (*marker).action = visualization_msgs::Marker::ADD;
01117                 (*marker).pose.position.x = x-this->graspsearchcenter.x;
01118                 (*marker).pose.position.y = y-this->graspsearchcenter.y;
01119                 (*marker).pose.position.z = z;
01120                 (*marker).pose.orientation.x = 0.0;
01121                 (*marker).pose.orientation.y = 0.0;
01122                 (*marker).pose.orientation.z = 0.0;
01123                 (*marker).pose.orientation.w = 1.0;
01124                 (*marker).scale.x = 0.002;
01125                 (*marker).lifetime = ros::Duration(1);
01126                 (*marker).scale.y = 0.002;
01127                 (*marker).scale.z = 0.002;
01128                 (*marker).color.a = 1.0;
01129                 if (green > 0){
01130                         (*marker).color.r = 0.0;
01131                         (*marker).color.g = 1.0;
01132                         (*marker).scale.x = 0.005;
01133                         (*marker).scale.y = 0.005;
01134                         (*marker).scale.z = 0.001*green;
01135                         (*marker).pose.position.z = z+(*marker).scale.z/2;
01136                 } else {
01137                         (*marker).color.r = 1.0;
01138                         (*marker).color.g = 0.0;
01139                 }
01140                 (*marker).color.b = 0.0;
01141         }
01142 }
01143 
01144 //this function publishes the area where grasps are searched for specific roll for visualization AND gripper closing direction AND best approach vector
01145 void CCalc_Grasppoints::grasp_area_to_marker(visualization_msgs::Marker *marker, float x, float y, float z, int gripperwidth=1, int nr_roll=0, int param_id=1, bool top_grasp=false){
01146 
01147         int fix_marker_id_gripper_dir = 10000;
01148         int fix_marker_id_gripper_appr_dir = 10001;
01149         int fix_marker_id_grasp_search_area = 10002;
01150         int fix_marker_id_grasp_search_area2 = 10003; //inner part where feature vectors are really calculated
01151 
01152         (*marker).header.frame_id = "tf_help";
01153         (*marker).header.stamp = ros::Time::now();//ros::Time();
01154         (*marker).ns = "haf_grasping_parameters";
01155 
01156         //select which marker part is returned
01157         switch(param_id) {
01158             case 1 : {  //publish (outer) grasping search area
01159                                         (*marker).id = fix_marker_id_grasp_search_area;
01160                                         (*marker).type = visualization_msgs::Marker::CUBE;
01161                                         (*marker).action = visualization_msgs::Marker::ADD;
01162                                         (*marker).color.a = 0.05;
01163                                         (*marker).color.r = 0.4;
01164                                         (*marker).color.g = 0.4;
01165                                         (*marker).color.b = 0.4;
01166                                         (*marker).pose.position.x = 0;//-this->graspsearchcenter.x;
01167                                         (*marker).pose.position.y = 0;//-this->graspsearchcenter.y;
01168                                         (*marker).pose.position.z = z;
01169 
01170                                         tf::Vector3 zaxis(0, 0, 1);
01171                                         tf::Quaternion qt_compensate_rot(zaxis, nr_roll*ROLL_STEPS_DEGREE*PI/180);      //compensate for rotation of tf "tf_help"
01172                                         geometry_msgs::Quaternion quat_msg_compensate_rot;
01173                                         tf::quaternionTFToMsg(qt_compensate_rot, quat_msg_compensate_rot);
01174                                         (*marker).pose.orientation = quat_msg_compensate_rot;
01175                                         (*marker).scale.x = 0.01*this->grasp_search_area_size_x_dir/ gripperwidth;
01176                                         (*marker).scale.y = 0.01*this->grasp_search_area_size_y_dir;
01177                                         (*marker).scale.z = 0.001;
01178                                         (*marker).lifetime = ros::Duration();
01179                                         break;
01180                          }
01181 
01182             case 2 : {  //pub search area, pub inner area:
01183                                         (*marker).id = fix_marker_id_grasp_search_area2;
01184                                         (*marker).type = visualization_msgs::Marker::CUBE;
01185                                         (*marker).action = visualization_msgs::Marker::ADD;
01186                                         (*marker).color.a = 0.4;
01187                                         (*marker).color.r = 0.2;
01188                                         (*marker).color.g = 0.2;
01189                                         (*marker).color.b = 0.2;
01190                                         (*marker).pose.position.x = 0;//this->graspsearchcenter.x;
01191                                         (*marker).pose.position.y = 0;//this->graspsearchcenter.y;
01192                                         (*marker).pose.position.z = z;
01193 
01194                                         tf::Vector3 zaxis(0, 0, 1);
01195                                         tf::Quaternion qt_compensate_rot(zaxis, nr_roll*ROLL_STEPS_DEGREE*PI/180);      //compensate for rotation of tf "tf_help"
01196                                         geometry_msgs::Quaternion quat_msg_compensate_rot;
01197                                         tf::quaternionTFToMsg(qt_compensate_rot, quat_msg_compensate_rot);
01198                                         (*marker).pose.orientation = quat_msg_compensate_rot;
01199 
01200                                         (*marker).scale.x = 0.01*(this->grasp_search_area_size_x_dir-14)/ gripperwidth;
01201                                         (*marker).scale.y = 0.01*(this->grasp_search_area_size_y_dir-14);
01202                                         (*marker).scale.z = 0.001;
01203                                         (*marker).lifetime = ros::Duration();
01204                                         break;
01205                          }
01206             case 3 : {
01207                                 (*marker).id = fix_marker_id_gripper_dir;
01208                                 (*marker).type = visualization_msgs::Marker::CUBE;
01209                                 (*marker).action = visualization_msgs::Marker::ADD;
01210                                 (*marker).color.a = 0.8;
01211                                 (*marker).color.r = 1.0;
01212                                 (*marker).color.g = 0.0;
01213                                 (*marker).color.b = 0.0;
01214                                 if (top_grasp){
01215                                         (*marker).pose.position.x = x;
01216                                         (*marker).pose.position.y = y;
01217                                         (*marker).pose.position.z = z;
01218                                         (*marker).scale.x = 0.5 * 1 / gripperwidth;
01219                                         (*marker).scale.y = 0.002;
01220                                         (*marker).scale.z = 0.002;
01221 
01222                                         //new transform for tf_helper
01223                                                 visualization_msgs::Marker markerdummy;
01224                                         gp_to_marker(&markerdummy, this->graspsearchcenter.x,this->graspsearchcenter.y,this->graspsearchcenter.z, 1, false, 1, nr_roll, false, false/*pub_grid*/);   //add grasping direction to marker
01225                                 } else {
01226                                         (*marker).pose.position.x = 0;//this->graspsearchcenter.x;
01227                                         (*marker).pose.position.y = 0;//this->graspsearchcenter.y;
01228                                         (*marker).pose.position.z = z;
01229                                         (*marker).scale.x = 0.5 * 1 / gripperwidth;
01230                                         (*marker).scale.y = 0.002;
01231                                         (*marker).scale.z = 0.002;
01232                                         (*marker).lifetime = ros::Duration(3);
01233                                         tf::Vector3 marker_gripper_open_dir_axis(0, 0, 1);
01234                                         tf::Quaternion qt_gripper_open_dir(marker_gripper_open_dir_axis, 0*(-nr_roll)*ROLL_STEPS_DEGREE*PI/180);
01235                                         geometry_msgs::Quaternion quat_msg_gripper_open_dir;
01236                                         tf::quaternionTFToMsg(qt_gripper_open_dir, quat_msg_gripper_open_dir);
01237                                         (*marker).pose.orientation = quat_msg_gripper_open_dir;
01238                                 }
01239                                 (*marker).lifetime = ros::Duration();
01240                                 break;
01241                          }
01242             case 4 : {  // draw grasp approach direction (black arrow)
01243                                         (*marker).header.frame_id = this->base_frame_id;
01244                                         (*marker).id = fix_marker_id_gripper_appr_dir;
01245                                         (*marker).type = visualization_msgs::Marker::ARROW;
01246                                         (*marker).action = visualization_msgs::Marker::ADD;
01247                                         (*marker).color.a = 0.8;
01248                                         (*marker).color.r = 0.0;
01249                                         (*marker).color.g = 0.0;
01250                                         (*marker).color.b = 0.0;
01251                                         float markerlength = 0.1;
01252                                         (*marker).pose.position.x = x + markerlength*this->approach_vector.x;
01253                                         (*marker).pose.position.y = y + markerlength*this->approach_vector.y;
01254                                         (*marker).pose.position.z = z + markerlength*this->approach_vector.z;
01255                                         (*marker).scale.x = markerlength;
01256                                         (*marker).scale.y = 0.003;
01257                                         (*marker).scale.z = 0.003;
01258                                         (*marker).lifetime = ros::Duration(3);
01259                                         tf::Vector3 marker_axis(0, 1, 0);
01260                                         tf::Quaternion qt(marker_axis, PI/2);
01261                                         geometry_msgs::Quaternion quat_msg;
01262                                         tf::quaternionTFToMsg( (this->quat_tf_to_tf_help)*qt, quat_msg);
01263                                         (*marker).pose.orientation = quat_msg;
01264                                         (*marker).lifetime = ros::Duration();
01265                                         break;
01266                          }
01267             default: cout << "CCalc_Grasppoints::grasp_area_to_marker: WRONG INPUT FOR param_id " << endl;
01268             break;
01269         }
01270 }
01271 
01272 //input: best row and col in virtual rotated box and rotation angle
01273 //output: calculates grasp point in world coordinate system and publishes it
01274 void CCalc_Grasppoints::transform_gp_in_wcs_and_publish(int id_row_top_all, int id_col_top_all,int nr_roll_top_all, int nr_tilt_top_all, int scaled_gp_eval){
01275         cout << "\n ===> transform_gp_in_wcs_and_publish(): TRANSFORM FOUND GRASP" << endl;
01276         Eigen::Matrix4f mat_sh_to_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from center to origin
01277         Eigen::Matrix4f mat_rot_z_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about z-axis)
01278         Eigen::Matrix4f mat_rot_x_axis = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about x-axis)
01279         Eigen::Matrix4f mat_sh_from_orig = Eigen::Matrix4f::Identity(); //matrix which defines shift of point cloud from origin to center
01280         Eigen::Matrix4f mat_rot = Eigen::Matrix4f::Identity(); //matrix which rotates pc
01281         Eigen::Matrix4f mat_scale_x_dir = Eigen::Matrix4f::Identity();//NEW grippertest: scale point cloud
01282 
01283         Eigen::Matrix4f mat_transform = Eigen::Matrix4f::Identity(); //matrix for transformation of pointcloud (rotation about box center)
01284 
01285         Eigen::Matrix3f mat_rot_for_appr_vec = Eigen::Matrix3f::Identity(); //matrix which makes the rotation for the approximation vector
01286 
01287         float rot_about_z;              //rotation needed about z-axis to align y-axis (old cs) with orthoganal projection of new z-axis on x-y-plane (rad)
01288         float rot_about_x = 0;  //rotation needed to align z axis old with z-axis new after rot_about_z was executed (this way old x-axis keeps direction in x-y-plane) (rad)
01289 
01290         mat_scale_x_dir(0,0) = this->gripper_opening_width;     //NEW grippertest: scale point cloud in x-axis direction
01291 
01292         mat_sh_to_orig(0,3) = -this->graspsearchcenter.x;       //shift x value
01293         mat_sh_to_orig(1,3) = -this->graspsearchcenter.y;       //shift y-value
01294         mat_sh_to_orig(2,3) = -this->graspsearchcenter.z;       //shift z-value
01295 
01296         mat_sh_from_orig(0,3) = 0;//this->graspsearchcenter.x;
01297         mat_sh_from_orig(1,3) = 0;//this->graspsearchcenter.y;
01298         mat_sh_from_orig(2,3) = 0/*this->graspsearchcenter.z*/ + this->trans_z_after_pc_transform;      //move pc up to make calculation possible
01299 
01300         if (this->approach_vector.y == 0 and this->approach_vector.x == 0){     //if this->approach_vector.y = this->approach_vector.x = 0
01301                 rot_about_z = 0;
01302                 if (this->approach_vector.z >= 0) {
01303                         rot_about_x = 0;        //grasp from top
01304                 } else {
01305                         rot_about_x = PI;       //grasp from upside down (in practice hardly relevant)
01306                 }
01307         } else {        //av->y <> 0 or = av->x <> 0
01308                 rot_about_z = 90*PI/180.0 - atan2(this->approach_vector.y, this->approach_vector.x);    // av->y, av->x not both 0
01309                 rot_about_x = 90*PI/180.0 - atan2( this->approach_vector.z, sqrt(this->approach_vector.y*this->approach_vector.y + this->approach_vector.x*this->approach_vector.x) );
01310         }
01311 
01312         //define matrices s.t. transformation matrix can be calculated for point cloud (=> roll and tilt are simulated)
01313 
01314         //define rotation about z-axis (for top roll):
01315         float angle = nr_roll_top_all*ROLL_STEPS_DEGREE*PI/180;//for top roll overall
01316         mat_rot(0,0) = cos(angle);
01317         mat_rot(0,1) = -sin(angle);
01318         mat_rot(1,0) = sin(angle);
01319         mat_rot(1,1) = cos(angle);
01320 
01321         //define rotation about z-axis:
01322         mat_rot_z_axis(0,0) = cos(rot_about_z);
01323         mat_rot_z_axis(0,1) = -sin(rot_about_z);
01324         mat_rot_z_axis(1,0) = sin(rot_about_z);
01325         mat_rot_z_axis(1,1) = cos(rot_about_z);
01326 
01327         //define rotation about x-axis
01328         mat_rot_x_axis(1,1) = cos(rot_about_x);
01329         mat_rot_x_axis(1,2) = -sin(rot_about_x);
01330         mat_rot_x_axis(2,1) = sin(rot_about_x);
01331         mat_rot_x_axis(2,2) = cos(rot_about_x);
01332 
01333         // transforms in a way that the old coordinate system is transformed to the new one by rotation about first: z-axis, second (new) x-axis
01334         mat_transform = mat_scale_x_dir * mat_rot * mat_sh_from_orig * mat_rot_x_axis * mat_rot_z_axis * mat_sh_to_orig;     //define transformation matrix mat_transform
01335 
01336 
01337         cout << " ---> id_row_top_all: " << id_row_top_all << "\t" << "id_col_top_all: " << id_col_top_all << "\t and rotation: " << nr_roll_top_all*ROLL_STEPS_DEGREE << "  tilt_top: " << nr_tilt_top_all <<endl;
01338         //publish best grasp point (with roll):
01339         float x_gp_roll = /*this->graspsearchcenter.x*/ - ((float)(HEIGHT/2 - id_row_top_all))/100;     //x-coordinate of the graspcenterpoint if the box would be rotated by nr_roll_top_all*ROLL_STEPS_DEGREE degree
01340         float y_gp_roll = /*this->graspsearchcenter.y*/ - ((float)(WIDTH/2  - id_col_top_all))/100;  //y-coordinate of the graspcenterpoint if the box would be rotated by nr_roll_top_all*ROLL_STEPS_DEGREE degree
01341         //estimate z-value for grasping (max height in area around grasp center - 0 cm
01342         float h_locmax_roll = -10;
01343         for (int row_z = -4; row_z < 5; row_z++){       //row_z defines which rows are taken into account for the calc. of max z
01344                 for (int col_z = -4; col_z < 4; col_z++){
01345                         //cout << "this->heightsgridroll[" << nr_roll_top_all << "][" << nr_tilt_top_all << "][" << id_row_top_all+row_z << "][" << id_col_top_all+col_z << "]: " << this->heightsgridroll[nr_roll_top_all][nr_tilt_top_all][id_row_top_all+row_z][id_col_top_all+col_z] << endl;
01346                         if (id_row_top_all+row_z >= 0 and id_col_top_all+col_z>=0 and h_locmax_roll < this->heightsgridroll[nr_roll_top_all][nr_tilt_top_all][id_row_top_all+row_z][id_col_top_all+col_z]){
01347                                 h_locmax_roll = this->heightsgridroll[nr_roll_top_all][nr_tilt_top_all][id_row_top_all+row_z][id_col_top_all+col_z];
01348                                 //cout << "this->heightsgridroll[" << nr_roll_top_all <<"][" << nr_tilt_top_all<<"][" <<id_row_top_all+row_z<<"][" << id_col_top_all+col_z<<"]: " << this->heightsgridroll[nr_roll_top_all][nr_tilt_top_all][id_row_top_all+row_z][id_col_top_all+col_z] << endl;
01349                         }
01350                 }
01351         }
01352 
01353 
01354         h_locmax_roll -= 0.01;  //reduce local maximal height by a threshold (2cm currently) => fine calculation should be done in simulation anyway
01355         float z_gp_roll = h_locmax_roll;
01356         cout << " ---> x_roll: "<< x_gp_roll << "\t y_roll: " << y_gp_roll << "\t z_gp_roll: " << z_gp_roll << endl;
01357 
01358         //make rotation
01359         //pcl::transformPointCloud(pcl_cloud_in, pcl_cloud_in_roll, mat_transform);
01360     float x_gp_dis = 0.03; //distance from grasp center to "real" grasp point
01361 
01362         Eigen::Vector4f gp1(x_gp_roll-x_gp_dis, y_gp_roll,z_gp_roll,1.0);
01363         Eigen::Vector4f gp2(x_gp_roll+x_gp_dis, y_gp_roll,z_gp_roll,1.0);
01364         Eigen::Vector4f gp1_wcs, gp2_wcs;
01365         Eigen::Vector3f appr_vec(0,0,1);
01366 
01367         gp1_wcs = mat_transform.inverse()*gp1;
01368         gp2_wcs = mat_transform.inverse()*gp2;
01369 
01370         mat_rot_for_appr_vec << this->av_trans_mat(0,0),this->av_trans_mat(1,0),this->av_trans_mat(2,0),
01371                                                         this->av_trans_mat(0,1),this->av_trans_mat(1,1),this->av_trans_mat(2,1),
01372                                                         this->av_trans_mat(0,2),this->av_trans_mat(1,2),this->av_trans_mat(2,2);
01373 
01374         appr_vec = mat_rot_for_appr_vec*appr_vec;
01375 
01376         cout << " ---> GP_1: x_roll_wcs: "<< gp1_wcs[0] << "\t y_roll_wcs: " << gp1_wcs[1] << "\t z_roll_wcs: " << gp1_wcs[2] << endl;
01377         cout << " ---> GP_2: x_roll_wcs: "<< gp2_wcs[0] << "\t y_roll_wcs: " << gp2_wcs[1] << "\t z_roll_wcs: " << gp2_wcs[2] << endl;
01378 
01379 
01380         //Publish grasp points
01381         std_msgs::String msgStrPoints;
01382         std::stringstream ss;
01383 
01384     ss << scaled_gp_eval << " " << gp1_wcs[0] <<" "<< gp1_wcs[1] << " "<< gp1_wcs[2] << " "<< gp2_wcs[0] << " " << gp2_wcs[1] << " " << gp2_wcs[2] << " "<< appr_vec(0) << " "<< appr_vec(1) << " "<< appr_vec(2) << " " << (gp1_wcs[0]+gp2_wcs[0])/2.0 <<" " << (gp1_wcs[1]+gp2_wcs[1])/2.0 <<" " << (gp1_wcs[2]+gp2_wcs[2])/2.0 <<" " << nr_roll_top_all*ROLL_STEPS_DEGREE;
01385         msgStrPoints.data = ss.str();
01386         this->gp_result.header.stamp = ros::Time::now();
01387         this->gp_result.header.frame_id = this->base_frame_id;
01388         this->gp_result.eval = scaled_gp_eval;
01389         this->gp_result.graspPoint1.x = gp1_wcs[0];
01390         this->gp_result.graspPoint1.y = gp1_wcs[1];
01391         this->gp_result.graspPoint1.z = gp1_wcs[2];
01392         this->gp_result.graspPoint2.x = gp2_wcs[0];
01393         this->gp_result.graspPoint2.y = gp2_wcs[1];
01394         this->gp_result.graspPoint2.z = gp2_wcs[2];
01395         this->gp_result.averagedGraspPoint.x = (gp1_wcs[0]+gp2_wcs[0])/2.0;
01396         this->gp_result.averagedGraspPoint.y = (gp1_wcs[1]+gp2_wcs[1])/2.0;
01397         this->gp_result.averagedGraspPoint.z = (gp1_wcs[2]+gp2_wcs[2])/2.0;
01398         this->gp_result.approachVector.x = appr_vec(0);
01399         this->gp_result.approachVector.y = appr_vec(1);
01400         this->gp_result.approachVector.z = appr_vec(2);
01401         this->gp_result.roll = (nr_roll_top_all * ROLL_STEPS_DEGREE * PI) / 180; // degree->radians
01402 
01403         //publish best grasp as rviz visualization_msgs::Marker
01404         visualization_msgs::Marker marker_best_params;
01405         visualization_msgs::MarkerArray ma_best_params;
01406         //show grasp params (grasp search field size, gripper closing direction)
01407         for (int i = 3; i <= 3; i++){   //closing direction (red line) for best grasp
01408                 grasp_area_to_marker(&marker_best_params, (gp1[0]+gp2[0])/2,(gp1[1]+gp2[1])/2,(gp1[2]+gp2[2])/2, this->gripper_opening_width /*gripperwidth*/, nr_roll_top_all, i /*param_id*/, true /*top_grasp*/ );   //add best grasping direction to marker
01409                 ma_best_params.markers.push_back(marker_best_params);
01410         }
01411         for (int i = 4; i <= 4; i++){   //approach vector (black arrow) for best grasp
01412                 grasp_area_to_marker(&marker_best_params, (gp1_wcs[0]+gp2_wcs[0])/2,(gp1_wcs[1]+gp2_wcs[1])/2,(gp1_wcs[2]+gp2_wcs[2])/2, this->gripper_opening_width /*gripperwidth*/, nr_roll_top_all, i /*param_id*/, true /*top_grasp*/ );   //add best grasping direction to marker
01413                 ma_best_params.markers.push_back(marker_best_params);
01414         }
01415         vis_pub_ma_params.publish(ma_best_params);      //publish best grasp parameter
01416 
01417         //pubGraspPoints.publish(msgStrPoints);
01418         cout << " ---> Scaled GP Evaluation (-20-99) [-20 <=> no GP found]: " << scaled_gp_eval << endl;
01419         pubGraspPointsEval.publish(msgStrPoints);
01420 
01421 }
01422 
01423 
01424 
01425 int main (int argc, char** argv)
01426 {
01427   ROS_INFO("ROS NODE calc_grasppoints_svm_action_server (from package haf_grasping) started");
01428   ros::init(argc, argv, "calc_grasppoints_svm_action_server");
01429   CCalc_Grasppoints * calc_gps = new CCalc_Grasppoints(ros::this_node::getName());
01430   ros::spin();
01431   return (0);
01432 }
01433 


haf_grasping
Author(s): David Fischinger
autogenerated on Wed Jan 11 2017 03:48:49