handle.cpp
Go to the documentation of this file.
00001 //This programe gets the pose of a marker above a door handle
00002 //and uses it to extract the points that belong to the handle geometrically
00003 //The assumptions about the position of the door handle are stated in
00004 //the setFilterLimits calls
00005 #include "ros/ros.h"
00006 #include <sensor_msgs/PointCloud2.h>
00007 #include <geometry_msgs/PoseStamped.h> 
00008 #include <geometry_msgs/Pose.h> 
00009 #include <tf/transform_datatypes.h>
00010 #include <pcl_ros/transforms.h>
00011 #include <pcl/ros/conversions.h>
00012 #include <sensor_msgs/point_cloud_conversion.h>
00013 
00014 #include "tools.h"
00015 
00016 // head control
00017 //#include <pr2_controllers_msgs/PointHeadAction.h>
00018 
00019 #include <iostream>
00020 
00021 #include <tf/transform_listener.h>
00022 
00023 //tf::Transform checkerboardPose;
00024 tf::TransformListener* tflistener;
00025 ros::Publisher handle_pub, pc_pub, vis_pub, pregrasp_pub, postgrasp_pub, grasp_pub;
00026 std::string global_checkerboard_frame;
00027 std::string global_torso_frame;
00028 
00029 
00030 void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg)
00031 {
00032   // tf stuff
00033   tf::StampedTransform door_to_torso;
00034   if(tflistener->waitForTransform(global_torso_frame, msg->header.frame_id, msg->header.stamp, ros::Duration(0.5))){
00035     tflistener->lookupTransform(global_torso_frame,  msg->header.frame_id, msg->header.stamp, door_to_torso);
00036   } else {
00037     ROS_WARN("No tranform from %s to %s available", msg->header.frame_id.c_str(), global_torso_frame.c_str());
00038     return;
00039   }
00040   tf::Stamped<tf::Pose> handle_pose_in_door_frame; 
00041   tf::poseStampedMsgToTF(*msg, handle_pose_in_door_frame);
00043   tf::Transform handle_pose_in_torso_frame = door_to_torso * handle_pose_in_door_frame; 
00044   tf::Transform grasp = handle_pose_in_torso_frame * tf::Transform(tf::Quaternion(0,0,0,1), tf::Vector3(0.05,0,0)); 
00045 
00046   //Grasp: Same as msg
00047   tf::Stamped<tf::Pose> graspTF(grasp, msg->header.stamp,global_torso_frame); 
00048   geometry_msgs::PoseStamped graspMsg;
00049   tf::poseStampedTFToMsg(graspTF, graspMsg);
00050 
00051   //Pregrasp: 10cm in front of grasp
00052 
00053   tf::Transform pregrasp(handle_pose_in_torso_frame);  
00054   pregrasp.getOrigin().setX(pregrasp.getOrigin().getX() - 0.08);
00055   tf::Stamped<tf::Pose> pregraspTF(pregrasp, msg->header.stamp,global_torso_frame); 
00056   geometry_msgs::PoseStamped pregraspMsg;
00057   tf::poseStampedTFToMsg(pregraspTF, pregraspMsg);
00058   
00059   //Postgrasp rotate Z downwards by +-45° around X (depending on which side it is)
00060   tf::Vector3 handle_tip_in_handle_frame(0,0,1); // Z Axis always points to door hinge along handle
00061   tf::Vector3 handle_tip_in_torso_frame = door_to_torso * handle_pose_in_door_frame * handle_tip_in_handle_frame - handle_pose_in_torso_frame.getOrigin();
00062 
00063   tf::Vector3 rotation_axis = handle_tip_in_torso_frame.cross(tf::Vector3(0,0,1));
00064   rotation_axis.normalize();
00065   ROS_DEBUG("rotation_axis (in torso frame) xyz= %f %f %f", rotation_axis.getX(), rotation_axis.getY(), rotation_axis.getY());
00066   
00067   tf::Quaternion grasp_to_postgrasp_rot(rotation_axis, -60.0/180.0*3.1415927);
00068   tf::Transform grasp_to_postgrasp(grasp_to_postgrasp_rot, tf::Vector3(0.05,0,0));//open door slightly so it doesn't fall back to latched
00069   tf::Transform postgrasp = grasp * grasp_to_postgrasp;
00070 
00071   //Grasp: Same as msg
00072   tf::Stamped<tf::Pose> postgraspTF(postgrasp, msg->header.stamp,global_torso_frame); 
00073   geometry_msgs::PoseStamped postgraspMsg;
00074   tf::poseStampedTFToMsg(postgraspTF, postgraspMsg);
00075 
00076   if (pregrasp_pub.getNumSubscribers() > 0){
00077     pregrasp_pub.publish(pregraspMsg);
00078   }
00079   if (grasp_pub.getNumSubscribers() > 0){
00080     grasp_pub.publish(graspMsg);
00081   }
00082   if (postgrasp_pub.getNumSubscribers() > 0){
00083     postgrasp_pub.publish(postgraspMsg);
00084   }
00085 
00086 }
00087 
00088 void pointCloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00089 {
00090   ROS_DEBUG_THROTTLE(5, "Received a point cloud: [%d, %d, %d] (This message is only printed every 5sec)", msg->width, msg->height, (int)msg->data.size());
00091 
00092   // tf stuff
00093   tf::StampedTransform torso_transform;
00094   tf::StampedTransform optical_transform;
00095   if(tflistener->waitForTransform(global_torso_frame, global_checkerboard_frame,msg->header.stamp, ros::Duration(0.5))){
00096     tflistener->lookupTransform(global_torso_frame, global_checkerboard_frame, msg->header.stamp, torso_transform);
00097     ROS_DEBUG("Checkerboard xyz= %f %f %f", torso_transform.getOrigin().getX(), torso_transform.getOrigin().getY(), torso_transform.getOrigin().getY());
00098   } else {
00099     ROS_INFO_THROTTLE(30, "No tranform from %s to %s available, probably no checkerboard in sight (or cb-detector not started).", global_torso_frame.c_str(), global_checkerboard_frame.c_str());
00100     return;
00101   }
00102   if(tflistener->waitForTransform(global_checkerboard_frame, msg->header.frame_id, msg->header.stamp, ros::Duration(5.0/30.0))){
00103     tflistener->lookupTransform(global_checkerboard_frame, msg->header.frame_id,  msg->header.stamp, optical_transform);
00104   } else {
00105     ROS_WARN("No tranform from %s to %s available", global_checkerboard_frame.c_str(), msg->header.frame_id.c_str());
00106     return;
00107   }
00108   // end tf stuff
00109 
00110   //Filtering the cloud in checkerboard Frame ##################################
00111   myCloudType::Ptr pc (new myCloudType );
00112   //TODO check whether checkerboardPose is identity and return if so
00113   pcl::fromROSMsg(*msg, *pc);
00114   pcl_ros::transformPointCloud(*pc, *pc, optical_transform);//pc is now in checkerboard frame
00115 
00116   //This filter settings should remove most points in and behind the door plane
00117   float xmin = -0.10,xmax = 0.25,ymin = 0.00,ymax = 0.32,zmin = -.2 ,zmax = -.03;
00118   if (vis_pub.getNumSubscribers() > 0)
00119     vis_pub.publish(visualize_filter_box(xmin,xmax,ymin,ymax,zmin,zmax, pc->header));
00120   box_filter(pc, xmin,xmax,ymin,ymax,zmin,zmax);
00121 
00122   if(pc->points.size() == 0){
00123     ROS_INFO_THROTTLE(5, "Empty Result Set");
00124     ros::Duration(0.5).sleep(); // sleep for half a second
00125     return;
00126   }
00127 
00128   pcl_ros::transformPointCloud(*pc, *pc, torso_transform);//pc is now in torso_lift_link
00129   pc->header.frame_id =global_torso_frame;
00130   sensor_msgs::PointCloud2 outmsg;
00131   pcl::toROSMsg(*pc,outmsg);
00132   if (pc_pub.getNumSubscribers() > 0)
00133     pc_pub.publish(outmsg);
00134 
00135   //Computation of the Desired Gripper Transformations #########################
00136   Eigen::Vector3f mean, principalAxis;
00137   if(!computeMainAxis(*pc, mean, principalAxis, 20.0)) return; //main axis eval is 100 times next eval
00138   //std::cout << "\nReturned principalAxis:\n" << principalAxis << "\nReturned Mean:\n" << mean << std::endl;
00139   if (!((principalAxis.array() == principalAxis.array())).all() || //checking for nan
00140       !((mean.array() == mean.array())).all()) ROS_WARN("No valid axis for grasp");
00141   ROS_DEBUG("Mean xyz= %f %f %f", mean(0), mean(1), mean(2));
00142 
00143   Eigen::Matrix4f torso_trans_mat;
00144   pcl_ros::transformAsMatrix(torso_transform, torso_trans_mat);
00145   Eigen::Matrix3f torso_rot_mat = torso_trans_mat.block<3,3>(0,0);
00146   //std::cout << std::endl << torso_rot_mat << std::endl;
00147 
00148   //DOOR NoRMAL GOES TOWARDS ROBOT
00149   Eigen::Vector3f door_normal(0,0,mean(2) - torso_transform.getOrigin().getZ()); //in checkerboard coord frame
00150   door_normal.normalize();
00151   door_normal = torso_rot_mat * door_normal; //door normal in torso coordinate frame
00152   Eigen::Vector3f handle_axis(principalAxis); //in torso_lift_link. Shall be gripper z axis
00153   Eigen::Vector3f y_axis  = handle_axis.cross(door_normal); //don't care about this, depends on the other two
00154   y_axis.normalize();
00155   door_normal  = y_axis.cross(handle_axis); //adapt door normal to be orthogonal to handle axis 
00156   ROS_DEBUG_STREAM("Door Normal:\n" << door_normal);
00157   ROS_DEBUG_STREAM("Handle Axis:\n" << handle_axis);
00158   ROS_DEBUG_STREAM("Third Axis:\n"  << y_axis);
00159   Eigen::Matrix3f grm;//gripper_rot_mat;
00160   grm << -door_normal, -y_axis, handle_axis;
00161   ROS_DEBUG_STREAM("Desired Gripper Coord Frame\n: " << grm);
00162 
00163   //gripper z should be aligned with the handle, gripper x with the door normal
00164 
00165   //This is the transpose (and since orthonormal, the inverse) of the desired gripper coord frame
00166   tf::Matrix3x3 toGripperTargetCoordFrame(grm(0,0), grm(0,1), grm(0,2), 
00167                                         grm(1,0), grm(1,1), grm(1,2), 
00168                                         grm(2,0), grm(2,1), grm(2,2)) ;
00169 
00170   tf::Quaternion gripperRotation; 
00171   toGripperTargetCoordFrame.getRotation(gripperRotation);
00172 
00173   //TODO: third axis and transform-rotation from that axis
00174   geometry_msgs::PoseStamped handle_pose = getPoseStamped(mean, gripperRotation); 
00175   if (handle_pub.getNumSubscribers() > 0)
00176     handle_pub.publish(handle_pose);
00177 
00178   //tf::Vector3 gripperPosition(mean(0), mean(1), mean(2));
00179   //tf::Transform grasp_tf(gripperRotation, gripperRotation);
00180   //tf::Stamped<tf::Pose> grasp_tf_pose(grasp_tf);
00181   //geometry_msgs::PoseStamped msg;
00182   //tf::poseStampedTFToMsg      (grasp_tf_pose, msg);
00183 
00184 //geometry_msgs::Pose makePose(tf::Transform t){
00185   geometry_msgs::PoseStamped pregrasp, grasp, postgrasp;
00186   //this should be 10 cm along the door normal towards the robot
00187   pregrasp = getPoseStamped(mean+0.16*door_normal, gripperRotation);
00188   pregrasp.header.stamp = msg->header.stamp;
00189   if (pregrasp_pub.getNumSubscribers() > 0)
00190     pregrasp_pub.publish(pregrasp);
00191 
00192   grasp = getPoseStamped(mean-(0.03*door_normal), gripperRotation);
00193   grasp.header.stamp = msg->header.stamp;
00194   if (grasp_pub.getNumSubscribers() > 0)
00195     grasp_pub.publish(grasp);
00196 
00197   ROS_DEBUG_COND(mean(1) > torso_transform.getOrigin().getY(), "Mean left of checkerboard");
00198   double rot_dir = -1.0;//mean(1) > torso_transform.getOrigin().getY() ? -1.0 : 1.0 ; //switch rotation depending on the side of the handle axis
00199   tf::Quaternion handleRotation(tf::Vector3(door_normal(0),door_normal(1),door_normal(2)), rot_dir/4.0*M_PI );
00200   gripperRotation *= handleRotation;
00201   postgrasp.header.stamp = msg->header.stamp;
00202   postgrasp.header.frame_id = global_torso_frame;
00203   postgrasp.pose.position.x = mean(0)- 0.05 * door_normal(0) + 0.05;
00204   postgrasp.pose.position.y = mean(1)- 0.05 * door_normal(1) + rot_dir * 0.02 * principalAxis(1);
00205   postgrasp.pose.position.z = mean(2)- 0.05 * door_normal(2) - 0.08 ; //torso_lift_link z is always up
00206   postgrasp.pose.orientation.w = gripperRotation.getW();
00207   postgrasp.pose.orientation.x = gripperRotation.getX();
00208   postgrasp.pose.orientation.y = gripperRotation.getY();
00209   postgrasp.pose.orientation.z = gripperRotation.getZ();
00210   if (postgrasp_pub.getNumSubscribers() > 0)
00211     postgrasp_pub.publish(postgrasp);
00212   ROS_INFO_THROTTLE(5, "Published all grasping poses");
00213   //grasp_handle(pregrasp.pose, grasp.pose, postgrasp.pose); 
00214 }
00215 
00216 /*
00217 void poseCallback(const geometry_msgs::PoseStamped::ConstPtr& msg){
00218   tf::Stamped<tf::Pose> bt;
00219   poseStampedMsgToTF(*msg, bt);
00220   checkerboardPose = bt;
00221   //make sure y axis goes upwards
00222   if(checkerboardPose.getOrigin().getZ() < 0.0){
00223     checkerboardPose *= tf::Transform(tf::Quaternion(tf::Vector3(0,1,0), M_PI));
00224   }
00225 }
00226 */
00227 int main(int argc, char **argv)
00228 {
00229   ros::init(argc, argv, "handle_grasp_computation");
00230   ros::NodeHandle n;
00231   tflistener = new tf::TransformListener; 
00232   global_checkerboard_frame = "/checkerboard_0";
00233   global_torso_frame = "/torso_lift_link";
00234 
00235   pc_pub = n.advertise<sensor_msgs::PointCloud2>("handle_segment", 1);
00236   vis_pub = n.advertise<visualization_msgs::Marker>( "/visualization_marker", 2 );
00237   pregrasp_pub = n.advertise<geometry_msgs::PoseStamped>( "pregrasp", 3 );
00238   grasp_pub = n.advertise<geometry_msgs::PoseStamped>( "grasp", 3 );
00239   postgrasp_pub = n.advertise<geometry_msgs::PoseStamped>( "postgrasp", 3 );
00240   handle_pub = n.advertise<geometry_msgs::PoseStamped>( "handle", 3 );
00241 
00242 //  ros::Subscriber subPS = n.subscribe("/pose0", 10, poseCallback); //this comes from the checkerboard_detector2
00243   //Subscribe to the point cloud containing the handle and extract 
00244   ros::Subscriber subPC = n.subscribe("cloud_in", 10, pointCloudCallback);
00245   ros::Subscriber subPose = n.subscribe("door_handle", 10, poseCallback);
00246   ROS_INFO("Handle extractor started");
00247   //Multithreaded spinner because waitfortransform in one callback may blocks the other callback otherwise
00248   ros::MultiThreadedSpinner spinner(2); // Use 2 threads
00249   spinner.spin(); // spin() will not return until the node has been shutdown
00250 
00251 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


door_manipulation_tools
Author(s): Felix Endres
autogenerated on Wed Dec 26 2012 16:02:19