00001 '''The in-program representation of a programmed action.'''
00002
00003
00004
00005
00006
00007
00008 import rospy
00009
00010
00011 import threading
00012
00013
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
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
00028
00029
00030
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)
00034
00035
00036 TOPIC_MARKERS = '/fetch_pbd/visualization_marker_array'
00037
00038
00039 BASE_LINK = 'base_link'
00040
00041
00042
00043
00044
00045
00046 class Action:
00047 '''Holds information for one action.'''
00048
00049
00050
00051
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
00071 self._name = ""
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
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
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
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
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
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,
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
00290 primitive.show_marker()
00291 self._update_markers()
00292
00293 self._lock.release()
00294 self.update_viz()
00295 else:
00296
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
00329 for primitive in self._seq:
00330 primitive.hide_marker()
00331 self._im_server.clear()
00332
00333 for i in self._link_markers.keys():
00334 self._link_markers[i].action = Marker.DELETE
00335
00336
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
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
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
00394 if primitive.get_primitive_number() == primitive_number:
00395 primitive.select(is_selected)
00396 primitive.update_viz()
00397 else:
00398
00399 if primitive.is_control_visible():
00400 primitive.select(False)
00401 primitive.update_viz()
00402
00403
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
00416
00417 marker_visibility = []
00418 for i in range(len(self._seq)):
00419 primitive = self._seq[i]
00420
00421
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
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
00553 primitives = self._seq
00554
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
00567
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
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
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
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
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
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
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
00745
00746 elif not self._check_pre_conditions():
00747 self._status = ExecutionStatus.CONDITION_ERROR
00748 else:
00749
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
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
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
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
00815 for i in range(self.n_primitives()):
00816 rospy.loginfo("Executing primitive " + str(i))
00817 primitive = self.get_primitive(i)
00818
00819
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
00827 else:
00828
00829
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
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
00853
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
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