mpc_teleop_rviz.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 #   Copyright 2013 Georgia Tech Research Corporation
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 #
00009 #     http://www.apache.org/licenses/LICENSE-2.0
00010 #
00011 #   Unless required by applicable law or agreed to in writing, software
00012 #   distributed under the License is distributed on an "AS IS" BASIS,
00013 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014 #   See the License for the specific language governing permissions and
00015 #   limitations under the License.
00016 #
00017 #  http://healthcare-robotics.com/
00018 
00019 ## @package hrl_haptic_mpc
00020 # 
00021 # @author Jeff Hawke 
00022 # @version 0.1
00023 # @copyright Apache 2.0
00024 
00025 import math, numpy as np
00026 import sys, optparse
00027 
00028 import interactive_marker_util as imu
00029 
00030 import roslib; roslib.load_manifest('hrl_haptic_mpc')
00031 import rospy
00032 
00033 import hrl_lib.transforms as tr
00034 import haptic_mpc_util
00035 import hrl_haptic_manipulation_in_clutter_msgs.msg as haptic_msgs
00036 import std_msgs.msg
00037 
00038 import interactive_markers.interactive_marker_server as ims
00039 import interactive_markers.menu_handler as mh
00040 
00041 import actionlib
00042 from visualization_msgs.msg import Marker, InteractiveMarker, InteractiveMarkerFeedback, InteractiveMarkerControl
00043 from geometry_msgs.msg import PoseStamped, PointStamped, PoseArray
00044 from std_msgs.msg import String, Bool, Empty
00045 from pr2_controllers_msgs.msg import Pr2GripperCommandGoal, Pr2GripperCommandAction, Pr2GripperCommand
00046 
00047 
00048 ## RViz teleop interface to the controller. 
00049 #
00050 # Publishes goal poses on the appropriate topics and allows a user to teleop the arm controller.
00051 class MPCTeleopInteractiveMarkers():
00052   def __init__(self, opt):
00053     self.opt = opt
00054     base_path = '/haptic_mpc'
00055     control_path = '/control_params'
00056     self.orient_weight = rospy.get_param(base_path + control_path + '/orientation_weight')
00057     self.pos_weight = rospy.get_param(base_path + control_path + '/position_weight')
00058     self.posture_weight = 1.0#rospy.get_param(base_path + control_path + '/posture_weight')    
00059     self.arm = opt.arm
00060   ## Callback for the interactive marker location. 
00061   #
00062   # Receives and stores the updated pose of the marker in space as the user moves it around.
00063   def interactiveMarkerLocationCallback(self, feedback):
00064 #    print "waypoint moved"
00065     if feedback.event_type == InteractiveMarkerFeedback.MOUSE_UP:
00066       ps = PoseStamped()
00067       ps.header.frame_id = feedback.header.frame_id
00068 
00069       pp = feedback.pose.position
00070       qq = feedback.pose.orientation
00071 
00072       quat = [qq.x, qq.y, qq.z, qq.w]
00073       r = tr.quaternion_to_matrix(quat)
00074       offset = np.matrix([0.0, 0., 0.]).T
00075       o_torso = r * offset
00076 
00077       ps.pose.position.x = pp.x + o_torso[0,0]
00078       ps.pose.position.y = pp.y + o_torso[1,0]
00079       ps.pose.position.z = pp.z + o_torso[2,0]
00080 
00081       ps.pose.orientation.x = qq.x
00082       ps.pose.orientation.y = qq.y
00083       ps.pose.orientation.z = qq.z
00084       ps.pose.orientation.w = qq.w
00085       
00086       self.current_goal_pose = ps
00087     
00088     self.server.applyChanges()
00089   
00090   ## Publishes the current pose of the interactive marker as the goal pose for the MPC.
00091   # Also sets the orientation weight for the controller to 0.0 (ie, position only).
00092   def goalPositionHandler(self, feedback):
00093     rospy.loginfo("MPC Teleop: Publishing new goal. Position only.")
00094     weights_msg = haptic_msgs.HapticMpcWeights()
00095     weights_msg.header.stamp = rospy.Time.now()
00096     weights_msg.position_weight = self.pos_weight
00097     weights_msg.orient_weight = 0.0
00098     weights_msg.posture_weight = 0.0
00099     self.mpc_weights_pub.publish(weights_msg) # Enable position tracking only - disable orientation by setting the weight to 0 
00100     self.goal_pos_pub.publish(self.current_goal_pose)
00101 #    self.ros_pub.publish('go_to_way_point')
00102   
00103   ## Publishes the current pose of the interactive marker as the goal pose for the MPC.
00104   # Also enables the orientation weight (ie, position and orientation).
00105   def goalPositionOrientationHandler(self, feedback):
00106     rospy.loginfo("MPC Teleop: Publishing new goal. Position and Orientation.")
00107     weights_msg = haptic_msgs.HapticMpcWeights()
00108     weights_msg.header.stamp = rospy.Time.now()
00109     weights_msg.position_weight = self.pos_weight
00110     weights_msg.orient_weight = self.orient_weight
00111     self.mpc_weights_pub.publish(weights_msg) # Enable position and orientation tracking 
00112     self.goal_pos_pub.publish(self.current_goal_pose)  
00113  #   self.ros_pub.publish('orient_to_way_point')
00114     self.add_topic_pub = rospy.Publisher('/haptic_mpc/add_taxel_array', std_msgs.msg.String)
00115     self.remove_topic_pub = rospy.Publisher('/haptic_mpc/remove_taxel_array', std_msgs.msg.String)
00116   
00117   ## Publishes the current pose of the interactive marker as the goal pose for a planner.
00118   # The planner should then 
00119   def planGoalHandler(self, feedback):  
00120     rospy.loginfo("MPC Teleop: Publishing new goal to the planner. Swapping to postural control")
00121     weights_msg = haptic_msgs.HapticMpcWeights()
00122     weights_msg.header.stamp = rospy.Time.now()
00123     weights_msg.position_weight = 0.0
00124     weights_msg.orient_weight = 0.0
00125     weights_msg.posture_weight = self.posture_weight
00126     self.mpc_weights_pub.publish(weights_msg) # Enable posture tracking 
00127     self.planner_goal_pub.publish(self.current_goal_pose)  
00128   
00129   ## Publishes an empty trajectory message. 
00130   # This has the effect of flushing the stored trajectory and goal pose from the waypoint generator, stopping the controller motion.
00131   def stopArmHandler(self, feedback):
00132     self.stop_start_epc()
00133     self.goal_traj_pub.publish(PoseArray())
00134     rospy.loginfo("Stopping MPC")
00135     
00136   ## Enable the PR2 PPS sensors by adding the topics to the skin client.
00137   def enablePps(self):
00138     self.add_topic_pub.publish('/pr2_pps_right_sensor/taxels/forces')
00139     self.add_topic_pub.publish('/pr2_pps_left_sensor/taxels/forces')
00140 
00141   ## Enable the PR2 PPS sensors by removing the topics from the skin client.
00142   def disablePps(self):
00143     self.remove_topic_pub.publish('/pr2_pps_right_sensor/taxels/forces')
00144     self.remove_topic_pub.publish('/pr2_pps_left_sensor/taxels/forces')
00145 
00146   ## Open the PR2 gripper for this arm and enable the PPS sensors (assumes this is running on the PR2).
00147   def openGripperHandler(self, feedback):
00148     self.openGripperPR2()
00149     self.enablePps()
00150 
00151   ## Close the PR2 gripper for this arm and enable the PPS sensors (assumes this is running on the PR2).
00152   def closeGripperHandler(self, feedback):
00153     self.disablePps()
00154     self.closeGripperPR2()
00155 
00156   ## Zeroes the PR2 skin (eg, to correct for calibration errors).
00157   def zeroSkinHandler(self, feedback):
00158     self.zero_gripper_pub.publish(Empty())
00159     self.zero_gripper_right_link_pub.publish(Empty())
00160     self.zero_gripper_left_link_pub.publish(Empty())
00161     self.zero_gripper_palm_pub.publish(Empty())
00162     self.zero_forearm_pub.publish(Empty())
00163     self.zero_upperarm_pub.publish(Empty())
00164     self.zero_pps_left_pub.publish(Empty())
00165     self.zero_pps_right_pub.publish(Empty())
00166 
00167     self.zero_cody_meka_skin_pub.publish(Empty())
00168     self.zero_cody_fabric_forearm_pub.publish(Empty())
00169     self.zero_cody_fabric_wrist_pub.publish(Empty())
00170   
00171   def goal_feedback_rviz_cb(self, feedback):
00172 #    print "goal_feedback_rviz"
00173     if feedback.event_type == InteractiveMarkerFeedback.MOUSE_UP:
00174       ps = PoseStamped()
00175       ps.header.frame_id = feedback.header.frame_id
00176 
00177       pp = feedback.pose.position
00178       ps.pose.position.x = pp.x
00179       ps.pose.position.y = pp.y
00180       ps.pose.position.z = pp.z
00181 
00182       qq = feedback.pose.orientation
00183       ps.pose.orientation.x = qq.x
00184       ps.pose.orientation.y = qq.y
00185       ps.pose.orientation.z = qq.z
00186       ps.pose.orientation.w = qq.w
00187 
00188       #goal_pos_pub.publish(ps)
00189     
00190     self.server.applyChanges()
00191   
00192   ## Initialise all publishers/subscribers
00193   def initComms(self, node_name):
00194     rospy.init_node(node_name)
00195     
00196     # Goal pose publisher.
00197     self.goal_pos_pub = rospy.Publisher("/haptic_mpc/goal_pose", PoseStamped, latch=True)
00198     self.mpc_weights_pub = rospy.Publisher("/haptic_mpc/weights", haptic_msgs.HapticMpcWeights)
00199     self.goal_traj_pub = rospy.Publisher("/haptic_mpc/goal_pose_array", PoseArray)
00200     self.planner_goal_pub = rospy.Publisher("/haptic_mpc/planner_goal_pose", PoseStamped, latch=True)
00201 
00202     self.add_topic_pub = rospy.Publisher("/haptic_mpc/add_taxel_array", std_msgs.msg.String)
00203     self.remove_topic_pub = rospy.Publisher("/haptic_mpc/remove_taxel_array", std_msgs.msg.String)
00204 
00205 
00206     # These are deprecated and should be cleaned up.
00207     #self.wp_pose_pub = rospy.Publisher('/teleop_rviz/command/way_point_pose', PoseStamped)
00208     #self.ros_pub = rospy.Publisher('/epc_skin/command/behavior', String)
00209     #self.pause_pub = rospy.Publisher('/epc/pause', Bool)
00210     #self.stop_pub = rospy.Publisher('/epc/stop', Bool)
00211     
00212     self.open_pub = rospy.Publisher('open_gripper', Empty)
00213     self.close_pub = rospy.Publisher('close_gripper', Empty)
00214     
00215     self.disable_pub = rospy.Publisher('/pr2_fabric_gripper_sensor/disable_sensor', Empty)
00216     self.enable_pub = rospy.Publisher('/pr2_fabric_gripper_sensor/enable_sensor', Empty)
00217     
00218     # Zero PR2 fabric skin sensors
00219     self.zero_gripper_pub = rospy.Publisher('/pr2_fabric_gripper_sensor/zero_sensor', Empty)
00220     self.zero_gripper_left_link_pub = rospy.Publisher('/pr2_fabric_gripper_left_link_sensor/zero_sensor', Empty)
00221     self.zero_gripper_right_link_pub = rospy.Publisher('/pr2_fabric_gripper_right_link_sensor/zero_sensor', Empty)
00222     self.zero_gripper_palm_pub = rospy.Publisher('/pr2_fabric_gripper_palm_sensor/zero_sensor', Empty)
00223     self.zero_forearm_pub = rospy.Publisher('/pr2_fabric_forearm_sensor/zero_sensor', Empty)
00224     self.zero_upperarm_pub = rospy.Publisher('/pr2_fabric_upperarm_sensor/zero_sensor', Empty)
00225     self.zero_pps_left_pub = rospy.Publisher('/pr2_pps_left_sensor/zero_sensor', Empty)
00226     self.zero_pps_right_pub = rospy.Publisher('/pr2_pps_right_sensor/zero_sensor', Empty)
00227     # Zero Cody skin sensors (fabric + meka)
00228     self.zero_cody_meka_skin_pub = rospy.Publisher('/skin_patch_forearm_right/zero_sensor', Empty)
00229     self.zero_cody_fabric_forearm_pub = rospy.Publisher('/fabric_forearm_sensor/zero_sensor', Empty)
00230     self.zero_cody_fabric_wrist_pub = rospy.Publisher('/fabric_wrist_sensor/zero_sensor', Empty)
00231     if self.opt.robot == 'pr2':
00232         self.gripper_action_client = actionlib.SimpleActionClient(self.arm+'_gripper_controller/gripper_action', Pr2GripperCommandAction)
00233  
00234     self.server = ims.InteractiveMarkerServer('teleop_rviz_server')
00235 
00236   ## Initialise the interactive marker based on what robot we're running on, and whether we use orientation or just position.
00237   def initMarkers(self):
00238     pos = np.matrix([0.,0.,0.]).T
00239     ps = PointStamped()
00240     ps.header.frame_id = '/torso_lift_link'
00241 
00242     #--- interactive marker for way point ---
00243     if self.opt.robot == "cody":
00244       ps.point.x = 0.4
00245       ps.point.y = -0.1
00246       ps.point.z = -0.15
00247       if self.opt.orientation:
00248         self.wp_im = imu.make_6dof_gripper(False, ps, 0.28, (1., 1., 0.,0.4), "cody")
00249         #wp_im = imu.make_6dof_marker(False, ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00250       else:
00251         self.wp_im = imu.make_3dof_marker_position(ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00252     elif self.opt.robot == "pr2":
00253       ps.point.x = 0.6
00254       ps.point.y = -0.1
00255       ps.point.z = -0.15
00256       if self.opt.orientation:
00257         #wp_im = imu.make_6dof_marker(False, ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00258         self.wp_im = imu.make_6dof_gripper(False, ps, 0.28, (1., 1., 0.,0.4))
00259       else:
00260         self.wp_im = imu.make_3dof_marker_position(ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00261     elif self.opt.robot == "sim3":
00262       ps.point.x = 0.4
00263       ps.point.y = -0.1
00264       ps.point.z = 0.15
00265       self.wp_im = imu.make_marker_position_xy(ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00266     elif self.opt.robot == "simcody":
00267       ps.point.x = 0.4
00268       ps.point.y = -0.1
00269       ps.point.z = -0.15
00270       if opt.orientation:
00271         self.wp_im = imu.make_6dof_gripper(False, ps, 0.28, (1., 1., 0.,0.4), "cody")
00272         #wp_im = imu.make_6dof_marker(False, ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00273       else:
00274         self.wp_im = imu.make_3dof_marker_position(ps, 0.15, (1., 1., 0.,0.4), 'sphere')
00275     elif self.opt.robot == "crona": 
00276       #ps.header.frame_id = "/torso_chest_link"
00277       ps.header.frame_id = "/base_link" # testing
00278       ps.point.x = 0.6
00279       ps.point.y = 0.15
00280       ps.point.z = 0.5
00281       self.wp_im = imu.make_6dof_marker(False, ps, 0.5, (1., 1., 0.,0.4), 'sphere')
00282     else:
00283       rospy.logerr('Please specify a robot type using the input arguments: -r <pr2, sim3, etc>')
00284       sys.exit()
00285   
00286     ps = PoseStamped()
00287     ps.header = self.wp_im.header
00288     ps.pose = self.wp_im.pose
00289     self.current_goal_pose = ps
00290      
00291     self.wp_im.name = 'way_point'
00292     self.wp_im.description = 'Waypoint'
00293     self.server.insert(self.wp_im, self.interactiveMarkerLocationCallback)
00294     self.server.applyChanges()
00295     
00296    #-------- gripper functions ------------
00297   def moveGripperPR2(self, dist=0.08, effort = 15):
00298     self.gripper_action_client.send_goal(Pr2GripperCommandGoal(Pr2GripperCommand(position=dist, max_effort = effort)))
00299 
00300   def openGripperPR2(self, dist=0.08):
00301     self.move_gripper(dist, -1)
00302   
00303   def closeGripperPR2(self, dist=0., effort = 15):
00304     self.move_gripper(dist, effort) 
00305     
00306    
00307   ## Initialise the menu used to control the arm behaviour.  
00308   def initMenu(self):
00309     self.wp_menu_handler = mh.MenuHandler()
00310     self.wp_menu_handler.insert('Go', callback = self.goalPositionHandler)
00311     if self.opt.robot != "sim3": # Sim can't orient in 6DOF as it's a 3DOF planar arm.
00312       self.wp_menu_handler.insert('Orient', callback = self.goalPositionOrientationHandler)
00313       
00314     self.wp_menu_handler.insert('Plan to goal', callback = self.planGoalHandler)
00315     if self.opt.robot != "sim3":  # Stop doesn't work for sim - don't use it.
00316       self.wp_menu_handler.insert('Stop', callback = self.stopArmHandler)
00317     if self.opt.robot == "pr2": # Gripper commands are specific to the PR2
00318       self.wp_menu_handler.insert('Open Gripper', callback = self.openGripperHandler)
00319       self.wp_menu_handler.insert('Close Gripper', callback = self.closeGripperHandler)
00320     if self.opt.robot != "sim3": # Sim doesn't need zeroing ever, doesn't need to be present.
00321       self.wp_menu_handler.insert('Zero Skin', callback = self.zeroSkinHandler)
00322     
00323     imu.add_menu_handler(self.wp_im, self.wp_menu_handler, self.server) 
00324   
00325   ## Start the interactive marker server (spin indefinitely).
00326   def start(self):
00327     mpc_ims.initComms("mpc_teleop_rviz")
00328     mpc_ims.initMarkers()
00329     mpc_ims.initMenu()
00330     rospy.loginfo('Haptic MPC interactive marker server started')
00331     while not rospy.is_shutdown():
00332       rospy.spin()
00333 
00334 if __name__ == '__main__':
00335   # Parse an options list specifying robot type
00336   import optparse
00337   p = optparse.OptionParser()
00338   haptic_mpc_util.initialiseOptParser(p)
00339   opt = haptic_mpc_util.getValidInput(p)
00340 
00341   # Initialise publishers/subscribers
00342   mpc_ims = MPCTeleopInteractiveMarkers(opt)
00343   mpc_ims.start()
00344   
00345 
00346 
00347 


hrl_haptic_mpc
Author(s): Jeff Hawke, Phillip Grice, Marc Killpack, Advait Jain. Advisor and Co-author: Prof. Charlie Kemp. Healthcare Robotics Lab, Georgia Tech
autogenerated on Wed Nov 27 2013 12:27:09