behavior_launcher.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 from flexbe_msgs.msg import *
5 from rospkg import RosPack, ResourceNotFound
6 
7 from flexbe_core import Logger, BehaviorLibrary
8 from std_msgs.msg import String
9 
10 import pickle
11 import zlib
12 import difflib
13 import os
14 import yaml
15 import xml.etree.ElementTree as ET
16 
17 class BehaviorLauncher(object):
18 
19  MIN_VERSION = '2.2.0'
20 
21  def __init__(self):
22  Logger.initialize()
23 
24  self._sub = rospy.Subscriber("flexbe/request_behavior", BehaviorRequest, self._callback)
25  self._version_sub = rospy.Subscriber("flexbe/ui_version", String, self._version_callback)
26 
27  self._pub = rospy.Publisher("flexbe/start_behavior", BehaviorSelection, queue_size=100)
28  self._status_pub = rospy.Publisher("flexbe/status", BEStatus, queue_size=100)
29  self._mirror_pub = rospy.Publisher("flexbe/mirror/structure", ContainerStructure, queue_size=100)
30 
31  self._rp = RosPack()
32  self._behavior_lib = BehaviorLibrary()
33 
34  rospy.loginfo("%d behaviors available, ready for start request." % self._behavior_lib.count_behaviors())
35 
36 
37  def _callback(self, msg):
38  be_id, behavior = self._behavior_lib.find_behavior(msg.behavior_name)
39  if be_id is None:
40  Logger.logerr("Did not find behavior with requested name: %s" % msg.behavior_name)
41  self._status_pub.publish(BEStatus(code=BEStatus.ERROR))
42  return
43 
44  rospy.loginfo("Request for behavior " + behavior["name"])
45 
46  be_selection = BehaviorSelection()
47  be_selection.behavior_id = be_id
48  be_selection.autonomy_level = msg.autonomy_level
49  try:
50  for k, v in zip(msg.arg_keys, msg.arg_values):
51  if k.startswith('/YAML:'):
52  key = k.replace('/YAML:', '/', 1)
53  path = v.split(':')[0]
54  ns = v.split(':')[1]
55  if path.startswith('~') or path.startswith('/'):
56  yamlpath = os.path.expanduser(path)
57  else:
58  yamlpath = os.path.join(self._rp.get_path(path.split('/')[0]), '/'.join(path.split('/')[1:]))
59  with open(yamlpath, 'r') as f:
60  content = yaml.load(f)
61  if ns != '' and ns in content:
62  content = content[ns]
63  be_selection.arg_keys.append(key)
64  be_selection.arg_values.append(yaml.dump(content))
65  else:
66  be_selection.arg_keys.append(k)
67  be_selection.arg_values.append(v)
68  except Exception as e:
69  rospy.logwarn('Failed to parse and substitute behavior arguments, will use direct input.\n%s' % str(e))
70  be_selection.arg_keys = msg.arg_keys
71  be_selection.arg_values = msg.arg_values
72 
73  be_structure = ContainerStructure()
74  be_structure.containers = msg.structure
75 
76  try:
77  be_filepath_new = os.path.join(self._rp.get_path(behavior["package"]), 'src/' + behavior["package"] + '/' + behavior["file"] + '.py')
78  except ResourceNotFound:
79  rospy.logerr("Could not find behavior package '%s'" % (behavior["package"]))
80  rospy.loginfo("Have you updated your ROS_PACKAGE_PATH after creating the behavior?")
81  return
82 
83  with open(be_filepath_new, "r") as f:
84  be_content_new = f.read()
85 
86  be_filepath_old = os.path.join(self._rp.get_path(behavior["package"]), 'src/' + behavior["package"] + '/' + behavior["file"] + '_tmp.py')
87  if not os.path.isfile(be_filepath_old):
88  be_selection.behavior_checksum = zlib.adler32(be_content_new)
89  if msg.autonomy_level != 255:
90  be_structure.behavior_id = be_selection.behavior_checksum
91  self._mirror_pub.publish(be_structure)
92  self._pub.publish(be_selection)
93  rospy.loginfo("No changes to behavior version.")
94  return
95 
96  with open(be_filepath_old, "r") as f:
97  be_content_old = f.read()
98 
99  sqm = difflib.SequenceMatcher(a=be_content_old, b=be_content_new)
100  diffs = [x[1] for x in sqm.get_grouped_opcodes(0)]
101  for opcode, a0, a1, b0, b1 in diffs:
102  content = be_content_new[b0:b1]
103  be_selection.modifications.append(BehaviorModification(a0, a1, content))
104 
105  be_selection.behavior_checksum = zlib.adler32(be_content_new)
106  if msg.autonomy_level != 255:
107  be_structure.behavior_id = be_selection.behavior_checksum
108  self._mirror_pub.publish(be_structure)
109 
110  self._pub.publish(be_selection)
111 
112  def _version_callback(self, msg):
113  vui = self._parse_version(msg.data)
114  vex = self._parse_version(BehaviorLauncher.MIN_VERSION)
115  if vui < vex:
116  Logger.logwarn('FlexBE App needs to be updated!\n' \
117  + 'Require at least version %s, but have %s\n' % (BehaviorLauncher.MIN_VERSION, msg.data) \
118  + 'Please run a "git pull" in "roscd flexbe_app".')
119 
120  def _parse_version(self, v):
121  result = 0
122  offset = 1
123  for n in reversed(v.split('.')):
124  result += int(n) * offset
125  offset *= 100
126  return result


flexbe_widget
Author(s): Philipp Schillinger
autogenerated on Wed Jun 5 2019 21:52:10