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 elif [f for f in args if not (f == '-' or os.path.exists(f))]:
209 parser.error("The following input files do not exist: %s"%f)
210
211 if args.count('-') > 1:
212 parser.error("Only a single instance of the dash ('-') may be specified.")
213
214 if len([x for x in [options.node_list, options.find_node, options.node_args, options.ros_args] if x]) > 1:
215 parser.error("only one of [--nodes, --find-node, --args --ros-args] may be specified")
216
217 -def main(argv=sys.argv):
218 options = None
219 logger = None
220 try:
221 from . import rlutil
222 parser = _get_optparse()
223
224 (options, args) = parser.parse_args(argv[1:])
225 args = rlutil.resolve_launch_arguments(args)
226 _validate_args(parser, options, args)
227
228
229 if any([options.node_args, options.node_list, options.find_node, options.dump_params, options.file_list, options.ros_args]):
230 if options.node_args and not args:
231 parser.error("please specify a launch file")
232
233 from . import node_args
234 if options.node_args:
235 node_args.print_node_args(options.node_args, args)
236 elif options.find_node:
237 node_args.print_node_filename(options.find_node, args)
238
239 elif options.dump_params:
240 roslaunch_param_dump.dump_params(args)
241 elif options.file_list:
242 rlutil.print_file_list(args)
243 elif options.ros_args:
244 import arg_dump as roslaunch_arg_dump
245 roslaunch_arg_dump.dump_args(args)
246 else:
247 node_args.print_node_list(args)
248 return
249
250
251 if options.wait_for_master:
252 if options.core:
253 parser.error("--wait cannot be used with roscore")
254 rlutil._wait_for_master()
255
256
257 write_pid_file(options.pid_fn, options.core, options.port)
258
259
260 uuid = rlutil.get_or_generate_uuid(options.run_id, options.wait_for_master)
261 configure_logging(uuid)
262
263
264 if not options.child_name and not options.skip_log_check:
265
266 rlutil.check_log_disk_usage()
267
268 logger = logging.getLogger('roslaunch')
269 logger.info("roslaunch starting with args %s"%str(argv))
270 logger.info("roslaunch env is %s"%os.environ)
271
272 if options.child_name:
273 logger.info('starting in child mode')
274
275
276
277
278 from . import child as roslaunch_child
279 c = roslaunch_child.ROSLaunchChild(uuid, options.child_name, options.server_uri)
280 c.run()
281 else:
282 logger.info('starting in server mode')
283
284
285 if not options.disable_title:
286 rlutil.change_terminal_name(args, options.core)
287
288
289 roslaunch_strs = []
290 if '-' in args:
291 roslaunch_core.printlog("Passed '-' as file argument, attempting to read roslaunch XML from stdin.")
292 roslaunch_strs.append(sys.stdin.read())
293 roslaunch_core.printlog("... %d bytes read successfully.\n" % len(roslaunch_strs[-1]))
294 args.remove('-')
295
296
297
298 from . import parent as roslaunch_parent
299 try:
300
301 if options.core:
302 options.port = options.port or DEFAULT_MASTER_PORT
303 p = roslaunch_parent.ROSLaunchParent(uuid, args, roslaunch_strs=roslaunch_strs,
304 is_core=options.core, port=options.port, local_only=options.local_only,
305 verbose=options.verbose, force_screen=options.force_screen,
306 num_workers=options.num_workers, timeout=options.timeout)
307 p.start()
308 p.spin()
309 finally:
310
311 if options.pid_fn:
312 try: os.unlink(options.pid_fn)
313 except os.error: pass
314
315 except RLException as e:
316 roslaunch_core.printerrlog(str(e))
317 roslaunch_core.printerrlog('The traceback for the exception was written to the log file')
318 if logger:
319 logger.error(traceback.format_exc())
320 sys.exit(1)
321 except ValueError as e:
322
323 roslaunch_core.printerrlog(str(e))
324 roslaunch_core.printerrlog('The traceback for the exception was written to the log file')
325 if logger:
326 logger.error(traceback.format_exc())
327 sys.exit(1)
328 except Exception as e:
329 traceback.print_exc()
330 sys.exit(1)
331
332 if __name__ == '__main__':
333 main()
334