behavior_action_server.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 import rospy
00003 import actionlib
00004 
00005 from flexbe_msgs.msg import *
00006 from rospkg import RosPack
00007 from flexbe_core import BehaviorLibrary
00008 
00009 from std_msgs.msg import String, Empty
00010 
00011 import zlib
00012 import difflib
00013 import os
00014 import xml.etree.ElementTree as ET
00015 
00016 
00017 class BehaviorActionServer(object):
00018 
00019         def __init__(self):
00020                 self._behavior_started = False
00021                 self._current_state = None
00022                 self._engine_status = None
00023 
00024                 self._pub = rospy.Publisher('flexbe/start_behavior', BehaviorSelection, queue_size=100)
00025                 self._preempt_pub = rospy.Publisher('flexbe/command/preempt', Empty, queue_size=100)
00026                 self._status_sub = rospy.Subscriber('flexbe/status', BEStatus, self._status_cb)
00027                 self._state_sub = rospy.Subscriber('flexbe/behavior_update', String, self._state_cb)
00028 
00029                 self._as = actionlib.SimpleActionServer('flexbe/execute_behavior', BehaviorExecutionAction, self._execute_cb, False)
00030 
00031                 self._rp = RosPack()
00032                 self._behavior_lib = BehaviorLibrary()
00033 
00034                 # start action server after all member variables have been initialized
00035                 self._as.start()
00036 
00037                 rospy.loginfo("%d behaviors available, ready for start request." % self._behavior_lib.count_behaviors())
00038 
00039 
00040         def _execute_cb(self, goal):
00041                 rospy.loginfo('Received a new request to start behavior: %s' % goal.behavior_name)
00042                 be_id, behavior = self._behavior_lib.find_behavior(goal.behavior_name)
00043                 if be_id is None:
00044                         Logger.logerr("Did not find behavior with requested name: %s" % goal.behavior_name)
00045                         self._as.set_preempted()
00046                         return
00047 
00048                 be_selection = BehaviorSelection()
00049                 be_selection.behavior_id = be_id
00050                 be_selection.autonomy_level = 255
00051                 be_selection.arg_keys = goal.arg_keys
00052                 be_selection.arg_values = goal.arg_values
00053                 be_selection.input_keys = goal.input_keys
00054                 be_selection.input_values = goal.input_values
00055 
00056                 # check for local modifications of the behavior to send them to the onboard behavior
00057                 be_filepath_new = os.path.join(self._rp.get_path(behavior["package"]), 'src/' + behavior["package"] + '/' + behavior["file"] + '.py')
00058                 with open(be_filepath_new, "r") as f:
00059                         be_content_new = f.read()
00060 
00061                 be_filepath_old = os.path.join(self._rp.get_path(behavior["package"]), 'src/' + behavior["package"] + '/' + behavior["file"] + '_tmp.py')
00062                 if not os.path.isfile(be_filepath_old):
00063                         be_selection.behavior_checksum = zlib.adler32(be_content_new)
00064                 else:
00065                         with open(be_filepath_old, "r") as f:
00066                                 be_content_old = f.read()
00067 
00068                         sqm = difflib.SequenceMatcher(a=be_content_old, b=be_content_new)
00069                         diffs = [x[1] for x in sqm.get_grouped_opcodes(0)]
00070                         for opcode, a0, a1, b0, b1 in diffs:
00071                                 content = be_content_new[b0:b1]
00072                                 be_selection.modifications.append(BehaviorModification(a0, a1, content))
00073 
00074                         be_selection.behavior_checksum = zlib.adler32(be_content_new)
00075 
00076                 # reset state before starting new behavior
00077                 self._engine_status = None
00078                 self._current_state = None
00079                 self._behavior_started = False
00080 
00081                 # start new behavior
00082                 self._pub.publish(be_selection)
00083 
00084                 try:
00085                         rate = rospy.Rate(10)
00086                         while not rospy.is_shutdown():
00087                                 if self._current_state is not None:
00088                                         self._as.publish_feedback(BehaviorExecutionFeedback(self._current_state))
00089                                         self._current_state = None
00090 
00091                                 # check if goal has been preempted first
00092                                 if self._as.is_preempt_requested():
00093                                         rospy.loginfo('Behavior execution preempt requested!')
00094                                         self._preempt_pub.publish()
00095                                         rate.sleep()
00096                                         self._as.set_preempted('')
00097                                         break
00098 
00099                                 if self._engine_status is None:
00100                                         rospy.logdebug_throttle(1, 'No behavior engine status received yet. Waiting for it...')
00101                                         rate.sleep()
00102                                         continue
00103 
00104                                 if self._engine_status.code == BEStatus.ERROR:
00105                                         rospy.logerr('Failed to run behavior! Check onboard terminal for further infos.')
00106                                         rate.sleep()
00107                                         self._as.set_aborted('')
00108                                         break
00109 
00110                                 if not self._behavior_started:
00111                                         rospy.logdebug_throttle(1, 'Behavior execution has not yet started. Waiting for it...')
00112                                         rate.sleep()
00113                                         continue
00114 
00115                                 if self._engine_status.code == BEStatus.FINISHED:
00116                                         result = self._engine_status.args[0] \
00117                                                 if len(self._engine_status.args) >= 1 else ''
00118                                         rospy.loginfo('Finished behavior execution with result "%s"!' % result)
00119                                         self._as.set_succeeded(BehaviorExecutionResult(outcome=result))
00120                                         break
00121 
00122                                 if self._engine_status.code == BEStatus.FAILED:
00123                                         rospy.logerr('Behavior execution failed in state %s!' % str(self._current_state))
00124                                         rate.sleep()
00125                                         self._as.set_aborted('')
00126                                         break
00127 
00128                                 rate.sleep()
00129 
00130                         rospy.loginfo('Ready for next behavior start request.')
00131 
00132                 except rospy.ROSInterruptException:
00133                         pass # allow clean exit on ROS shutdown
00134 
00135 
00136         def _status_cb(self, msg):
00137                 self._engine_status = msg
00138 
00139                 # check for behavior start here, to avoid race condition between execute_cb and status_cb threads
00140                 if not self._behavior_started and self._engine_status.code == BEStatus.STARTED:
00141                         self._behavior_started = True
00142                         rospy.loginfo('Behavior execution has started!')
00143 
00144 
00145         def _state_cb(self, msg):
00146                 self._current_state = msg.data
00147                 rospy.loginfo('Current state: %s' % self._current_state)


flexbe_widget
Author(s): Philipp Schillinger
autogenerated on Thu Jun 6 2019 19:32:34