action.py
Go to the documentation of this file.
00001 '''The in-program representation of a programmed action.'''
00002 
00003 # ######################################################################
00004 # Imports
00005 # ######################################################################
00006 
00007 # Core ROS imports come first.
00008 import rospy
00009 
00010 # System builtins
00011 import threading
00012 
00013 # ROS builtins
00014 from geometry_msgs.msg import Vector3, PoseStamped, Quaternion
00015 from std_msgs.msg import Header, ColorRGBA, String
00016 from visualization_msgs.msg import MarkerArray, Marker
00017 import tf
00018 
00019 # Local
00020 from fetch_pbd_interaction.arm_target import ArmTarget
00021 from fetch_pbd_interaction.arm_trajectory import ArmTrajectory
00022 from fetch_pbd_interaction.grasp import Grasp
00023 from fetch_pbd_interaction.msg import ExecutionStatus, OrientationRPY, \
00024                                       ArmState, Landmark
00025 
00026 # ######################################################################
00027 # Module level constants
00028 # ######################################################################
00029 
00030 # Marker properties for little arrows drawn between consecutive primitives.
00031 LINK_MARKER_LIFETIME = rospy.Duration()
00032 LINK_SCALE = Vector3(0.01, 0.03, 0.03)
00033 LINK_COLOR = ColorRGBA(0.8, 0.8, 0.8, 0.3)  # sort of light gray
00034 
00035 # ROS topics, etc.
00036 TOPIC_MARKERS = '/fetch_pbd/visualization_marker_array'
00037 
00038 # TODO(sarah): Is this necessary?
00039 BASE_LINK = 'base_link'
00040 
00041 # ######################################################################
00042 # Classes
00043 # ######################################################################
00044 
00045 
00046 class Action:
00047     '''Holds information for one action.'''
00048 
00049     # TODO(sarah) : Probably get rid of this. Should the class get passed a
00050     # shared marker publisher from the Session or each instance should have
00051     # its own?
00052     _marker_publisher = None
00053 
00054     def __init__(self, robot, tf_listener, im_server, primitive_click_cb,
00055                  action_change_cb, action_id=None, 
00056                  grasp_suggestion_service=None,
00057                  grasp_feedback_topic=None,
00058                  external_ee_link=None):
00059         '''
00060         Args:
00061             robot (Robot) : interface to lower level robot functionality
00062             tf_listener (TransformListener)
00063             im_server (InteractiveMarkerSerever)
00064             primitive_click_cb (function(int)): The function to call when a
00065                 primitive is clicked on (normally in the GUI). The function
00066                 should take the number of the primitive
00067             action_id (int, optional): The index of this action.
00068 
00069         '''
00070         # Initialize a bunch of state.
00071         self._name = ""  # Human-friendly name for this action.
00072         self._im_server = im_server
00073         self._seq = []
00074         self._action_id = action_id
00075         self._robot = robot
00076         self._primitive_click_cb = primitive_click_cb
00077         self._action_change_cb = action_change_cb
00078         self._status = ExecutionStatus.NOT_EXECUTING
00079         self._preempt = False
00080         self._tf_listener = tf_listener
00081         self._primitive_counter = 0
00082 
00083         # Markers to connect consecutive primitives together
00084         self._link_markers = {}
00085         self._grasp_suggestion_service = grasp_suggestion_service
00086         self._grasp_feedback_topic = grasp_feedback_topic
00087         self._external_ee_link = external_ee_link
00088 
00089         # TODO(sarah): Understand this note better
00090         # NOTE(mbforbes): It appears that this is locking manipulation
00091         # of the internal sequence (self._seq). There have been race
00092         # conditions involving this (e.g. marker_click_cb(...)).
00093         #
00094         # In general, be aware the other code calling these methods
00095         # with data about this class (like how many primitives it holds)
00096         # is bad because that means the outside code is assuming that it
00097         # knows about state internal to this class, and that information
00098         # may not be true by the time the code here gets executed. This
00099         # is because there are several callbacks that trigger here so
00100         # we must reason asyncronously.
00101         #
00102         # Unless the information you have (e.g. about the number of
00103         # primitives that exist) was learned while this lock was acquired,
00104         # you cannot assume it is true.
00105         self._lock = threading.Lock()
00106         self._status_publisher = rospy.Publisher('/fetch_pbd/fetch_pbd_status',
00107                                                 String,
00108                                                 queue_size=10)
00109 
00110         if Action._marker_publisher is None:
00111             Action._marker_publisher = rospy.Publisher(TOPIC_MARKERS,
00112                                                                  MarkerArray,
00113                                                                  queue_size=10,
00114                                                                  latch=True)
00115 
00116 
00117     # ##################################################################
00118     # Instance methods: Public (API)
00119     # ##################################################################
00120 
00121     def head_busy(self):
00122         '''Returns true if head is busy
00123         
00124         Returns:
00125             bool
00126         '''
00127         for primitive in self._seq:
00128             if primitive.head_busy():
00129                 return True
00130         return False
00131 
00132     def get_action_id(self):
00133         ''' Returns action_id
00134 
00135         Returns:
00136             int
00137         '''
00138         return self._action_id
00139 
00140     def set_action_id(self, action_id):
00141         ''' Returns action_id
00142 
00143         Args:
00144             action_id (int)
00145         '''
00146         self._action_id = action_id
00147 
00148     def set_name(self, name):
00149         '''Sets human-readable name for action
00150 
00151         Args:
00152             name (string)
00153         '''
00154         self._name = name
00155 
00156     def get_name(self):
00157         '''Returns human-readable name for action
00158 
00159         Returns
00160             (string)
00161         '''
00162         return self._name
00163 
00164     def get_json(self):
00165         '''Return json for this action for saving to db
00166 
00167         Returns:
00168             dict
00169         '''
00170         json = {}
00171         json['name'] = self._name
00172         json['primitive_counter'] = self._primitive_counter
00173         json['id'] = self._action_id
00174         json['seq'] = []
00175         for primitive in self._seq:
00176             json['seq'].append(primitive.get_json())
00177 
00178         return json
00179 
00180     def build_from_json(self, json):
00181         '''Fills out action using information using json from db
00182 
00183         Args:
00184             dict : json/dict retrieved from couchdb
00185         '''
00186         enabled = True
00187         self._action_id = json['id']
00188         self._name = json['name']
00189         self._primitive_counter = json['primitive_counter']
00190         for primitive in json['seq']:
00191             if primitive.has_key('arm_target'):
00192                 target = primitive['arm_target']
00193                 primitive = ArmTarget(self._robot, self._tf_listener,
00194                               self._im_server)
00195                 primitive.build_from_json(target)
00196 
00197             elif primitive.has_key('arm_trajectory'):
00198                 target = primitive['arm_trajectory']
00199                 primitive = ArmTrajectory(self._robot, self._tf_listener,
00200                                   self._im_server)
00201                 primitive.build_from_json(target)
00202             elif primitive.has_key('grasp'):
00203                 if self._grasp_suggestion_service == "":
00204                     enabled = False
00205                 target = primitive['grasp']
00206                 primitive = Grasp(self._robot, self._tf_listener,
00207                             self._im_server, 
00208                             self._grasp_suggestion_service,
00209                             self._grasp_feedback_topic,
00210                             self._external_ee_link)
00211                 primitive.build_from_json(target)
00212 
00213             self.add_primitive(primitive, False, False)
00214 
00215         self.reset_viz()
00216         return enabled
00217 
00218     def start_execution(self):
00219         ''' Starts execution of action.
00220 
00221         This method spawns a new thread.
00222 
00223         Args:
00224             z_offset (float): Amount to add to z-values of pose
00225                 positions.
00226         '''
00227         # This will take long; create a thread.
00228         self._preempt = False
00229         self._status = ExecutionStatus.EXECUTING
00230         thread = threading.Thread(
00231             group=None,
00232             target=self._execute_action,
00233             name="action_execution_thread"
00234         )
00235         thread.start()
00236 
00237     def stop_execution(self):
00238         ''' Indicate that user wants to preempt action execution '''
00239         self._preempt = True
00240 
00241     def end_execution(self):
00242         ''' Indicate that execution status can reset to
00243             ExecutionStatus.NOT_EXECUTING
00244         '''
00245         self._status = ExecutionStatus.NOT_EXECUTING
00246 
00247     def get_status(self):
00248         '''Return execution status of action
00249 
00250         Returns:
00251             ExecutionStatus.EXECUTING|NOT_EXECUTING|...etc
00252         '''
00253         return self._status
00254 
00255     def set_status(self, status):
00256         '''Set execution status of action
00257 
00258         Args:
00259             status (ExecutionStatus.EXECUTING|NOT_EXECUTING|...etc)
00260         '''
00261         self._status = status
00262 
00263 
00264     def add_primitive(self, primitive, add_marker=True, add_name=True):
00265         '''Add primitive to action.
00266 
00267         Args:
00268             primitive (Primitive)
00269             add_marker (bool)
00270             add_name (bool)
00271         '''
00272         self._lock.acquire()
00273         rospy.loginfo("Adding primitive")
00274         if add_name:
00275             primitive.set_name("primitive_" + str(self._primitive_counter))
00276             self._primitive_counter += 1
00277         primitive.add_marker_callbacks(
00278                 self.select_primitive,  # marker_click_cb
00279                 self.delete_primitive,
00280                 self._primitive_pose_change,
00281                 self._action_change_cb
00282             )
00283         if primitive.get_ref_type() ==  ArmState.PREVIOUS_TARGET:
00284             primitive.change_ref_frame(ArmState.PREVIOUS_TARGET, Landmark())
00285         self._seq.append(primitive)
00286 
00287         if add_marker:
00288 
00289             # self._marker_visibility.append(True)
00290             primitive.show_marker()
00291             self._update_markers()
00292 
00293             self._lock.release()
00294             self.update_viz()
00295         else:
00296             # self._marker_visibility.append(False)
00297             primitive.hide_marker()
00298             self._lock.release()
00299         rospy.loginfo("Primitive added")
00300 
00301     def update_objects(self):
00302         '''For each primitive, updates the reference frames based on
00303         the locations of objects in the world
00304         '''
00305         self._lock.acquire()
00306         rospy.loginfo("Updating objects")
00307         for primitive in self._seq:
00308             if not primitive.update_ref_frames():
00309                 primitive.hide_marker()
00310             else:
00311                 primitive.show_marker()
00312         self._update_markers()
00313         self._lock.release()
00314         self._action_change_cb()
00315 
00316     def n_primitives(self):
00317         '''Returns the number of primitives in this action.
00318 
00319         Returns:
00320             int
00321         '''
00322         return len(self._seq)
00323 
00324     def reset_viz(self):
00325         '''Removes all visualization relating to this action.'''
00326         self._lock.acquire()
00327 
00328         # Destroy the primitive markers.
00329         for primitive in self._seq:
00330             primitive.hide_marker()
00331         self._im_server.clear()
00332         # Mark the links for destruction.
00333         for i in self._link_markers.keys():
00334             self._link_markers[i].action = Marker.DELETE
00335 
00336         # Publish the link destructions.
00337         m_array = MarkerArray()
00338         for i in self._link_markers.keys():
00339             m_array.markers.append(self._link_markers[i])
00340         self._marker_publisher.publish(m_array)
00341 
00342         self._link_markers = {}
00343         self._lock.release()
00344 
00345     def delete_primitive_marker(self, primitive_number):
00346         '''Delete marker with certain index
00347 
00348         Args:
00349             primitive_number (int)
00350         '''
00351         # self._marker_visibility[primitive_number] = False
00352         if self.n_primitives() > 0:
00353             primitive = self._seq[primitive_number]
00354             primitive.hide_marker()
00355 
00356     def make_primitive_marker(self, primitive_number):
00357         '''Show marker with certain index
00358 
00359         Args:
00360             primitive_number (int)
00361         '''
00362         # self._marker_visibility[primitive_number] = True
00363         primitive = self._seq[primitive_number]
00364         if not primitive.show_marker():
00365             rospy.logwarn
00366             self._status_publisher.publish(
00367                 'Not showing marker for {}'.format(primitive.get_name()) + 
00368                 ' because no matching object found. Try "record objects"?')
00369 
00370     def get_marker_visibility(self):
00371         '''Returns visibility status of primitive markers
00372 
00373         Returns:
00374             [bool]
00375         '''
00376         marker_visibility = []
00377         for primitive in self._seq:
00378             marker_visibility += [primitive.marker_visible()]
00379         return marker_visibility
00380 
00381     def select_primitive(self, primitive_number, is_selected):
00382         '''Callback for when one of the markers is clicked.
00383         Selects clicked marker and unselects others.
00384 
00385         Args:
00386             primitive_number (int)
00387             is_selected(bool): Whether the marker was
00388                 selected (True) or de-selected (False).
00389 
00390         '''
00391         self._lock.acquire()
00392         for primitive in self._seq:
00393             # If we match the one we've clicked on, select it.
00394             if primitive.get_primitive_number() == primitive_number:
00395                 primitive.select(is_selected)
00396                 primitive.update_viz()
00397             else:
00398                 # Otherwise, deselect it.
00399                 if primitive.is_control_visible():
00400                     primitive.select(False)
00401                     primitive.update_viz()
00402 
00403         # If we selected it, really click on it.
00404         if is_selected:
00405             self._primitive_click_cb(primitive_number)
00406         else:
00407             self._primitive_click_cb(-1)
00408         self._lock.release()
00409         self.update_viz()
00410 
00411     def initialize_viz(self):
00412         '''Initialize visualization.'''
00413 
00414         rospy.loginfo("Initialising viz for: {}".format(self.get_action_id()))
00415         # self._lock.acquire()
00416         # self._marker_visibility = [True] * len(self._seq)
00417         marker_visibility = []
00418         for i in range(len(self._seq)):
00419             primitive = self._seq[i]
00420 
00421             # Construct the markers.
00422             marker_visibility.append(primitive.show_marker())
00423 
00424         if False in marker_visibility:
00425             rospy.logwarn("Not showing primitive markers because " +
00426                           "no objects present")
00427             self._status_publisher.publish(
00428                         String("Not showing primitive markers because " +
00429                        "no objects present"))
00430 
00431         self._update_markers()
00432         # self._lock.release()
00433         self.update_viz()
00434 
00435 
00436     def delete_last_primitive(self):
00437         '''Deletes the last primitive of the action.'''
00438         if self.n_primitives() > 0:
00439             self.delete_primitive(len(self._seq) - 1)
00440 
00441     def is_object_required(self):
00442         '''Returns whether this action has any primitives that are relative
00443         to objects in the world (instead of absolute).
00444 
00445         Returns:
00446             bool
00447         '''
00448         is_required = False
00449         self._lock.acquire()
00450         for primitive in self._seq:
00451 
00452             is_required = primitive.is_object_required()
00453             if is_required:
00454                 break
00455         self._lock.release()
00456         return is_required
00457 
00458     def get_ref_frame_names(self):
00459         '''Returns the names of the reference frame objects for all
00460         action primitives.
00461 
00462         Returns:
00463             [str]
00464         '''
00465         self._lock.acquire()
00466         ref_frame_names = []
00467         for primitive in self._seq:
00468             ref_frame_names += [primitive.get_ref_frame_name()]
00469         self._lock.release()
00470         return ref_frame_names
00471 
00472     def get_primitive_names(self):
00473         '''Returns the names of primitives.
00474 
00475         Returns:
00476             [str]
00477         '''
00478         self._lock.acquire()
00479         names = []
00480         for primitive in self._seq:
00481             names += [primitive.get_name()]
00482         self._lock.release()
00483         return names
00484 
00485     def get_primitive_positions_orientations(self):
00486         '''Returns the positions and orientations of primitives
00487         Returns:
00488             Point[], OrientationRPY[]
00489         '''
00490         self._lock.acquire()
00491         positions = []
00492         orientations = []
00493         for primitive in self._seq:
00494             pose = primitive.get_relative_pose()
00495             quaternion = (
00496                 pose.pose.orientation.x,
00497                 pose.pose.orientation.y,
00498                 pose.pose.orientation.z,
00499                 pose.pose.orientation.w)
00500             euler = tf.transformations.euler_from_quaternion(quaternion)
00501             rpy = OrientationRPY(euler[0], euler[1], euler[2])
00502             positions += [pose.pose.position]
00503             orientations += [rpy]
00504         self._lock.release()
00505         return positions, orientations
00506 
00507     def get_primitives_editable(self):
00508         '''Returns list of whether primitive poses are editable
00509 
00510         Returns:
00511             [bool]
00512         '''
00513         self._lock.acquire()
00514         editable = []
00515         for primitive in self._seq:
00516             editable += [primitive.pose_editable()]
00517         self._lock.release()
00518         return editable
00519 
00520     def update_primitive_pose(self, primitive_number, position, orientation):
00521         '''Update pose of primitive given by primitive_number
00522 
00523         Args:
00524             primitive_number (int)
00525             position (Point)
00526             orientation (OrientationRPY)
00527         '''
00528         rospy.loginfo("Updating primitive pose")
00529         frame_id = self.get_ref_frame_names()[primitive_number]
00530         pose_stamped = PoseStamped()
00531         pose_stamped.header.frame_id = frame_id
00532         pose_stamped.pose.position = position
00533         roll = orientation.r
00534         pitch = orientation.p
00535         yaw = orientation.y
00536         quat = tf.transformations.quaternion_from_euler(roll, pitch, yaw)
00537 
00538         pose_stamped.pose.orientation = Quaternion(quat[0],
00539                                                    quat[1],
00540                                                    quat[2],
00541                                                    quat[3])
00542         primitive = self._seq[primitive_number]
00543         primitive.set_pose(pose_stamped)
00544         self._primitive_pose_change()
00545 
00546     def get_primitives(self):
00547         '''Return list of primitives
00548 
00549         Returns:
00550             [Primitive]
00551         '''
00552         # self._lock.acquire()
00553         primitives = self._seq
00554         # self._lock.release()
00555         return primitives
00556 
00557     def get_primitive(self, index):
00558         '''Returns primitive of the action based on index.
00559 
00560         Args:
00561             index (int): Index (0-based) of primitive to return.
00562 
00563         Returns:
00564             Primitive|None: Returns None if no such primitive exists.
00565         '''
00566         # NOTE(mbforbes): For this lock to be meaningful, we have to
00567         # check that the index is valid within it.
00568         self._lock.acquire()
00569         n_primitives = len(self._seq)
00570         if index < 0 or index >= n_primitives:
00571             rospy.logerr("Requested primitive index " + str(index) +
00572                          ", but only have " + str(n_primitives) +
00573                          " primitives.")
00574             requested_primitive = None
00575         else:
00576             requested_primitive = self._seq[index]
00577         self._lock.release()
00578         return requested_primitive
00579 
00580     def update_viz(self):
00581         '''Updates the visualization of the action.'''
00582         self._lock.acquire()
00583         self._update_links()
00584         m_array = MarkerArray()
00585         for i in self._link_markers.keys():
00586             m_array.markers.append(self._link_markers[i])
00587         self._marker_publisher.publish(m_array)
00588         self._lock.release()
00589 
00590     def clear(self):
00591         '''Clears the action.'''
00592         self.reset_viz()
00593         self._lock.acquire()
00594         self._seq = []
00595         self._link_markers = dict()
00596         self._lock.release()
00597 
00598     def decrease_id(self):
00599         '''Decrement the action's id by one'''
00600         self._action_id = self._action_id - 1
00601 
00602     def switch_primitive_order(self, old_index, new_index):
00603         '''Change the order of primitives in action
00604 
00605         Args:
00606             old_index (int)
00607             new_index (int)
00608         '''
00609         self._lock.acquire()
00610         primitive = self._seq.pop(old_index)
00611         self._seq.insert(new_index, primitive)
00612         relative_primitives = {}
00613         for i in range(self.n_primitives()):
00614             primitive = self._seq[i]
00615             if primitive.get_ref_type() == ArmState.PREVIOUS_TARGET:
00616                 relative_primitives[i] = primitive.get_absolute_pose()
00617             primitive.set_primitive_number(i)
00618 
00619         for key in relative_primitives:
00620             primitive = self._seq[key]
00621             if primitive.get_ref_type() == ArmState.PREVIOUS_TARGET:
00622                 if key == 0:
00623                     primitive.change_ref_frame(ArmState.ROBOT_BASE,
00624                                                         Landmark())
00625                 else:
00626                     pose = relative_primitives[key]
00627 
00628                     new_pose = self._tf_listener.transformPose(
00629                         primitive.get_ref_frame_name(),
00630                         pose)
00631                     primitive.set_pose(new_pose)
00632 
00633         self._lock.release()
00634         self.update_viz()
00635         for idx, primitive in enumerate(self._seq):
00636             if primitive.is_selected():
00637                 self._primitive_click_cb(idx)
00638         self._action_change_cb()
00639 
00640     def delete_primitive(self, to_delete):
00641         '''Deletes a primitive from the action.
00642 
00643         NOTE(mbforbes): The lock should be acquired before calling this
00644         method.
00645 
00646         Args:
00647             to_delete (int): The index of the primitive to delete.
00648         '''
00649         if self.n_primitives() == 0:
00650             rospy.logwarn("No primitives to delete")
00651             return
00652         self._lock.acquire()
00653         # if (to_delete + 1) < self.n_primitives():
00654         self._seq[to_delete].hide_marker()
00655         if self._seq[to_delete].is_selected():
00656             self._primitive_click_cb(-1)
00657         for i in range(to_delete + 1, self.n_primitives()):
00658             self._seq[i].decrease_id()
00659 
00660         if self.n_primitives() > (to_delete + 1):
00661             next_primitive = self._seq[to_delete + 1]
00662             if next_primitive.get_ref_type() == ArmState.PREVIOUS_TARGET:
00663                 if to_delete == 0:
00664                     next_primitive.change_ref_frame(ArmState.ROBOT_BASE,
00665                                                     Landmark())
00666                 else:
00667                     pose = next_primitive.get_absolute_pose()
00668 
00669                     new_pose = self._tf_listener.transformPose(
00670                         next_primitive.get_ref_frame_name(),
00671                         pose)
00672                     next_primitive.set_pose(new_pose)
00673         self._seq.pop(to_delete)
00674         # self._marker_visibility.pop(to_delete)
00675         self._lock.release()
00676         self.update_viz()
00677 
00678         self._action_change_cb()
00679 
00680     def execute_primitive(self, to_execute):
00681         '''Execute specified primitive
00682 
00683         Args:
00684             to_execute (int)
00685         '''
00686         self._seq[to_execute].execute()
00687 
00688 
00689     # ##################################################################
00690     # Static methods: Internal ("private")
00691     # ##################################################################
00692 
00693     @staticmethod
00694     def _get_link(primitive0, primitive1, marker_id):
00695         '''Returns a marker representing a link b/w two consecutive
00696         primitives (both must already exist).
00697 
00698         Args:
00699             primitive0 (Primitive)
00700             primitive1 (Primitive)
00701             marker_id (int) : id for link marker between to primitives
00702 
00703         Returns:
00704             Marker|None
00705         '''
00706         start = primitive0.get_absolute_marker_position(use_final=True)
00707         end = primitive1.get_absolute_marker_position(use_final=False)
00708         if start == end:
00709             return None
00710         elif not start is None and not end is None:
00711             return Marker(type=Marker.ARROW,
00712                           id=marker_id,
00713                           lifetime=LINK_MARKER_LIFETIME,
00714                           scale=LINK_SCALE,
00715                           header=Header(frame_id=BASE_LINK),
00716                           color=LINK_COLOR,
00717                           points=[start, end])
00718         else:
00719             return None
00720 
00721     # ##################################################################
00722     # Instance methods: Internal ("private")
00723     # ##################################################################
00724 
00725     def _primitive_pose_change(self):
00726         '''Update links when primitive pose changes'''
00727         for primitive in self._seq:
00728             primitive.update_viz()
00729         # self._lock.release()
00730         self.update_viz()
00731 
00732     def _execute_action(self):
00733         ''' Function to replay the demonstrated action.'''
00734         primitive = self.get_primitive(0)
00735 
00736         rospy.loginfo("Starting to execute action!")
00737 
00738         # Make sure the primitive exists.
00739         if primitive is None:
00740             rospy.logwarn("First primitive does not exist.")
00741             self._status = ExecutionStatus.CONDITION_ERROR
00742             self._status_publisher.publish(
00743                 String("First primitive does not exist."))
00744         # Check if the very first precondition is met.
00745         # Not actually implemented right now.
00746         elif not self._check_pre_conditions():
00747             self._status = ExecutionStatus.CONDITION_ERROR
00748         else:
00749             # Check that all parts of the action are reachable
00750             if not self._is_action_reachable():
00751                 rospy.logwarn("Problem finding IK solutions.")
00752                 self._status = ExecutionStatus.NO_IK
00753                 self._status_publisher.publish(
00754                     String("Problem finding IK solutions."))
00755             else:
00756                 self._loop_through_primitives()
00757 
00758             self._robot.reset_arm_movement_history()
00759 
00760             # If we haven't been preempted, we now report success.
00761             if self._status == ExecutionStatus.EXECUTING:
00762                 self._status = ExecutionStatus.SUCCEEDED
00763                 rospy.loginfo("Action execution has succeeded.")
00764 
00765     def _check_pre_conditions(self):
00766         '''Loop through primitives and make sure all of their 
00767         preconditions are met
00768 
00769         Returns:
00770             bool
00771         '''
00772         for i in range(self.n_primitives()):
00773             rospy.loginfo("checking preconditions " + str(i))
00774             primitive = self.get_primitive(i)
00775 
00776             # Make sure primitive exists.
00777             if primitive is None:
00778                 rospy.logwarn("Primitive " + str(primitive.get_name()) + " does not exist.")
00779                 self._status = ExecutionStatus.CONDITION_ERROR
00780                 self._status_publisher.publish(
00781                     String("Primitive " + str(primitive.get_name()) + " does not exist."))
00782 
00783                 return False
00784             # Check that preconditions are met (doesn't do anything right now)
00785             else:
00786                 success, msg = primitive.check_pre_condition()
00787                 if not success:
00788                     rospy.logwarn(
00789                         "\tPreconditions of primitive " + str(primitive.get_name()) + " are not " +
00790                         "satisfied. " + msg)
00791                     self._status = ExecutionStatus.CONDITION_ERROR
00792                     self._status_publisher.publish(
00793                         String("Preconditions of primitive " + str(primitive.get_name()) +
00794                             " are not satisfied. " + msg))
00795                     return False
00796         return True
00797 
00798     def _is_action_reachable(self):
00799         '''Make sure that action is possible to execute entire action'''
00800         for i in range(len(self._seq)):
00801             primitive = self.get_primitive(i)
00802             if primitive is None:
00803                 rospy.logwarn("Primitive " + str(i) + " does not exist.")
00804                 break
00805             else:
00806                 if not primitive.is_reachable():
00807                     return False
00808         return True
00809 
00810     def _loop_through_primitives(self):
00811         '''Goes through the primitives of the current action and moves to
00812         each.
00813         '''
00814         # Go over primitives of the action
00815         for i in range(self.n_primitives()):
00816             rospy.loginfo("Executing primitive " + str(i))
00817             primitive = self.get_primitive(i)
00818 
00819             # Make sure primitive exists.
00820             if primitive is None:
00821                 rospy.logwarn("Primitive " + str(i) + " does not exist.")
00822                 self._status = ExecutionStatus.CONDITION_ERROR
00823                 self._status_publisher.publish(
00824                     String("Primitive " + str(i) + " does not exist."))
00825                 break
00826             # Check that preconditions are met (doesn't do anything right now)
00827             else:
00828 
00829                 # Try executing.
00830                 self._status = ExecutionStatus.EXECUTING
00831                 success, msg = primitive.execute()
00832                 if not success:
00833                     self._status = ExecutionStatus.NO_IK
00834                     self._status_publisher.publish(
00835                         String(msg))
00836                     break
00837 
00838                 # Finished executing; check that postconditions are met
00839                 success, msg = primitive.check_post_condition()
00840                 if success:
00841                     rospy.loginfo('\tPost-conditions of the action are met.')
00842                 else:
00843                     rospy.logwarn(
00844                         "\tPost-conditions of action primitive " + str(i) +
00845                         " are not satisfied. Aborting.")
00846                     self._status = ExecutionStatus.CONDITION_ERROR
00847                     self._status_publisher.publish(
00848                         String("Post-conditions of action primitive " +
00849                             str(i) + " are not satisfied. " + msg))
00850                     break
00851 
00852             # Perhaps the execution was pre-empted by the user. Check
00853             # this before continuing onto the next primitive.
00854             if self._preempt:
00855                 rospy.logwarn("\tExecution preempted by user.")
00856                 self._status = ExecutionStatus.PREEMPTED
00857                 self._status_publisher.publish(
00858                     String("Execution preempted by user."))
00859                 break
00860 
00861             # Primitive completed successfully.
00862             rospy.loginfo("\tPrimitive " + str(i) + " of action is complete.")
00863 
00864     def _update_markers(self):
00865         '''Updates the markers after a change.'''
00866         rospy.loginfo("Updating viz markers")
00867         for primitive in self._seq:
00868             primitive.update_viz()
00869 
00870     def _update_links(self):
00871         '''Updates the visualized links b/w action primitives.'''
00872         current_num_links = len(self._link_markers)
00873         new_num_links = len(self._seq) - 1
00874 
00875         self._link_markers = {}
00876         if new_num_links >= 1:
00877             for i in range(new_num_links):
00878                 link_marker = Action._get_link(self._seq[i],
00879                                            self._seq[i + 1],
00880                                            i)
00881                 if not link_marker is None:
00882                     self._link_markers[i] = link_marker
00883             if (current_num_links - new_num_links) > 0:
00884                 for i in range(new_num_links, current_num_links):
00885                     self._link_markers[i] = Marker(id=i, action=Marker.DELETE)
00886                     
00887         else:
00888             marker = Marker()
00889             marker.id = 0
00890             self._link_markers[0] = marker
00891             self._link_markers[0].action = Marker.DELETE


fetch_pbd_interaction
Author(s): Sarah Elliott
autogenerated on Thu Jun 6 2019 18:27:21