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 from __future__ import print_function
36
37 import os
38 import logging
39 import sys
40 import traceback
41
42
43
44 if sys.version_info[:3] == (2, 7, 3):
45 import threading
46 threading._DummyThread._Thread__stop = lambda _dummy: None
47
48 import rospkg
49
50 from . import core as roslaunch_core
51 from . import param_dump as roslaunch_param_dump
52
53
54 from .core import Node, Test, Master, RLException
55 from .config import ROSLaunchConfig
56 from .launch import ROSLaunchRunner
57 from .xmlloader import XmlLoader, XmlParseException
58
59
60
61 from .scriptapi import ROSLaunch
62 from .pmon import Process
63
64 try:
65 from rosmaster import DEFAULT_MASTER_PORT
66 except:
67 DEFAULT_MASTER_PORT = 11311
68
69 from rosmaster.master_api import NUM_WORKERS
70
71 NAME = 'roslaunch'
72
92
94 if options_pid_fn or options_core:
95
96 ros_home = rospkg.get_ros_home()
97 if options_pid_fn:
98 pid_fn = os.path.expanduser(options_pid_fn)
99 if os.path.dirname(pid_fn) == ros_home and not os.path.exists(ros_home):
100 os.makedirs(ros_home)
101 else:
102
103 if port is None:
104 port = DEFAULT_MASTER_PORT
105 pid_fn = os.path.join(ros_home, 'roscore-%s.pid'%(port))
106
107 if not os.path.exists(ros_home):
108 os.makedirs(ros_home)
109
110 with open(pid_fn, "w") as f:
111 f.write(str(os.getpid()))
112
114 from optparse import OptionParser
115
116 usage = "usage: %prog [options] [package] <filename> [arg_name:=value...]\n"
117 usage += " %prog [options] <filename> [<filename>...] [arg_name:=value...]\n\n"
118 usage += "If <filename> is a single dash ('-'), launch XML is read from standard input."
119 parser = OptionParser(usage=usage, prog=NAME)
120 parser.add_option("--files",
121 dest="file_list", default=False, action="store_true",
122 help="Print list files loaded by launch file, including launch file itself")
123 parser.add_option("--args",
124 dest="node_args", default=None,
125 help="Print command-line arguments for node", metavar="NODE_NAME")
126 parser.add_option("--nodes",
127 dest="node_list", default=False, action="store_true",
128 help="Print list of node names in launch file")
129 parser.add_option("--find-node",
130 dest="find_node", default=None,
131 help="Find launch file that node is defined in", metavar="NODE_NAME")
132 parser.add_option("-c", "--child",
133 dest="child_name", default=None,
134 help="Run as child service 'NAME'. Required with -u", metavar="NAME")
135 parser.add_option("--local",
136 dest="local_only", default=False, action="store_true",
137 help="Do not launch remote nodes")
138
139 parser.add_option("--screen",
140 dest="force_screen", default=False, action="store_true",
141 help="Force output of all local nodes to screen")
142 parser.add_option("-u", "--server_uri",
143 dest="server_uri", default=None,
144 help="URI of server. Required with -c", metavar="URI")
145 parser.add_option("--run_id",
146 dest="run_id", default=None,
147 help="run_id of session. Required with -c", metavar="RUN_ID")
148
149 parser.add_option("--wait", action="store_true",
150 dest="wait_for_master", default=False,
151 help="wait for master to start before launching")
152 parser.add_option("-p", "--port",
153 dest="port", default=None,
154 help="master port. Only valid if master is launched", metavar="PORT")
155 parser.add_option("--core", action="store_true",
156 dest="core", default=False,
157 help="Launch core services only")
158 parser.add_option("--pid",
159 dest="pid_fn", default="",
160 help="write the roslaunch pid to filename")
161 parser.add_option("-v", action="store_true",
162 dest="verbose", default=False,
163 help="verbose printing")
164
165 parser.add_option("--dump-params", default=False, action="store_true",
166 dest="dump_params",
167 help="Dump parameters of all roslaunch files to stdout")
168 parser.add_option("--skip-log-check", default=False, action="store_true",
169 dest="skip_log_check",
170 help="skip check size of log folder")
171 parser.add_option("--ros-args", default=False, action="store_true",
172 dest="ros_args",
173 help="Display command-line arguments for this launch file")
174 parser.add_option("--disable-title", default=False, action="store_true",
175 dest="disable_title",
176 help="Disable setting of terminal title")
177 parser.add_option("-w", "--numworkers",
178 dest="num_workers", default=NUM_WORKERS, type=int,
179 help="override number of worker threads. Only valid for core services.", metavar="NUM_WORKERS")
180 parser.add_option("-t", "--timeout",
181 dest="timeout",
182 help="override the socket connection timeout (in seconds). Only valid for core services.", metavar="TIMEOUT")
183
184 return parser
185
187
188 if options.child_name:
189 if not options.server_uri:
190 parser.error("--child option requires --server_uri to be set as well")
191 if not options.run_id:
192 parser.error("--child option requires --run_id to be set as well")
193 if options.port:
194 parser.error("port option cannot be used with roslaunch child mode")
195 if args:
196 parser.error("Input files are not allowed when run in child mode")
197 elif options.core:
198 if args:
199 parser.error("Input files are not allowed when launching core")
200 if options.run_id:
201 parser.error("--run_id should only be set for child roslaunches (-c)")
202
203
204
205
206 elif len(args) == 0:
207 parser.error("you must specify at least one input file")
208 else:
209 missing_files = [f for f in args if not (f == '-' or os.path.exists(f))]
210 if missing_files:
211 parser.error("The following input files do not exist: %s"%', '.join(missing_files))
212
213 if args.count('-') > 1:
214 parser.error("Only a single instance of the dash ('-') may be specified.")
215
216 if len([x for x in [options.node_list, options.find_node, options.node_args, options.ros_args] if x]) > 1:
217 parser.error("only one of [--nodes, --find-node, --args --ros-args] may be specified")
218
219 -def main(argv=sys.argv):
220 options = None
221 logger = None
222 try:
223 from . import rlutil
224 parser = _get_optparse()
225
226 (options, args) = parser.parse_args(argv[1:])
227 args = rlutil.resolve_launch_arguments(args)
228 _validate_args(parser, options, args)
229
230
231 if any([options.node_args, options.node_list, options.find_node, options.dump_params, options.file_list, options.ros_args]):
232 if options.node_args and not args:
233 parser.error("please specify a launch file")
234
235 from . import node_args
236 if options.node_args:
237 node_args.print_node_args(options.node_args, args)
238 elif options.find_node:
239 node_args.print_node_filename(options.find_node, args)
240
241 elif options.dump_params:
242 roslaunch_param_dump.dump_params(args)
243 elif options.file_list:
244 rlutil.print_file_list(args)
245 elif options.ros_args:
246 import arg_dump as roslaunch_arg_dump
247 roslaunch_arg_dump.dump_args(args)
248 else:
249 node_args.print_node_list(args)
250 return
251
252
253 if options.wait_for_master:
254 if options.core:
255 parser.error("--wait cannot be used with roscore")
256 rlutil._wait_for_master()
257
258
259 write_pid_file(options.pid_fn, options.core, options.port)
260
261
262 uuid = rlutil.get_or_generate_uuid(options.run_id, options.wait_for_master)
263 configure_logging(uuid)
264
265
266 if not options.child_name and not options.skip_log_check:
267
268 rlutil.check_log_disk_usage()
269
270 logger = logging.getLogger('roslaunch')
271 logger.info("roslaunch starting with args %s"%str(argv))
272 logger.info("roslaunch env is %s"%os.environ)
273
274 if options.child_name:
275 logger.info('starting in child mode')
276
277
278
279
280 from . import child as roslaunch_child
281 c = roslaunch_child.ROSLaunchChild(uuid, options.child_name, options.server_uri)
282 c.run()
283 else:
284 logger.info('starting in server mode')
285
286
287 if not options.disable_title:
288 rlutil.change_terminal_name(args, options.core)
289
290
291 roslaunch_strs = []
292 if '-' in args:
293 roslaunch_core.printlog("Passed '-' as file argument, attempting to read roslaunch XML from stdin.")
294 roslaunch_strs.append(sys.stdin.read())
295 roslaunch_core.printlog("... %d bytes read successfully.\n" % len(roslaunch_strs[-1]))
296 args.remove('-')
297
298
299
300 from . import parent as roslaunch_parent
301
302 if options.core:
303 options.port = options.port or DEFAULT_MASTER_PORT
304 p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs,
305 is_core=options.core, port=options.port, local_only=options.local_only,
306 verbose=options.verbose, force_screen=options.force_screen,
307 num_workers=options.num_workers, timeout=options.timeout)
308 p.start()
309 p.spin()
310
311 except RLException as e:
312 roslaunch_core.printerrlog(str(e))
313 roslaunch_core.printerrlog('The traceback for the exception was written to the log file')
314 if logger:
315 logger.error(traceback.format_exc())
316 sys.exit(1)
317 except ValueError as e:
318
319 roslaunch_core.printerrlog(str(e))
320 roslaunch_core.printerrlog('The traceback for the exception was written to the log file')
321 if logger:
322 logger.error(traceback.format_exc())
323 sys.exit(1)
324 except Exception as e:
325 traceback.print_exc()
326 sys.exit(1)
327 finally:
328
329 if options is not None and options.pid_fn:
330 try: os.unlink(options.pid_fn)
331 except os.error: pass
332
333
334 if __name__ == '__main__':
335 main()
336