Package roslaunch :: Module node_args
[frames] | no frames]

Source Code for Module roslaunch.node_args

  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  Utility module of roslaunch that computes the command-line arguments 
 37  for a node. 
 38  """ 
 39   
 40  import logging 
 41  import os 
 42  import shlex 
 43  import sys 
 44  import time 
 45   
 46  import rospkg 
 47  import rosgraph 
 48  import rosgraph.names 
 49  from rosgraph.names import script_resolve_name 
 50   
 51  import roslib.packages 
 52   
 53  from . import substitution_args 
 54   
 55  from roslaunch.core import setup_env, local_machine, RLException 
 56  from roslaunch.config import load_config_default 
 57  import roslaunch.xmlloader 
 58   
59 -class NodeParamsException(Exception):
60 """ 61 Exception to indicate that node parameters were invalid 62 """ 63 pass
64
65 -def get_node_list(config):
66 """ 67 @param config: roslaunch config 68 @type config: ROSLaunchConfig 69 @return: list of node names in config 70 @rtype: [str] 71 """ 72 l = [_resolved_name(node) for node in config.nodes] + [_resolved_name(test) for test in config.tests] 73 # filter out unnamed nodes 74 return [x for x in l if x]
75 92 111
112 -def _resolved_name(node):
113 if node.name: 114 # $(anon id) passthrough 115 if node.name.startswith('$'): 116 return node.name 117 else: 118 return rosgraph.names.ns_join(node.namespace, node.name) 119 else: 120 return None
121 142
143 -def get_node_args(node_name, roslaunch_files):
144 """ 145 Get the node arguments for a node in roslaunch_files. 146 147 @param node_name: name of node in roslaunch_files. 148 @type node_name: str 149 @param roslaunch_files: roslaunch file names 150 @type roslaunch_files: [str] 151 @return: list of command-line arguments used to launch node_name 152 @rtype: [str] 153 @raise RLException: if node args cannot be retrieved 154 """ 155 156 # we have to create our own XmlLoader so that we can use the same 157 # resolution context for substitution args 158 159 loader = roslaunch.xmlloader.XmlLoader(resolve_anon=False) 160 config = load_config_default(roslaunch_files, None, loader=loader, verbose=False, assign_machines=False) 161 (node_name) = substitution_args.resolve_args((node_name), resolve_anon=False) 162 node_name = script_resolve_name('roslaunch', node_name) if not node_name.startswith('$') else node_name 163 164 node = [n for n in config.nodes if _resolved_name(n) == node_name] + \ 165 [n for n in config.tests if _resolved_name(n) == node_name] 166 if not node: 167 node_list = get_node_list(config) 168 node_list_str = '\n'.join([" * %s"%x for x in node_list]) 169 raise RLException("ERROR: Cannot find node named [%s] in [%s].\nNode names are:\n%s"%(node_name, ', '.join(roslaunch_files), node_list_str)) 170 elif len(node) > 1: 171 raise RLException("ERROR: multiple nodes named [%s] in [%s].\nPlease fix the launch files as duplicate names are not allowed."%(node_name, ', '.join(roslaunch_files))) 172 node = node[0] 173 174 master_uri = rosgraph.get_master_uri() 175 machine = local_machine() 176 env = setup_env(node, machine, master_uri) 177 178 # remove setting identical to current environment for easier debugging 179 to_remove = [] 180 for k in env.iterkeys(): 181 if env[k] == os.environ.get(k, None): 182 to_remove.append(k) 183 for k in to_remove: 184 del env[k] 185 186 # resolve node name for generating args 187 args = create_local_process_args(node, machine) 188 # join environment vars are bash prefix args 189 return ["%s=%s"%(k, v) for k, v in env.iteritems()] + args
190
191 -def _launch_prefix_args(node):
192 if node.launch_prefix: 193 prefix = node.launch_prefix 194 if type(prefix) == unicode: 195 prefix = prefix.encode('UTF-8') 196 return shlex.split(prefix) 197 else: 198 return []
199
200 -def create_local_process_args(node, machine, env=None):
201 """ 202 Subroutine for creating node arguments. 203 204 :param env: override os.environ. Warning, this does not override 205 substitution args in node configuration (for now), ``dict`` 206 :returns: arguments for node process, ``[str]`` 207 :raises: :exc:`NodeParamsException` If args cannot be constructed for Node 208 as specified (e.g. the node type does not exist) 209 """ 210 if not node.name: 211 raise ValueError("node name must be defined") 212 if env is None: 213 env = os.environ 214 215 # - Construct rosrun command 216 remap_args = ["%s:=%s"%(src,dst) for src, dst in node.remap_args] 217 resolve_dict = {} 218 219 #resolve args evaluates substitution commands 220 #shlex parses a command string into a list of args 221 # - for the local process args, we *do* resolve the anon tag so that the user can execute 222 # - the node name and args must be resolved together in case the args refer to the anon node name 223 (node_name) = substitution_args.resolve_args((node.name), context=resolve_dict, resolve_anon=True) 224 node.name = node_name 225 remap_args.append('__name:=%s'%node_name) 226 227 resolved = substitution_args.resolve_args(node.args, context=resolve_dict, resolve_anon=True) 228 if type(resolved) == unicode: 229 resolved = resolved.encode('UTF-8') #attempt to force to string for shlex/subprocess 230 args = shlex.split(resolved) + remap_args 231 try: 232 #TODO:fuerte: pass through rospack and catkin cache 233 rospack = rospkg.RosPack(rospkg.get_ros_paths(env=env)) 234 matches = roslib.packages.find_node(node.package, node.type, rospack) 235 except rospkg.ResourceNotFound as e: 236 # multiple nodes, invalid package 237 raise NodeParamsException(str(e)) 238 if not matches: 239 raise NodeParamsException("can't locate node [%s] in package [%s]"%(node.type, node.package)) 240 else: 241 # old behavior was to take first, do we want to change this in Fuerte-style? 242 cmd = matches[0] 243 if not cmd: 244 raise NodeParamsException("Cannot locate node of type [%s] in package [%s]"%(node.type, node.package)) 245 cmd = [cmd] 246 if sys.platform in ['win32']: 247 if os.path.splitext(cmd[0])[1] == '.py': 248 cmd = ['python'] + cmd 249 return _launch_prefix_args(node) + cmd + args
250