1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 roslib.packages
47 import roslib.rosenv
48 import roslib.substitution_args
49 from roslib.scriptutil import script_resolve_name
50
51 from roslaunch.core import setup_env, local_machine, RLException
52 from roslaunch.config import load_config_default
53 import roslaunch.xmlloader
54
56 """
57 Exception to indicate that node parameters were invalid
58 """
59 pass
60
62 """
63 @param config: roslaunch config
64 @type config: ROSLaunchConfig
65 @return: list of node names in config
66 @rtype: [str]
67 """
68 l = [_resolved_name(node) for node in config.nodes] + [_resolved_name(test) for test in config.tests]
69
70 return [x for x in l if x]
71
73 """
74 Print list of nodes to screen. Will cause system exit if exception
75 occurs. This is a subroutine for the roslaunch main handler.
76
77 @param roslaunch_files: list of launch files to load
78 @type roslaunch_files: str
79 """
80 try:
81 loader = roslaunch.xmlloader.XmlLoader(resolve_anon=False)
82 config = load_config_default(roslaunch_files, None, loader=loader, verbose=False, assign_machines=False)
83 node_list = get_node_list(config)
84 print '\n'.join(node_list)
85 except RLException, e:
86 print >> sys.stderr, str(e)
87 sys.exit(1)
88
90 """
91 Print arguments of node to screen. Will cause system exit if
92 exception occurs. This is a subroutine for the roslaunch main
93 handler.
94
95 @param node_name: node name
96 @type node_name: str
97 @param roslaunch_files: list of launch files to load
98 @type roslaunch_files: str
99 """
100 try:
101 node_name = script_resolve_name('roslaunch', node_name)
102 args = get_node_args(node_name, roslaunch_files)
103 print ' '.join(args)
104 except RLException, e:
105 print >> sys.stderr, str(e)
106 sys.exit(1)
107
109 if node.name:
110
111 if node.name.startswith('$'):
112 return node.name
113 else:
114 return roslib.names.ns_join(node.namespace, node.name)
115 else:
116 return None
117
119 try:
120
121 node_name = script_resolve_name('roslaunch', node_name)
122
123 loader = roslaunch.xmlloader.XmlLoader(resolve_anon=False)
124 config = load_config_default(roslaunch_files, None, loader=loader, verbose=False, assign_machines=False)
125 nodes = [n for n in config.nodes if _resolved_name(n) == node_name] + \
126 [t for t in config.tests if _resolved_name(t) == node_name]
127
128 if len(nodes) > 1:
129 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)))
130 if not nodes:
131 print >> sys.stderr, 'ERROR: cannot find node named [%s]. Run \n\troslaunch --nodes <files>\nto see list of node names.'%(node_name)
132 else:
133 print nodes[0].filename
134
135 except RLException, e:
136 print >> sys.stderr, str(e)
137 sys.exit(1)
138
140 """
141 Get the node arguments for a node in roslaunch_files.
142
143 @param node_name: name of node in roslaunch_files.
144 @type node_name: str
145 @param roslaunch_files: roslaunch file names
146 @type roslaunch_files: [str]
147 @return: list of command-line arguments used to launch node_name
148 @rtype: [str]
149 @raise RLException: if node args cannot be retrieved
150 """
151
152
153
154
155 loader = roslaunch.xmlloader.XmlLoader(resolve_anon=False)
156 config = load_config_default(roslaunch_files, None, loader=loader, verbose=False, assign_machines=False)
157 (node_name) = roslib.substitution_args.resolve_args((node_name), resolve_anon=False)
158 node_name = script_resolve_name('roslaunch', node_name) if not node_name.startswith('$') else node_name
159
160 node = [n for n in config.nodes if _resolved_name(n) == node_name] + \
161 [n for n in config.tests if _resolved_name(n) == node_name]
162 if not node:
163 node_list = get_node_list(config)
164 node_list_str = '\n'.join([" * %s"%x for x in node_list])
165 raise RLException("ERROR: Cannot find node named [%s] in [%s].\nNode names are:\n%s"%(node_name, ', '.join(roslaunch_files), node_list_str))
166 elif len(node) > 1:
167 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)))
168 node = node[0]
169
170 master_uri = roslib.rosenv.get_master_uri()
171 machine = local_machine()
172
173
174 env = setup_env(node, machine, master_uri)
175 to_remove = []
176 for k in env.iterkeys():
177 if env[k] == os.environ.get(k, None):
178 to_remove.append(k)
179 for k in to_remove:
180 del env[k]
181
182
183 args = create_local_process_args(node, machine)
184
185 return ["%s=%s"%(k, v) for k, v in env.iteritems()] + args
186
188 """
189 Setup environment for locally launched process. The local
190 environment includes the default os environment, with any
191 ROS-specific environment variables overriding this enviornment.
192 @return: environment variables
193 @rtype: dict
194 """
195
196
197
198
199
200 full_env = env.copy()
201
202 for evar in [
203 roslib.rosenv.ROS_MASTER_URI,
204 roslib.rosenv.ROS_ROOT,
205 roslib.rosenv.ROS_PACKAGE_PATH,
206 roslib.rosenv.ROS_IP,
207 'PYTHONPATH',
208 roslib.rosenv.ROS_NAMESPACE]:
209 if evar in full_env:
210 del full_env[evar]
211
212 proc_env = setup_env(node, machine, master_uri)
213
214
215 rosroot_bin = os.path.join(roslib.rosenv.get_ros_root(), 'bin')
216 path = os.environ.get('PATH', '')
217 if not rosroot_bin in path.split(os.pathsep):
218 proc_env['PATH'] = path + os.pathsep + rosroot_bin
219
220 full_env.update(proc_env)
221 return full_env
222
224 if node.launch_prefix:
225 prefix = node.launch_prefix
226 if type(prefix) == unicode:
227 prefix = prefix.encode('UTF-8')
228 return shlex.split(prefix)
229 else:
230 return []
231
233 """
234 Subroutine for creating node arguments.
235 @return: arguments for node process
236 @rtype: [str]
237 @raise NodeParamsException: if args cannot be constructed for Node
238 as specified (e.g. the node type does not exist)
239 """
240 if not node.name:
241 raise ValueError("node name must be defined")
242
243
244 remap_args = ["%s:=%s"%(src,dst) for src, dst in node.remap_args]
245 resolve_dict = {}
246
247
248
249
250
251 (node_name) = roslib.substitution_args.resolve_args((node.name), context=resolve_dict, resolve_anon=True)
252 node.name = node_name
253 remap_args.append('__name:=%s'%node_name)
254
255 resolved = roslib.substitution_args.resolve_args(node.args, context=resolve_dict, resolve_anon=True)
256 if type(resolved) == unicode:
257 resolved = resolved.encode('UTF-8')
258 args = shlex.split(resolved) + remap_args
259
260 start_t = time.time()
261 try:
262 cmd = roslib.packages.find_node(node.package, node.type,\
263 machine.ros_root, machine.ros_package_path)
264 except roslib.packages.ROSPkgException, e:
265
266 raise NodeParamsException(str(e))
267 end_t = time.time()
268 logging.getLogger('roslaunch.node_args').info('find_node(%s, %s, %s, %s) took %ss'%(node.package, node.type, machine.ros_root, machine.ros_package_path, (end_t - start_t)))
269 if not cmd:
270 raise NodeParamsException("Cannot locate node of type [%s] in package [%s]"%(node.type, node.package))
271 return _launch_prefix_args(node) + [cmd] + args
272