6 from rospkg
import RosPack
7 from flexbe_core
import BehaviorLibrary
9 from std_msgs.msg
import String, Empty
15 import xml.etree.ElementTree
as ET
26 self.
_pub = rospy.Publisher(
'flexbe/start_behavior', BehaviorSelection, queue_size=100)
27 self.
_preempt_pub = rospy.Publisher(
'flexbe/command/preempt', Empty, queue_size=100)
32 self._as.register_preempt_callback(self.
_preempt_cb)
33 self._as.register_goal_callback(self.
_goal_cb)
41 rospy.loginfo(
"%d behaviors available, ready for start request." % self._behavior_lib.count_behaviors())
45 if self._as.is_active()
or not self._as.is_new_goal_available():
47 goal = self._as.accept_new_goal()
48 rospy.loginfo(
'Received a new request to start behavior: %s' % goal.behavior_name)
49 be_id, behavior = self._behavior_lib.find_behavior(goal.behavior_name)
51 rospy.logerr(
"Deny goal: Did not find behavior with requested name %s" % goal.behavior_name)
52 self._as.set_preempted()
55 be_selection = BehaviorSelection()
56 be_selection.behavior_id = be_id
57 be_selection.autonomy_level = 255
59 for k, v
in zip(goal.arg_keys, goal.arg_values):
60 if v.startswith(
'file://'):
61 v = v.replace(
'file://',
'', 1)
62 path = v.split(
':')[0]
63 if len(v.split(
':')) > 1:
67 if path.startswith(
'~')
or path.startswith(
'/'):
68 filepath = os.path.expanduser(path)
70 filepath = os.path.join(self._rp.get_path(path.split(
'/')[0]),
'/'.join(path.split(
'/')[1:]))
71 with open(filepath,
'r') as f: 74 content = getattr(yaml,
'full_load', yaml.load)(content)
77 content = yaml.dump(content)
78 be_selection.arg_keys.append(k)
79 be_selection.arg_values.append(content)
81 be_selection.arg_keys.append(k)
82 be_selection.arg_values.append(v)
83 except Exception
as e:
84 rospy.logwarn(
'Failed to parse and substitute behavior arguments, will use direct input.\n%s' % str(e))
85 be_selection.arg_keys = goal.arg_keys
86 be_selection.arg_values = goal.arg_values
87 be_selection.input_keys = goal.input_keys
88 be_selection.input_values = goal.input_values
91 be_filepath_new = self._behavior_lib.get_sourcecode_filepath(be_id)
92 with open(be_filepath_new,
"r") as f: 93 be_content_new = f.read() 95 be_filepath_old = self._behavior_lib.get_sourcecode_filepath(be_id, add_tmp=True)
96 if not os.path.isfile(be_filepath_old):
97 be_selection.behavior_checksum = zlib.adler32(be_content_new.encode()) & 0x7fffffff
99 with open(be_filepath_old,
"r") as f: 100 be_content_old = f.read() 102 sqm = difflib.SequenceMatcher(a=be_content_old, b=be_content_new) 103 diffs = [x[1] for x
in sqm.get_grouped_opcodes(0)]
104 for opcode, a0, a1, b0, b1
in diffs:
105 content = be_content_new[b0:b1]
106 be_selection.modifications.append(BehaviorModification(a0, a1, content))
108 be_selection.behavior_checksum = zlib.adler32(be_content_new.encode()) & 0x7fffffff
116 self._pub.publish(be_selection)
123 self._preempt_pub.publish()
124 rospy.loginfo(
'Behavior execution preempt requested!')
128 if msg.code == BEStatus.ERROR:
129 rospy.logerr(
'Failed to run behavior! Check onboard terminal for further infos.')
130 self._as.set_aborted(
'')
137 rospy.loginfo(
'Behavior execution has started!')
146 rospy.logwarn(
'Ignored status because behavior id differed ({} vs {})!'.format(msg.behavior_id, self.
_active_behavior_id))
148 elif msg.code == BEStatus.FINISHED:
149 result = msg.args[0]
if len(msg.args) >= 1
else '' 150 rospy.loginfo(
'Finished behavior execution with result "%s"!' % result)
151 self._as.set_succeeded(BehaviorExecutionResult(outcome=result))
154 elif msg.code == BEStatus.FAILED:
155 rospy.logerr(
'Behavior execution failed in state %s!' % str(self.
_current_state))
156 self._as.set_aborted(
'')
163 if self._as.is_active():
164 self._as.publish_feedback(BehaviorExecutionFeedback(self.
_current_state))