armplanning_openrave.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- coding: utf-8 -*-
00003 # Copyright (c) 2010 Rosen Diankov (rosen.diankov@gmail.com)
00004 #
00005 # Licensed under the Apache License, Version 2.0 (the "License");
00006 # you may not use this file except in compliance with the License.
00007 # You may obtain a copy of the License at
00008 #     http://www.apache.org/licenses/LICENSE-2.0
00009 # 
00010 # Unless required by applicable law or agreed to in writing, software
00011 # distributed under the License is distributed on an "AS IS" BASIS,
00012 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 # See the License for the specific language governing permissions and
00014 # limitations under the License.
00015 from __future__ import with_statement # for python 2.5
00016 __author__ = 'Rosen Diankov'
00017 __copyright__ = 'Copyright (C) 2010 Rosen Diankov (rosen.diankov@gmail.com)'
00018 __license__ = 'Apache License, Version 2.0'
00019 import roslib; roslib.load_manifest('orrosplanning')
00020 import rospy
00021 
00022 from optparse import OptionParser
00023 from openravepy import *
00024 from openravepy.misc import OpenRAVEGlobalArguments
00025 from numpy import *
00026 import numpy,time,threading
00027 from itertools import izip
00028 import tf
00029 import os
00030 import orrosplanning.srv
00031 import sensor_msgs.msg
00032 import trajectory_msgs.msg
00033 import geometry_msgs.msg
00034 
00035 
00036 if __name__ == "__main__":
00037     parser = OptionParser(description='openrave planning example')
00038     OpenRAVEGlobalArguments.addOptions(parser)
00039     parser.add_option('--scene',action="store",type='string',dest='scene',default='robots/pr2-beta-static.zae',
00040                       help='scene to load (default=%default)')
00041     parser.add_option('--collision_map',action="store",type='string',dest='collision_map',default='/collision_map/collision_map',
00042                       help='The collision map topic (maping_msgs/CollisionMap), by (default=%default)')
00043     parser.add_option('--ipython', '-i',action="store_true",dest='ipython',default=False,
00044                       help='if true will drop into the ipython interpreter rather than spin')
00045     parser.add_option('--mapframe',action="store",type='string',dest='mapframe',default=None,
00046                       help='The frame of the map used to position the robot. If --mapframe="" is specified, then nothing will be transformed with tf')
00047     parser.add_option('--jitter',action="store",type='float',dest='jitter',default=None,
00048                       help='The jitter to use when moving robot out of collision')
00049     parser.add_option('--maxvelmult',action='store',type='float',dest='maxvelmult',default=1.0,
00050                       help='The maximum velocity multiplier when timing the trajectories (default=%default)')
00051     parser.add_option('--wait-for-collisionmap',action='store',type='float',dest='wait_for_collisionmap',default=None,
00052                       help='Time (seconds) to set. Will wait for the collision map time stamp to reach the same time as the service being called. If 0, will wait indefinitely.')
00053     parser.add_option('--request-for-joint_states',action='store',type='string',dest='request_for_joint_states',default='topic',
00054                       help='whether to get joint states from topic or service. If ="service", will not update robot joint states until receiving service call.')
00055     parser.add_option('--use-simulation',action='store',type='string',dest='simulation',default=None,
00056                       help='if use-simulation is set, we dismiss timestamp of collisionmap.')
00057     (options, args) = parser.parse_args()
00058     env = OpenRAVEGlobalArguments.parseAndCreate(options,defaultviewer=False)
00059     RaveLoadPlugin(os.path.join(roslib.packages.get_pkg_dir('orrosplanning'),'lib','liborrosplanning.so'))
00060     #RaveLoadPlugin(os.path.join(roslib.packages.get_pkg_dir('openraveros'),'lib','openraveros'))
00061     namespace = 'openrave'
00062     #env.AddModule(RaveCreateModule(env,'rosserver'),namespace)
00063     rospy.loginfo('initializing, please wait for ready signal...')
00064     handles = [] # for viewer
00065     def UpdateRobotJoints(msg):
00066         global options
00067         with envlock:
00068             with env:
00069                 for name,pos in izip(msg.name,msg.position):
00070                     j = robot.GetJoint(name)
00071                     if j is not None:
00072                         values[j.GetDOFIndex()] = pos
00073                     robot.SetDOFValues(values)
00074     def UpdateRobotJointsFn(req):
00075         rospy.loginfo("Update joint states")
00076         UpdateRobotJoints(req.jointstate)
00077         return True
00078     try:
00079         rospy.init_node('armplanning_openrave',disable_signals=False)
00080         with env:
00081             env.Load(options.scene)
00082             robot = env.GetRobots()[0]
00083 
00084             #set robot weights/resolutions (without this planning will be slow)
00085             if 1:
00086                 lmodel = databases.linkstatistics.LinkStatisticsModel(robot)
00087                 if not lmodel.load():
00088                     lmodel.autogenerate()
00089                 lmodel.setRobotWeights()
00090                 lmodel.setRobotResolutions()
00091                 resolutions=robot.GetDOFResolutions()
00092                 weights=robot.GetDOFWeights()
00093                 for j in robot.GetJoints():
00094                     j.SetResolution(3.0*resolutions[j.GetDOFIndex():(j.GetDOFIndex()+j.GetDOF())])
00095                     j.SetWeights(1.0*weights[j.GetDOFIndex():(j.GetDOFIndex()+j.GetDOF())])
00096             # create ground right under the robot
00097             ab=robot.ComputeAABB()
00098             ground=RaveCreateKinBody(env,'')
00099             ground.SetName('map')
00100             ground.InitFromBoxes(array([r_[ab.pos()-array([0,0,ab.extents()[2]+0.002]),2.0,2.0,0.001]]),True)
00101             env.AddKinBody(ground,False)
00102             if options.mapframe is None:
00103                 options.mapframe = robot.GetLinks()[0].GetName()
00104                 print 'setting map frame to %s'%options.mapframe
00105             collisionmap = RaveCreateSensorSystem(env,'CollisionMap expirationtime 20 bodyoffset %s topic %s'%(robot.GetName(),options.collision_map))
00106             if options.request_for_joint_states == 'topic':
00107                 sub = rospy.Subscriber("/joint_states", sensor_msgs.msg.JointState, UpdateRobotJoints,queue_size=1)
00108                 # joint_states = '/joint_states'
00109                 # for a in args:
00110                 #     if a.startswith('%s:='%joint_states):
00111                 #         joint_states = a[len(joint_states)+2:]
00112                 # robot.SetController(RaveCreateController(env,'ROSPassiveController jointstate %s'%joint_states),range(robot.GetDOF()),False)
00113 
00114         # have to do this manually because running linkstatistics when viewer is enabled segfaults things
00115         if options._viewer is None:
00116             env.SetViewer('qtcoin')
00117         elif len(options._viewer) > 0:
00118             env.SetViewer(options._viewer)
00119         if len(options.mapframe) > 0:
00120             listener = tf.TransformListener()
00121         values = robot.GetDOFValues()
00122         envlock = threading.Lock()
00123 
00124         postprocessing = ['shortcut_linear','<_nmaxiterations>20</_nmaxiterations><_postprocessing planner=\"parabolicsmoother\"><_nmaxiterations>40</_nmaxiterations></_postprocessing>']
00125         def MoveToHandPositionFn(req):
00126             global options
00127             rospy.loginfo("MoveToHandPosition")
00128             try:
00129                 with envlock:
00130                     if options.wait_for_collisionmap is not None:
00131                         starttime=time.time()
00132                         handgoalstamp = int64(req.hand_goal.header.stamp.to_nsec())
00133                         while True:
00134                             timepassed = time.time()-starttime
00135                             collisionstamp = collisionmap.SendCommand("gettimestamp")
00136                             if collisionstamp is not None:
00137                                 if int64(collisionstamp)-handgoalstamp >= 0:
00138                                      break
00139                             if options.wait_for_collisionmap > 0 and timepassed > options.wait_for_collisionmap:
00140                                 if options.simulation is not None:
00141                                     break;
00142                                 raise ValueError('failed to acquire new collision map, collision timestamp is %s, service timestamp is %s'%(collisionstamp,handgoalstamp))
00143                             time.sleep(0.1) # wait
00144 
00145                     collisionmap.SendCommand("collisionstream 0")
00146 
00147                     with env:
00148                         basemanip = interfaces.BaseManipulation(robot,plannername=None if len(req.planner)==0 else req.planner,maxvelmult=options.maxvelmult)
00149                         rospy.loginfo("MoveToHandPosition2")
00150                         if len(options.mapframe) > 0:
00151                             (robot_trans,robot_rot) = listener.lookupTransform(options.mapframe, robot.GetLinks()[0].GetName(), rospy.Time(0))
00152                             Trobot = matrixFromQuat([robot_rot[3],robot_rot[0],robot_rot[1],robot_rot[2]])
00153                             Trobot[0:3,3] = robot_trans
00154                             robot.SetTransform(Trobot)
00155                             hand = listener.transformPose(options.mapframe, req.hand_goal)
00156                         else:
00157                             hand = req.hand_goal
00158                         o = hand.pose.orientation
00159                         p = hand.pose.position
00160                         Thandgoal = matrixFromQuat([o.w,o.x,o.y,o.z])
00161                         Thandgoal[0:3,3] = [p.x,p.y,p.z]
00162 
00163                         if len(req.manip_name) > 0:
00164                             manip = robot.GetManipulator(req.manip_name)
00165                             if manip is None:
00166                                 rospy.logerr('failed to find manipulator %s'%req.manip_name)
00167                                 return None
00168                         else:
00169                             manips = [manip for manip in robot.GetManipulators() if manip.GetEndEffector().GetName()==req.hand_frame_id]
00170                             if len(manips) == 0:
00171                                 rospy.logerr('failed to find manipulator end effector %s'%req.hand_frame_id)
00172                                 return None
00173                             manip = manips[0]
00174 
00175                         robot.SetActiveManipulator(manip)
00176                         robot.SetActiveDOFs(manip.GetArmIndices())
00177                         if len(req.hand_frame_id) > 0:
00178                             handlink = robot.GetLink(req.hand_frame_id)
00179                             if handlink is None:
00180                                 rospy.logerr('failed to find link %s'%req.hand_frame_id)
00181                                 return None
00182                             Thandlink = handlink.GetTransform()
00183                         else:
00184                             Thandlink = manip.GetEndEffectorTransform()
00185                         if manip.GetIkSolver() is None:
00186                             rospy.loginfo('generating ik for %s'%str(manip))
00187                             ikmodel = databases.inversekinematics.InverseKinematicsModel(robot,iktype=IkParameterization.Type.Transform6D)
00188                             if not ikmodel.load():
00189                                 ikmodel.autogenerate()
00190 
00191                         Tgoalee = dot(Thandgoal,dot(linalg.inv(Thandlink),manip.GetTransform()))
00192                         try:
00193                             starttime = time.time()
00194                             traj = basemanip.MoveToHandPosition(matrices=[Tgoalee],maxtries=3,seedik=4,execute=False,outputtrajobj=True,maxiter=750,jitter=options.jitter,postprocessing=postprocessing)
00195                             rospy.loginfo('total planning time: %fs'%(time.time()-starttime))
00196                         except:
00197                             rospy.logerr('failed to solve for T=%s, error messages are:'%repr(Tgoalee))
00198                             RaveSetDebugLevel(DebugLevel.Verbose)
00199                             manip.FindIKSolution(Tgoalee,IkFilterOptions.CheckEnvCollisions)
00200                             RaveSetDebugLevel(DebugLevel.Debug)
00201                             return None
00202                         # parse trajectory data into the ROS structure
00203                         res = orrosplanning.srv.MoveToHandPositionResponse()
00204                         spec = traj.GetConfigurationSpecification()
00205                         res.traj.joint_names = [str(j.GetName()) for j in robot.GetJoints(manip.GetArmIndices())]
00206                         starttime = 0.0
00207                         for i in range(traj.GetNumWaypoints()):
00208                             pt=trajectory_msgs.msg.JointTrajectoryPoint()
00209                             data = traj.GetWaypoint(i)
00210                             pt.positions = spec.ExtractJointValues(data,robot,manip.GetArmIndices(),0)
00211                             starttime += spec.ExtractDeltaTime(data)
00212                             pt.time_from_start = rospy.Duration(starttime)
00213                             res.traj.points.append(pt)
00214                         return res
00215 
00216             finally:
00217                 collisionmap.SendCommand("collisionstream 1")
00218 
00219         def MoveManipulatorFn(req):
00220             global options
00221             rospy.loginfo("MoveManipulator")
00222             try:
00223                 with envlock:
00224                     if options.wait_for_collisionmap is not None:
00225                         starttime=time.time()
00226                         handgoalstamp = int64(req.hand_goal.header.stamp.to_nsec())
00227                         while True:
00228                             timepassed = time.time()-starttime
00229                             collisionstamp = collisionmap.SendCommand("gettimestamp")
00230                             if collisionstamp is not None:
00231                                 if int64(collisionstamp)-handgoalstamp >= 0:
00232                                      break
00233                             if options.wait_for_collisionmap > 0 and timepassed > options.wait_for_collisionmap:
00234                                 if options.simulation is not None:
00235                                     break;
00236                                 raise ValueError('failed to acquire new collision map, collision timestamp is %s, service timestamp is %s'%(collisionstamp,handgoalstamp))
00237                             time.sleep(0.1) # wait
00238 
00239                     collisionmap.SendCommand("collisionstream 0")
00240 
00241                     with env:
00242                         basemanip = interfaces.BaseManipulation(robot,plannername=None if len(req.planner)==0 else req.planner,maxvelmult=options.maxvelmult)
00243                         rospy.loginfo("MoveManipulator2")
00244                         manip = robot.SetActiveManipulator(req.manip_name)
00245                         if manip is None:
00246                             rospy.logerr('failed to find manipulator %s'%req.manip_name)
00247                             return None
00248 
00249                         try:
00250                             starttime = time.time()
00251                             traj = basemanip.MoveManipulator(goal=req.manip_goal,execute=False,outputtrajobj=True,maxiter=750,jitter=options.jitter)
00252                             rospy.loginfo('total planning time: %fs'%(time.time()-starttime))
00253                         except:
00254                             rospy.logerr('failed to solve for goal=%s, error messages are:'%repr(req.manip_goal))
00255                             return None
00256                         # parse trajectory data into the ROS structure
00257                         res = orrosplanning.srv.MoveManipulatorResponse()
00258                         spec = traj.GetConfigurationSpecification()
00259                         res.traj.joint_names = [str(j.GetName()) for j in robot.GetJoints(manip.GetArmIndices())]
00260                         starttime = 0.0
00261                         for i in range(traj.GetNumWaypoints()):
00262                             pt=trajectory_msgs.msg.JointTrajectoryPoint()
00263                             data = traj.GetWaypoint(i)
00264                             pt.positions = spec.ExtractJointValues(data,robot,manip.GetArmIndices(),0)
00265                             starttime += spec.ExtractDeltaTime(data)
00266                             pt.time_from_start = rospy.Duration(starttime)
00267                             res.traj.points.append(pt)
00268                         return res
00269 
00270             finally:
00271                 collisionmap.SendCommand("collisionstream 1")
00272 
00273         if options.request_for_joint_states == 'service':
00274             js = rospy.Service('SetJointState', orrosplanning.srv.SetJointState, UpdateRobotJointsFn)
00275 
00276         s1 = rospy.Service('MoveToHandPosition', orrosplanning.srv.MoveToHandPosition, MoveToHandPositionFn)
00277         s2 = rospy.Service('MoveManipulator', orrosplanning.srv.MoveManipulator, MoveManipulatorFn)
00278         RaveSetDebugLevel(DebugLevel.Debug)
00279         rospy.loginfo('openrave %s,%s service ready'%(s1.resolved_name,s2.resolved_name))
00280 
00281         if options.ipython:
00282             from IPython.Shell import IPShellEmbed
00283             ipshell = IPShellEmbed(argv='',banner = 'Dropping into IPython',exit_msg = 'Leaving Interpreter, back to program.')
00284             ipshell(local_ns=locals())
00285         else:
00286             rospy.spin()
00287     finally:
00288         RaveDestroy()
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


orrosplanning
Author(s): Rosen Diankov (rosen.diankov@gmail.com)
autogenerated on Sat Mar 23 2013 22:32:56