reimplemented roslib.find_resources and find_node. Need to move to roslaunch now

This commit is contained in:
Ken Conley 2012-01-07 02:41:23 +00:00
parent 6c28b0f4d8
commit e62f78bfd5
1 changed files with 105 additions and 99 deletions

View File

@ -386,25 +386,19 @@ def list_pkgs_by_path(path, packages=None, cache=None, env=None):
return packages
def find_node(pkg, node_type, ros_root=None, ros_package_path=None):
def find_node(pkg, node_type, rospack=None, catkin_packages_cache=None):
"""
Locate the executable that implements the node
@param node_type: type of node
@type node_type: str
@param ros_root: if specified, override ROS_ROOT
@type ros_root: str
@param ros_package_path: if specified, override ROS_PACKAGE_PATH
@type ros_package_path: str
@return: path to node or None if node is not in the package
@rtype: str
@raise roslib.packages.InvalidROSPkgException: If package does not exist
:param node_type: type of node, ``str``
:returns: path to node or None if node is not in the package ``str``
:raises: :exc:rospkg.ResourceNotFound` If package does not exist
"""
d = get_pkg_dir(pkg, required=True, \
ros_root=ros_root, ros_package_path=ros_package_path)
#UNIXONLY: (partial) slowly supporting Windows here
if rospack is None:
rospack = rospkg.RosPack()
# TODO: figure out how to generalize find_resource to take multiple resource name options
if sys.platform in ['win32', 'cygwin']:
# Windows logic requires more file patterns to resolve and is
# not case-sensitive, so leave it separate
@ -420,6 +414,8 @@ def find_node(pkg, node_type, ros_root=None, ros_package_path=None):
# specified extension manually
node_type = node_type.lower()
matches = [node_type, node_type+'.exe', node_type+'.bat']
d = rospack.get_path(pkg)
for p, dirs, files in os.walk(d):
# case insensitive
files = [f.lower() for f in files]
@ -430,101 +426,111 @@ def find_node(pkg, node_type, ros_root=None, ros_package_path=None):
if (s.st_mode & (stat.S_IRUSR | stat.S_IXUSR) ==
(stat.S_IRUSR | stat.S_IXUSR)):
return test_path
if '.svn' in dirs:
dirs.remove('.svn')
elif '.git' in dirs:
dirs.remove('.git')
to_prune = [x for x in dirs if x.startswith('.')]
for x in to_prune:
dirs.remove(x)
else:
#TODO: this could just execute find_resource with a filter_fn
for p, dirs, files in os.walk(d):
if node_type in files:
test_path = os.path.join(p, node_type)
s = os.stat(test_path)
if (s.st_mode & (stat.S_IRUSR | stat.S_IXUSR) ==
(stat.S_IRUSR | stat.S_IXUSR)):
return test_path
if '.svn' in dirs:
dirs.remove('.svn')
elif '.git' in dirs:
dirs.remove('.git')
return find_resource(pkg, node_type, filter_fn=_executable_filter,
rospack=rospack, catkin_packages_cache=catkin_packages_cache)
def find_resource(pkg, resource_name, filter_fn=None, ros_root=None, ros_package_path=None):
def _executable_filter(test_path):
s = os.stat(test_path)
return (s.st_mode & (stat.S_IRUSR | stat.S_IXUSR) == (stat.S_IRUSR | stat.S_IXUSR))
def _load_catkin_packages_cache(catkin_packages_cache, env=None):
"""
env[CATKIN_BINARY_DIR] *must* be set
:param env: OS environment (defaults to os.environ if None/not set)
:param catkin_packages_cache: dictionary to read cache into.
Contents of dictionary will be replaced if cache is read. ``dict``
:raises: :exc:`KeyError` if env[CATKIN_BINARY_DIR] is not set
"""
if env is None:
env=os.environ
prefix = env[CATKIN_BINARY_DIR]
cache_file = os.path.join(prefix, 'etc', 'packages.list')
if os.path.isfile(cache_file):
catkin_packages_cache.clear()
with open(cache_file, 'r') as f:
for l in f.readlines():
l = l.strip()
# Example:
# rosconsole ros_comm/tools/rosconsole\n
if not l:
continue
idx = l.find(' ')
catkin_packages_cache[l[:idx]] = l[idx+1:]
def _find_resource(d, resource_name, filter_fn=None):
"""
subroutine of find_resource
"""
#UNIXONLY
matches = []
node_exe = None
for p, dirs, files in os.walk(d):
if resource_name in files:
test_path = os.path.join(p, resource_name)
if filter_fn is not None:
if filter_fn(test_path):
matches.append(test_path)
else:
matches.append(test_path)
# remove .svn/.git/etc
to_prune = [x for x in dirs if x.startswith('.')]
for x in to_prune:
dirs.remove(x)
return [os.path.abspath(m) for m in matches]
def find_resource(pkg, resource_name, filter_fn=None, rospack=None, catkin_packages_cache=None):
"""
Locate the file named resource_name in package, optionally
matching specified filter
@param filter: function that takes in a path argument and
returns True if the it matches the desired resource
@type filter: fn(str)
@param ros_root: if specified, override ROS_ROOT
@type ros_root: str
@param ros_package_path: if specified, override ROS_PACKAGE_PATH
@type ros_package_path: str
@return: lists of matching paths for resource
@rtype: [str]
@raise roslib.packages.InvalidROSPkgException: If package does not exist
matching specified filter. find_resource() will return a list of
matches, but only for a given scope. If the resource is found in
the binary build directory, it will only return matches in that
directory; it will not return matches from the ROS_PACKAGE_PATH as
well in this case.
:param filter: function that takes in a path argument and
returns True if the it matches the desired resource, ``fn(str)``
:param rospack: `rospkg.RosPack` instance to use
:param catkin_packages_cache: dictionary for caching catkin packages.list
:returns: lists of matching paths for resource within a given scope, ``[str]``
:raises: :exc:`rospkg.ResourceNotFound` If package does not exist
"""
# New resource-location policy in Fuerte, induced by the new catkin
# build system:
# (1) If CATKIN_SOURCE_DIR is set, look recursively there. If the
# (1) If CATKIN_BINARY_DIR is set, look recursively there. If the
# resource is found, done. Else continue:
# (2) If CATKIN_BINARY_DIR is set, look recursively there. If the
# resource is found, done. Else continue:
# (3) If the package was found in (1) or (2), then fail (i.e., if the
# package exists in the source or build tree, don't go looking
# somewhere else). Else continue:
# (4) Do the traditional search (using ROS_ROOT:ROS_PACKAGE_PATH).
# (2) If ROS_PACKAGE_PATH is set, look recursively there. If the
# resource is found, done. Else raise
#
# NOTE: package *must* exist on ROS_PACKAGE_PATH no matter what
rrs = []
rpps = []
if CATKIN_SOURCE_DIR in os.environ:
rrs.append(None)
rpps.append(os.environ[CATKIN_SOURCE_DIR])
if CATKIN_BINARY_DIR in os.environ:
rrs.append(None)
rpps.append(os.environ[CATKIN_BINARY_DIR])
if rospack is None:
rospack = rospkg.RosPack()
if catkin_packages_cache is None:
catkin_packages_cache = {}
#if CATKIN_SOURCE_DIR in os.environ:
# rrs.append(None)
# rpps.append(os.environ[CATKIN_SOURCE_DIR])
rrs.append(ros_root)
rpps.append(ros_package_path)
# lookup package as it *must* exist
pkg_path = rospack.get_path(pkg)
# load catkin packages list, if necessary
if CATKIN_BINARY_DIR in os.environ and not catkin_packages_cache:
_load_catkin_packages_cache(catkin_packages_cache)
found = False
i = 0
for rr, rpp in zip(rrs, rpps):
on_last_search_step = (i == len(rrs) - 1)
i += 1
# If we've previously found the package, but not the resource, then
# don't do the last search step.
if on_last_search_step and found:
return []
try:
d = get_pkg_dir(pkg, required=True, \
ros_root=rr, ros_package_path=rpp)
except roslib.packages.InvalidROSPkgException as e:
if on_last_search_step:
# If we're at the last search step, re-raise
raise
else:
# Keep looking
continue
found = True
#UNIXONLY
matches = []
node_exe = None
for p, dirs, files in os.walk(d):
if resource_name in files:
test_path = os.path.join(p, resource_name)
if filter_fn is not None:
if filter_fn(test_path):
matches.append(test_path)
else:
matches.append(test_path)
if '.svn' in dirs:
dirs.remove('.svn')
elif '.git' in dirs:
dirs.remove('.git')
# If we found anything, or if we're on the last step, we're done
if matches or on_last_search_step:
# return matches from binary dir if found, otherwise ROS_PACKAGE_PATH
if pkg in catkin_packages_cache:
matches = _find_resource(catkin_packages_cache[pkg], resource_name)
if matches:
return matches
else:
return _find_resource(pkg_path, resource_name)