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