Package roswtf :: Module context
[frames] | no frames]

Source Code for Module roswtf.context

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id$ 
 34   
 35  """ 
 36  L{WtfContext} object, which is commonly used throughout the roswtf 
 37  APIs to pass state. 
 38  """ 
 39   
 40  import os 
 41  import sys 
 42   
 43  import rospkg 
 44  import rospkg.environment 
 45   
 46  import rosgraph 
 47   
 48  import roslaunch.depends 
 49  import roslaunch.substitution_args 
 50   
 51  from roswtf.model import WtfWarning 
52 53 -class WtfException(Exception):
54 """ 55 Base exception class of roswtf-related issues. 56 """ 57 pass
58
59 -class WtfContext(object):
60 """ 61 WtfContext stores common state about the ROS filesystem and online 62 environment. The primary use of this is for convenience (not 63 having to load this state manually) and performance (not having to 64 do the same calculation repeatedly). 65 """ 66 __slots__ = ['pkg', 'pkg_dir', 'pkgs', 67 'stack', 'stack_dir', 'stacks', 68 'manifest_file', 'manifest', 69 'env', 'ros_root', 'ros_package_path', 'pythonpath', 70 'ros_master_uri', 71 'roslaunch_uris', 72 'launch_files', 73 'launch_file_deps', 74 'launch_file_missing_deps', 75 'system_state', 76 'service_providers', 77 'topics', 'services', 78 'nodes', 'uri_node_map', 79 'expected_edges', 80 'actual_edges', 81 'unconnected_subscriptions', 82 'use_sim_time', 83 'warnings', 'errors', 84 'rospack', 'rosstack'] 85
86 - def __init__(self):
87 # main package we are running 88 self.pkg = None 89 self.pkg_dir = None 90 # main stack we are running 91 self.stack = None 92 self.stack_dir = None 93 94 # - list of all packages involved in this check 95 self.pkgs = [] 96 # - list of all stacks involved in this check 97 self.stacks = [] 98 99 # manifest location of package that we are running 100 self.manifest_file = None 101 # manifest of package that we are running 102 self.manifest = None 103 104 # environment variables 105 self.env = {} 106 107 # provide these for convenience 108 self.ros_root = None 109 self.ros_package_path = None 110 self.pythonpath = None 111 112 # launch file that is being run 113 self.launch_files = None 114 self.launch_file_deps = None 115 self.launch_file_missing_deps = None 116 117 # online state 118 self.roslaunch_uris = None 119 self.system_state = None #master.getSystemState 120 self.topics = None 121 self.services = None 122 self.service_providers = None #names of nodes with services 123 self.nodes = None 124 self.uri_node_map = {} 125 self.expected_edges = None 126 self.actual_edges = None 127 self.unconnected_subscriptions = None 128 self.use_sim_time = None 129 130 # caching rospack instance 131 self.rospack = self.rosstack = None 132 133 # warnings that we have collected so far 134 self.warnings = [] 135 # errors that we have collected so far 136 self.errors = []
137
138 - def as_dictionary(self):
139 """ 140 @return: dictionary representation of context, which is 141 useful for producing error messages 142 @rtype: dict 143 """ 144 return dict((s, getattr(self, s)) for s in self.__slots__)
145 146 @staticmethod
147 - def from_roslaunch(roslaunch_files, env=None):
148 """ 149 @param roslaunch_file: roslaunch_file to load from 150 @type roslaunch_file: str 151 """ 152 if env is None: 153 env = os.environ 154 155 # can't go any further if launch file doesn't validate 156 l, c = roslaunch.XmlLoader(), roslaunch.ROSLaunchConfig() 157 for f in roslaunch_files: 158 try: 159 l.load(f, c, verbose=False) 160 except roslaunch.RLException as e: 161 raise WtfException("Unable to load roslaunch file [%s]: %s"%(f, str(e))) 162 163 ctx = WtfContext() 164 ctx.rospack = rospkg.RosPack(rospkg.get_ros_paths(env)) 165 ctx.rosstack = rospkg.RosStack(rospkg.get_ros_paths(env)) 166 167 ctx.launch_files = roslaunch_files 168 _load_roslaunch(ctx, roslaunch_files) 169 # ctx.pkg and ctx.stack initialized by _load_roslaunch 170 _load_pkg(ctx, ctx.pkg) 171 if ctx.stack: 172 _load_stack(ctx, ctx.stack) 173 _load_env(ctx, env) 174 return ctx
175 176 @staticmethod
177 - def from_stack(stack, env=None):
178 """ 179 Initialize WtfContext from stack. 180 @param stack: stack name 181 @type stack: str 182 @raise WtfException: if context state cannot be initialized 183 """ 184 if env is None: 185 env = os.environ 186 187 ctx = WtfContext() 188 ctx.rospack = rospkg.RosPack(rospkg.get_ros_paths(env)) 189 ctx.rosstack = rospkg.RosStack(rospkg.get_ros_paths(env)) 190 191 _load_stack(ctx, stack) 192 try: 193 ctx.pkgs = ctx.rosstack.packages_of(stack) 194 except rospkg.ResourceNotFound: 195 # this should be handled elsewhere 196 ctx.pkgs = [] 197 _load_env(ctx, env) 198 return ctx
199 200 @staticmethod
201 - def from_package(pkg, env=None):
202 """ 203 Initialize WtfContext from package name. 204 205 @param pkg: package name 206 @type pkg: str 207 @raise WtfException: if context state cannot be initialized 208 """ 209 if env is None: 210 env = os.environ 211 212 ctx = WtfContext() 213 ctx.rospack = rospkg.RosPack(rospkg.get_ros_paths(env)) 214 ctx.rosstack = rospkg.RosStack(rospkg.get_ros_paths(env)) 215 216 _load_pkg(ctx, pkg) 217 stack = ctx.rospack.stack_of(pkg) 218 if stack: 219 _load_stack(ctx, stack) 220 _load_env(ctx, env) 221 return ctx
222 223 @staticmethod
224 - def from_env(env=None):
225 """ 226 Initialize WtfContext from environment. 227 228 @raise WtfException: if context state cannot be initialized 229 """ 230 if env is None: 231 env = os.environ 232 233 ctx = WtfContext() 234 ctx.rospack = rospkg.RosPack(rospkg.get_ros_paths(env)) 235 ctx.rosstack = rospkg.RosStack(rospkg.get_ros_paths(env)) 236 237 _load_env(ctx, env) 238 return ctx
239
240 -def _load_roslaunch(ctx, roslaunch_files):
241 """ 242 Utility for initializing WtfContext state from roslaunch file 243 """ 244 try: 245 base_pkg, file_deps, missing = roslaunch.depends.roslaunch_deps(roslaunch_files) 246 ctx.pkg = base_pkg 247 ctx.launch_file_deps = file_deps 248 ctx.launch_file_missing_deps = missing 249 except roslaunch.substitution_args.SubstitutionException as se: 250 raise WtfException("Cannot load roslaunch file(s): "+str(se)) 251 except roslaunch.depends.RoslaunchDepsException as e: 252 raise WtfException(str(e))
253
254 -def _load_pkg(ctx, pkg):
255 """ 256 Utility for initializing WtfContext state 257 @raise WtfException: if context state cannot be initialized 258 """ 259 r = ctx.rospack 260 ctx.pkg = pkg 261 try: 262 ctx.pkgs = [pkg] + r.get_depends(pkg) 263 except rospkg.ResourceNotFound as e: 264 raise WtfException("Cannot find dependencies for package [%s]: missing %s"%(pkg, e)) 265 try: 266 ctx.pkg_dir = r.get_path(pkg) 267 ctx.manifest_file = os.path.join(ctx.pkg_dir, 'manifest.xml') 268 ctx.manifest = r.get_manifest(pkg) 269 except rospkg.ResourceNotFound: 270 raise WtfException("Cannot locate manifest file for package [%s]"%pkg) 271 except rospkg.InvalidManifest as e: 272 raise WtfException("Package [%s] has an invalid manifest: %s"%(pkg, e))
273
274 -def _load_stack(ctx, stack):
275 """ 276 Utility for initializing WtfContext state 277 @raise WtfException: if context state cannot be initialized 278 """ 279 r = ctx.rosstack 280 ctx.stack = stack 281 try: 282 ctx.stacks = [stack] + r.get_depends(stack, implicit=True) 283 except rospkg.ResourceNotFound as e: 284 raise WtfException("Cannot load dependencies of stack [%s]: %s"%(stack, e)) 285 try: 286 ctx.stack_dir = r.get_path(stack) 287 except rospkg.ResourceNotFound: 288 raise WtfException("[%s] appears to be a stack, but it's not on your ROS_PACKAGE_PATH"%stack)
289
290 291 -def _load_env(ctx, env):
292 """ 293 Utility for initializing WtfContext state 294 295 @raise WtfException: if context state cannot be initialized 296 """ 297 ctx.env = env 298 try: 299 ctx.ros_root = env[rospkg.environment.ROS_ROOT] 300 except KeyError: 301 raise WtfException("ROS_ROOT is not set") 302 ctx.ros_package_path = env.get(rospkg.environment.ROS_PACKAGE_PATH, None) 303 ctx.pythonpath = env.get('PYTHONPATH', None) 304 ctx.ros_master_uri = env.get(rosgraph.ROS_MASTER_URI, None)
305