5 from rospkg
import RosPack, ResourceNotFound
7 from flexbe_core
import Logger, BehaviorLibrary
8 from std_msgs.msg
import String
15 import xml.etree.ElementTree
as ET
27 self.
_sub = rospy.Subscriber(
"flexbe/request_behavior", BehaviorRequest, self.
_callback)
30 self.
_pub = rospy.Publisher(
"flexbe/start_behavior", BehaviorSelection, queue_size=100)
31 self.
_status_pub = rospy.Publisher(
"flexbe/status", BEStatus, queue_size=100)
33 self.
_mirror_pub = rospy.Publisher(
"flexbe/mirror/structure", ContainerStructure, queue_size=100)
38 rospy.loginfo(
"%d behaviors available, ready for start request." % self._behavior_lib.count_behaviors())
41 if msg.code
in [BEStatus.READY, BEStatus.FINISHED, BEStatus.FAILED, BEStatus.ERROR]:
42 self._ready_event.set()
45 be_id, behavior = self._behavior_lib.find_behavior(msg.behavior_name)
47 Logger.logerr(
"Did not find behavior with requested name: %s" % msg.behavior_name)
48 self._status_pub.publish(BEStatus(code=BEStatus.ERROR))
51 rospy.loginfo(
"Request for behavior " + behavior[
"name"])
53 be_selection = BehaviorSelection()
54 be_selection.behavior_id = be_id
55 be_selection.autonomy_level = msg.autonomy_level
57 for k, v
in zip(msg.arg_keys, msg.arg_values):
58 if k.startswith(
'/YAML:'):
59 key = k.replace(
'/YAML:',
'/', 1)
60 path = v.split(
':')[0]
62 if path.startswith(
'~')
or path.startswith(
'/'):
63 yamlpath = os.path.expanduser(path)
65 yamlpath = os.path.join(self._rp.get_path(path.split(
'/')[0]),
'/'.join(path.split(
'/')[1:]))
66 with open(yamlpath,
'r') as f: 67 content = getattr(yaml, 'full_load', yaml.load)(f)
68 if ns !=
'' and ns
in content:
70 be_selection.arg_keys.append(key)
71 be_selection.arg_values.append(yaml.dump(content))
73 be_selection.arg_keys.append(k)
74 be_selection.arg_values.append(v)
75 except Exception
as e:
76 rospy.logwarn(
'Failed to parse and substitute behavior arguments, will use direct input.\n%s' % str(e))
77 be_selection.arg_keys = msg.arg_keys
78 be_selection.arg_values = msg.arg_values
81 self._ready_event.wait()
83 be_structure = ContainerStructure()
84 be_structure.containers = msg.structure
87 be_filepath_new = self._behavior_lib.get_sourcecode_filepath(be_id)
88 except ResourceNotFound:
89 rospy.logerr(
"Could not find behavior package '%s'" % (behavior[
"package"]))
90 rospy.loginfo(
"Have you updated your ROS_PACKAGE_PATH after creating the behavior?")
93 with open(be_filepath_new,
"r") as f: 94 be_content_new = f.read() 96 be_filepath_old = self._behavior_lib.get_sourcecode_filepath(be_id, add_tmp=True)
97 if not os.path.isfile(be_filepath_old):
98 be_selection.behavior_checksum = zlib.adler32(be_content_new.encode()) & 0x7fffffff
99 if msg.autonomy_level != 255:
100 be_structure.behavior_id = be_selection.behavior_checksum
101 self._mirror_pub.publish(be_structure)
102 self._pub.publish(be_selection)
103 rospy.loginfo(
"No changes to behavior version.")
106 with open(be_filepath_old,
"r") as f: 107 be_content_old = f.read() 109 sqm = difflib.SequenceMatcher(a=be_content_old, b=be_content_new) 110 diffs = [x[1] for x
in sqm.get_grouped_opcodes(0)]
111 for opcode, a0, a1, b0, b1
in diffs:
112 content = be_content_new[b0:b1]
113 be_selection.modifications.append(BehaviorModification(a0, a1, content))
115 be_selection.behavior_checksum = zlib.adler32(be_content_new.encode()) & 0x7fffffff
116 if msg.autonomy_level != 255:
117 be_structure.behavior_id = be_selection.behavior_checksum
118 self._mirror_pub.publish(be_structure)
120 self._pub.publish(be_selection)
126 Logger.logwarn(
'FlexBE App needs to be updated!\n' \
127 +
'Require at least version %s, but have %s\n' % (BehaviorLauncher.MIN_VERSION, msg.data) \
128 +
'Please run a "git pull" in "roscd flexbe_app".')
133 for n
in reversed(v.split(
'.')):
134 result += int(n) * offset