Go to the documentation of this file.00001
00002 import os
00003 import rospy
00004 from rospkg import RosPack
00005 import xml.etree.ElementTree as ET
00006 import zlib
00007
00008
00009 '''
00010 Created on 10.01.2017
00011
00012 @author: Philipp Schillinger
00013 '''
00014
00015 class BehaviorLibrary(object):
00016 '''
00017 Provides a list of all known behavior manifests.
00018 '''
00019
00020 def __init__(self):
00021 self._rp = RosPack()
00022 self._behavior_lib = dict()
00023 self.parse_packages()
00024
00025
00026 def parse_packages(self):
00027 """
00028 Parses all ROS packages to update the internal behavior library.
00029 """
00030 self._behavior_lib = dict()
00031 for pkg in self._rp.list():
00032 for export in self._rp._load_manifest(pkg).exports:
00033 if export.tag == "flexbe_behaviors":
00034 self._add_behavior_manifests(self._rp.get_path(pkg), pkg)
00035
00036
00037 def _add_behavior_manifests(self, path, pkg=None):
00038 """
00039 Recursively add all behavior manifests in the given folder to the internal library.
00040 If a package name is specified, only manifests referring to this package are added.
00041
00042 @type path: string
00043 @param path: Path of the folder to be traversed.
00044
00045 @type pkg: string
00046 @param pkg: Optional name of a package to only add manifests referring to this package.
00047 """
00048 for entry in os.listdir(path):
00049 entry_path = os.path.join(path, entry)
00050 if os.path.isdir(entry_path):
00051 self._add_behavior_manifests(entry_path, pkg)
00052 elif entry.endswith(".xml") and not entry.startswith("#"):
00053 m = ET.parse(entry_path).getroot()
00054
00055 if m.tag != "behavior" \
00056 or len(m.findall(".//executable")) == 0 \
00057 or m.find("executable").get("package_path") is None \
00058 or len(m.find("executable").get("package_path").split(".")) != 2:
00059 continue;
00060 e = m.find("executable")
00061 if pkg is not None and e.get("package_path").split(".")[0] != pkg:
00062 continue
00063 be_id = zlib.adler32(e.get("package_path"))
00064 self._behavior_lib[be_id] = {
00065 "name": m.get("name"),
00066 "package": e.get("package_path").split(".")[0],
00067 "file": e.get("package_path").split(".")[1],
00068 "class": e.get("class")
00069 }
00070
00071
00072 def get_behavior(self, be_id):
00073 """
00074 Provides the library entry corresponding to the given ID.
00075
00076 @type be_id: int
00077 @param be_id: Behavior ID to look up.
00078
00079 @return Corresponding library entry or None if not found.
00080 """
00081 try:
00082 return self._behavior_lib[be_id]
00083 except KeyError:
00084 rospy.logwarn("Did not find ID %d in libary, updating..." % be_id)
00085 self.parse_packages()
00086 return self._behavior_lib.get(be_id, None)
00087
00088
00089 def find_behavior(self, be_name):
00090 """
00091 Searches for a behavior with the given name and returns it along with its ID.
00092
00093 @type be_name: string
00094 @param be_name: Behavior ID to look up.
00095
00096 @return Tuple (be_id, be_entry) corresponding to the name or (None, None) if not found.
00097 """
00098 find = lambda: next((id, be) for (id, be) in self._behavior_lib.items() if be["name"] == be_name)
00099 try:
00100 return find()
00101 except StopIteration:
00102 rospy.logwarn("Did not find behavior '%s' in libary, updating..." % be_name)
00103 self.parse_packages()
00104 return find()
00105
00106
00107 def count_behaviors(self):
00108 """
00109 Counts the available behaviors.
00110
00111 @return Number of behaviors.
00112 """
00113 return len(self._behavior_lib)
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135