or_grasp_generation.py
Go to the documentation of this file.
00001 """Generates a database of grasps
00002 """
00003 #libs and modules
00004 from openravepy import *
00005 from itertools import groupby
00006 import numpy, time, analyzegrasp3d, scipy
00007 import tf, csv, os
00008 import operator, random
00009 
00010 #ROS
00011 import rospy, roslib
00012 from moveit_msgs.msg import * 
00013 from geometry_msgs.msg import * 
00014 from trajectory_msgs.msg import *
00015 
00016 
00017 class ORGraspGeneration:
00018         def __init__(self, viewer=False):
00019                 self.env = None
00020                 self.target = None
00021                 self.grasp_list = None
00022         
00023         def setup_environment(self, object_name, viewer=False):
00024                 if self.env == None:
00025                         self.env = Environment()
00026                         self.env.Load(roslib.packages.get_pkg_dir('cob_grasp_generation')+'/files/env/target_scene.env.xml')
00027                 
00028                 if viewer:
00029                         if self.env.GetViewer() == None:
00030                                 self.env.SetViewer('qtcoin')
00031                         else:
00032                                 print "Viewer already loaded"
00033                 else:
00034                         print "Not using a viewer for OpenRAVE"
00035                 
00036                 if self.target == None:
00037                         self.target = self.env.ReadKinBodyURI(roslib.packages.get_pkg_dir('cob_pick_place_action')+'/files/meshes/'+str(object_name)+'.stl')
00038                         self.env.Add(self.target,True)
00039                 
00040                 if self.target.GetName() != object_name:
00041                         print "Changing the target object"
00042                         self.env.Remove(self.target)
00043                         self.target = self.env.ReadKinBodyURI(roslib.packages.get_pkg_dir('cob_pick_place_action')+'/files/meshes/'+str(object_name)+'.stl')
00044                         self.env.Add(self.target,True)
00045                 
00046                 print "Environment set up!"
00047         
00048         
00049         def generate_grasps(self, object_name, replan=False):
00050                 #robot
00051                 robot = self.env.GetRobots()[0]
00052                 manip = robot.GetManipulator('arm')
00053                 gmodel = databases.grasping.GraspingModel(robot,self.target)
00054 
00055                 #TCP - transformed to hand wrist
00056                 tool_trafo = manip.GetLocalToolTransform()
00057                 tool_trafo[2,3] = 0.0
00058                 manip.SetLocalToolTransform(tool_trafo)
00059 
00060 
00061                 ### Options for GraspGeneration
00062                 #~ friction = None
00063                 #~ preshapes = None
00064                 #~ manipulatordirections = None
00065                 #~ approachrays = None
00066                 #~ standoffs = None
00067                 #~ rolls = None
00068                 #~ avoidlinks = None
00069                 #~ graspingnoise = None
00070                 #~ plannername = None
00071                 #~ normalanglerange = 0
00072                 #~ directiondelta=0
00073                 #~ translationstepmult=None
00074                 #~ finestep=None
00075                 ####
00076                 
00077                 
00078                 options = self.configure_grasp_generation()
00079                 
00080                 
00081                 
00082                 
00083                 now_plan = time.time()
00084                 
00085                 ### Do actual GraspGeneration
00086                 if gmodel.load():
00087                         if replan == True:
00088                                 print "Replanning database"
00089                                 gmodel.autogenerate(options)
00090                         print "Successfully loaded a database"
00091                 else:
00092                         print "No database available"
00093                         print "Generating a database"
00094                         gmodel.autogenerate(options)
00095                 
00096                 
00097                 #time diff
00098                 end_plan = time.time()
00099                 time_difference = int(end_plan - now_plan)
00100                 print "GraspGeneration took: ", time_difference
00101                 
00102                 
00103                 
00104                 
00105                 ### GetValidGrasps now
00106                 #Return all validgrasps
00107                 #@OPTIONAL: We can return a desired number of grasps
00108                 #computeValidGrasps(startindex=0, checkcollision=True, checkik=True, checkgrasper=True, backupdist=0.0, returnnum=inf)
00109                 #Note: setting backupdist does somehow not effect the validgrasps list???
00110                 
00111                 validgrasps, validindicees = gmodel.computeValidGrasps(checkcollision=True, checkik=False)
00112                 #validgrasps, validindicees = gmodel.computeValidGrasps(backupdist=0.025, checkcollision=True, checkik=False)   #opt1
00113                 #validgrasps, validindicees = gmodel.computeValidGrasps(backupdist=0.0, checkcollision=True, checkik=False)             #opt2
00114                 print "TotalNumValidGrasps: ",len(validgrasps)
00115                 
00116                 #prevent from saving an empty file
00117                 if len(validgrasps) == 0:
00118                         print('No valid grasps generated')
00119                         return []
00120                         databases.grasping.RaveDestroy()
00121                 
00122                 #~ backupdist_array = [0.025, 0.05, 0.075, 0.1]
00123                 #~ num_grasps=numpy.inf
00124                 #~ #num_grasps = 20
00125                 #~ 
00126                 #~ validgrasps = []
00127                 #~ validindicees = []
00128                 #~ 
00129                 #~ 
00130                 #~ for bd in backupdist_array:
00131                         #~ ###GRASP-PLANNING
00132                         #~ #Return all validgrasps
00133                         #~ #@OPTIONAL: We can return a desired number of grasps
00134                         #~ #computeValidGrasps(startindex=0, checkcollision=True, checkik=True, checkgrasper=True, backupdist=0.0, returnnum=inf)
00135                         #~ validgrasps_bd, validindicees_bd = gmodel.computeValidGrasps(checkcollision=True, checkik=False, backupdist=bd, returnnum=num_grasps)
00136                         #~ 
00137                         #~ print "Backupdist: ",bd
00138                         #~ print "NumValidGrasps: ",len(validgrasps_bd)
00139                         #~ 
00140                         #~ validgrasps.extend(validgrasps_bd)
00141                         #~ validindicees.extend(validindicees_bd)
00142                 #~ 
00143                 #~ print "TotalNumValidGrasps: ",len(validgrasps)
00144                 
00145                 
00146                 
00147                 ##Write all validgrasps to file
00148                 grasps_to_file = []
00149                 meta_info = []
00150                 meta_info.append(object_name)
00151                 meta_info.append(time)
00152                 grasps_to_file.append(meta_info)
00153                 
00154                 #@todo: for debug, remove
00155                 for graspnmb in range(0,len(validgrasps)):
00156                 
00157                         #for segmentation fault purposes
00158                         auto_fill_rest = False
00159                         
00160                         grasp_to_file = []
00161                         grasp_to_file.append(graspnmb) #to file grasp number for id
00162                         grasp_num = int(graspnmb)
00163                         
00164                         #calculate metric and final joint configuration 
00165                         try:
00166                                 print "Grasp: ",graspnmb
00167                                 contacts,finalconfig,mindist,volume = gmodel.runGrasp(grasp=validgrasps[grasp_num], forceclosure=True)
00168                         except:
00169                                 print "something went wrong"
00170                                 mindist = 0.0
00171                                 volume = 0.0
00172                         
00173                         #show grasp before calculating the correct transformation
00174                         direction = gmodel.getGlobalApproachDir(validgrasps[graspnmb])
00175                         #gmodel.showgrasp(validgrasps[graspnmb],collisionfree=True)
00176                         transf = []
00177                         
00178                         with gmodel.GripperVisibility(manip):
00179                                 with self.env:
00180                                         gmodel.setPreshape(validgrasps[graspnmb])
00181                                         Tgrasp = gmodel.getGlobalGraspTransform(validgrasps[graspnmb],collisionfree=True)
00182                                         Tdelta = numpy.dot(Tgrasp,numpy.linalg.inv(manip.GetEndEffectorTransform()))
00183                                         DOFValues = robot.GetActiveDOFValues()
00184                                         DOFValues[manip.GetGripperIndices()] = finalconfig[0][manip.GetGripperIndices()]
00185                                         robot.SetDOFValues(DOFValues)
00186                                         robot.SetTransform(numpy.dot(Tdelta,robot.GetTransform()))
00187                                         self.env.UpdatePublishedBodies()
00188                         with self.target:
00189                                 self.target.SetTransform(numpy.eye(4))
00190                                 with gmodel.GripperVisibility(manip):
00191                                         with self.env:
00192                                                 gmodel.setPreshape(validgrasps[graspnmb])
00193                                                 Tgrasp = gmodel.getGlobalGraspTransform(validgrasps[graspnmb],collisionfree=True)
00194                                                 Tdelta = numpy.dot(Tgrasp,numpy.linalg.inv(manip.GetEndEffectorTransform()))
00195                                                 for link in manip.GetChildLinks():
00196                                                         link.SetTransform(numpy.dot(Tdelta,link.GetTransform()))
00197                                                 self.env.UpdatePublishedBodies()
00198                                                 # wait while environment is locked?
00199                                                 transf = manip.GetEndEffectorTransform()
00200                                                 
00201                         grasp_to_file.append(finalconfig[0][manip.GetGripperIndices()])
00202                         grasp_to_file.append(transf)
00203                         #gmodel.showgrasp(validgrasps[graspnmb],collisionfree=True)
00204                         grasp_to_file.append(mindist)
00205                         grasp_to_file.append(volume)
00206                         
00207                         forceclosure = validgrasps[graspnmb][gmodel.graspindices['forceclosure']]
00208                         grasp_to_file.append(forceclosure) 
00209                         grasp_to_file.append(validindicees[graspnmb])
00210                         grasp_to_file.append(direction)
00211                         #print "GlobApproachDir: ",gmodel.getGlobalApproachDir(validgrasps[i])
00212                         #SDH Joint Values - Beginnend mit Daumen(1) und die Zwei Finger GUZS nummeriert(2)(3)
00213                         #[Fingerwinkel(2), Fingerknick(2), Fingerrotation(2)(3), Fingerwinkel(3), Fingerknick(3), Fingerwinkel(1), Fingerknick(1)]
00214                         grasps_to_file.append(grasp_to_file)
00215                         
00216                         gmodel.getGlobalApproachDir(validgrasps[graspnmb])
00217                 
00218                 #Create a csv file if needed
00219                 analyzegrasp3d.or_to_csv(grasps_to_file) 
00220                 
00221                 print('Finished.')
00222                 databases.grasping.RaveDestroy()
00223                 return len(validgrasps)
00224         
00225         
00226         
00227         def configure_grasp_generation(self):
00228                 ### Options for GraspGeneration
00229                 #~ 'preshapes'
00230                 #~ 'manipulatordirections'
00231                 #~ 'boxdelta'
00232                 #~ 'spheredelta'
00233                 #~ 'standoffs'
00234                 #~ 'rolls'
00235                 #~ 'friction'
00236                 #~ 'avoidlinks'
00237                 #~ 'graspingnoise'
00238                 #~ 'plannername'
00239                 #~ 'normalanglerange'
00240                 #~ 'directiondelta'
00241                 #~ 'translationstepmult'
00242                 #~ 'finestep'
00243                 #~ 'numthreads'
00244                 ####
00245                 
00246                 #preshape --- default is 'something strange' ?
00247                 preshape_array = []
00248                 #preshape = '1.047 -0.785 1.047 -0.785 1.047 -0.785 1.047' # spheric_open
00249                 #preshape_array.append(preshape)
00250                 preshape = '0.0 -0.9854 0.9472 -0.9854 0.9472 -0.9854 0.9472' # cylindric_open
00251                 preshape_array.append(preshape)
00252                 preshape = '0.0 -0.9854 0.47 -0.9854 0.47 -0.9854 0.47' # fingers_half_straight_open
00253                 preshape_array.append(preshape)
00254                 #preshape = '0.0 -0.9854 0.0 -0.9854 0.0 -0.9854 0.0' # fingers_straight_open
00255                 #preshape_array.append(preshape)
00256                 options.preshapes = numpy.array(preshape_array)
00257                 
00258                 #manipulatordirections --- default is [0.0,1.0,0.0] ?
00259                 #~ md_array = []
00260                 #~ direction1 = '0.0 0.0 1.0' #along z-axis -- points 'out of sdh'
00261                 #~ md_array.append(direction1)
00262                 #~ options.manipulatordirections = numpy.array(md_array)
00263                 
00264                 #boxdelta --- default is 0.02
00265                 options.boxdelta = 0.05
00266                 
00267                 #spheredelta --- default is 0.1
00268                 #~ only used if boxdelta is not set
00269                 
00270                 #standoffs --- default is [0.0, 0.025] --- 0.0 is bad as we will hit the object!
00271                 standoff_array = [0.025, 0.075]
00272                 options.standoffs = numpy.array(standoff_array)
00273                 
00274                 #rolls --- default is [0.0, pi/2, pi, 3*pi/2, 2*pi]
00275                 
00276                 #fricion
00277                 options.friction = 1.0 #coefficient of static friction in graspit: rubber-<xobject> = 1
00278                 
00279                 #avoidlinks --- default is None ?
00280                 
00281                 #graspingnoise --- ?
00282                 
00283                 #plannername --- ?
00284                 
00285                 #normalanglerange --- default is 0.0 - used for computeXXXApproachRays
00286                 options.normalanglerange = 0.0
00287                 #options.normalanglerange = 15
00288                 
00289                 #directiondelta --- default is 0.4 - used for computeXXXApproachRays
00290                 options.directiondelta = 1
00291                 #options.directiondelta = 5
00292                 
00293                 #translationstepmult --- default is None ?
00294                 
00295                 #finestep
00296                 
00297                 #numthreads --- default is 1
00298                 #options.numthreads = 4         #--- multiple threads somehow not working
00299                 
00300                 return options
00301         
00302         
00303         #check if a database with the object_id exists
00304         def check_database(self, object_name):
00305                 #Begins here to read the grasp .csv-Files
00306                 path_in = roslib.packages.get_pkg_dir('cob_grasp_generation')+'/files/database/'+object_name+'/'+object_name+'.csv'
00307 
00308                 #Check if path exists
00309                 if os.path.exists(path_in):
00310                         return True
00311                 else: 
00312                         return False
00313         
00314         
00315         
00316         def get_grasp_list(self, object_name, sort_by_quality=False):
00317                 #Begins here to read the grasp .csv-Files
00318                 path_in = roslib.packages.get_pkg_dir('cob_grasp_generation')+'/files/database/'+object_name+'/'+object_name+'.csv'
00319 
00320                 #Check if path exists
00321                 try:
00322                         with open(path_in) as f: pass
00323                 except IOError as e:
00324                         rospy.logerr("The path or file does not exist: "+path_in)
00325 
00326                 #If exists open with dictreader
00327                 reader = csv.DictReader( open(path_in, "rb"), delimiter=',')
00328                 
00329                 if sort_by_quality:
00330                         #sorting for threshold
00331                         self.grasp_list = sorted(reader, key=lambda d: float(d['eps_l1']), reverse=True)
00332                 else:
00333                         self.grasp_list = sorted(reader, key=lambda d: float(d['id']), reverse=False)
00334         
00335         
00336         #get the grasps
00337         def get_grasps(self, object_name, grasp_id=0, num_grasps=0, threshold=0):
00338                 #open database
00339                 self.get_grasp_list(object_name)
00340                 
00341                 #check for grasp_id and return 
00342                 if grasp_id > 0:
00343                         if grasp_id < len(self.grasp_list):
00344                                 #print self._fill_grasp_msg(self.grasp_list[grasp_id])
00345                                 return [self._fill_grasp_msg(self.grasp_list[grasp_id])]
00346                         else:
00347                                 print "Grasp not available"
00348                                 return []
00349         
00350                 #sorting for threshold
00351                 sorted_list = sorted(self.grasp_list, key=lambda d: float(d['eps_l1']), reverse=True)
00352 
00353                 #calculate max_grasps
00354                 if num_grasps > 0:
00355                         max_grasps=min(len(sorted_list),num_grasps)
00356                 else:
00357                         max_grasps=len(sorted_list)
00358                         
00359                 #grasp output
00360                 selected_grasp_list = []
00361                 for i in range(0,max_grasps):
00362                         if threshold > 0 and float(sorted_list[i]['eps_l1']) >= threshold:
00363                                 selected_grasp_list.append(self._fill_grasp_msg(sorted_list[i]))
00364                         elif threshold == 0:
00365                                 selected_grasp_list.append(self._fill_grasp_msg(sorted_list[i]))
00366                         else:
00367                                 pass
00368 
00369                 #print len(selected_grasp_list)
00370                 return selected_grasp_list
00371         
00372         
00373         #fill the grasp message of ROS
00374         def _fill_grasp_msg(self, grasp):
00375                 
00376                 #grasp posture
00377                 joint_config = JointTrajectory()
00378                 joint_config.header.stamp = rospy.Time.now()
00379                 #joint_config.header.frame_id = ""
00380                 joint_config.joint_names = ['sdh_knuckle_joint', 'sdh_finger_12_joint', 'sdh_finger_13_joint', 'sdh_finger_22_joint', 'sdh_finger_23_joint', 'sdh_thumb_2_joint', 'sdh_thumb_3_joint']
00381                 print "Optimize grasp_configuration"
00382                 for joint_name in joint_config.joint_names:
00383                         point = JointTrajectoryPoint()
00384                         point.positions.append(float(grasp[joint_name]))
00385                         point.velocities.append(0.0)
00386                         point.accelerations.append(0.0)
00387                         point.time_from_start = rospy.Duration(3.0)
00388                         joint_config.points.append(point)
00389                 ## WARNING: in hydro the message format has changed, thus the following does not work anymore
00390                 ##joint_config.position = [float(grasp['sdh_knuckle_joint']), float(grasp['sdh_finger_12_joint']), float(grasp['sdh_finger_13_joint']), float(grasp['sdh_finger_22_joint']), float(grasp['sdh_finger_23_joint']), float(grasp['sdh_thumb_2_joint']), float(grasp['sdh_thumb_3_joint'])]
00391                 ##print joint_config.position
00392                 #joint_config.position = [float(grasp['sdh_knuckle_joint']), 0.92*float(grasp['sdh_finger_12_joint']), float(grasp['sdh_finger_13_joint']), 0.92*float(grasp['sdh_finger_22_joint']), float(grasp['sdh_finger_23_joint']), 0.92*float(grasp['sdh_thumb_2_joint']), float(grasp['sdh_thumb_3_joint'])]
00393                 #print joint_config
00394 
00395                 #pregrasp posture
00396                 pre_joint_config = JointTrajectory()
00397                 pre_joint_config.header.stamp = rospy.Time.now()
00398                 pre_joint_config.joint_names = ['sdh_knuckle_joint', 'sdh_finger_12_joint', 'sdh_finger_13_joint', 'sdh_finger_22_joint', 'sdh_finger_23_joint', 'sdh_thumb_2_joint', 'sdh_thumb_3_joint']
00399                 cyl_open = [0.0, -0.9854, 0.9472, -0.9854, 0.9472, -0.9854, 0.9472]
00400                 #pre_joint_config.header.frame_id = ""
00401                 for i in range(len(pre_joint_config.joint_names)):
00402                         point = JointTrajectoryPoint()
00403                         point.positions.append(cyl_open[i])
00404                         point.velocities.append(0.0)
00405                         point.accelerations.append(0.0)
00406                         point.time_from_start = rospy.Duration(3.0)
00407                         pre_joint_config.points.append(point)
00408                 print pre_joint_config
00409 
00410                 #grasp pose
00411                 grasp_pose = PoseStamped()
00412                 grasp_pose.header.stamp = rospy.Time.now()
00413                 #grasp_pose.header.frame_id = ""
00414                 grasp_pose.pose.position.x = float(grasp['pos-x'])*0.001 #mm to m
00415                 grasp_pose.pose.position.y = float(grasp['pos-y'])*0.001 #mm to m
00416                 grasp_pose.pose.position.z = float(grasp['pos-z'])*0.001 #mm to m
00417                 grasp_pose.pose.orientation.x = float(grasp['qx'])
00418                 grasp_pose.pose.orientation.y = float(grasp['qy'])
00419                 grasp_pose.pose.orientation.z = float(grasp['qz'])
00420                 grasp_pose.pose.orientation.w = float(grasp['qw'])
00421    
00422                 #grasp
00423                 grasp_out = Grasp()
00424                 grasp_out.id = grasp['id']
00425                 grasp_out.pre_grasp_posture = pre_joint_config
00426                 grasp_out.grasp_posture = joint_config
00427                 grasp_out.grasp_pose = grasp_pose
00428                 grasp_out.grasp_quality = float(grasp['eps_l1'])
00429                 grasp_out.max_contact_force = 0
00430 
00431                 return grasp_out
00432         
00433         
00434         def show_grasp(self, object_name, grasp_id, sort_by_quality=False):
00435                 self.setup_environment(object_name, viewer=True)
00436                 
00437                 self.get_grasp_list(object_name, sort_by_quality)
00438                 
00439                 
00440                 #robot
00441                 robot = self.env.GetRobots()[0]
00442                 manip = robot.GetManipulator('arm')
00443                 gmodel = databases.grasping.GraspingModel(robot,self.target)
00444 
00445                 #TCP - transformed to hand wrist
00446                 tool_trafo = manip.GetLocalToolTransform()
00447                 tool_trafo[2,3] = 0.0
00448                 manip.SetLocalToolTransform(tool_trafo)
00449 
00450                 #Show the grasps
00451                 #SetDOFValues
00452                 grasp = self.grasp_list[int(grasp_id)]
00453                 print 'Grasp ID: '+str(grasp['id'])
00454                 print 'Grasp Quality epsilon: '+str(grasp['eps_l1'])
00455                 print 'Grasp Quality volume: '+str(grasp['vol_l1'])
00456                 #print grasp
00457 
00458                 with gmodel.GripperVisibility(manip):
00459                         dof_array = [0]*27
00460                         dof_array[7:13] =[float(grasp['sdh_finger_22_joint']),float(grasp['sdh_finger_23_joint']),float(grasp['sdh_knuckle_joint']),float(grasp['sdh_finger_12_joint']),float(grasp['sdh_finger_13_joint']),float(grasp['sdh_thumb_2_joint']),float(grasp['sdh_thumb_3_joint'])]
00461                         robot.SetDOFValues(numpy.array(dof_array))
00462 
00463                         #matrix from pose
00464                         mm_in_m = 0.001
00465                         pos = [float(grasp['pos-x'])*mm_in_m, float(grasp['pos-y'])*mm_in_m, float(grasp['pos-z'])*mm_in_m]  
00466                         quat = [float(grasp['qw']), float(grasp['qx']), float(grasp['qy']), float(grasp['qz'])]
00467                         Tgrasp = matrixFromPose(quat+pos)
00468 
00469                         #transform robot
00470                         Tdelta = numpy.dot(Tgrasp,numpy.linalg.inv(manip.GetEndEffectorTransform()))
00471                         for link in manip.GetChildLinks():
00472                                 link.SetTransform(numpy.dot(Tdelta,link.GetTransform()))
00473 
00474                         #publish update of scene
00475                         time.sleep(1)
00476                         self.env.UpdatePublishedBodies()
00477 
00478 


cob_grasp_generation
Author(s): Witalij Siebert, Felix Messmer
autogenerated on Wed Aug 26 2015 11:01:25