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("-u", "--server_uri",
144 dest="server_uri", default=None,
145 help="URI of server. Required with -c", metavar="URI")
146 parser.add_option("--run_id",
147 dest="run_id", default=None,
148 help="run_id of session. Required with -c", metavar="RUN_ID")
149
150 parser.add_option("--wait", action="store_true",
151 dest="wait_for_master", default=False,
152 help="wait for master to start before launching")
153 parser.add_option("-p", "--port",
154 dest="port", default=None,
155 help="master port. Only valid if master is launched", metavar="PORT")
156 parser.add_option("--core", action="store_true",
157 dest="core", default=False,
158 help="Launch core services only")
159 parser.add_option("--pid",
160 dest="pid_fn", default="",
161 help="write the roslaunch pid to filename")
162 parser.add_option("-v", action="store_true",
163 dest="verbose", default=False,
164 help="verbose printing")
165
166 parser.add_option("--dump-params", default=False, action="store_true",
167 dest="dump_params",
168 help="Dump parameters of all roslaunch files to stdout")
169 parser.add_option("--skip-log-check", default=False, action="store_true",
170 dest="skip_log_check",
171 help="skip check size of log folder")
172 parser.add_option("--ros-args", default=False, action="store_true",
173 dest="ros_args",
174 help="Display command-line arguments for this launch file")
175 parser.add_option("--disable-title", default=False, action="store_true",
176 dest="disable_title",
177 help="Disable setting of terminal title")
178 parser.add_option("-w", "--numworkers",
179 dest="num_workers", default=NUM_WORKERS, type=int,
180 help="override number of worker threads. Only valid for core services.", metavar="NUM_WORKERS")
181 parser.add_option("-t", "--timeout",
182 dest="timeout",
183 help="override the socket connection timeout (in seconds). Only valid for core services.", metavar="TIMEOUT")
184 parser.add_option("--master-logger-level",
185 dest="master_logger_level", default=False, type=str,
186 help="set rosmaster.master logger level ('debug', 'info', 'warn', 'error', 'fatal')")
187
188 return parser
189
191
192 if options.child_name:
193 if not options.server_uri:
194 parser.error("--child option requires --server_uri to be set as well")
195 if not options.run_id:
196 parser.error("--child option requires --run_id to be set as well")
197 if options.port:
198 parser.error("port option cannot be used with roslaunch child mode")
199 if args:
200 parser.error("Input files are not allowed when run in child mode")
201 elif options.core:
202 if args:
203 parser.error("Input files are not allowed when launching core")
204 if options.run_id:
205 parser.error("--run_id should only be set for child roslaunches (-c)")
206
207
208
209
210 elif len(args) == 0:
211 parser.error("you must specify at least one input file")
212 elif [f for f in args if not (f == '-' or os.path.exists(f))]:
213 parser.error("The following input files do not exist: %s"%f)
214
215 if args.count('-') > 1:
216 parser.error("Only a single instance of the dash ('-') may be specified.")
217
218 if len([x for x in [options.node_list, options.find_node, options.node_args, options.ros_args] if x]) > 1:
219 parser.error("only one of [--nodes, --find-node, --args --ros-args] may be specified")
220
222 roslaunch_core.printerrlog(msg + str(e))
223 roslaunch_core.printerrlog('The traceback for the exception was written to the log file')
224 if logger:
225 logger.error(traceback.format_exc())
226 sys.exit(1)
227
228 -def main(argv=sys.argv):
229 options = None
230 logger = None
231 try:
232 from . import rlutil
233 parser = _get_optparse()
234
235 (options, args) = parser.parse_args(argv[1:])
236 args = rlutil.resolve_launch_arguments(args)
237 _validate_args(parser, options, args)
238
239
240 if any([options.node_args, options.node_list, options.find_node, options.dump_params, options.file_list, options.ros_args]):
241 if options.node_args and not args:
242 parser.error("please specify a launch file")
243
244 from . import node_args
245 if options.node_args:
246 node_args.print_node_args(options.node_args, args)
247 elif options.find_node:
248 node_args.print_node_filename(options.find_node, args)
249
250 elif options.dump_params:
251 roslaunch_param_dump.dump_params(args)
252 elif options.file_list:
253 rlutil.print_file_list(args)
254 elif options.ros_args:
255 import arg_dump as roslaunch_arg_dump
256 roslaunch_arg_dump.dump_args(args)
257 else:
258 node_args.print_node_list(args)
259 return
260
261
262 if options.wait_for_master:
263 if options.core:
264 parser.error("--wait cannot be used with roscore")
265 rlutil._wait_for_master()
266
267
268 write_pid_file(options.pid_fn, options.core, options.port)
269
270
271 uuid = rlutil.get_or_generate_uuid(options.run_id, options.wait_for_master)
272 configure_logging(uuid)
273
274
275 if not options.child_name and not options.skip_log_check:
276
277 rlutil.check_log_disk_usage()
278
279 logger = logging.getLogger('roslaunch')
280 logger.info("roslaunch starting with args %s"%str(argv))
281 logger.info("roslaunch env is %s"%os.environ)
282
283 if options.child_name:
284 logger.info('starting in child mode')
285
286
287
288
289 from . import child as roslaunch_child
290 c = roslaunch_child.ROSLaunchChild(uuid, options.child_name, options.server_uri)
291 c.run()
292 else:
293 logger.info('starting in server mode')
294
295
296 if not options.disable_title:
297 rlutil.change_terminal_name(args, options.core)
298
299
300 roslaunch_strs = []
301 if '-' in args:
302 roslaunch_core.printlog("Passed '-' as file argument, attempting to read roslaunch XML from stdin.")
303 roslaunch_strs.append(sys.stdin.read())
304 roslaunch_core.printlog("... %d bytes read successfully.\n" % len(roslaunch_strs[-1]))
305 args.remove('-')
306
307
308
309 from . import parent as roslaunch_parent
310
311 if options.core:
312 options.port = options.port or DEFAULT_MASTER_PORT
313 p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs,
314 is_core=options.core, port=options.port, local_only=options.local_only,
315 verbose=options.verbose, force_screen=options.force_screen,
316 num_workers=options.num_workers, timeout=options.timeout,
317 master_logger_level=options.master_logger_level)
318 p.start()
319 p.spin()
320
321 except RLException as e:
322 handle_exception(roslaunch_core, logger, "RLException: ", e)
323 except ValueError as e:
324
325 handle_exception(roslaunch_core, logger, "Value error: ", e)
326 except rospkg.ResourceNotFound as e:
327 handle_exception(roslaunch_core, logger, "Resource not found: ", e)
328 except Exception as e:
329 traceback.print_exc()
330 sys.exit(1)
331 finally:
332
333 if options is not None and options.pid_fn:
334 try: os.unlink(options.pid_fn)
335 except os.error: pass
336
337
338 if __name__ == '__main__':
339 main()
340