00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 import roslib; roslib.load_manifest('tabletop_collision_map_processing')
00042 import random, time, math, scipy, pdb
00043 import rospy
00044 from arm_navigation_msgs.msg import Shape
00045 from tabletop_object_detector.msg import Table
00046 from arm_navigation_msgs.msg import MakeStaticCollisionMapAction, MakeStaticCollisionMapGoal
00047 from arm_navigation_msgs.msg import CollisionObject, AttachedCollisionObject, CollisionObjectOperation
00048 from actionlib_msgs.msg import GoalStatus
00049 from std_srvs.srv import Empty, EmptyRequest
00050 from arm_navigation_msgs.msg import Shape
00051 import actionlib
00052 import tf
00053 from geometry_msgs.msg import PoseStamped, Point, Quaternion, Pose
00054 from arm_navigation_msgs.srv import SetPlanningSceneDiff, SetPlanningSceneDiffRequest
00055
00056
00057
00058 class CollisionMapInterface():
00059
00060 def __init__(self):
00061
00062
00063 rospy.loginfo("advertising on collision object topics")
00064 self.object_in_map_pub = rospy.Publisher("collision_object", CollisionObject)
00065 self.attached_object_pub = rospy.Publisher("attached_collision_object", AttachedCollisionObject)
00066
00067 rospy.loginfo("waiting for collision map reset service")
00068 rospy.wait_for_service("collider_node/reset")
00069 rospy.loginfo("found collision map reset service")
00070 self.reset_collision_map_srv = rospy.ServiceProxy("collider_node/reset", Empty)
00071
00072 rospy.loginfo("waiting for set planning scene diff service")
00073 rospy.wait_for_service("environment_server/set_planning_scene_diff")
00074 self.set_planning_scene_srv = rospy.ServiceProxy("environment_server/set_planning_scene_diff", SetPlanningSceneDiff)
00075
00076 self.object_in_map_current_id = 0
00077 rospy.loginfo("done initializing collision map interface")
00078
00079
00080
00081 def set_planning_scene(self, ordered_collision_ops = None, link_padding = None):
00082 req = SetPlanningSceneDiffRequest()
00083 if ordered_collision_ops != None:
00084 req.operations = ordered_collision_ops
00085 if link_padding != None:
00086 req.planning_scene_diff.link_padding = link_padding
00087 try:
00088 resp = self.set_planning_scene_srv(req)
00089 except:
00090 rospy.logerr("error in calling set_planning_scene_diff!")
00091 return 0
00092 return 1
00093
00094
00095
00096 def clear_octomap(self):
00097 self.reset_collision_map_srv()
00098
00099
00100
00101 def reset_collision_map(self):
00102
00103
00104 reset_object = CollisionObject()
00105 reset_object.operation.operation = CollisionObjectOperation.REMOVE
00106 reset_object.header.frame_id = "base_link"
00107 reset_object.header.stamp = rospy.Time.now()
00108 reset_object.id = "all"
00109 self.object_in_map_pub.publish(reset_object)
00110
00111
00112 reset_attached_objects = AttachedCollisionObject()
00113 reset_attached_objects.link_name = "all"
00114 reset_attached_objects.object.header.frame_id = "base_link"
00115 reset_attached_objects.object.header.stamp = rospy.Time.now()
00116 reset_attached_objects.object = reset_object
00117 self.attached_object_pub.publish(reset_attached_objects)
00118
00119
00120 self.clear_octomap()
00121
00122 rospy.loginfo("collision objects reset")
00123 self.object_in_map_current_id = 0.
00124 return 1
00125
00126
00127
00128 def attach_object_to_gripper(self, object_name, whicharm = 'r'):
00129
00130 obj = AttachedCollisionObject()
00131
00132 obj.link_name = whicharm+"_gripper_r_finger_tip_link"
00133 obj.object.operation.operation = CollisionObjectOperation.ATTACH_AND_REMOVE_AS_OBJECT
00134 obj.object.header.stamp = rospy.Time.now()
00135 obj.object.header.frame_id = "base_link"
00136 obj.object.id = object_name
00137 touch_links = ["_gripper_palm_link", "_gripper_r_finger_tip_link", "_gripper_l_finger_tip_link", "_gripper_l_finger_link", "_gripper_r_finger_link"]
00138 obj.touch_links = [whicharm+link for link in touch_links]
00139 self.attached_object_pub.publish(obj)
00140
00141
00142
00143
00144 def detach_all_objects_from_gripper(self, whicharm = 'r'):
00145
00146 rospy.loginfo("detaching all objects from gripper %s"%whicharm)
00147 obj = AttachedCollisionObject()
00148 obj.object.header.stamp = rospy.Time.now()
00149 obj.object.header.frame_id = "base_link"
00150 obj.link_name = whicharm+"_gripper_r_finger_tip_link"
00151 obj.object.operation.operation = CollisionObjectOperation.REMOVE
00152 self.attached_object_pub.publish(obj)
00153
00154
00155
00156
00157
00158 def detach_and_add_back_objects_attached_to_gripper(self, whicharm = 'r', object_collision_name = None):
00159
00160 rospy.loginfo("detaching all objects from gripper %s and adding them back to the collision map"%whicharm)
00161
00162 if object_collision_name == None:
00163 rospy.loginfo("need to specify the object name! Detaching and not adding back object.")
00164 self.detach_all_objects_from_gripper(whicharm)
00165 return
00166
00167 obj = AttachedCollisionObject()
00168 obj.object.header.stamp = rospy.Time.now()
00169 obj.object.header.frame_id = "base_link"
00170 obj.link_name = whicharm+"_gripper_r_finger_tip_link"
00171 obj.object.id = object_collision_name
00172 obj.object.operation.operation = CollisionObjectOperation.DETACH_AND_ADD_AS_OBJECT
00173 self.attached_object_pub.publish(obj)
00174
00175
00176
00177 def pose_to_mat(self, pose):
00178 quat = [pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w]
00179 pos = scipy.matrix([pose.position.x, pose.position.y, pose.position.z]).T
00180 mat = scipy.matrix(tf.transformations.quaternion_matrix(quat))
00181 mat[0:3, 3] = pos
00182 return mat
00183
00184
00185
00186 def mat_to_pose(self, mat):
00187 pose = Pose()
00188 pose.position.x = mat[0,3]
00189 pose.position.y = mat[1,3]
00190 pose.position.z = mat[2,3]
00191 quat = tf.transformations.quaternion_from_matrix(mat)
00192 pose.orientation.x = quat[0]
00193 pose.orientation.y = quat[1]
00194 pose.orientation.z = quat[2]
00195 pose.orientation.w = quat[3]
00196 return pose
00197
00198
00199
00200 def process_collision_geometry_for_table(self, firsttable, additional_tables = []):
00201
00202 table_object = CollisionObject()
00203 table_object.operation.operation = CollisionObjectOperation.ADD
00204 table_object.header.frame_id = firsttable.pose.header.frame_id
00205 table_object.header.stamp = rospy.Time.now()
00206
00207
00208 for table in [firsttable,]+additional_tables:
00209 object = Shape()
00210 object.type = Shape.BOX;
00211 object.dimensions.append(math.fabs(table.x_max-table.x_min))
00212 object.dimensions.append(math.fabs(table.y_max-table.y_min))
00213 object.dimensions.append(0.01)
00214 table_object.shapes.append(object)
00215
00216
00217 table_mat = self.pose_to_mat(firsttable.pose.pose)
00218 table_offset = scipy.matrix([(firsttable.x_min + firsttable.x_max)/2.0, (firsttable.y_min + firsttable.y_max)/2.0, 0.0]).T
00219 table_offset_mat = scipy.matrix(scipy.identity(4))
00220 table_offset_mat[0:3,3] = table_offset
00221 table_center = table_mat * table_offset_mat
00222 origin_pose = self.mat_to_pose(table_center)
00223 table_object.poses.append(origin_pose)
00224
00225 table_object.id = "table"
00226 self.object_in_map_pub.publish(table_object)
00227
00228
00229
00230 def get_next_object_name(self):
00231 string = "graspable_object_"+str(self.object_in_map_current_id)
00232 self.object_in_map_current_id += 1
00233 return string
00234
00235
00236
00237 def add_collision_box(self, box_pose, box_dims, frame_id, collision_name):
00238
00239 rospy.loginfo("adding box to collision map")
00240 box = CollisionObject()
00241 box.operation.operation = CollisionObjectOperation.ADD
00242 box.header.frame_id = frame_id
00243 box.header.stamp = rospy.Time.now()
00244 shape = Shape()
00245 shape.type = Shape.BOX
00246 shape.dimensions = box_dims
00247 box.shapes.append(shape)
00248 box.poses.append(box_pose)
00249 box.id = collision_name
00250 self.object_in_map_pub.publish(box)
00251
00252
00253
00254 def process_collision_geometry_for_cluster(self, cluster):
00255
00256 rospy.loginfo("adding cluster with %d points to collision map"%len(cluster.points))
00257
00258 many_boxes = CollisionObject()
00259
00260 many_boxes.operation.operation = CollisionObjectOperation.ADD
00261 many_boxes.header = cluster.header
00262 many_boxes.header.stamp = rospy.Time.now()
00263 num_to_use = int(len(cluster.points)/100.0)
00264 random_indices = range(len(cluster.points))
00265 scipy.random.shuffle(random_indices)
00266 random_indices = random_indices[0:num_to_use]
00267 for i in range(num_to_use):
00268 shape = Shape()
00269 shape.type = Shape.BOX
00270 shape.dimensions = [.005]*3
00271 pose = Pose()
00272 pose.position.x = cluster.points[random_indices[i]].x
00273 pose.position.y = cluster.points[random_indices[i]].y
00274 pose.position.z = cluster.points[random_indices[i]].z
00275 pose.orientation = Quaternion(*[0,0,0,1])
00276 many_boxes.shapes.append(shape)
00277 many_boxes.poses.append(pose)
00278
00279 collision_name = self.get_next_object_name()
00280 many_boxes.id = collision_name
00281 self.object_in_map_pub.publish(many_boxes)
00282 return collision_name
00283
00284
00285
00286 def remove_collision_object(self, collision_name):
00287
00288 reset_object = CollisionObject()
00289 reset_object.operation.operation = CollisionObjectOperation.REMOVE
00290 reset_object.header.frame_id = "base_link"
00291 reset_object.header.stamp = rospy.Time.now()
00292 reset_object.id = collision_name
00293 self.object_in_map_pub.publish(reset_object)